diff --git a/Core/nbproject/project.properties b/Core/nbproject/project.properties
index d9f4d9824a..945b30562a 100644
--- a/Core/nbproject/project.properties
+++ b/Core/nbproject/project.properties
@@ -3,6 +3,7 @@ file.reference.apache-mime4j-core-0.8.2.jar=release\\modules\\ext\\apache-mime4j
file.reference.apache-mime4j-dom-0.8.2.jar=release\\modules\\ext\\apache-mime4j-dom-0.8.2.jar
file.reference.asm-7.0.jar=release\\modules\\ext\\asm-7.0.jar
file.reference.bcmail-jdk15on-1.60.jar=release\\modules\\ext\\bcmail-jdk15on-1.60.jar
+file.reference.bcpkix-jdk15on-1.60.jar=release\\modules\\ext\\bcpkix-jdk15on-1.60.jar
file.reference.bcprov-jdk15on-1.60.jar=release\\modules\\ext\\bcprov-jdk15on-1.60.jar
file.reference.boilerpipe-1.1.0.jar=release\\modules\\ext\\boilerpipe-1.1.0.jar
file.reference.c3p0-0.9.5.jar=release/modules/ext/c3p0-0.9.5.jar
@@ -16,7 +17,6 @@ file.reference.commons-io-2.6.jar=release\\modules\\ext\\commons-io-2.6.jar
file.reference.commons-lang3-3.8.1.jar=release\\modules\\ext\\commons-lang3-3.8.1.jar
file.reference.commons-pool2-2.4.2.jar=release/modules/ext/commons-pool2-2.4.2.jar
file.reference.cxf-rt-rs-client-3.3.0.jar=release\\modules\\ext\\cxf-rt-rs-client-3.3.0.jar
-file.reference.dd-plist-1.20.jar=release/modules/ext/dd-plist-1.20.jar
file.reference.dec-0.1.2.jar=release\\modules\\ext\\dec-0.1.2.jar
file.reference.fontbox-2.0.13.jar=release\\modules\\ext\\fontbox-2.0.13.jar
file.reference.geoapi-3.0.1.jar=release\\modules\\ext\\geoapi-3.0.1.jar
@@ -55,7 +55,7 @@ file.reference.mchange-commons-java-0.2.9.jar=release/modules/ext/mchange-common
file.reference.metadata-extractor-2.11.0.jar=release\\modules\\ext\\metadata-extractor-2.11.0.jar
file.reference.netcdf4-4.5.5.jar=release\\modules\\ext\\netcdf4-4.5.5.jar
file.reference.openjson-1.0.10.jar=release\\modules\\ext\\openjson-1.0.10.jar
-file.reference.opennlp-tools-1.9.0.jar=release\\modules\\ext\\opennlp-tools-1.9.0.jar
+file.reference.opennlp-tools-1.9.1.jar=release\\modules\\ext\\opennlp-tools-1.9.1.jar
file.reference.parso-2.0.10.jar=release\\modules\\ext\\parso-2.0.10.jar
file.reference.pdfbox-2.0.13.jar=release\\modules\\ext\\pdfbox-2.0.13.jar
file.reference.pdfbox-tools-2.0.13.jar=release\\modules\\ext\\pdfbox-tools-2.0.13.jar
diff --git a/Core/nbproject/project.xml b/Core/nbproject/project.xml
index 967399cc20..53c318a22b 100644
--- a/Core/nbproject/project.xml
+++ b/Core/nbproject/project.xml
@@ -350,49 +350,29 @@
release\modules\ext\commons-lang3-3.8.1.jar
- ext/jempbox-1.8.16.jar
- release\modules\ext\jempbox-1.8.16.jar
-
-
- ext/jackcess-2.2.0.jar
- release\modules\ext\jackcess-2.2.0.jar
-
-
- ext/jericho-html-3.3.jar
- release/modules/ext/jericho-html-3.3.jar
+ ext/gax-grpc-1.44.0.jar
+ release/modules/ext/gax-grpc-1.44.0.jar
ext/cdm-4.5.5.jar
release\modules\ext\cdm-4.5.5.jar
-
- ext/httpservices-4.5.5.jar
- release\modules\ext\httpservices-4.5.5.jar
-
-
- ext/xz-1.8.jar
- release\modules\ext\xz-1.8.jar
-
-
- ext/commons-validator-1.6.jar
- release/modules/ext/commons-validator-1.6.jar
-
ext/sis-utility-0.8.jar
release\modules\ext\sis-utility-0.8.jar
- ext/jna-5.1.0.jar
- release\modules\ext\jna-5.1.0.jar
+ ext/opencensus-api-0.19.2.jar
+ release/modules/ext/opencensus-api-0.19.2.jar
+
+
+ ext/gax-httpjson-0.61.0.jar
+ release/modules/ext/gax-httpjson-0.61.0.jar
ext/boilerpipe-1.1.0.jar
release\modules\ext\boilerpipe-1.1.0.jar
-
- ext/jbig2-imageio-3.0.2.jar
- release\modules\ext\jbig2-imageio-3.0.2.jar
-
ext/jsoup-1.11.3.jar
release\modules\ext\jsoup-1.11.3.jar
@@ -401,22 +381,10 @@
ext/sevenzipjbinding.jar
release/modules/ext/sevenzipjbinding.jar
-
- ext/apache-mime4j-dom-0.8.2.jar
- release\modules\ext\apache-mime4j-dom-0.8.2.jar
-
ext/mchange-commons-java-0.2.9.jar
release/modules/ext/mchange-commons-java-0.2.9.jar
-
- ext/pdfbox-2.0.13.jar
- release\modules\ext\pdfbox-2.0.13.jar
-
-
- ext/xmlbeans-3.0.2.jar
- release\modules\ext\xmlbeans-3.0.2.jar
-
ext/jackson-databind-2.9.7.jar
release\modules\ext\jackson-databind-2.9.7.jar
@@ -425,41 +393,33 @@
ext/jai-imageio-core-1.4.0.jar
release\modules\ext\jai-imageio-core-1.4.0.jar
+
+ ext/api-common-1.7.0.jar
+ release/modules/ext/api-common-1.7.0.jar
+
ext/jcl-over-slf4j-1.7.25.jar
release\modules\ext\jcl-over-slf4j-1.7.25.jar
- ext/curator-recipes-2.8.0.jar
- release/modules/ext/curator-recipes-2.8.0.jar
+ ext/okhttp-2.7.5.jar
+ release/modules/ext/okhttp-2.7.5.jar
ext/tika-core-1.20.jar
release\modules\ext\tika-core-1.20.jar
-
- ext/tagsoup-1.2.1.jar
- release\modules\ext\tagsoup-1.2.1.jar
-
ext/StixLib.jar
release/modules/ext/StixLib.jar
-
- ext/jackson-core-2.9.7.jar
- release\modules\ext\jackson-core-2.9.7.jar
-
-
- ext/sis-metadata-0.8.jar
- release\modules\ext\sis-metadata-0.8.jar
-
ext/bcprov-jdk15on-1.60.jar
release\modules\ext\bcprov-jdk15on-1.60.jar
- ext/parso-2.0.10.jar
- release\modules\ext\parso-2.0.10.jar
+ ext/google-auth-library-credentials-0.15.0.jar
+ release/modules/ext/google-auth-library-credentials-0.15.0.jar
ext/json-simple-1.1.1.jar
@@ -473,18 +433,10 @@
ext/commons-codec-1.11.jar
release\modules\ext\commons-codec-1.11.jar
-
- ext/apache-mime4j-core-0.8.2.jar
- release\modules\ext\apache-mime4j-core-0.8.2.jar
-
ext/jmatio-1.5.jar
release\modules\ext\jmatio-1.5.jar
-
- ext/sleuthkit-postgresql-4.6.7.jar
- release/modules/ext/sleuthkit-postgresql-4.6.7.jar
-
ext/tika-parsers-1.20.jar
release\modules\ext\tika-parsers-1.20.jar
@@ -497,18 +449,10 @@
ext/commons-pool2-2.4.2.jar
release/modules/ext/commons-pool2-2.4.2.jar
-
- ext/commons-io-2.6.jar
- release\modules\ext\commons-io-2.6.jar
-
ext/jdom-2.0.5-contrib.jar
release/modules/ext/jdom-2.0.5-contrib.jar
-
- ext/SparseBitSet-1.1.jar
- release/modules/ext/SparseBitSet-1.1.jar
-
ext/openjson-1.0.10.jar
release\modules\ext\openjson-1.0.10.jar
@@ -517,38 +461,18 @@
ext/isoparser-1.1.22.jar
release\modules\ext\isoparser-1.1.22.jar
-
- 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
-
- ext/zookeeper-3.4.6.jar
- release/modules/ext/zookeeper-3.4.6.jar
-
ext/javax.activation-1.2.0.jar
release\modules\ext\javax.activation-1.2.0.jar
-
- ext/commons-csv-1.6.jar
- release\modules\ext\commons-csv-1.6.jar
-
-
- ext/jdom-2.0.5.jar
- release/modules/ext/jdom-2.0.5.jar
-
ext/rome-1.12.0.jar
release\modules\ext\rome-1.12.0.jar
-
- ext/jackson-annotations-2.9.7.jar
- release\modules\ext\jackson-annotations-2.9.7.jar
-
ext/javax.annotation-api-1.3.2.jar
release\modules\ext\javax.annotation-api-1.3.2.jar
@@ -557,49 +481,25 @@
ext/vorbis-java-core-0.8.jar
release\modules\ext\vorbis-java-core-0.8.jar
-
- ext/netcdf4-4.5.5.jar
- release\modules\ext\netcdf4-4.5.5.jar
-
ext/java-libpst-0.8.1.jar
release\modules\ext\java-libpst-0.8.1.jar
- ext/opennlp-tools-1.9.0.jar
- release\modules\ext\opennlp-tools-1.9.0.jar
-
-
- ext/sis-netcdf-0.8.jar
- release\modules\ext\sis-netcdf-0.8.jar
+ ext/okio-1.6.0.jar
+ release/modules/ext/okio-1.6.0.jar
ext/curator-framework-2.8.0.jar
release/modules/ext/curator-framework-2.8.0.jar
-
- ext/sentiment-analysis-parser-0.1.jar
- release\modules\ext\sentiment-analysis-parser-0.1.jar
-
-
- ext/commons-collections4-4.2.jar
- release\modules\ext\commons-collections4-4.2.jar
-
ext/commons-dbcp2-2.1.1.jar
release/modules/ext/commons-dbcp2-2.1.1.jar
- ext/jgraphx-v3.8.0.jar
- release/modules/ext/jgraphx-v3.8.0.jar
-
-
- ext/juniversalchardet-1.0.3.jar
- release\modules\ext\juniversalchardet-1.0.3.jar
-
-
- ext/jython-standalone-2.7.0.jar
- release/modules/ext/jython-standalone-2.7.0.jar
+ ext/google-http-client-appengine-1.29.0.jar
+ release/modules/ext/google-http-client-appengine-1.29.0.jar
ext/uimafit-core-2.4.0.jar
@@ -609,26 +509,30 @@
ext/jackcess-encrypt-2.1.4.jar
release\modules\ext\jackcess-encrypt-2.1.4.jar
-
- ext/jhighlight-1.0.3.jar
- release\modules\ext\jhighlight-1.0.3.jar
-
ext/junrar-2.0.0.jar
release\modules\ext\junrar-2.0.0.jar
- ext/jul-to-slf4j-1.7.25.jar
- release\modules\ext\jul-to-slf4j-1.7.25.jar
+ ext/google-http-client-1.29.0.jar
+ release/modules/ext/google-http-client-1.29.0.jar
- ext/postgresql-9.4.1211.jre7.jar
- release/modules/ext/postgresql-9.4.1211.jre7.jar
+ ext/bcpkix-jdk15on-1.60.jar
+ release\modules\ext\bcpkix-jdk15on-1.60.jar
+
+
+ ext/opennlp-tools-1.9.1.jar
+ release\modules\ext\opennlp-tools-1.9.1.jar
ext/slf4j-api-1.7.25.jar
release\modules\ext\slf4j-api-1.7.25.jar
+
+ ext/google-cloud-core-1.70.0.jar
+ release/modules/ext/google-cloud-core-1.70.0.jar
+
ext/geoapi-3.0.1.jar
release\modules\ext\geoapi-3.0.1.jar
@@ -641,18 +545,10 @@
ext/jdom2-2.0.6.jar
release\modules\ext\jdom2-2.0.6.jar
-
- ext/httpclient-4.5.6.jar
- release\modules\ext\httpclient-4.5.6.jar
-
ext/uimaj-core-3.0.1.jar
release\modules\ext\uimaj-core-3.0.1.jar
-
- ext/curator-client-2.8.0.jar
- release/modules/ext/curator-client-2.8.0.jar
-
ext/sqlite-jdbc-3.25.2.jar
release/modules/ext/sqlite-jdbc-3.25.2.jar
@@ -670,65 +566,133 @@
release\modules\ext\grib-4.5.5.jar
- ext/fontbox-2.0.13.jar
- release\modules\ext\fontbox-2.0.13.jar
+ ext/gax-1.44.0.jar
+ release/modules/ext/gax-1.44.0.jar
- ext/activemq-all-5.11.1.jar
- release/modules/ext/activemq-all-5.11.1.jar
+ ext/jempbox-1.8.16.jar
+ release\modules\ext\jempbox-1.8.16.jar
- ext/dec-0.1.2.jar
- release\modules\ext\dec-0.1.2.jar
-
-
- ext/Rejistry-1.1-SNAPSHOT.jar
- release/modules/ext/Rejistry-1.1-SNAPSHOT.jar
-
-
- ext/dd-plist-1.20.jar
- release/modules/ext/dd-plist-1.20.jar
-
-
- ext/sevenzipjbinding-AllPlatforms.jar
- release/modules/ext/sevenzipjbinding-AllPlatforms.jar
-
-
- ext/bcmail-jdk15on-1.60.jar
- release\modules\ext\bcmail-jdk15on-1.60.jar
-
-
- ext/vorbis-java-tika-0.8.jar
- release\modules\ext\vorbis-java-tika-0.8.jar
+ ext/jackcess-2.2.0.jar
+ release\modules\ext\jackcess-2.2.0.jar
ext/grpc-context-1.19.0.jar
release/modules/ext/grpc-context-1.19.0.jar
- ext/gax-grpc-1.44.0.jar
- release/modules/ext/gax-grpc-1.44.0.jar
+ ext/jericho-html-3.3.jar
+ release/modules/ext/jericho-html-3.3.jar
- ext/opencensus-api-0.19.2.jar
- release/modules/ext/opencensus-api-0.19.2.jar
+ ext/httpservices-4.5.5.jar
+ release\modules\ext\httpservices-4.5.5.jar
- ext/gax-httpjson-0.61.0.jar
- release/modules/ext/gax-httpjson-0.61.0.jar
+ ext/xz-1.8.jar
+ release\modules\ext\xz-1.8.jar
- ext/api-common-1.7.0.jar
- release/modules/ext/api-common-1.7.0.jar
+ ext/commons-validator-1.6.jar
+ release/modules/ext/commons-validator-1.6.jar
- ext/google-auth-library-credentials-0.15.0.jar
- release/modules/ext/google-auth-library-credentials-0.15.0.jar
+ ext/jna-5.1.0.jar
+ release\modules\ext\jna-5.1.0.jar
+
+
+ ext/jbig2-imageio-3.0.2.jar
+ release\modules\ext\jbig2-imageio-3.0.2.jar
+
+
+ ext/sleuthkit-postgresql-4.6.7.jar
+ release/modules/ext/sleuthkit-postgresql-4.6.7.jar
+
+
+ ext/apache-mime4j-dom-0.8.2.jar
+ release\modules\ext\apache-mime4j-dom-0.8.2.jar
+
+
+ ext/pdfbox-2.0.13.jar
+ release\modules\ext\pdfbox-2.0.13.jar
+
+
+ ext/xmlbeans-3.0.2.jar
+ release\modules\ext\xmlbeans-3.0.2.jar
+
+
+ ext/curator-recipes-2.8.0.jar
+ release/modules/ext/curator-recipes-2.8.0.jar
+
+
+ ext/tagsoup-1.2.1.jar
+ release\modules\ext\tagsoup-1.2.1.jar
+
+
+ ext/jackson-core-2.9.7.jar
+ release\modules\ext\jackson-core-2.9.7.jar
+
+
+ ext/sis-metadata-0.8.jar
+ release\modules\ext\sis-metadata-0.8.jar
+
+
+ ext/parso-2.0.10.jar
+ release\modules\ext\parso-2.0.10.jar
+
+
+ ext/apache-mime4j-core-0.8.2.jar
+ release\modules\ext\apache-mime4j-core-0.8.2.jar
+
+
+ ext/commons-io-2.6.jar
+ release\modules\ext\commons-io-2.6.jar
+
+
+ ext/SparseBitSet-1.1.jar
+ release/modules/ext/SparseBitSet-1.1.jar
+
+
+ ext/c3p0-0.9.5.jar
+ release/modules/ext/c3p0-0.9.5.jar
+
+
+ ext/zookeeper-3.4.6.jar
+ release/modules/ext/zookeeper-3.4.6.jar
+
+
+ ext/commons-csv-1.6.jar
+ release\modules\ext\commons-csv-1.6.jar
+
+
+ ext/jdom-2.0.5.jar
+ release/modules/ext/jdom-2.0.5.jar
+
+
+ ext/jackson-annotations-2.9.7.jar
+ release\modules\ext\jackson-annotations-2.9.7.jar
ext/google-api-client-1.27.0.jar
release/modules/ext/google-api-client-1.27.0.jar
+
+ ext/netcdf4-4.5.5.jar
+ release\modules\ext\netcdf4-4.5.5.jar
+
+
+ ext/sis-netcdf-0.8.jar
+ release\modules\ext\sis-netcdf-0.8.jar
+
+
+ ext/sentiment-analysis-parser-0.1.jar
+ release\modules\ext\sentiment-analysis-parser-0.1.jar
+
+
+ ext/commons-collections4-4.2.jar
+ release\modules\ext\commons-collections4-4.2.jar
+
ext/opencensus-contrib-http-util-0.19.2.jar
release/modules/ext/opencensus-contrib-http-util-0.19.2.jar
@@ -738,21 +702,57 @@
release/modules/ext/google-auth-library-oauth2-http-0.15.0.jar
- ext/google-http-client-appengine-1.29.0.jar
- release/modules/ext/google-http-client-appengine-1.29.0.jar
+ ext/jgraphx-v3.8.0.jar
+ release/modules/ext/jgraphx-v3.8.0.jar
- ext/google-http-client-1.29.0.jar
- release/modules/ext/google-http-client-1.29.0.jar
+ ext/juniversalchardet-1.0.3.jar
+ release\modules\ext\juniversalchardet-1.0.3.jar
- ext/google-cloud-core-1.70.0.jar
- release/modules/ext/google-cloud-core-1.70.0.jar
+ ext/jython-standalone-2.7.0.jar
+ release/modules/ext/jython-standalone-2.7.0.jar
+
+
+ ext/jhighlight-1.0.3.jar
+ release\modules\ext\jhighlight-1.0.3.jar
+
+
+ ext/jul-to-slf4j-1.7.25.jar
+ release\modules\ext\jul-to-slf4j-1.7.25.jar
+
+
+ ext/postgresql-9.4.1211.jre7.jar
+ release/modules/ext/postgresql-9.4.1211.jre7.jar
+
+
+ ext/httpclient-4.5.6.jar
+ release\modules\ext\httpclient-4.5.6.jar
+
+
+ ext/curator-client-2.8.0.jar
+ release/modules/ext/curator-client-2.8.0.jar
+
+
+ ext/fontbox-2.0.13.jar
+ release\modules\ext\fontbox-2.0.13.jar
+
+
+ ext/activemq-all-5.11.1.jar
+ release/modules/ext/activemq-all-5.11.1.jar
ext/google-cloud-core-http-1.70.0.jar
release/modules/ext/google-cloud-core-http-1.70.0.jar
+
+ ext/Rejistry-1.1-SNAPSHOT.jar
+ release/modules/ext/Rejistry-1.1-SNAPSHOT.jar
+
+
+ ext/dec-0.1.2.jar
+ release\modules\ext\dec-0.1.2.jar
+
ext/google-http-client-jackson2-1.29.0.jar
release/modules/ext/google-http-client-jackson2-1.29.0.jar
@@ -766,20 +766,20 @@
release/modules/ext/google-cloud-translate-1.70.0.jar
- ext/gax-1.44.0.jar
- release/modules/ext/gax-1.44.0.jar
+ ext/sevenzipjbinding-AllPlatforms.jar
+ release/modules/ext/sevenzipjbinding-AllPlatforms.jar
ext/google-api-services-translate-v2-rev20170525-1.27.0.jar
release/modules/ext/google-api-services-translate-v2-rev20170525-1.27.0.jar
- ext/okhttp-2.7.5.jar
- release/modules/ext/okhttp-2.7.5.jar
+ ext/bcmail-jdk15on-1.60.jar
+ release\modules\ext\bcmail-jdk15on-1.60.jar
- ext/okio-1.6.0.jar
- release/modules/ext/okio-1.6.0.jar
+ ext/vorbis-java-tika-0.8.jar
+ release\modules\ext\vorbis-java-tika-0.8.jar
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AccessLimiterUtils.java b/Core/src/org/sleuthkit/autopsy/casemodule/AccessLimiterUtils.java
new file mode 100644
index 0000000000..3b2a201e07
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/AccessLimiterUtils.java
@@ -0,0 +1,49 @@
+/*
+ * Autopsy Forensic Browser
+ *
+ * Copyright 2019 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.nio.file.Paths;
+import org.sleuthkit.autopsy.coreutils.PlatformUtil;
+
+/**
+ * Class for methods to check if access should be limited to a feature
+ *
+ */
+final class AccessLimiterUtils {
+
+ private final static String MULTI_USER_ACCESS_FILE_NAME = "mualimit"; // NON-NLS
+ private final static String MULTI_USER_ACCESS_FILE_PATH = Paths.get(PlatformUtil.getUserConfigDirectory(), MULTI_USER_ACCESS_FILE_NAME).toString();
+
+ /**
+ * Check if privileges regarding multi-user cases should be restricted.
+ *
+ * @return True if privileges should be restricted, false otherwise.
+ */
+ static boolean limitMultiUserAccess() {
+ return new File(MULTI_USER_ACCESS_FILE_PATH).exists();
+ }
+
+ /**
+ * Private constructor for a utility class
+ */
+ private AccessLimiterUtils() {
+ //private constructer left empty intentionally
+ }
+}
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java
index f455a0c9fb..0a4586dd42 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java
@@ -1049,7 +1049,7 @@ public class Case {
/*
* Enable the case-specific actions.
*/
- CallableSystemAction.get(AddImageAction.class).setEnabled(true);
+ CallableSystemAction.get(AddImageAction.class).setEnabled(Case.getCurrentCase().getMetadata().getCaseType() == CaseType.SINGLE_USER_CASE || !AccessLimiterUtils.limitMultiUserAccess());
CallableSystemAction.get(CaseCloseAction.class).setEnabled(true);
CallableSystemAction.get(CaseDetailsAction.class).setEnabled(true);
CallableSystemAction.get(DataSourceSummaryAction.class).setEnabled(true);
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseVisualPanel1.java b/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseVisualPanel1.java
index aedbb3671f..789913d78a 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseVisualPanel1.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseVisualPanel1.java
@@ -61,7 +61,7 @@ final class NewCaseVisualPanel1 extends JPanel implements DocumentListener {
*/
void readSettings() {
caseNameTextField.setText("");
- if (UserPreferences.getIsMultiUserModeEnabled()) {
+ if (UserPreferences.getIsMultiUserModeEnabled() && !AccessLimiterUtils.limitMultiUserAccess()) {
multiUserCaseRadioButton.setEnabled(true);
multiUserCaseRadioButton.setSelected(true);
} else {
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/Services.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/Services.java
index 02f98f2887..81bc6a643c 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/services/Services.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/Services.java
@@ -80,7 +80,7 @@ public class Services implements Closeable {
/**
* Gets the artifacts blackboard for the current case.
*
- * @return @org.sleuthkit.datamodel.Blackboard Blackboard for the current
+ * @return org.sleuthkit.datamodel.Blackboard Blackboard for the current
* case.
*/
public org.sleuthkit.datamodel.Blackboard getArtifactsBlackboard() {
diff --git a/Core/src/org/sleuthkit/autopsy/commandlineingest/Bundle.properties b/Core/src/org/sleuthkit/autopsy/commandlineingest/Bundle.properties
index 8675363370..9200d5dd2f 100755
--- a/Core/src/org/sleuthkit/autopsy/commandlineingest/Bundle.properties
+++ b/Core/src/org/sleuthkit/autopsy/commandlineingest/Bundle.properties
@@ -2,16 +2,12 @@ OpenIDE-Module-Name=CommandLineAutopsy
OptionsCategory_Keywords_Command_Line_Ingest_Settings=Command Line Ingest Settings
OptionsCategory_Keywords_General=Options
OptionsCategory_Name_Command_Line_Ingest=Command Line Ingest
-CommandLineIngestSettingsPanel.ResultsDirectoryUnspecified=Output folder must be set
-CommandLineIngestSettingsPanel.PathInvalid=Path is not valid
-CommandLineIngestSettingsPanel.CannotAccess=Cannot access
-CommandLineIngestSettingsPanel.CheckPermissions=Check permissions.
-CommandLineIngestSettingsPanel.jLabelSelectOutputFolder.text=Select output folder:
-CommandLineIngestSettingsPanel.jLabelInvalidResultsFolder.text=jLabelInvalidOutputFolder
-CommandLineIngestSettingsPanel.outputPathTextField.toolTipText=Output folder for command line processing, i.e., the location where case folder will be created by command line processing mode.
-CommandLineIngestSettingsPanel.outputPathTextField.text=
-CommandLineIngestSettingsPanel.browseOutputFolderButton.text=Browse
CommandLineIngestSettingsPanel.bnEditIngestSettings.toolTipText=Ingest job settings for the command line processing mode context.
CommandLineIngestSettingsPanel.bnEditIngestSettings.text=Ingest Module Settings
CommandLinePanel.jLabel1.text=Ingest is running from command line
CommandLineStartupWindow.title.text=Running in Command Line Mode
+CommandLineIngestSettingsPanel.bnEditReportSettings.actionCommand=Report Module Settings
+CommandLineIngestSettingsPanel.bnEditReportSettings.toolTipText=Report generation settings for the command line processing mode context.
+CommandLineIngestSettingsPanel.bnEditReportSettings.text=Report Module Settings
+CommandLineIngestSettingsPanel.jLabelReportConfig.text=Configure Report Generation for Command Line Ingest:
+CommandLineIngestSettingsPanel.jLabelBaselineConfig.text=Configure Baseline Configuration for Command Line Ingest:
diff --git a/Core/src/org/sleuthkit/autopsy/commandlineingest/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/commandlineingest/Bundle.properties-MERGED
index 8675363370..9200d5dd2f 100755
--- a/Core/src/org/sleuthkit/autopsy/commandlineingest/Bundle.properties-MERGED
+++ b/Core/src/org/sleuthkit/autopsy/commandlineingest/Bundle.properties-MERGED
@@ -2,16 +2,12 @@ OpenIDE-Module-Name=CommandLineAutopsy
OptionsCategory_Keywords_Command_Line_Ingest_Settings=Command Line Ingest Settings
OptionsCategory_Keywords_General=Options
OptionsCategory_Name_Command_Line_Ingest=Command Line Ingest
-CommandLineIngestSettingsPanel.ResultsDirectoryUnspecified=Output folder must be set
-CommandLineIngestSettingsPanel.PathInvalid=Path is not valid
-CommandLineIngestSettingsPanel.CannotAccess=Cannot access
-CommandLineIngestSettingsPanel.CheckPermissions=Check permissions.
-CommandLineIngestSettingsPanel.jLabelSelectOutputFolder.text=Select output folder:
-CommandLineIngestSettingsPanel.jLabelInvalidResultsFolder.text=jLabelInvalidOutputFolder
-CommandLineIngestSettingsPanel.outputPathTextField.toolTipText=Output folder for command line processing, i.e., the location where case folder will be created by command line processing mode.
-CommandLineIngestSettingsPanel.outputPathTextField.text=
-CommandLineIngestSettingsPanel.browseOutputFolderButton.text=Browse
CommandLineIngestSettingsPanel.bnEditIngestSettings.toolTipText=Ingest job settings for the command line processing mode context.
CommandLineIngestSettingsPanel.bnEditIngestSettings.text=Ingest Module Settings
CommandLinePanel.jLabel1.text=Ingest is running from command line
CommandLineStartupWindow.title.text=Running in Command Line Mode
+CommandLineIngestSettingsPanel.bnEditReportSettings.actionCommand=Report Module Settings
+CommandLineIngestSettingsPanel.bnEditReportSettings.toolTipText=Report generation settings for the command line processing mode context.
+CommandLineIngestSettingsPanel.bnEditReportSettings.text=Report Module Settings
+CommandLineIngestSettingsPanel.jLabelReportConfig.text=Configure Report Generation for Command Line Ingest:
+CommandLineIngestSettingsPanel.jLabelBaselineConfig.text=Configure Baseline Configuration for Command Line Ingest:
diff --git a/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineCommand.java b/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineCommand.java
new file mode 100755
index 0000000000..8888ac72de
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineCommand.java
@@ -0,0 +1,82 @@
+/*
+ * Autopsy Forensic Browser
+ *
+ * Copyright 2019-2019 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.commandlineingest;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Class that contains list of input parameters passed in via command line.
+ */
+class CommandLineCommand {
+
+ /**
+ * An enumeration of command types.
+ */
+ static enum CommandType {
+ CREATE_CASE,
+ ADD_DATA_SOURCE,
+ RUN_INGEST,
+ LIST_ALL_DATA_SOURCES,
+ GENERATE_REPORTS;
+ }
+
+ /**
+ * An enumeration of input types.
+ */
+ static enum InputType {
+ CASE_NAME,
+ CASES_BASE_DIR_PATH,
+ CASE_FOLDER_PATH,
+ DATA_SOURCE_PATH,
+ DATA_SOURCE_ID,
+ INGEST_PROFILE_NAME;
+ }
+
+ private final CommandType type;
+ private final Map inputs = new HashMap<>();
+
+ CommandLineCommand(CommandType type) {
+ this.type = type;
+ }
+
+ /**
+ * Adds an parameter to the command.
+ *
+ * @param inputName Input parameter name
+ * @param inputValue Input parameter value
+ */
+ void addInputValue(String inputName, String inputValue) {
+ inputs.put(inputName, inputValue);
+ }
+
+ /**
+ * @return the inputs
+ */
+ Map getInputs() {
+ return inputs;
+ }
+
+ /**
+ * @return the type
+ */
+ CommandType getType() {
+ return type;
+ }
+}
diff --git a/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineIngestManager.java b/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineIngestManager.java
index 29faa16356..9768547546 100755
--- a/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineIngestManager.java
+++ b/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineIngestManager.java
@@ -24,11 +24,14 @@ import java.io.File;
import java.io.FilenameFilter;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.Collection;
import java.util.EnumSet;
import java.util.Iterator;
+import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import org.netbeans.spi.sendopts.OptionProcessor;
@@ -38,9 +41,11 @@ import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.CaseActionException;
import org.sleuthkit.autopsy.casemodule.CaseDetails;
import org.sleuthkit.autopsy.casemodule.CaseMetadata;
+import static org.sleuthkit.autopsy.casemodule.CaseMetadata.getFileExtension;
import org.sleuthkit.autopsy.core.RuntimeProperties;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
import static org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS;
+import static org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback.DataSourceProcessorResult.NO_ERRORS;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.TimeStampUtils;
@@ -54,21 +59,26 @@ import org.sleuthkit.autopsy.ingest.IngestJobSettings;
import org.sleuthkit.autopsy.ingest.IngestJobStartResult;
import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.autopsy.ingest.IngestModuleError;
-import org.sleuthkit.autopsy.report.ReportProgressPanel;
-import org.sleuthkit.autopsy.report.caseuco.CaseUcoFormatExporter;
-import org.sleuthkit.autopsy.report.caseuco.ReportCaseUco;
+import org.sleuthkit.autopsy.ingest.IngestProfiles;
+import org.sleuthkit.autopsy.modules.interestingitems.FilesSet;
+import org.sleuthkit.autopsy.modules.interestingitems.FilesSetsManager;
+import org.sleuthkit.autopsy.report.infrastructure.ReportProgressLogger;
+import org.sleuthkit.autopsy.report.infrastructure.ReportGenerator;
import org.sleuthkit.datamodel.Content;
+import org.sleuthkit.datamodel.TskCoreException;
/**
* Allows Autopsy to be invoked with a command line arguments. Causes Autopsy to
- * create a case, add a specified data source, run ingest on that data source,
- * produce a CASE/UCO report and exit.
+ * create a case, add a specified data source, run ingest on that data source,
+ * list all data source in a case, generate reports.
*/
public class CommandLineIngestManager {
private static final Logger LOGGER = Logger.getLogger(CommandLineIngestManager.class.getName());
private static final Set INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.CANCELLED, IngestManager.IngestJobEvent.COMPLETED);
- private Path rootOutputDirectory;
+ private Case caseForJob = null;
+ private AutoIngestDataSource dataSource = null;
+ private static final String LOG_DIR_NAME = "Command Output";
public CommandLineIngestManager() {
}
@@ -103,6 +113,10 @@ public class CommandLineIngestManager {
}
}
+ /**
+ * Requests the list of command line commands from command line options
+ * processor and executes the commands one by one.
+ */
@Override
public void run() {
LOGGER.log(Level.INFO, "Job processing task started");
@@ -110,8 +124,7 @@ public class CommandLineIngestManager {
try {
// read command line inputs
LOGGER.log(Level.INFO, "Autopsy is running from command line"); //NON-NLS
- String dataSourcePath = "";
- String baseCaseName = "";
+ List commands = null;
// first look up all OptionProcessors and get input data from CommandLineOptionProcessor
Collection extends OptionProcessor> optionProcessors = Lookup.getDefault().lookupAll(OptionProcessor.class);
@@ -120,86 +133,172 @@ public class CommandLineIngestManager {
// find CommandLineOptionProcessor
OptionProcessor processor = optionsIterator.next();
if (processor instanceof CommandLineOptionProcessor) {
- // check if we are running from command line
- dataSourcePath = ((CommandLineOptionProcessor) processor).getPathToDataSource();
- baseCaseName = ((CommandLineOptionProcessor) processor).getBaseCaseName();
+ // check if we are running from command line
+ commands = ((CommandLineOptionProcessor) processor).getCommands();
}
}
- LOGGER.log(Level.INFO, "Data source path = {0}", dataSourcePath); //NON-NLS
- LOGGER.log(Level.INFO, "Case name = {0}", baseCaseName); //NON-NLS
- System.out.println("Data source path = " + dataSourcePath);
- System.out.println("Case name = " + baseCaseName);
-
- // verify inputs
- if (dataSourcePath.isEmpty()) {
- LOGGER.log(Level.SEVERE, "Data source path not specified");
- System.out.println("Data source path not specified");
+ if (commands == null || commands.isEmpty()) {
+ LOGGER.log(Level.SEVERE, "No command line commands specified");
+ System.err.println("No command line commands specified");
return;
}
- if (baseCaseName.isEmpty()) {
- LOGGER.log(Level.SEVERE, "Case name not specified");
- System.out.println("Case name not specified");
- return;
- }
-
- if (!(new File(dataSourcePath).exists())) {
- LOGGER.log(Level.SEVERE, "Data source file not found {0}", dataSourcePath);
- System.out.println("Data source file not found " + dataSourcePath);
- return;
- }
-
- // read options panel configuration
- String rootOutputDir = UserPreferences.getCommandLineModeResultsFolder();
- LOGGER.log(Level.INFO, "Output directory = {0}", rootOutputDir); //NON-NLS
- System.out.println("Output directory = " + rootOutputDir);
-
- if (rootOutputDir.isEmpty()) {
- LOGGER.log(Level.SEVERE, "Output directory not specified, please configure Command Line Options Panel (in Tools -> Options)");
- System.out.println("Output directory not specified, please configure Command Line Options Panel (in Tools -> Options)");
- return;
- }
-
- if (!(new File(rootOutputDir).exists())) {
- LOGGER.log(Level.SEVERE, "The output directory doesn't exist {0}", rootOutputDir);
- System.out.println("The output directory doesn't exist " + rootOutputDir);
- return;
- }
- rootOutputDirectory = Paths.get(rootOutputDir);
-
- // open case
- Case caseForJob;
try {
- caseForJob = openCase(baseCaseName);
- } catch (CaseActionException ex) {
- LOGGER.log(Level.SEVERE, "Error creating or opening case " + baseCaseName, ex);
- System.out.println("Error creating or opening case " + baseCaseName);
- return;
- }
+ // Commands are already stored in order in which they should be executed
+ for (CommandLineCommand command : commands) {
+ CommandLineCommand.CommandType type = command.getType();
+ switch (type) {
+ case CREATE_CASE:
+ try {
+ LOGGER.log(Level.INFO, "Processing 'Create Case' command");
+ System.out.println("Processing 'Create Case' command");
+ Map inputs = command.getInputs();
+ String baseCaseName = inputs.get(CommandLineCommand.InputType.CASE_NAME.name());
+ String rootOutputDirectory = inputs.get(CommandLineCommand.InputType.CASES_BASE_DIR_PATH.name());
+ openCase(baseCaseName, rootOutputDirectory);
- if (caseForJob == null) {
- LOGGER.log(Level.SEVERE, "Error creating or opening case {0}", baseCaseName);
- System.out.println("Error creating or opening case " + baseCaseName);
- return;
- }
+ String outputDirPath = getOutputDirPath(caseForJob);
+ OutputGenerator.saveCreateCaseOutput(caseForJob, outputDirPath, baseCaseName);
+ } catch (CaseActionException ex) {
+ String baseCaseName = command.getInputs().get(CommandLineCommand.InputType.CASE_NAME.name());
+ LOGGER.log(Level.SEVERE, "Error creating or opening case " + baseCaseName, ex);
+ System.err.println("Error creating or opening case " + baseCaseName);
+ // Do not process any other commands
+ return;
+ }
+ break;
+ case ADD_DATA_SOURCE:
+ try {
+ LOGGER.log(Level.INFO, "Processing 'Add Data Source' command");
+ System.out.println("Processing 'Add Data Source' command");
+ Map inputs = command.getInputs();
- AutoIngestDataSource dataSource = new AutoIngestDataSource("", Paths.get(dataSourcePath));
- try {
- // run data source processor
- runDataSourceProcessor(caseForJob, dataSource);
+ // open the case, if it hasn't been already opened by CREATE_CASE command
+ if (caseForJob == null) {
+ String caseDirPath = inputs.get(CommandLineCommand.InputType.CASE_FOLDER_PATH.name());
+ openCase(caseDirPath);
+ }
- // run ingest manager
- analyze(dataSource);
+ String dataSourcePath = inputs.get(CommandLineCommand.InputType.DATA_SOURCE_PATH.name());
+ dataSource = new AutoIngestDataSource("", Paths.get(dataSourcePath));
+ runDataSourceProcessor(caseForJob, dataSource);
- // generate CASE-UCO report
- Long selectedDataSourceId = getDataSourceId(dataSource);
- Path reportFolderPath = Paths.get(caseForJob.getReportDirectory(), "CASE-UCO", "Data_Source_ID_" + selectedDataSourceId.toString() + "_" + TimeStampUtils.createTimeStamp(), ReportCaseUco.getReportFileName()); //NON_NLS
- ReportProgressPanel progressPanel = new ReportProgressPanel("CASE_UCO", rootOutputDir); // dummy progress panel
- CaseUcoFormatExporter.generateReport(selectedDataSourceId, reportFolderPath.toString(), progressPanel);
- } catch (InterruptedException | AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException | AnalysisStartupException ex) {
- LOGGER.log(Level.SEVERE, "Unable to ingest data source " + dataSourcePath + ". Exiting...", ex);
- System.out.println("Unable to ingest data source " + dataSourcePath + ". Exiting...");
+ String outputDirPath = getOutputDirPath(caseForJob);
+ OutputGenerator.saveAddDataSourceOutput(caseForJob, dataSource, outputDirPath);
+ } catch (InterruptedException | AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException | CaseActionException ex) {
+ String dataSourcePath = command.getInputs().get(CommandLineCommand.InputType.DATA_SOURCE_PATH.name());
+ LOGGER.log(Level.SEVERE, "Error adding data source " + dataSourcePath, ex);
+ System.err.println("Error adding data source " + dataSourcePath);
+ // Do not process any other commands
+ return;
+ }
+ break;
+ case RUN_INGEST:
+ try {
+ LOGGER.log(Level.INFO, "Processing 'Run Ingest' command");
+ System.out.println("Processing 'Run Ingest' command");
+ Map inputs = command.getInputs();
+
+ // open the case, if it hasn't been already opened by CREATE_CASE or ADD_DATA_SOURCE commands
+ if (caseForJob == null) {
+ String caseDirPath = inputs.get(CommandLineCommand.InputType.CASE_FOLDER_PATH.name());
+ openCase(caseDirPath);
+ }
+
+ // populate the AutoIngestDataSource structure, if that hasn't been done by ADD_DATA_SOURCE command
+ if (dataSource == null) {
+
+ String dataSourceId = inputs.get(CommandLineCommand.InputType.DATA_SOURCE_ID.name());
+ Long dataSourceObjId = Long.valueOf(dataSourceId);
+
+ // get Content object for the data source
+ Content content = null;
+ try {
+ content = Case.getCurrentCaseThrows().getSleuthkitCase().getContentById(dataSourceObjId);
+ } catch (TskCoreException ex) {
+ LOGGER.log(Level.SEVERE, "Exception while trying to find data source with object ID " + dataSourceId, ex);
+ System.err.println("Exception while trying to find data source with object ID " + dataSourceId);
+ // Do not process any other commands
+ return;
+ }
+
+ if (content == null) {
+ LOGGER.log(Level.SEVERE, "Unable to find data source with object ID {0}", dataSourceId);
+ System.out.println("Unable to find data source with object ID " + dataSourceId);
+ // Do not process any other commands
+ return;
+ }
+
+ // populate the AutoIngestDataSource structure
+ dataSource = new AutoIngestDataSource("", Paths.get(content.getName()));
+ List contentList = Arrays.asList(new Content[]{content});
+ List errorList = new ArrayList<>();
+ dataSource.setDataSourceProcessorOutput(NO_ERRORS, errorList, contentList);
+ }
+
+ // run ingest
+ String ingestProfile = inputs.get(CommandLineCommand.InputType.INGEST_PROFILE_NAME.name());
+ analyze(dataSource, ingestProfile);
+ } catch (InterruptedException | CaseActionException ex) {
+ String dataSourcePath = command.getInputs().get(CommandLineCommand.InputType.DATA_SOURCE_PATH.name());
+ LOGGER.log(Level.SEVERE, "Error running ingest on data source " + dataSourcePath, ex);
+ System.err.println("Error running ingest on data source " + dataSourcePath);
+ // Do not process any other commands
+ return;
+ }
+ break;
+
+ case LIST_ALL_DATA_SOURCES:
+ try {
+ LOGGER.log(Level.INFO, "Processing 'List All Data Sources' command");
+ System.out.println("Processing 'List All Data Sources' command");
+ Map inputs = command.getInputs();
+
+ // open the case, if it hasn't been already opened by previous command
+ if (caseForJob == null) {
+ String caseDirPath = inputs.get(CommandLineCommand.InputType.CASE_FOLDER_PATH.name());
+ openCase(caseDirPath);
+ }
+
+ String outputDirPath = getOutputDirPath(caseForJob);
+ OutputGenerator.listAllDataSources(caseForJob, outputDirPath);
+ } catch (CaseActionException ex) {
+ String caseDirPath = command.getInputs().get(CommandLineCommand.InputType.CASE_FOLDER_PATH.name());
+ LOGGER.log(Level.SEVERE, "Error opening case in case directory: " + caseDirPath, ex);
+ System.err.println("Error opening case in case directory: " + caseDirPath);
+ // Do not process any other commands
+ return;
+ }
+ break;
+
+ case GENERATE_REPORTS:
+ try {
+ LOGGER.log(Level.INFO, "Processing 'Generate Reports' command");
+ System.out.println("Processing 'Generate Reports' command");
+ Map inputs = command.getInputs();
+
+ // open the case, if it hasn't been already opened by previous command
+ if (caseForJob == null) {
+ String caseDirPath = inputs.get(CommandLineCommand.InputType.CASE_FOLDER_PATH.name());
+ openCase(caseDirPath);
+ }
+
+ // generate reports
+ ReportGenerator generator = new ReportGenerator(CommandLineIngestSettingsPanel.getReportingConfigName(), new ReportProgressLogger()); //NON-NLS
+ generator.generateReports();
+ } catch (CaseActionException ex) {
+ String caseDirPath = command.getInputs().get(CommandLineCommand.InputType.CASE_FOLDER_PATH.name());
+ LOGGER.log(Level.SEVERE, "Error opening case in case directory: " + caseDirPath, ex);
+ System.err.println("Error opening case in case directory: " + caseDirPath);
+ // Do not process any other commands
+ return;
+ }
+ break;
+ default:
+ break;
+ }
+ }
} catch (Throwable ex) {
/*
* Unexpected runtime exceptions firewall. This task is
@@ -208,15 +307,15 @@ public class CommandLineIngestManager {
* Future, so this ensures that such errors get
* logged.
*/
- LOGGER.log(Level.SEVERE, "Unexpected error while ingesting data source " + dataSourcePath, ex);
- System.out.println("Unexpected error while ingesting data source " + dataSourcePath + ". Exiting...");
+ LOGGER.log(Level.SEVERE, "Unexpected error", ex);
+ System.err.println("Unexpected error. Exiting...");
} finally {
try {
Case.closeCurrentCase();
} catch (CaseActionException ex) {
LOGGER.log(Level.WARNING, "Exception while closing case", ex);
- System.out.println("Exception while closing case");
+ System.err.println("Exception while closing case");
}
}
@@ -230,29 +329,24 @@ public class CommandLineIngestManager {
}
/**
- * Provides object ID of the data source by reading it from Content
- * object.
+ * Creates a new case using arguments passed in from command line
+ * CREATE_CASE command.
*
- * @param dataSource DataSource object
- *
- * @return object ID
+ * @param baseCaseName Case name
+ * @param rootOutputDirectory Full path to directory in which case
+ * output folder will be created
+ * @throws CaseActionException
*/
- private Long getDataSourceId(AutoIngestDataSource dataSource) {
- Content content = dataSource.getContent().get(0);
- return content.getId();
- }
+ private void openCase(String baseCaseName, String rootOutputDirectory) throws CaseActionException {
- private Case openCase(String baseCaseName) throws CaseActionException {
-
- LOGGER.log(Level.INFO, "Opening case {0}", baseCaseName);
-
- Path caseDirectoryPath = findCaseDirectory(rootOutputDirectory, baseCaseName);
+ LOGGER.log(Level.INFO, "Opening case {0} in directory {1}", new Object[]{baseCaseName, rootOutputDirectory});
+ Path caseDirectoryPath = findCaseDirectory(Paths.get(rootOutputDirectory), baseCaseName);
if (null != caseDirectoryPath) {
// found an existing case directory for same case name. the input case name must be unique. Exit.
LOGGER.log(Level.SEVERE, "Case {0} already exists. Case name must be unique. Exiting", baseCaseName);
throw new CaseActionException("Case " + baseCaseName + " already exists. Case name must be unique. Exiting");
} else {
- caseDirectoryPath = createCaseFolderPath(rootOutputDirectory, baseCaseName);
+ caseDirectoryPath = createCaseFolderPath(Paths.get(rootOutputDirectory), baseCaseName);
// Create the case directory
Case.createCaseDirectory(caseDirectoryPath.toString(), Case.CaseType.SINGLE_USER_CASE);
@@ -261,9 +355,56 @@ public class CommandLineIngestManager {
Case.createAsCurrentCase(Case.CaseType.SINGLE_USER_CASE, caseDirectoryPath.toString(), caseDetails);
}
- Case caseForJob = Case.getCurrentCase();
+ caseForJob = Case.getCurrentCase();
LOGGER.log(Level.INFO, "Opened case {0}", caseForJob.getName());
- return caseForJob;
+ }
+
+ /**
+ * Opens existing case.
+ *
+ * @param caseFolderPath full path to case directory
+ * @throws CaseActionException
+ */
+ private void openCase(String caseFolderPath) throws CaseActionException {
+
+ LOGGER.log(Level.INFO, "Opening case in directory {0}", caseFolderPath);
+
+ String metadataFilePath = findAutFile(caseFolderPath);
+ Case.openAsCurrentCase(metadataFilePath);
+
+ caseForJob = Case.getCurrentCase();
+ LOGGER.log(Level.INFO, "Opened case {0}", caseForJob.getName());
+ }
+
+ /**
+ * Finds the path to the .aut file for the specified case directory.
+ *
+ * @param caseDirectory the directory to check for a .aut file
+ *
+ * @return the path to the first .aut file found in the directory
+ *
+ * @throws CaseActionException if there was an issue finding a .aut file
+ */
+ private String findAutFile(String caseDirectory) throws CaseActionException {
+ File caseFolder = Paths.get(caseDirectory).toFile();
+ if (caseFolder.exists()) {
+ /*
+ * Search for '*.aut' files.
+ */
+ File[] fileArray = caseFolder.listFiles();
+ if (fileArray == null) {
+ throw new CaseActionException("No files found in case directory");
+ }
+ String autFilePath = null;
+ for (File file : fileArray) {
+ String name = file.getName().toLowerCase();
+ if (autFilePath == null && name.endsWith(getFileExtension())) {
+ return file.getAbsolutePath();
+ }
+ }
+ throw new CaseActionException("No .aut files found in case directory");
+ }
+ throw new CaseActionException("Case directory was not found");
}
/**
@@ -375,9 +516,12 @@ public class CommandLineIngestManager {
/**
* Analyzes the data source content returned by the data source
* processor using the configured set of data source level and file
- * level analysis modules.
+ * level analysis modules. If an ingest profile is specified, load that
+ * profile (profile = ingest context + ingest filter) for ingest.
+ * Otherwise use baseline configuration.
*
* @param dataSource The data source to analyze.
+ * @param ingestProfileName Name of ingest profile to use (optional)
*
* @throws AnalysisStartupException if there is an error analyzing the
* data source.
@@ -385,14 +529,46 @@ public class CommandLineIngestManager {
* task is interrupted while blocked, i.e., if auto ingest is shutting
* down.
*/
- private void analyze(AutoIngestDataSource dataSource) throws AnalysisStartupException, InterruptedException {
+ private void analyze(AutoIngestDataSource dataSource, String ingestProfileName) throws AnalysisStartupException, InterruptedException {
LOGGER.log(Level.INFO, "Starting ingest modules analysis for {0} ", dataSource.getPath());
+
+ // configure ingest profile and file filter
+ IngestProfiles.IngestProfile selectedProfile = null;
+ FilesSet selectedFileSet = null;
+ if (!ingestProfileName.isEmpty()) {
+ selectedProfile = getSelectedProfile(ingestProfileName);
+ if (selectedProfile == null) {
+ // unable to find the user specified profile
+ LOGGER.log(Level.SEVERE, "Unable to find ingest profile: {0}. Ingest cancelled!", ingestProfileName);
+ System.err.println("Unable to find ingest profile: " + ingestProfileName + ". Ingest cancelled!");
+ return;
+ }
+
+ // get FileSet filter associated with this profile
+ selectedFileSet = getSelectedFilter(selectedProfile.getFileIngestFilter());
+ if (selectedFileSet == null) {
+ // unable to find the user specified profile
+ LOGGER.log(Level.SEVERE, "Unable to find file filter {0} for ingest profile: {1}. Ingest cancelled!", new Object[]{selectedProfile.getFileIngestFilter(), ingestProfileName});
+ System.err.println("Unable to find file filter " + selectedProfile.getFileIngestFilter() + " for ingest profile: " + ingestProfileName + ". Ingest cancelled!");
+ return;
+ }
+ }
+
IngestJobEventListener ingestJobEventListener = new IngestJobEventListener();
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, ingestJobEventListener);
try {
synchronized (ingestLock) {
- IngestJobSettings ingestJobSettings = new IngestJobSettings(UserPreferences.getCommandLineModeIngestModuleContextString());
+ IngestJobSettings ingestJobSettings;
+ if (selectedProfile == null || selectedFileSet == null) {
+ // use baseline configuration
+ ingestJobSettings = new IngestJobSettings(UserPreferences.getCommandLineModeIngestModuleContextString());
+ } else {
+ // load the custom ingest
+ ingestJobSettings = new IngestJobSettings(selectedProfile.toString());
+ ingestJobSettings.setFileFilter(selectedFileSet);
+ }
+
List settingsWarnings = ingestJobSettings.getWarnings();
if (settingsWarnings.isEmpty()) {
IngestJobStartResult ingestJobStartResult = IngestManager.getInstance().beginIngestJob(dataSource.getContent(), ingestJobSettings);
@@ -447,6 +623,48 @@ public class CommandLineIngestManager {
}
}
+ /**
+ * Gets the specified ingest profile from the list of all existing
+ * ingest profiles.
+ *
+ * @param ingestProfileName Ingest profile name
+ * @return IngestProfile object, or NULL if the profile doesn't exist
+ */
+ private IngestProfiles.IngestProfile getSelectedProfile(String ingestProfileName) {
+
+ IngestProfiles.IngestProfile selectedProfile = null;
+ // lookup the profile by name
+ for (IngestProfiles.IngestProfile profile : IngestProfiles.getIngestProfiles()) {
+ if (profile.toString().equalsIgnoreCase(ingestProfileName)) {
+ // found the profile
+ selectedProfile = profile;
+ break;
+ }
+ }
+ return selectedProfile;
+ }
+
+ /**
+ * Gets the specified file filter from the list of all existing file
+ * filters (custom and standard).
+ *
+ * @param filterName Name of the file filter
+ * @return FilesSet object, or NULL if the filter doesn't exist
+ */
+ private FilesSet getSelectedFilter(String filterName) {
+ try {
+ Map fileIngestFilters = FilesSetsManager.getInstance()
+ .getCustomFileIngestFilters();
+ for (FilesSet fSet : FilesSetsManager.getStandardFileIngestFilters()) {
+ fileIngestFilters.put(fSet.getName(), fSet);
+ }
+ return fileIngestFilters.get(filterName);
+ } catch (FilesSetsManager.FilesSetsManagerException ex) {
+ LOGGER.log(Level.SEVERE, "Failed to get file ingest filter: " + filterName, ex); //NON-NLS
+ return null;
+ }
+ }
+
/**
* Creates a case folder path. Does not create the folder described by
* the path.
@@ -456,7 +674,7 @@ public class CommandLineIngestManager {
*
* @return A case folder path with a time stamp suffix.
*/
- Path createCaseFolderPath(Path caseFoldersPath, String caseName) {
+ private Path createCaseFolderPath(Path caseFoldersPath, String caseName) {
String folderName = caseName + "_" + TimeStampUtils.createTimeStamp();
return Paths.get(caseFoldersPath.toString(), folderName);
}
@@ -471,7 +689,7 @@ public class CommandLineIngestManager {
*
* @return The path of the case folder, or null if it is not found.
*/
- Path findCaseDirectory(Path folderToSearch, String caseName) {
+ private Path findCaseDirectory(Path folderToSearch, String caseName) {
File searchFolder = new File(folderToSearch.toString());
if (!searchFolder.isDirectory()) {
return null;
@@ -489,6 +707,16 @@ public class CommandLineIngestManager {
return caseFolderPath;
}
+ /**
+ * Returns full path to directory where command outputs should be saved.
+ *
+ * @param caseForJob Case object
+ * @return Full path to directory where command outputs should be saved
+ */
+ private String getOutputDirPath(Case caseForJob) {
+ return caseForJob.getCaseDirectory() + File.separator + LOG_DIR_NAME;
+ }
+
/**
* An ingest job event listener that allows the job processing task to
* block until the analysis of a data source by the data source level
diff --git a/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineIngestSettingsPanel.form b/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineIngestSettingsPanel.form
index 2333564f89..ea8344c216 100755
--- a/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineIngestSettingsPanel.form
+++ b/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineIngestSettingsPanel.form
@@ -1,6 +1,11 @@