diff --git a/Core/build.xml b/Core/build.xml
index c22d725cce..e75c217d15 100644
--- a/Core/build.xml
+++ b/Core/build.xml
@@ -17,6 +17,8 @@
+
+
@@ -52,8 +54,8 @@
-
+
-
-
+
+
diff --git a/Core/nbproject/project.properties b/Core/nbproject/project.properties
index ff1f4f81de..8e75908180 100644
--- a/Core/nbproject/project.properties
+++ b/Core/nbproject/project.properties
@@ -1,6 +1,6 @@
file.reference.activemq-all-5.11.1.jar=release/modules/ext/activemq-all-5.11.1.jar
file.reference.c3p0-0.9.5.jar=release/modules/ext/c3p0-0.9.5.jar
-file.reference.commons-compress-1.12.jar=release/modules/ext/commons-compress-1.12.jar
+file.reference.commons-compress-1.14.jar=release/modules/ext/commons-compress-1.14.jar
file.reference.commons-dbcp2-2.1.1.jar=release\\modules\\ext\\commons-dbcp2-2.1.1.jar
file.reference.commons-pool2-2.4.2.jar=release\\modules\\ext\\commons-pool2-2.4.2.jar
file.reference.jdom-2.0.5-contrib.jar=release/modules/ext/jdom-2.0.5-contrib.jar
@@ -9,7 +9,7 @@ file.reference.jgraphx-v3.8.0.jar=release/modules/ext/jgraphx-v3.8.0.jar
file.reference.jsoup-1.10.3.jar=release/modules/ext/jsoup-1.10.3.jar
file.reference.jython-standalone-2.7.0.jar=release/modules/ext/jython-standalone-2.7.0.jar
file.reference.mchange-commons-java-0.2.9.jar=release/modules/ext/mchange-commons-java-0.2.9.jar
-file.reference.metadata-extractor-2.9.1.jar=release/modules/ext/metadata-extractor-2.9.1.jar
+file.reference.metadata-extractor-2.10.1.jar=release/modules/ext/metadata-extractor-2.10.1.jar
file.reference.postgresql-9.4.1211.jre7.jar=release/modules/ext/postgresql-9.4.1211.jre7.jar
file.reference.opencv-248.jar=release/modules/ext/opencv-248.jar
file.reference.Rejistry-1.0-SNAPSHOT.jar=release/modules/ext/Rejistry-1.0-SNAPSHOT.jar
@@ -17,14 +17,14 @@ file.reference.sevenzipjbinding-AllPlatforms.jar=release/modules/ext/sevenzipjbi
file.reference.sevenzipjbinding.jar=release/modules/ext/sevenzipjbinding.jar
file.reference.sqlite-jdbc-3.8.11.jar=release/modules/ext/sqlite-jdbc-3.8.11.jar
file.reference.StixLib.jar=release/modules/ext/StixLib.jar
-file.reference.tika-core-1.14.jar=release/modules/ext/tika-core-1.14.jar
-file.reference.tika-parsers-1.14.jar=release/modules/ext/tika-parsers-1.14.jar
-file.reference.Tsk_DataModel_PostgreSQL.jar=release/modules/ext/Tsk_DataModel_PostgreSQL.jar
-file.reference.xmpcore-5.1.2.jar=release/modules/ext/xmpcore-5.1.2.jar
+file.reference.sleuthkit-postgresql-4.6.0.jar=release/modules/ext/sleuthkit-postgresql-4.6.0.jar
+file.reference.tika-core-1.17.jar=release/modules/ext/tika-core-1.17.jar
+file.reference.tika-parsers-1.17.jar=release/modules/ext/tika-parsers-1.17.jar
file.reference.curator-client-2.8.0.jar=release/modules/ext/curator-client-2.8.0.jar
file.reference.curator-framework-2.8.0.jar=release/modules/ext/curator-framework-2.8.0.jar
file.reference.curator-recipes-2.8.0.jar=release/modules/ext/curator-recipes-2.8.0.jar
-file.reference.xz-1.5.jar=release/modules/ext/xz-1.5.jar
+file.reference.xmpcore-5.1.3.jar=release/modules/ext/xmpcore-5.1.3.jar
+file.reference.xz-1.6.jar=release/modules/ext/xz-1.6.jar
file.reference.zookeeper-3.4.6.jar=release/modules/ext/zookeeper-3.4.6.jar
javac.source=1.8
javac.compilerargs=-Xlint -Xlint:-serial
diff --git a/Core/nbproject/project.xml b/Core/nbproject/project.xml
index baaf061b92..9f75c01eeb 100644
--- a/Core/nbproject/project.xml
+++ b/Core/nbproject/project.xml
@@ -286,6 +286,7 @@
+
net.sf.sevenzipjbinding
net.sf.sevenzipjbinding.impl
@@ -329,12 +330,8 @@
release/modules/ext/jdom-2.0.5.jar
- ext/tika-core-1.14.jar
- release/modules/ext/tika-core-1.14.jar
-
-
- ext/Tsk_DataModel_PostgreSQL.jar
- release/modules/ext/Tsk_DataModel_PostgreSQL.jar
+ ext/sleuthkit-postgresql-4.6.0.jar
+ release/modules/ext/sleuthkit-postgresql-4.6.0.jar
ext/opencv-248.jar
@@ -353,8 +350,12 @@
release/modules/ext/jgraphx-v3.8.0.jar
- ext/tika-parsers-1.14.jar
- release/modules/ext/tika-parsers-1.14.jar
+ ext/commons-compress-1.14.jar
+ release/modules/ext/commons-compress-1.14.jar
+
+
+ ext/commons-dbcp2-2.1.1.jar
+ release\modules\ext\commons-dbcp2-2.1.1.jar
ext/jython-standalone-2.7.0.jar
@@ -377,12 +378,12 @@
release/modules/ext/curator-recipes-2.8.0.jar
- ext/xz-1.5.jar
- release/modules/ext/xz-1.5.jar
+ ext/metadata-extractor-2.10.1.jar
+ release/modules/ext/metadata-extractor-2.10.1.jar
- ext/xmpcore-5.1.2.jar
- release/modules/ext/xmpcore-5.1.2.jar
+ ext/tika-core-1.17.jar
+ release/modules/ext/tika-core-1.17.jar
ext/StixLib.jar
@@ -392,6 +393,10 @@
ext/curator-client-2.8.0.jar
release/modules/ext/curator-client-2.8.0.jar
+
+ ext/tika-parsers-1.17.jar
+ release/modules/ext/tika-parsers-1.17.jar
+
ext/sqlite-jdbc-3.8.11.jar
release/modules/ext/sqlite-jdbc-3.8.11.jar
@@ -400,6 +405,10 @@
ext/activemq-all-5.11.1.jar
release/modules/ext/activemq-all-5.11.1.jar
+
+ ext/xz-1.6.jar
+ release/modules/ext/xz-1.6.jar
+
ext/Rejistry-1.0-SNAPSHOT.jar
release/modules/ext/Rejistry-1.0-SNAPSHOT.jar
@@ -412,14 +421,6 @@
ext/commons-pool2-2.4.2.jar
release\modules\ext\commons-pool2-2.4.2.jar
-
- ext/metadata-extractor-2.9.1.jar
- release/modules/ext/metadata-extractor-2.9.1.jar
-
-
- ext/commons-compress-1.12.jar
- release/modules/ext/commons-compress-1.12.jar
-
ext/jsoup-1.10.3.jar
release/modules/ext/jsoup-1.10.3.jar
@@ -432,6 +433,10 @@
ext/c3p0-0.9.5.jar
release/modules/ext/c3p0-0.9.5.jar
+
+ ext/xmpcore-5.1.3.jar
+ release/modules/ext/xmpcore-5.1.3.jar
+
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties
index 1cc822fea5..ab2b5c12dc 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties
@@ -223,17 +223,11 @@ ReviewModeCasePanel.MetadataFileHeaderText=Metadata File
OpenMultiUserCasePanel.jLabel1.text=Recent Cases
OpenMultiUserCasePanel.openButton.text=Open
OpenMultiUserCasePanel.cancelButton.text=Cancel
-MultiUserCasesPanel.rbWeeks.text=Weeks
-MultiUserCasesPanel.rbDays.text=Days
-MultiUserCasesPanel.bnShowLog.toolTipText=Display case log file for selected case
-MultiUserCasesPanel.bnShowLog.text=&Show Auto Ingest Case Log
-MultiUserCasesPanel.rbAllCases.text=Everything
-MultiUserCasesPanel.bnRefresh.text=&Refresh
MultiUserCasesPanel.bnOpen.text=&Open
-MultiUserCasesPanel.rbGroupLabel.text=Show cases created in the last 10:
-MultiUserCasesPanel.rbMonths.text=Months
CueBannerPanel.newCaseLabel.text=New Case
CueBannerPanel.openCaseButton.text=
CueBannerPanel.openCaseLabel.text=Open Case
MultiUserCasesPanel.bnOpenSingleUserCase.text=Open Single-User Case...
CueBannerPanel.newCaseButton.text=
+MultiUserCasesPanel.searchLabel.text=Start typing to search by case name
+MultiUserCasesPanel.cancelButton.text=Cancel
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.form b/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.form
new file mode 100644
index 0000000000..edda7a749c
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.form
@@ -0,0 +1,47 @@
+
+
+
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.java
new file mode 100644
index 0000000000..9440ca1356
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.java
@@ -0,0 +1,296 @@
+/*
+ * Autopsy Forensic Browser
+ *
+ * Copyright 2017-2018 Basis Technology Corp.
+ * Contact: carrier sleuthkit org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.sleuthkit.autopsy.casemodule;
+
+import java.awt.Component;
+import java.lang.reflect.InvocationTargetException;
+import javax.swing.ListSelectionModel;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.table.TableCellRenderer;
+import javax.swing.table.TableColumnModel;
+import org.netbeans.swing.etable.ETableColumn;
+import org.netbeans.swing.etable.ETableColumnModel;
+import org.netbeans.swing.outline.DefaultOutlineModel;
+import org.netbeans.swing.outline.Outline;
+import org.openide.nodes.Node;
+import java.awt.EventQueue;
+import java.io.File;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import javax.swing.SwingWorker;
+import org.openide.explorer.ExplorerManager;
+import org.openide.util.NbBundle;
+import org.sleuthkit.autopsy.coordinationservice.CaseNodeData;
+import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
+import org.sleuthkit.autopsy.coreutils.Logger;
+import org.sleuthkit.autopsy.datamodel.EmptyNode;
+
+/**
+ * A Swing JPanel with a scroll pane child component. The scroll pane contain
+ * the table of cases.
+ *
+ * Used to display a list of multi user cases and allow the user to open one of
+ * them.
+ *
+ */
+class CaseBrowser extends javax.swing.JPanel implements ExplorerManager.Provider {
+
+ private static final long serialVersionUID = 1L;
+ private final Outline outline;
+ private ExplorerManager em;
+ private final org.openide.explorer.view.OutlineView outlineView;
+ private int originalPathColumnIndex = 0;
+ private static final Logger LOGGER = Logger.getLogger(CaseBrowser.class.getName());
+ private LoadCaseMapWorker tableWorker;
+
+ @Override
+ public ExplorerManager getExplorerManager() {
+ return em;
+ }
+
+ /**
+ * Creates a new CaseBrowser
+ */
+ CaseBrowser() {
+ outlineView = new org.openide.explorer.view.OutlineView();
+ initComponents();
+
+ outline = outlineView.getOutline();
+ outlineView.setPropertyColumns(
+ Bundle.CaseNode_column_createdTime(), Bundle.CaseNode_column_createdTime(),
+ Bundle.CaseNode_column_status(), Bundle.CaseNode_column_status(),
+ Bundle.CaseNode_column_metadataFilePath(), Bundle.CaseNode_column_metadataFilePath());
+ ((DefaultOutlineModel) outline.getOutlineModel()).setNodesColumnLabel(Bundle.CaseNode_column_name());
+ customize();
+
+ }
+
+ /**
+ * Configures the the table of cases and its columns.
+ */
+ private void customize() {
+ outline.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+ TableColumnModel columnModel = outline.getColumnModel();
+ int dateColumnIndex = 0;
+ for (int index = 0; index < columnModel.getColumnCount(); index++) {
+ //get indexes for created date column and path column
+ if (columnModel.getColumn(index).getHeaderValue().toString().equals(Bundle.CaseNode_column_metadataFilePath())) {
+ originalPathColumnIndex = index;
+ } else if (columnModel.getColumn(index).getHeaderValue().toString().equals(Bundle.CaseNode_column_createdTime())) {
+ dateColumnIndex = index;
+ }
+ }
+ //Hide path column by default will need to
+ ETableColumn column = (ETableColumn) columnModel.getColumn(originalPathColumnIndex);
+ ((ETableColumnModel) columnModel).setColumnHidden(column, true);
+ outline.setRootVisible(false);
+
+ //Sort on Created date column in descending order by default
+ outline.setColumnSorted(dateColumnIndex, false, 1);
+ if (null == em) {
+ em = new ExplorerManager();
+ }
+ caseTableScrollPane.setViewportView(outlineView);
+ this.setVisible(true);
+ outline.setRowSelectionAllowed(false);
+ }
+
+ /**
+ * Add a listener to changes in case selections in the table
+ *
+ * @param listener the ListSelectionListener to add
+ */
+ void addListSelectionListener(ListSelectionListener listener) {
+ outline.getSelectionModel().addListSelectionListener(listener);
+ }
+
+ String getCasePath() {
+ int[] selectedRows = outline.getSelectedRows();
+ if (selectedRows.length == 1) {
+ try {
+ return ((Node.Property) outline.getModel().getValueAt(outline.convertRowIndexToModel(selectedRows[0]), originalPathColumnIndex)).getValue().toString();
+ } catch (IllegalAccessException | InvocationTargetException ex) {
+ LOGGER.log(Level.SEVERE, "Unable to get case path from table.", ex);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Check if a row could be and is selected.
+ *
+ * @return true if a row is selected, false if no row is selected
+ */
+ boolean isRowSelected() {
+ return outline.getRowSelectionAllowed() && outline.getSelectedRows().length > 0;
+ }
+
+ @NbBundle.Messages({"CaseBrowser.caseListLoading.message=Please Wait..."})
+ /**
+ * Gets the list of cases known to the review mode cases manager and
+ * refreshes the cases table.
+ */
+ void refresh() {
+ if (tableWorker == null || tableWorker.isDone()) {
+ outline.setRowSelectionAllowed(false);
+ //create a new TableWorker to and execute it in a background thread if one is not currently working
+ //set the table to display text informing the user that the list is being retreived and disable case selection
+ EmptyNode emptyNode = new EmptyNode(Bundle.CaseBrowser_caseListLoading_message());
+ em.setRootContext(emptyNode);
+ tableWorker = new LoadCaseMapWorker();
+ tableWorker.execute();
+ }
+
+ }
+
+ /**
+ * 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() {
+
+ caseTableScrollPane = new javax.swing.JScrollPane();
+
+ setMinimumSize(new java.awt.Dimension(0, 5));
+ setPreferredSize(new java.awt.Dimension(5, 5));
+ setLayout(new java.awt.BorderLayout());
+
+ caseTableScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
+ caseTableScrollPane.setMinimumSize(new java.awt.Dimension(0, 5));
+ caseTableScrollPane.setOpaque(false);
+ caseTableScrollPane.setPreferredSize(new java.awt.Dimension(5, 5));
+ add(caseTableScrollPane, java.awt.BorderLayout.CENTER);
+ }// //GEN-END:initComponents
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JScrollPane caseTableScrollPane;
+ // End of variables declaration//GEN-END:variables
+
+ /**
+ * Swingworker to fetch the updated map of cases and their status in a
+ * background thread
+ */
+ private class LoadCaseMapWorker extends SwingWorker {
+
+ private static final String ALERT_FILE_NAME = "autoingest.alert";
+ private Map cases;
+
+ /**
+ * Gets a list of the cases in the top level case folder
+ *
+ * @return List of cases.
+ *
+ * @throws CoordinationServiceException
+ */
+ private Map getCases() throws CoordinationService.CoordinationServiceException {
+ Map casesMap = new HashMap<>();
+ List nodeList = CoordinationService.getInstance().getNodeList(CoordinationService.CategoryNode.CASES);
+
+ for (String node : nodeList) {
+ Path casePath = Paths.get(node);
+ File caseFolder = casePath.toFile();
+ if (caseFolder.exists()) {
+ /*
+ * Search for '*.aut' and 'autoingest.alert' files.
+ */
+ File[] fileArray = caseFolder.listFiles();
+ if (fileArray == null) {
+ continue;
+ }
+ String autFilePath = null;
+ boolean alertFileFound = false;
+ for (File file : fileArray) {
+ String name = file.getName().toLowerCase();
+ if (autFilePath == null && name.endsWith(".aut")) {
+ autFilePath = file.getAbsolutePath();
+ if (!alertFileFound) {
+ continue;
+ }
+ }
+ if (!alertFileFound && name.endsWith(ALERT_FILE_NAME)) {
+ alertFileFound = true;
+ }
+ if (autFilePath != null && alertFileFound) {
+ break;
+ }
+ }
+
+ if (autFilePath != null) {
+ try {
+ boolean hasAlertStatus = false;
+ if (alertFileFound) {
+ /*
+ * When an alert file exists, ignore the node
+ * data and use the ALERT status.
+ */
+ hasAlertStatus = true;
+ } else {
+ byte[] rawData = CoordinationService.getInstance().getNodeData(CoordinationService.CategoryNode.CASES, node);
+ if (rawData != null && rawData.length > 0) {
+ /*
+ * When node data exists, use the status
+ * stored in the node data.
+ */
+ CaseNodeData caseNodeData = new CaseNodeData(rawData);
+ if (caseNodeData.getErrorsOccurred()) {
+ hasAlertStatus = true;
+ }
+ }
+ }
+
+ CaseMetadata caseMetadata = new CaseMetadata(Paths.get(autFilePath));
+ casesMap.put(caseMetadata, hasAlertStatus);
+ } catch (CaseMetadata.CaseMetadataException ex) {
+ LOGGER.log(Level.SEVERE, String.format("Error reading case metadata file '%s'.", autFilePath), ex);
+ } catch (InterruptedException | CaseNodeData.InvalidDataException ex) {
+ LOGGER.log(Level.SEVERE, String.format("Error reading case node data for '%s'.", node), ex);
+ }
+ }
+ }
+ }
+ return casesMap;
+ }
+
+ @Override
+ protected Void doInBackground() throws Exception {
+
+ try {
+ cases = getCases();
+ } catch (CoordinationService.CoordinationServiceException ex) {
+ LOGGER.log(Level.SEVERE, "Unexpected exception while refreshing the table.", ex); //NON-NLS
+ }
+ return null;
+ }
+
+ @Override
+ protected void done() {
+ EventQueue.invokeLater(() -> {
+ MultiUserNode caseListNode = new MultiUserNode(cases);
+ em.setRootContext(caseListNode);
+ outline.setRowSelectionAllowed(true);
+ });
+ }
+ }
+}
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java
deleted file mode 100644
index bedc09d799..0000000000
--- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCaseManager.java
+++ /dev/null
@@ -1,442 +0,0 @@
-/*
- * Autopsy Forensic Browser
- *
- * Copyright 2011-2017 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.casemodule;
-
-import java.io.File;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.nio.file.attribute.BasicFileAttributes;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.Date;
-import java.util.List;
-import java.util.Objects;
-import java.util.logging.Level;
-import org.sleuthkit.autopsy.coordinationservice.CaseNodeData;
-import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
-import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException;
-import org.sleuthkit.autopsy.coreutils.Logger;
-
-/**
- * Handles locating and opening multi-user cases.
- */
-final class MultiUserCaseManager {
-
- private static final Logger LOGGER = Logger.getLogger(MultiUserCaseManager.class.getName());
- private static final String ALERT_FILE_NAME = "autoingest.alert";
- private static MultiUserCaseManager instance;
- private CoordinationService coordinationService;
-
- /**
- * Gets the multi-user case manager.
- *
- * @return The multi-user case manager singleton.
- *
- * @throws MultiUserCaseManagerException
- */
- synchronized static MultiUserCaseManager getInstance() throws MultiUserCaseManager.MultiUserCaseManagerException {
- if (null == instance) {
- instance = new MultiUserCaseManager();
- }
- return instance;
- }
-
- /**
- * Constructs an object that handles locating and opening multi-user cases.
- *
- * @throws MultiUserCaseManagerException
- */
- private MultiUserCaseManager() throws MultiUserCaseManagerException {
- try {
- coordinationService = CoordinationService.getInstance();
- } catch (CoordinationServiceException ex) {
- throw new MultiUserCaseManager.MultiUserCaseManagerException("Failed to get the coordination service.", ex);
- }
- }
-
- /**
- * Gets a list of the cases in the top level case folder
- *
- * @return List of cases.
- *
- * @throws CoordinationServiceException
- */
- List getCases() throws CoordinationServiceException {
- List cases = new ArrayList<>();
- List nodeList = coordinationService.getNodeList(CoordinationService.CategoryNode.CASES);
- for (String node : nodeList) {
- Path casePath = Paths.get(node);
- File caseFolder = casePath.toFile();
- if (caseFolder.exists()) {
- /*
- * Search for '*.aut' and 'autoingest.alert' files.
- */
- File[] fileArray = caseFolder.listFiles();
- if (fileArray == null) {
- continue;
- }
- String autFilePath = null;
- boolean alertFileFound = false;
- for (File file : fileArray) {
- String name = file.getName().toLowerCase();
- if (autFilePath == null && name.endsWith(".aut")) {
- autFilePath = file.getAbsolutePath();
- if (!alertFileFound) {
- continue;
- }
- }
- if (!alertFileFound && name.endsWith(ALERT_FILE_NAME)) {
- alertFileFound = true;
- }
- if (autFilePath != null && alertFileFound) {
- break;
- }
- }
-
- if (autFilePath != null) {
- try {
- CaseStatus caseStatus;
- if (alertFileFound) {
- /*
- * When an alert file exists, ignore the node data
- * and use the ALERT status.
- */
- caseStatus = CaseStatus.ALERT;
- } else {
- byte[] rawData = coordinationService.getNodeData(CoordinationService.CategoryNode.CASES, node);
- if (rawData != null && rawData.length > 0) {
- /*
- * When node data exists, use the status stored
- * in the node data.
- */
- CaseNodeData caseNodeData = new CaseNodeData(rawData);
- if (caseNodeData.getErrorsOccurred()) {
- caseStatus = CaseStatus.ALERT;
- } else {
- caseStatus = CaseStatus.OK;
- }
- } else {
- /*
- * When no node data is available, use the 'OK'
- * status to avoid confusing the end-user.
- */
- caseStatus = CaseStatus.OK;
- }
- }
-
- CaseMetadata caseMetadata = new CaseMetadata(Paths.get(autFilePath));
- cases.add(new MultiUserCase(casePath, caseMetadata, caseStatus));
- } catch (CaseMetadata.CaseMetadataException | MultiUserCase.MultiUserCaseException ex) {
- LOGGER.log(Level.SEVERE, String.format("Error reading case metadata file '%s'.", autFilePath), ex);
- } catch (InterruptedException | CaseNodeData.InvalidDataException ex) {
- LOGGER.log(Level.SEVERE, String.format("Error reading case node data for '%s'.", node), ex);
- }
- }
- }
- }
- return cases;
- }
-
- /**
- * Opens a multi-user case.
- *
- * @param caseMetadataFilePath Path to the case metadata file.
- *
- * @throws CaseActionException
- */
- synchronized void openCase(Path caseMetadataFilePath) throws CaseActionException {
- /*
- * Open the case.
- */
- Case.openAsCurrentCase(caseMetadataFilePath.toString());
- }
-
- /**
- * Exception type thrown when there is an error completing a multi-user case
- * manager operation.
- */
- static final class MultiUserCaseManagerException extends Exception {
-
- private static final long serialVersionUID = 1L;
-
- /**
- * Constructs an instance of the exception type thrown when there is an
- * error completing a multi-user case manager operation.
- *
- * @param message The exception message.
- */
- private MultiUserCaseManagerException(String message) {
- super(message);
- }
-
- /**
- * Constructs an instance of the exception type thrown when there is an
- * error completing a multi-user case manager operation.
- *
- * @param message The exception message.
- * @param cause A Throwable cause for the error.
- */
- private MultiUserCaseManagerException(String message, Throwable cause) {
- super(message, cause);
- }
-
- }
-
- /**
- * A representation of a multi-user case.
- */
- static class MultiUserCase implements Comparable {
-
- private final Path caseDirectoryPath;
- private final String caseDisplayName;
- private final String metadataFileName;
- private final Date createDate;
- private final Date lastAccessedDate;
- private CaseStatus status;
-
- /**
- * Constructs a representation of a multi-user case
- *
- * @param caseDirectoryPath The case directory path.
- * @param caseMetadata The case metadata.
- *
- * @throws MultiUserCaseException If no case metadata (.aut) file is
- * found in the case directory.
- */
- MultiUserCase(Path caseDirectoryPath, CaseMetadata caseMetadata, CaseStatus status) throws MultiUserCaseException {
- this.caseDirectoryPath = caseDirectoryPath;
- caseDisplayName = caseMetadata.getCaseDisplayName();
- metadataFileName = caseMetadata.getFilePath().getFileName().toString();
- this.status = status;
- BasicFileAttributes fileAttrs = null;
- try {
- fileAttrs = Files.readAttributes(Paths.get(caseDirectoryPath.toString(), metadataFileName), BasicFileAttributes.class);
- } catch (IOException ex) {
- LOGGER.log(Level.SEVERE, String.format("Error reading file attributes of case metadata file in %s, will use current time for case createDate/lastModfiedDate", caseDirectoryPath), ex);
- }
- if (null != fileAttrs) {
- createDate = new Date(fileAttrs.creationTime().toMillis());
- lastAccessedDate = new Date(fileAttrs.lastAccessTime().toMillis());
- } else {
- createDate = new Date();
- lastAccessedDate = new Date();
- }
- }
-
- /**
- * Gets the case directory path.
- *
- * @return The case directory path.
- */
- Path getCaseDirectoryPath() {
- return this.caseDirectoryPath;
- }
-
- /**
- * Gets the case display name. This may differ from the name supplied to
- * the directory or metadata file names if a case has been renamed.
- *
- * @return The case display name.
- */
- String getCaseDisplayName() {
- return this.caseDisplayName;
- }
-
- /**
- * Gets the creation date for the case, defined as the create time of
- * the case metadata file.
- *
- * @return The case creation date.
- */
- Date getCreationDate() {
- return this.createDate;
- }
-
- /**
- * Gets the last accessed date for the case, defined as the last
- * accessed time of the case metadata file.
- *
- * @return The last accessed date.
- */
- Date getLastAccessedDate() {
- return this.lastAccessedDate;
- }
-
- /**
- * Gets metadata (.aut) file name.
- *
- * @return The metadata file name.
- */
- String getMetadataFileName() {
- return this.metadataFileName;
- }
-
- /**
- * Gets the status of this case.
- *
- * @return See CaseStatus enum definition.
- */
- CaseStatus getStatus() {
- return status;
- }
-
- /**
- * Gets the case metadata from a case directory path.
- *
- * @param caseDirectoryPath The case directory path.
- *
- * @return Case metadata.
- *
- * @throws CaseMetadata.CaseMetadataException If the CaseMetadata object
- * cannot be constructed.
- * @throws MultiUserCaseException If no case metadata (.aut)
- * file is found in the case
- * directory.
- */
- private CaseMetadata getCaseMetadataFromCaseDirectoryPath(Path caseDirectoryPath) throws CaseMetadata.CaseMetadataException, MultiUserCaseException {
- CaseMetadata caseMetadata = null;
-
- File directory = new File(caseDirectoryPath.toString());
- if (directory.isDirectory()) {
- File autFile = null;
-
- /*
- * Attempt to find an AUT file via a directory scan.
- */
- for (File file : directory.listFiles()) {
- if (file.getName().toLowerCase().endsWith(CaseMetadata.getFileExtension()) && file.isFile()) {
- autFile = file;
- break;
- }
- }
-
- if (autFile == null || !autFile.isFile()) {
- throw new MultiUserCaseException(String.format("No case metadata (.aut) file found in the case directory '%s'.", caseDirectoryPath.toString()));
- }
-
- caseMetadata = new CaseMetadata(Paths.get(autFile.getAbsolutePath()));
- }
-
- return caseMetadata;
- }
-
- /**
- * Indicates whether or not some other object is "equal to" this
- * MultiUserCase object.
- *
- * @param other The other object.
- *
- * @return True or false.
- */
- @Override
- public boolean equals(Object other) {
- if (!(other instanceof MultiUserCase)) {
- return false;
- }
- if (other == this) {
- return true;
- }
- return this.caseDirectoryPath.toString().equals(((MultiUserCase) other).caseDirectoryPath.toString());
- }
-
- /**
- * Returns a hash code value for this MultiUserCase object.
- *
- * @return The has code.
- */
- @Override
- public int hashCode() {
- int hash = 7;
- hash = 71 * hash + Objects.hashCode(this.caseDirectoryPath);
- hash = 71 * hash + Objects.hashCode(this.createDate);
- hash = 71 * hash + Objects.hashCode(this.caseDisplayName);
- return hash;
- }
-
- /**
- * Compares this MultiUserCase object with another MultiUserCase object
- * for order.
- */
- @Override
- public int compareTo(MultiUserCase other) {
- return -this.lastAccessedDate.compareTo(other.getLastAccessedDate());
- }
-
- /**
- * Comparator for a descending order sort on date created.
- */
- static class LastAccessedDateDescendingComparator implements Comparator {
-
- /**
- * Compares two MultiUserCase objects for order based on last
- * accessed date (descending).
- *
- * @param object The first MultiUserCase object
- * @param otherObject The second MultiUserCase object.
- *
- * @return A negative integer, zero, or a positive integer as the
- * first argument is less than, equal to, or greater than
- * the second.
- */
- @Override
- public int compare(MultiUserCase object, MultiUserCase otherObject) {
- return -object.getLastAccessedDate().compareTo(otherObject.getLastAccessedDate());
- }
- }
-
- /**
- * Exception thrown when there is a problem creating a multi-user case.
- */
- final class MultiUserCaseException extends Exception {
-
- private static final long serialVersionUID = 1L;
-
- /**
- * Constructs an exception to throw when there is a problem creating
- * a multi-user case.
- *
- * @param message The exception message.
- */
- private MultiUserCaseException(String message) {
- super(message);
- }
-
- /**
- * Constructs an exception to throw when there is a problem creating
- * a multi-user case.
- *
- * @param message The exception message.
- * @param cause The cause of the exception, if it was an
- * exception.
- */
- private MultiUserCaseException(String message, Throwable cause) {
- super(message, cause);
- }
- }
-
- }
-
- static enum CaseStatus {
- OK,
- ALERT
- }
-
-}
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.form
index 58ef6f79fb..3f897d70c0 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.form
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.form
@@ -1,10 +1,6 @@
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java
index e0d63f07d7..a2a2ec13ad 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java
@@ -19,79 +19,29 @@
package org.sleuthkit.autopsy.casemodule;
import java.awt.Cursor;
-import java.awt.Desktop;
-import java.io.IOException;
-import java.nio.file.Path;
-import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Date;
-import java.util.List;
import java.util.logging.Level;
import javax.swing.JDialog;
-import javax.swing.JOptionPane;
+import javax.swing.JPanel;
import javax.swing.SortOrder;
-import javax.swing.SwingWorker;
import javax.swing.SwingUtilities;
import javax.swing.event.ListSelectionEvent;
import javax.swing.table.DefaultTableModel;
-import javax.swing.table.TableColumn;
import javax.swing.table.TableRowSorter;
import org.openide.util.Lookup;
-import org.openide.util.NbBundle;
-import org.sleuthkit.autopsy.casemodule.MultiUserCaseManager.MultiUserCase;
-import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
import org.sleuthkit.autopsy.coreutils.Logger;
-import org.sleuthkit.autopsy.guiutils.LongDateCellRenderer;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
-import org.sleuthkit.autopsy.guiutils.GrayableCellRenderer;
-import org.sleuthkit.autopsy.guiutils.StatusIconCellRenderer;
/**
* A panel that allows a user to open cases created by auto ingest.
*/
-@NbBundle.Messages({"MultiUSerCasesPanel.caseListLoading.message=Retrieving list of cases, please wait..."})
-final class MultiUserCasesPanel extends javax.swing.JPanel {
+final class MultiUserCasesPanel extends JPanel{
- private static final long serialVersionUID = 1L;
private static final Logger LOGGER = Logger.getLogger(MultiUserCasesPanel.class.getName());
- private static final String LOG_FILE_NAME = "auto_ingest_log.txt";
- private static final int CASE_COL_MIN_WIDTH = 30;
- private static final int CASE_COL_MAX_WIDTH = 2000;
- private static final int CASE_COL_PREFERRED_WIDTH = 300;
- private static final int TIME_COL_MIN_WIDTH = 40;
- private static final int TIME_COL_MAX_WIDTH = 250;
- private static final int TIME_COL_PREFERRED_WIDTH = 160;
- private static final int STATUS_COL_MIN_WIDTH = 55;
- private static final int STATUS_COL_MAX_WIDTH = 250;
- private static final int STATUS_COL_PREFERRED_WIDTH = 60;
- private static final String CASES_POPULATING_MESSAGE = NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUSerCasesPanel.caseListLoading.message");
-
- /*
- * The JTable table model for the cases table presented by this view is
- * defined by the following string, enum, and array.
- *
- * TODO (RC): Consider unifying this stuff in an enum as in
- * AutoIngestDashboard to make it less error prone.
- */
- private static final String CASE_HEADER = NbBundle.getMessage(MultiUserCasesPanel.class, "ReviewModeCasePanel.CaseHeaderText");
- private static final String CREATEDTIME_HEADER = NbBundle.getMessage(MultiUserCasesPanel.class, "ReviewModeCasePanel.CreatedTimeHeaderText");
- private static final String STATUS_ICON_HEADER = NbBundle.getMessage(MultiUserCasesPanel.class, "ReviewModeCasePanel.StatusIconHeaderText");
- private static final String OUTPUT_FOLDER_HEADER = NbBundle.getMessage(MultiUserCasesPanel.class, "ReviewModeCasePanel.OutputFolderHeaderText");
- private static final String METADATA_FILE_HEADER = NbBundle.getMessage(MultiUserCasesPanel.class, "ReviewModeCasePanel.MetadataFileHeaderText");
-
- enum COLUMN_HEADERS {
-
- CASE,
- CREATEDTIME,
- STATUS_ICON,
- OUTPUTFOLDER,
- METADATA_FILE
- }
- private final String[] columnNames = {CASE_HEADER, CREATEDTIME_HEADER, STATUS_ICON_HEADER, OUTPUT_FOLDER_HEADER, METADATA_FILE_HEADER};
- private DefaultTableModel caseTableModel;
- private JDialog parentDialog;
- private LoadTableWorker tableWorker;
- private Path currentlySelectedCase;
+ private static final long serialVersionUID = 1L;
+ private final JDialog parentDialog;
+ private final CaseBrowser caseBrowserPanel;
/**
* Constructs a panel that allows a user to open cases created by automated
@@ -99,66 +49,19 @@ final class MultiUserCasesPanel extends javax.swing.JPanel {
*/
MultiUserCasesPanel(JDialog parentDialog) {
this.parentDialog = parentDialog;
- caseTableModel = new DefaultTableModel(columnNames, 0) {
- private static final long serialVersionUID = 1L;
-
- @Override
- public boolean isCellEditable(int row, int column) {
- return false;
- }
-
- @Override
- public Class> getColumnClass(int col) {
- if (this.getColumnName(col).equals(CREATEDTIME_HEADER)) {
- return Date.class;
- } else {
- return super.getColumnClass(col);
- }
- }
- };
-
initComponents();
- /*
- * Configure the columns of the cases table.
- */
- TableColumn theColumn;
- theColumn = casesTable.getColumn(CASE_HEADER);
- theColumn.setCellRenderer(new GrayableCellRenderer());
- theColumn.setMinWidth(CASE_COL_MIN_WIDTH);
- theColumn.setMaxWidth(CASE_COL_MAX_WIDTH);
- theColumn.setPreferredWidth(CASE_COL_PREFERRED_WIDTH);
- theColumn.setWidth(CASE_COL_PREFERRED_WIDTH);
-
- theColumn = casesTable.getColumn(CREATEDTIME_HEADER);
- theColumn.setCellRenderer(new LongDateCellRenderer());
- theColumn.setMinWidth(TIME_COL_MIN_WIDTH);
- theColumn.setMaxWidth(TIME_COL_MAX_WIDTH);
- theColumn.setPreferredWidth(TIME_COL_PREFERRED_WIDTH);
- theColumn.setWidth(TIME_COL_PREFERRED_WIDTH);
-
- theColumn = casesTable.getColumn(STATUS_ICON_HEADER);
- theColumn.setCellRenderer(new StatusIconCellRenderer());
- theColumn.setMinWidth(STATUS_COL_MIN_WIDTH);
- theColumn.setMaxWidth(STATUS_COL_MAX_WIDTH);
- theColumn.setPreferredWidth(STATUS_COL_PREFERRED_WIDTH);
- theColumn.setWidth(STATUS_COL_PREFERRED_WIDTH);
-
- casesTable.removeColumn(casesTable.getColumn(OUTPUT_FOLDER_HEADER));
- casesTable.removeColumn(casesTable.getColumn(METADATA_FILE_HEADER));
- casesTable.setRowSorter(new RowSorter<>(caseTableModel));
- casesTable.getRowSorter().toggleSortOrder(casesTable.getColumn(CREATEDTIME_HEADER).getModelIndex());
+ caseBrowserPanel = new CaseBrowser();
+ caseExplorerScrollPane.add(caseBrowserPanel);
+ caseExplorerScrollPane.setViewportView(caseBrowserPanel);
/*
* Listen for row selection changes and set button state for the current
* selection.
*/
- casesTable.getSelectionModel().addListSelectionListener((ListSelectionEvent e) -> {
- //Ignore extra messages.
- if (e.getValueIsAdjusting()) {
- return;
- }
+ caseBrowserPanel.addListSelectionListener((ListSelectionEvent e) -> {
setButtons();
});
+
}
/**
@@ -166,87 +69,15 @@ final class MultiUserCasesPanel extends javax.swing.JPanel {
* refreshes the cases table.
*/
void refresh() {
- if (tableWorker == null || tableWorker.isDone()) {
- //create a new TableWorker to and execute it in a background thread if one is not currently working
- currentlySelectedCase = getSelectedCase();
- //set the table to display text informing the user that the list is being retreived and disable case selection
- caseTableModel.setRowCount(0);
- casesTable.setRowSelectionAllowed(false);
- caseTableModel.addRow(new Object[]{CASES_POPULATING_MESSAGE, null, null, "", ""});
- tableWorker = new LoadTableWorker();
- tableWorker.execute();
- }
- }
-
- /**
- * Gets the current selection in the cases table.
- *
- * @return A path representing the current selected case, null if there is
- * no selection.
- */
- private Path getSelectedCase() {
- try {
- int selectedRow = casesTable.getSelectedRow();
- if (selectedRow >= 0 && selectedRow < casesTable.getRowCount()) {
- return Paths.get(caseTableModel.getValueAt(casesTable.convertRowIndexToModel(selectedRow), COLUMN_HEADERS.CASE.ordinal()).toString());
- }
- } catch (Exception ignored) {
- return null;
- }
- return null;
- }
-
- /**
- * Sets the current selection in the cases table.
- *
- * @param path The case folder path of the case to select.
- */
- private void setSelectedCase(Path path) {
- if (path != null) {
- try {
- for (int row = 0; row < casesTable.getRowCount(); ++row) {
- Path temp = Paths.get(caseTableModel.getValueAt(casesTable.convertRowIndexToModel(row), COLUMN_HEADERS.CASE.ordinal()).toString());
- if (temp.compareTo(path) == 0) { // found it
- casesTable.setRowSelectionInterval(row, row);
- return;
- }
- }
- } catch (Exception ignored) {
- casesTable.clearSelection();
- }
- }
- casesTable.clearSelection();
+ caseBrowserPanel.refresh();
}
/**
* Enables/disables the Open and Show Log buttons based on the case selected
* in the cases table.
*/
- private void setButtons() {
- boolean openEnabled = casesTable.getRowSelectionAllowed() && casesTable.getSelectedRow() >= 0 && casesTable.getSelectedRow() < casesTable.getRowCount();
- bnOpen.setEnabled(openEnabled);
-
- Path pathToLog = getSelectedCaseLogFilePath();
- boolean showLogEnabled = openEnabled && pathToLog != null && pathToLog.toFile().exists();
- bnShowLog.setEnabled(showLogEnabled);
- }
-
- /**
- * Retrieves the log file path for the selected case in the cases table.
- *
- * @return The case log path.
- */
- private Path getSelectedCaseLogFilePath() {
- Path retValue = null;
-
- int selectedRow = casesTable.getSelectedRow();
- int rowCount = casesTable.getRowCount();
- if (selectedRow >= 0 && selectedRow < rowCount) {
- String caseDirectory = (String) caseTableModel.getValueAt(casesTable.convertRowIndexToModel(selectedRow), COLUMN_HEADERS.OUTPUTFOLDER.ordinal());
- retValue = Paths.get(caseDirectory, LOG_FILE_NAME);
- }
-
- return retValue;
+ void setButtons() {
+ bnOpen.setEnabled(caseBrowserPanel.isRowSelected());
}
/**
@@ -254,56 +85,34 @@ final class MultiUserCasesPanel extends javax.swing.JPanel {
*
* @param caseMetadataFilePath The path to the case metadata file.
*/
- private void openCase(Path caseMetadataFilePath) {
- setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+ private void openCase(String caseMetadataFilePath) {
+ if (caseMetadataFilePath != null) {
+ setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
- StartupWindowProvider.getInstance().close();
- if (parentDialog != null) {
- parentDialog.setVisible(false);
- }
- new Thread(() -> {
- try {
- MultiUserCaseManager.getInstance().openCase(caseMetadataFilePath);
- } catch (CaseActionException | MultiUserCaseManager.MultiUserCaseManagerException ex) {
- if (null != ex.getCause() && !(ex.getCause() instanceof CaseActionCancelledException)) {
- LOGGER.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", caseMetadataFilePath), ex); //NON-NLS
- MessageNotifyUtil.Message.error(ex.getCause().getLocalizedMessage());
- }
- SwingUtilities.invokeLater(() -> {
- //GUI changes done back on the EDT
- StartupWindowProvider.getInstance().open();
- });
- } finally {
- SwingUtilities.invokeLater(() -> {
- //GUI changes done back on the EDT
- setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
- });
+ StartupWindowProvider.getInstance().close();
+ if (parentDialog != null) {
+ parentDialog.setVisible(false);
}
- }).start();
- }
-
- /**
- * Indicates whether or not a time satisfies a time filter defined by this
- * panel's time filter radio buttons.
- *
- * @param currentTime The current date and time in milliseconds from the
- * Unix epoch.
- * @param inputTime The date and time to be tested as milliseconds from
- * the Unix epoch.
- */
- private boolean passesTimeFilter(long currentTime, long inputTime) {
- long numberOfUnits = 10;
- long multiplier = 1;
- if (rbAllCases.isSelected()) {
- return true;
- } else if (rbMonths.isSelected()) {
- multiplier = 31;
- } else if (rbWeeks.isSelected()) {
- multiplier = 7;
- } else if (rbDays.isSelected()) {
- multiplier = 1;
+ new Thread(() -> {
+ try {
+ Case.openAsCurrentCase(caseMetadataFilePath);
+ } catch (CaseActionException ex) {
+ if (null != ex.getCause() && !(ex.getCause() instanceof CaseActionCancelledException)) {
+ LOGGER.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", caseMetadataFilePath), ex); //NON-NLS
+ MessageNotifyUtil.Message.error(ex.getCause().getLocalizedMessage());
+ }
+ SwingUtilities.invokeLater(() -> {
+ //GUI changes done back on the EDT
+ StartupWindowProvider.getInstance().open();
+ });
+ } finally {
+ SwingUtilities.invokeLater(() -> {
+ //GUI changes done back on the EDT
+ setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+ });
+ }
+ }).start();
}
- return ((currentTime - inputTime) / (1000 * 60 * 60 * 24)) < (numberOfUnits * multiplier);
}
/**
@@ -345,19 +154,11 @@ final class MultiUserCasesPanel extends javax.swing.JPanel {
// //GEN-BEGIN:initComponents
private void initComponents() {
- rbGroupHistoryLength = new javax.swing.ButtonGroup();
bnOpen = new javax.swing.JButton();
- scrollPaneTable = new javax.swing.JScrollPane();
- casesTable = new javax.swing.JTable();
- bnRefresh = new javax.swing.JButton();
- panelFilter = new javax.swing.JPanel();
- rbAllCases = new javax.swing.JRadioButton();
- bnShowLog = new javax.swing.JButton();
- rbDays = new javax.swing.JRadioButton();
- rbWeeks = new javax.swing.JRadioButton();
- rbMonths = new javax.swing.JRadioButton();
- rbGroupLabel = new javax.swing.JLabel();
bnOpenSingleUserCase = new javax.swing.JButton();
+ cancelButton = new javax.swing.JButton();
+ searchLabel = new javax.swing.JLabel();
+ caseExplorerScrollPane = new javax.swing.JScrollPane();
setName("Completed Cases"); // NOI18N
setPreferredSize(new java.awt.Dimension(960, 485));
@@ -370,84 +171,6 @@ final class MultiUserCasesPanel extends javax.swing.JPanel {
}
});
- casesTable.setModel(caseTableModel);
- casesTable.setRowHeight(20);
- casesTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
- casesTable.addMouseListener(new java.awt.event.MouseAdapter() {
- public void mouseClicked(java.awt.event.MouseEvent evt) {
- casesTableMouseClicked(evt);
- }
- });
- scrollPaneTable.setViewportView(casesTable);
-
- org.openide.awt.Mnemonics.setLocalizedText(bnRefresh, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUserCasesPanel.bnRefresh.text")); // NOI18N
- bnRefresh.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- bnRefreshActionPerformed(evt);
- }
- });
-
- rbGroupHistoryLength.add(rbAllCases);
- rbAllCases.setSelected(true);
- org.openide.awt.Mnemonics.setLocalizedText(rbAllCases, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUserCasesPanel.rbAllCases.text")); // NOI18N
- rbAllCases.addItemListener(new java.awt.event.ItemListener() {
- public void itemStateChanged(java.awt.event.ItemEvent evt) {
- rbAllCasesItemStateChanged(evt);
- }
- });
-
- javax.swing.GroupLayout panelFilterLayout = new javax.swing.GroupLayout(panelFilter);
- panelFilter.setLayout(panelFilterLayout);
- panelFilterLayout.setHorizontalGroup(
- panelFilterLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGroup(panelFilterLayout.createSequentialGroup()
- .addComponent(rbAllCases)
- .addGap(0, 0, Short.MAX_VALUE))
- );
- panelFilterLayout.setVerticalGroup(
- panelFilterLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, panelFilterLayout.createSequentialGroup()
- .addGap(0, 0, 0)
- .addComponent(rbAllCases))
- );
-
- org.openide.awt.Mnemonics.setLocalizedText(bnShowLog, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUserCasesPanel.bnShowLog.text")); // NOI18N
- bnShowLog.setToolTipText(org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUserCasesPanel.bnShowLog.toolTipText")); // NOI18N
- bnShowLog.setEnabled(false);
- bnShowLog.addActionListener(new java.awt.event.ActionListener() {
- public void actionPerformed(java.awt.event.ActionEvent evt) {
- bnShowLogActionPerformed(evt);
- }
- });
-
- rbGroupHistoryLength.add(rbDays);
- org.openide.awt.Mnemonics.setLocalizedText(rbDays, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUserCasesPanel.rbDays.text")); // NOI18N
- rbDays.setName(""); // NOI18N
- rbDays.addItemListener(new java.awt.event.ItemListener() {
- public void itemStateChanged(java.awt.event.ItemEvent evt) {
- rbDaysItemStateChanged(evt);
- }
- });
-
- rbGroupHistoryLength.add(rbWeeks);
- org.openide.awt.Mnemonics.setLocalizedText(rbWeeks, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUserCasesPanel.rbWeeks.text")); // NOI18N
- rbWeeks.addItemListener(new java.awt.event.ItemListener() {
- public void itemStateChanged(java.awt.event.ItemEvent evt) {
- rbWeeksItemStateChanged(evt);
- }
- });
-
- rbGroupHistoryLength.add(rbMonths);
- org.openide.awt.Mnemonics.setLocalizedText(rbMonths, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUserCasesPanel.rbMonths.text")); // NOI18N
- rbMonths.addItemListener(new java.awt.event.ItemListener() {
- public void itemStateChanged(java.awt.event.ItemEvent evt) {
- rbMonthsItemStateChanged(evt);
- }
- });
-
- rbGroupLabel.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
- org.openide.awt.Mnemonics.setLocalizedText(rbGroupLabel, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUserCasesPanel.rbGroupLabel.text")); // NOI18N
-
org.openide.awt.Mnemonics.setLocalizedText(bnOpenSingleUserCase, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUserCasesPanel.bnOpenSingleUserCase.text")); // NOI18N
bnOpenSingleUserCase.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
@@ -455,55 +178,45 @@ final class MultiUserCasesPanel extends javax.swing.JPanel {
}
});
+ org.openide.awt.Mnemonics.setLocalizedText(cancelButton, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUserCasesPanel.cancelButton.text")); // NOI18N
+ cancelButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ cancelButtonActionPerformed(evt);
+ }
+ });
+
+ org.openide.awt.Mnemonics.setLocalizedText(searchLabel, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUserCasesPanel.searchLabel.text")); // NOI18N
+
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGroup(layout.createSequentialGroup()
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap()
- .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
+ .addComponent(caseExplorerScrollPane)
.addGroup(layout.createSequentialGroup()
- .addGap(4, 4, 4)
+ .addComponent(searchLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 555, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 175, Short.MAX_VALUE)
.addComponent(bnOpen, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(bnOpenSingleUserCase)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(bnShowLog)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 13, Short.MAX_VALUE)
- .addComponent(rbGroupLabel)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(rbDays)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(rbWeeks)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(rbMonths)
- .addGap(0, 0, 0)
- .addComponent(panelFilter, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addGap(14, 14, 14)
- .addComponent(bnRefresh))
- .addComponent(scrollPaneTable))
+ .addComponent(cancelButton)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(6, 6, 6)
- .addComponent(scrollPaneTable, javax.swing.GroupLayout.PREFERRED_SIZE, 450, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(caseExplorerScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 450, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
- .addComponent(bnOpen)
- .addComponent(bnOpenSingleUserCase)
- .addComponent(bnShowLog))
- .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
- .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
- .addComponent(rbDays)
- .addComponent(rbWeeks)
- .addComponent(rbMonths)
- .addComponent(rbGroupLabel))
- .addComponent(panelFilter, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
- .addComponent(bnRefresh, javax.swing.GroupLayout.Alignment.TRAILING))
- .addGap(0, 0, 0))
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(cancelButton)
+ .addComponent(bnOpen)
+ .addComponent(bnOpenSingleUserCase)
+ .addComponent(searchLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
}// //GEN-END:initComponents
@@ -513,129 +226,24 @@ final class MultiUserCasesPanel extends javax.swing.JPanel {
* @param evt -- The event that caused this to be called
*/
private void bnOpenActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnOpenActionPerformed
- int modelRow = casesTable.convertRowIndexToModel(casesTable.getSelectedRow());
- String caseDirectory = (String) caseTableModel.getValueAt(modelRow, COLUMN_HEADERS.OUTPUTFOLDER.ordinal());
- Path caseMetadataFilePath = Paths.get(caseDirectory, (String) caseTableModel.getValueAt(modelRow, COLUMN_HEADERS.METADATA_FILE.ordinal()));
- openCase(caseMetadataFilePath);
+ openCase(caseBrowserPanel.getCasePath());
}//GEN-LAST:event_bnOpenActionPerformed
- /**
- * Refresh button action
- *
- * @param evt -- The event that caused this to be called
- */
- private void bnRefreshActionPerformed(java.awt.event.ActionEvent evt) {
- refresh();
- }
-
- private void rbDaysItemStateChanged(java.awt.event.ItemEvent evt) {
- if (rbDays.isSelected()) {
- refresh();
- }
- }
-
- private void rbAllCasesItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_rbAllCasesItemStateChanged
- if (rbAllCases.isSelected()) {
- refresh();
- }
- }//GEN-LAST:event_rbAllCasesItemStateChanged
-
- private void rbMonthsItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_rbMonthsItemStateChanged
- if (rbMonths.isSelected()) {
- refresh();
- }
- }//GEN-LAST:event_rbMonthsItemStateChanged
-
- private void rbWeeksItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_rbWeeksItemStateChanged
- if (rbWeeks.isSelected()) {
- refresh();
- }
- }//GEN-LAST:event_rbWeeksItemStateChanged
-
- private void bnShowLogActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnShowLogActionPerformed
- Path pathToLog = getSelectedCaseLogFilePath();
- if (pathToLog != null) {
- try {
- if (pathToLog.toFile().exists()) {
- Desktop.getDesktop().edit(pathToLog.toFile());
-
- } else {
- JOptionPane.showMessageDialog(this, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "DisplayLogDialog.cannotFindLog"),
- org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "DisplayLogDialog.unableToShowLogFile"), JOptionPane.ERROR_MESSAGE);
- }
- } catch (IOException ex) {
- LOGGER.log(Level.SEVERE, String.format("Error attempting to open case auto ingest log file %s", pathToLog), ex);
- JOptionPane.showMessageDialog(this,
- org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "DisplayLogDialog.cannotOpenLog"),
- org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "DisplayLogDialog.unableToShowLogFile"),
- JOptionPane.PLAIN_MESSAGE);
- }
- }
- }//GEN-LAST:event_bnShowLogActionPerformed
-
- private void casesTableMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_casesTableMouseClicked
- if (evt.getClickCount() == 2 && casesTable.getRowSelectionAllowed() && casesTable.getSelectedRow() >= 0 && casesTable.getSelectedRow() < casesTable.getRowCount()) {
- int modelRow = casesTable.convertRowIndexToModel(casesTable.getSelectedRow());
- String caseDirectory = (String) caseTableModel.getValueAt(modelRow, COLUMN_HEADERS.OUTPUTFOLDER.ordinal());
- Path caseMetadataFilePath = Paths.get(caseDirectory, (String) caseTableModel.getValueAt(modelRow, COLUMN_HEADERS.METADATA_FILE.ordinal()));
- openCase(caseMetadataFilePath);
- }
- }//GEN-LAST:event_casesTableMouseClicked
-
private void bnOpenSingleUserCaseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnOpenSingleUserCaseActionPerformed
Lookup.getDefault().lookup(CaseOpenAction.class).openCaseSelectionWindow();
}//GEN-LAST:event_bnOpenSingleUserCaseActionPerformed
+ private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed
+ if (parentDialog != null) {
+ parentDialog.setVisible(false);
+ }
+ }//GEN-LAST:event_cancelButtonActionPerformed
+
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton bnOpen;
private javax.swing.JButton bnOpenSingleUserCase;
- private javax.swing.JButton bnRefresh;
- private javax.swing.JButton bnShowLog;
- private javax.swing.JTable casesTable;
- private javax.swing.JPanel panelFilter;
- private javax.swing.JRadioButton rbAllCases;
- private javax.swing.JRadioButton rbDays;
- private javax.swing.ButtonGroup rbGroupHistoryLength;
- private javax.swing.JLabel rbGroupLabel;
- private javax.swing.JRadioButton rbMonths;
- private javax.swing.JRadioButton rbWeeks;
- private javax.swing.JScrollPane scrollPaneTable;
+ private javax.swing.JButton cancelButton;
+ private javax.swing.JScrollPane caseExplorerScrollPane;
+ private javax.swing.JLabel searchLabel;
// End of variables declaration//GEN-END:variables
-
- private class LoadTableWorker extends SwingWorker {
-
- private List cases;
-
- @Override
- protected Void doInBackground() throws Exception {
-
- try {
- MultiUserCaseManager manager = MultiUserCaseManager.getInstance();
- cases = manager.getCases();
- } catch (MultiUserCaseManager.MultiUserCaseManagerException | CoordinationService.CoordinationServiceException ex) {
- LOGGER.log(Level.SEVERE, "Unexpected exception while refreshing the table.", ex); //NON-NLS
- }
- return null;
- }
-
- @Override
- protected void done() {
- caseTableModel.setRowCount(0);
- long now = new Date().getTime();
- for (MultiUserCase autoIngestCase : cases) {
- if (autoIngestCase.getCreationDate() != null && passesTimeFilter(now, autoIngestCase.getCreationDate().getTime())) {
- caseTableModel.addRow(new Object[]{
- autoIngestCase.getCaseDisplayName(),
- autoIngestCase.getCreationDate(),
- (MultiUserCaseManager.CaseStatus.OK != autoIngestCase.getStatus()) ? StatusIconCellRenderer.Status.WARNING : StatusIconCellRenderer.Status.OK,
- autoIngestCase.getCaseDirectoryPath().toString(),
- autoIngestCase.getMetadataFileName()});
- }
- }
- //ensure the cases are able to be selected
- casesTable.setRowSelectionAllowed(true);
- setSelectedCase(currentlySelectedCase);
- setButtons();
- }
- }
}
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserNode.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserNode.java
new file mode 100644
index 0000000000..9443ae35e9
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserNode.java
@@ -0,0 +1,241 @@
+/*
+ * Autopsy Forensic Browser
+ *
+ * Copyright 2017-2018 Basis Technology Corp.
+ * Contact: carrier sleuthkit org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.sleuthkit.autopsy.casemodule;
+
+import java.awt.Desktop;
+import java.awt.event.ActionEvent;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.logging.Level;
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+import javax.swing.JOptionPane;
+import javax.swing.SwingUtilities;
+import org.openide.nodes.AbstractNode;
+import org.openide.nodes.ChildFactory;
+import org.openide.nodes.Children;
+import org.openide.nodes.Node;
+import org.openide.nodes.Sheet;
+import org.openide.util.NbBundle.Messages;
+import org.sleuthkit.autopsy.coreutils.Logger;
+import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
+import org.sleuthkit.autopsy.datamodel.NodeProperty;
+
+/**
+ * A root node containing child nodes of the multi user cases
+ */
+final class MultiUserNode extends AbstractNode {
+
+ @Messages({"CaseNode.column.name=Name",
+ "CaseNode.column.createdTime=Created Time",
+ "CaseNode.column.status=Status",
+ "CaseNode.column.metadataFilePath=Path"})
+ private static final Logger LOGGER = Logger.getLogger(MultiUserNode.class.getName());
+ private static final String LOG_FILE_NAME = "auto_ingest_log.txt";
+
+ /**
+ * Provides a root node with children which each represent a case.
+ *
+ * @param caseMap the map of cases and a boolean indicating if they have an
+ * alert
+ */
+ MultiUserNode(Map caseMap) {
+ super(Children.create(new MultiUserNodeChildren(caseMap), true));
+ }
+
+ static class MultiUserNodeChildren extends ChildFactory> {
+
+ private final Map caseMap;
+
+ MultiUserNodeChildren(Map caseMap) {
+ this.caseMap = caseMap;
+ }
+
+ @Override
+ protected boolean createKeys(List> list) {
+ if (caseMap != null && caseMap.size() > 0) {
+ list.addAll(caseMap.entrySet());
+ }
+ return true;
+ }
+
+ @Override
+ protected Node createNodeForKey(Entry key) {
+ return new MultiUserCaseNode(key);
+ }
+
+ }
+
+ /**
+ * A node which represents a single multi user case.
+ */
+ static final class MultiUserCaseNode extends AbstractNode {
+
+ private final String caseName;
+ private final String caseCreatedDate;
+ private final String caseMetadataFilePath;
+ private final boolean caseHasAlert;
+ private final Path caseLogFilePath;
+
+ MultiUserCaseNode(Entry multiUserCase) {
+ super(Children.LEAF);
+ caseName = multiUserCase.getKey().getCaseDisplayName();
+ caseCreatedDate = multiUserCase.getKey().getCreatedDate();
+ caseHasAlert = multiUserCase.getValue();
+ super.setName(caseName);
+ setName(caseName);
+ setDisplayName(caseName);
+ caseMetadataFilePath = multiUserCase.getKey().getFilePath().toString();
+ caseLogFilePath = Paths.get(multiUserCase.getKey().getCaseDirectory(), LOG_FILE_NAME);
+ }
+
+ /**
+ * Returns action to open the Case represented by this node
+ * @return an action which will open the current case
+ */
+ @Override
+ public Action getPreferredAction() {
+ return new OpenMultiUserCaseAction(caseMetadataFilePath);
+ }
+
+ @Messages({"MultiUserNode.AlertColumn.text=Alert"}) //text to display when there is an alert present
+ @Override
+ protected Sheet createSheet() {
+ Sheet s = super.createSheet();
+ Sheet.Set ss = s.get(Sheet.PROPERTIES);
+ if (ss == null) {
+ ss = Sheet.createPropertiesSet();
+ s.put(ss);
+ }
+ ss.put(new NodeProperty<>(Bundle.CaseNode_column_name(), Bundle.CaseNode_column_name(), Bundle.CaseNode_column_name(),
+ caseName));
+ ss.put(new NodeProperty<>(Bundle.CaseNode_column_createdTime(), Bundle.CaseNode_column_createdTime(), Bundle.CaseNode_column_createdTime(),
+ caseCreatedDate));
+ ss.put(new NodeProperty<>(Bundle.CaseNode_column_status(), Bundle.CaseNode_column_status(), Bundle.CaseNode_column_status(),
+ (caseHasAlert == true ? Bundle.MultiUserNode_AlertColumn_text() : "")));
+ ss.put(new NodeProperty<>(Bundle.CaseNode_column_metadataFilePath(), Bundle.CaseNode_column_metadataFilePath(), Bundle.CaseNode_column_metadataFilePath(),
+ caseMetadataFilePath));
+ return s;
+ }
+
+ @Override
+ public Action[] getActions(boolean context) {
+ List actions = new ArrayList<>();
+ actions.add(new OpenMultiUserCaseAction(caseMetadataFilePath)); //open case context menu option
+ actions.add(new OpenCaseLogAction(caseLogFilePath));
+ return actions.toArray(new Action[actions.size()]);
+ }
+ }
+
+ @Messages({"MultiUserNode.OpenMultiUserCaseAction.text=Open Case"})
+ /**
+ * An action that opens the specified case and hides the multi user case
+ * panel.
+ */
+ private static final class OpenMultiUserCaseAction extends AbstractAction {
+
+ private static final long serialVersionUID = 1L;
+
+ private final String caseMetadataFilePath;
+
+ OpenMultiUserCaseAction(String path) {
+ super(Bundle.MultiUserNode_OpenMultiUserCaseAction_text());
+ caseMetadataFilePath = path;
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ StartupWindowProvider.getInstance().close();
+ MultiUserCasesDialog.getInstance().setVisible(false);
+ new Thread(
+ () -> {
+ try {
+ Case.openAsCurrentCase(caseMetadataFilePath);
+ } catch (CaseActionException ex) {
+ if (null != ex.getCause() && !(ex.getCause() instanceof CaseActionCancelledException)) {
+ LOGGER.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", caseMetadataFilePath), ex); //NON-NLS
+ MessageNotifyUtil.Message.error(ex.getCause().getLocalizedMessage());
+ }
+ SwingUtilities.invokeLater(() -> {
+ //GUI changes done back on the EDT
+ StartupWindowProvider.getInstance().open();
+ MultiUserCasesDialog.getInstance().setVisible(true);
+ });
+ }
+ }
+ ).start();
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ return super.clone(); //To change body of generated methods, choose Tools | Templates.
+ }
+ }
+
+ @Messages({"MultiUserNode.OpenCaseLogAction.text=Open Log File"})
+ /**
+ * An action that opens the specified case and hides the multi user case
+ * panel.
+ */
+ private static final class OpenCaseLogAction extends AbstractAction {
+
+ private static final long serialVersionUID = 1L;
+
+ private final Path pathToLog;
+
+ OpenCaseLogAction(Path caseLogFilePath) {
+ super(Bundle.MultiUserNode_OpenCaseLogAction_text());
+ pathToLog = caseLogFilePath;
+ this.setEnabled(caseLogFilePath != null && caseLogFilePath.toFile().exists());
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+
+ if (pathToLog != null) {
+ try {
+ if (pathToLog.toFile().exists()) {
+ Desktop.getDesktop().edit(pathToLog.toFile());
+
+ } else {
+ JOptionPane.showMessageDialog(MultiUserCasesDialog.getInstance(), org.openide.util.NbBundle.getMessage(MultiUserNode.class, "DisplayLogDialog.cannotFindLog"),
+ org.openide.util.NbBundle.getMessage(MultiUserNode.class, "DisplayLogDialog.unableToShowLogFile"), JOptionPane.ERROR_MESSAGE);
+ }
+ } catch (IOException ex) {
+ LOGGER.log(Level.SEVERE, String.format("Error attempting to open case auto ingest log file %s", pathToLog), ex);
+ JOptionPane.showMessageDialog(MultiUserCasesDialog.getInstance(),
+ org.openide.util.NbBundle.getMessage(MultiUserNode.class, "DisplayLogDialog.cannotOpenLog"),
+ org.openide.util.NbBundle.getMessage(MultiUserNode.class, "DisplayLogDialog.unableToShowLogFile"),
+ JOptionPane.PLAIN_MESSAGE);
+ }
+ }
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ return super.clone(); //To change body of generated methods, choose Tools | Templates.
+ }
+ }
+
+}
diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties b/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties
index 45916b87b3..8267587395 100644
--- a/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties
+++ b/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties
@@ -33,3 +33,7 @@ MessageContentViewer.directionText.text=direction
MessageContentViewer.ccLabel.text=CC:
MessageContentViewer.attachmentsPanel.TabConstraints.tabTitle=Attachments
MessageContentViewer.viewInNewWindowButton.text=View in New Window
+JPEGViewerDummy.jLabel1.text=You are looking at a JPEG file:
+JPEGViewerDummy.jTextField1.text=jTextField1
+SQLiteViewer.jLabel1.text=Table
+SQLiteViewer.numEntriesField.text=num Entries
diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/FileTypeViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/FileTypeViewer.java
new file mode 100644
index 0000000000..f4a677c4f4
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/contentviewers/FileTypeViewer.java
@@ -0,0 +1,50 @@
+/*
+ * Autopsy Forensic Browser
+ *
+ * Copyright 2018 Basis Technology Corp.
+ * Contact: carrier sleuthkit org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.sleuthkit.autopsy.contentviewers;
+
+import java.awt.Component;
+import java.util.List;
+import org.sleuthkit.datamodel.AbstractFile;
+
+/**
+ * Defines an interface for application specific content viewer
+ *
+ */
+interface FileTypeViewer {
+
+ /**
+ * Returns list of MIME types supported by this viewer
+ */
+ List getSupportedMIMETypes();
+
+ /**
+ * Display the given file's content in the view panel
+ */
+ void setFile(AbstractFile file);
+
+ /**
+ * Returns panel
+ */
+ Component getComponent();
+
+ /**
+ * Clears the data in the panel
+ */
+ void resetComponent();
+}
diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/FileViewer.form b/Core/src/org/sleuthkit/autopsy/contentviewers/FileViewer.form
new file mode 100644
index 0000000000..d07831cafe
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/contentviewers/FileViewer.form
@@ -0,0 +1,41 @@
+
+
+
diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/FileViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/FileViewer.java
new file mode 100644
index 0000000000..0d17ce2cd6
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/contentviewers/FileViewer.java
@@ -0,0 +1,235 @@
+/*
+ * Autopsy Forensic Browser
+ *
+ * Copyright 2018 Basis Technology Corp.
+ * Contact: carrier sleuthkit org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.sleuthkit.autopsy.contentviewers;
+
+import com.google.common.base.Strings;
+import java.awt.Component;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Level;
+import org.openide.nodes.Node;
+import org.openide.util.NbBundle;
+import org.openide.util.lookup.ServiceProvider;
+import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer;
+import org.sleuthkit.autopsy.coreutils.Logger;
+import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector;
+import org.sleuthkit.datamodel.AbstractFile;
+
+/**
+ * Generic Application content viewer
+ */
+@ServiceProvider(service = DataContentViewer.class, position = 5)
+public class FileViewer extends javax.swing.JPanel implements DataContentViewer {
+
+ private static final int CONFIDENCE_LEVEL = 7;
+ private static final long serialVersionUID = 1L;
+ private static final Logger LOGGER = Logger.getLogger(FileViewer.class.getName());
+
+ private final Map mimeTypeToViewerMap = new HashMap<>();
+
+ // TBD: This hardcoded list of viewers should be replaced with a dynamic lookup
+ private static final FileTypeViewer[] KNOWN_VIEWERS = new FileTypeViewer[]{
+ // new JPEGViewerDummy(), // this if for testing only
+ new SQLiteViewer()
+ };
+
+ private FileTypeViewer lastViewer;
+
+ /**
+ * Creates new form ApplicationContentViewer
+ */
+ public FileViewer() {
+
+ // init the mimetype to viewer map
+ for (FileTypeViewer cv : KNOWN_VIEWERS) {
+ cv.getSupportedMIMETypes().forEach((mimeType) -> {
+ if (mimeTypeToViewerMap.containsKey(mimeType) == false) {
+ mimeTypeToViewerMap.put(mimeType, cv);
+ } else {
+ LOGGER.log(Level.WARNING, "Duplicate viewer for mimtype: {0}", mimeType); //NON-NLS
+ }
+ });
+ }
+
+ initComponents();
+
+ LOGGER.log(Level.INFO, "Created ApplicationContentViewer instance: {0}", this); //NON-NLS
+ }
+
+ /**
+ * Get the FileTypeViewer for a given mimetype
+ *
+ * @param mimeType
+ *
+ * @return FileTypeViewer, null if no known content viewer supports the mimetype
+ */
+ private FileTypeViewer getSupportingViewer(String mimeType) {
+ return mimeTypeToViewerMap.get(mimeType);
+ }
+
+ /**
+ * 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() {
+
+ setLayout(new javax.swing.OverlayLayout(this));
+ }// //GEN-END:initComponents
+
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ // End of variables declaration//GEN-END:variables
+
+ @Override
+ public void setNode(Node selectedNode) {
+
+ resetComponent();
+
+ if (selectedNode == null) {
+ return;
+ }
+
+ AbstractFile file = selectedNode.getLookup().lookup(AbstractFile.class);
+ if (file == null) {
+ return;
+ }
+
+ String mimeType = file.getMIMEType();
+ if (Strings.isNullOrEmpty(mimeType)) {
+ LOGGER.log(Level.INFO, "Mimetype not known for file: {0}", file.getName()); //NON-NLS
+ try {
+ FileTypeDetector fileTypeDetector = new FileTypeDetector();
+ mimeType = fileTypeDetector.detectMIMEType(file);
+ }catch (FileTypeDetector.FileTypeDetectorInitException ex) {
+ LOGGER.log(Level.SEVERE, "Failed to initialize FileTypeDetector.", ex); //NON-NLS
+ return;
+ }
+ }
+
+ if (mimeType.equalsIgnoreCase("application/octet-stream")) {
+ return;
+ }
+ else {
+ FileTypeViewer viewer = getSupportingViewer(mimeType);
+ if (viewer != null) {
+ lastViewer = viewer;
+
+ viewer.setFile(file);
+ this.removeAll();
+ this.add(viewer.getComponent());
+ this.repaint();
+ }
+ }
+
+ }
+
+ @Override
+ @NbBundle.Messages("ApplicationContentViewer.title=Application")
+ public String getTitle() {
+ return Bundle.ApplicationContentViewer_title();
+ }
+
+ @Override
+ @NbBundle.Messages("ApplicationContentViewer.toolTip=Displays file contents.")
+ public String getToolTip() {
+ return Bundle.ApplicationContentViewer_toolTip();
+ }
+
+ @Override
+ public DataContentViewer createInstance() {
+ return new FileViewer();
+ }
+
+ @Override
+ public Component getComponent() {
+ return this;
+ }
+
+ @Override
+ public void resetComponent() {
+
+ if (lastViewer != null) {
+ lastViewer.resetComponent();
+ }
+ this.removeAll();
+ lastViewer = null;
+ }
+
+ @Override
+ public boolean isSupported(Node node) {
+
+ if (node == null) {
+ return false;
+ }
+
+ AbstractFile aFile = node.getLookup().lookup(AbstractFile.class);
+ if (aFile == null) {
+ return false;
+ }
+
+ String mimeType = aFile.getMIMEType();
+ if (Strings.isNullOrEmpty(mimeType)) {
+ LOGGER.log(Level.INFO, "Mimetype not known for file: {0}", aFile.getName()); //NON-NLS
+ try {
+ FileTypeDetector fileTypeDetector = new FileTypeDetector();
+ mimeType = fileTypeDetector.detectMIMEType(aFile);
+ }catch (FileTypeDetector.FileTypeDetectorInitException ex) {
+ LOGGER.log(Level.SEVERE, "Failed to initialize FileTypeDetector.", ex); //NON-NLS
+ return false;
+ }
+ }
+
+ if (mimeType.equalsIgnoreCase("application/octet-stream")) {
+ return false;
+ } else {
+ return (getSupportingViewer(mimeType) != null);
+ }
+
+ }
+
+ @Override
+ public int isPreferred(Node node) {
+ AbstractFile file = node.getLookup().lookup(AbstractFile.class);
+ String mimeType = file.getMIMEType();
+
+ if (Strings.isNullOrEmpty(mimeType)) {
+ LOGGER.log(Level.INFO, "Mimetype not known for file: {0}", file.getName()); //NON-NLS
+ try {
+ FileTypeDetector fileTypeDetector = new FileTypeDetector();
+ mimeType = fileTypeDetector.detectMIMEType(file);
+ }catch (FileTypeDetector.FileTypeDetectorInitException ex) {
+ LOGGER.log(Level.SEVERE, "Failed to initialize FileTypeDetector.", ex); //NON-NLS
+ return 0;
+ }
+ }
+
+ if (mimeType.equalsIgnoreCase("application/octet-stream")) {
+ return 0;
+ } else {
+ if (null != getSupportingViewer(mimeType)) {
+ return CONFIDENCE_LEVEL;
+ }
+ }
+
+ return 0;
+ }
+}
diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/JPEGViewerDummy.form b/Core/src/org/sleuthkit/autopsy/contentviewers/JPEGViewerDummy.form
new file mode 100644
index 0000000000..587dd3c9a0
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/contentviewers/JPEGViewerDummy.form
@@ -0,0 +1,58 @@
+
+
+
diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/JPEGViewerDummy.java b/Core/src/org/sleuthkit/autopsy/contentviewers/JPEGViewerDummy.java
new file mode 100644
index 0000000000..8aea7540e1
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/contentviewers/JPEGViewerDummy.java
@@ -0,0 +1,89 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.sleuthkit.autopsy.contentviewers;
+
+import java.awt.Component;
+import java.util.Arrays;
+import java.util.List;
+import org.sleuthkit.datamodel.AbstractFile;
+
+public class JPEGViewerDummy extends javax.swing.JPanel implements FileTypeViewer {
+
+ public static final String[] SUPPORTED_MIMETYPES = new String[]{"image/jpeg"};
+
+ /**
+ * Creates new form JPEGViewer
+ */
+ public JPEGViewerDummy() {
+ initComponents();
+ }
+
+ /**
+ * This method is called from within the constructor to initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is always
+ * regenerated by the Form Editor.
+ */
+ @SuppressWarnings("unchecked")
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ jLabel1 = new javax.swing.JLabel();
+ jTextField1 = new javax.swing.JTextField();
+
+ org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(JPEGViewerDummy.class, "JPEGViewerDummy.jLabel1.text")); // NOI18N
+
+ jTextField1.setEditable(false);
+ jTextField1.setText(org.openide.util.NbBundle.getMessage(JPEGViewerDummy.class, "JPEGViewerDummy.jTextField1.text")); // NOI18N
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+ this.setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addGap(43, 43, 43)
+ .addComponent(jLabel1)
+ .addGap(35, 35, 35)
+ .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addContainerGap(120, Short.MAX_VALUE))
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(jLabel1)
+ .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addContainerGap(269, Short.MAX_VALUE))
+ );
+ }// //GEN-END:initComponents
+
+ @Override
+ public List getSupportedMIMETypes() {
+ return Arrays.asList(SUPPORTED_MIMETYPES);
+ }
+
+ @Override
+ public Component getComponent() {
+ return this;
+ }
+
+ @Override
+ public void resetComponent() {
+ this.jTextField1.setText("");
+ }
+
+ @Override
+ public void setFile(AbstractFile file) {
+ this.jTextField1.setText(file.getName());
+ }
+
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JLabel jLabel1;
+ private javax.swing.JTextField jTextField1;
+ // End of variables declaration//GEN-END:variables
+
+}
diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.form b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.form
new file mode 100644
index 0000000000..3cdee8658c
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.form
@@ -0,0 +1,153 @@
+
+
+
diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java
new file mode 100644
index 0000000000..fff2f5d781
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java
@@ -0,0 +1,395 @@
+/*
+ * Autopsy Forensic Browser
+ *
+ * Copyright 2018 Basis Technology Corp.
+ * Contact: carrier sleuthkit org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.sleuthkit.autopsy.contentviewers;
+
+import java.awt.Component;
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.logging.Level;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import java.sql.SQLException;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.concurrent.ExecutionException;
+import javax.swing.JComboBox;
+import javax.swing.SwingWorker;
+import org.sleuthkit.autopsy.casemodule.Case;
+import org.sleuthkit.autopsy.coreutils.Logger;
+import org.sleuthkit.autopsy.datamodel.ContentUtils;
+import org.sleuthkit.datamodel.AbstractFile;
+
+public class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer {
+
+ public static final String[] SUPPORTED_MIMETYPES = new String[]{"application/x-sqlite3"};
+ private static final Logger LOGGER = Logger.getLogger(FileViewer.class.getName());
+ private Connection connection = null;
+
+ private String tmpDBPathName = null;
+ private File tmpDBFile = null;
+
+ // TBD: Change the value to be a Array of ColDefs
+ Map dbTablesMap = new TreeMap<>();
+
+ /**
+ * Creates new form SQLiteViewer
+ */
+ public SQLiteViewer() {
+ initComponents();
+
+ customizeComponents();
+ }
+
+ /**
+ * 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() {
+
+ jHdrPanel = new javax.swing.JPanel();
+ tablesDropdownList = new javax.swing.JComboBox<>();
+ jLabel1 = new javax.swing.JLabel();
+ numEntriesField = new javax.swing.JTextField();
+ jTableDataPanel = new javax.swing.JPanel();
+ jScrollPane1 = new javax.swing.JScrollPane();
+ jTable1 = new javax.swing.JTable();
+
+ tablesDropdownList.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
+ tablesDropdownList.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ tablesDropdownListActionPerformed(evt);
+ }
+ });
+
+ org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(SQLiteViewer.class, "SQLiteViewer.jLabel1.text")); // NOI18N
+
+ numEntriesField.setEditable(false);
+ numEntriesField.setText(org.openide.util.NbBundle.getMessage(SQLiteViewer.class, "SQLiteViewer.numEntriesField.text")); // NOI18N
+ numEntriesField.setBorder(null);
+ numEntriesField.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ numEntriesFieldActionPerformed(evt);
+ }
+ });
+
+ javax.swing.GroupLayout jHdrPanelLayout = new javax.swing.GroupLayout(jHdrPanel);
+ jHdrPanel.setLayout(jHdrPanelLayout);
+ jHdrPanelLayout.setHorizontalGroup(
+ jHdrPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jHdrPanelLayout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(jLabel1)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(tablesDropdownList, javax.swing.GroupLayout.PREFERRED_SIZE, 130, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGap(23, 23, 23)
+ .addComponent(numEntriesField, javax.swing.GroupLayout.PREFERRED_SIZE, 71, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addContainerGap(130, Short.MAX_VALUE))
+ );
+ jHdrPanelLayout.setVerticalGroup(
+ jHdrPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jHdrPanelLayout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(jHdrPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(tablesDropdownList, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(jLabel1)
+ .addComponent(numEntriesField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addContainerGap(16, Short.MAX_VALUE))
+ );
+
+ jTable1.setModel(new javax.swing.table.DefaultTableModel(
+ new Object [][] {
+ {null, null, null, null},
+ {null, null, null, null},
+ {null, null, null, null},
+ {null, null, null, null}
+ },
+ new String [] {
+ "Title 1", "Title 2", "Title 3", "Title 4"
+ }
+ ));
+ jScrollPane1.setViewportView(jTable1);
+
+ javax.swing.GroupLayout jTableDataPanelLayout = new javax.swing.GroupLayout(jTableDataPanel);
+ jTableDataPanel.setLayout(jTableDataPanelLayout);
+ jTableDataPanelLayout.setHorizontalGroup(
+ jTableDataPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jTableDataPanelLayout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
+ .addGap(15, 15, 15))
+ );
+ jTableDataPanelLayout.setVerticalGroup(
+ jTableDataPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jTableDataPanelLayout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 275, Short.MAX_VALUE)
+ .addContainerGap())
+ );
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+ this.setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jHdrPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(jTableDataPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(jHdrPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(jTableDataPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ );
+ }// //GEN-END:initComponents
+
+ private void numEntriesFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_numEntriesFieldActionPerformed
+ // TODO add your handling code here:
+ }//GEN-LAST:event_numEntriesFieldActionPerformed
+
+ private void tablesDropdownListActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_tablesDropdownListActionPerformed
+ JComboBox cb = (JComboBox) evt.getSource();
+ String tableName = (String) cb.getSelectedItem();
+ if (null == tableName) {
+ return;
+ }
+
+ readTable(tableName);
+ }//GEN-LAST:event_tablesDropdownListActionPerformed
+
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JPanel jHdrPanel;
+ private javax.swing.JLabel jLabel1;
+ private javax.swing.JScrollPane jScrollPane1;
+ private javax.swing.JTable jTable1;
+ private javax.swing.JPanel jTableDataPanel;
+ private javax.swing.JTextField numEntriesField;
+ private javax.swing.JComboBox tablesDropdownList;
+ // End of variables declaration//GEN-END:variables
+
+ @Override
+ public List getSupportedMIMETypes() {
+ return Arrays.asList(SUPPORTED_MIMETYPES);
+ }
+
+ @Override
+ public void setFile(AbstractFile file) {
+ processSQLiteFile(file);
+ }
+
+ @Override
+ public Component getComponent() {
+ return this;
+ }
+
+ @Override
+ public void resetComponent() {
+
+ dbTablesMap.clear();
+
+ tablesDropdownList.setEnabled(true);
+ tablesDropdownList.removeAllItems();
+ numEntriesField.setText("");
+
+ // close DB connection to file
+ if (null != connection) {
+ try {
+ connection.close();
+ connection = null;
+ } catch (SQLException ex) {
+ LOGGER.log(Level.SEVERE, "Failed to close DB connection to file.", ex); //NON-NLS
+ }
+ }
+
+ // delete last temp file
+ if (null != tmpDBFile) {
+ tmpDBFile.delete();
+ tmpDBFile = null;
+ }
+ }
+
+ private void customizeComponents() {
+
+ // add a actionListener to jTablesComboBox
+ }
+
+ /**
+ * Process the given SQLite DB file
+ *
+ * @param sqliteFile -
+ *
+ * @return none
+ */
+ private void processSQLiteFile(AbstractFile sqliteFile) {
+
+ tablesDropdownList.removeAllItems();
+
+ new SwingWorker() {
+ @Override
+ protected Boolean doInBackground() throws Exception {
+
+ try {
+ // Copy the file to temp folder
+ tmpDBPathName = Case.getCurrentCase().getTempDirectory() + File.separator + sqliteFile.getName() + "-" + sqliteFile.getId();
+ tmpDBFile = new File(tmpDBPathName);
+ ContentUtils.writeToFile(sqliteFile, tmpDBFile);
+
+ // Open copy using JDBC
+ Class.forName("org.sqlite.JDBC"); //NON-NLS //load JDBC driver
+ connection = DriverManager.getConnection("jdbc:sqlite:" + tmpDBPathName); //NON-NLS
+
+ // Read all table names and schema
+ return getTables();
+ } catch (IOException ex) {
+ LOGGER.log(Level.SEVERE, "Failed to copy DB file.", ex); //NON-NLS
+ } catch (SQLException ex) {
+ LOGGER.log(Level.SEVERE, "Failed to Open DB.", ex); //NON-NLS
+ } catch (ClassNotFoundException ex) {
+ LOGGER.log(Level.SEVERE, "Failed to initialize JDBC Sqlite.", ex); //NON-NLS
+ }
+ return false;
+ }
+
+ @Override
+ protected void done() {
+ super.done();
+ try {
+ boolean status = get();
+ if ((status == true) && (dbTablesMap.size() > 0)) {
+ dbTablesMap.keySet().forEach((tableName) -> {
+ tablesDropdownList.addItem(tableName);
+ });
+ } else {
+ // Populate error message
+ tablesDropdownList.addItem("No tables found");
+ tablesDropdownList.setEnabled(false);
+ }
+ } catch (InterruptedException | ExecutionException ex) {
+ LOGGER.log(Level.SEVERE, "Unexpected exception while opening DB file", ex); //NON-NLS
+ }
+ }
+ }.execute();
+
+ }
+
+ /**
+ * Gets the table names and their schema from loaded SQLite db file
+ *
+ * @return true if success, false otherwise
+ */
+ private boolean getTables() {
+
+ try {
+ Statement statement = connection.createStatement();
+
+ ResultSet resultSet = statement.executeQuery(
+ "SELECT name, sql FROM sqlite_master "
+ + " WHERE type= 'table' "
+ + " ORDER BY name;"); //NON-NLS
+
+ while (resultSet.next()) {
+ String tableName = resultSet.getString("name"); //NON-NLS
+ String tableSQL = resultSet.getString("sql"); //NON-NLS
+
+ dbTablesMap.put(tableName, tableSQL);
+ String query = "PRAGMA table_info(" + tableName + ")"; //NON-NLS
+ ResultSet rs2;
+ try {
+ Statement statement2 = connection.createStatement();
+ rs2 = statement2.executeQuery(query);
+ while (rs2.next()) {
+
+ // System.out.println("RAMAN: Col Name = " + rs2.getString("name"));
+ // System.out.println("RAMAN: Col Type = " + rs2.getString("type"));
+
+ // RAMAN TBD: parse and save the table schema
+ }
+ } catch (Exception ex) {
+ LOGGER.log(Level.WARNING, "Error while trying to get columns from sqlite db." + connection, ex); //NON-NLS
+ }
+ }
+ } catch (Exception e) {
+ LOGGER.log(Level.SEVERE, "Error getting table names from the DB", e); //NON-NLS
+ }
+ return true;
+ }
+
+ private void readTable(String tableName) {
+ // TBD: need to handle cancelling if one is already in progress
+
+ new SwingWorker() {
+ @Override
+ protected Integer doInBackground() throws Exception {
+
+ try {
+ Statement statement = connection.createStatement();
+ ResultSet resultSet = statement.executeQuery(
+ "SELECT COUNT(*) as count FROM " + tableName); //NON-NLS
+
+ // TBD: read the rows here and popluate the ExplorerManager.
+
+ return resultSet.getInt("count");
+ } catch (SQLException ex) {
+ LOGGER.log(Level.SEVERE, "Failed to get data for table.", ex); //NON-NLS
+ }
+ //NON-NLS
+ return 0;
+ }
+
+ @Override
+ protected void done() {
+ super.done();
+ try {
+ int numRows = get();
+ numEntriesField.setText(numRows + " entries");
+ } catch (InterruptedException | ExecutionException ex) {
+ LOGGER.log(Level.SEVERE, "Unexpected exception while reading table.", ex); //NON-NLS
+ }
+ }
+ }.execute();
+
+ }
+
+ enum SQLStorageClass {
+ NULL,
+ INTEGER,
+ REAL,
+ TEXT,
+ BLOB
+ };
+
+ private class SQLColDef {
+
+ private final String colName;
+ private final SQLStorageClass storageClass;
+
+ SQLColDef(String colName, SQLStorageClass sc) {
+ this.colName = colName;
+ this.storageClass = sc;
+ }
+
+ }
+}
diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java
index e6e8afed52..2713992139 100644
--- a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java
+++ b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java
@@ -41,7 +41,7 @@ public interface DisplayableItemNodeVisitor {
T visit(LocalFileNode dfn);
T visit(VirtualDirectoryNode ldn);
-
+
T visit(LocalDirectoryNode ldn);
T visit(DirectoryNode dn);
diff --git a/Core/src/org/sleuthkit/autopsy/datasourceprocessors/AddRawImageTask.java b/Core/src/org/sleuthkit/autopsy/datasourceprocessors/AddRawImageTask.java
index 14a3dc9e2f..3d576eebf0 100644
--- a/Core/src/org/sleuthkit/autopsy/datasourceprocessors/AddRawImageTask.java
+++ b/Core/src/org/sleuthkit/autopsy/datasourceprocessors/AddRawImageTask.java
@@ -178,7 +178,7 @@ final class AddRawImageTask implements Runnable {
logger.log(Level.SEVERE, errorMessage, ex);
criticalErrorOccurred = true;
} finally {
- caseDatabase.releaseSingleUserCaseReadLock();
+ caseDatabase.releaseSingleUserCaseWriteLock();
}
}
diff --git a/Core/src/org/sleuthkit/autopsy/livetriage/Bundle.properties b/Core/src/org/sleuthkit/autopsy/livetriage/Bundle.properties
new file mode 100644
index 0000000000..61f522a6b4
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/livetriage/Bundle.properties
@@ -0,0 +1,7 @@
+SelectDriveDialog.bnOk.text=Ok
+SelectDriveDialog.bnRefresh.text=Refresh
+SelectDriveDialog.lbSelectDrive.text=Select the drive to copy the application and script to:
+SelectDriveDialog.jLabel1.text=Select drive to use for live triage (may take time to load):
+SelectDriveDialog.errorLabel.text=jLabel2
+SelectDriveDialog.bnCancel.text=Cancel
+SelectDriveDialog.jTextArea1.text=This feature copies the application and a batch file to a removable drive,\nallowing systems to be analyzed without installing the software or\nimaging the drives.\n\nTo analyze a system, insert the drive and run "RunFromUSB.bat" as\nadministrator, then select the "Local Disk" option on the Add Data Source\npanel.
diff --git a/Core/src/org/sleuthkit/autopsy/livetriage/CreateLiveTriageDriveAction.java b/Core/src/org/sleuthkit/autopsy/livetriage/CreateLiveTriageDriveAction.java
new file mode 100644
index 0000000000..846632a092
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/livetriage/CreateLiveTriageDriveAction.java
@@ -0,0 +1,284 @@
+/*
+ * Autopsy Forensic Browser
+ *
+ * Copyright 2018 Basis Technology Corp.
+ * Contact: carrier sleuthkit org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.sleuthkit.autopsy.livetriage;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.InvalidPathException;
+import java.util.logging.Level;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeEvent;
+import javax.swing.JOptionPane;
+import java.awt.Frame;
+import javax.swing.SwingWorker;
+import org.apache.commons.io.FileUtils;
+import org.openide.awt.ActionID;
+import org.openide.awt.ActionReference;
+import org.openide.awt.ActionRegistration;
+import org.openide.util.HelpCtx;
+import org.openide.util.NbBundle;
+import org.openide.util.actions.CallableSystemAction;
+import org.openide.windows.WindowManager;
+import org.sleuthkit.autopsy.core.UserPreferences;
+import org.sleuthkit.autopsy.coreutils.Logger;
+import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
+import org.sleuthkit.autopsy.coreutils.PlatformUtil;
+import org.sleuthkit.autopsy.progress.ModalDialogProgressIndicator;
+
+@ActionID(category = "Tools", id = "org.sleuthkit.autopsy.livetriage.CreateLiveTriageDriveAction")
+@ActionReference(path = "Menu/Tools", position = 1401)
+@ActionRegistration(displayName = "#CTL_CreateLiveTriageDriveAction", lazy = false)
+@NbBundle.Messages({"CTL_CreateLiveTriageDriveAction=Make Live Triage Drive"})
+public final class CreateLiveTriageDriveAction extends CallableSystemAction implements PropertyChangeListener {
+
+ private static final String DISPLAY_NAME = Bundle.CTL_CreateLiveTriageDriveAction();
+ private ModalDialogProgressIndicator progressIndicator = null;
+ private String drivePath = "";
+ private CopyFilesWorker worker;
+
+ @Override
+ public boolean isEnabled() {
+ return true;
+ }
+
+ @NbBundle.Messages({"CreateLiveTriageDriveAction.error.title=Error creating live triage disk",
+ "CreateLiveTriageDriveAction.exenotfound.message=Executable could not be found",
+ "CreateLiveTriageDriveAction.batchFileError.message=Error creating batch file",
+ "CreateLiveTriageDriveAction.appPathError.message=Could not location application directory",
+ "CreateLiveTriageDriveAction.copyError.message=Could not copy application. Only works on installed version.",
+ "CreateLiveTriageDriveAction.success.title=Success",
+ "CreateLiveTriageDriveAction.success.message=Live triage drive created. Use RunFromUSB.bat to run the application"
+ })
+ @Override
+ @SuppressWarnings("fallthrough")
+ public void performAction() {
+
+ Frame mainWindow = WindowManager.getDefault().getMainWindow();
+
+ // If this is an installed version, there should be an 64.exe file in the bin folder
+ String appName = UserPreferences.getAppName();
+ String exeName = appName + "64.exe";
+ String installPath = PlatformUtil.getInstallPath();
+
+ Path exePath = Paths.get(installPath, "bin", exeName);
+
+ if (!exePath.toFile().exists()) {
+ JOptionPane.showMessageDialog(mainWindow,
+ Bundle.CreateLiveTriageDriveAction_exenotfound_message(),
+ Bundle.CreateLiveTriageDriveAction_error_title(),
+ JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+
+ Path applicationBasePath;
+ try {
+ applicationBasePath = exePath.getParent().getParent();
+ } catch (InvalidPathException ex) {
+ JOptionPane.showMessageDialog(mainWindow,
+ Bundle.CreateLiveTriageDriveAction_appPathError_message(),
+ Bundle.CreateLiveTriageDriveAction_error_title(),
+ JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+
+ SelectDriveDialog driveDialog = new SelectDriveDialog(mainWindow, true);
+ driveDialog.display();
+
+ if (!driveDialog.getSelectedDrive().isEmpty()) {
+ drivePath = driveDialog.getSelectedDrive();
+ if (drivePath.startsWith("\\\\.\\")) {
+ drivePath = drivePath.substring(4);
+ }
+
+ worker = new CopyFilesWorker(applicationBasePath, drivePath, appName);
+ worker.addPropertyChangeListener(this);
+ worker.execute();
+ }
+ }
+
+ @NbBundle.Messages({"# {0} - drivePath",
+ "CreateLiveTriageDriveAction.progressBar.text=Copying live triage files to {0}",
+ "CreateLiveTriageDriveAction.progressBar.title=Please wait"})
+ @Override
+ public void propertyChange(PropertyChangeEvent evt) {
+
+ if ("state".equals(evt.getPropertyName())
+ && (SwingWorker.StateValue.STARTED.equals(evt.getNewValue()))) {
+
+ // Setup progress bar.
+ String displayStr = NbBundle.getMessage(this.getClass(), "CreateLiveTriageDriveAction.progressBar.text",
+ drivePath);
+
+ progressIndicator = new ModalDialogProgressIndicator(WindowManager.getDefault().getMainWindow(),
+ NbBundle.getMessage(this.getClass(), "CreateLiveTriageDriveAction.progressBar.title"));
+ progressIndicator.start(displayStr);
+
+ } else if ("state".equals(evt.getPropertyName())
+ && (SwingWorker.StateValue.DONE.equals(evt.getNewValue()))) {
+ if (progressIndicator != null) {
+ progressIndicator.finish();
+ }
+
+ if (worker.hadError()) {
+ MessageNotifyUtil.Message.error(NbBundle.getMessage(CopyFilesWorker.class, "CopyFilesWorker.error.text"));
+ } else {
+ MessageNotifyUtil.Message.info(NbBundle.getMessage(CopyFilesWorker.class, "CopyFilesWorker.done.text"));
+ }
+ }
+ }
+
+ private class CopyFilesWorker extends SwingWorker {
+
+ private final Path sourceFolder;
+ private final String drivePath;
+ private final String appName;
+ private boolean error = false;
+
+ CopyFilesWorker(Path sourceFolder, String drivePath, String appName) {
+ this.sourceFolder = sourceFolder;
+ this.drivePath = drivePath;
+ this.appName = appName;
+ }
+
+ boolean hadError() {
+ return error;
+ }
+
+ @Override
+ protected Void doInBackground() throws Exception {
+
+ copyBatchFile(drivePath, appName);
+ copyApplication(sourceFolder, drivePath, appName);
+
+ return null;
+ }
+
+ @NbBundle.Messages({"CopyFilesWorker.error.text=Error copying live triage files",
+ "CopyFilesWorker.done.text=Finished creating live triage disk"})
+ @Override
+ protected void done() {
+ try {
+ super.get();
+ } catch (Exception ex) {
+ error = true;
+ Logger.getLogger(CreateLiveTriageDriveAction.class.getName()).log(Level.SEVERE, "Fatal error during live triage drive creation", ex); //NON-NLS
+ }
+ }
+ }
+
+ private void copyApplication(Path sourceFolder, String destBaseFolder, String appName) throws IOException {
+
+ // Create an appName folder in the destination
+ Path destAppFolder = Paths.get(destBaseFolder, appName);
+ if (!destAppFolder.toFile().exists()) {
+ if (!destAppFolder.toFile().mkdirs()) {
+ throw new IOException("Failed to create directory " + destAppFolder.toString());
+ }
+ }
+
+ // Now copy the files
+ FileUtils.copyDirectory(sourceFolder.toFile(), destAppFolder.toFile());
+ }
+
+ private void copyBatchFile(String destPath, String appName) throws IOException, InvalidPathException {
+ Path batchFilePath = Paths.get(destPath, "RunFromUSB.bat");
+ FileUtils.writeStringToFile(batchFilePath.toFile(), getBatchFileContents(appName), "UTF-8");
+
+ }
+
+ private String getBatchFileContents(String appName) {
+
+ String batchFile
+ = "@echo off\n"
+ + "\n"
+ + "REM This restores the working directory when using 'Run as administrator'"
+ + "@setlocal enableextensions\n"
+ + "@cd /d \"%~dp0\""
+ + "\n"
+ + "SET appName=\"" + appName + "\"\n"
+ + "\n"
+ + "REM Create the configData directory. Exit if it does not exist after attempting to create it\n"
+ + "if not exist configData mkdir configData\n"
+ + "if not exist configData (\n"
+ + " echo Error creating directory configData\n"
+ + " goto end\n"
+ + ")\n"
+ + "\n"
+ + "REM Create the userdir sub directory. Exit if it does not exist after attempting to create it\n"
+ + "if not exist configData\\userdir mkdir configData\\userdir\n"
+ + "if not exist configData\\userdir (\n"
+ + " echo Error creating directory configData\\userdir\n"
+ + " goto end\n"
+ + ")\n"
+ + "\n"
+ + "REM Create the cachedir sub directory. Exit if it does not exist after attempting to create it\n"
+ + "REM If it exists to start with, delete it to clear out old data\n"
+ + "if exist configData\\cachedir rd /s /q configData\\cachedir\n"
+ + "mkdir configData\\cachedir\n"
+ + "if not exist configData\\cachedir (\n"
+ + " echo Error creating directory configData\\cachedir\n"
+ + " goto end\n"
+ + ")\n"
+ + "\n"
+ + "REM Create the temp sub directory. Exit if it does not exist after attempting to create it\n"
+ + "REM If it exists to start with, delete it to clear out old data\n"
+ + "if exist configData\\temp rd /s /q configData\\temp\n"
+ + "mkdir configData\\temp\n"
+ + "if not exist configData\\temp (\n"
+ + " echo Error creating directory configData\\temp\n"
+ + " goto end\n"
+ + ")\n"
+ + "\n"
+ + "REM Create the cases directory. It's ok if this fails.\n"
+ + "if not exist cases mkdir cases\n"
+ + "\n"
+ + "if exist %appName% (\n"
+ + " if not exist %appName%\\bin\\%appName%64.exe (\n"
+ + " echo %appName%\\bin\\%appName%64.exe does not exist\n"
+ + " goto end\n"
+ + " )\n"
+ + " %appName%\\bin\\%appName%64.exe --userdir ..\\configData\\userdir --cachedir ..\\configData\\cachedir -J-Djava.io.tmpdir=..\\configData\\temp\n"
+ + ") else (\n"
+ + " echo Could not find %appName% directory\n"
+ + " goto end\n"
+ + ")\n"
+ + "\n"
+ + ":end\n"
+ + "\n"
+ + "REM Keep the cmd window open in case there was an error\n"
+ + "@pause\n";
+ return batchFile;
+ }
+
+ @Override
+ public String getName() {
+ return DISPLAY_NAME;
+ }
+
+ @Override
+ public HelpCtx getHelpCtx() {
+ return HelpCtx.DEFAULT_HELP;
+ }
+
+ @Override
+ public boolean asynchronous() {
+ return false; // run on edt
+ }
+}
diff --git a/Core/src/org/sleuthkit/autopsy/livetriage/SelectDriveDialog.form b/Core/src/org/sleuthkit/autopsy/livetriage/SelectDriveDialog.form
new file mode 100644
index 0000000000..ee776348dc
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/livetriage/SelectDriveDialog.form
@@ -0,0 +1,163 @@
+
+
+
diff --git a/Core/src/org/sleuthkit/autopsy/livetriage/SelectDriveDialog.java b/Core/src/org/sleuthkit/autopsy/livetriage/SelectDriveDialog.java
new file mode 100644
index 0000000000..c13d82d324
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/livetriage/SelectDriveDialog.java
@@ -0,0 +1,388 @@
+/*
+ * 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.livetriage;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CancellationException;
+import java.util.logging.Level;
+import java.awt.Dimension;
+import java.awt.Point;
+import javax.swing.SwingWorker;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.event.TableModelListener;
+import javax.swing.table.TableModel;
+import org.openide.util.NbBundle;
+import org.sleuthkit.autopsy.coreutils.LocalDisk;
+import org.sleuthkit.autopsy.coreutils.Logger;
+import org.sleuthkit.autopsy.coreutils.PlatformUtil;
+
+/**
+ *
+ */
+class SelectDriveDialog extends javax.swing.JDialog {
+
+ private List disks = new ArrayList<>();
+ private final LocalDiskModel model = new LocalDiskModel();
+ private final java.awt.Frame parent;
+ private String drivePath = "";
+
+ /**
+ * Creates new form SelectDriveDialog
+ */
+ @NbBundle.Messages({"SelectDriveDialog.title=Create Live Triage Drive"})
+ SelectDriveDialog(java.awt.Frame parent, boolean modal) {
+ super(parent, modal);
+ initComponents();
+ this.parent = parent;
+
+ model.loadDisks();
+ bnOk.setEnabled(false);
+ diskTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
+ @Override
+ public void valueChanged(ListSelectionEvent e) {
+ if (diskTable.getSelectedRow() >= 0 && diskTable.getSelectedRow() < disks.size()) {
+ bnOk.setEnabled(true);
+ } else { //The selection changed to nothing valid being selected, such as with ctrl+click
+ bnOk.setEnabled(false);
+ }
+ }
+ });
+ }
+
+ void display() {
+ this.setTitle(Bundle.SelectDriveDialog_title());
+
+ final Dimension parentSize = parent.getSize();
+ final Point parentLocationOnScreen = parent.getLocationOnScreen();
+ final Dimension childSize = this.getSize();
+ int x;
+ int y;
+ x = (parentSize.width - childSize.width) / 2;
+ y = (parentSize.height - childSize.height) / 2;
+ x += parentLocationOnScreen.x;
+ y += parentLocationOnScreen.y;
+
+ setLocation(x, y);
+ setVisible(true);
+ }
+
+ String getSelectedDrive() {
+ return this.drivePath;
+ }
+
+ /**
+ * This method is called from within the constructor to initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is always
+ * regenerated by the Form Editor.
+ */
+ @SuppressWarnings("unchecked")
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ jScrollPane1 = new javax.swing.JScrollPane();
+ diskTable = new javax.swing.JTable();
+ jLabel1 = new javax.swing.JLabel();
+ bnRefresh = new javax.swing.JButton();
+ bnOk = new javax.swing.JButton();
+ errorLabel = new javax.swing.JLabel();
+ jSeparator1 = new javax.swing.JSeparator();
+ bnCancel = new javax.swing.JButton();
+ jScrollPane2 = new javax.swing.JScrollPane();
+ jTextArea1 = new javax.swing.JTextArea();
+
+ setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
+
+ diskTable.setModel(model);
+ jScrollPane1.setViewportView(diskTable);
+
+ org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(SelectDriveDialog.class, "SelectDriveDialog.jLabel1.text")); // NOI18N
+
+ org.openide.awt.Mnemonics.setLocalizedText(bnRefresh, org.openide.util.NbBundle.getMessage(SelectDriveDialog.class, "SelectDriveDialog.bnRefresh.text")); // NOI18N
+ bnRefresh.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ bnRefreshActionPerformed(evt);
+ }
+ });
+
+ org.openide.awt.Mnemonics.setLocalizedText(bnOk, org.openide.util.NbBundle.getMessage(SelectDriveDialog.class, "SelectDriveDialog.bnOk.text")); // NOI18N
+ bnOk.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ bnOkActionPerformed(evt);
+ }
+ });
+
+ org.openide.awt.Mnemonics.setLocalizedText(errorLabel, org.openide.util.NbBundle.getMessage(SelectDriveDialog.class, "SelectDriveDialog.errorLabel.text")); // NOI18N
+
+ org.openide.awt.Mnemonics.setLocalizedText(bnCancel, org.openide.util.NbBundle.getMessage(SelectDriveDialog.class, "SelectDriveDialog.bnCancel.text")); // NOI18N
+ bnCancel.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ bnCancelActionPerformed(evt);
+ }
+ });
+
+ jScrollPane2.setBorder(null);
+
+ jTextArea1.setBackground(new java.awt.Color(240, 240, 240));
+ jTextArea1.setColumns(20);
+ jTextArea1.setFont(new java.awt.Font("Tahoma", 0, 11)); // NOI18N
+ jTextArea1.setRows(5);
+ jTextArea1.setText(org.openide.util.NbBundle.getMessage(SelectDriveDialog.class, "SelectDriveDialog.jTextArea1.text")); // NOI18N
+ jTextArea1.setBorder(null);
+ jScrollPane2.setViewportView(jTextArea1);
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
+ getContentPane().setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(bnRefresh, javax.swing.GroupLayout.DEFAULT_SIZE, 112, Short.MAX_VALUE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 48, Short.MAX_VALUE)
+ .addComponent(bnOk, javax.swing.GroupLayout.PREFERRED_SIZE, 101, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(bnCancel, javax.swing.GroupLayout.PREFERRED_SIZE, 101, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
+ .addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(jSeparator1)
+ .addComponent(errorLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(jScrollPane2))
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 107, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(jLabel1)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 112, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(bnRefresh)
+ .addComponent(bnCancel)
+ .addComponent(bnOk))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(errorLabel)
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ );
+
+ pack();
+ }// //GEN-END:initComponents
+
+ private void bnRefreshActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnRefreshActionPerformed
+ model.loadDisks();
+ }//GEN-LAST:event_bnRefreshActionPerformed
+
+ private void bnOkActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnOkActionPerformed
+ if (diskTable.getSelectedRow() >= 0 && diskTable.getSelectedRow() < disks.size()) {
+ LocalDisk selectedDisk = disks.get(diskTable.getSelectedRow());
+ drivePath = selectedDisk.getPath();
+ } else {
+ drivePath = "";
+ }
+ dispose();
+ }//GEN-LAST:event_bnOkActionPerformed
+
+ private void bnCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnCancelActionPerformed
+ dispose();
+ }//GEN-LAST:event_bnCancelActionPerformed
+
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JButton bnCancel;
+ private javax.swing.JButton bnOk;
+ private javax.swing.JButton bnRefresh;
+ private javax.swing.JTable diskTable;
+ private javax.swing.JLabel errorLabel;
+ private javax.swing.JLabel jLabel1;
+ private javax.swing.JScrollPane jScrollPane1;
+ private javax.swing.JScrollPane jScrollPane2;
+ private javax.swing.JSeparator jSeparator1;
+ private javax.swing.JTextArea jTextArea1;
+ // End of variables declaration//GEN-END:variables
+
+ /**
+ * Table model for displaying information from LocalDisk Objects in a table.
+ */
+ @NbBundle.Messages({"SelectDriveDialog.localDiskModel.loading.msg=",
+ "SelectDriveDialog.localDiskModel.nodrives.msg=Executable could not be found",
+ "SelectDriveDialog.diskTable.column1.title=Disk Name",
+ "SelectDriveDialog.diskTable.column2.title=Disk Size",
+ "SelectDriveDialog.errLabel.disksNotDetected.text=Disks were not detected. On some systems it requires admin privileges",
+ "SelectDriveDialog.errLabel.disksNotDetected.toolTipText=Disks were not detected."
+
+ })
+ private class LocalDiskModel implements TableModel {
+
+ private LocalDiskThread worker = null;
+ private boolean ready = false;
+ private volatile boolean loadingDisks = false;
+
+ //private String SELECT = "Select a local disk:";
+ private final String LOADING = NbBundle.getMessage(this.getClass(), "SelectDriveDialog.localDiskModel.loading.msg");
+ private final String NO_DRIVES = NbBundle.getMessage(this.getClass(), "SelectDriveDialog.localDiskModel.nodrives.msg");
+
+ private void loadDisks() {
+
+ // if there is a worker already building the lists, then cancel it first.
+ if (loadingDisks && worker != null) {
+ worker.cancel(false);
+ }
+
+ // Clear the lists
+ errorLabel.setText("");
+ diskTable.setEnabled(false);
+ ready = false;
+ loadingDisks = true;
+ worker = new LocalDiskThread();
+ worker.execute();
+ }
+
+ @Override
+ public int getRowCount() {
+ if (disks.isEmpty()) {
+ return 0;
+ }
+ return disks.size();
+ }
+
+ @Override
+ public int getColumnCount() {
+ return 2;
+
+ }
+
+ @Override
+ public String getColumnName(int columnIndex) {
+ switch (columnIndex) {
+ case 0:
+ return NbBundle.getMessage(this.getClass(), "SelectDriveDialog.diskTable.column1.title");
+ case 1:
+ return NbBundle.getMessage(this.getClass(), "SelectDriveDialog.diskTable.column2.title");
+ default:
+ return "Unnamed"; //NON-NLS
+ }
+ }
+
+ @Override
+ public Class> getColumnClass(int columnIndex) {
+ return String.class;
+ }
+
+ @Override
+ public boolean isCellEditable(int rowIndex, int columnIndex) {
+ return false;
+ }
+
+ @Override
+ public Object getValueAt(int rowIndex, int columnIndex) {
+ if (ready) {
+ if (disks.isEmpty()) {
+ return NO_DRIVES;
+ }
+ switch (columnIndex) {
+ case 0:
+ return disks.get(rowIndex).getName();
+ case 1:
+ return disks.get(rowIndex).getReadableSize();
+ default:
+ return disks.get(rowIndex).getPath();
+ }
+ } else {
+ return LOADING;
+ }
+ }
+
+ @Override
+ public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
+ //setter does nothing they should not be able to modify table
+ }
+
+ @Override
+ public void addTableModelListener(TableModelListener l) {
+
+ }
+
+ @Override
+ public void removeTableModelListener(TableModelListener l) {
+
+ }
+
+ /**
+ * Gets the lists of physical drives and partitions and combines them
+ * into a list of disks.
+ */
+ class LocalDiskThread extends SwingWorker
ext/commons-logging-1.1.2-sources.jar
@@ -763,10 +781,6 @@
ext/joda-time-2.4-javadoc.jar
release/modules/ext/joda-time-2.4-javadoc.jar
-
- ext/poi-excelant-3.15.jar
- release/modules/ext/poi-excelant-3.15.jar
-
ext/imageio-psd-3.2.jar
release/modules/ext/imageio-psd-3.2.jar
@@ -823,10 +837,6 @@
ext/jfxtras-fxml-8.0-r4.jar
release/modules/ext/jfxtras-fxml-8.0-r4.jar
-
- ext/poi-ooxml-3.15.jar
- release/modules/ext/poi-ooxml-3.15.jar
-
ext/joda-time-2.4.jar
release/modules/ext/joda-time-2.4.jar
@@ -851,18 +861,22 @@
ext/guava-19.0.jar
release/modules/ext/guava-19.0.jar
+
+ ext/poi-3.17.jar
+ release/modules/ext/poi-3.17.jar
+
+
+ ext/poi-ooxml-schemas-3.17.jar
+ release/modules/ext/poi-ooxml-schemas-3.17.jar
+
+
+ ext/poi-scratchpad-3.17.jar
+ release/modules/ext/poi-scratchpad-3.17.jar
+
ext/commons-io-2.5.jar
release/modules/ext/commons-io-2.5.jar
-
- ext/poi-ooxml-schemas-3.15.jar
- release/modules/ext/poi-ooxml-schemas-3.15.jar
-
-
- ext/poi-scratchpad-3.15.jar
- release/modules/ext/poi-scratchpad-3.15.jar
-
ext/imageio-bmp-3.2.jar
release/modules/ext/imageio-bmp-3.2.jar
@@ -887,6 +901,10 @@
ext/ant-1.8.2.jar
release/modules/ext/ant-1.8.2.jar
+
+ ext/poi-excelant-3.17.jar
+ release/modules/ext/poi-excelant-3.17.jar
+
ext/javassist-3.12.1.GA.jar
release/modules/ext/javassist-3.12.1.GA.jar
@@ -899,6 +917,10 @@
ext/commons-logging-1.1.2.jar
release/modules/ext/commons-logging-1.1.2.jar
+
+ ext/poi-ooxml-3.17.jar
+ release/modules/ext/poi-ooxml-3.17.jar
+
ext/controlsfx-8.40.11.jar
release/modules/ext/controlsfx-8.40.11.jar
@@ -911,10 +933,6 @@
ext/javaee-api-5.0-2.jar
release/modules/ext/javaee-api-5.0-2.jar
-
- ext/poi-3.15.jar
- release/modules/ext/poi-3.15.jar
-
ext/common-image-3.2.jar
release/modules/ext/common-image-3.2.jar
diff --git a/Experimental/ivy.xml b/Experimental/ivy.xml
index 93d6dafa8d..965af1bc12 100644
--- a/Experimental/ivy.xml
+++ b/Experimental/ivy.xml
@@ -6,7 +6,7 @@
-
+
diff --git a/Experimental/nbproject/project.properties b/Experimental/nbproject/project.properties
index 1bd0e2fc90..2db8202ab7 100644
--- a/Experimental/nbproject/project.properties
+++ b/Experimental/nbproject/project.properties
@@ -3,7 +3,7 @@ file.reference.jackson-core-2.7.0.jar=release/modules/ext/jackson-core-2.7.0.jar
file.reference.LGoodDatePicker-10.3.1.jar=release/modules/ext/LGoodDatePicker-10.3.1.jar
file.reference.mchange-commons-java-0.2.9.jar=release/modules/ext/mchange-commons-java-0.2.9.jar
file.reference.postgresql-9.4-1201-jdbc41.jar=release/modules/ext/postgresql-9.4-1201-jdbc41.jar
-file.reference.tika-core-1.14.jar=release/modules/ext/tika-core-1.14.jar
+file.reference.tika-core-1.17.jar=release/modules/ext/tika-core-1.17.jar
javac.source=1.8
javac.compilerargs=-Xlint -Xlint:-serial
javadoc.reference.LGoodDatePicker-10.3.1.jar=release/modules/ext/LGoodDatePicker-10.3.1-javadoc.jar
diff --git a/Experimental/nbproject/project.xml b/Experimental/nbproject/project.xml
index 8293608102..f2bf6d1996 100644
--- a/Experimental/nbproject/project.xml
+++ b/Experimental/nbproject/project.xml
@@ -146,12 +146,12 @@
org.sleuthkit.autopsy.experimental.configuration
- ext/tika-core-1.14.jar
- release/modules/ext/tika-core-1.14.jar
+ ext/LGoodDatePicker-10.3.1.jar
+ release/modules/ext/LGoodDatePicker-10.3.1.jar
- ext/LGoodDatePicker-10.3.1.jar
- release/modules/ext/LGoodDatePicker-10.3.1.jar
+ ext/tika-core-1.17.jar
+ release/modules/ext/tika-core-1.17.jar
ext/mchange-commons-java-0.2.9.jar
diff --git a/KeywordSearch/ivy.xml b/KeywordSearch/ivy.xml
index 3ceb4e6378..fc6aa00269 100644
--- a/KeywordSearch/ivy.xml
+++ b/KeywordSearch/ivy.xml
@@ -22,7 +22,7 @@
-
+
diff --git a/KeywordSearch/nbproject/project.properties b/KeywordSearch/nbproject/project.properties
index 5aa1b716e0..ddc825b4d4 100644
--- a/KeywordSearch/nbproject/project.properties
+++ b/KeywordSearch/nbproject/project.properties
@@ -1,6 +1,5 @@
-file.reference.aopalliance-1.0.jar=release/modules/ext/aopalliance-1.0.jar
-file.reference.apache-mime4j-core-0.7.2.jar=release/modules/ext/apache-mime4j-core-0.7.2.jar
-file.reference.apache-mime4j-dom-0.7.2.jar=release/modules/ext/apache-mime4j-dom-0.7.2.jar
+file.reference.apache-mime4j-core-0.8.1.jar=release/modules/ext/apache-mime4j-core-0.8.1.jar
+file.reference.apache-mime4j-dom-0.8.1.jar=release/modules/ext/apache-mime4j-dom-0.8.1.jar
file.reference.asm-5.0.4.jar=release/modules/ext/asm-5.0.4.jar
file.reference.asm-all-3.1.jar=release/modules/ext/asm-all-3.1.jar
file.reference.bcmail-jdk15on-1.54.jar=release/modules/ext/bcmail-jdk15on-1.54.jar
@@ -15,7 +14,7 @@ file.reference.commons-beanutils-1.9.2.jar=release/modules/ext/commons-beanutils
file.reference.commons-codec-1.10.jar=release/modules/ext/commons-codec-1.10.jar
file.reference.commons-collections-3.2.2.jar=release/modules/ext/commons-collections-3.2.2.jar
file.reference.commons-collections4-4.1.jar=release/modules/ext/commons-collections4-4.1.jar
-file.reference.commons-compress-1.12.jar=release/modules/ext/commons-compress-1.12.jar
+file.reference.commons-compress-1.14.jar=release/modules/ext/commons-compress-1.14.jar
file.reference.commons-csv-1.0.jar=release/modules/ext/commons-csv-1.0.jar
file.reference.commons-digester-1.8.1.jar=release/modules/ext/commons-digester-1.8.1.jar
file.reference.commons-exec-1.3.jar=release/modules/ext/commons-exec-1.3.jar
@@ -26,35 +25,34 @@ file.reference.commons-logging-api-1.1.jar=release/modules/ext/commons-logging-a
file.reference.commons-validator-1.5.1-javadoc.jar=release/modules/ext/commons-validator-1.5.1-javadoc.jar
file.reference.commons-validator-1.5.1-sources.jar=release/modules/ext/commons-validator-1.5.1-sources.jar
file.reference.commons-validator-1.5.1.jar=release/modules/ext/commons-validator-1.5.1.jar
-file.reference.commons-vfs2-2.0.jar=release/modules/ext/commons-vfs2-2.0.jar
file.reference.ctakes-core-3.2.2.jar=release/modules/ext/ctakes-core-3.2.2.jar
file.reference.ctakes-core-res-3.2.2.jar=release/modules/ext/ctakes-core-res-3.2.2.jar
file.reference.ctakes-type-system-3.2.2.jar=release/modules/ext/ctakes-type-system-3.2.2.jar
file.reference.ctakes-utils-3.2.2.jar=release/modules/ext/ctakes-utils-3.2.2.jar
file.reference.curvesapi-1.04.jar=release/modules/ext/curvesapi-1.04.jar
-file.reference.cxf-core-3.0.3.jar=release/modules/ext/cxf-core-3.0.3.jar
-file.reference.cxf-rt-frontend-jaxrs-3.0.3.jar=release/modules/ext/cxf-rt-frontend-jaxrs-3.0.3.jar
-file.reference.cxf-rt-rs-client-3.0.3.jar=release/modules/ext/cxf-rt-rs-client-3.0.3.jar
-file.reference.cxf-rt-transports-http-3.0.3.jar=release/modules/ext/cxf-rt-transports-http-3.0.3.jar
+file.reference.cxf-core-3.0.16.jar=release/modules/ext/cxf-core-3.0.16.jar
+file.reference.cxf-rt-frontend-jaxrs-3.0.16.jar=release/modules/ext/cxf-rt-frontend-jaxrs-3.0.16.jar
+file.reference.cxf-rt-rs-client-3.0.16.jar=release/modules/ext/cxf-rt-rs-client-3.0.16.jar
+file.reference.cxf-rt-transports-http-3.0.16.jar=release/modules/ext/cxf-rt-transports-http-3.0.16.jar
file.reference.ehcache-core-2.6.2.jar=release/modules/ext/ehcache-core-2.6.2.jar
file.reference.findstructapi-0.0.1.jar=release/modules/ext/findstructapi-0.0.1.jar
-file.reference.fontbox-2.0.3.jar=release/modules/ext/fontbox-2.0.3.jar
+file.reference.fontbox-2.0.8.jar=release/modules/ext/fontbox-2.0.8.jar
file.reference.geoapi-3.0.0.jar=release/modules/ext/geoapi-3.0.0.jar
file.reference.grib-4.5.5.jar=release/modules/ext/grib-4.5.5.jar
-file.reference.gson-2.2.4.jar=release/modules/ext/gson-2.2.4.jar
+file.reference.gson-2.8.1.jar=release/modules/ext/gson-2.8.1.jar
file.reference.guava-17.0.jar=release/modules/ext/guava-17.0.jar
file.reference.hamcrest-core-1.3.jar=release/modules/ext/hamcrest-core-1.3.jar
-file.reference.httpclient-4.3.1.jar=release/modules/ext/httpclient-4.3.1.jar
-file.reference.httpcore-4.3.jar=release/modules/ext/httpcore-4.3.jar
+file.reference.httpclient-4.5.4.jar=release/modules/ext/httpclient-4.5.4.jar
file.reference.httpcore-4.4.1.jar=release/modules/ext/httpcore-4.4.1.jar
-file.reference.httpmime-4.3.1.jar=release/modules/ext/httpmime-4.3.1.jar
+file.reference.httpcore-4.4.7.jar=release/modules/ext/httpcore-4.4.7.jar
file.reference.httpmime-4.4.1.jar=release/modules/ext/httpmime-4.4.1.jar
+file.reference.httpmime-4.5.4.jar=release/modules/ext/httpmime-4.5.4.jar
file.reference.httpservices-4.5.5.jar=release/modules/ext/httpservices-4.5.5.jar
file.reference.icu4j-3.8.jar=release/modules/ext/icu4j-3.8.jar
file.reference.isoparser-1.1.18.jar=release/modules/ext/isoparser-1.1.18.jar
-file.reference.jackcess-2.1.4.jar=release/modules/ext/jackcess-2.1.4.jar
-file.reference.jackcess-encrypt-2.1.1.jar=release/modules/ext/jackcess-encrypt-2.1.1.jar
-file.reference.jackson-core-2.8.1.jar=release/modules/ext/jackson-core-2.8.1.jar
+file.reference.jackcess-2.1.8.jar=release/modules/ext/jackcess-2.1.8.jar
+file.reference.jackcess-encrypt-2.1.2.jar=release/modules/ext/jackcess-encrypt-2.1.2.jar
+file.reference.jackson-core-2.9.2.jar=release/modules/ext/jackson-core-2.9.2.jar
file.reference.jakarta-regexp-1.4.jar=release/modules/ext/jakarta-regexp-1.4.jar
file.reference.java-libpst-0.8.1.jar=release/modules/ext/java-libpst-0.8.1.jar
file.reference.javax.annotation-api-1.2.jar=release/modules/ext/javax.annotation-api-1.2.jar
@@ -63,20 +61,17 @@ file.reference.jcip-annotations-1.0.jar=release/modules/ext/jcip-annotations-1.0
file.reference.jcommander-1.35.jar=release/modules/ext/jcommander-1.35.jar
file.reference.jdom-1.0.jar=release/modules/ext/jdom-1.0.jar
file.reference.jdom2-2.0.4.jar=release/modules/ext/jdom2-2.0.4.jar
-file.reference.jempbox-1.8.12.jar=release/modules/ext/jempbox-1.8.12.jar
+file.reference.jempbox-1.8.13.jar=release/modules/ext/jempbox-1.8.13.jar
file.reference.jericho-html-3.3-javadoc.jar=release/modules/ext/jericho-html-3.3-javadoc.jar
file.reference.jericho-html-3.3-sources.jar=release/modules/ext/jericho-html-3.3-sources.jar
file.reference.jericho-html-3.3.jar=release/modules/ext/jericho-html-3.3.jar
file.reference.jhighlight-1.0.2.jar=release/modules/ext/jhighlight-1.0.2.jar
-file.reference.jj2000-5.2.jar=release/modules/ext/jj2000-5.2.jar
file.reference.jmatio-1.2.jar=release/modules/ext/jmatio-1.2.jar
file.reference.jna-4.1.0.jar=release/modules/ext/jna-4.1.0.jar
file.reference.joda-time-2.2.jar=release/modules/ext/joda-time-2.2.jar
-file.reference.json-20140107.jar=release/modules/ext/json-20140107.jar
file.reference.json-simple-1.1.1.jar=release/modules/ext/json-simple-1.1.1.jar
file.reference.jsoup-1.7.2.jar=release/modules/ext/jsoup-1.7.2.jar
file.reference.jsr-275-0.9.3.jar=release/modules/ext/jsr-275-0.9.3.jar
-file.reference.junit-4.11.jar=release/modules/ext/junit-4.11.jar
file.reference.juniversalchardet-1.0.3.jar=release/modules/ext/juniversalchardet-1.0.3.jar
file.reference.junrar-0.7.jar=release/modules/ext/junrar-0.7.jar
file.reference.jVinci-2.6.0.jar=release/modules/ext/jVinci-2.6.0.jar
@@ -88,10 +83,7 @@ file.reference.lucene-core-4.0.0.jar=release/modules/ext/lucene-core-4.0.0.jar
file.reference.lucene-queries-4.0.0.jar=release/modules/ext/lucene-queries-4.0.0.jar
file.reference.lucene-queryparser-4.0.0.jar=release/modules/ext/lucene-queryparser-4.0.0.jar
file.reference.lucene-sandbox-4.0.0.jar=release/modules/ext/lucene-sandbox-4.0.0.jar
-file.reference.maven-scm-api-1.4.jar=release/modules/ext/maven-scm-api-1.4.jar
-file.reference.maven-scm-provider-svn-commons-1.4.jar=release/modules/ext/maven-scm-provider-svn-commons-1.4.jar
-file.reference.maven-scm-provider-svnexe-1.4.jar=release/modules/ext/maven-scm-provider-svnexe-1.4.jar
-file.reference.metadata-extractor-2.9.1.jar=release/modules/ext/metadata-extractor-2.9.1.jar
+file.reference.metadata-extractor-2.10.1.jar=release/modules/ext/metadata-extractor-2.10.1.jar
file.reference.netcdf4-4.5.5.jar=release/modules/ext/netcdf4-4.5.5.jar
file.reference.noggit-0.5.jar=release/modules/ext/noggit-0.5.jar
file.reference.openaifsm-0.0.1.jar=release/modules/ext/openaifsm-0.0.1.jar
@@ -101,18 +93,15 @@ file.reference.org.apache.felix.scr.annotations-1.6.0.jar=release/modules/ext/or
file.reference.org.apache.felix.scr.generator-1.1.2.jar=release/modules/ext/org.apache.felix.scr.generator-1.1.2.jar
file.reference.org.osgi.compendium-4.0.0.jar=release/modules/ext/org.osgi.compendium-4.0.0.jar
file.reference.org.osgi.core-4.0.0.jar=release/modules/ext/org.osgi.core-4.0.0.jar
-file.reference.pdfbox-2.0.3.jar=release/modules/ext/pdfbox-2.0.3.jar
-file.reference.pdfbox-debugger-2.0.3.jar=release/modules/ext/pdfbox-debugger-2.0.3.jar
-file.reference.pdfbox-tools-2.0.3.jar=release/modules/ext/pdfbox-tools-2.0.3.jar
-file.reference.plexus-utils-1.5.6.jar=release/modules/ext/plexus-utils-1.5.6.jar
-file.reference.poi-3.15.jar=release/modules/ext/poi-3.15.jar
-file.reference.poi-ooxml-3.15.jar=release/modules/ext/poi-ooxml-3.15.jar
-file.reference.poi-ooxml-schemas-3.15.jar=release/modules/ext/poi-ooxml-schemas-3.15.jar
-file.reference.poi-scratchpad-3.15.jar=release/modules/ext/poi-scratchpad-3.15.jar
+file.reference.pdfbox-2.0.8.jar=release/modules/ext/pdfbox-2.0.8.jar
+file.reference.pdfbox-tools-2.0.8.jar=release/modules/ext/pdfbox-tools-2.0.8.jar
+file.reference.poi-3.17.jar=release/modules/ext/poi-3.17.jar
+file.reference.poi-ooxml-3.17.jar=release/modules/ext/poi-ooxml-3.17.jar
+file.reference.poi-ooxml-schemas-3.17.jar=release/modules/ext/poi-ooxml-schemas-3.17.jar
+file.reference.poi-scratchpad-3.17.jar=release/modules/ext/poi-scratchpad-3.17.jar
file.reference.protobuf-java-2.5.0.jar=release/modules/ext/protobuf-java-2.5.0.jar
file.reference.qdox-1.12.jar=release/modules/ext/qdox-1.12.jar
file.reference.quartz-2.2.0.jar=release/modules/ext/quartz-2.2.0.jar
-file.reference.regexp-1.3.jar=release/modules/ext/regexp-1.3.jar
file.reference.rome-1.5.1.jar=release/modules/ext/rome-1.5.1.jar
file.reference.rome-utils-1.5.1.jar=release/modules/ext/rome-utils-1.5.1.jar
file.reference.sis-metadata-0.6.jar=release/modules/ext/sis-metadata-0.6.jar
@@ -120,24 +109,18 @@ file.reference.sis-netcdf-0.6.jar=release/modules/ext/sis-netcdf-0.6.jar
file.reference.sis-referencing-0.6.jar=release/modules/ext/sis-referencing-0.6.jar
file.reference.sis-storage-0.6.jar=release/modules/ext/sis-storage-0.6.jar
file.reference.sis-utility-0.6.jar=release/modules/ext/sis-utility-0.6.jar
-file.reference.slf4j-api-1.7.12.jar=release/modules/ext/slf4j-api-1.7.12.jar
+file.reference.slf4j-api-1.7.24.jar=release/modules/ext/slf4j-api-1.7.24.jar
file.reference.solr-solrj-4.9.1-javadoc.jar=release/modules/ext/solr-solrj-4.9.1-javadoc.jar
file.reference.solr-solrj-4.9.1-sources.jar=release/modules/ext/solr-solrj-4.9.1-sources.jar
file.reference.solr-solrj-4.9.1.jar=release/modules/ext/solr-solrj-4.9.1.jar
-file.reference.spring-aop-3.1.2.RELEASE.jar=release/modules/ext/spring-aop-3.1.2.RELEASE.jar
-file.reference.spring-asm-3.1.2.RELEASE.jar=release/modules/ext/spring-asm-3.1.2.RELEASE.jar
-file.reference.spring-beans-3.1.2.RELEASE.jar=release/modules/ext/spring-beans-3.1.2.RELEASE.jar
-file.reference.spring-context-3.1.2.RELEASE.jar=release/modules/ext/spring-context-3.1.2.RELEASE.jar
-file.reference.spring-core-3.1.2.RELEASE.jar=release/modules/ext/spring-core-3.1.2.RELEASE.jar
-file.reference.spring-expression-3.1.2.RELEASE.jar=release/modules/ext/spring-expression-3.1.2.RELEASE.jar
-file.reference.sqlite-jdbc-3.8.11.2.jar=release/modules/ext/sqlite-jdbc-3.8.11.2.jar
+file.reference.sqlite-jdbc-3.19.3.jar=release/modules/ext/sqlite-jdbc-3.19.3.jar
file.reference.sqlwrapper-0.0.1.jar=release/modules/ext/sqlwrapper-0.0.1.jar
file.reference.stax2-api-3.1.4.jar=release/modules/ext/stax2-api-3.1.4.jar
file.reference.tagsoup-1.2.1.jar=release/modules/ext/tagsoup-1.2.1.jar
-file.reference.tika-core-1.14.jar=release/modules/ext/tika-core-1.14.jar
-file.reference.tika-parsers-1.14-javadoc.jar=release/modules/ext/tika-parsers-1.14-javadoc.jar
-file.reference.tika-parsers-1.14-sources.jar=release/modules/ext/tika-parsers-1.14-sources.jar
-file.reference.tika-parsers-1.14.jar=release/modules/ext/tika-parsers-1.14.jar
+file.reference.tika-core-1.17.jar=release/modules/ext/tika-core-1.17.jar
+file.reference.tika-parsers-1.17-javadoc.jar=release/modules/ext/tika-parsers-1.17-javadoc.jar
+file.reference.tika-parsers-1.17-sources.jar=release/modules/ext/tika-parsers-1.17-sources.jar
+file.reference.tika-parsers-1.17.jar=release/modules/ext/tika-parsers-1.17.jar
file.reference.udunits-4.5.5.jar=release/modules/ext/udunits-4.5.5.jar
file.reference.uimafit-core-2.1.0.jar=release/modules/ext/uimafit-core-2.1.0.jar
file.reference.uimaj-adapter-vinci-2.6.0.jar=release/modules/ext/uimaj-adapter-vinci-2.6.0.jar
@@ -150,9 +133,7 @@ file.reference.vorbis-java-core-0.8.jar=release/modules/ext/vorbis-java-core-0.8
file.reference.vorbis-java-tika-0.8.jar=release/modules/ext/vorbis-java-tika-0.8.jar
file.reference.woodstox-core-asl-4.4.1.jar=release/modules/ext/woodstox-core-asl-4.4.1.jar
file.reference.xmlbeans-2.6.0.jar=release/modules/ext/xmlbeans-2.6.0.jar
-file.reference.xmlschema-core-2.1.0.jar=release/modules/ext/xmlschema-core-2.1.0.jar
-file.reference.xmpcore-5.1.2.jar=release/modules/ext/xmpcore-5.1.2.jar
-file.reference.xz-1.5.jar=release/modules/ext/xz-1.5.jar
+file.reference.xmpcore-5.1.3.jar=release/modules/ext/xmpcore-5.1.3.jar
file.reference.zookeeper-3.4.6.jar=release/modules/ext/zookeeper-3.4.6.jar
javac.source=1.8
javac.compilerargs=-Xlint -Xlint:-serial
diff --git a/KeywordSearch/nbproject/project.xml b/KeywordSearch/nbproject/project.xml
index 357c2178e2..db9ada1b1b 100644
--- a/KeywordSearch/nbproject/project.xml
+++ b/KeywordSearch/nbproject/project.xml
@@ -141,6 +141,10 @@
ext/commons-validator-1.5.1-sources.jar
release/modules/ext/commons-validator-1.5.1-sources.jar
+
+ ext/apache-mime4j-dom-0.8.1.jar
+ release/modules/ext/apache-mime4j-dom-0.8.1.jar
+
ext/commons-digester-1.8.1.jar
release/modules/ext/commons-digester-1.8.1.jar
@@ -149,14 +153,14 @@
ext/jwnl-1.3.3.jar
release/modules/ext/jwnl-1.3.3.jar
-
- ext/tika-core-1.14.jar
- release/modules/ext/tika-core-1.14.jar
-
ext/lucene-queryparser-4.0.0.jar
release/modules/ext/lucene-queryparser-4.0.0.jar
+
+ ext/httpclient-4.5.4.jar
+ release/modules/ext/httpclient-4.5.4.jar
+
ext/uimaj-examples-2.4.0.jar
release/modules/ext/uimaj-examples-2.4.0.jar
@@ -165,10 +169,6 @@
ext/cdm-4.5.5.jar
release/modules/ext/cdm-4.5.5.jar
-
- ext/gson-2.2.4.jar
- release/modules/ext/gson-2.2.4.jar
-
ext/org.osgi.compendium-4.0.0.jar
release/modules/ext/org.osgi.compendium-4.0.0.jar
@@ -177,6 +177,10 @@
ext/geoapi-3.0.0.jar
release/modules/ext/geoapi-3.0.0.jar
+
+ ext/commons-compress-1.14.jar
+ release/modules/ext/commons-compress-1.14.jar
+
ext/hamcrest-core-1.3.jar
release/modules/ext/hamcrest-core-1.3.jar
@@ -197,30 +201,34 @@
ext/xmlbeans-2.6.0.jar
release/modules/ext/xmlbeans-2.6.0.jar
-
- ext/maven-scm-api-1.4.jar
- release/modules/ext/maven-scm-api-1.4.jar
-
ext/quartz-2.2.0.jar
release/modules/ext/quartz-2.2.0.jar
- ext/jackcess-2.1.4.jar
- release/modules/ext/jackcess-2.1.4.jar
-
-
- ext/slf4j-api-1.7.12.jar
- release/modules/ext/slf4j-api-1.7.12.jar
+ ext/sqlite-jdbc-3.19.3.jar
+ release/modules/ext/sqlite-jdbc-3.19.3.jar
ext/guava-17.0.jar
release/modules/ext/guava-17.0.jar
+
+ ext/metadata-extractor-2.10.1.jar
+ release/modules/ext/metadata-extractor-2.10.1.jar
+
+
+ ext/apache-mime4j-core-0.8.1.jar
+ release/modules/ext/apache-mime4j-core-0.8.1.jar
+
ext/opennlp-maxent-3.0.3.jar
release/modules/ext/opennlp-maxent-3.0.3.jar
+
+ ext/pdfbox-tools-2.0.8.jar
+ release/modules/ext/pdfbox-tools-2.0.8.jar
+
ext/jVinci-2.6.0.jar
release/modules/ext/jVinci-2.6.0.jar
@@ -229,18 +237,14 @@
ext/json-simple-1.1.1.jar
release/modules/ext/json-simple-1.1.1.jar
+
+ ext/tika-parsers-1.17.jar
+ release/modules/ext/tika-parsers-1.17.jar
+
ext/sis-utility-0.6.jar
release/modules/ext/sis-utility-0.6.jar
-
- ext/jj2000-5.2.jar
- release/modules/ext/jj2000-5.2.jar
-
-
- ext/httpclient-4.3.1.jar
- release/modules/ext/httpclient-4.3.1.jar
-
ext/jhighlight-1.0.2.jar
release/modules/ext/jhighlight-1.0.2.jar
@@ -258,12 +262,12 @@
release/modules/ext/ctakes-utils-3.2.2.jar
- ext/apache-mime4j-dom-0.7.2.jar
- release/modules/ext/apache-mime4j-dom-0.7.2.jar
+ ext/cxf-rt-rs-client-3.0.16.jar
+ release/modules/ext/cxf-rt-rs-client-3.0.16.jar
- ext/commons-compress-1.12.jar
- release/modules/ext/commons-compress-1.12.jar
+ ext/jempbox-1.8.13.jar
+ release/modules/ext/jempbox-1.8.13.jar
ext/openaifsm-0.0.1.jar
@@ -277,14 +281,18 @@
ext/commons-collections4-4.1.jar
release/modules/ext/commons-collections4-4.1.jar
-
- ext/cxf-rt-rs-client-3.0.3.jar
- release/modules/ext/cxf-rt-rs-client-3.0.3.jar
-
ext/solr-solrj-4.9.1.jar
release/modules/ext/solr-solrj-4.9.1.jar
+
+ ext/xmpcore-5.1.3.jar
+ release/modules/ext/xmpcore-5.1.3.jar
+
+
+ ext/jackcess-2.1.8.jar
+ release/modules/ext/jackcess-2.1.8.jar
+
ext/findstructapi-0.0.1.jar
release/modules/ext/findstructapi-0.0.1.jar
@@ -317,6 +325,22 @@
ext/commons-codec-1.10.jar
release/modules/ext/commons-codec-1.10.jar
+
+ ext/gson-2.8.1.jar
+ release/modules/ext/gson-2.8.1.jar
+
+
+ ext/poi-ooxml-schemas-3.17.jar
+ release/modules/ext/poi-ooxml-schemas-3.17.jar
+
+
+ ext/poi-scratchpad-3.17.jar
+ release/modules/ext/poi-scratchpad-3.17.jar
+
+
+ ext/poi-3.17.jar
+ release/modules/ext/poi-3.17.jar
+
ext/lucene-queries-4.0.0.jar
release/modules/ext/lucene-queries-4.0.0.jar
@@ -326,45 +350,25 @@
release/modules/ext/bcprov-jdk15on-1.54.jar
- ext/poi-ooxml-schemas-3.15.jar
- release/modules/ext/poi-ooxml-schemas-3.15.jar
-
-
- ext/poi-scratchpad-3.15.jar
- release/modules/ext/poi-scratchpad-3.15.jar
+ ext/fontbox-2.0.8.jar
+ release/modules/ext/fontbox-2.0.8.jar
ext/solr-solrj-4.9.1-sources.jar
release/modules/ext/solr-solrj-4.9.1-sources.jar
-
- ext/commons-vfs2-2.0.jar
- release/modules/ext/commons-vfs2-2.0.jar
-
-
- ext/tika-parsers-1.14.jar
- release/modules/ext/tika-parsers-1.14.jar
-
-
- ext/jackcess-encrypt-2.1.1.jar
- release/modules/ext/jackcess-encrypt-2.1.1.jar
-
-
- ext/spring-expression-3.1.2.RELEASE.jar
- release/modules/ext/spring-expression-3.1.2.RELEASE.jar
-
ext/lucene-analyzers-common-4.0.0.jar
release/modules/ext/lucene-analyzers-common-4.0.0.jar
-
- ext/tika-parsers-1.14-sources.jar
- release/modules/ext/tika-parsers-1.14-sources.jar
-
ext/javax.ws.rs-api-2.0.1.jar
release/modules/ext/javax.ws.rs-api-2.0.1.jar
+
+ ext/httpmime-4.5.4.jar
+ release/modules/ext/httpmime-4.5.4.jar
+
ext/junrar-0.7.jar
release/modules/ext/junrar-0.7.jar
@@ -378,21 +382,13 @@
release/modules/ext/noggit-0.5.jar
- ext/xmlschema-core-2.1.0.jar
- release/modules/ext/xmlschema-core-2.1.0.jar
-
-
- ext/httpmime-4.3.1.jar
- release/modules/ext/httpmime-4.3.1.jar
+ ext/poi-ooxml-3.17.jar
+ release/modules/ext/poi-ooxml-3.17.jar
ext/jna-4.1.0.jar
release/modules/ext/jna-4.1.0.jar
-
- ext/xz-1.5.jar
- release/modules/ext/xz-1.5.jar
-
ext/qdox-1.12.jar
release/modules/ext/qdox-1.12.jar
@@ -410,37 +406,17 @@
release/modules/ext/grib-4.5.5.jar
- ext/maven-scm-provider-svn-commons-1.4.jar
- release/modules/ext/maven-scm-provider-svn-commons-1.4.jar
-
-
- ext/poi-3.15.jar
- release/modules/ext/poi-3.15.jar
-
-
- ext/spring-aop-3.1.2.RELEASE.jar
- release/modules/ext/spring-aop-3.1.2.RELEASE.jar
-
-
- ext/json-20140107.jar
- release/modules/ext/json-20140107.jar
+ ext/jackson-core-2.9.2.jar
+ release/modules/ext/jackson-core-2.9.2.jar
ext/uimaj-core-2.5.0.jar
release/modules/ext/uimaj-core-2.5.0.jar
-
- ext/pdfbox-2.0.3.jar
- release/modules/ext/pdfbox-2.0.3.jar
-
ext/jmatio-1.2.jar
release/modules/ext/jmatio-1.2.jar
-
- ext/metadata-extractor-2.9.1.jar
- release/modules/ext/metadata-extractor-2.9.1.jar
-
ext/commons-csv-1.0.jar
release/modules/ext/commons-csv-1.0.jar
@@ -466,21 +442,13 @@
release/modules/ext/httpservices-4.5.5.jar
- ext/plexus-utils-1.5.6.jar
- release/modules/ext/plexus-utils-1.5.6.jar
-
-
- ext/fontbox-2.0.3.jar
- release/modules/ext/fontbox-2.0.3.jar
+ ext/httpcore-4.4.7.jar
+ release/modules/ext/httpcore-4.4.7.jar
ext/bcmail-jdk15on-1.54.jar
release/modules/ext/bcmail-jdk15on-1.54.jar
-
- ext/spring-beans-3.1.2.RELEASE.jar
- release/modules/ext/spring-beans-3.1.2.RELEASE.jar
-
ext/solr-solrj-4.9.1-javadoc.jar
release/modules/ext/solr-solrj-4.9.1-javadoc.jar
@@ -490,8 +458,8 @@
release/modules/ext/asm-all-3.1.jar
- ext/tika-parsers-1.14-javadoc.jar
- release/modules/ext/tika-parsers-1.14-javadoc.jar
+ ext/tika-parsers-1.17-javadoc.jar
+ release/modules/ext/tika-parsers-1.17-javadoc.jar
ext/icu4j-3.8.jar
@@ -501,10 +469,6 @@
ext/curvesapi-1.04.jar
release/modules/ext/curvesapi-1.04.jar
-
- ext/xmpcore-5.1.2.jar
- release/modules/ext/xmpcore-5.1.2.jar
-
ext/sis-referencing-0.6.jar
release/modules/ext/sis-referencing-0.6.jar
@@ -521,6 +485,10 @@
ext/tagsoup-1.2.1.jar
release/modules/ext/tagsoup-1.2.1.jar
+
+ ext/tika-core-1.17.jar
+ release/modules/ext/tika-core-1.17.jar
+
ext/lucene-core-4.0.0.jar
release/modules/ext/lucene-core-4.0.0.jar
@@ -533,10 +501,6 @@
ext/commons-logging-1.2.jar
release/modules/ext/commons-logging-1.2.jar
-
- ext/jackson-core-2.8.1.jar
- release/modules/ext/jackson-core-2.8.1.jar
-
ext/org.osgi.core-4.0.0.jar
release/modules/ext/org.osgi.core-4.0.0.jar
@@ -545,10 +509,18 @@
ext/c3p0-0.9.1.1.jar
release/modules/ext/c3p0-0.9.1.1.jar
+
+ ext/tika-parsers-1.17-sources.jar
+ release/modules/ext/tika-parsers-1.17-sources.jar
+
ext/sqlwrapper-0.0.1.jar
release/modules/ext/sqlwrapper-0.0.1.jar
+
+ ext/jackcess-encrypt-2.1.2.jar
+ release/modules/ext/jackcess-encrypt-2.1.2.jar
+
ext/jericho-html-3.3-javadoc.jar
release/modules/ext/jericho-html-3.3-javadoc.jar
@@ -557,18 +529,10 @@
ext/udunits-4.5.5.jar
release/modules/ext/udunits-4.5.5.jar
-
- ext/aopalliance-1.0.jar
- release/modules/ext/aopalliance-1.0.jar
-
ext/commons-collections-3.2.2.jar
release/modules/ext/commons-collections-3.2.2.jar
-
- ext/cxf-rt-frontend-jaxrs-3.0.3.jar
- release/modules/ext/cxf-rt-frontend-jaxrs-3.0.3.jar
-
ext/uimaj-document-annotation-2.5.0.jar
release/modules/ext/uimaj-document-annotation-2.5.0.jar
@@ -577,41 +541,29 @@
ext/woodstox-core-asl-4.4.1.jar
release/modules/ext/woodstox-core-asl-4.4.1.jar
-
- ext/poi-ooxml-3.15.jar
- release/modules/ext/poi-ooxml-3.15.jar
-
ext/org.apache.felix.scr.generator-1.1.2.jar
release/modules/ext/org.apache.felix.scr.generator-1.1.2.jar
+
+ ext/pdfbox-2.0.8.jar
+ release/modules/ext/pdfbox-2.0.8.jar
+
ext/zookeeper-3.4.6.jar
release/modules/ext/zookeeper-3.4.6.jar
- ext/cxf-rt-transports-http-3.0.3.jar
- release/modules/ext/cxf-rt-transports-http-3.0.3.jar
-
-
- ext/pdfbox-debugger-2.0.3.jar
- release/modules/ext/pdfbox-debugger-2.0.3.jar
-
-
- ext/spring-core-3.1.2.RELEASE.jar
- release/modules/ext/spring-core-3.1.2.RELEASE.jar
+ ext/cxf-rt-transports-http-3.0.16.jar
+ release/modules/ext/cxf-rt-transports-http-3.0.16.jar
ext/netcdf4-4.5.5.jar
release/modules/ext/netcdf4-4.5.5.jar
- ext/spring-asm-3.1.2.RELEASE.jar
- release/modules/ext/spring-asm-3.1.2.RELEASE.jar
-
-
- ext/junit-4.11.jar
- release/modules/ext/junit-4.11.jar
+ ext/slf4j-api-1.7.24.jar
+ release/modules/ext/slf4j-api-1.7.24.jar
ext/protobuf-java-2.5.0.jar
@@ -642,37 +594,17 @@
release/modules/ext/commons-lang-2.6.jar
- ext/sqlite-jdbc-3.8.11.2.jar
- release/modules/ext/sqlite-jdbc-3.8.11.2.jar
-
-
- ext/jempbox-1.8.12.jar
- release/modules/ext/jempbox-1.8.12.jar
-
-
- ext/maven-scm-provider-svnexe-1.4.jar
- release/modules/ext/maven-scm-provider-svnexe-1.4.jar
+ ext/cxf-core-3.0.16.jar
+ release/modules/ext/cxf-core-3.0.16.jar
ext/opennlp-tools-1.5.3.jar
release/modules/ext/opennlp-tools-1.5.3.jar
-
- ext/apache-mime4j-core-0.7.2.jar
- release/modules/ext/apache-mime4j-core-0.7.2.jar
-
ext/rome-utils-1.5.1.jar
release/modules/ext/rome-utils-1.5.1.jar
-
- ext/httpcore-4.3.jar
- release/modules/ext/httpcore-4.3.jar
-
-
- ext/pdfbox-tools-2.0.3.jar
- release/modules/ext/pdfbox-tools-2.0.3.jar
-
ext/sis-storage-0.6.jar
release/modules/ext/sis-storage-0.6.jar
@@ -689,6 +621,10 @@
ext/uimafit-core-2.1.0.jar
release/modules/ext/uimafit-core-2.1.0.jar
+
+ ext/cxf-rt-frontend-jaxrs-3.0.16.jar
+ release/modules/ext/cxf-rt-frontend-jaxrs-3.0.16.jar
+
ext/cleartk-util-2.0.0.jar
release/modules/ext/cleartk-util-2.0.0.jar
@@ -697,14 +633,6 @@
ext/jdom-1.0.jar
release/modules/ext/jdom-1.0.jar
-
- ext/cxf-core-3.0.3.jar
- release/modules/ext/cxf-core-3.0.3.jar
-
-
- ext/regexp-1.3.jar
- release/modules/ext/regexp-1.3.jar
-
ext/commons-beanutils-1.9.2.jar
release/modules/ext/commons-beanutils-1.9.2.jar
@@ -713,10 +641,6 @@
ext/ehcache-core-2.6.2.jar
release/modules/ext/ehcache-core-2.6.2.jar
-
- ext/spring-context-3.1.2.RELEASE.jar
- release/modules/ext/spring-context-3.1.2.RELEASE.jar
-
ext/ctakes-type-system-3.2.2.jar
release/modules/ext/ctakes-type-system-3.2.2.jar
diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/GlobalListsManagementPanel.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/GlobalListsManagementPanel.java
index 8aeb498432..aebf606380 100644
--- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/GlobalListsManagementPanel.java
+++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/GlobalListsManagementPanel.java
@@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
- * Copyright 2011-2017 Basis Technology Corp.
+ * Copyright 2011-2018 Basis Technology Corp.
* Contact: carrier sleuthkit org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -24,6 +24,7 @@ import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
+import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFileChooser;
@@ -35,6 +36,8 @@ import javax.swing.table.AbstractTableModel;
import org.netbeans.spi.options.OptionsPanelController;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.corecomponents.OptionsPanel;
+import org.sleuthkit.autopsy.coreutils.ModuleSettings;
+import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.ingest.IngestManager;
/**
@@ -45,6 +48,7 @@ class GlobalListsManagementPanel extends javax.swing.JPanel implements OptionsPa
private static final long serialVersionUID = 1L;
private final KeywordListTableModel tableModel;
private final org.sleuthkit.autopsy.keywordsearch.GlobalListSettingsPanel globalListSettingsPanel;
+ private final static String LAST_KEYWORD_LIST_PATH_KEY = "KeyWordImport_List";
GlobalListsManagementPanel(org.sleuthkit.autopsy.keywordsearch.GlobalListSettingsPanel gsp) {
this.globalListSettingsPanel = gsp;
@@ -345,8 +349,13 @@ class GlobalListsManagementPanel extends javax.swing.JPanel implements OptionsPa
}//GEN-LAST:event_newListButtonActionPerformed
private void importButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_importButtonActionPerformed
-
+ String lastBaseDirectory = Paths.get(PlatformUtil.getUserConfigDirectory(), "KeywordList").toString();
+ if (ModuleSettings.settingExists(ModuleSettings.MAIN_SETTINGS, LAST_KEYWORD_LIST_PATH_KEY)) {
+ lastBaseDirectory = ModuleSettings.getConfigSetting(ModuleSettings.MAIN_SETTINGS, LAST_KEYWORD_LIST_PATH_KEY);
+ }
+ File importFolder = new File(lastBaseDirectory);
JFileChooser chooser = new JFileChooser();
+ chooser.setCurrentDirectory(importFolder);
final String[] AUTOPSY_EXTENSIONS = new String[]{"xml"}; //NON-NLS
final String[] ENCASE_EXTENSIONS = new String[]{"txt"}; //NON-NLS
FileNameExtensionFilter autopsyFilter = new FileNameExtensionFilter(
@@ -430,7 +439,7 @@ class GlobalListsManagementPanel extends javax.swing.JPanel implements OptionsPa
KeywordSearchUtil.displayDialog(
NbBundle.getMessage(this.getClass(), "KeywordSearch.listImportFeatureTitle"), NbBundle.getMessage(this.getClass(), "KeywordSearch.kwListFailImportMsg"), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.INFO);
}
-
+ ModuleSettings.setConfigSetting(ModuleSettings.MAIN_SETTINGS, LAST_KEYWORD_LIST_PATH_KEY, selFile.getParent());
}
tableModel.resync();
diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java
index a48b40e756..a8bc995eae 100644
--- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java
+++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java
@@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
- * Copyright 2011-2017 Basis Technology Corp.
+ * Copyright 2011-2018 Basis Technology Corp.
* Contact: carrier sleuthkit org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -44,6 +44,7 @@ import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode;
import static org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode.AbstractFilePropertyType.LOCATION;
import org.sleuthkit.autopsy.datamodel.AbstractFsContentNode;
+import org.sleuthkit.autopsy.datamodel.EmptyNode;
import org.sleuthkit.autopsy.datamodel.KeyValue;
import org.sleuthkit.autopsy.datamodel.KeyValueNode;
import org.sleuthkit.autopsy.keywordsearch.KeywordSearchResultFactory.KeyValueQueryContent;
@@ -63,21 +64,21 @@ import org.sleuthkit.datamodel.TskCoreException;
* Responsible for assembling nodes and columns in the right way and performing
* lazy queries as needed.
*/
-class KeywordSearchResultFactory extends ChildFactory {
+class KeywordSearchResultFactory extends ChildFactory {
- private static final Logger logger = Logger.getLogger(KeywordSearchResultFactory.class.getName());
+ private static final Logger LOGGER = Logger.getLogger(KeywordSearchResultFactory.class.getName());
//common properties (superset of all Node properties) to be displayed as columns
- static final List COMMON_PROPERTIES =
- Stream.concat(
+ static final List COMMON_PROPERTIES
+ = Stream.concat(
Stream.of(
TSK_KEYWORD,
TSK_KEYWORD_REGEXP,
TSK_KEYWORD_PREVIEW)
- .map(BlackboardAttribute.ATTRIBUTE_TYPE::getDisplayName),
+ .map(BlackboardAttribute.ATTRIBUTE_TYPE::getDisplayName),
Arrays.stream(AbstractAbstractFileNode.AbstractFilePropertyType.values())
- .map(Object::toString))
- .collect(Collectors.toList());
+ .map(Object::toString))
+ .collect(Collectors.toList());
private final Collection queryRequests;
@@ -93,7 +94,7 @@ class KeywordSearchResultFactory extends ChildFactory {
* @param toPopulate property set map for a Node
*/
@Override
- protected boolean createKeys(List toPopulate) {
+ protected boolean createKeys(List toPopulate) {
for (QueryRequest queryRequest : queryRequests) {
/**
@@ -130,7 +131,7 @@ class KeywordSearchResultFactory extends ChildFactory {
* @return
*/
@NbBundle.Messages({"KeywordSearchResultFactory.query.exception.msg=Could not perform the query "})
- private boolean createFlatKeys(KeywordSearchQuery queryRequest, List toPopulate) {
+ private boolean createFlatKeys(KeywordSearchQuery queryRequest, List toPopulate) {
/**
* Execute the requested query.
@@ -139,15 +140,15 @@ class KeywordSearchResultFactory extends ChildFactory {
try {
queryResults = queryRequest.performQuery();
} catch (KeywordSearchModuleException | NoOpenCoreException ex) {
- logger.log(Level.SEVERE, "Could not perform the query " + queryRequest.getQueryString(), ex); //NON-NLS
+ LOGGER.log(Level.SEVERE, "Could not perform the query " + queryRequest.getQueryString(), ex); //NON-NLS
MessageNotifyUtil.Notify.error(Bundle.KeywordSearchResultFactory_query_exception_msg() + queryRequest.getQueryString(), ex.getCause().getMessage());
return false;
}
- SleuthkitCase tskCase = null;
+ SleuthkitCase tskCase;
try {
tskCase = Case.getCurrentCase().getSleuthkitCase();
} catch (IllegalStateException ex) {
- logger.log(Level.SEVERE, "There was no case open.", ex); //NON-NLS
+ LOGGER.log(Level.SEVERE, "There was no case open.", ex); //NON-NLS
return false;
}
@@ -159,16 +160,16 @@ class KeywordSearchResultFactory extends ChildFactory {
* Get file properties.
*/
Map properties = new LinkedHashMap<>();
- Content content = null;
- String contentName = "";
+ Content content;
+ String contentName;
try {
content = tskCase.getContentById(hit.getContentID());
if (content == null) {
- logger.log(Level.SEVERE, "There was a error getting content by id."); //NON-NLS
+ LOGGER.log(Level.SEVERE, "There was a error getting content by id."); //NON-NLS
return false;
}
} catch (TskCoreException ex) {
- logger.log(Level.SEVERE, "There was a error getting content by id.", ex); //NON-NLS
+ LOGGER.log(Level.SEVERE, "There was a error getting content by id.", ex); //NON-NLS
return false;
}
@@ -191,7 +192,7 @@ class KeywordSearchResultFactory extends ChildFactory {
try {
hitName = tskCase.getBlackboardArtifact(hit.getArtifactID().get()).getDisplayName() + " Artifact"; //NON-NLS
} catch (TskCoreException ex) {
- logger.log(Level.SEVERE, "Error getting blckboard artifact by id", ex);
+ LOGGER.log(Level.SEVERE, "Error getting blckboard artifact by id", ex);
return false;
}
} else {
@@ -202,9 +203,13 @@ class KeywordSearchResultFactory extends ChildFactory {
}
- // Add all the nodes to toPopulate at once. Minimizes node creation
- // EDT threads, which can slow and/or hang the UI on large queries.
- toPopulate.addAll(tempList);
+ if (hitNumber == 0) {
+ toPopulate.add(new KeyValue("This KeyValue Is Empty", 0));
+ } else {
+ // Add all the nodes to toPopulate at once. Minimizes node creation
+ // EDT threads, which can slow and/or hang the UI on large queries.
+ toPopulate.addAll(tempList);
+ }
//write to bb
//cannot reuse snippet in BlackboardResultWriter
@@ -239,15 +244,25 @@ class KeywordSearchResultFactory extends ChildFactory {
return hits.values();
}
+ @NbBundle.Messages({"KeywordSearchResultFactory.createNodeForKey.noResultsFound.text=No results found."})
@Override
- protected Node createNodeForKey(KeyValueQueryContent key) {
- final Content content = key.getContent();
- QueryResults hits = key.getHits();
+ protected Node createNodeForKey(KeyValue key) {
+ Node resultNode;
- Node kvNode = new KeyValueNode(key, Children.LEAF, Lookups.singleton(content));
+ if (key instanceof KeyValueQueryContent) {
+ final Content content = ((KeyValueQueryContent) key).getContent();
+ QueryResults hits = ((KeyValueQueryContent) key).getHits();
- //wrap in KeywordSearchFilterNode for the markup content, might need to override FilterNode for more customization
- return new KeywordSearchFilterNode(hits, kvNode);
+ Node kvNode = new KeyValueNode(key, Children.LEAF, Lookups.singleton(content));
+
+ //wrap in KeywordSearchFilterNode for the markup content, might need to override FilterNode for more customization
+ resultNode = new KeywordSearchFilterNode(hits, kvNode);
+ } else {
+ resultNode = new EmptyNode("This Node Is Empty");
+ resultNode.setDisplayName(NbBundle.getMessage(this.getClass(), "KeywordSearchResultFactory.createNodeForKey.noResultsFound.text"));
+ }
+
+ return resultNode;
}
@@ -308,7 +323,7 @@ class KeywordSearchResultFactory extends ChildFactory {
*/
static class BlackboardResultWriter extends SwingWorker {
- private static final List writers = new ArrayList<>();
+ private static final List WRITERS = new ArrayList<>();
private ProgressHandle progress;
private final KeywordSearchQuery query;
private final QueryResults hits;
@@ -343,24 +358,24 @@ class KeywordSearchResultFactory extends ChildFactory {
try {
get();
} catch (InterruptedException | CancellationException ex) {
- logger.log(Level.WARNING, "User cancelled writing of ad hoc search query results for '{0}' to the blackboard", query.getQueryString()); //NON-NLS
+ LOGGER.log(Level.WARNING, "User cancelled writing of ad hoc search query results for '{0}' to the blackboard", query.getQueryString()); //NON-NLS
} catch (ExecutionException ex) {
- logger.log(Level.SEVERE, "Error writing of ad hoc search query results for " + query.getQueryString() + " to the blackboard", ex); //NON-NLS
+ LOGGER.log(Level.SEVERE, "Error writing of ad hoc search query results for " + query.getQueryString() + " to the blackboard", ex); //NON-NLS
}
}
private static synchronized void registerWriter(BlackboardResultWriter writer) {
- writers.add(writer);
+ WRITERS.add(writer);
}
private static synchronized void deregisterWriter(BlackboardResultWriter writer) {
- writers.remove(writer);
+ WRITERS.remove(writer);
}
static synchronized void stopAllWriters() {
- for (BlackboardResultWriter w : writers) {
+ for (BlackboardResultWriter w : WRITERS) {
w.cancel(true);
- writers.remove(w);
+ WRITERS.remove(w);
}
}
}
diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/TikaTextExtractor.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/TikaTextExtractor.java
index fcbace158d..4b9c3b17cb 100644
--- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/TikaTextExtractor.java
+++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/TikaTextExtractor.java
@@ -33,7 +33,11 @@ import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.tika.Tika;
import org.apache.tika.metadata.Metadata;
+import org.apache.tika.parser.AutoDetectParser;
import org.apache.tika.parser.ParseContext;
+import org.apache.tika.parser.Parser;
+import org.apache.tika.parser.ParsingReader;
+import org.apache.tika.parser.microsoft.OfficeParserConfig;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.AbstractFile;
@@ -48,6 +52,8 @@ class TikaTextExtractor extends FileTextExtractor {
static final private Logger logger = Logger.getLogger(TikaTextExtractor.class.getName());
private final ExecutorService tikaParseExecutor = Executors.newSingleThreadExecutor();
+ private final AutoDetectParser parser = new AutoDetectParser();
+
private static final List TIKA_SUPPORTED_TYPES
= new Tika().getParser().getSupportedTypes(new ParseContext())
.stream()
@@ -64,8 +70,18 @@ class TikaTextExtractor extends FileTextExtractor {
ReadContentInputStream stream = new ReadContentInputStream(sourceFile);
Metadata metadata = new Metadata();
+ ParseContext parseContext = new ParseContext();
+ parseContext.set(Parser.class, parser);
+
+ // Use the more memory efficient Tika SAX parsers for DOCX and
+ // PPTX files (it already uses SAX for XLSX).
+ OfficeParserConfig officeParserConfig = new OfficeParserConfig();
+ officeParserConfig.setUseSAXPptxExtractor(true);
+ officeParserConfig.setUseSAXDocxExtractor(true);
+ parseContext.set(OfficeParserConfig.class, officeParserConfig);
+
//Parse the file in a task, a convenient way to have a timeout...
- final Future future = tikaParseExecutor.submit(() -> new Tika().parse(stream, metadata));
+ final Future future = tikaParseExecutor.submit(() -> new ParsingReader(parser, stream, metadata, parseContext));
try {
final Reader tikaReader = future.get(getTimeout(sourceFile.getSize()), TimeUnit.SECONDS);
diff --git a/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties b/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties
index e0a4c85328..bafc320fad 100644
--- a/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties
+++ b/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties
@@ -1,5 +1,5 @@
#Updated by build script
-#Fri, 05 Jan 2018 10:31:22 -0500
+#Fri, 05 Jan 2018 12:14:19 -0500
LBL_splash_window_title=Starting Autopsy
SPLASH_HEIGHT=314
SPLASH_WIDTH=538
diff --git a/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties b/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties
index 8f4ccbd194..6097052361 100644
--- a/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties
+++ b/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties
@@ -1,4 +1,4 @@
#Updated by build script
-#Fri, 05 Jan 2018 10:31:22 -0500
+#Fri, 05 Jan 2018 12:14:19 -0500
CTL_MainWindow_Title=Autopsy 4.5.0
CTL_MainWindow_Title_No_Project=Autopsy 4.5.0
diff --git a/test/script/regression.py b/test/script/regression.py
index be6515f054..afe1ea4976 100644
--- a/test/script/regression.py
+++ b/test/script/regression.py
@@ -652,10 +652,10 @@ class TestData(object):
# we are looking for is the only one in the self.reports_dir folder
html_path = ""
for fs in os.listdir(self.reports_dir):
- html_path = make_path(self.reports_dir, fs)
- if os.path.isdir(html_path):
+ if "HTML Report" in fs:
+ html_path = make_path(self.reports_dir, fs)
break
- return make_path(html_path, os.listdir(html_path)[0])
+ return html_path
def get_sorted_data_path(self, file_type):
"""Get the path to the BlackboardDump file that corresponds to the given DBType.