mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-17 02:07:42 +00:00
Merge branch 'develop' into cleanup-file-types-tree-abit
This commit is contained in:
commit
2b299999ca
1
.gitignore
vendored
1
.gitignore
vendored
@ -76,4 +76,5 @@ hs_err_pid*.log
|
||||
/ImageGallery/release/
|
||||
/thunderbirdparser/release/
|
||||
/RecentActivity/release/
|
||||
/CentralRepository/release/
|
||||
|
||||
|
BIN
CentralRepository/Central Repository User Guide.pdf
Normal file
BIN
CentralRepository/Central Repository User Guide.pdf
Normal file
Binary file not shown.
31
CentralRepository/build.xml
Normal file
31
CentralRepository/build.xml
Normal file
@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- You may freely edit this file. See harness/README in the NetBeans platform -->
|
||||
<!-- for some information on what you could do (e.g. targets to override). -->
|
||||
<!-- If you delete this file and reopen the project it will be recreated. -->
|
||||
<project name="org.sleuthkit.autopsy.centralrepository" default="netbeans" basedir="." xmlns:ivy="antlib:org.apache.ivy.ant">
|
||||
<description>Builds, tests, and runs the project org.sleuthkit.autopsy.centralrepository.</description>
|
||||
<import file="nbproject/build-impl.xml"/>
|
||||
<import file="../BootstrapIvy.xml"/>
|
||||
|
||||
<property name="thirdparty.dir" value="${basedir}/../thirdparty" />
|
||||
<property name="modules.dir" value="${basedir}/release/modules/" />
|
||||
<property name="ext.dir" value="${modules.dir}/ext" />
|
||||
|
||||
<target name="resolve">
|
||||
<ivy:settings file="ivysettings.xml" />
|
||||
<ivy:resolve file="ivy.xml" conf="central-repository"/>
|
||||
</target>
|
||||
|
||||
<target name="retrieve" depends="resolve">
|
||||
<ivy:retrieve conf="central-repository" pattern="${basedir}/release/modules/ext/[artifact]-[revision](-[classifier]).[ext]" />
|
||||
</target>
|
||||
|
||||
<target name="init" depends="retrieve, harness.init" />
|
||||
|
||||
<target name="clean" depends="projectized-common.clean">
|
||||
<!--Override clean to delete jars, etc downloaded with Ivy
|
||||
or copied in from thirdparty folder. This way we don't end up with
|
||||
out-of-date/unneeded stuff in the installer-->
|
||||
<delete dir="${basedir}/release"/>
|
||||
</target>
|
||||
</project>
|
15
CentralRepository/ivy.xml
Normal file
15
CentralRepository/ivy.xml
Normal file
@ -0,0 +1,15 @@
|
||||
<ivy-module version="2.0">
|
||||
<info organisation="org.sleuthkit.autopsy" module="centralrepository"/>
|
||||
<configurations >
|
||||
<!-- module dependencies -->
|
||||
<conf name="central-repository"/>
|
||||
</configurations>
|
||||
<dependencies>
|
||||
<!-- for enterprise artifacts manager -->
|
||||
<dependency conf="central-repository->default" org="org.apache.commons" name="commons-dbcp2" rev="2.1.1"/>
|
||||
<dependency conf="central-repository->default" org="commons-logging" name="commons-logging" rev="1.2"/>
|
||||
<dependency conf="central-repository->default" org="org.apache.commons" name="commons-pool2" rev="2.4.2"/>
|
||||
<dependency conf="central-repository->default" org="org.postgresql" name="postgresql" rev="42.1.1"/>
|
||||
<dependency conf="central-repository->default" org="org.xerial" name="sqlite-jdbc" rev="3.16.1"/>
|
||||
</dependencies>
|
||||
</ivy-module>
|
10
CentralRepository/ivysettings.xml
Normal file
10
CentralRepository/ivysettings.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<ivysettings>
|
||||
<settings defaultResolver="main"/>
|
||||
<resolvers>
|
||||
<chain name="main">
|
||||
<ibiblio name="central" m2compatible="true"/>
|
||||
<ibiblio name="ibiblio" m2compatible="true"/>
|
||||
<ibiblio name="xerial" m2compatible="true" root="http://www.xerial.org/maven/repository/snapshot" />
|
||||
</chain>
|
||||
</resolvers>
|
||||
</ivysettings>
|
6
CentralRepository/manifest.mf
Normal file
6
CentralRepository/manifest.mf
Normal file
@ -0,0 +1,6 @@
|
||||
Manifest-Version: 1.0
|
||||
AutoUpdate-Show-In-Client: true
|
||||
OpenIDE-Module: org.sleuthkit.autopsy.centralrepository
|
||||
OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/centralrepository/Bundle.properties
|
||||
OpenIDE-Module-Specification-Version: 1.0
|
||||
OpenIDE-Module-Install: org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.class
|
45
CentralRepository/nbproject/build-impl.xml
Normal file
45
CentralRepository/nbproject/build-impl.xml
Normal file
@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
*** GENERATED FROM project.xml - DO NOT EDIT ***
|
||||
*** EDIT ../build.xml INSTEAD ***
|
||||
-->
|
||||
<project name="org.sleuthkit.autopsy.centralrepository-impl" basedir="..">
|
||||
<fail message="Please build using Ant 1.7.1 or higher.">
|
||||
<condition>
|
||||
<not>
|
||||
<antversion atleast="1.7.1"/>
|
||||
</not>
|
||||
</condition>
|
||||
</fail>
|
||||
<property file="nbproject/private/suite-private.properties"/>
|
||||
<property file="nbproject/suite.properties"/>
|
||||
<fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail>
|
||||
<property file="${suite.dir}/nbproject/private/platform-private.properties"/>
|
||||
<property file="${suite.dir}/nbproject/platform.properties"/>
|
||||
<macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2">
|
||||
<attribute name="name"/>
|
||||
<attribute name="value"/>
|
||||
<sequential>
|
||||
<property name="@{name}" value="${@{value}}"/>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
<macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-project/2">
|
||||
<attribute name="property"/>
|
||||
<attribute name="value"/>
|
||||
<sequential>
|
||||
<property name="@{property}" value="@{value}"/>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
<property file="${user.properties.file}"/>
|
||||
<nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
|
||||
<nbmproject2:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
|
||||
<nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
|
||||
<fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness).">
|
||||
<condition>
|
||||
<not>
|
||||
<contains string="${cluster.path.evaluated}" substring="platform"/>
|
||||
</not>
|
||||
</condition>
|
||||
</fail>
|
||||
<import file="${harness.dir}/build.xml"/>
|
||||
</project>
|
9
CentralRepository/nbproject/project.properties
Normal file
9
CentralRepository/nbproject/project.properties
Normal file
@ -0,0 +1,9 @@
|
||||
file.reference.commons-dbcp2-2.1.1.jar=release/modules/ext/commons-dbcp2-2.1.1.jar
|
||||
file.reference.commons-logging-1.2.jar=release/modules/ext/commons-logging-1.2.jar
|
||||
file.reference.commons-pool2-2.4.2.jar=release/modules/ext/commons-pool2-2.4.2.jar
|
||||
file.reference.postgresql-42.1.1.jar=release/modules/ext/postgresql-42.1.1.jar
|
||||
file.reference.sqlite-jdbc-3.16.1.jar=release/modules/ext/sqlite-jdbc-3.16.1.jar
|
||||
javac.source=1.8
|
||||
javac.compilerargs=-Xlint -Xlint:-serial
|
||||
license.file=../LICENSE-2.0.txt
|
||||
nbm.homepage=http://www.sleuthkit.org/autopsy/
|
116
CentralRepository/nbproject/project.xml
Normal file
116
CentralRepository/nbproject/project.xml
Normal file
@ -0,0 +1,116 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://www.netbeans.org/ns/project/1">
|
||||
<type>org.netbeans.modules.apisupport.project</type>
|
||||
<configuration>
|
||||
<data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
|
||||
<code-name-base>org.sleuthkit.autopsy.centralrepository</code-name-base>
|
||||
<suite-component/>
|
||||
<module-dependencies>
|
||||
<dependency>
|
||||
<code-name-base>org.netbeans.api.progress</code-name-base>
|
||||
<build-prerequisite/>
|
||||
<compile-dependency/>
|
||||
<run-dependency>
|
||||
<release-version>1</release-version>
|
||||
<specification-version>1.47.1</specification-version>
|
||||
</run-dependency>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<code-name-base>org.netbeans.modules.options.api</code-name-base>
|
||||
<build-prerequisite/>
|
||||
<compile-dependency/>
|
||||
<run-dependency>
|
||||
<release-version>1</release-version>
|
||||
<specification-version>1.45.1</specification-version>
|
||||
</run-dependency>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<code-name-base>org.openide.awt</code-name-base>
|
||||
<build-prerequisite/>
|
||||
<compile-dependency/>
|
||||
<run-dependency>
|
||||
<specification-version>7.67.1</specification-version>
|
||||
</run-dependency>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<code-name-base>org.openide.modules</code-name-base>
|
||||
<build-prerequisite/>
|
||||
<compile-dependency/>
|
||||
<run-dependency>
|
||||
<specification-version>7.48.1</specification-version>
|
||||
</run-dependency>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<code-name-base>org.openide.nodes</code-name-base>
|
||||
<build-prerequisite/>
|
||||
<compile-dependency/>
|
||||
<run-dependency>
|
||||
<specification-version>7.45.1</specification-version>
|
||||
</run-dependency>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<code-name-base>org.openide.util</code-name-base>
|
||||
<build-prerequisite/>
|
||||
<compile-dependency/>
|
||||
<run-dependency>
|
||||
<specification-version>9.7.1</specification-version>
|
||||
</run-dependency>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<code-name-base>org.openide.util.lookup</code-name-base>
|
||||
<build-prerequisite/>
|
||||
<compile-dependency/>
|
||||
<run-dependency>
|
||||
<specification-version>8.33.1</specification-version>
|
||||
</run-dependency>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<code-name-base>org.openide.util.ui</code-name-base>
|
||||
<build-prerequisite/>
|
||||
<compile-dependency/>
|
||||
<run-dependency>
|
||||
<specification-version>9.6.1</specification-version>
|
||||
</run-dependency>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<code-name-base>org.openide.windows</code-name-base>
|
||||
<build-prerequisite/>
|
||||
<compile-dependency/>
|
||||
<run-dependency>
|
||||
<specification-version>6.75.1</specification-version>
|
||||
</run-dependency>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<code-name-base>org.sleuthkit.autopsy.core</code-name-base>
|
||||
<build-prerequisite/>
|
||||
<compile-dependency/>
|
||||
<run-dependency>
|
||||
<release-version>10</release-version>
|
||||
<specification-version>10.8</specification-version>
|
||||
</run-dependency>
|
||||
</dependency>
|
||||
</module-dependencies>
|
||||
<public-packages/>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/sqlite-jdbc-3.16.1.jar</runtime-relative-path>
|
||||
<binary-origin>release\modules\ext\sqlite-jdbc-3.16.1.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/commons-dbcp2-2.1.1.jar</runtime-relative-path>
|
||||
<binary-origin>release\modules\ext\commons-dbcp2-2.1.1.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/postgresql-42.1.1.jar</runtime-relative-path>
|
||||
<binary-origin>release\modules\ext\postgresql-42.1.1.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/commons-pool2-2.4.2.jar</runtime-relative-path>
|
||||
<binary-origin>release\modules\ext\commons-pool2-2.4.2.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/commons-logging-1.2.jar</runtime-relative-path>
|
||||
<binary-origin>release\modules\ext\commons-logging-1.2.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
</data>
|
||||
</configuration>
|
||||
</project>
|
1
CentralRepository/nbproject/suite.properties
Normal file
1
CentralRepository/nbproject/suite.properties
Normal file
@ -0,0 +1 @@
|
||||
suite.dir=${basedir}/..
|
@ -0,0 +1,7 @@
|
||||
OpenIDE-Module-Name=Central Repository
|
||||
OpenIDE-Module-Display-Category=Ingest Module
|
||||
OpenIDE-Module-Short-Description=Correlation Engine Ingest Module
|
||||
OpenIDE-Module-Long-Description=\
|
||||
Correlation Engine ingest module and central database. \n\n\
|
||||
The Correlation Engine ingest module stores attributes of artifacts matching selected correlation types into a central database.\n\
|
||||
Stored attributes are used in future cases to correlate and analyzes files and artifacts during ingest.
|
@ -66,7 +66,7 @@
|
||||
<Component class="javax.swing.JButton" name="bnClose">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/actions/Bundle.properties" key="EamCaseEditDetailsDialog.bnClose.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/actions/Bundle.properties" key="EamCaseEditDetailsDialog.bnClose.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
@ -76,7 +76,7 @@
|
||||
<Component class="javax.swing.JButton" name="bnOk">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/actions/Bundle.properties" key="EamCaseEditDetailsDialog.bnOk.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/actions/Bundle.properties" key="EamCaseEditDetailsDialog.bnOk.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
@ -88,7 +88,7 @@
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
|
||||
<TitledBorder title="Case Metadata">
|
||||
<ResourceString PropertyName="titleX" bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/actions/Bundle.properties" key="EamCaseEditDetailsDialog.pnCaseMetadata.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString PropertyName="titleX" bundle="org/sleuthkit/autopsy/centralrepository/actions/Bundle.properties" key="EamCaseEditDetailsDialog.pnCaseMetadata.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<Font PropertyName="font" name="Tahoma" size="12" style="0"/>
|
||||
</TitledBorder>
|
||||
</Border>
|
||||
@ -149,28 +149,28 @@
|
||||
<Component class="javax.swing.JLabel" name="lbCaseNameLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/actions/Bundle.properties" key="EamCaseEditDetailsDialog.lbCaseNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/actions/Bundle.properties" key="EamCaseEditDetailsDialog.lbCaseNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lbCreationDateLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/actions/Bundle.properties" key="EamCaseEditDetailsDialog.lbCreationDateLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/actions/Bundle.properties" key="EamCaseEditDetailsDialog.lbCreationDateLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lbCaseNumberLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/actions/Bundle.properties" key="EamCaseEditDetailsDialog.lbCaseNumberLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/actions/Bundle.properties" key="EamCaseEditDetailsDialog.lbCaseNumberLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lbCaseUUIDLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/actions/Bundle.properties" key="EamCaseEditDetailsDialog.lbCaseUUIDLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/actions/Bundle.properties" key="EamCaseEditDetailsDialog.lbCaseUUIDLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
@ -189,7 +189,7 @@
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
|
||||
<TitledBorder title="Organization">
|
||||
<ResourceString PropertyName="titleX" bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/actions/Bundle.properties" key="EamCaseEditDetailsDialog.pnOrganization.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString PropertyName="titleX" bundle="org/sleuthkit/autopsy/centralrepository/actions/Bundle.properties" key="EamCaseEditDetailsDialog.pnOrganization.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<Font PropertyName="font" name="Tahoma" size="12" style="0"/>
|
||||
</TitledBorder>
|
||||
</Border>
|
||||
@ -272,7 +272,7 @@
|
||||
<Component class="javax.swing.JLabel" name="lbOrganizationNameLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/actions/Bundle.properties" key="EamCaseEditDetailsDialog.lbOrganizationNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/actions/Bundle.properties" key="EamCaseEditDetailsDialog.lbOrganizationNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
@ -292,28 +292,28 @@
|
||||
<Component class="javax.swing.JLabel" name="lbPointOfContactGroupLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/actions/Bundle.properties" key="EamCaseEditDetailsDialog.lbPointOfContactGroupLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/actions/Bundle.properties" key="EamCaseEditDetailsDialog.lbPointOfContactGroupLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lbPointOfContactNameLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/actions/Bundle.properties" key="EamCaseEditDetailsDialog.lbPointOfContactNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/actions/Bundle.properties" key="EamCaseEditDetailsDialog.lbPointOfContactNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lbPointOfContactEmailLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/actions/Bundle.properties" key="EamCaseEditDetailsDialog.lbPointOfContactEmailLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/actions/Bundle.properties" key="EamCaseEditDetailsDialog.lbPointOfContactEmailLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lbPointOfContactPhoneLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/actions/Bundle.properties" key="EamCaseEditDetailsDialog.lbPointOfContactPhoneLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/actions/Bundle.properties" key="EamCaseEditDetailsDialog.lbPointOfContactPhoneLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
@ -326,7 +326,7 @@
|
||||
<Component class="javax.swing.JButton" name="bnNewOrganization">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/actions/Bundle.properties" key="EamCaseEditDetailsDialog.bnNewOrganization.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/actions/Bundle.properties" key="EamCaseEditDetailsDialog.bnNewOrganization.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
@ -340,7 +340,7 @@
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
|
||||
<TitledBorder title="Examiner">
|
||||
<ResourceString PropertyName="titleX" bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/actions/Bundle.properties" key="EamCaseEditDetailsDialog.pnExaminer.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString PropertyName="titleX" bundle="org/sleuthkit/autopsy/centralrepository/actions/Bundle.properties" key="EamCaseEditDetailsDialog.pnExaminer.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<Font PropertyName="font" name="Tahoma" size="12" style="0"/>
|
||||
</TitledBorder>
|
||||
</Border>
|
||||
@ -401,7 +401,7 @@
|
||||
<Component class="javax.swing.JLabel" name="lbExaminerNameLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/actions/Bundle.properties" key="EamCaseEditDetailsDialog.lbExaminerNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/actions/Bundle.properties" key="EamCaseEditDetailsDialog.lbExaminerNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
@ -410,7 +410,7 @@
|
||||
<Component class="javax.swing.JLabel" name="lbExaminerEmailLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/actions/Bundle.properties" key="EamCaseEditDetailsDialog.lbExaminerEmailLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/actions/Bundle.properties" key="EamCaseEditDetailsDialog.lbExaminerEmailLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
@ -419,7 +419,7 @@
|
||||
<Component class="javax.swing.JLabel" name="lbExaminerPhoneLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/actions/Bundle.properties" key="EamCaseEditDetailsDialog.lbExaminerPhoneLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/actions/Bundle.properties" key="EamCaseEditDetailsDialog.lbExaminerPhoneLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
@ -428,7 +428,7 @@
|
||||
<Component class="javax.swing.JLabel" name="lbNotesLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/actions/Bundle.properties" key="EamCaseEditDetailsDialog.lbNotesLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/actions/Bundle.properties" key="EamCaseEditDetailsDialog.lbNotesLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Enterprise Artifacts Manager
|
||||
* Central Repository
|
||||
*
|
||||
* Copyright 2015-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
@ -16,12 +16,11 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.actions;
|
||||
package org.sleuthkit.autopsy.centralrepository.actions;
|
||||
|
||||
import java.awt.Cursor;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
@ -34,18 +33,17 @@ import javax.swing.JTextArea;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
import org.openide.util.Exceptions;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.openide.windows.WindowManager;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamCase;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDbException;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamOrganization;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.optionspanel.AddNewOrganizationDialog;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDb;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamCase;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamOrganization;
|
||||
import org.sleuthkit.autopsy.centralrepository.optionspanel.AddNewOrganizationDialog;
|
||||
|
||||
/**
|
||||
* Handle editing details of cases within the Enterprise Artifacts Manager
|
||||
* Handle editing details of cases within the Central Repository
|
||||
*/
|
||||
public class EamCaseEditDetailsDialog extends JDialog {
|
||||
|
||||
@ -61,12 +59,12 @@ public class EamCaseEditDetailsDialog extends JDialog {
|
||||
private boolean comboboxOrganizationActionListenerActive;
|
||||
|
||||
/**
|
||||
* Creates new form EnterpriseArtifactsManagerCasedEditDetailsForm
|
||||
* Creates new EamCaseEditDetailsDialog form
|
||||
*/
|
||||
@Messages({"EnterpriseArtifactsManagerCaseEditDetails.window.title=Edit Case Details"})
|
||||
@Messages({"EamCaseEditDetailsDialog.window.title=Central Repository Case Properties"})
|
||||
public EamCaseEditDetailsDialog() {
|
||||
super((JFrame) WindowManager.getDefault().getMainWindow(),
|
||||
Bundle.EnterpriseArtifactsManagerCaseEditDetails_window_title(),
|
||||
Bundle.EamCaseEditDetailsDialog_window_title(),
|
||||
true); // NON-NLS
|
||||
|
||||
try {
|
||||
@ -414,7 +412,7 @@ public class EamCaseEditDetailsDialog extends JDialog {
|
||||
|
||||
private void bnOkActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnOkActionPerformed
|
||||
if (contentChanged) {
|
||||
updateEnterpriseArtifactsManagerCase();
|
||||
updateEamCase();
|
||||
updateDb();
|
||||
}
|
||||
dispose();
|
||||
@ -513,7 +511,7 @@ public class EamCaseEditDetailsDialog extends JDialog {
|
||||
* Save changed value from text fields and text areas into the EamCase
|
||||
* object.
|
||||
*/
|
||||
private void updateEnterpriseArtifactsManagerCase() {
|
||||
private void updateEamCase() {
|
||||
eamCase.setOrg(selectedOrg);
|
||||
eamCase.setExaminerName(tfExaminerNameText.getText());
|
||||
eamCase.setExaminerEmail(tfExaminerEmailText.getText());
|
||||
@ -525,14 +523,14 @@ public class EamCaseEditDetailsDialog extends JDialog {
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
|
||||
if (!EamDb.isEnabled()) {
|
||||
LOGGER.log(Level.SEVERE, "Enteprise artifacts manager database not enabled"); // NON-NLS
|
||||
LOGGER.log(Level.SEVERE, "Central Repository database not enabled"); // NON-NLS
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
dbManager.updateCase(eamCase);
|
||||
} catch (IllegalArgumentException | EamDbException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error connecting to enterprise artifacts manager database", ex); // NON-NLS
|
||||
LOGGER.log(Level.SEVERE, "Error connecting to Central Repository database", ex); // NON-NLS
|
||||
} finally {
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Enterprise Artifacts Manager
|
||||
* Central Repository
|
||||
*
|
||||
* Copyright 2015-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
@ -16,7 +16,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.actions;
|
||||
package org.sleuthkit.autopsy.centralrepository.actions;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
@ -28,25 +28,25 @@ import org.openide.util.HelpCtx;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.openide.util.actions.CallableSystemAction;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDb;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
|
||||
|
||||
/**
|
||||
* Action to update case details in enterprise artifacts manager database
|
||||
* Action to update case details in Central Repository database
|
||||
*/
|
||||
@ActionID(
|
||||
category = "Case",
|
||||
id = "org.sleuthkit.enterpriseartifactsmanager.actions.EnterpriseArtifactsManagerCaseEditCaseInfoAction"
|
||||
id = "org.sleuthkit.centralrepository.actions.CentralRepositoryCaseProperties"
|
||||
)
|
||||
@ActionRegistration(
|
||||
displayName = "#CTL_EnterpriseArtifactsManagerCaseEditCaseInfo",
|
||||
displayName = "#CTL_CentralRepositoryCaseProperties",
|
||||
lazy = false
|
||||
)
|
||||
@ActionReference(path = "Menu/Case", position = 650, separatorAfter = 824)
|
||||
@Messages("CTL_EnterpriseArtifactsManagerCaseEditCaseInfo=Enterprise Artifacts Manager Case Details")
|
||||
@Messages("CTL_CentralRepositoryCaseProperties=Central Repository Case Properties...")
|
||||
public final class EamEditCaseInfoAction extends CallableSystemAction implements ActionListener {
|
||||
|
||||
EamEditCaseInfoAction() {
|
||||
putValue(Action.NAME, Bundle.CTL_EnterpriseArtifactsManagerCaseEditCaseInfo()); // put the action Name
|
||||
putValue(Action.NAME, Bundle.CTL_CentralRepositoryCaseProperties()); // put the action Name
|
||||
this.setEnabled(true);
|
||||
}
|
||||
|
||||
@ -68,7 +68,7 @@ public final class EamEditCaseInfoAction extends CallableSystemAction implements
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return Bundle.CTL_EnterpriseArtifactsManagerCaseEditCaseInfo();
|
||||
return Bundle.CTL_CentralRepositoryCaseProperties();
|
||||
}
|
||||
|
||||
@Override
|
@ -11,28 +11,28 @@
|
||||
<MenuItem class="javax.swing.JMenuItem" name="selectAllMenuItem">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/contentviewer/Bundle.properties" key="DataContentViewerOtherCases.selectAllMenuItem.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/contentviewer/Bundle.properties" key="DataContentViewerOtherCases.selectAllMenuItem.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</MenuItem>
|
||||
<MenuItem class="javax.swing.JMenuItem" name="exportToCSVMenuItem">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/contentviewer/Bundle.properties" key="DataContentViewerOtherCases.exportToCSVMenuItem.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/contentviewer/Bundle.properties" key="DataContentViewerOtherCases.exportToCSVMenuItem.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</MenuItem>
|
||||
<MenuItem class="javax.swing.JMenuItem" name="showCaseDetailsMenuItem">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/contentviewer/Bundle.properties" key="DataContentViewerOtherCases.showCaseDetailsMenuItem.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/contentviewer/Bundle.properties" key="DataContentViewerOtherCases.showCaseDetailsMenuItem.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</MenuItem>
|
||||
<MenuItem class="javax.swing.JMenuItem" name="showCommonalityMenuItem">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/contentviewer/Bundle.properties" key="DataContentViewerOtherCases.showCommonalityMenuItem.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/contentviewer/Bundle.properties" key="DataContentViewerOtherCases.showCommonalityMenuItem.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</MenuItem>
|
||||
@ -127,7 +127,7 @@
|
||||
<Connection code="tableModel" type="code"/>
|
||||
</Property>
|
||||
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/contentviewer/Bundle.properties" key="DataContentViewerOtherCases.table.toolTip.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/contentviewer/Bundle.properties" key="DataContentViewerOtherCases.table.toolTip.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="columnModel" type="javax.swing.table.TableColumnModel" editor="org.netbeans.modules.form.editors2.TableColumnModelEditor">
|
||||
<TableColumnModel selectionModel="0"/>
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Enterprise Artifacts Manager
|
||||
* Central Repository
|
||||
*
|
||||
* Copyright 2015-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
@ -16,7 +16,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.contentviewer;
|
||||
package org.sleuthkit.autopsy.centralrepository.contentviewer;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.event.ActionEvent;
|
||||
@ -47,13 +47,12 @@ import org.openide.util.NbBundle.Messages;
|
||||
import org.openide.util.lookup.ServiceProvider;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.contentviewer.Bundle;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamArtifact;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamArtifactInstance;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamArtifactUtil;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamCase;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDbException;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamGlobalFileInstance;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifact;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifactInstance;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifactUtil;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamCase;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamGlobalFileInstance;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifactTag;
|
||||
@ -61,14 +60,14 @@ import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.ContentTag;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.TskException;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDb;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
|
||||
|
||||
/**
|
||||
* View correlation results from other cases
|
||||
*/
|
||||
@ServiceProvider(service = DataContentViewer.class, position = 8)
|
||||
@Messages({"DataContentViewerOtherCases.title=Other Cases",
|
||||
"DataContentViewerOtherCases.toolTip=Displays instances of the selected file/artifact from other cases.",})
|
||||
@Messages({"DataContentViewerOtherCases.title=Other Data Sources",
|
||||
"DataContentViewerOtherCases.toolTip=Displays instances of the selected file/artifact from other data sources.",})
|
||||
public class DataContentViewerOtherCases extends javax.swing.JPanel implements DataContentViewer {
|
||||
|
||||
private final static Logger LOGGER = Logger.getLogger(DataContentViewerOtherCases.class.getName());
|
||||
@ -118,9 +117,9 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D
|
||||
|
||||
@Messages({"DataContentViewerOtherCases.correlatedArtifacts.isEmpty=There are no files or artifacts to correlate.",
|
||||
"# {0} - commonality percentage",
|
||||
"# {1} - artifact type",
|
||||
"# {2} - artifact value",
|
||||
"DataContentViewerOtherCases.correlatedArtifacts.byType={0}% for Artifact Type: {1} and Artifact Value: {2}.\n",
|
||||
"# {1} - correlation type",
|
||||
"# {2} - correlation value",
|
||||
"DataContentViewerOtherCases.correlatedArtifacts.byType={0}% for Correlation Type: {1} and Correlation Value: {2}.\n",
|
||||
"DataContentViewerOtherCases.correlatedArtifacts.title=Commonality Percentages",
|
||||
"DataContentViewerOtherCases.correlatedArtifacts.failed=Failed to get commonality details."})
|
||||
private void showCommonalityDetails() {
|
||||
@ -135,10 +134,10 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D
|
||||
try {
|
||||
EamDb dbManager = EamDb.getInstance();
|
||||
for (EamArtifact eamArtifact : correlatedArtifacts) {
|
||||
percentage = dbManager.getCommonalityPercentageForTypeValue(eamArtifact);
|
||||
percentage = dbManager.getCommonalityPercentageForTypeValue(eamArtifact.getCorrelationType(), eamArtifact.getCorrelationValue());
|
||||
msg.append(Bundle.DataContentViewerOtherCases_correlatedArtifacts_byType(percentage,
|
||||
eamArtifact.getArtifactType().getName(),
|
||||
eamArtifact.getArtifactValue()));
|
||||
eamArtifact.getCorrelationType().getDisplayName(),
|
||||
eamArtifact.getCorrelationValue()));
|
||||
}
|
||||
JOptionPane.showConfirmDialog(showCommonalityMenuItem,
|
||||
msg.toString(),
|
||||
@ -156,6 +155,7 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D
|
||||
|
||||
@Messages({"DataContentViewerOtherCases.caseDetailsDialog.notSelected=No Row Selected",
|
||||
"DataContentViewerOtherCases.caseDetailsDialog.noDetails=No details for this case.",
|
||||
"DataContentViewerOtherCases.caseDetailsDialog.noDetailsReference=No case details for Global reference properties.",
|
||||
"DataContentViewerOtherCases.caseDetailsDialog.noCaseNameError=Error"})
|
||||
private void showCaseDetails(int selectedRowViewIdx) {
|
||||
String caseDisplayName = Bundle.DataContentViewerOtherCases_caseDetailsDialog_noCaseNameError();
|
||||
@ -165,6 +165,13 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D
|
||||
int selectedRowModelIdx = otherCasesTable.convertRowIndexToModel(selectedRowViewIdx);
|
||||
EamArtifact eamArtifact = (EamArtifact) tableModel.getRow(selectedRowModelIdx);
|
||||
EamCase eamCasePartial = eamArtifact.getInstances().get(0).getEamCase();
|
||||
if (eamCasePartial == null) {
|
||||
JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
|
||||
Bundle.DataContentViewerOtherCases_caseDetailsDialog_noDetailsReference(),
|
||||
caseDisplayName,
|
||||
DEFAULT_OPTION, PLAIN_MESSAGE);
|
||||
return;
|
||||
}
|
||||
caseDisplayName = eamCasePartial.getDisplayName();
|
||||
// query case details
|
||||
EamCase eamCase = dbManager.getCaseDetails(eamCasePartial.getCaseUUID());
|
||||
@ -198,7 +205,7 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D
|
||||
private void saveToCSV() {
|
||||
if (0 != otherCasesTable.getSelectedRowCount()) {
|
||||
Calendar now = Calendar.getInstance();
|
||||
String fileName = String.format("%1$tY%1$tm%1$te%1$tI%1$tM%1$tS_other_cases.csv", now);
|
||||
String fileName = String.format("%1$tY%1$tm%1$te%1$tI%1$tM%1$tS_other_data_sources.csv", now);
|
||||
CSVFileChooser.setCurrentDirectory(new File(Case.getCurrentCase().getExportDirectory()));
|
||||
CSVFileChooser.setSelectedFile(new File(fileName));
|
||||
CSVFileChooser.setFileFilter(new FileNameExtensionFilter("csv file", "csv"));
|
||||
@ -359,12 +366,11 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D
|
||||
|
||||
/**
|
||||
* Scan a Node for blackboard artifacts / content that we can correlate on
|
||||
* and create the corresponding enterprise artifacts manager artifacts for
|
||||
* display
|
||||
* and create the corresponding Central Repository artifacts for display
|
||||
*
|
||||
* @param node The node to view
|
||||
*
|
||||
* @return A collection of enterprise artifacts manager artifacts to display
|
||||
* @return A collection of Central Repository artifacts to display
|
||||
*/
|
||||
private Collection<EamArtifact> getArtifactsFromCorrelatableAttributes(Node node) {
|
||||
Collection<EamArtifact> ret = new ArrayList<>();
|
||||
@ -379,22 +385,19 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D
|
||||
List<EamArtifact.Type> artifactTypes = null;
|
||||
try {
|
||||
EamDb dbManager = EamDb.getInstance();
|
||||
artifactTypes = dbManager.getCorrelationArtifactTypes();
|
||||
artifactTypes = dbManager.getCorrelationTypes();
|
||||
if (bbArtifact != null) {
|
||||
EamArtifact eamArtifact = EamArtifactUtil.fromBlackboardArtifact(bbArtifact, false, artifactTypes, false);
|
||||
if (eamArtifact != null) {
|
||||
ret.add(eamArtifact);
|
||||
}
|
||||
ret.addAll(EamArtifactUtil.fromBlackboardArtifact(bbArtifact, false, artifactTypes, false));
|
||||
}
|
||||
} catch (EamDbException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error retrieving correlation artifact types", ex); // NON-NLS
|
||||
LOGGER.log(Level.SEVERE, "Error retrieving correlation types", ex); // NON-NLS
|
||||
}
|
||||
|
||||
if (abstractFile != null) {
|
||||
String md5 = abstractFile.getMd5Hash();
|
||||
if (md5 != null && !md5.isEmpty() && null != artifactTypes && !artifactTypes.isEmpty()) {
|
||||
for (EamArtifact.Type aType : artifactTypes) {
|
||||
if (aType.getName().equals("FILES")) {
|
||||
if (aType.getId() == EamArtifact.FILES_TYPE_ID) {
|
||||
ret.add(new EamArtifact(aType, md5));
|
||||
break;
|
||||
}
|
||||
@ -447,17 +450,17 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D
|
||||
|
||||
/**
|
||||
* Query the db for artifact instances from other cases correlated to the
|
||||
* given enterprise artifacts manager artifact.
|
||||
* given Central Repository artifact.
|
||||
*
|
||||
* @param eamArtifact The artifact to correlate against
|
||||
*
|
||||
* @return A collection of correlated artifact instances from other cases
|
||||
*/
|
||||
private Collection<EamArtifactInstance> getCorrelatedInstances(EamArtifact eamArtifact, String dataSourceName, String deviceId) {
|
||||
private Collection<EamArtifactInstance> getCorrelatedInstances(EamArtifact.Type aType, String value, String dataSourceName, String deviceId) {
|
||||
String caseUUID = Case.getCurrentCase().getName();
|
||||
try {
|
||||
EamDb dbManager = EamDb.getInstance();
|
||||
Collection<EamArtifactInstance> artifactInstances = dbManager.getArtifactInstancesByTypeValue(eamArtifact).stream()
|
||||
Collection<EamArtifactInstance> artifactInstances = dbManager.getArtifactInstancesByTypeValue(aType, value).stream()
|
||||
.filter(artifactInstance -> !artifactInstance.getEamCase().getCaseUUID().equals(caseUUID)
|
||||
|| !artifactInstance.getEamDataSource().getName().equals(dataSourceName)
|
||||
|| !artifactInstance.getEamDataSource().getDeviceID().equals(deviceId))
|
||||
@ -472,32 +475,30 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D
|
||||
|
||||
/**
|
||||
* Get the Global File Instances matching the given eamArtifact and convert
|
||||
* them to Enterprise Artifacts Manager Artifact Instancess.
|
||||
* them to Central Repository Artifact Instancess.
|
||||
*
|
||||
* @param eamArtifact Artifact to use for ArtifactTypeEnum matching
|
||||
*
|
||||
* @return List of Enterprise Artifacts Manager Artifact Instances, empty
|
||||
* list if none found
|
||||
* @return List of Central Repository Artifact Instances, empty list if none
|
||||
* found
|
||||
*/
|
||||
public Collection<EamArtifactInstance> getGlobalFileInstancesAsArtifactInstances(EamArtifact eamArtifact) {
|
||||
public Collection<EamArtifactInstance> getReferenceInstancesAsArtifactInstances(EamArtifact eamArtifact) {
|
||||
Collection<EamArtifactInstance> eamArtifactInstances = new ArrayList<>();
|
||||
// FUTURE: support other reference types
|
||||
if (eamArtifact.getCorrelationType().getId() != EamArtifact.FILES_TYPE_ID) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
try {
|
||||
EamDb dbManager = EamDb.getInstance();
|
||||
if (dbManager.getCorrelationArtifactTypeByName("FILES").equals(eamArtifact.getArtifactType())) {
|
||||
try {
|
||||
Collection<EamGlobalFileInstance> eamGlobalFileInstances = dbManager.getGlobalFileInstancesByHash(eamArtifact.getArtifactValue());
|
||||
for (EamGlobalFileInstance eamGlobalFileInstance : eamGlobalFileInstances) {
|
||||
eamArtifactInstances.add(new EamArtifactInstance(
|
||||
null, null, "", eamGlobalFileInstance.getComment(), eamGlobalFileInstance.getKnownStatus(), EamArtifactInstance.GlobalStatus.GLOBAL
|
||||
));
|
||||
}
|
||||
return eamArtifactInstances;
|
||||
} catch (EamDbException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error getting global file instances from database.", ex); // NON-NLS
|
||||
}
|
||||
}
|
||||
Collection<EamGlobalFileInstance> eamGlobalFileInstances = dbManager.getReferenceInstancesByTypeValue(eamArtifact.getCorrelationType(), eamArtifact.getCorrelationValue());
|
||||
eamGlobalFileInstances.forEach((eamGlobalFileInstance) -> {
|
||||
eamArtifactInstances.add(new EamArtifactInstance(
|
||||
null, null, "", eamGlobalFileInstance.getComment(), eamGlobalFileInstance.getKnownStatus(), EamArtifactInstance.GlobalStatus.GLOBAL
|
||||
));
|
||||
});
|
||||
return eamArtifactInstances;
|
||||
} catch (EamDbException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error getting correlation artifact type MD5 from database.", ex); // NON-NLS
|
||||
LOGGER.log(Level.SEVERE, "Error getting reference instances from database.", ex); // NON-NLS
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
@ -513,7 +514,7 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D
|
||||
}
|
||||
|
||||
@Override
|
||||
@Messages({"DataContentViewerOtherCases.table.nodbconnection=Cannot connect to enterprise artifacts manager database."})
|
||||
@Messages({"DataContentViewerOtherCases.table.nodbconnection=Cannot connect to central repository database."})
|
||||
public void setNode(Node node) {
|
||||
if (!EamDb.isEnabled()) {
|
||||
return;
|
||||
@ -537,17 +538,17 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D
|
||||
correlatedArtifacts.addAll(getArtifactsFromCorrelatableAttributes(node));
|
||||
correlatedArtifacts.forEach((eamArtifact) -> {
|
||||
// get local instances
|
||||
Collection<EamArtifactInstance> eamArtifactInstances = getCorrelatedInstances(eamArtifact, dataSourceName, deviceId);
|
||||
Collection<EamArtifactInstance> eamArtifactInstances = getCorrelatedInstances(eamArtifact.getCorrelationType(), eamArtifact.getCorrelationValue(), dataSourceName, deviceId);
|
||||
// get global instances
|
||||
eamArtifactInstances.addAll(getGlobalFileInstancesAsArtifactInstances(eamArtifact));
|
||||
eamArtifactInstances.addAll(getReferenceInstancesAsArtifactInstances(eamArtifact));
|
||||
|
||||
eamArtifactInstances.forEach((eamArtifactInstance) -> {
|
||||
EamArtifact newCeArtifact = new EamArtifact(
|
||||
eamArtifact.getArtifactType(),
|
||||
eamArtifact.getArtifactValue()
|
||||
eamArtifact.getCorrelationType(),
|
||||
eamArtifact.getCorrelationValue()
|
||||
);
|
||||
newCeArtifact.addInstance(eamArtifactInstance);
|
||||
tableModel.addEnterpriseArtifactManagerArtifact(newCeArtifact);
|
||||
tableModel.addEamArtifact(newCeArtifact);
|
||||
});
|
||||
});
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Enterprise Artifacts Manager
|
||||
* Central Repository
|
||||
*
|
||||
* Copyright 2015-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
@ -16,7 +16,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.contentviewer;
|
||||
package org.sleuthkit.autopsy.centralrepository.contentviewer;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
@ -24,6 +24,7 @@ import javax.swing.JLabel;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.table.DefaultTableCellRenderer;
|
||||
import javax.swing.table.TableCellRenderer;
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
|
||||
/**
|
||||
* Renderer for cells in data content viewer table
|
||||
@ -49,19 +50,15 @@ public class DataContentViewerOtherCasesTableCellRenderer implements TableCellRe
|
||||
background = Color.BLUE;
|
||||
} else {
|
||||
String known_status = (String) table.getModel().getValueAt(row, 5);
|
||||
switch (known_status) {
|
||||
case "Bad":
|
||||
if (known_status.equals(TskData.FileKnown.BAD.getName())) {
|
||||
foreground = Color.WHITE;
|
||||
background = Color.RED;
|
||||
break;
|
||||
case "Unknown":
|
||||
} else if (known_status.equals(TskData.FileKnown.UNKNOWN.getName())) {
|
||||
foreground = Color.BLACK;
|
||||
background = Color.YELLOW;
|
||||
break;
|
||||
default:
|
||||
} else {
|
||||
foreground = Color.BLACK;
|
||||
background = Color.WHITE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
renderer.setForeground(foreground);
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Enterprise Artifacts Manager
|
||||
* Central Repository
|
||||
*
|
||||
* Copyright 2015-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
@ -16,14 +16,14 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.contentviewer;
|
||||
package org.sleuthkit.autopsy.centralrepository.contentviewer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamArtifact;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamArtifactInstance;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifact;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifactInstance;
|
||||
|
||||
/**
|
||||
* Model for cells in data content viewer table
|
||||
@ -34,10 +34,10 @@ public class DataContentViewerOtherCasesTableModel extends AbstractTableModel {
|
||||
"DataContentViewerOtherCasesTableModel.device=Device",
|
||||
"DataContentViewerOtherCasesTableModel.dataSource=Data Source",
|
||||
"DataContentViewerOtherCasesTableModel.path=Path",
|
||||
"DataContentViewerOtherCasesTableModel.type=Artifact Type",
|
||||
"DataContentViewerOtherCasesTableModel.value=Artifact Value",
|
||||
"DataContentViewerOtherCasesTableModel.scope=Scope", // was globalStatus
|
||||
"DataContentViewerOtherCasesTableModel.known=Known", // was knownStatus
|
||||
"DataContentViewerOtherCasesTableModel.type=Correlation Type",
|
||||
"DataContentViewerOtherCasesTableModel.value=Correlation Value",
|
||||
"DataContentViewerOtherCasesTableModel.scope=Scope",
|
||||
"DataContentViewerOtherCasesTableModel.known=Known",
|
||||
"DataContentViewerOtherCasesTableModel.comment=Comment",
|
||||
"DataContentViewerOtherCasesTableModel.noData=No Data.",})
|
||||
private enum TableColumns {
|
||||
@ -48,7 +48,7 @@ public class DataContentViewerOtherCasesTableModel extends AbstractTableModel {
|
||||
DEVICE(Bundle.DataContentViewerOtherCasesTableModel_device(), 145),
|
||||
TYPE(Bundle.DataContentViewerOtherCasesTableModel_type(), 40),
|
||||
VALUE(Bundle.DataContentViewerOtherCasesTableModel_value(), 145),
|
||||
KNOWN(Bundle.DataContentViewerOtherCasesTableModel_known(), 25),
|
||||
KNOWN(Bundle.DataContentViewerOtherCasesTableModel_known(), 45),
|
||||
SCOPE(Bundle.DataContentViewerOtherCasesTableModel_scope(), 20),
|
||||
COMMENT(Bundle.DataContentViewerOtherCasesTableModel_comment(), 200),
|
||||
FILE_PATH(Bundle.DataContentViewerOtherCasesTableModel_path(), 250);
|
||||
@ -151,16 +151,16 @@ public class DataContentViewerOtherCasesTableModel extends AbstractTableModel {
|
||||
value = eamArtifactInstance.getFilePath();
|
||||
break;
|
||||
case TYPE:
|
||||
value = eamArtifact.getArtifactType().getName();
|
||||
value = eamArtifact.getCorrelationType().getDisplayName();
|
||||
break;
|
||||
case VALUE:
|
||||
value = eamArtifact.getArtifactValue();
|
||||
value = eamArtifact.getCorrelationValue();
|
||||
break;
|
||||
case SCOPE:
|
||||
value = eamArtifactInstance.getGlobalStatus().toString();
|
||||
break;
|
||||
case KNOWN:
|
||||
value = eamArtifactInstance.getKnownStatus().toString();
|
||||
value = eamArtifactInstance.getKnownStatus().getName();
|
||||
break;
|
||||
case COMMENT:
|
||||
value = eamArtifactInstance.getComment();
|
||||
@ -175,12 +175,12 @@ public class DataContentViewerOtherCasesTableModel extends AbstractTableModel {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add one local Enterprise Artifacts Manager Artifact to the table.
|
||||
* Add one local Central Repository Artifact to the table.
|
||||
*
|
||||
* @param eamArtifact Enterprise Artifacts Manager Artifact to add to the
|
||||
* @param eamArtifact Central Repository Artifact to add to the
|
||||
* table
|
||||
*/
|
||||
public void addEnterpriseArtifactManagerArtifact(EamArtifact eamArtifact) {
|
||||
public void addEamArtifact(EamArtifact eamArtifact) {
|
||||
eamArtifacts.add(eamArtifact);
|
||||
fireTableDataChanged();
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,367 @@
|
||||
/*
|
||||
* Central Repository
|
||||
*
|
||||
* Copyright 2015-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> 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.centralrepository.datamodel;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Pattern;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
|
||||
/**
|
||||
*
|
||||
* Used to store info about a specific artifact.
|
||||
*/
|
||||
public class EamArtifact implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String ID;
|
||||
private String correlationValue;
|
||||
private Type correlationType;
|
||||
private final List<EamArtifactInstance> artifactInstances;
|
||||
|
||||
// Type ID's for Default Correlation Types
|
||||
public static final int FILES_TYPE_ID = 0;
|
||||
public static final int DOMAIN_TYPE_ID = 1;
|
||||
public static final int EMAIL_TYPE_ID = 2;
|
||||
public static final int PHONE_TYPE_ID = 3;
|
||||
public static final int USBID_TYPE_ID = 4;
|
||||
|
||||
/**
|
||||
* Load the default correlation types
|
||||
*
|
||||
* @throws EamDbException if the Type's dbTableName has invalid characters/format
|
||||
*/
|
||||
@Messages({"CorrelationType.FILES.displayName=Files",
|
||||
"CorrelationType.DOMAIN.displayName=Domains",
|
||||
"CorrelationType.EMAIL.displayName=Email Addresses",
|
||||
"CorrelationType.PHONE.displayName=Phone Numbers",
|
||||
"CorrelationType.USBID.displayName=USB Devices"})
|
||||
public static List<EamArtifact.Type> getDefaultCorrelationTypes() throws EamDbException {
|
||||
List<EamArtifact.Type> DEFAULT_CORRELATION_TYPES = new ArrayList<>();
|
||||
DEFAULT_CORRELATION_TYPES.add(new EamArtifact.Type(FILES_TYPE_ID, Bundle.CorrelationType_FILES_displayName(), "file", true, true)); // NON-NLS
|
||||
DEFAULT_CORRELATION_TYPES.add(new EamArtifact.Type(DOMAIN_TYPE_ID, Bundle.CorrelationType_DOMAIN_displayName(), "domain", true, false)); // NON-NLS
|
||||
DEFAULT_CORRELATION_TYPES.add(new EamArtifact.Type(EMAIL_TYPE_ID, Bundle.CorrelationType_EMAIL_displayName(), "email_address", true, false)); // NON-NLS
|
||||
DEFAULT_CORRELATION_TYPES.add(new EamArtifact.Type(PHONE_TYPE_ID, Bundle.CorrelationType_PHONE_displayName(), "phone_number", true, false)); // NON-NLS
|
||||
DEFAULT_CORRELATION_TYPES.add(new EamArtifact.Type(USBID_TYPE_ID, Bundle.CorrelationType_USBID_displayName(), "usb_devices", true, false)); // NON-NLS
|
||||
return DEFAULT_CORRELATION_TYPES;
|
||||
}
|
||||
|
||||
public EamArtifact(Type correlationType, String correlationValue) {
|
||||
this.ID = "";
|
||||
this.correlationType = correlationType;
|
||||
// Lower-case all values to normalize and improve correlation hits, going forward make sure this makes sense for all correlation types
|
||||
this.correlationValue = correlationValue.toLowerCase();
|
||||
this.artifactInstances = new ArrayList<>();
|
||||
}
|
||||
|
||||
public Boolean equals(EamArtifact otherArtifact) {
|
||||
return ((this.getID().equals(otherArtifact.getID()))
|
||||
&& (this.getCorrelationType().equals(otherArtifact.getCorrelationType()))
|
||||
&& (this.getCorrelationValue().equals(otherArtifact.getCorrelationValue()))
|
||||
&& (this.getInstances().equals(otherArtifact.getInstances())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String result = this.getID()
|
||||
+ this.getCorrelationType().toString()
|
||||
+ this.getCorrelationValue();
|
||||
result = this.getInstances().stream().map((inst) -> inst.toString()).reduce(result, String::concat);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the ID
|
||||
*/
|
||||
public String getID() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ID the ID to set
|
||||
*/
|
||||
public void setID(String ID) {
|
||||
this.ID = ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the correlationValue
|
||||
*/
|
||||
public String getCorrelationValue() {
|
||||
return correlationValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param correlationValue the correlationValue to set
|
||||
*/
|
||||
public void setCorrelationValue(String correlationValue) {
|
||||
// Lower-case all values to normalize and improve correlation hits, going forward make sure this makes sense for all correlation types
|
||||
this.correlationValue = correlationValue.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the correlation Type
|
||||
*/
|
||||
public Type getCorrelationType() {
|
||||
return correlationType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param correlationType the correlation Type to set
|
||||
*/
|
||||
public void setCorrelationType(Type correlationType) {
|
||||
this.correlationType = correlationType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the List of artifactInstances; empty list of none have been
|
||||
* added.
|
||||
*/
|
||||
public List<EamArtifactInstance> getInstances() {
|
||||
return new ArrayList<>(artifactInstances);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param artifactInstances the List of artifactInstances to set.
|
||||
*/
|
||||
public void setInstances(List<EamArtifactInstance> artifactInstances) {
|
||||
this.artifactInstances.clear();
|
||||
if (null != artifactInstances) {
|
||||
this.artifactInstances.addAll(artifactInstances);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param instance the instance to add
|
||||
*/
|
||||
public void addInstance(EamArtifactInstance artifactInstance) {
|
||||
this.artifactInstances.add(artifactInstance);
|
||||
}
|
||||
|
||||
public static class Type implements Serializable {
|
||||
|
||||
private int id;
|
||||
private String displayName;
|
||||
private String dbTableName;
|
||||
private Boolean supported;
|
||||
private Boolean enabled;
|
||||
private final String DB_NAMES_REGEX = "[a-z][a-z0-9_]*";
|
||||
|
||||
/**
|
||||
*
|
||||
* @param id Unique ID for this Correlation Type
|
||||
* @param displayName Name of this type displayed in the UI.
|
||||
* @param dbTableName Central Repository db table where data of this type is stored.
|
||||
* Must start with a lowercase letter and only contain
|
||||
* lowercase letters, numbers, and '_' characters.
|
||||
* @param supported Is this Type currently supported
|
||||
* @param enabled Is this Type currentl enabled.
|
||||
*/
|
||||
public Type(int id, String displayName, String dbTableName, Boolean supported, Boolean enabled) throws EamDbException {
|
||||
this.id = id;
|
||||
this.displayName = displayName;
|
||||
this.dbTableName = dbTableName;
|
||||
this.supported = supported;
|
||||
this.enabled = enabled;
|
||||
if (!Pattern.matches(DB_NAMES_REGEX, dbTableName)) {
|
||||
throw new EamDbException("Invalid database table name. Name must start with a lowercase letter and can only contain lowercase letters, numbers, and '_'."); // NON-NLS
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructior for custom types where we do not know the Type ID until
|
||||
* the row has been entered into the correlation_types table
|
||||
* in the Central Repository.
|
||||
*
|
||||
* @param displayName Name of this type displayed in the UI.
|
||||
* @param dbTableName Central Repository db table where data of this type is stored
|
||||
* Must start with a lowercase letter and only contain
|
||||
* lowercase letters, numbers, and '_' characters.
|
||||
* @param supported Is this Type currently supported
|
||||
* @param enabled Is this Type currentl enabled.
|
||||
*/
|
||||
public Type(String displayName, String dbTableName, Boolean supported, Boolean enabled) throws EamDbException {
|
||||
this(-1, displayName, dbTableName, supported, enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if 2 Type objects are equal
|
||||
*
|
||||
* @param otherType Type object for comparison.
|
||||
*
|
||||
* @return true or false
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object that) {
|
||||
if (this == that) {
|
||||
return true;
|
||||
} else if (!(that instanceof EamArtifact.Type)) {
|
||||
return false;
|
||||
} else {
|
||||
return ((EamArtifact.Type) that).sameType(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the content of this artifact type object is equivalent
|
||||
* to the content of another artifact type object.
|
||||
*
|
||||
* @param that the other type
|
||||
*
|
||||
* @return true if it is the same type
|
||||
*/
|
||||
private boolean sameType(EamArtifact.Type that) {
|
||||
return this.id == that.getId()
|
||||
&& Objects.equals(this.supported, that.isSupported())
|
||||
&& Objects.equals(this.enabled, that.isEnabled());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 7;
|
||||
hash = 67 * hash + Objects.hashCode(this.id);
|
||||
hash = 67 * hash + Objects.hashCode(this.supported);
|
||||
hash = 67 * hash + Objects.hashCode(this.enabled);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder str = new StringBuilder();
|
||||
str.append("(id=").append(getId());
|
||||
str.append(", displayName=").append(getDisplayName());
|
||||
str.append(", dbTableName=").append(getDbTableName());
|
||||
str.append(", supported=").append(isSupported().toString());
|
||||
str.append(", enabled=").append(isEnabled().toString());
|
||||
str.append(")");
|
||||
return str.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the id
|
||||
*/
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param id the id to set
|
||||
*/
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this Artifact Type is supported.
|
||||
*
|
||||
* @return true or false
|
||||
*/
|
||||
public Boolean isSupported() {
|
||||
return supported;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this Artifact Type as supported or not supported.
|
||||
*
|
||||
* @param supported the supported to set
|
||||
*/
|
||||
public void setSupported(Boolean supported) {
|
||||
this.supported = supported;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this Artifact Type is enabled.
|
||||
*
|
||||
* @return true or false
|
||||
*/
|
||||
public Boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this Artifact Type as enabled or not enabled.
|
||||
*
|
||||
* @param enabled the enabled to set
|
||||
*/
|
||||
public void setEnabled(Boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the displayName
|
||||
*/
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param displayName the displayName to set
|
||||
*/
|
||||
public void setDisplayName(String displayName) {
|
||||
this.displayName = displayName;
|
||||
}
|
||||
|
||||
/**
|
||||
* To support having different database tables for each Type,
|
||||
* this field provides the prefix/suffix of the table name,
|
||||
* which allows us to automatically compute the table names
|
||||
* and index names.
|
||||
*
|
||||
* It is the prefix for the instances tables *_instances. (i.e. file_instances)
|
||||
* It is the suffix for the reference tables reference_*. (i.e. reference_file)
|
||||
*
|
||||
* When custom Types are added in the future, they are already supported
|
||||
* by just giving the desired value for the table name for each custom
|
||||
* Type. Possibly having all custom Types use a common table name.
|
||||
*
|
||||
* @return the dbTableName
|
||||
*/
|
||||
public String getDbTableName() {
|
||||
return dbTableName;
|
||||
}
|
||||
|
||||
/**
|
||||
* To support having different database tables for each Type,
|
||||
* this field provides the prefix/suffix of the table name,
|
||||
* which allows us to automatically compute the table names
|
||||
* and index names.
|
||||
*
|
||||
* It is the prefix for the instances tables *_instances. (i.e. file_instances)
|
||||
* It is the suffix for the reference tables reference_*. (i.e. reference_file)
|
||||
*
|
||||
* When custom Types are added in the future, they are already supported
|
||||
* by just giving the desired value for the table name for each custom
|
||||
* Type. Possibly having all custom Types use a common table name. (i.e. custom_instances)
|
||||
*
|
||||
* @param dbTableName the dbTableName to set. Must start with lowercase letter
|
||||
* and can only contain lowercase letters, numbers, and '_' characters.
|
||||
*
|
||||
* @throws EamDbException if dbTableName contains invalid characters
|
||||
*/
|
||||
public void setDbTableName(String dbTableName) throws EamDbException {
|
||||
if (!Pattern.matches(DB_NAMES_REGEX, dbTableName)) {
|
||||
throw new EamDbException("Invalid database table name. Name must start with a lowercase letter and can only contain lowercase letters, numbers, and '_'."); // NON-NLS
|
||||
}
|
||||
this.dbTableName = dbTableName;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Enterprise Artifacts Manager
|
||||
* Central Repository
|
||||
*
|
||||
* Copyright 2015-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
@ -16,26 +16,27 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel;
|
||||
package org.sleuthkit.autopsy.centralrepository.datamodel;
|
||||
|
||||
import java.io.Serializable;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
|
||||
/**
|
||||
*
|
||||
* Used to store info about a specific Artifact Instance.
|
||||
*
|
||||
*/
|
||||
@Messages({"EnterpriseArtifactsManagerArtifactInstances.globalStatus.local=Local",
|
||||
"EnterpriseArtifactsManagerArtifactInstances.globalStatus.global=Global",
|
||||
"EnterpriseArtifactsManagerArtifactInstances.knownStatus.bad=Bad",
|
||||
"EnterpriseArtifactsManagerArtifactInstances.knownStatus.known=Known",
|
||||
"EnterpriseArtifactsManagerArtifactInstances.knownStatus.unknown=Unknown"})
|
||||
@Messages({"EamArtifactInstances.globalStatus.local=Local",
|
||||
"EamArtifactInstances.globalStatus.global=Global",
|
||||
"EamArtifactInstances.knownStatus.bad=Bad",
|
||||
"EamArtifactInstances.knownStatus.known=Known",
|
||||
"EamArtifactInstances.knownStatus.unknown=Unknown"})
|
||||
public class EamArtifactInstance implements Serializable {
|
||||
|
||||
public enum GlobalStatus {
|
||||
LOCAL(Bundle.EnterpriseArtifactsManagerArtifactInstances_globalStatus_local()),
|
||||
GLOBAL(Bundle.EnterpriseArtifactsManagerArtifactInstances_globalStatus_global());
|
||||
LOCAL(Bundle.EamArtifactInstances_globalStatus_local()),
|
||||
GLOBAL(Bundle.EamArtifactInstances_globalStatus_global());
|
||||
|
||||
private final String globalStatus;
|
||||
|
||||
@ -49,23 +50,6 @@ public class EamArtifactInstance implements Serializable {
|
||||
}
|
||||
}
|
||||
|
||||
public enum KnownStatus {
|
||||
UNKNOWN(Bundle.EnterpriseArtifactsManagerArtifactInstances_knownStatus_unknown()),
|
||||
KNOWN(Bundle.EnterpriseArtifactsManagerArtifactInstances_knownStatus_known()),
|
||||
BAD(Bundle.EnterpriseArtifactsManagerArtifactInstances_knownStatus_bad());
|
||||
|
||||
private final String knownStatus;
|
||||
|
||||
private KnownStatus(String knownStatus) {
|
||||
this.knownStatus = knownStatus;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return knownStatus;
|
||||
}
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String ID;
|
||||
@ -73,14 +57,14 @@ public class EamArtifactInstance implements Serializable {
|
||||
private EamDataSource eamDataSource;
|
||||
private String filePath;
|
||||
private String comment;
|
||||
private KnownStatus knownStatus;
|
||||
private TskData.FileKnown knownStatus;
|
||||
private GlobalStatus globalStatus;
|
||||
|
||||
public EamArtifactInstance(
|
||||
EamCase eamCase,
|
||||
EamDataSource eamDataSource
|
||||
) {
|
||||
this("", eamCase, eamDataSource, "", "", KnownStatus.UNKNOWN, GlobalStatus.LOCAL);
|
||||
this("", eamCase, eamDataSource, "", null, TskData.FileKnown.UNKNOWN, GlobalStatus.LOCAL);
|
||||
}
|
||||
|
||||
public EamArtifactInstance(
|
||||
@ -88,7 +72,7 @@ public class EamArtifactInstance implements Serializable {
|
||||
EamDataSource eamDataSource,
|
||||
String filePath
|
||||
) {
|
||||
this("", eamCase, eamDataSource, filePath, "", KnownStatus.UNKNOWN, GlobalStatus.LOCAL);
|
||||
this("", eamCase, eamDataSource, filePath, null, TskData.FileKnown.UNKNOWN, GlobalStatus.LOCAL);
|
||||
}
|
||||
|
||||
public EamArtifactInstance(
|
||||
@ -97,7 +81,7 @@ public class EamArtifactInstance implements Serializable {
|
||||
String filePath,
|
||||
String comment
|
||||
) {
|
||||
this("", eamCase, eamDataSource, filePath, comment, KnownStatus.UNKNOWN, GlobalStatus.LOCAL);
|
||||
this("", eamCase, eamDataSource, filePath, comment, TskData.FileKnown.UNKNOWN, GlobalStatus.LOCAL);
|
||||
}
|
||||
|
||||
public EamArtifactInstance(
|
||||
@ -105,7 +89,7 @@ public class EamArtifactInstance implements Serializable {
|
||||
EamDataSource eamDataSource,
|
||||
String filePath,
|
||||
String comment,
|
||||
KnownStatus knownStatus,
|
||||
TskData.FileKnown knownStatus,
|
||||
GlobalStatus globalStatus
|
||||
) {
|
||||
this("", eamCase, eamDataSource, filePath, comment, knownStatus, globalStatus);
|
||||
@ -117,13 +101,14 @@ public class EamArtifactInstance implements Serializable {
|
||||
EamDataSource eamDataSource,
|
||||
String filePath,
|
||||
String comment,
|
||||
KnownStatus knownStatus,
|
||||
TskData.FileKnown knownStatus,
|
||||
GlobalStatus globalStatus
|
||||
) {
|
||||
this.ID = ID;
|
||||
this.eamCase = eamCase;
|
||||
this.eamDataSource = eamDataSource;
|
||||
this.filePath = filePath;
|
||||
// Lower case paths to normalize paths and improve correlation results, if this causes significant issues on case-sensitive file systems, remove
|
||||
this.filePath = filePath.toLowerCase();
|
||||
this.comment = comment;
|
||||
this.knownStatus = knownStatus;
|
||||
this.globalStatus = globalStatus;
|
||||
@ -203,14 +188,15 @@ public class EamArtifactInstance implements Serializable {
|
||||
* @param filePath the filePath to set
|
||||
*/
|
||||
public void setFilePath(String filePath) {
|
||||
this.filePath = filePath;
|
||||
// Lower case paths to normalize paths and improve correlation results, if this causes significant issues on case-sensitive file systems, remove
|
||||
this.filePath = filePath.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the comment
|
||||
*/
|
||||
public String getComment() {
|
||||
return comment;
|
||||
return null == comment ? "" : comment;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -223,14 +209,14 @@ public class EamArtifactInstance implements Serializable {
|
||||
/**
|
||||
* @return the knownStatus
|
||||
*/
|
||||
public KnownStatus getKnownStatus() {
|
||||
public TskData.FileKnown getKnownStatus() {
|
||||
return knownStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param knownStatus the knownStatus to set
|
||||
*/
|
||||
public void setKnownStatus(KnownStatus knownStatus) {
|
||||
public void setKnownStatus(TskData.FileKnown knownStatus) {
|
||||
this.knownStatus = knownStatus;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Enterprise Artifacts Manager
|
||||
* Central Repository
|
||||
*
|
||||
* Copyright 2015-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
@ -16,8 +16,9 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel;
|
||||
package org.sleuthkit.autopsy.centralrepository.datamodel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
@ -27,6 +28,7 @@ import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
import org.sleuthkit.datamodel.TskDataException;
|
||||
|
||||
/**
|
||||
@ -40,36 +42,37 @@ public class EamArtifactUtil {
|
||||
public EamArtifactUtil() {
|
||||
}
|
||||
|
||||
@Messages({"enterpriseartifactsmanagerartifact.emailaddresses.text=Email Addresses"})
|
||||
@Messages({"EamArtifactUtil.emailaddresses.text=Email Addresses"})
|
||||
public static String getEmailAddressAttrString() {
|
||||
return Bundle.enterpriseartifactsmanagerartifact_emailaddresses_text();
|
||||
return Bundle.EamArtifactUtil_emailaddresses_text();
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Static factory method to examine a BlackboardArtifact to determine if it
|
||||
* has contents that can be used for Correlation. If so, return a
|
||||
* EamArtifact with a single EamArtifactInstance within. If not, return
|
||||
* null.
|
||||
*
|
||||
* @param bbArtifact BlackboardArtifact to examine @return EamArtifact or
|
||||
* null
|
||||
* @param bbArtifact BlackboardArtifact to examine
|
||||
* @return List of EamArtifacts
|
||||
*/
|
||||
public static EamArtifact fromBlackboardArtifact(BlackboardArtifact bbArtifact,
|
||||
public static List<EamArtifact> fromBlackboardArtifact(BlackboardArtifact bbArtifact,
|
||||
boolean includeInstances,
|
||||
List<EamArtifact.Type> artifactTypes,
|
||||
boolean checkEnabled) {
|
||||
|
||||
EamArtifact eamArtifact = null;
|
||||
List<EamArtifact> eamArtifacts = new ArrayList<>();
|
||||
|
||||
for (EamArtifact.Type aType : artifactTypes) {
|
||||
if ((checkEnabled && aType.isEnabled()) || !checkEnabled) {
|
||||
eamArtifact = getTypeFromBlackboardArtifact(aType, bbArtifact);
|
||||
}
|
||||
if (null != eamArtifact) {
|
||||
break;
|
||||
EamArtifact eamArtifact = getTypeFromBlackboardArtifact(aType, bbArtifact);
|
||||
if (eamArtifact != null) {
|
||||
eamArtifacts.add(eamArtifact);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (null != eamArtifact && includeInstances) {
|
||||
if (!eamArtifacts.isEmpty() && includeInstances) {
|
||||
try {
|
||||
AbstractFile af = Case.getCurrentCase().getSleuthkitCase().getAbstractFileById(bbArtifact.getObjectID());
|
||||
if (null == af) {
|
||||
@ -88,23 +91,26 @@ public class EamArtifactUtil {
|
||||
new EamDataSource(deviceId, af.getDataSource().getName()),
|
||||
af.getParentPath() + af.getName(),
|
||||
"",
|
||||
EamArtifactInstance.KnownStatus.UNKNOWN,
|
||||
TskData.FileKnown.UNKNOWN,
|
||||
EamArtifactInstance.GlobalStatus.LOCAL
|
||||
);
|
||||
eamArtifact.addInstance(eamInstance);
|
||||
|
||||
for (EamArtifact eamArtifact : eamArtifacts) {
|
||||
eamArtifact.addInstance(eamInstance);
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error creating artifact instance.", ex); // NON-NLS
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return eamArtifact;
|
||||
return eamArtifacts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a blackboard artifact to an EamArtifact
|
||||
*
|
||||
* @param aType The enterprise artifacts manager artifact type to create
|
||||
* @param aType The Central Repository artifact type to create
|
||||
* @param bbArtifact The blackboard artifact to convert
|
||||
*
|
||||
* @return
|
||||
@ -114,7 +120,7 @@ public class EamArtifactUtil {
|
||||
int artifactTypeID = bbArtifact.getArtifactTypeID();
|
||||
|
||||
try {
|
||||
if (aType.getName().equals("EMAIL")
|
||||
if (aType.getId() == EamArtifact.EMAIL_TYPE_ID
|
||||
&& BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID() == artifactTypeID) {
|
||||
|
||||
BlackboardAttribute setNameAttr = bbArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME));
|
||||
@ -122,15 +128,15 @@ public class EamArtifactUtil {
|
||||
&& EamArtifactUtil.getEmailAddressAttrString().equals(setNameAttr.getValueString())) {
|
||||
value = bbArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD)).getValueString();
|
||||
}
|
||||
} else if (aType.getName().equals("DOMAIN")
|
||||
} else if (aType.getId() == EamArtifact.DOMAIN_TYPE_ID
|
||||
&& (BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK.getTypeID() == artifactTypeID
|
||||
|| BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE.getTypeID() == artifactTypeID
|
||||
|| BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID() == artifactTypeID
|
||||
|| BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY.getTypeID() == artifactTypeID)) {
|
||||
|
||||
// Lower-case this to normalize domains
|
||||
value = bbArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN)).getValueString();
|
||||
|
||||
} else if (aType.getName().equals("PHONE")
|
||||
} else if (aType.getId() == EamArtifact.PHONE_TYPE_ID
|
||||
&& (BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT.getTypeID() == artifactTypeID
|
||||
|| BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG.getTypeID() == artifactTypeID
|
||||
|| BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE.getTypeID() == artifactTypeID)) {
|
||||
@ -143,7 +149,16 @@ public class EamArtifactUtil {
|
||||
value = bbArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO)).getValueString();
|
||||
}
|
||||
|
||||
} else if (aType.getName().equals("USBID")
|
||||
// Remove all non-numeric symbols to semi-normalize phone numbers, preserving leading "+" character
|
||||
if (value != null) {
|
||||
String newValue = value.replaceAll("\\D", "");
|
||||
if (value.startsWith("+")) {
|
||||
newValue = "+" + newValue;
|
||||
}
|
||||
|
||||
value = newValue;
|
||||
}
|
||||
} else if (aType.getId() == EamArtifact.USBID_TYPE_ID
|
||||
&& BlackboardArtifact.ARTIFACT_TYPE.TSK_DEVICE_ATTACHED.getTypeID() == artifactTypeID) {
|
||||
|
||||
value = bbArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DEVICE_ID)).getValueString();
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Enterprise Artifacts Manager
|
||||
* Central Repository
|
||||
*
|
||||
* Copyright 2015-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
@ -16,7 +16,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel;
|
||||
package org.sleuthkit.autopsy.centralrepository.datamodel;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.text.DateFormat;
|
||||
@ -46,7 +46,7 @@ public class EamCase implements Serializable {
|
||||
private String notes;
|
||||
|
||||
public EamCase(String caseUUID, String displayName) {
|
||||
this(-1, caseUUID, null, displayName, DATE_FORMAT.format(new Date()), "", "", "", "", "");
|
||||
this(-1, caseUUID, null, displayName, DATE_FORMAT.format(new Date()), null, null, null, null, null);
|
||||
}
|
||||
|
||||
public EamCase(int ID,
|
||||
@ -89,54 +89,54 @@ public class EamCase implements Serializable {
|
||||
return str.toString();
|
||||
}
|
||||
|
||||
@Messages({"EnterpriseArtifactsManagerCase.title.caseUUID=Case UUID: "})
|
||||
@Messages({"EamCase.title.caseUUID=Case UUID: "})
|
||||
public String getTitleCaseUUID() {
|
||||
return Bundle.EnterpriseArtifactsManagerCase_title_caseUUID();
|
||||
return Bundle.EamCase_title_caseUUID();
|
||||
}
|
||||
|
||||
@Messages({"EnterpriseArtifactsManagerCase.title.creationDate=Creation Date: "})
|
||||
@Messages({"EamCase.title.creationDate=Creation Date: "})
|
||||
public String getTitleCreationDate() {
|
||||
return Bundle.EnterpriseArtifactsManagerCase_title_creationDate();
|
||||
return Bundle.EamCase_title_creationDate();
|
||||
}
|
||||
|
||||
@Messages({"EnterpriseArtifactsManagerCase.title.caseDisplayName=Case Name: "})
|
||||
@Messages({"EamCase.title.caseDisplayName=Case Name: "})
|
||||
public String getTitleCaseDisplayName() {
|
||||
return Bundle.EnterpriseArtifactsManagerCase_title_caseDisplayName();
|
||||
return Bundle.EamCase_title_caseDisplayName();
|
||||
}
|
||||
|
||||
@Messages({"EnterpriseArtifactsManagerCase.title.caseNumber=Case Number: "})
|
||||
@Messages({"EamCase.title.caseNumber=Case Number: "})
|
||||
public String getTitleCaseNumber() {
|
||||
return Bundle.EnterpriseArtifactsManagerCase_title_caseNumber();
|
||||
return Bundle.EamCase_title_caseNumber();
|
||||
}
|
||||
|
||||
@Messages({"EnterpriseArtifactsManagerCase.title.examinerName=Examiner Name: "})
|
||||
@Messages({"EamCase.title.examinerName=Examiner Name: "})
|
||||
public String getTitleExaminerName() {
|
||||
return Bundle.EnterpriseArtifactsManagerCase_title_examinerName();
|
||||
return Bundle.EamCase_title_examinerName();
|
||||
}
|
||||
|
||||
@Messages({"EnterpriseArtifactsManagerCase.title.examinerEmail=Examiner Email: "})
|
||||
@Messages({"EamCase.title.examinerEmail=Examiner Email: "})
|
||||
public String getTitleExaminerEmail() {
|
||||
return Bundle.EnterpriseArtifactsManagerCase_title_examinerEmail();
|
||||
return Bundle.EamCase_title_examinerEmail();
|
||||
}
|
||||
|
||||
@Messages({"EnterpriseArtifactsManagerCase.title.examinerPhone=Examiner Phone: "})
|
||||
@Messages({"EamCase.title.examinerPhone=Examiner Phone: "})
|
||||
public String getTitleExaminerPhone() {
|
||||
return Bundle.EnterpriseArtifactsManagerCase_title_examinerPhone();
|
||||
return Bundle.EamCase_title_examinerPhone();
|
||||
}
|
||||
|
||||
@Messages({"EnterpriseArtifactsManagerCase.title.org=Organization: "})
|
||||
@Messages({"EamCase.title.org=Organization: "})
|
||||
public String getTitleOrganization() {
|
||||
return Bundle.EnterpriseArtifactsManagerCase_title_org();
|
||||
return Bundle.EamCase_title_org();
|
||||
}
|
||||
|
||||
@Messages({"EnterpriseArtifactsManagerCase.title.notes=Notes: "})
|
||||
@Messages({"EamCase.title.notes=Notes: "})
|
||||
public String getTitleNotes() {
|
||||
return Bundle.EnterpriseArtifactsManagerCase_title_notes();
|
||||
return Bundle.EamCase_title_notes();
|
||||
}
|
||||
|
||||
public String getCaseDetailsOptionsPaneDialog() {
|
||||
StringBuilder content = new StringBuilder();
|
||||
content.append(getTitleCaseUUID()).append(getCaseUUID().toString()).append("\n");
|
||||
content.append(getTitleCaseUUID()).append(getCaseUUID()).append("\n");
|
||||
content.append(getTitleCaseDisplayName()).append(getDisplayName()).append("\n");
|
||||
content.append(getTitleCreationDate()).append(getCreationDate()).append("\n");
|
||||
content.append(getTitleCaseNumber()).append(getCaseNumber()).append("\n");
|
||||
@ -222,7 +222,7 @@ public class EamCase implements Serializable {
|
||||
* @return the caseNumber
|
||||
*/
|
||||
public String getCaseNumber() {
|
||||
return caseNumber;
|
||||
return null == caseNumber ? "" : caseNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -236,7 +236,7 @@ public class EamCase implements Serializable {
|
||||
* @return the examinerName
|
||||
*/
|
||||
public String getExaminerName() {
|
||||
return examinerName;
|
||||
return null == examinerName ? "" : examinerName;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -250,7 +250,7 @@ public class EamCase implements Serializable {
|
||||
* @return the examinerEmail
|
||||
*/
|
||||
public String getExaminerEmail() {
|
||||
return examinerEmail;
|
||||
return null == examinerEmail ? "" : examinerEmail;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -264,7 +264,7 @@ public class EamCase implements Serializable {
|
||||
* @return the examinerPhone
|
||||
*/
|
||||
public String getExaminerPhone() {
|
||||
return examinerPhone;
|
||||
return null == examinerPhone ? "" : examinerPhone;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -278,7 +278,7 @@ public class EamCase implements Serializable {
|
||||
* @return the notes
|
||||
*/
|
||||
public String getNotes() {
|
||||
return notes;
|
||||
return null == notes ? "" : notes;
|
||||
}
|
||||
|
||||
/**
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Enterprise Artifacts Manager
|
||||
* Central Repository
|
||||
*
|
||||
* Copyright 2015-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
@ -16,7 +16,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel;
|
||||
package org.sleuthkit.autopsy.centralrepository.datamodel;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Enterprise Artifacts Manager
|
||||
* Central Repository
|
||||
*
|
||||
* Copyright 2015-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
@ -16,14 +16,16 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel;
|
||||
package org.sleuthkit.autopsy.centralrepository.datamodel;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Main interface for interacting with the database
|
||||
*/
|
||||
public interface EamDb {
|
||||
|
||||
public static final int SCHEMA_VERSION = 1;
|
||||
|
||||
/**
|
||||
@ -33,7 +35,7 @@ public interface EamDb {
|
||||
*
|
||||
* @throws EamDbException
|
||||
*/
|
||||
static EamDb getInstance() {
|
||||
static EamDb getInstance() throws EamDbException {
|
||||
EamDbPlatformEnum selectedPlatform = EamDbPlatformEnum.getSelectedPlatform();
|
||||
|
||||
switch (selectedPlatform) {
|
||||
@ -47,8 +49,24 @@ public interface EamDb {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdown the connection pool.
|
||||
*
|
||||
* This closes the connection pool including all idle database connections.
|
||||
* It will not close active/in-use connections. Thus, it is vital that there
|
||||
* are no in-use connections when you call this method.
|
||||
*
|
||||
* @throws EamDbException if there is a problem closing the connection pool.
|
||||
*/
|
||||
void shutdownConnections() throws EamDbException;
|
||||
|
||||
/**
|
||||
* Update settings
|
||||
*
|
||||
* When using updateSettings, if any database settings have changed, you
|
||||
* should call shutdownConnections() before using any API methods. That will
|
||||
* ensure that any old connections are closed and all new connections will
|
||||
* be made using the new settings.
|
||||
*/
|
||||
void updateSettings();
|
||||
|
||||
@ -187,23 +205,24 @@ public interface EamDb {
|
||||
void addArtifact(EamArtifact eamArtifact) throws EamDbException;
|
||||
|
||||
/**
|
||||
* Retrieves eamArtifact instances from the database that are associated with
|
||||
* the eamArtifactType and eamArtifactValue of the given eamArtifact.
|
||||
* Retrieves eamArtifact instances from the database that are associated
|
||||
* with the eamArtifactType and eamArtifactValue of the given eamArtifact.
|
||||
*
|
||||
* @param eamArtifact The type/value to look up (artifact with 0 instances)
|
||||
* @param aType EamArtifact.Type to search for
|
||||
* @param value Value to search for
|
||||
*
|
||||
* @return List of artifact instances for a given type/value
|
||||
*/
|
||||
List<EamArtifactInstance> getArtifactInstancesByTypeValue(EamArtifact eamArtifact) throws EamDbException;
|
||||
List<EamArtifactInstance> getArtifactInstancesByTypeValue(EamArtifact.Type aType, String value) throws EamDbException;
|
||||
|
||||
/**
|
||||
* Retrieves eamArtifact instances from the database that are associated with
|
||||
* the aType and filePath
|
||||
* Retrieves eamArtifact instances from the database that are associated
|
||||
* with the aType and filePath
|
||||
*
|
||||
* @param aType EamArtifact.Type to search for
|
||||
* @param filePath File path to search for
|
||||
*
|
||||
* @return List of 0 or more EnterpriseArtifactManagerArtifactInstances
|
||||
* @return List of 0 or more EamArtifactInstances
|
||||
*
|
||||
* @throws EamDbException
|
||||
*/
|
||||
@ -213,13 +232,13 @@ public interface EamDb {
|
||||
* Retrieves number of artifact instances in the database that are
|
||||
* associated with the ArtifactType and artifactValue of the given artifact.
|
||||
*
|
||||
* @param eamArtifact Artifact with artifactType and artifactValue to search
|
||||
* for
|
||||
* @param aType EamArtifact.Type to search for
|
||||
* @param value Value to search for
|
||||
*
|
||||
* @return Number of artifact instances having ArtifactType and
|
||||
* ArtifactValue.
|
||||
*/
|
||||
Long getCountArtifactInstancesByTypeValue(EamArtifact eamArtifact) throws EamDbException;
|
||||
Long getCountArtifactInstancesByTypeValue(EamArtifact.Type aType, String value) throws EamDbException;
|
||||
|
||||
/**
|
||||
* Using the ArtifactType and ArtifactValue from the given eamArtfact,
|
||||
@ -227,24 +246,24 @@ public interface EamDb {
|
||||
* where Type/Value is found) divided by (The total number of unique
|
||||
* case_id/datasource_id tuples in the database) expressed as a percentage.
|
||||
*
|
||||
* @param eamArtifact Artifact with artifactType and artifactValue to search
|
||||
* for
|
||||
* @param aType EamArtifact.Type to search for
|
||||
* @param value Value to search for
|
||||
*
|
||||
* @return Int between 0 and 100
|
||||
*/
|
||||
int getCommonalityPercentageForTypeValue(EamArtifact eamArtifact) throws EamDbException;
|
||||
int getCommonalityPercentageForTypeValue(EamArtifact.Type aType, String value) throws EamDbException;
|
||||
|
||||
/**
|
||||
* Retrieves number of unique caseDisplayName / dataSource tuples in the
|
||||
* database that are associated with the artifactType and artifactValue of
|
||||
* the given artifact.
|
||||
*
|
||||
* @param eamArtifact Artifact with artifactType and artifactValue to search
|
||||
* for
|
||||
* @param aType EamArtifact.Type to search for
|
||||
* @param value Value to search for
|
||||
*
|
||||
* @return Number of unique tuples
|
||||
*/
|
||||
Long getCountUniqueCaseDataSourceTuplesHavingTypeValue(EamArtifact eamArtifact) throws EamDbException;
|
||||
Long getCountUniqueCaseDataSourceTuplesHavingTypeValue(EamArtifact.Type aType, String value) throws EamDbException;
|
||||
|
||||
/**
|
||||
* Retrieves number of unique caseDisplayName/dataSource tuples in the
|
||||
@ -259,15 +278,13 @@ public interface EamDb {
|
||||
* associated with the caseDisplayName and dataSource of the given
|
||||
* eamArtifact instance.
|
||||
*
|
||||
* @param eamInstance Instance with caseName and dataSource to search for
|
||||
*
|
||||
* @param eamInstance Instance with caseDisplayName and dataSource to search
|
||||
* for
|
||||
* @param caseUUID Case ID to search for
|
||||
* @param dataSourceID Data source ID to search for
|
||||
*
|
||||
* @return Number of artifact instances having caseDisplayName and
|
||||
* dataSource
|
||||
*/
|
||||
Long getCountArtifactInstancesByCaseDataSource(EamArtifactInstance eamInstance) throws EamDbException;
|
||||
Long getCountArtifactInstancesByCaseDataSource(String caseUUID, String dataSourceID) throws EamDbException;
|
||||
|
||||
/**
|
||||
* Adds an eamArtifact to an internal list to be later added to DB. Artifact
|
||||
@ -290,52 +307,57 @@ public interface EamDb {
|
||||
void bulkInsertCases(List<EamCase> cases) throws EamDbException;
|
||||
|
||||
/**
|
||||
* Sets an eamArtifact instance as knownStatus = "Bad". If eamArtifact exists,
|
||||
* it is updated. If eamArtifact does not exist nothing happens
|
||||
* Sets an eamArtifact instance as knownStatus = "Bad". If eamArtifact
|
||||
* exists, it is updated. If eamArtifact does not exist nothing happens
|
||||
*
|
||||
* @param eamArtifact Artifact containing exactly one (1) ArtifactInstance.
|
||||
*/
|
||||
void setArtifactInstanceKnownBad(EamArtifact eamArtifact) throws EamDbException;
|
||||
|
||||
/**
|
||||
* Gets list of matching eamArtifact instances that have knownStatus = "Bad".
|
||||
* Gets list of matching eamArtifact instances that have knownStatus =
|
||||
* "Bad".
|
||||
*
|
||||
* @param eamArtifact Artifact containing Type and Value
|
||||
* @param aType EamArtifact.Type to search for
|
||||
* @param value Value to search for
|
||||
*
|
||||
* @return List with 0 or more matching eamArtifact instances.
|
||||
*/
|
||||
List<EamArtifactInstance> getArtifactInstancesKnownBad(EamArtifact eamArtifact) throws EamDbException;
|
||||
List<EamArtifactInstance> getArtifactInstancesKnownBad(EamArtifact.Type aType, String value) throws EamDbException;
|
||||
|
||||
/**
|
||||
* Count matching eamArtifacts instances that have knownStatus = "Bad".
|
||||
*
|
||||
* @param eamArtifact Artifact containing Type and Value
|
||||
* @param aType EamArtifact.Type to search for
|
||||
* @param value Value to search for
|
||||
*
|
||||
* @return Number of matching eamArtifacts
|
||||
*/
|
||||
Long getCountArtifactInstancesKnownBad(EamArtifact eamArtifact) throws EamDbException;
|
||||
Long getCountArtifactInstancesKnownBad(EamArtifact.Type aType, String value) throws EamDbException;
|
||||
|
||||
/**
|
||||
* Gets list of distinct case display names, where each case has 1+ Artifact
|
||||
* Instance matching eamArtifact with knownStatus = "Bad".
|
||||
*
|
||||
* @param eamArtifact Artifact containing Type and Value
|
||||
* @param aType EamArtifact.Type to search for
|
||||
* @param value Value to search for
|
||||
*
|
||||
* @return List of cases containing this artifact with instances marked as
|
||||
* bad
|
||||
*
|
||||
* @throws EamDbException
|
||||
*/
|
||||
List<String> getListCasesHavingArtifactInstancesKnownBad(EamArtifact eamArtifact) throws EamDbException;
|
||||
List<String> getListCasesHavingArtifactInstancesKnownBad(EamArtifact.Type aType, String value) throws EamDbException;
|
||||
|
||||
/**
|
||||
* Is the artifact globally known as bad?
|
||||
* Is the artifact known as bad according to the reference entries?
|
||||
*
|
||||
* @param eamArtifact Artifact containing Type and Value
|
||||
* @param aType EamArtifact.Type to search for
|
||||
* @param value Value to search for
|
||||
*
|
||||
* @return Global known status of the artifact
|
||||
*/
|
||||
boolean isArtifactGlobalKnownBad(EamArtifact eamArtifact) throws EamDbException;
|
||||
boolean isArtifactlKnownBadByReference(EamArtifact.Type aType, String value) throws EamDbException;
|
||||
|
||||
/**
|
||||
* Add a new organization
|
||||
@ -375,7 +397,7 @@ public interface EamDb {
|
||||
*
|
||||
* @throws EamDbException
|
||||
*/
|
||||
int newGlobalSet(EamGlobalSet eamGlobalSet) throws EamDbException;
|
||||
int newReferencelSet(EamGlobalSet eamGlobalSet) throws EamDbException;
|
||||
|
||||
/**
|
||||
* Get a global set by ID
|
||||
@ -386,16 +408,18 @@ public interface EamDb {
|
||||
*
|
||||
* @throws EamDbException
|
||||
*/
|
||||
EamGlobalSet getGlobalSetByID(int globalSetID) throws EamDbException;
|
||||
EamGlobalSet getReferenceSetByID(int globalSetID) throws EamDbException;
|
||||
|
||||
/**
|
||||
* Add a new global file instance
|
||||
* Add a new reference instance
|
||||
*
|
||||
* @param eamGlobalFileInstance The global file instance to add
|
||||
* @param eamGlobalFileInstance The reference instance to add
|
||||
* @param correlationType Correlation Type that this Reference
|
||||
* Instance is
|
||||
*
|
||||
* @throws EamDbException
|
||||
*/
|
||||
void addGlobalFileInstance(EamGlobalFileInstance eamGlobalFileInstance) throws EamDbException;
|
||||
void addReferenceInstance(EamGlobalFileInstance eamGlobalFileInstance, EamArtifact.Type correlationType) throws EamDbException;
|
||||
|
||||
/**
|
||||
* Add a new global file instance to the bulk collection
|
||||
@ -404,34 +428,40 @@ public interface EamDb {
|
||||
*
|
||||
* @throws EamDbException
|
||||
*/
|
||||
void prepareGlobalFileInstance(EamGlobalFileInstance eamGlobalFileInstance) throws EamDbException;
|
||||
|
||||
// void prepareGlobalFileInstance(EamGlobalFileInstance eamGlobalFileInstance) throws EamDbException;
|
||||
/**
|
||||
* Insert the bulk collection of Global File Instances
|
||||
*
|
||||
* @param globalInstances a Set of EamGlobalFileInstances to insert into the
|
||||
* db.
|
||||
* @param contentType the Type of the global instances
|
||||
*
|
||||
* @throws EamDbException
|
||||
*/
|
||||
void bulkInsertGlobalFileInstances() throws EamDbException;
|
||||
void bulkInsertReferenceTypeEntries(Set<EamGlobalFileInstance> globalInstances, EamArtifact.Type contentType) throws EamDbException;
|
||||
|
||||
/**
|
||||
* Get all global file instances having a given MD5 hash
|
||||
* Get all reference entries having a given correlation type and value
|
||||
*
|
||||
* @param MD5Hash The hash to lookup
|
||||
* @param aType Type to use for matching
|
||||
* @param aValue Value to use for matching
|
||||
*
|
||||
* @return List of all global file instances with a given hash
|
||||
* @return List of all global file instances with a type and value
|
||||
*
|
||||
* @throws EamDbException
|
||||
*/
|
||||
List<EamGlobalFileInstance> getGlobalFileInstancesByHash(String MD5Hash) throws EamDbException;
|
||||
List<EamGlobalFileInstance> getReferenceInstancesByTypeValue(EamArtifact.Type aType, String aValue) throws EamDbException;
|
||||
|
||||
/**
|
||||
* Add a new EamArtifact.Type to the db.
|
||||
*
|
||||
* @param newType New type to add.
|
||||
*
|
||||
* @return Type.ID for newType
|
||||
*
|
||||
* @throws EamDbException
|
||||
*/
|
||||
public void newCorrelationArtifactType(EamArtifact.Type newType) throws EamDbException;
|
||||
public int newCorrelationType(EamArtifact.Type newType) throws EamDbException;
|
||||
|
||||
/**
|
||||
* Get the list of EamArtifact.Type's that will be used to correlate
|
||||
@ -442,7 +472,7 @@ public interface EamDb {
|
||||
*
|
||||
* @throws EamDbException
|
||||
*/
|
||||
public List<EamArtifact.Type> getCorrelationArtifactTypes() throws EamDbException;
|
||||
public List<EamArtifact.Type> getCorrelationTypes() throws EamDbException;
|
||||
|
||||
/**
|
||||
* Get the list of enabled EamArtifact.Type's that will be used to correlate
|
||||
@ -453,7 +483,7 @@ public interface EamDb {
|
||||
*
|
||||
* @throws EamDbException
|
||||
*/
|
||||
public List<EamArtifact.Type> getEnabledCorrelationArtifactTypes() throws EamDbException;
|
||||
public List<EamArtifact.Type> getEnabledCorrelationTypes() throws EamDbException;
|
||||
|
||||
/**
|
||||
* Get the list of supported EamArtifact.Type's that can be used to
|
||||
@ -464,7 +494,7 @@ public interface EamDb {
|
||||
*
|
||||
* @throws EamDbException
|
||||
*/
|
||||
public List<EamArtifact.Type> getSupportedCorrelationArtifactTypes() throws EamDbException;
|
||||
public List<EamArtifact.Type> getSupportedCorrelationTypes() throws EamDbException;
|
||||
|
||||
/**
|
||||
* Update a EamArtifact.Type.
|
||||
@ -473,16 +503,16 @@ public interface EamDb {
|
||||
*
|
||||
* @throws EamDbException
|
||||
*/
|
||||
public void updateCorrelationArtifactType(EamArtifact.Type aType) throws EamDbException;
|
||||
public void updateCorrelationType(EamArtifact.Type aType) throws EamDbException;
|
||||
|
||||
/**
|
||||
* Get the EamArtifact.Type that has name of typeName.
|
||||
* Get the EamArtifact.Type that has the given Type.Id.
|
||||
*
|
||||
* @param typeName Name of Type to get
|
||||
* @param typeId Type.Id of Correlation Type to get
|
||||
*
|
||||
* @return EamArtifact.Type or null if it doesn't exist.
|
||||
*
|
||||
* @throws EamDbException
|
||||
*/
|
||||
public EamArtifact.Type getCorrelationArtifactTypeByName(String typeName) throws EamDbException;
|
||||
public EamArtifact.Type getCorrelationTypeById(int typeId) throws EamDbException;
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Enterprise Artifacts Manager
|
||||
* Central Repository
|
||||
*
|
||||
* Copyright 2015-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
@ -16,7 +16,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel;
|
||||
package org.sleuthkit.autopsy.centralrepository.datamodel;
|
||||
|
||||
/*
|
||||
* An exception to be thrown by an artifact manager.
|
||||
@ -43,5 +43,4 @@ public class EamDbException extends Exception {
|
||||
public EamDbException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Enterprise Artifacts Manager
|
||||
* Central Repository
|
||||
*
|
||||
* Copyright 2015-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
@ -16,7 +16,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel;
|
||||
package org.sleuthkit.autopsy.centralrepository.datamodel;
|
||||
|
||||
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
|
||||
|
||||
@ -41,7 +41,7 @@ public enum EamDbPlatformEnum {
|
||||
* Load the selectedPlatform boolean from the config file, if it is set.
|
||||
*/
|
||||
private void loadSettings() {
|
||||
String selectedPlatformString = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.selectedPlatform"); // NON-NLS
|
||||
String selectedPlatformString = ModuleSettings.getConfigSetting("CentralRepository", "db.selectedPlatform"); // NON-NLS
|
||||
|
||||
if (null != selectedPlatformString) {
|
||||
selected = this.toString().equalsIgnoreCase(selectedPlatformString);
|
||||
@ -86,7 +86,7 @@ public enum EamDbPlatformEnum {
|
||||
selectedPlatform = p;
|
||||
}
|
||||
}
|
||||
ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.selectedPlatform", selectedPlatform.name()); // NON-NLS
|
||||
ModuleSettings.setConfigSetting("CentralRepository", "db.selectedPlatform", selectedPlatform.name()); // NON-NLS
|
||||
}
|
||||
|
||||
/**
|
@ -4,18 +4,17 @@
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel;
|
||||
package org.sleuthkit.autopsy.centralrepository.datamodel;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import static org.sleuthkit.autopsy.centralrepository.datamodel.EamDb.SCHEMA_VERSION;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import static org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDb.SCHEMA_VERSION;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -75,27 +74,30 @@ public class EamDbUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert the default artifact types into the database.
|
||||
* Insert the default correlation types into the database.
|
||||
*
|
||||
* @param conn Open connection to use.
|
||||
* @return true on success, else false
|
||||
*/
|
||||
public static boolean insertDefaultArtifactTypes(Connection conn) {
|
||||
public static boolean insertDefaultCorrelationTypes(Connection conn) {
|
||||
PreparedStatement preparedStatement = null;
|
||||
List<EamArtifact.Type> DEFAULT_ARTIFACT_TYPES = EamArtifact.getDefaultArtifactTypes();
|
||||
String sql = "INSERT INTO artifact_types(name, supported, enabled) VALUES (?, ?, ?)";
|
||||
String sql = "INSERT INTO correlation_types(id, display_name, db_table_name, supported, enabled) VALUES (?, ?, ?, ?, ?)";
|
||||
|
||||
try {
|
||||
List<EamArtifact.Type> DEFAULT_CORRELATION_TYPES = EamArtifact.getDefaultCorrelationTypes();
|
||||
preparedStatement = conn.prepareStatement(sql);
|
||||
for (EamArtifact.Type newType : DEFAULT_ARTIFACT_TYPES) {
|
||||
preparedStatement.setString(1, newType.getName());
|
||||
preparedStatement.setInt(2, newType.isSupported() ? 1 : 0);
|
||||
preparedStatement.setInt(3, newType.isEnabled() ? 1 : 0);
|
||||
for (EamArtifact.Type newType : DEFAULT_CORRELATION_TYPES) {
|
||||
preparedStatement.setInt(1, newType.getId());
|
||||
preparedStatement.setString(2, newType.getDisplayName());
|
||||
preparedStatement.setString(3, newType.getDbTableName());
|
||||
preparedStatement.setInt(4, newType.isSupported() ? 1 : 0);
|
||||
preparedStatement.setInt(5, newType.isEnabled() ? 1 : 0);
|
||||
|
||||
preparedStatement.addBatch();
|
||||
}
|
||||
preparedStatement.executeBatch();
|
||||
} catch (SQLException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error inserting default correlation artifact types.", ex); // NON-NLS
|
||||
} catch (EamDbException | SQLException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error inserting default correlation types.", ex); // NON-NLS
|
||||
return false;
|
||||
} finally {
|
||||
EamDbUtil.closePreparedStatement(preparedStatement);
|
||||
@ -181,4 +183,26 @@ public class EamDbUtil {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Conver thte Type's DbTableName string to the *_instances table name.
|
||||
*
|
||||
* @param type Correlation Type
|
||||
* @return Instance table name for this Type.
|
||||
*/
|
||||
public static String correlationTypeToInstanceTableName(EamArtifact.Type type) {
|
||||
return type.getDbTableName() + "_instances";
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the Type's DbTableName string to the reference_* table name.
|
||||
*
|
||||
* @param type Correlation Type
|
||||
* @return Reference table name for this Type.
|
||||
*/
|
||||
public static String correlationTypeToReferenceTableName(EamArtifact.Type type) {
|
||||
return "reference_" + type.getDbTableName();
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Enterprise Artifacts Manager
|
||||
* Central Repository
|
||||
*
|
||||
* Copyright 2015-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
@ -16,9 +16,10 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel;
|
||||
package org.sleuthkit.autopsy.centralrepository.datamodel;
|
||||
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamArtifactInstance.KnownStatus;
|
||||
import java.util.Objects;
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
|
||||
/**
|
||||
* Global file hash instance
|
||||
@ -28,30 +29,50 @@ public class EamGlobalFileInstance {
|
||||
private int instanceID;
|
||||
private int globalSetID;
|
||||
private String MD5Hash;
|
||||
private KnownStatus knownStatus;
|
||||
private TskData.FileKnown knownStatus;
|
||||
private String comment;
|
||||
|
||||
public EamGlobalFileInstance(
|
||||
int globalSetID,
|
||||
String MD5Hash,
|
||||
TskData.FileKnown knownStatus,
|
||||
String comment) {
|
||||
this(-1, globalSetID, MD5Hash, knownStatus, comment);
|
||||
}
|
||||
|
||||
public EamGlobalFileInstance(
|
||||
int instanceID,
|
||||
int globalSetID,
|
||||
String MD5Hash,
|
||||
KnownStatus knownStatus,
|
||||
TskData.FileKnown knownStatus,
|
||||
String comment) {
|
||||
this.instanceID = instanceID;
|
||||
this.globalSetID = globalSetID;
|
||||
this.MD5Hash = MD5Hash;
|
||||
// Normalize hashes by lower casing
|
||||
this.MD5Hash = MD5Hash.toLowerCase();
|
||||
this.knownStatus = knownStatus;
|
||||
this.comment = comment;
|
||||
}
|
||||
|
||||
public EamGlobalFileInstance(
|
||||
int globalSetID,
|
||||
String MD5Hash,
|
||||
KnownStatus knownStatus,
|
||||
String comment) {
|
||||
this(-1, globalSetID, MD5Hash, knownStatus, comment);
|
||||
@Override
|
||||
public boolean equals(Object otherInstance) {
|
||||
if (this == otherInstance) {
|
||||
return true;
|
||||
} else if (!(otherInstance instanceof EamGlobalFileInstance)) {
|
||||
return false;
|
||||
} else {
|
||||
return (this.hashCode() == otherInstance.hashCode());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 5;
|
||||
hash = 59 * hash + this.globalSetID;
|
||||
hash = 59 * hash + Objects.hashCode(this.MD5Hash);
|
||||
hash = 59 * hash + this.knownStatus.hashCode();
|
||||
return hash;
|
||||
}
|
||||
/**
|
||||
* @return the instanceID
|
||||
*/
|
||||
@ -91,20 +112,21 @@ public class EamGlobalFileInstance {
|
||||
* @param MD5Hash the MD5Hash to set
|
||||
*/
|
||||
public void setMD5Hash(String MD5Hash) {
|
||||
this.MD5Hash = MD5Hash;
|
||||
// Normalize hashes by lower casing
|
||||
this.MD5Hash = MD5Hash.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the knownStatus
|
||||
*/
|
||||
public KnownStatus getKnownStatus() {
|
||||
public TskData.FileKnown getKnownStatus() {
|
||||
return knownStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param knownStatus the knownStatus to set
|
||||
*/
|
||||
public void setKnownStatus(KnownStatus knownStatus) {
|
||||
public void setKnownStatus(TskData.FileKnown knownStatus) {
|
||||
this.knownStatus = knownStatus;
|
||||
}
|
||||
|
||||
@ -112,7 +134,7 @@ public class EamGlobalFileInstance {
|
||||
* @return the comment
|
||||
*/
|
||||
public String getComment() {
|
||||
return comment;
|
||||
return null == comment ? "" : comment;
|
||||
}
|
||||
|
||||
/**
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Enterprise Artifacts Manager
|
||||
* Central Repository
|
||||
*
|
||||
* Copyright 2015-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
@ -16,12 +16,12 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel;
|
||||
package org.sleuthkit.autopsy.centralrepository.datamodel;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
/**
|
||||
* A global set in the enterprise artifacts manager database
|
||||
* A global set in the Central Repository database
|
||||
*/
|
||||
public class EamGlobalSet {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Enterprise Artifacts Manager
|
||||
* Central Repository
|
||||
*
|
||||
* Copyright 2015-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
@ -16,10 +16,10 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel;
|
||||
package org.sleuthkit.autopsy.centralrepository.datamodel;
|
||||
|
||||
/**
|
||||
* An organization in the enterprise artifacts manager database
|
||||
* An organization in the Central Repository database
|
||||
*/
|
||||
public class EamOrganization {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Enterprise Artifacts Manager
|
||||
* Central Repository
|
||||
*
|
||||
* Copyright 2015-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
@ -16,23 +16,26 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel;
|
||||
package org.sleuthkit.autopsy.centralrepository.datamodel;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import org.apache.commons.dbcp2.BasicDataSource;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
/**
|
||||
* Enterprise artifacts manager database implementation using Postgres as a
|
||||
* Central Repository database implementation using Postgres as a
|
||||
* backend
|
||||
*/
|
||||
public class PostgresEamDb extends AbstractSqlEamDb {
|
||||
|
||||
private final static Logger LOGGER = Logger.getLogger(PostgresEamDb.class.getName());
|
||||
|
||||
private final static String CONFLICT_CLAUSE = "ON CONFLICT DO NOTHING";
|
||||
|
||||
private static PostgresEamDb instance;
|
||||
|
||||
private static final int CONN_POOL_SIZE = 10;
|
||||
@ -40,7 +43,14 @@ public class PostgresEamDb extends AbstractSqlEamDb {
|
||||
|
||||
private final PostgresEamDbSettings dbSettings;
|
||||
|
||||
public synchronized static PostgresEamDb getInstance() {
|
||||
/**
|
||||
* Get the singleton instance of PostgresEamDb
|
||||
*
|
||||
* @return the singleton instance of PostgresEamDb
|
||||
*
|
||||
* @throws EamDbException if one or more default correlation type(s) have an invalid db table name.
|
||||
*/
|
||||
public synchronized static PostgresEamDb getInstance() throws EamDbException {
|
||||
if (instance == null) {
|
||||
instance = new PostgresEamDb();
|
||||
}
|
||||
@ -48,9 +58,26 @@ public class PostgresEamDb extends AbstractSqlEamDb {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private PostgresEamDb() {
|
||||
/**
|
||||
*
|
||||
* @throws EamDbException if the AbstractSqlEamDb class has one or more default
|
||||
* correlation type(s) having an invalid db table name.
|
||||
*/
|
||||
private PostgresEamDb() throws EamDbException {
|
||||
dbSettings = new PostgresEamDbSettings();
|
||||
updateSettings();
|
||||
bulkArtifactsThreshold = dbSettings.getBulkThreshold();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdownConnections() throws EamDbException {
|
||||
try {
|
||||
synchronized(this) {
|
||||
connectionPool.close();
|
||||
connectionPool = null; // force it to be re-created on next connect()
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
throw new EamDbException("Failed to close existing database connections.", ex); // NON-NLS
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -77,18 +104,21 @@ public class PostgresEamDb extends AbstractSqlEamDb {
|
||||
dropContent.executeUpdate("TRUNCATE TABLE organizations RESTART IDENTITY CASCADE");
|
||||
dropContent.executeUpdate("TRUNCATE TABLE cases RESTART IDENTITY CASCADE");
|
||||
dropContent.executeUpdate("TRUNCATE TABLE data_sources RESTART IDENTITY CASCADE");
|
||||
dropContent.executeUpdate("TRUNCATE TABLE global_reference_sets RESTART IDENTITY CASCADE");
|
||||
dropContent.executeUpdate("TRUNCATE TABLE global_files RESTART IDENTITY CASCADE");
|
||||
dropContent.executeUpdate("TRUNCATE TABLE artifact_types RESTART IDENTITY CASCADE");
|
||||
dropContent.executeUpdate("TRUNCATE TABLE reference_sets RESTART IDENTITY CASCADE");
|
||||
dropContent.executeUpdate("TRUNCATE TABLE correlation_types RESTART IDENTITY CASCADE");
|
||||
dropContent.executeUpdate("TRUNCATE TABLE db_info RESTART IDENTITY CASCADE");
|
||||
|
||||
String instancesTemplate = "TRUNCATE TABLE %s_instances RESTART IDENTITY CASCADE";
|
||||
for (EamArtifact.Type type : DEFAULT_ARTIFACT_TYPES) {
|
||||
dropContent.executeUpdate(String.format(instancesTemplate, type.getName().toLowerCase()));
|
||||
String referencesTemplate = "TRUNCATE TABLE reference_%s RESTART IDENTITY CASCADE";
|
||||
for (EamArtifact.Type type : DEFAULT_CORRELATION_TYPES) {
|
||||
dropContent.executeUpdate(String.format(instancesTemplate, type.getDbTableName()));
|
||||
// FUTURE: support other reference types
|
||||
if (type.getId() == EamArtifact.FILES_TYPE_ID) {
|
||||
dropContent.executeUpdate(String.format(referencesTemplate, type.getDbTableName()));
|
||||
}
|
||||
}
|
||||
|
||||
} catch (SQLException ex) {
|
||||
//LOGGER.log(Level.WARNING, "Failed to reset database.", ex);
|
||||
LOGGER.log(Level.WARNING, "Failed to reset database.", ex);
|
||||
} finally {
|
||||
EamDbUtil.closeConnection(conn);
|
||||
}
|
||||
@ -135,7 +165,7 @@ public class PostgresEamDb extends AbstractSqlEamDb {
|
||||
protected Connection connect() throws EamDbException {
|
||||
synchronized (this) {
|
||||
if (!EamDb.isEnabled()) {
|
||||
throw new EamDbException("Enterprise artifacts manager is not enabled"); // NON-NLS
|
||||
throw new EamDbException("Central Repository module is not enabled"); // NON-NLS
|
||||
}
|
||||
|
||||
if (connectionPool == null) {
|
||||
@ -150,6 +180,11 @@ public class PostgresEamDb extends AbstractSqlEamDb {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getConflictClause() {
|
||||
return CONFLICT_CLAUSE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getBadTags() {
|
||||
return dbSettings.getBadTags();
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Enterprise Artifacts Manager
|
||||
* Central Repository
|
||||
*
|
||||
* Copyright 2015-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
@ -16,7 +16,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel;
|
||||
package org.sleuthkit.autopsy.centralrepository.datamodel;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
@ -36,15 +36,14 @@ import org.sleuthkit.autopsy.coreutils.TextConverter;
|
||||
import org.sleuthkit.autopsy.coreutils.TextConverterException;
|
||||
|
||||
/**
|
||||
* Settings for the Postgres implementation of the enterprise artifacts manager
|
||||
* database
|
||||
* Settings for the Postgres implementation of the Central Repository database
|
||||
*/
|
||||
public final class PostgresEamDbSettings {
|
||||
|
||||
private final static Logger LOGGER = Logger.getLogger(PostgresEamDbSettings.class.getName());
|
||||
private final String DEFAULT_HOST = "localhost"; // NON-NLS
|
||||
private final int DEFAULT_PORT = 5432;
|
||||
private final String DEFAULT_DBNAME = "enterpriseartifacts"; // NON-NLS
|
||||
private final String DEFAULT_DBNAME = "central_repository"; // NON-NLS
|
||||
private final int DEFAULT_BULK_THRESHHOLD = 1000;
|
||||
private final String DEFAULT_USERNAME = "";
|
||||
private final String DEFAULT_PASSWORD = "";
|
||||
@ -67,13 +66,13 @@ public final class PostgresEamDbSettings {
|
||||
}
|
||||
|
||||
public void loadSettings() {
|
||||
host = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.postgresql.host"); // NON-NLS
|
||||
host = ModuleSettings.getConfigSetting("CentralRepository", "db.postgresql.host"); // NON-NLS
|
||||
if (host == null || host.isEmpty()) {
|
||||
host = DEFAULT_HOST;
|
||||
}
|
||||
|
||||
try {
|
||||
String portString = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.postgresql.port"); // NON-NLS
|
||||
String portString = ModuleSettings.getConfigSetting("CentralRepository", "db.postgresql.port"); // NON-NLS
|
||||
if (portString == null || portString.isEmpty()) {
|
||||
port = DEFAULT_PORT;
|
||||
} else {
|
||||
@ -86,13 +85,13 @@ public final class PostgresEamDbSettings {
|
||||
port = DEFAULT_PORT;
|
||||
}
|
||||
|
||||
dbName = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.postgresql.dbName"); // NON-NLS
|
||||
dbName = ModuleSettings.getConfigSetting("CentralRepository", "db.postgresql.dbName"); // NON-NLS
|
||||
if (dbName == null || dbName.isEmpty()) {
|
||||
dbName = DEFAULT_DBNAME;
|
||||
}
|
||||
|
||||
try {
|
||||
String bulkThresholdString = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.postgresql.bulkThreshold"); // NON-NLS
|
||||
String bulkThresholdString = ModuleSettings.getConfigSetting("CentralRepository", "db.postgresql.bulkThreshold"); // NON-NLS
|
||||
if (bulkThresholdString == null || bulkThresholdString.isEmpty()) {
|
||||
this.bulkThreshold = DEFAULT_BULK_THRESHHOLD;
|
||||
} else {
|
||||
@ -105,12 +104,12 @@ public final class PostgresEamDbSettings {
|
||||
this.bulkThreshold = DEFAULT_BULK_THRESHHOLD;
|
||||
}
|
||||
|
||||
userName = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.postgresql.user"); // NON-NLS
|
||||
userName = ModuleSettings.getConfigSetting("CentralRepository", "db.postgresql.user"); // NON-NLS
|
||||
if (userName == null || userName.isEmpty()) {
|
||||
userName = DEFAULT_USERNAME;
|
||||
}
|
||||
|
||||
password = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.postgresql.password"); // NON-NLS
|
||||
password = ModuleSettings.getConfigSetting("CentralRepository", "db.postgresql.password"); // NON-NLS
|
||||
if (password == null || password.isEmpty()) {
|
||||
password = DEFAULT_PASSWORD;
|
||||
} else {
|
||||
@ -122,7 +121,7 @@ public final class PostgresEamDbSettings {
|
||||
}
|
||||
}
|
||||
|
||||
String badTagsStr = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.badTags"); // NON-NLS
|
||||
String badTagsStr = ModuleSettings.getConfigSetting("CentralRepository", "db.badTags"); // NON-NLS
|
||||
if (badTagsStr == null || badTagsStr.isEmpty()) {
|
||||
badTagsStr = DEFAULT_BAD_TAGS;
|
||||
}
|
||||
@ -130,26 +129,26 @@ public final class PostgresEamDbSettings {
|
||||
}
|
||||
|
||||
public void saveSettings() {
|
||||
ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.postgresql.host", getHost()); // NON-NLS
|
||||
ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.postgresql.port", Integer.toString(port)); // NON-NLS
|
||||
ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.postgresql.dbName", getDbName()); // NON-NLS
|
||||
ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.postgresql.bulkThreshold", Integer.toString(getBulkThreshold())); // NON-NLS
|
||||
ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.postgresql.user", getUserName()); // NON-NLS
|
||||
ModuleSettings.setConfigSetting("CentralRepository", "db.postgresql.host", getHost()); // NON-NLS
|
||||
ModuleSettings.setConfigSetting("CentralRepository", "db.postgresql.port", Integer.toString(port)); // NON-NLS
|
||||
ModuleSettings.setConfigSetting("CentralRepository", "db.postgresql.dbName", getDbName()); // NON-NLS
|
||||
ModuleSettings.setConfigSetting("CentralRepository", "db.postgresql.bulkThreshold", Integer.toString(getBulkThreshold())); // NON-NLS
|
||||
ModuleSettings.setConfigSetting("CentralRepository", "db.postgresql.user", getUserName()); // NON-NLS
|
||||
try {
|
||||
ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.postgresql.password", TextConverter.convertTextToHexText(getPassword())); // NON-NLS
|
||||
ModuleSettings.setConfigSetting("CentralRepository", "db.postgresql.password", TextConverter.convertTextToHexText(getPassword())); // NON-NLS
|
||||
} catch (TextConverterException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Failed to convert password from text to hex text.", ex);
|
||||
}
|
||||
|
||||
ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.badTags", String.join(",", badTags)); // NON-NLS
|
||||
ModuleSettings.setConfigSetting("CentralRepository", "db.badTags", String.join(",", badTags)); // NON-NLS
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the full connection URL as a String
|
||||
*
|
||||
* @param usePostgresDb Connect to the 'postgres' database when testing
|
||||
* connectivity and creating the main database.
|
||||
*
|
||||
* connectivity and creating the main database.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getConnectionURL(boolean usePostgresDb) {
|
||||
@ -167,8 +166,9 @@ public final class PostgresEamDbSettings {
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the current settings to get an ephemeral client connection for testing.
|
||||
*
|
||||
* Use the current settings to get an ephemeral client connection for
|
||||
* testing.
|
||||
*
|
||||
* @return Connection or null.
|
||||
*/
|
||||
private Connection getEphemeralConnection(boolean usePostgresDb) {
|
||||
@ -191,9 +191,9 @@ public final class PostgresEamDbSettings {
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the current settings and the validation query
|
||||
* to test the connection to the database.
|
||||
*
|
||||
* Use the current settings and the validation query to test the connection
|
||||
* to the database.
|
||||
*
|
||||
* @return true if successfull connection, else false.
|
||||
*/
|
||||
public boolean verifyConnection() {
|
||||
@ -201,7 +201,7 @@ public final class PostgresEamDbSettings {
|
||||
if (null == conn) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
boolean result = EamDbUtil.executeValidationQuery(conn, VALIDATION_QUERY);
|
||||
EamDbUtil.closeConnection(conn);
|
||||
return result;
|
||||
@ -209,7 +209,7 @@ public final class PostgresEamDbSettings {
|
||||
|
||||
/**
|
||||
* Check to see if the database exists.
|
||||
*
|
||||
*
|
||||
* @return true if exists, else false
|
||||
*/
|
||||
public boolean verifyDatabaseExists() {
|
||||
@ -238,11 +238,11 @@ public final class PostgresEamDbSettings {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Use the current settings and the schema version query
|
||||
* to test the database schema.
|
||||
*
|
||||
* Use the current settings and the schema version query to test the
|
||||
* database schema.
|
||||
*
|
||||
* @return true if successfull connection, else false.
|
||||
*/
|
||||
public boolean verifyDatabaseSchema() {
|
||||
@ -275,8 +275,9 @@ public final class PostgresEamDbSettings {
|
||||
EamDbUtil.closeConnection(conn);
|
||||
}
|
||||
return true;
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the database schema.
|
||||
*
|
||||
@ -305,7 +306,6 @@ public final class PostgresEamDbSettings {
|
||||
|
||||
// NOTE: The organizations will only have a small number of rows, so
|
||||
// an index is probably not worthwhile.
|
||||
|
||||
StringBuilder createCasesTable = new StringBuilder();
|
||||
createCasesTable.append("CREATE TABLE IF NOT EXISTS cases (");
|
||||
createCasesTable.append("id SERIAL PRIMARY KEY,");
|
||||
@ -313,12 +313,12 @@ public final class PostgresEamDbSettings {
|
||||
createCasesTable.append("org_id integer,");
|
||||
createCasesTable.append("case_name text NOT NULL,");
|
||||
createCasesTable.append("creation_date text NOT NULL,");
|
||||
createCasesTable.append("case_number text NOT NULL,");
|
||||
createCasesTable.append("examiner_name text NOT NULL,");
|
||||
createCasesTable.append("examiner_email text NOT NULL,");
|
||||
createCasesTable.append("examiner_phone text NOT NULL,");
|
||||
createCasesTable.append("notes text NOT NULL,");
|
||||
createCasesTable.append("foreign key (org_id) references organizations(id) on update set null on delete set null");
|
||||
createCasesTable.append("case_number text,");
|
||||
createCasesTable.append("examiner_name text,");
|
||||
createCasesTable.append("examiner_email text,");
|
||||
createCasesTable.append("examiner_phone text,");
|
||||
createCasesTable.append("notes text,");
|
||||
createCasesTable.append("foreign key (org_id) references organizations(id) ON UPDATE SET NULL ON DELETE SET NULL");
|
||||
createCasesTable.append(")");
|
||||
|
||||
// NOTE: when there are few cases in the cases table, these indices may not be worthwhile
|
||||
@ -335,63 +335,64 @@ public final class PostgresEamDbSettings {
|
||||
|
||||
String dataSourceIdx1 = "CREATE INDEX IF NOT EXISTS data_sources_name ON data_sources (name)";
|
||||
|
||||
StringBuilder createGlobalReferenceSetsTable = new StringBuilder();
|
||||
createGlobalReferenceSetsTable.append("CREATE TABLE IF NOT EXISTS global_reference_sets (");
|
||||
createGlobalReferenceSetsTable.append("id SERIAL PRIMARY KEY,");
|
||||
createGlobalReferenceSetsTable.append("org_id integer,");
|
||||
createGlobalReferenceSetsTable.append("set_name text NOT NULL,");
|
||||
createGlobalReferenceSetsTable.append("version text NOT NULL,");
|
||||
createGlobalReferenceSetsTable.append("import_date text NOT NULL,");
|
||||
createGlobalReferenceSetsTable.append("foreign key (org_id) references organizations(id) on update set null on delete set null");
|
||||
createGlobalReferenceSetsTable.append(")");
|
||||
StringBuilder createReferenceSetsTable = new StringBuilder();
|
||||
createReferenceSetsTable.append("CREATE TABLE IF NOT EXISTS reference_sets (");
|
||||
createReferenceSetsTable.append("id SERIAL PRIMARY KEY,");
|
||||
createReferenceSetsTable.append("org_id integer NOT NULL,");
|
||||
createReferenceSetsTable.append("set_name text NOT NULL,");
|
||||
createReferenceSetsTable.append("version text NOT NULL,");
|
||||
createReferenceSetsTable.append("import_date text NOT NULL,");
|
||||
createReferenceSetsTable.append("foreign key (org_id) references organizations(id) ON UPDATE SET NULL ON DELETE SET NULL");
|
||||
createReferenceSetsTable.append(")");
|
||||
|
||||
String globalReferenceSetsIdx1 = "CREATE INDEX IF NOT EXISTS global_reference_sets_org_id ON global_reference_sets (org_id)";
|
||||
String referenceSetsIdx1 = "CREATE INDEX IF NOT EXISTS reference_sets_org_id ON reference_sets (org_id)";
|
||||
|
||||
StringBuilder createGlobalFilesTable = new StringBuilder();
|
||||
createGlobalFilesTable.append("CREATE TABLE IF NOT EXISTS global_files (");
|
||||
createGlobalFilesTable.append("id SERIAL PRIMARY KEY,");
|
||||
createGlobalFilesTable.append("global_reference_set_id integer,");
|
||||
createGlobalFilesTable.append("value text NOT NULL,");
|
||||
createGlobalFilesTable.append("known_status text NOT NULL,");
|
||||
createGlobalFilesTable.append("comment text NOT NULL,");
|
||||
createGlobalFilesTable.append("CONSTRAINT global_files_multi_unique UNIQUE (global_reference_set_id,value),");
|
||||
createGlobalFilesTable.append("foreign key (global_reference_set_id) references global_reference_sets(id) on update set null on delete set null");
|
||||
createGlobalFilesTable.append(")");
|
||||
// Each "%s" will be replaced with the relevant reference_TYPE table name.
|
||||
StringBuilder createReferenceTypesTableTemplate = new StringBuilder();
|
||||
createReferenceTypesTableTemplate.append("CREATE TABLE IF NOT EXISTS %s (");
|
||||
createReferenceTypesTableTemplate.append("id SERIAL PRIMARY KEY,");
|
||||
createReferenceTypesTableTemplate.append("reference_set_id integer,");
|
||||
createReferenceTypesTableTemplate.append("value text NOT NULL,");
|
||||
createReferenceTypesTableTemplate.append("known_status text NOT NULL,");
|
||||
createReferenceTypesTableTemplate.append("comment text,");
|
||||
createReferenceTypesTableTemplate.append("CONSTRAINT %s_multi_unique UNIQUE (reference_set_id, value),");
|
||||
createReferenceTypesTableTemplate.append("foreign key (reference_set_id) references reference_sets(id) ON UPDATE SET NULL ON DELETE SET NULL");
|
||||
createReferenceTypesTableTemplate.append(")");
|
||||
|
||||
String globalFilesIdx1 = "CREATE INDEX IF NOT EXISTS global_files_value ON global_files (value)";
|
||||
String globalFilesIdx2 = "CREATE INDEX IF NOT EXISTS global_files_value_known_status ON global_files (value, known_status)";
|
||||
// Each "%s" will be replaced with the relevant reference_TYPE table name.
|
||||
String referenceTypesIdx1 = "CREATE INDEX IF NOT EXISTS %s_value ON %s (value)";
|
||||
String referenceTypesIdx2 = "CREATE INDEX IF NOT EXISTS %s_value_known_status ON %s (value, known_status)";
|
||||
|
||||
StringBuilder createArtifactTypesTable = new StringBuilder();
|
||||
createArtifactTypesTable.append("CREATE TABLE IF NOT EXISTS artifact_types (");
|
||||
createArtifactTypesTable.append("id SERIAL PRIMARY KEY,");
|
||||
createArtifactTypesTable.append("name text NOT NULL,");
|
||||
createArtifactTypesTable.append("supported integer NOT NULL,");
|
||||
createArtifactTypesTable.append("enabled integer NOT NULL,");
|
||||
createArtifactTypesTable.append("CONSTRAINT artifact_type_name_unique UNIQUE (name)");
|
||||
createArtifactTypesTable.append(")");
|
||||
StringBuilder createCorrelationTypesTable = new StringBuilder();
|
||||
createCorrelationTypesTable.append("CREATE TABLE IF NOT EXISTS correlation_types (");
|
||||
createCorrelationTypesTable.append("id SERIAL PRIMARY KEY,");
|
||||
createCorrelationTypesTable.append("display_name text NOT NULL,");
|
||||
createCorrelationTypesTable.append("db_table_name text NOT NULL,");
|
||||
createCorrelationTypesTable.append("supported integer NOT NULL,");
|
||||
createCorrelationTypesTable.append("enabled integer NOT NULL,");
|
||||
createCorrelationTypesTable.append("CONSTRAINT correlation_types_names UNIQUE (display_name, db_table_name)");
|
||||
createCorrelationTypesTable.append(")");
|
||||
|
||||
// NOTE: there are API methods that query by one of: name, supported, or enabled.
|
||||
// Only name is currently implemented, but, there will only be a small number
|
||||
// of artifact_types, so there is no benefit to having any indices.
|
||||
// Each "%s" will be replaced with the relevant TYPE_instances table name.
|
||||
StringBuilder createArtifactInstancesTableTemplate = new StringBuilder();
|
||||
createArtifactInstancesTableTemplate.append("CREATE TABLE IF NOT EXISTS %s_instances (");
|
||||
createArtifactInstancesTableTemplate.append("CREATE TABLE IF NOT EXISTS %s (");
|
||||
createArtifactInstancesTableTemplate.append("id SERIAL PRIMARY KEY,");
|
||||
createArtifactInstancesTableTemplate.append("case_id integer,");
|
||||
createArtifactInstancesTableTemplate.append("data_source_id integer,");
|
||||
createArtifactInstancesTableTemplate.append("value text NOT NULL,");
|
||||
createArtifactInstancesTableTemplate.append("file_path text NOT NULL,");
|
||||
createArtifactInstancesTableTemplate.append("known_status text NOT NULL,");
|
||||
createArtifactInstancesTableTemplate.append("comment text NOT NULL,");
|
||||
createArtifactInstancesTableTemplate.append("CONSTRAINT %s_instances_multi_unique_ UNIQUE (case_id, data_source_id, value, file_path),");
|
||||
createArtifactInstancesTableTemplate.append("foreign key (case_id) references cases(id) on update set null on delete set null,");
|
||||
createArtifactInstancesTableTemplate.append("foreign key (data_source_id) references data_sources(id) on update set null on delete set null");
|
||||
createArtifactInstancesTableTemplate.append("comment text,");
|
||||
createArtifactInstancesTableTemplate.append("CONSTRAINT %s_multi_unique_ UNIQUE (case_id, data_source_id, value, file_path),");
|
||||
createArtifactInstancesTableTemplate.append("foreign key (case_id) references cases(id) ON UPDATE SET NULL ON DELETE SET NULL,");
|
||||
createArtifactInstancesTableTemplate.append("foreign key (data_source_id) references data_sources(id) ON UPDATE SET NULL ON DELETE SET NULL");
|
||||
createArtifactInstancesTableTemplate.append(")");
|
||||
|
||||
// TODO: do we need any more indices?
|
||||
String instancesIdx1 = "CREATE INDEX IF NOT EXISTS %s_instances_case_id ON %s_instances (case_id)";
|
||||
String instancesIdx2 = "CREATE INDEX IF NOT EXISTS %s_instances_data_source_id ON %s_instances (data_source_id)";
|
||||
String instancesIdx3 = "CREATE INDEX IF NOT EXISTS %s_instances_value ON %s_instances (value)";
|
||||
String instancesIdx4 = "CREATE INDEX IF NOT EXISTS %s_instances_value_known_status ON %s_instances (value, known_status)";
|
||||
// Each "%s" will be replaced with the relevant TYPE_instances table name.
|
||||
String instancesIdx1 = "CREATE INDEX IF NOT EXISTS %s_case_id ON %s (case_id)";
|
||||
String instancesIdx2 = "CREATE INDEX IF NOT EXISTS %s_data_source_id ON %s (data_source_id)";
|
||||
String instancesIdx3 = "CREATE INDEX IF NOT EXISTS %s_value ON %s (value)";
|
||||
String instancesIdx4 = "CREATE INDEX IF NOT EXISTS %s_value_known_status ON %s (value, known_status)";
|
||||
|
||||
StringBuilder createDbInfoTable = new StringBuilder();
|
||||
createDbInfoTable.append("CREATE TABLE IF NOT EXISTS db_info (");
|
||||
@ -402,7 +403,6 @@ public final class PostgresEamDbSettings {
|
||||
|
||||
// NOTE: the db_info table currenly only has 1 row, so having an index
|
||||
// provides no benefit.
|
||||
|
||||
Connection conn = null;
|
||||
try {
|
||||
conn = getEphemeralConnection(false);
|
||||
@ -420,31 +420,42 @@ public final class PostgresEamDbSettings {
|
||||
stmt.execute(createDataSourcesTable.toString());
|
||||
stmt.execute(dataSourceIdx1);
|
||||
|
||||
stmt.execute(createGlobalReferenceSetsTable.toString());
|
||||
stmt.execute(globalReferenceSetsIdx1);
|
||||
stmt.execute(createReferenceSetsTable.toString());
|
||||
stmt.execute(referenceSetsIdx1);
|
||||
|
||||
stmt.execute(createGlobalFilesTable.toString());
|
||||
stmt.execute(globalFilesIdx1);
|
||||
stmt.execute(globalFilesIdx2);
|
||||
|
||||
stmt.execute(createArtifactTypesTable.toString());
|
||||
stmt.execute(createCorrelationTypesTable.toString());
|
||||
|
||||
stmt.execute(createDbInfoTable.toString());
|
||||
|
||||
// Create a separate table for each artifact type
|
||||
List<EamArtifact.Type> DEFAULT_ARTIFACT_TYPES = EamArtifact.getDefaultArtifactTypes();
|
||||
String type_name;
|
||||
for (EamArtifact.Type type : DEFAULT_ARTIFACT_TYPES) {
|
||||
type_name = type.getName();
|
||||
stmt.execute(String.format(createArtifactInstancesTableTemplate.toString(), type_name, type_name));
|
||||
stmt.execute(String.format(instancesIdx1, type_name, type_name));
|
||||
stmt.execute(String.format(instancesIdx2, type_name, type_name));
|
||||
stmt.execute(String.format(instancesIdx3, type_name, type_name));
|
||||
stmt.execute(String.format(instancesIdx4, type_name, type_name));
|
||||
// Create a separate instance and reference table for each correlation type
|
||||
List<EamArtifact.Type> DEFAULT_CORRELATION_TYPES = EamArtifact.getDefaultCorrelationTypes();
|
||||
|
||||
String reference_type_dbname;
|
||||
String instance_type_dbname;
|
||||
for (EamArtifact.Type type : DEFAULT_CORRELATION_TYPES) {
|
||||
reference_type_dbname = EamDbUtil.correlationTypeToReferenceTableName(type);
|
||||
instance_type_dbname = EamDbUtil.correlationTypeToInstanceTableName(type);
|
||||
|
||||
stmt.execute(String.format(createArtifactInstancesTableTemplate.toString(), instance_type_dbname, instance_type_dbname));
|
||||
stmt.execute(String.format(instancesIdx1, instance_type_dbname, instance_type_dbname));
|
||||
stmt.execute(String.format(instancesIdx2, instance_type_dbname, instance_type_dbname));
|
||||
stmt.execute(String.format(instancesIdx3, instance_type_dbname, instance_type_dbname));
|
||||
stmt.execute(String.format(instancesIdx4, instance_type_dbname, instance_type_dbname));
|
||||
|
||||
// FUTURE: allow more than the FILES type
|
||||
if (type.getId() == EamArtifact.FILES_TYPE_ID) {
|
||||
stmt.execute(String.format(createReferenceTypesTableTemplate.toString(), reference_type_dbname, reference_type_dbname));
|
||||
stmt.execute(String.format(referenceTypesIdx1, reference_type_dbname, reference_type_dbname));
|
||||
stmt.execute(String.format(referenceTypesIdx2, reference_type_dbname, reference_type_dbname));
|
||||
}
|
||||
}
|
||||
|
||||
} catch (SQLException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error initializing db schema.", ex); // NON-NLS
|
||||
return false;
|
||||
} catch (EamDbException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error getting default correlation types. Likely due to one or more Type's with an invalid db table name."); // NON-NLS
|
||||
return false;
|
||||
} finally {
|
||||
EamDbUtil.closeConnection(conn);
|
||||
}
|
||||
@ -457,7 +468,7 @@ public final class PostgresEamDbSettings {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean result = EamDbUtil.insertDefaultArtifactTypes(conn)
|
||||
boolean result = EamDbUtil.insertDefaultCorrelationTypes(conn)
|
||||
&& EamDbUtil.insertSchemaVersion(conn);
|
||||
EamDbUtil.closeConnection(conn);
|
||||
|
||||
@ -465,12 +476,12 @@ public final class PostgresEamDbSettings {
|
||||
}
|
||||
|
||||
public boolean isChanged() {
|
||||
String hostString = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.postgresql.host"); // NON-NLS
|
||||
String portString = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.postgresql.port"); // NON-NLS
|
||||
String dbNameString = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.postgresql.dbName"); // NON-NLS
|
||||
String bulkThresholdString = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.postgresql.bulkThreshold"); // NON-NLS
|
||||
String userNameString = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.postgresql.user"); // NON-NLS
|
||||
String userPasswordString = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.postgresql.password"); // NON-NLS
|
||||
String hostString = ModuleSettings.getConfigSetting("CentralRepository", "db.postgresql.host"); // NON-NLS
|
||||
String portString = ModuleSettings.getConfigSetting("CentralRepository", "db.postgresql.port"); // NON-NLS
|
||||
String dbNameString = ModuleSettings.getConfigSetting("CentralRepository", "db.postgresql.dbName"); // NON-NLS
|
||||
String bulkThresholdString = ModuleSettings.getConfigSetting("CentralRepository", "db.postgresql.bulkThreshold"); // NON-NLS
|
||||
String userNameString = ModuleSettings.getConfigSetting("CentralRepository", "db.postgresql.user"); // NON-NLS
|
||||
String userPasswordString = ModuleSettings.getConfigSetting("CentralRepository", "db.postgresql.password"); // NON-NLS
|
||||
|
||||
return !host.equals(hostString) || !Integer.toString(port).equals(portString)
|
||||
|| !dbName.equals(dbNameString) || !Integer.toString(bulkThreshold).equals(bulkThresholdString)
|
||||
@ -514,9 +525,9 @@ public final class PostgresEamDbSettings {
|
||||
}
|
||||
|
||||
/**
|
||||
* To prevent issues where one command can honor case and another cannot,
|
||||
* we will force the dbname to lower case.
|
||||
*
|
||||
* To prevent issues where one command can honor case and another cannot, we
|
||||
* will force the dbname to lower case.
|
||||
*
|
||||
* @return the dbName
|
||||
*/
|
||||
public String getDbName() {
|
||||
@ -530,7 +541,7 @@ public final class PostgresEamDbSettings {
|
||||
if (dbName == null || dbName.isEmpty()) {
|
||||
throw new EamDbException("Invalid database name. Cannot be empty."); // NON-NLS
|
||||
} else if (!Pattern.matches(DB_NAMES_REGEX, dbName)) {
|
||||
throw new EamDbException("Invalid database name. Name must start with a letter and can only contain letters, numbers, and '_'."); // NON-NLS
|
||||
throw new EamDbException("Invalid database name. Name must start with a lowercase letter and can only contain lowercase letters, numbers, and '_'."); // NON-NLS
|
||||
}
|
||||
|
||||
this.dbName = dbName.toLowerCase();
|
||||
@ -550,7 +561,7 @@ public final class PostgresEamDbSettings {
|
||||
if (bulkThreshold > 0) {
|
||||
this.bulkThreshold = bulkThreshold;
|
||||
} else {
|
||||
throw new EamDbException("Invalid bulk threshold for database connection."); // NON-NLS
|
||||
throw new EamDbException("Invalid bulk threshold."); // NON-NLS
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Enterprise Artifacts Manager
|
||||
* Central Repository
|
||||
*
|
||||
* Copyright 2015-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
@ -16,7 +16,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel;
|
||||
package org.sleuthkit.autopsy.centralrepository.datamodel;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.Connection;
|
||||
@ -28,7 +28,7 @@ import org.apache.commons.dbcp2.BasicDataSource;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
/**
|
||||
* Sqlite implementation of the enterprise artifacts manager database
|
||||
* Sqlite implementation of the Central Repository database
|
||||
*/
|
||||
public class SqliteEamDb extends AbstractSqlEamDb {
|
||||
|
||||
@ -40,7 +40,14 @@ public class SqliteEamDb extends AbstractSqlEamDb {
|
||||
|
||||
private final SqliteEamDbSettings dbSettings;
|
||||
|
||||
public synchronized static SqliteEamDb getInstance() {
|
||||
/**
|
||||
* Get the singleton instance of SqliteEamDb
|
||||
*
|
||||
* @return the singleton instance of SqliteEamDb
|
||||
*
|
||||
* @throws EamDbException if one or more default correlation type(s) have an invalid db table name.
|
||||
*/
|
||||
public synchronized static SqliteEamDb getInstance() throws EamDbException {
|
||||
if (instance == null) {
|
||||
instance = new SqliteEamDb();
|
||||
}
|
||||
@ -48,11 +55,30 @@ public class SqliteEamDb extends AbstractSqlEamDb {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private SqliteEamDb() {
|
||||
/**
|
||||
*
|
||||
* @throws EamDbException if the AbstractSqlEamDb class has one or more default
|
||||
* correlation type(s) having an invalid db table name.
|
||||
*/
|
||||
private SqliteEamDb() throws EamDbException {
|
||||
dbSettings = new SqliteEamDbSettings();
|
||||
updateSettings();
|
||||
bulkArtifactsThreshold = dbSettings.getBulkThreshold();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdownConnections() throws EamDbException {
|
||||
try {
|
||||
synchronized(this) {
|
||||
if (null != connectionPool) {
|
||||
connectionPool.close();
|
||||
connectionPool = null; // force it to be re-created on next connect()
|
||||
}
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
throw new EamDbException("Failed to close existing database connections.", ex); // NON-NLS
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSettings() {
|
||||
synchronized (this) {
|
||||
@ -77,24 +103,28 @@ public class SqliteEamDb extends AbstractSqlEamDb {
|
||||
dropContent.executeUpdate("DELETE FROM organizations");
|
||||
dropContent.executeUpdate("DELETE FROM cases");
|
||||
dropContent.executeUpdate("DELETE FROM data_sources");
|
||||
dropContent.executeUpdate("DELETE FROM global_reference_sets");
|
||||
dropContent.executeUpdate("DELETE FROM global_files");
|
||||
dropContent.executeUpdate("DELETE FROM reference_sets");
|
||||
dropContent.executeUpdate("DELETE FROM artifact_types");
|
||||
dropContent.executeUpdate("DELETE FROM db_info");
|
||||
|
||||
String instancesTemplate = "DELETE FROM %s_instances";
|
||||
for (EamArtifact.Type type : DEFAULT_ARTIFACT_TYPES) {
|
||||
dropContent.executeUpdate(String.format(instancesTemplate, type.getName().toLowerCase()));
|
||||
String referencesTemplate = "DELETE FROM global_files";
|
||||
for (EamArtifact.Type type : DEFAULT_CORRELATION_TYPES) {
|
||||
dropContent.executeUpdate(String.format(instancesTemplate, type.getDbTableName()));
|
||||
// FUTURE: support other reference types
|
||||
if (type.getId() == EamArtifact.FILES_TYPE_ID) {
|
||||
dropContent.executeUpdate(String.format(referencesTemplate, type.getDbTableName()));
|
||||
}
|
||||
}
|
||||
|
||||
dropContent.executeUpdate("VACUUM");
|
||||
dbSettings.insertDefaultDatabaseContent();
|
||||
|
||||
} catch (SQLException ex) {
|
||||
LOGGER.log(Level.WARNING, "Failed to reset database.", ex);
|
||||
} finally {
|
||||
EamDbUtil.closeConnection(conn);
|
||||
}
|
||||
|
||||
dbSettings.insertDefaultDatabaseContent();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -132,7 +162,7 @@ public class SqliteEamDb extends AbstractSqlEamDb {
|
||||
protected Connection connect() throws EamDbException {
|
||||
synchronized (this) {
|
||||
if (!EamDb.isEnabled()) {
|
||||
throw new EamDbException("Enterprise artifacts manager is not enabled"); // NON-NLS
|
||||
throw new EamDbException("Central Repository module is not enabled"); // NON-NLS
|
||||
}
|
||||
|
||||
if (connectionPool == null) {
|
||||
@ -147,6 +177,12 @@ public class SqliteEamDb extends AbstractSqlEamDb {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getConflictClause() {
|
||||
// For sqlite, our conflict clause is part of the table schema
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getBadTags() {
|
||||
return dbSettings.getBadTags();
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Enterprise Artifacts Manager
|
||||
* Central Repository
|
||||
*
|
||||
* Copyright 2015-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
@ -16,7 +16,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel;
|
||||
package org.sleuthkit.autopsy.centralrepository.datamodel;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@ -35,13 +35,13 @@ import org.sleuthkit.autopsy.coreutils.ModuleSettings;
|
||||
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
|
||||
|
||||
/**
|
||||
* Settings for the sqlite implementation of the enterprise artifacts manager database
|
||||
* Settings for the sqlite implementation of the Central Repository database
|
||||
*/
|
||||
public final class SqliteEamDbSettings {
|
||||
|
||||
private final static Logger LOGGER = Logger.getLogger(SqliteEamDbSettings.class.getName());
|
||||
private final String DEFAULT_DBNAME = "EnterpriseArtifacts.db"; // NON-NLS
|
||||
private final String DEFAULT_DBDIRECTORY = PlatformUtil.getUserDirectory() + File.separator + "enterprise_artifacts_manager"; // NON-NLS
|
||||
private final String DEFAULT_DBNAME = "central_repository.db"; // NON-NLS
|
||||
private final String DEFAULT_DBDIRECTORY = PlatformUtil.getUserDirectory() + File.separator + "central_repository"; // NON-NLS
|
||||
private final int DEFAULT_BULK_THRESHHOLD = 1000;
|
||||
private final String DEFAULT_BAD_TAGS = "Evidence"; // NON-NLS
|
||||
private final String JDBC_DRIVER = "org.sqlite.JDBC"; // NON-NLS
|
||||
@ -54,7 +54,7 @@ public final class SqliteEamDbSettings {
|
||||
private static final String PRAGMA_ENCODING_UTF8 = "PRAGMA encoding = 'UTF-8'";
|
||||
private static final String PRAGMA_PAGE_SIZE_4096 = "PRAGMA page_size = 4096";
|
||||
private static final String PRAGMA_FOREIGN_KEYS_ON = "PRAGMA foreign_keys = ON";
|
||||
private final String DB_NAMES_REGEX = "[a-zA-Z]\\w*(\\.db)?";
|
||||
private final String DB_NAMES_REGEX = "[a-z][a-z0-9_]*(\\.db)?";
|
||||
private String dbName;
|
||||
private String dbDirectory;
|
||||
private int bulkThreshold;
|
||||
@ -65,18 +65,18 @@ public final class SqliteEamDbSettings {
|
||||
}
|
||||
|
||||
public void loadSettings() {
|
||||
dbName = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.sqlite.dbName"); // NON-NLS
|
||||
dbName = ModuleSettings.getConfigSetting("CentralRepository", "db.sqlite.dbName"); // NON-NLS
|
||||
if (dbName == null || dbName.isEmpty()) {
|
||||
dbName = DEFAULT_DBNAME;
|
||||
}
|
||||
|
||||
dbDirectory = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.sqlite.dbDirectory"); // NON-NLS
|
||||
dbDirectory = ModuleSettings.getConfigSetting("CentralRepository", "db.sqlite.dbDirectory"); // NON-NLS
|
||||
if (dbDirectory == null || dbDirectory.isEmpty()) {
|
||||
dbDirectory = DEFAULT_DBDIRECTORY;
|
||||
}
|
||||
|
||||
try {
|
||||
String bulkThresholdString = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.sqlite.bulkThreshold"); // NON-NLS
|
||||
String bulkThresholdString = ModuleSettings.getConfigSetting("CentralRepository", "db.sqlite.bulkThreshold"); // NON-NLS
|
||||
if (bulkThresholdString == null || bulkThresholdString.isEmpty()) {
|
||||
this.bulkThreshold = DEFAULT_BULK_THRESHHOLD;
|
||||
} else {
|
||||
@ -89,7 +89,7 @@ public final class SqliteEamDbSettings {
|
||||
this.bulkThreshold = DEFAULT_BULK_THRESHHOLD;
|
||||
}
|
||||
|
||||
String badTagsStr = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.badTags"); // NON-NLS
|
||||
String badTagsStr = ModuleSettings.getConfigSetting("CentralRepository", "db.badTags"); // NON-NLS
|
||||
if (badTagsStr == null || badTagsStr.isEmpty()) {
|
||||
badTagsStr = DEFAULT_BAD_TAGS;
|
||||
}
|
||||
@ -99,10 +99,10 @@ public final class SqliteEamDbSettings {
|
||||
public void saveSettings() {
|
||||
createDbDirectory();
|
||||
|
||||
ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.sqlite.dbName", getDbName()); // NON-NLS
|
||||
ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.sqlite.dbDirectory", getDbDirectory()); // NON-NLS
|
||||
ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.sqlite.bulkThreshold", Integer.toString(getBulkThreshold())); // NON-NLS
|
||||
ModuleSettings.setConfigSetting("EnterpriseArtifactsManager", "db.badTags", String.join(",", badTags)); // NON-NLS
|
||||
ModuleSettings.setConfigSetting("CentralRepository", "db.sqlite.dbName", getDbName()); // NON-NLS
|
||||
ModuleSettings.setConfigSetting("CentralRepository", "db.sqlite.dbDirectory", getDbDirectory()); // NON-NLS
|
||||
ModuleSettings.setConfigSetting("CentralRepository", "db.sqlite.bulkThreshold", Integer.toString(getBulkThreshold())); // NON-NLS
|
||||
ModuleSettings.setConfigSetting("CentralRepository", "db.badTags", String.join(",", badTags)); // NON-NLS
|
||||
}
|
||||
|
||||
/**
|
||||
@ -251,13 +251,13 @@ public final class SqliteEamDbSettings {
|
||||
createCasesTable.append("org_id integer,");
|
||||
createCasesTable.append("case_name text NOT NULL,");
|
||||
createCasesTable.append("creation_date text NOT NULL,");
|
||||
createCasesTable.append("case_number text NOT NULL,");
|
||||
createCasesTable.append("examiner_name text NOT NULL,");
|
||||
createCasesTable.append("examiner_email text NOT NULL,");
|
||||
createCasesTable.append("examiner_phone text NOT NULL,");
|
||||
createCasesTable.append("notes text NOT NULL,");
|
||||
createCasesTable.append("foreign key (org_id) references organizations(id) on update set null on delete set null,");
|
||||
createCasesTable.append("CONSTRAINT case_uid_unique UNIQUE(case_uid)");
|
||||
createCasesTable.append("case_number text,");
|
||||
createCasesTable.append("examiner_name text,");
|
||||
createCasesTable.append("examiner_email text,");
|
||||
createCasesTable.append("examiner_phone text,");
|
||||
createCasesTable.append("notes text,");
|
||||
createCasesTable.append("CONSTRAINT case_uid_unique UNIQUE(case_uid) ON CONFLICT IGNORE,");
|
||||
createCasesTable.append("foreign key (org_id) references organizations(id) ON UPDATE SET NULL ON DELETE SET NULL");
|
||||
createCasesTable.append(")");
|
||||
|
||||
// NOTE: when there are few cases in the cases table, these indices may not be worthwhile
|
||||
@ -274,63 +274,64 @@ public final class SqliteEamDbSettings {
|
||||
|
||||
String dataSourceIdx1 = "CREATE INDEX IF NOT EXISTS data_sources_name ON data_sources (name)";
|
||||
|
||||
StringBuilder createGlobalReferenceSetsTable = new StringBuilder();
|
||||
createGlobalReferenceSetsTable.append("CREATE TABLE IF NOT EXISTS global_reference_sets (");
|
||||
createGlobalReferenceSetsTable.append("id integer primary key autoincrement NOT NULL,");
|
||||
createGlobalReferenceSetsTable.append("org_id integer,");
|
||||
createGlobalReferenceSetsTable.append("set_name text NOT NULL,");
|
||||
createGlobalReferenceSetsTable.append("version text NOT NULL,");
|
||||
createGlobalReferenceSetsTable.append("import_date text NOT NULL,");
|
||||
createGlobalReferenceSetsTable.append("foreign key (org_id) references organizations(id) on update set null on delete set null");
|
||||
createGlobalReferenceSetsTable.append(")");
|
||||
StringBuilder createReferenceSetsTable = new StringBuilder();
|
||||
createReferenceSetsTable.append("CREATE TABLE IF NOT EXISTS reference_sets (");
|
||||
createReferenceSetsTable.append("id integer primary key autoincrement NOT NULL,");
|
||||
createReferenceSetsTable.append("org_id integer NOT NULL,");
|
||||
createReferenceSetsTable.append("set_name text NOT NULL,");
|
||||
createReferenceSetsTable.append("version text NOT NULL,");
|
||||
createReferenceSetsTable.append("import_date text NOT NULL,");
|
||||
createReferenceSetsTable.append("foreign key (org_id) references organizations(id) ON UPDATE SET NULL ON DELETE SET NULL");
|
||||
createReferenceSetsTable.append(")");
|
||||
|
||||
String globalReferenceSetsIdx1 = "CREATE INDEX IF NOT EXISTS global_reference_sets_org_id ON global_reference_sets (org_id)";
|
||||
String referenceSetsIdx1 = "CREATE INDEX IF NOT EXISTS reference_sets_org_id ON reference_sets (org_id)";
|
||||
|
||||
StringBuilder createGlobalFilesTable = new StringBuilder();
|
||||
createGlobalFilesTable.append("CREATE TABLE IF NOT EXISTS global_files (");
|
||||
createGlobalFilesTable.append("id integer primary key autoincrement NOT NULL,");
|
||||
createGlobalFilesTable.append("global_reference_set_id integer,");
|
||||
createGlobalFilesTable.append("value text NOT NULL,");
|
||||
createGlobalFilesTable.append("known_status text NOT NULL,");
|
||||
createGlobalFilesTable.append("comment text NOT NULL,");
|
||||
createGlobalFilesTable.append("CONSTRAINT global_files_multi_unique UNIQUE(global_reference_set_id, value)");
|
||||
createGlobalFilesTable.append("foreign key (global_reference_set_id) references global_reference_sets(id) on update set null on delete set null");
|
||||
createGlobalFilesTable.append(")");
|
||||
// Each "%s" will be replaced with the relevant reference_TYPE table name.
|
||||
StringBuilder createReferenceTypesTableTemplate = new StringBuilder();
|
||||
createReferenceTypesTableTemplate.append("CREATE TABLE IF NOT EXISTS %s (");
|
||||
createReferenceTypesTableTemplate.append("id integer primary key autoincrement NOT NULL,");
|
||||
createReferenceTypesTableTemplate.append("reference_set_id integer,");
|
||||
createReferenceTypesTableTemplate.append("value text NOT NULL,");
|
||||
createReferenceTypesTableTemplate.append("known_status text NOT NULL,");
|
||||
createReferenceTypesTableTemplate.append("comment text,");
|
||||
createReferenceTypesTableTemplate.append("CONSTRAINT %s_multi_unique UNIQUE(reference_set_id, value) ON CONFLICT IGNORE,");
|
||||
createReferenceTypesTableTemplate.append("foreign key (reference_set_id) references reference_sets(id) ON UPDATE SET NULL ON DELETE SET NULL");
|
||||
createReferenceTypesTableTemplate.append(")");
|
||||
|
||||
String globalFilesIdx1 = "CREATE INDEX IF NOT EXISTS global_files_value ON global_files (value)";
|
||||
String globalFilesIdx2 = "CREATE INDEX IF NOT EXISTS global_files_value_known_status ON global_files (value, known_status)";
|
||||
// Each "%s" will be replaced with the relevant reference_TYPE table name.
|
||||
String referenceTypesIdx1 = "CREATE INDEX IF NOT EXISTS %s_value ON %s (value)";
|
||||
String referenceTypesIdx2 = "CREATE INDEX IF NOT EXISTS %s_value_known_status ON %s (value, known_status)";
|
||||
|
||||
StringBuilder createArtifactTypesTable = new StringBuilder();
|
||||
createArtifactTypesTable.append("CREATE TABLE IF NOT EXISTS artifact_types (");
|
||||
createArtifactTypesTable.append("id integer primary key autoincrement NOT NULL,");
|
||||
createArtifactTypesTable.append("name text NOT NULL,");
|
||||
createArtifactTypesTable.append("supported integer NOT NULL,");
|
||||
createArtifactTypesTable.append("enabled integer NOT NULL,");
|
||||
createArtifactTypesTable.append("CONSTRAINT artifact_type_name_unique UNIQUE (name)");
|
||||
createArtifactTypesTable.append(")");
|
||||
StringBuilder createCorrelationTypesTable = new StringBuilder();
|
||||
createCorrelationTypesTable.append("CREATE TABLE IF NOT EXISTS correlation_types (");
|
||||
createCorrelationTypesTable.append("id integer primary key autoincrement NOT NULL,");
|
||||
createCorrelationTypesTable.append("display_name text NOT NULL,");
|
||||
createCorrelationTypesTable.append("db_table_name text NOT NULL,");
|
||||
createCorrelationTypesTable.append("supported integer NOT NULL,");
|
||||
createCorrelationTypesTable.append("enabled integer NOT NULL,");
|
||||
createCorrelationTypesTable.append("CONSTRAINT correlation_types_names UNIQUE (display_name, db_table_name)");
|
||||
createCorrelationTypesTable.append(")");
|
||||
|
||||
// NOTE: there are API methods that query by one of: name, supported, or enabled.
|
||||
// Only name is currently implemented, but, there will only be a small number
|
||||
// of artifact_types, so there is no benefit to having any indices.
|
||||
// Each "%s" will be replaced with the relevant TYPE_instances table name.
|
||||
StringBuilder createArtifactInstancesTableTemplate = new StringBuilder();
|
||||
createArtifactInstancesTableTemplate.append("CREATE TABLE IF NOT EXISTS %s_instances (");
|
||||
createArtifactInstancesTableTemplate.append("CREATE TABLE IF NOT EXISTS %s (");
|
||||
createArtifactInstancesTableTemplate.append("id integer primary key autoincrement NOT NULL,");
|
||||
createArtifactInstancesTableTemplate.append("case_id integer,");
|
||||
createArtifactInstancesTableTemplate.append("data_source_id integer,");
|
||||
createArtifactInstancesTableTemplate.append("value text NOT NULL,");
|
||||
createArtifactInstancesTableTemplate.append("file_path text NOT NULL,");
|
||||
createArtifactInstancesTableTemplate.append("known_status text NOT NULL,");
|
||||
createArtifactInstancesTableTemplate.append("comment text NOT NULL,");
|
||||
createArtifactInstancesTableTemplate.append("CONSTRAINT %s_instances_multi_unique UNIQUE(case_id, data_source_id, value, file_path),");
|
||||
createArtifactInstancesTableTemplate.append("foreign key (case_id) references cases(id) on update set null on delete set null,");
|
||||
createArtifactInstancesTableTemplate.append("foreign key (data_source_id) references data_sources(id) on update set null on delete set null");
|
||||
createArtifactInstancesTableTemplate.append("comment text,");
|
||||
createArtifactInstancesTableTemplate.append("CONSTRAINT %s_multi_unique UNIQUE(case_id, data_source_id, value, file_path) ON CONFLICT IGNORE,");
|
||||
createArtifactInstancesTableTemplate.append("foreign key (case_id) references cases(id) ON UPDATE SET NULL ON DELETE SET NULL,");
|
||||
createArtifactInstancesTableTemplate.append("foreign key (data_source_id) references data_sources(id) ON UPDATE SET NULL ON DELETE SET NULL");
|
||||
createArtifactInstancesTableTemplate.append(")");
|
||||
|
||||
// TODO: do we need any more indices?
|
||||
String instancesIdx1 = "CREATE INDEX IF NOT EXISTS %s_instances_case_id ON %s_instances (case_id)";
|
||||
String instancesIdx2 = "CREATE INDEX IF NOT EXISTS %s_instances_data_source_id ON %s_instances (data_source_id)";
|
||||
String instancesIdx3 = "CREATE INDEX IF NOT EXISTS %s_instances_value ON %s_instances (value)";
|
||||
String instancesIdx4 = "CREATE INDEX IF NOT EXISTS %s_instances_value_known_status ON %s_instances (value, known_status)";
|
||||
// Each "%s" will be replaced with the relevant TYPE_instances table name.
|
||||
String instancesIdx1 = "CREATE INDEX IF NOT EXISTS %s_case_id ON %s (case_id)";
|
||||
String instancesIdx2 = "CREATE INDEX IF NOT EXISTS %s_data_source_id ON %s (data_source_id)";
|
||||
String instancesIdx3 = "CREATE INDEX IF NOT EXISTS %s_value ON %s (value)";
|
||||
String instancesIdx4 = "CREATE INDEX IF NOT EXISTS %s_value_known_status ON %s (value, known_status)";
|
||||
|
||||
StringBuilder createDbInfoTable = new StringBuilder();
|
||||
createDbInfoTable.append("CREATE TABLE IF NOT EXISTS db_info (");
|
||||
@ -365,32 +366,41 @@ public final class SqliteEamDbSettings {
|
||||
stmt.execute(createDataSourcesTable.toString());
|
||||
stmt.execute(dataSourceIdx1);
|
||||
|
||||
stmt.execute(createGlobalReferenceSetsTable.toString());
|
||||
stmt.execute(globalReferenceSetsIdx1);
|
||||
stmt.execute(createReferenceSetsTable.toString());
|
||||
stmt.execute(referenceSetsIdx1);
|
||||
|
||||
stmt.execute(createGlobalFilesTable.toString());
|
||||
stmt.execute(globalFilesIdx1);
|
||||
stmt.execute(globalFilesIdx2);
|
||||
|
||||
stmt.execute(createArtifactTypesTable.toString());
|
||||
stmt.execute(createCorrelationTypesTable.toString());
|
||||
|
||||
stmt.execute(createDbInfoTable.toString());
|
||||
|
||||
// Create a separate table for each artifact type
|
||||
List<EamArtifact.Type> DEFAULT_ARTIFACT_TYPES = EamArtifact.getDefaultArtifactTypes();
|
||||
// Create a separate instance and reference table for each artifact type
|
||||
List<EamArtifact.Type> DEFAULT_CORRELATION_TYPES = EamArtifact.getDefaultCorrelationTypes();
|
||||
|
||||
String type_name;
|
||||
for (EamArtifact.Type type : DEFAULT_ARTIFACT_TYPES) {
|
||||
type_name = type.getName();
|
||||
stmt.execute(String.format(createArtifactInstancesTableTemplate.toString(), type_name, type_name));
|
||||
stmt.execute(String.format(instancesIdx1, type_name, type_name));
|
||||
stmt.execute(String.format(instancesIdx2, type_name, type_name));
|
||||
stmt.execute(String.format(instancesIdx3, type_name, type_name));
|
||||
stmt.execute(String.format(instancesIdx4, type_name, type_name));
|
||||
String reference_type_dbname;
|
||||
String instance_type_dbname;
|
||||
for (EamArtifact.Type type : DEFAULT_CORRELATION_TYPES) {
|
||||
reference_type_dbname = EamDbUtil.correlationTypeToReferenceTableName(type);
|
||||
instance_type_dbname = EamDbUtil.correlationTypeToInstanceTableName(type);
|
||||
|
||||
stmt.execute(String.format(createArtifactInstancesTableTemplate.toString(), instance_type_dbname, instance_type_dbname));
|
||||
stmt.execute(String.format(instancesIdx1, instance_type_dbname, instance_type_dbname));
|
||||
stmt.execute(String.format(instancesIdx2, instance_type_dbname, instance_type_dbname));
|
||||
stmt.execute(String.format(instancesIdx3, instance_type_dbname, instance_type_dbname));
|
||||
stmt.execute(String.format(instancesIdx4, instance_type_dbname, instance_type_dbname));
|
||||
|
||||
// FUTURE: allow more than the FILES type
|
||||
if (type.getId() == EamArtifact.FILES_TYPE_ID) {
|
||||
stmt.execute(String.format(createReferenceTypesTableTemplate.toString(), reference_type_dbname, reference_type_dbname));
|
||||
stmt.execute(String.format(referenceTypesIdx1, reference_type_dbname, reference_type_dbname));
|
||||
stmt.execute(String.format(referenceTypesIdx2, reference_type_dbname, reference_type_dbname));
|
||||
}
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error initializing db schema.", ex); // NON-NLS
|
||||
return false;
|
||||
} catch (EamDbException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error getting default correlation types. Likely due to one or more Type's with an invalid db table name."); // NON-NLS
|
||||
return false;
|
||||
} finally {
|
||||
EamDbUtil.closeConnection(conn);
|
||||
}
|
||||
@ -403,16 +413,16 @@ public final class SqliteEamDbSettings {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean result = EamDbUtil.insertDefaultArtifactTypes(conn)
|
||||
boolean result = EamDbUtil.insertDefaultCorrelationTypes(conn)
|
||||
&& EamDbUtil.insertSchemaVersion(conn);
|
||||
EamDbUtil.closeConnection(conn);
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean isChanged() {
|
||||
String dbNameString = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.sqlite.dbName"); // NON-NLS
|
||||
String dbDirectoryString = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.sqlite.dbDirectory"); // NON-NLS
|
||||
String bulkThresholdString = ModuleSettings.getConfigSetting("EnterpriseArtifactsManager", "db.sqlite.bulkThreshold"); // NON-NLS
|
||||
String dbNameString = ModuleSettings.getConfigSetting("CentralRepository", "db.sqlite.dbName"); // NON-NLS
|
||||
String dbDirectoryString = ModuleSettings.getConfigSetting("CentralRepository", "db.sqlite.dbDirectory"); // NON-NLS
|
||||
String bulkThresholdString = ModuleSettings.getConfigSetting("CentralRepository", "db.sqlite.bulkThreshold"); // NON-NLS
|
||||
|
||||
return !dbName.equals(dbNameString)
|
||||
|| !dbDirectory.equals(dbDirectoryString)
|
||||
@ -435,7 +445,7 @@ public final class SqliteEamDbSettings {
|
||||
if (dbName == null || dbName.isEmpty()) {
|
||||
throw new EamDbException("Invalid database file name. Cannot be null or empty."); // NON-NLS
|
||||
} else if (!Pattern.matches(DB_NAMES_REGEX, dbName)) {
|
||||
throw new EamDbException("Invalid database file name. Name must start with a letter and can only contain letters, numbers, and '_'."); // NON-NLS
|
||||
throw new EamDbException("Invalid database file name. Name must start with a lowercase letter and can only contain lowercase letters, numbers, and '_'."); // NON-NLS
|
||||
}
|
||||
|
||||
this.dbName = dbName;
|
||||
@ -455,7 +465,7 @@ public final class SqliteEamDbSettings {
|
||||
if (bulkThreshold > 0) {
|
||||
this.bulkThreshold = bulkThreshold;
|
||||
} else {
|
||||
throw new EamDbException("Invalid bulk threshold for database connection."); // NON-NLS
|
||||
throw new EamDbException("Invalid bulk threshold."); // NON-NLS
|
||||
}
|
||||
}
|
||||
|
||||
@ -491,7 +501,7 @@ public final class SqliteEamDbSettings {
|
||||
if (dbDirectory != null && !dbDirectory.isEmpty()) {
|
||||
this.dbDirectory = dbDirectory;
|
||||
} else {
|
||||
throw new EamDbException("Error invalid directory for sqlite database. Cannot be null or empty"); // NON-NLS
|
||||
throw new EamDbException("Invalid directory for sqlite database. Cannot empty"); // NON-NLS
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Enterprise Artifacts Manager
|
||||
* Central Repository
|
||||
*
|
||||
* Copyright 2015-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
@ -16,13 +16,13 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.eventlisteners;
|
||||
package org.sleuthkit.autopsy.centralrepository.eventlisteners;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamArtifact;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDbException;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDb;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifact;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
|
||||
|
||||
/**
|
||||
* Thread to send info to remote DB that tags a file as known bad.
|
||||
@ -33,24 +33,23 @@ public class BadFileTagRunner implements Runnable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final EamArtifact artifact;
|
||||
private final EamDb dbManager;
|
||||
|
||||
public BadFileTagRunner(EamArtifact artifact) {
|
||||
this.artifact = artifact;
|
||||
this.dbManager = EamDb.getInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (!EamDb.isEnabled()) {
|
||||
LOGGER.log(Level.WARNING, "Enterprise artifacts manager database not configured"); // NON-NLS
|
||||
LOGGER.log(Level.WARNING, "Central Repository database not configured"); // NON-NLS
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
EamDb dbManager = EamDb.getInstance();
|
||||
dbManager.setArtifactInstanceKnownBad(this.artifact);
|
||||
} catch (EamDbException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error connecting to enterprise artifacts manager database.", ex); //NON-NLS
|
||||
LOGGER.log(Level.SEVERE, "Error connecting to Central Repository database.", ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Enterprise Artifacts Manager
|
||||
* Central Repository
|
||||
*
|
||||
* Copyright 2015-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
@ -16,10 +16,11 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.eventlisteners;
|
||||
package org.sleuthkit.autopsy.centralrepository.eventlisteners;
|
||||
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
@ -29,13 +30,14 @@ import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent;
|
||||
import org.sleuthkit.autopsy.casemodule.events.DataSourceAddedEvent;
|
||||
import org.sleuthkit.autopsy.casemodule.services.TagsManager;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamArtifact;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamArtifactInstance;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamArtifactUtil;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamCase;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDataSource;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDbException;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamOrganization;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifact;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifactInstance;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifactUtil;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamCase;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDataSource;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamOrganization;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifactTag;
|
||||
@ -45,11 +47,10 @@ import org.sleuthkit.datamodel.TagName;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
import org.sleuthkit.datamodel.TskDataException;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDb;
|
||||
|
||||
/**
|
||||
* Listen for case events and update entries in the enterprise artifacts manager
|
||||
* database accordingly
|
||||
* Listen for case events and update entries in the Central Repository database
|
||||
* accordingly
|
||||
*/
|
||||
@Messages({"caseeventlistener.evidencetag=Evidence"})
|
||||
public class CaseEventListener implements PropertyChangeListener {
|
||||
@ -58,7 +59,13 @@ public class CaseEventListener implements PropertyChangeListener {
|
||||
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
EamDb dbManager = EamDb.getInstance();
|
||||
EamDb dbManager;
|
||||
try {
|
||||
dbManager = EamDb.getInstance();
|
||||
} catch (EamDbException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Failed to get instance of db manager.", ex);
|
||||
return;
|
||||
}
|
||||
switch (Case.Events.valueOf(evt.getPropertyName())) {
|
||||
case CONTENT_TAG_ADDED: {
|
||||
if (!EamDb.isEnabled()) {
|
||||
@ -75,7 +82,8 @@ public class CaseEventListener implements PropertyChangeListener {
|
||||
|| (af.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS)
|
||||
|| (af.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.SLACK)
|
||||
|| (af.getKnown() == TskData.FileKnown.KNOWN)
|
||||
|| (af.isDir() == true)) {
|
||||
|| (af.isDir() == true)
|
||||
|| (!af.isMetaFlagSet(TskData.TSK_FS_META_FLAG_ENUM.ALLOC))) {
|
||||
break;
|
||||
}
|
||||
|
||||
@ -92,33 +100,34 @@ public class CaseEventListener implements PropertyChangeListener {
|
||||
if (md5 == null || md5.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
String deviceId = "";
|
||||
String deviceId;
|
||||
try {
|
||||
deviceId = Case.getCurrentCase().getSleuthkitCase().getDataSource(af.getDataSource().getId()).getDeviceId();
|
||||
} catch (TskCoreException | TskDataException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error, failed to get deviceID or data source from current case.", ex);
|
||||
return;
|
||||
}
|
||||
|
||||
EamArtifact eamArtifact;
|
||||
try {
|
||||
EamArtifact.Type filesType = dbManager.getCorrelationArtifactTypeByName("FILES");
|
||||
EamArtifact.Type filesType = dbManager.getCorrelationTypeById(EamArtifact.FILES_TYPE_ID);
|
||||
eamArtifact = new EamArtifact(filesType, af.getMd5Hash());
|
||||
EamArtifactInstance cei = new EamArtifactInstance(
|
||||
new EamCase(Case.getCurrentCase().getName(), Case.getCurrentCase().getDisplayName()),
|
||||
new EamDataSource(deviceId, dsName),
|
||||
af.getParentPath() + af.getName(),
|
||||
tagAdded.getComment(),
|
||||
EamArtifactInstance.KnownStatus.BAD,
|
||||
TskData.FileKnown.BAD,
|
||||
EamArtifactInstance.GlobalStatus.LOCAL
|
||||
);
|
||||
eamArtifact.addInstance(cei);
|
||||
// send update to enterprise artifacts manager db
|
||||
// send update to Central Repository db
|
||||
Runnable r = new BadFileTagRunner(eamArtifact);
|
||||
// TODO: send r into a thread pool instead
|
||||
Thread t = new Thread(r);
|
||||
t.start();
|
||||
} catch (EamDbException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error, unable to get FILES artifact type during CONTENT_TAG_ADDED event.", ex);
|
||||
LOGGER.log(Level.SEVERE, "Error, unable to get FILES correlation type during CONTENT_TAG_ADDED event.", ex);
|
||||
}
|
||||
}
|
||||
} // CONTENT_TAG_ADDED
|
||||
@ -141,8 +150,8 @@ public class CaseEventListener implements PropertyChangeListener {
|
||||
|
||||
if (dbManager.getBadTags().contains(tagName.getDisplayName())) {
|
||||
try {
|
||||
EamArtifact eamArtifact = EamArtifactUtil.fromBlackboardArtifact(bbArtifact, true, dbManager.getCorrelationArtifactTypes(), true);
|
||||
if (null != eamArtifact) {
|
||||
List<EamArtifact> convertedArtifacts = EamArtifactUtil.fromBlackboardArtifact(bbArtifact, true, dbManager.getCorrelationTypes(), true);
|
||||
for (EamArtifact eamArtifact : convertedArtifacts) {
|
||||
eamArtifact.getInstances().get(0).setComment(bbTagAdded.getComment());
|
||||
Runnable r = new BadFileTagRunner(eamArtifact);
|
||||
// TODO: send r into a thread pool instead
|
||||
@ -171,7 +180,7 @@ public class CaseEventListener implements PropertyChangeListener {
|
||||
dbManager.newDataSource(new EamDataSource(deviceId, newDataSource.getName()));
|
||||
}
|
||||
} catch (EamDbException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error connecting to enterprise artifacts manager database.", ex); //NON-NLS
|
||||
LOGGER.log(Level.SEVERE, "Error connecting to Central Repository database.", ex); //NON-NLS
|
||||
} catch (TskCoreException | TskDataException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error getting data source from DATA_SOURCE_ADDED event content.", ex); //NON-NLS
|
||||
}
|
||||
@ -210,9 +219,9 @@ public class CaseEventListener implements PropertyChangeListener {
|
||||
curCase.getCreatedDate(),
|
||||
curCase.getNumber(),
|
||||
curCase.getExaminer(),
|
||||
"",
|
||||
"",
|
||||
"");
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
|
||||
if (!EamDb.isEnabled()) {
|
||||
break;
|
||||
@ -227,7 +236,7 @@ public class CaseEventListener implements PropertyChangeListener {
|
||||
dbManager.newCase(curCeCase);
|
||||
}
|
||||
} catch (EamDbException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error connecting to enterprise artifacts manager database.", ex); //NON-NLS
|
||||
LOGGER.log(Level.SEVERE, "Error connecting to Central Repository database.", ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
} // CURRENT_CASE
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Enterprise Artifacts Manager
|
||||
* Central Repository
|
||||
*
|
||||
* Copyright 2015-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
@ -16,7 +16,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.eventlisteners;
|
||||
package org.sleuthkit.autopsy.centralrepository.eventlisteners;
|
||||
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
@ -34,24 +34,25 @@ import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
import org.sleuthkit.autopsy.ingest.IngestServices;
|
||||
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamArtifact;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamArtifactUtil;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDbException;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifact;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifactUtil;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDb;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
|
||||
|
||||
/**
|
||||
* Listen for ingest events and update entries in the enterprise artifacts manager database accordingly
|
||||
* Listen for ingest events and update entries in the Central Repository
|
||||
* database accordingly
|
||||
*/
|
||||
public class IngestEventsListener {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(EamArtifact.class.getName());
|
||||
|
||||
final Collection<String> addedCeArtifactTrackerSet = new LinkedHashSet<>();
|
||||
|
||||
|
||||
private final PropertyChangeListener pcl1 = new IngestModuleEventListener();
|
||||
private final PropertyChangeListener pcl2 = new IngestJobEventListener();
|
||||
|
||||
@ -75,7 +76,13 @@ public class IngestEventsListener {
|
||||
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
EamDb dbManager = EamDb.getInstance();
|
||||
EamDb dbManager;
|
||||
try {
|
||||
dbManager = EamDb.getInstance();
|
||||
} catch (EamDbException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Failed to connect to Central Repository database.", ex);
|
||||
return;
|
||||
}
|
||||
switch (IngestManager.IngestModuleEvent.valueOf(evt.getPropertyName())) {
|
||||
case DATA_ADDED: {
|
||||
if (!EamDb.isEnabled()) {
|
||||
@ -91,10 +98,9 @@ public class IngestEventsListener {
|
||||
List<EamArtifact> eamArtifacts = new ArrayList<>();
|
||||
try {
|
||||
for (BlackboardArtifact bbArtifact : bbArtifacts) {
|
||||
// eamArtifact will be null OR a EamArtifact containing one EnterpriseArtifactsManagerArtifactInstance.
|
||||
EamArtifact eamArtifact = EamArtifactUtil.fromBlackboardArtifact(bbArtifact, true, dbManager.getCorrelationArtifactTypes(), true);
|
||||
if (null != eamArtifact) {
|
||||
|
||||
// eamArtifact will be null OR a EamArtifact containing one EamArtifactInstance.
|
||||
List<EamArtifact> convertedArtifacts = EamArtifactUtil.fromBlackboardArtifact(bbArtifact, true, dbManager.getCorrelationTypes(), true);
|
||||
for (EamArtifact eamArtifact : convertedArtifacts) {
|
||||
try {
|
||||
// Only do something with this artifact if it's unique within the job
|
||||
if (addedCeArtifactTrackerSet.add(eamArtifact.toString())) {
|
||||
@ -102,10 +108,10 @@ public class IngestEventsListener {
|
||||
// query db for artifact instances having this TYPE/VALUE and knownStatus = "Bad".
|
||||
// if gettKnownStatus() is "Unknown" and this artifact instance was marked bad in a previous case,
|
||||
// create TSK_INTERESTING_ARTIFACT_HIT artifact on BB.
|
||||
List<String> caseDisplayNames = dbManager.getListCasesHavingArtifactInstancesKnownBad(eamArtifact);
|
||||
List<String> caseDisplayNames = dbManager.getListCasesHavingArtifactInstancesKnownBad(eamArtifact.getCorrelationType(), eamArtifact.getCorrelationValue());
|
||||
if (!caseDisplayNames.isEmpty()) {
|
||||
postCorrelatedBadArtifactToBlackboard(bbArtifact,
|
||||
caseDisplayNames);
|
||||
caseDisplayNames);
|
||||
}
|
||||
eamArtifacts.add(eamArtifact);
|
||||
}
|
||||
@ -115,7 +121,7 @@ public class IngestEventsListener {
|
||||
}
|
||||
}
|
||||
} catch (EamDbException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error getting enterprise artifacts manager artifact types.", ex);
|
||||
LOGGER.log(Level.SEVERE, "Error getting correlation types.", ex);
|
||||
}
|
||||
if (FALSE == eamArtifacts.isEmpty()) {
|
||||
// send update to entperirse artifact manager db
|
||||
@ -140,30 +146,30 @@ public class IngestEventsListener {
|
||||
// @@@ This isnt' entirely accurate to do here. We could have multiple
|
||||
// ingest jobs at the same time
|
||||
addedCeArtifactTrackerSet.clear();
|
||||
|
||||
|
||||
} // DATA_SOURCE_ANALYSIS_COMPLETED
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NbBundle.Messages({"EnterpriseArtifactsManager.prevcases.text=Previous Cases",
|
||||
"EnterpriseArtifactsManager.ingestmodule.name=Enterprise Artifacts Manager"})
|
||||
@NbBundle.Messages({"IngestEventsListener.prevcases.text=Previous Cases",
|
||||
"IngestEventsListener.ingestmodule.name=Correlation Engine"})
|
||||
private void postCorrelatedBadArtifactToBlackboard(BlackboardArtifact bbArtifact, List<String> caseDisplayNames) {
|
||||
|
||||
try {
|
||||
AbstractFile af = bbArtifact.getSleuthkitCase().getAbstractFileById(bbArtifact.getObjectID());
|
||||
|
||||
String MODULE_NAME = Bundle.EnterpriseArtifactsManager_ingestmodule_name();
|
||||
|
||||
String MODULE_NAME = Bundle.IngestEventsListener_ingestmodule_name();
|
||||
BlackboardArtifact tifArtifact = af.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT);
|
||||
BlackboardAttribute att = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME, MODULE_NAME,
|
||||
Bundle.EnterpriseArtifactsManager_prevcases_text());
|
||||
Bundle.IngestEventsListener_prevcases_text());
|
||||
BlackboardAttribute att2 = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT, MODULE_NAME,
|
||||
"Previous Case: " + caseDisplayNames.stream().distinct().collect(Collectors.joining(",", "", "")));
|
||||
tifArtifact.addAttribute(att);
|
||||
tifArtifact.addAttribute(att2);
|
||||
tifArtifact.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT, MODULE_NAME, bbArtifact.getArtifactID()));
|
||||
|
||||
|
||||
try {
|
||||
// index the artifact for keyword search
|
||||
Blackboard blackboard = Case.getCurrentCase().getServices().getBlackboard();
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Enterprise Artifacts Manager
|
||||
* Central Repository
|
||||
*
|
||||
* Copyright 2015-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
@ -16,14 +16,14 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.eventlisteners;
|
||||
package org.sleuthkit.autopsy.centralrepository.eventlisteners;
|
||||
|
||||
import java.beans.PropertyChangeListener;
|
||||
import org.openide.modules.ModuleInstall;
|
||||
import org.openide.util.actions.CallableSystemAction;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.actions.EamEditCaseInfoAction;
|
||||
import org.sleuthkit.autopsy.centralrepository.actions.EamEditCaseInfoAction;
|
||||
|
||||
/**
|
||||
* Install event listeners during module initialization
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Enterprise Artifacts Manager
|
||||
* Central Repository
|
||||
*
|
||||
* Copyright 2015-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
@ -16,15 +16,15 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.eventlisteners;
|
||||
package org.sleuthkit.autopsy.centralrepository.eventlisteners;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.logging.Level;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamArtifact;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDbException;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDb;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifact;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
|
||||
|
||||
/**
|
||||
* Thread to insert a new artifact into remote DB.
|
||||
@ -34,30 +34,28 @@ public class NewArtifactsRunner implements Runnable {
|
||||
private static final Logger LOGGER = Logger.getLogger(NewArtifactsRunner.class.getName());
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final EamDb dbManager;
|
||||
private final Collection<EamArtifact> eamArtifacts;
|
||||
|
||||
@SuppressWarnings(value = {"unchecked", "rawtypes"})
|
||||
public NewArtifactsRunner(Collection<EamArtifact> eamArtifacts) {
|
||||
this.dbManager = EamDb.getInstance();
|
||||
this.eamArtifacts = new ArrayList(eamArtifacts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (!EamDb.isEnabled()) {
|
||||
LOGGER.log(Level.WARNING, "Enterprise artifacts manager database not configured"); // NON-NLS
|
||||
LOGGER.log(Level.WARNING, "Central Repository database not configured"); // NON-NLS
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
EamDb dbManager = EamDb.getInstance();
|
||||
|
||||
for (EamArtifact eamArtifact : eamArtifacts) {
|
||||
dbManager.addArtifact(eamArtifact);
|
||||
}
|
||||
} catch (EamDbException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error connecting to enterprise artifacts manager database.", ex); //NON-NLS
|
||||
LOGGER.log(Level.SEVERE, "Error connecting to Central Repository database.", ex); //NON-NLS
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 619 B |
Binary file not shown.
After Width: | Height: | Size: 724 B |
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Enterprise Artifacts Manager
|
||||
* Central Repository
|
||||
*
|
||||
* Copyright 2015-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
@ -16,10 +16,10 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.ingestmodule;
|
||||
package org.sleuthkit.autopsy.centralrepository.ingestmodule;
|
||||
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamCase;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDbException;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamCase;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
@ -35,25 +35,24 @@ import org.sleuthkit.autopsy.ingest.IngestMessage;
|
||||
import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter;
|
||||
import org.sleuthkit.autopsy.ingest.IngestServices;
|
||||
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamArtifact;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamArtifactInstance;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDataSource;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifact;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifactInstance;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDataSource;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.HashUtility;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamOrganization;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamOrganization;
|
||||
import org.sleuthkit.datamodel.TskDataException;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDb;
|
||||
|
||||
/**
|
||||
* Ingest module for inserting entries into the enterprise artifacts manager
|
||||
* database on ingest of a data source
|
||||
* Ingest module for inserting entries into the Central Repository database on
|
||||
* ingest of a data source
|
||||
*/
|
||||
@Messages({"EnterpriseArtifactsManager.prevcases.text=Previous Cases",
|
||||
"EnterpriseArtifactsManager.ingestmodule.name=Enterprise Artifacts Manager"})
|
||||
@Messages({"IngestModule.prevcases.text=Previous Cases"})
|
||||
class IngestModule implements FileIngestModule {
|
||||
|
||||
private final static Logger LOGGER = Logger.getLogger(IngestModule.class.getName());
|
||||
@ -84,11 +83,18 @@ class IngestModule implements FileIngestModule {
|
||||
|| (af.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS)
|
||||
|| (af.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.SLACK)
|
||||
|| (af.getKnown() == TskData.FileKnown.KNOWN)
|
||||
|| (af.isDir() == true)) {
|
||||
|| (af.isDir() == true)
|
||||
|| (!af.isMetaFlagSet(TskData.TSK_FS_META_FLAG_ENUM.ALLOC))) {
|
||||
return ProcessResult.OK;
|
||||
}
|
||||
|
||||
EamDb dbManager = EamDb.getInstance();
|
||||
EamDb dbManager;
|
||||
try {
|
||||
dbManager = EamDb.getInstance();
|
||||
} catch (EamDbException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error connecting to Central Repository database.", ex);
|
||||
return ProcessResult.ERROR;
|
||||
}
|
||||
|
||||
// only continue if we are correlating filesType
|
||||
if (!filesType.isEnabled()) {
|
||||
@ -101,15 +107,13 @@ class IngestModule implements FileIngestModule {
|
||||
return ProcessResult.OK;
|
||||
}
|
||||
|
||||
EamArtifact eamArtifact = new EamArtifact(filesType, md5);
|
||||
|
||||
// If unknown to both the hash module and as a globally known artifact in the EAM DB, correlate to other cases
|
||||
if (af.getKnown() == TskData.FileKnown.UNKNOWN) {
|
||||
// query db for artifact instances having this MD5 and knownStatus = "Bad".
|
||||
try {
|
||||
// if af.getKnown() is "UNKNOWN" and this artifact instance was marked bad in a previous case,
|
||||
// create TSK_INTERESTING_FILE artifact on BB.
|
||||
List<String> caseDisplayNames = dbManager.getListCasesHavingArtifactInstancesKnownBad(eamArtifact);
|
||||
List<String> caseDisplayNames = dbManager.getListCasesHavingArtifactInstancesKnownBad(filesType, md5);
|
||||
if (!caseDisplayNames.isEmpty()) {
|
||||
postCorrelatedBadFileToBlackboard(af, caseDisplayNames);
|
||||
}
|
||||
@ -121,7 +125,7 @@ class IngestModule implements FileIngestModule {
|
||||
|
||||
// Make a TSK_HASHSET_HIT blackboard artifact for global known bad files
|
||||
try {
|
||||
if (dbManager.isArtifactGlobalKnownBad(eamArtifact)) {
|
||||
if (dbManager.isArtifactlKnownBadByReference(filesType, md5)) {
|
||||
postCorrelatedHashHitToBlackboard(af);
|
||||
}
|
||||
} catch (EamDbException ex) {
|
||||
@ -130,12 +134,13 @@ class IngestModule implements FileIngestModule {
|
||||
}
|
||||
|
||||
try {
|
||||
EamArtifact eamArtifact = new EamArtifact(filesType, md5);
|
||||
EamArtifactInstance cefi = new EamArtifactInstance(
|
||||
eamCase,
|
||||
eamDataSource,
|
||||
af.getParentPath() + af.getName(),
|
||||
"",
|
||||
EamArtifactInstance.KnownStatus.UNKNOWN,
|
||||
null,
|
||||
TskData.FileKnown.UNKNOWN,
|
||||
EamArtifactInstance.GlobalStatus.LOCAL
|
||||
);
|
||||
eamArtifact.addInstance(cefi);
|
||||
@ -159,15 +164,21 @@ class IngestModule implements FileIngestModule {
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
EamDb dbManager = EamDb.getInstance();
|
||||
|
||||
EamDb dbManager;
|
||||
try {
|
||||
dbManager = EamDb.getInstance();
|
||||
} catch (EamDbException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error connecting to Central Repository database.", ex);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
dbManager.bulkInsertArtifacts();
|
||||
} catch (EamDbException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error doing bulk insert of artifacts.", ex); // NON-NLS
|
||||
}
|
||||
try {
|
||||
Long count = dbManager.getCountArtifactInstancesByCaseDataSource(new EamArtifactInstance(eamCase, eamDataSource));
|
||||
Long count = dbManager.getCountArtifactInstancesByCaseDataSource(eamCase.getCaseUUID(), eamDataSource.getDeviceID());
|
||||
LOGGER.log(Level.INFO, "{0} artifacts in db for case: {1} ds:{2}", new Object[]{count, eamCase.getDisplayName(), eamDataSource.getName()}); // NON-NLS
|
||||
} catch (EamDbException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error counting artifacts.", ex); // NON-NLS
|
||||
@ -179,8 +190,8 @@ class IngestModule implements FileIngestModule {
|
||||
|
||||
// see ArtifactManagerTimeTester for details
|
||||
@Messages({
|
||||
"EnterpriseArtifactsManager.notfyBubble.title=Enterprise Artifacts Manager Not Initialized",
|
||||
"EnterpriseArtifactsManager.errorMessage.isNotEnabled=Enterprise artifacts manager settings are not initialized, cannot run enteprise artifact manager ingest module."
|
||||
"IngestModule.notfyBubble.title=Central Repository Not Initialized",
|
||||
"IngestModule.errorMessage.isNotEnabled=Central Repository settings are not initialized, cannot run Correlation Engine ingest module."
|
||||
})
|
||||
@Override
|
||||
public void startUp(IngestJobContext context) throws IngestModuleException {
|
||||
@ -194,7 +205,7 @@ class IngestModule implements FileIngestModule {
|
||||
*/
|
||||
if (RuntimeProperties.runningWithGUI()) {
|
||||
if (1L == warningMsgRefCounter.incrementAndGet(jobId)) {
|
||||
MessageNotifyUtil.Notify.warn(Bundle.EnterpriseArtifactsManager_notfyBubble_title(), Bundle.EnterpriseArtifactsManager_errorMessage_isNotEnabled());
|
||||
MessageNotifyUtil.Notify.warn(Bundle.IngestModule_notfyBubble_title(), Bundle.IngestModule_errorMessage_isNotEnabled());
|
||||
}
|
||||
}
|
||||
return;
|
||||
@ -203,20 +214,29 @@ class IngestModule implements FileIngestModule {
|
||||
jobId = context.getJobId();
|
||||
eamCase = new EamCase(Case.getCurrentCase().getName(), Case.getCurrentCase().getDisplayName());
|
||||
|
||||
String deviceId = "";
|
||||
String deviceId;
|
||||
try {
|
||||
deviceId = Case.getCurrentCase().getSleuthkitCase().getDataSource(context.getDataSource().getId()).getDeviceId();
|
||||
} catch (TskCoreException | TskDataException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error getting data source device id in ingest module start up.", ex); // NON-NLS
|
||||
throw new IngestModuleException("Error getting data source device id in ingest module start up.", ex); // NON-NLS
|
||||
}
|
||||
|
||||
eamDataSource = new EamDataSource(deviceId, context.getDataSource().getName());
|
||||
|
||||
EamDb dbManager = EamDb.getInstance();
|
||||
EamDb dbManager;
|
||||
try {
|
||||
filesType = dbManager.getCorrelationArtifactTypeByName("FILES");
|
||||
dbManager = EamDb.getInstance();
|
||||
} catch (EamDbException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error getting correlation artifact type FILES in startUp.", ex); // NON-NLS
|
||||
throw new IngestModuleException("Error getting correlation artifact type FILES in startUp.", ex); // NON-NLS
|
||||
LOGGER.log(Level.SEVERE, "Error connecting to Central Repository database.", ex); // NON-NLS
|
||||
throw new IngestModuleException("Error connecting to Central Repository database.", ex); // NON-NLS
|
||||
}
|
||||
|
||||
try {
|
||||
filesType = dbManager.getCorrelationTypeById(EamArtifact.FILES_TYPE_ID);
|
||||
} catch (EamDbException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error getting correlation type FILES in ingest module start up.", ex); // NON-NLS
|
||||
throw new IngestModuleException("Error getting correlation type FILES in ingest module start up.", ex); // NON-NLS
|
||||
}
|
||||
|
||||
// TODO: once we implement a shared cache, load/init it here w/ syncronized and define reference counter
|
||||
@ -230,8 +250,8 @@ class IngestModule implements FileIngestModule {
|
||||
dbManager.newDataSource(eamDataSource);
|
||||
}
|
||||
} catch (EamDbException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error creating new data source in startUp.", ex); // NON-NLS
|
||||
throw new IngestModuleException("Error creating new data source in startUp.", ex); // NON-NLS
|
||||
LOGGER.log(Level.SEVERE, "Error creating new data source in ingest module start up.", ex); // NON-NLS
|
||||
throw new IngestModuleException("Error creating new data source in ingest module start up.", ex); // NON-NLS
|
||||
}
|
||||
|
||||
// ensure we have this case defined in the EAM DB
|
||||
@ -245,9 +265,9 @@ class IngestModule implements FileIngestModule {
|
||||
curCase.getCreatedDate(),
|
||||
curCase.getNumber(),
|
||||
curCase.getExaminer(),
|
||||
"",
|
||||
"",
|
||||
"");
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
try {
|
||||
existingCase = dbManager.getCaseDetails(curCeCase.getCaseUUID());
|
||||
if (existingCase == null) {
|
||||
@ -255,8 +275,8 @@ class IngestModule implements FileIngestModule {
|
||||
}
|
||||
|
||||
} catch (EamDbException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error creating new case in startUp.", ex); // NON-NLS
|
||||
throw new IngestModuleException("Error creating new case in startUp.", ex); // NON-NLS
|
||||
LOGGER.log(Level.SEVERE, "Error creating new case in ingest module start up.", ex); // NON-NLS
|
||||
throw new IngestModuleException("Error creating new case in ingest module start up.", ex); // NON-NLS
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -264,10 +284,10 @@ class IngestModule implements FileIngestModule {
|
||||
private void postCorrelatedBadFileToBlackboard(AbstractFile abstractFile, List<String> caseDisplayNames) {
|
||||
|
||||
try {
|
||||
String MODULE_NAME = Bundle.EnterpriseArtifactsManager_ingestmodule_name();
|
||||
String MODULE_NAME = IngestModuleFactory.getModuleName();
|
||||
BlackboardArtifact tifArtifact = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT);
|
||||
BlackboardAttribute att = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME, MODULE_NAME,
|
||||
Bundle.EnterpriseArtifactsManager_prevcases_text());
|
||||
Bundle.IngestModule_prevcases_text());
|
||||
BlackboardAttribute att2 = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT, MODULE_NAME,
|
||||
"Previous Case: " + caseDisplayNames.stream().distinct().collect(Collectors.joining(",", "", "")));
|
||||
tifArtifact.addAttribute(att);
|
||||
@ -294,10 +314,10 @@ class IngestModule implements FileIngestModule {
|
||||
|
||||
private void postCorrelatedHashHitToBlackboard(AbstractFile abstractFile) {
|
||||
try {
|
||||
String MODULE_NAME = Bundle.EnterpriseArtifactsManager_ingestmodule_name();
|
||||
String MODULE_NAME = IngestModuleFactory.getModuleName();
|
||||
BlackboardArtifact tifArtifact = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT);
|
||||
BlackboardAttribute att = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME, MODULE_NAME,
|
||||
Bundle.EnterpriseArtifactsManager_prevcases_text());
|
||||
Bundle.IngestModule_prevcases_text());
|
||||
tifArtifact.addAttribute(att);
|
||||
|
||||
try {
|
||||
@ -330,7 +350,7 @@ class IngestModule implements FileIngestModule {
|
||||
@Messages({"IngestModule.postToBB.fileName=File Name",
|
||||
"IngestModule.postToBB.md5Hash=MD5 Hash",
|
||||
"IngestModule.postToBB.hashSetSource=Source of Hash",
|
||||
"IngestModule.postToBB.eamHit=Enterprise Artifacts Manager",
|
||||
"IngestModule.postToBB.eamHit=Central Repository",
|
||||
"# {0} - Name of file that is Known Bad",
|
||||
"IngestModule.postToBB.knownBadMsg=Known Bad: {0}"})
|
||||
public void sendBadFileInboxMessage(BlackboardArtifact artifact, String name, String md5Hash) {
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Enterprise Artifacts Manager
|
||||
* Central Repository
|
||||
*
|
||||
* Copyright 2015-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
@ -16,26 +16,28 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.ingestmodule;
|
||||
package org.sleuthkit.autopsy.centralrepository.ingestmodule;
|
||||
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.lookup.ServiceProvider;
|
||||
import org.sleuthkit.autopsy.ingest.FileIngestModule;
|
||||
import org.sleuthkit.autopsy.ingest.IngestModuleFactoryAdapter;
|
||||
import org.sleuthkit.autopsy.ingest.IngestModuleGlobalSettingsPanel;
|
||||
import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.optionspanel.GlobalSettingsPanel;
|
||||
import org.sleuthkit.autopsy.centralrepository.optionspanel.GlobalSettingsPanel;
|
||||
|
||||
/**
|
||||
* Factory for enterprise artifacts manager ingest modules
|
||||
* Factory for Central Repository ingest modules
|
||||
*/
|
||||
@ServiceProvider(service = org.sleuthkit.autopsy.ingest.IngestModuleFactory.class)
|
||||
@NbBundle.Messages({"IngestModuleFactory.ingestmodule.name=Correlation Engine",
|
||||
"IngestModuleFactory.ingestmodule.desc=Saves properties to the central repository for later correlation"})
|
||||
public class IngestModuleFactory extends IngestModuleFactoryAdapter {
|
||||
|
||||
private static final String VERSION_NUMBER = "0.8.0";
|
||||
|
||||
static String getModuleName() {
|
||||
return java.util.ResourceBundle.getBundle("org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/Bundle")
|
||||
.getString("OpenIDE-Module-Name");
|
||||
return Bundle.IngestModuleFactory_ingestmodule_name();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -45,8 +47,7 @@ public class IngestModuleFactory extends IngestModuleFactoryAdapter {
|
||||
|
||||
@Override
|
||||
public String getModuleDescription() {
|
||||
return java.util.ResourceBundle.getBundle("org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/Bundle")
|
||||
.getString("OpenIDE-Module-Long-Description");
|
||||
return Bundle.IngestModuleFactory_ingestmodule_desc();
|
||||
}
|
||||
|
||||
@Override
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Enterprise Artifacts Manager
|
||||
* Central Repository
|
||||
*
|
||||
* Copyright 2015-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
@ -104,7 +104,7 @@
|
||||
<Component class="javax.swing.JButton" name="bnOK">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="AddNewOrganizationDialog.bnOK.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="AddNewOrganizationDialog.bnOK.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
@ -114,7 +114,7 @@
|
||||
<Component class="javax.swing.JButton" name="bnCancel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="AddNewOrganizationDialog.bnCancel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="AddNewOrganizationDialog.bnCancel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
@ -124,42 +124,42 @@
|
||||
<Component class="javax.swing.JLabel" name="lbOrganizationName">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="AddNewOrganizationDialog.lbOrganizationName.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="AddNewOrganizationDialog.lbOrganizationName.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lbPocHeading">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="AddNewOrganizationDialog.lbPocHeading.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="AddNewOrganizationDialog.lbPocHeading.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lbPocName">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="AddNewOrganizationDialog.lbPocName.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="AddNewOrganizationDialog.lbPocName.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lbPocEmail">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="AddNewOrganizationDialog.lbPocEmail.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="AddNewOrganizationDialog.lbPocEmail.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lbPocPhone">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="AddNewOrganizationDialog.lbPocPhone.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="AddNewOrganizationDialog.lbPocPhone.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="tfPocName">
|
||||
<Properties>
|
||||
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="AddNewOrganizationDialog.tfName.tooltip" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="AddNewOrganizationDialog.tfName.tooltip" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Enterprise Artifacts Manager
|
||||
* Central Repository
|
||||
*
|
||||
* Copyright 2015-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
@ -16,7 +16,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.optionspanel;
|
||||
package org.sleuthkit.autopsy.centralrepository.optionspanel;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Toolkit;
|
||||
@ -31,12 +31,12 @@ import org.netbeans.spi.options.OptionsPanelController;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.openide.windows.WindowManager;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDbException;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamOrganization;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDb;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamOrganization;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
|
||||
|
||||
/**
|
||||
* Dialog to add a new organization to the enterprise artifacts manager database
|
||||
* Dialog to add a new organization to the Central Repository database
|
||||
*/
|
||||
public class AddNewOrganizationDialog extends javax.swing.JDialog {
|
||||
|
@ -1,14 +1,7 @@
|
||||
OptionsCategory_Name_Enterprise_Artifacts_Manager_Options=Enterprise Artifacts Manager
|
||||
OptionsCategory_Keywords_Enterprise_Artifacts_Manager_Options=Enterprise Artifacts Manager Settings
|
||||
OptionsCategory_Name_Central_Repository_Options=Central Repository
|
||||
OptionsCategory_Keywords_Central_Repository_Options=Central Repository Settings
|
||||
ImportHashDatabaseDialog.known.text=Known
|
||||
ImportHashDatabaseDialog.knownBad.text=Known Bad
|
||||
ImportHashDatabaseDialog.importHashDbMsg=Import Hash Database
|
||||
ImportHashDatabaseDialog.fileNameExtFilter.text=Hash Database File
|
||||
ImportHashDatabaseDialog.failedToGetDbPathMsg=Failed to get the path of the selected database.
|
||||
ImportHashDatabaseDialog.importHashDbErr=Import Hash Database Error
|
||||
ImportHashDatabaseDialog.mustSelectHashDbFilePathMsg=A hash database file path must be selected.
|
||||
ImportHashDatabaseDialog.hashDbDoesNotExistMsg=The selected hash database does not exist.
|
||||
ImportHashDatabaseDialog.errorMessage.failedToOpenHashDbMsg=Failed to open hash database at {0}.
|
||||
EamPostgresSettingsDialog.lbUserPassword.text=User Password :
|
||||
EamPostgresSettingsDialog.lbUserName.text=User Name :
|
||||
EamPostgresSettingsDialog.bnCancel.text=Cancel
|
||||
@ -28,21 +21,18 @@ ImportHashDatabaseDialog.tfDatabaseName.tooltip=Name for this database
|
||||
ImportHashDatabaseDialog.tfDatabaseVersion.tooltip.text=Database Version Number
|
||||
ImportHashDatabaseDialog.knownRadioButton.text=Known (NSRL or other)
|
||||
ImportHashDatabaseDialog.openButton.text=Open...
|
||||
ImportHashDatabaseDialog.databasePathTextField.text=
|
||||
ImportHashDatabaseDialog.cancelButton.text=Cancel
|
||||
ImportHashDatabaseDialog.lbDatabaseVersion.text=Database Version:
|
||||
ImportHashDatabaseDialog.okButton.text=OK
|
||||
ImportHashDatabaseDialog.lbDatabaseName.text=Database Name:
|
||||
ImportHashDatabaseDialog.lbSourceOrganization.text=Source Organization:
|
||||
ImportHashDatabaseDialog.lbDatabaseAttribution.text=Database Attribution:
|
||||
ImportHashDatabaseDialog.lbDatabasePath.text=Database Path:
|
||||
ImportHashDatabaseDialog.lbDatabaseType.text=Type of database:
|
||||
ImportHashDatabaseDialog.knownBadRadioButton.text=Known Bad
|
||||
ImportHashDatabaseDialog.bnNewOrganization.text=Add New Organization
|
||||
ImportHashDatabaseDialog.tfDatabaseName.tooltip=Name for this database
|
||||
ImportHashDatabaseDialog.tfDatabaseVersion.tooltip.text=Database Version Number
|
||||
GlobalSettingsPanel.bnImportDatabase.actionCommand=
|
||||
GlobalSettingsPanel.bnManageTypes.text=Manage Artifact Types
|
||||
GlobalSettingsPanel.bnManageTags.actionCommand=
|
||||
GlobalSettingsPanel.bnManageTags.toolTipText=
|
||||
GlobalSettingsPanel.bnManageTags.text=Manage Tags
|
||||
@ -59,10 +49,7 @@ AddNewOrganizationDialog.bnOK.text=OK
|
||||
AddNewOrganizationDialog.tfName.tooltip=POC Name
|
||||
ManageTagsDialog.okButton.text=OK
|
||||
ManageTagsDialog.cancelButton.text=Cancel
|
||||
ManageArtifactTypesDialog.cancelButton.text=Cancel
|
||||
ManageArtifactTypesDialog.okButton.text=OK
|
||||
ManageArtifactTypesDialog.lbWarningMsg.text=Warning Message
|
||||
ManageArtifactTypesDialog.taInstructionsMsg.text=Select one or more artifact types to store in the database and use for correlation during Ingest.
|
||||
ManageArtifactTypesDialog.taInstructionsMsg.text=Enable one or more correlation properties to use for correlation during ingest. Note, these properties are global and impact all users of the central repository.
|
||||
EamSqliteSettingsDialog.bnOk.text=OK
|
||||
EamPostgresSettingsDialog.bnSave.text=Save
|
||||
EamDbSettingsDialog.pnDatabaseConnectionSettings.border.title=Database Settings
|
||||
@ -88,3 +75,10 @@ GlobalSettingsPanel.lbDbPlatformTypeLabel.text=Type:
|
||||
GlobalSettingsPanel.lbDbNameLabel.text=Name:
|
||||
GlobalSettingsPanel.bnDbConfigure.text=Configure
|
||||
GlobalSettingsPanel.lbDbLocationLabel.text=Location:
|
||||
ManageCorrelationPropertiesDialog.lbWarningMsg.text=Warning Message
|
||||
ManageCorrelationPropertiesDialog.cancelButton.text=Cancel
|
||||
ManageCorrelationPropertiesDialog.okButton.text=OK
|
||||
GlobalSettingsPanel.bnManageProperties.text=Manage Correlation Properties
|
||||
ImportHashDatabaseDialog.lbInstructions.text=Choose an .idx file to import into the central repository.
|
||||
ImportHashDatabaseDialog.lbFilePath.text=File Path:
|
||||
ImportHashDatabaseDialog.tfFilePath.text=
|
@ -60,7 +60,7 @@
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
|
||||
<TitledBorder title="Database Settings">
|
||||
<ResourceString PropertyName="titleX" bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="EamDbSettingsDialog.pnDatabaseConnectionSettings.border.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString PropertyName="titleX" bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="EamDbSettingsDialog.pnDatabaseConnectionSettings.border.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<Font PropertyName="font" name="Tahoma" size="12" style="0"/>
|
||||
</TitledBorder>
|
||||
</Border>
|
||||
@ -151,17 +151,17 @@
|
||||
<Component class="javax.swing.JLabel" name="lbDatabasePath">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="EamDbSettingsDialog.lbDatabasePath.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="EamDbSettingsDialog.lbDatabasePath.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="tfDatabasePath">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="EamDbSettingsDialog.tfDatabasePath.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="EamDbSettingsDialog.tfDatabasePath.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="EamDbSettingsDialog.tfDatabasePath.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="EamDbSettingsDialog.tfDatabasePath.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
@ -171,7 +171,7 @@
|
||||
<Component class="javax.swing.JButton" name="bnDatabasePathFileOpen">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="EamDbSettingsDialog.bnDatabasePathFileOpen.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="EamDbSettingsDialog.bnDatabasePathFileOpen.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
@ -250,35 +250,35 @@
|
||||
<Component class="javax.swing.JLabel" name="lbHostName">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="EamDbSettingsDialog.lbHostName.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="EamDbSettingsDialog.lbHostName.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lbPort">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="EamDbSettingsDialog.lbPort.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="EamDbSettingsDialog.lbPort.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lbUserName">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="EamDbSettingsDialog.lbUserName.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="EamDbSettingsDialog.lbUserName.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lbUserPassword">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="EamDbSettingsDialog.lbUserPassword.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="EamDbSettingsDialog.lbUserPassword.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lbDatabaseName">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="EamDbSettingsDialog.lbDatabaseName.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="EamDbSettingsDialog.lbDatabaseName.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
@ -297,7 +297,7 @@
|
||||
<Component class="javax.swing.JRadioButton" name="rdioBnSQLite">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="EamDbSettingsDialog.rdioBnSQLite.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="EamDbSettingsDialog.rdioBnSQLite.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
@ -307,7 +307,7 @@
|
||||
<Component class="javax.swing.JRadioButton" name="rdioBnPostgreSQL">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="EamDbSettingsDialog.rdioBnPostgreSQL.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="EamDbSettingsDialog.rdioBnPostgreSQL.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
@ -317,7 +317,7 @@
|
||||
<Component class="javax.swing.JRadioButton" name="rdioBnDisabled">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="EamDbSettingsDialog.rdioBnDisabled.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="EamDbSettingsDialog.rdioBnDisabled.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
@ -374,7 +374,7 @@
|
||||
<Component class="javax.swing.JButton" name="bnCancel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="EamDbSettingsDialog.bnCancel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="EamDbSettingsDialog.bnCancel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
@ -384,7 +384,7 @@
|
||||
<Component class="javax.swing.JButton" name="bnOk">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="EamDbSettingsDialog.bnOk.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="EamDbSettingsDialog.bnOk.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
@ -394,7 +394,7 @@
|
||||
<Component class="javax.swing.JButton" name="bnTest">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="EamDbSettingsDialog.bnTest.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="EamDbSettingsDialog.bnTest.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
@ -404,7 +404,7 @@
|
||||
<Component class="javax.swing.JButton" name="bnCreateDb">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="EamDbSettingsDialog.bnCreateDb.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="EamDbSettingsDialog.bnCreateDb.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
@ -422,7 +422,7 @@
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
|
||||
<TitledBorder title="Setup Guidance">
|
||||
<ResourceString PropertyName="titleX" bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="EamDbSettingsDialog.pnSetupGuidance.border.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString PropertyName="titleX" bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="EamDbSettingsDialog.pnSetupGuidance.border.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<Font PropertyName="font" name="Tahoma" size="12" style="0"/>
|
||||
</TitledBorder>
|
||||
</Border>
|
@ -3,7 +3,7 @@
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.optionspanel;
|
||||
package org.sleuthkit.autopsy.centralrepository.optionspanel;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Cursor;
|
||||
@ -20,19 +20,20 @@ import javax.swing.JFileChooser;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
import org.netbeans.spi.options.OptionsPanelController;
|
||||
import org.openide.util.ImageUtilities;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.openide.windows.WindowManager;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
|
||||
import org.sleuthkit.autopsy.corecomponents.TextPrompt;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDb;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDbException;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDbPlatformEnum;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.PostgresEamDbSettings;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.SqliteEamDbSettings;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbPlatformEnum;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.PostgresEamDbSettings;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.SqliteEamDbSettings;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -53,7 +54,7 @@ public class EamDbSettingsDialog extends JDialog {
|
||||
/**
|
||||
* Creates new form EamDbSettingsDialog
|
||||
*/
|
||||
@Messages({"EamDbSettingsDialog.title.text=Enterprise Artifacts Manager Settings"})
|
||||
@Messages({"EamDbSettingsDialog.title.text=Central Repository Database Configuration"})
|
||||
public EamDbSettingsDialog() {
|
||||
super((JFrame) WindowManager.getDefault().getMainWindow(),
|
||||
Bundle.EamDbSettingsDialog_title_text(),
|
||||
@ -546,17 +547,67 @@ public class EamDbSettingsDialog extends JDialog {
|
||||
}
|
||||
}//GEN-LAST:event_bnCreateDbActionPerformed
|
||||
|
||||
@Messages({"EamDbSettingsDialog.okButton.errorTitle.text=Restart Required.",
|
||||
"EamDbSettingsDialog.okButton.errorMsg.text=Please restart Autopsy to begin using the new database platform.",
|
||||
"EamDbSettingsDialog.okButton.connectionErrorMsg.text=Failed to connect to Central Repository database."})
|
||||
private void bnOkActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnOkActionPerformed
|
||||
/**
|
||||
* We have to shutdown the previous platform's connection pool first;
|
||||
* assuming it wasn't DISABLED. This will close any existing idle
|
||||
* connections.
|
||||
*
|
||||
* The next use of an EamDb API method will start a new connection pool
|
||||
* using those new settings.
|
||||
*/
|
||||
try {
|
||||
EamDb previousDbManager = EamDb.getInstance();
|
||||
if (null != previousDbManager) {
|
||||
// NOTE: do not set/save the seleted platform before calling this.
|
||||
EamDb.getInstance().shutdownConnections();
|
||||
}
|
||||
} catch (EamDbException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Failed to close database connections in previously selected platform.", ex); // NON-NLS
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
JOptionPane.showMessageDialog(null,
|
||||
Bundle.EamDbSettingsDialog_okButton_errorMsg_text(),
|
||||
Bundle.EamDbSettingsDialog_okButton_errorTitle_text(),
|
||||
JOptionPane.WARNING_MESSAGE);
|
||||
});
|
||||
}
|
||||
|
||||
// Even if we fail to close the existing connections, make sure that we
|
||||
// save the new connection settings, so an Autopsy restart will correctly
|
||||
// start with the new settings.
|
||||
EamDbPlatformEnum.setSelectedPlatform(selectedPlatform.name());
|
||||
EamDbPlatformEnum.saveSelectedPlatform();
|
||||
|
||||
switch (selectedPlatform) {
|
||||
case POSTGRESQL:
|
||||
// save the new PostgreSQL settings
|
||||
dbSettingsPostgres.saveSettings();
|
||||
EamDb.getInstance().updateSettings();
|
||||
// Load those newly saved settings into the postgres db manager instance
|
||||
// in case we are still using the same instance.
|
||||
try {
|
||||
EamDb.getInstance().updateSettings();
|
||||
} catch (EamDbException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Failed to connect to Central Repository database.", ex);
|
||||
setGuidanceMessage(Bundle.EamDbSettingsDialog_okButton_connectionErrorMsg_text(), true);
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
case SQLITE:
|
||||
// save the new SQLite settings
|
||||
dbSettingsSqlite.saveSettings();
|
||||
EamDb.getInstance().updateSettings();
|
||||
// Load those newly saved settings into the sqlite db manager instance
|
||||
// in case we are still using the same instance.
|
||||
try {
|
||||
EamDb.getInstance().updateSettings();
|
||||
} catch (EamDbException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Failed to connect to Central Repository database.", ex);
|
||||
setGuidanceMessage(Bundle.EamDbSettingsDialog_okButton_connectionErrorMsg_text(), true);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case DISABLED:
|
||||
break;
|
||||
@ -847,7 +898,7 @@ public class EamDbSettingsDialog extends JDialog {
|
||||
*
|
||||
* @return true
|
||||
*/
|
||||
@Messages({"EamDbSettingsDialog.validation.finished=Click OK to save your database settings and return to the Options. Or select a differnt database type."})
|
||||
@Messages({"EamDbSettingsDialog.validation.finished=Click OK to save your database settings and return to the Options. Or select a different database type."})
|
||||
private boolean enableOkButton() {
|
||||
if (testingStatus == DatabaseTestResult.TESTEDOK || selectedPlatform == EamDbPlatformEnum.DISABLED) {
|
||||
bnOk.setEnabled(true);
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Enterprise Artifacts Manager
|
||||
* Central Repository
|
||||
*
|
||||
* Copyright 2015-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
@ -16,7 +16,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.optionspanel;
|
||||
package org.sleuthkit.autopsy.centralrepository.optionspanel;
|
||||
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
@ -33,11 +33,11 @@ import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
/**
|
||||
* Controller for the main settings panel
|
||||
*/
|
||||
@OptionsPanelController.TopLevelRegistration(categoryName = "#OptionsCategory_Name_Enterprise_Artifacts_Manager_Options",
|
||||
iconBase = "org/sleuthkit/autopsy/experimental/images/options-icon.png",
|
||||
@OptionsPanelController.TopLevelRegistration(categoryName = "#OptionsCategory_Name_Central_Repository_Options",
|
||||
iconBase = "org/sleuthkit/autopsy/centralrepository/images/options-icon.png",
|
||||
position = 14,
|
||||
keywords = "#OptionsCategory_Keywords_Enterprise_Artifacts_Manager_Options",
|
||||
keywordsCategory = "EnterpriseArtifactsManager")
|
||||
keywords = "#OptionsCategory_Keywords_Central_Repository_Options",
|
||||
keywordsCategory = "CentralRepository")
|
||||
public final class EamOptionsPanelController extends OptionsPanelController {
|
||||
|
||||
private GlobalSettingsPanel panel;
|
||||
@ -111,8 +111,8 @@ public final class EamOptionsPanelController extends OptionsPanelController {
|
||||
return panel;
|
||||
}
|
||||
|
||||
@Messages({"EnterpriseArtifactsManagerOptionsController.moduleErr=Error processing value changes.",
|
||||
"EnterpriseArtifactsManagerOptionsController.moduleErr.msg=Value change processing failed."})
|
||||
@Messages({"EamOptionsController.moduleErr=Error processing value changes.",
|
||||
"EamOptionsController.moduleErr.msg=Value change processing failed."})
|
||||
void changed() {
|
||||
if (!changed) {
|
||||
changed = true;
|
||||
@ -122,8 +122,8 @@ public final class EamOptionsPanelController extends OptionsPanelController {
|
||||
} catch (Exception ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error processing property change", ex); //NON-NLS
|
||||
MessageNotifyUtil.Notify.show(
|
||||
Bundle.EnterpriseArtifactsManagerOptionsController_moduleErr(),
|
||||
Bundle.EnterpriseArtifactsManagerOptionsController_moduleErr_msg(),
|
||||
Bundle.EamOptionsController_moduleErr(),
|
||||
Bundle.EamOptionsController_moduleErr_msg(),
|
||||
MessageNotifyUtil.MessageType.ERROR);
|
||||
}
|
||||
}
|
||||
@ -133,8 +133,8 @@ public final class EamOptionsPanelController extends OptionsPanelController {
|
||||
} catch (Exception e) {
|
||||
LOGGER.log(Level.SEVERE, "Error processing property change validation.", e); //NON-NLS
|
||||
MessageNotifyUtil.Notify.show(
|
||||
Bundle.EnterpriseArtifactsManagerOptionsController_moduleErr(),
|
||||
Bundle.EnterpriseArtifactsManagerOptionsController_moduleErr_msg(),
|
||||
Bundle.EamOptionsController_moduleErr(),
|
||||
Bundle.EamOptionsController_moduleErr_msg(),
|
||||
MessageNotifyUtil.MessageType.ERROR);
|
||||
}
|
||||
}
|
@ -50,7 +50,7 @@
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
|
||||
<TitledBorder title="Database Configuration">
|
||||
<ResourceString PropertyName="titleX" bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="GlobalSettingsPanel.pnDatabaseConfiguration.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString PropertyName="titleX" bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="GlobalSettingsPanel.pnDatabaseConfiguration.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<Font PropertyName="font" name="Tahoma" size="12" style="0"/>
|
||||
</TitledBorder>
|
||||
</Border>
|
||||
@ -113,28 +113,28 @@
|
||||
<Component class="javax.swing.JLabel" name="lbDbPlatformTypeLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="GlobalSettingsPanel.lbDbPlatformTypeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="GlobalSettingsPanel.lbDbPlatformTypeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lbDbNameLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="GlobalSettingsPanel.lbDbNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="GlobalSettingsPanel.lbDbNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lbDbLocationLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="GlobalSettingsPanel.lbDbLocationLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="GlobalSettingsPanel.lbDbLocationLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="bnDbConfigure">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="GlobalSettingsPanel.bnDbConfigure.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="GlobalSettingsPanel.bnDbConfigure.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
@ -183,13 +183,13 @@
|
||||
<Component class="javax.swing.JButton" name="bnImportDatabase">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/experimental/images/import16.png"/>
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/centralrepository/images/import16.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="GlobalSettingsPanel.bnImportDatabase.label" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="GlobalSettingsPanel.bnImportDatabase.label" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="actionCommand" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="GlobalSettingsPanel.bnImportDatabase.actionCommand" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="GlobalSettingsPanel.bnImportDatabase.actionCommand" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
@ -199,13 +199,13 @@
|
||||
<Component class="javax.swing.JButton" name="bnManageTags">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="GlobalSettingsPanel.bnManageTags.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="GlobalSettingsPanel.bnManageTags.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="GlobalSettingsPanel.bnManageTags.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="GlobalSettingsPanel.bnManageTags.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="actionCommand" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="GlobalSettingsPanel.bnManageTags.actionCommand" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="GlobalSettingsPanel.bnManageTags.actionCommand" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
@ -215,7 +215,7 @@
|
||||
<Component class="javax.swing.JButton" name="bnManageTypes">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="GlobalSettingsPanel.bnManageTypes.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="GlobalSettingsPanel.bnManageProperties.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
@ -233,7 +233,7 @@
|
||||
</FontInfo>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="GlobalSettingsPanel.tbOops.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="GlobalSettingsPanel.tbOops.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="null"/>
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Enterprise Artifacts Manager
|
||||
* Central Repository
|
||||
*
|
||||
* Copyright 2015-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
@ -16,7 +16,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.optionspanel;
|
||||
package org.sleuthkit.autopsy.centralrepository.optionspanel;
|
||||
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
@ -25,16 +25,15 @@ import javax.swing.SwingUtilities;
|
||||
import org.netbeans.spi.options.OptionsPanelController;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.sleuthkit.autopsy.corecomponents.OptionsPanel;
|
||||
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
|
||||
import org.sleuthkit.autopsy.events.AutopsyEvent;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
import org.sleuthkit.autopsy.ingest.IngestModuleGlobalSettingsPanel;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDbPlatformEnum;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.PostgresEamDbSettings;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.SqliteEamDbSettings;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbPlatformEnum;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.PostgresEamDbSettings;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.SqliteEamDbSettings;
|
||||
|
||||
/**
|
||||
* Main settings panel for the enterprise artifacts manager
|
||||
* Main settings panel for the Central Repository
|
||||
*/
|
||||
public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel implements OptionsPanel {
|
||||
|
||||
@ -44,7 +43,7 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
|
||||
private final IngestJobEventPropertyChangeListener ingestJobEventListener;
|
||||
|
||||
/**
|
||||
* Creates new form EnterpriseArtifactsManagerOptionsPanel
|
||||
* Creates new form EamOptionsPanel
|
||||
*/
|
||||
public GlobalSettingsPanel() {
|
||||
ingestJobEventListener = new IngestJobEventPropertyChangeListener();
|
||||
@ -54,7 +53,7 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
|
||||
addIngestJobEventsListener();
|
||||
}
|
||||
|
||||
@Messages({"GlobalSettingsPanel.title=Global Enterprise Artifacts Manager Settings"})
|
||||
@Messages({"GlobalSettingsPanel.title=Central Repository Settings"})
|
||||
private void customizeComponents() {
|
||||
setName(Bundle.GlobalSettingsPanel_title());
|
||||
}
|
||||
@ -145,7 +144,7 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
bnImportDatabase.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/experimental/images/import16.png"))); // NOI18N
|
||||
bnImportDatabase.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/centralrepository/images/import16.png"))); // NOI18N
|
||||
org.openide.awt.Mnemonics.setLocalizedText(bnImportDatabase, org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.bnImportDatabase.label")); // NOI18N
|
||||
bnImportDatabase.setActionCommand(org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.bnImportDatabase.actionCommand")); // NOI18N
|
||||
bnImportDatabase.addActionListener(new java.awt.event.ActionListener() {
|
||||
@ -163,7 +162,7 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
|
||||
}
|
||||
});
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(bnManageTypes, org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.bnManageTypes.text")); // NOI18N
|
||||
org.openide.awt.Mnemonics.setLocalizedText(bnManageTypes, org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.bnManageProperties.text")); // NOI18N
|
||||
bnManageTypes.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
bnManageTypesActionPerformed(evt);
|
||||
@ -235,7 +234,7 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
|
||||
}//GEN-LAST:event_bnManageTagsActionPerformed
|
||||
|
||||
private void bnManageTypesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnManageTypesActionPerformed
|
||||
ManageArtifactTypesDialog dialog = new ManageArtifactTypesDialog();
|
||||
ManageCorrelationPropertiesDialog dialog = new ManageCorrelationPropertiesDialog();
|
||||
firePropertyChange(OptionsPanelController.PROP_VALID, null, null);
|
||||
}//GEN-LAST:event_bnManageTypesActionPerformed
|
||||
|
@ -30,33 +30,19 @@
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="lbInstructions" max="32767" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="lbWarningMsg" max="32767" attributes="0"/>
|
||||
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
<Component id="okButton" linkSize="1" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="cancelButton" linkSize="1" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="lbDatabaseType" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" pref="19" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="knownRadioButton" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="knownBadRadioButton" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<Component id="lbDatabaseAttribution" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<Group type="103" groupAlignment="1" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="lbDatabasePath" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="databasePathTextField" max="32767" attributes="0"/>
|
||||
<Component id="tfFilePath" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" pref="23" max="-2" attributes="0"/>
|
||||
@ -86,6 +72,21 @@
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="openButton" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="lbDatabaseType" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" pref="19" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="knownRadioButton" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="knownBadRadioButton" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<Component id="lbDatabaseAttribution" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="lbWarningMsg" alignment="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
@ -94,48 +95,56 @@
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="lbInstructions" min="-2" pref="26" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="openButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="databasePathTextField" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="tfFilePath" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lbDatabasePath" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="lbDatabaseType" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="knownRadioButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="knownBadRadioButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="lbDatabaseAttribution" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||
<Component id="bnNewOrganization" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace min="3" pref="3" max="-2" attributes="0"/>
|
||||
<Component id="lbSourceOrganization" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="comboboxSourceOrganization" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||
<Component id="tfDatabaseName" max="32767" attributes="0"/>
|
||||
<Component id="lbDatabaseName" min="-2" pref="20" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="lbDatabaseVersion" alignment="3" min="-2" pref="20" max="-2" attributes="0"/>
|
||||
<Component id="tfDatabaseVersion" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="lbWarningMsg" alignment="0" max="32767" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="okButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="cancelButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="lbDatabaseType" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="knownRadioButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="knownBadRadioButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="lbDatabaseAttribution" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||
<Component id="bnNewOrganization" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="3" pref="3" max="-2" attributes="0"/>
|
||||
<Component id="lbSourceOrganization" min="-2" pref="20" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="comboboxSourceOrganization" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||
<Component id="tfDatabaseName" max="32767" attributes="0"/>
|
||||
<Component id="lbDatabaseName" min="-2" pref="20" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="lbDatabaseVersion" alignment="3" min="-2" pref="20" max="-2" attributes="0"/>
|
||||
<Component id="tfDatabaseVersion" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="lbWarningMsg" min="-2" pref="23" max="-2" attributes="0"/>
|
||||
<EmptySpace pref="44" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="okButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="cancelButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
@ -144,7 +153,7 @@
|
||||
<Component class="javax.swing.JButton" name="okButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="ImportHashDatabaseDialog.okButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="ImportHashDatabaseDialog.okButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
@ -154,24 +163,24 @@
|
||||
<Component class="javax.swing.JButton" name="cancelButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="ImportHashDatabaseDialog.cancelButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="ImportHashDatabaseDialog.cancelButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cancelButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="databasePathTextField">
|
||||
<Component class="javax.swing.JTextField" name="tfFilePath">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="ImportHashDatabaseDialog.databasePathTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="ImportHashDatabaseDialog.tfFilePath.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="openButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="ImportHashDatabaseDialog.openButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="ImportHashDatabaseDialog.openButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
@ -184,7 +193,7 @@
|
||||
<ComponentRef name="buttonGroup1"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="ImportHashDatabaseDialog.knownRadioButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="ImportHashDatabaseDialog.knownRadioButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
@ -195,49 +204,49 @@
|
||||
</Property>
|
||||
<Property name="selected" type="boolean" value="true"/>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="ImportHashDatabaseDialog.knownBadRadioButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="ImportHashDatabaseDialog.knownBadRadioButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lbDatabaseType">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="ImportHashDatabaseDialog.lbDatabaseType.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="ImportHashDatabaseDialog.lbDatabaseType.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lbDatabasePath">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="ImportHashDatabaseDialog.lbDatabasePath.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="ImportHashDatabaseDialog.lbFilePath.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lbDatabaseAttribution">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="ImportHashDatabaseDialog.lbDatabaseAttribution.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="ImportHashDatabaseDialog.lbDatabaseAttribution.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lbSourceOrganization">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="ImportHashDatabaseDialog.lbSourceOrganization.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="ImportHashDatabaseDialog.lbSourceOrganization.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lbDatabaseName">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="ImportHashDatabaseDialog.lbDatabaseName.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="ImportHashDatabaseDialog.lbDatabaseName.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lbDatabaseVersion">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="ImportHashDatabaseDialog.lbDatabaseVersion.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="ImportHashDatabaseDialog.lbDatabaseVersion.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
@ -262,21 +271,21 @@
|
||||
<Component class="javax.swing.JTextField" name="tfDatabaseName">
|
||||
<Properties>
|
||||
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="ImportHashDatabaseDialog.tfDatabaseName.tooltip" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="ImportHashDatabaseDialog.tfDatabaseName.tooltip" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="tfDatabaseVersion">
|
||||
<Properties>
|
||||
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="ImportHashDatabaseDialog.tfDatabaseVersion.tooltip.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="ImportHashDatabaseDialog.tfDatabaseVersion.tooltip.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="bnNewOrganization">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="ImportHashDatabaseDialog.bnNewOrganization.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="ImportHashDatabaseDialog.bnNewOrganization.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
@ -293,5 +302,15 @@
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lbInstructions">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Tahoma" size="12" style="0"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="ImportHashDatabaseDialog.lbInstructions.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Enterprise Artifacts Manager
|
||||
* Central Repository
|
||||
*
|
||||
* Copyright 2015-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
@ -16,7 +16,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.optionspanel;
|
||||
package org.sleuthkit.autopsy.centralrepository.optionspanel;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Toolkit;
|
||||
@ -29,30 +29,38 @@ import java.nio.file.Files;
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.SwingWorker;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
import javax.swing.filechooser.FileNameExtensionFilter;
|
||||
import org.netbeans.api.progress.ProgressHandle;
|
||||
import org.netbeans.spi.options.OptionsPanelController;
|
||||
import org.openide.util.Exceptions;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.openide.windows.WindowManager;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifact;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamArtifactInstance;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDbException;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamGlobalFileInstance;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamGlobalSet;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamOrganization;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDb;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifactInstance;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamGlobalFileInstance;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamGlobalSet;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamOrganization;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
|
||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
|
||||
/**
|
||||
* Instances of this class allow a user to select an existing hash database and
|
||||
@ -63,7 +71,7 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog {
|
||||
private static final Logger LOGGER = Logger.getLogger(ImportHashDatabaseDialog.class.getName());
|
||||
|
||||
private final JFileChooser fileChooser = new JFileChooser();
|
||||
private final static String LAST_FILE_PATH_KEY = "EnterpriseArtifactsManagerImport_Path"; // NON-NLS
|
||||
private final static String LAST_FILE_PATH_KEY = "CentralRepositoryImport_Path"; // NON-NLS
|
||||
private EamOrganization selectedOrg = null;
|
||||
private List<EamOrganization> orgs = null;
|
||||
private final Collection<JTextField> textBoxes;
|
||||
@ -75,9 +83,10 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog {
|
||||
* and add it to the set of hash databases used to classify files as
|
||||
* unknown, known, or known bad.
|
||||
*/
|
||||
@Messages({"ImportHashDatabaseDialog.importHashDbMsg=Import Hash Database"})
|
||||
ImportHashDatabaseDialog() {
|
||||
super((JFrame) WindowManager.getDefault().getMainWindow(),
|
||||
NbBundle.getMessage(ImportHashDatabaseDialog.class, "ImportHashDatabaseDialog.importHashDbMsg"),
|
||||
Bundle.ImportHashDatabaseDialog_importHashDbMsg(),
|
||||
true); // NON-NLS
|
||||
textBoxes = new ArrayList<>();
|
||||
textBoxChangedListener = new TextBoxChangedListener();
|
||||
@ -87,12 +96,14 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog {
|
||||
display();
|
||||
}
|
||||
|
||||
@Messages({"ImportHashDatabaseDialog.fileNameExtFilter.text=Hash Database File",})
|
||||
private void initFileChooser() {
|
||||
fileChooser.setDragEnabled(false);
|
||||
fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
|
||||
String[] EXTENSION = new String[]{"idx"}; //NON-NLS
|
||||
FileNameExtensionFilter filter = new FileNameExtensionFilter(
|
||||
NbBundle.getMessage(this.getClass(), "ImportHashDatabaseDialog.fileNameExtFilter.text"), EXTENSION); // NON-NLS
|
||||
Bundle.ImportHashDatabaseDialog_fileNameExtFilter_text(),
|
||||
EXTENSION); // NON-NLS
|
||||
fileChooser.setFileFilter(filter);
|
||||
fileChooser.setMultiSelectionEnabled(false);
|
||||
}
|
||||
@ -107,6 +118,7 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog {
|
||||
* Register for notifications when the text boxes get updated.
|
||||
*/
|
||||
private void setTextBoxListeners() {
|
||||
textBoxes.add(tfFilePath);
|
||||
textBoxes.add(tfDatabaseName);
|
||||
textBoxes.add(tfDatabaseVersion);
|
||||
addDocumentListeners(textBoxes, textBoxChangedListener);
|
||||
@ -150,7 +162,7 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog {
|
||||
private boolean textFieldsArePopulated() {
|
||||
return !tfDatabaseName.getText().trim().isEmpty()
|
||||
&& !tfDatabaseVersion.getText().trim().isEmpty()
|
||||
&& !databasePathTextField.getText().trim().isEmpty();
|
||||
&& !tfFilePath.getText().trim().isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -177,10 +189,9 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog {
|
||||
*
|
||||
* @return true if it's okay, false otherwise.
|
||||
*/
|
||||
@Messages({"ImportHashDatabaseDialog.validation.notEnabled=Database not initialized. Restart Autopsy."})
|
||||
@Messages({"ImportHashDatabaseDialog.validation.notEnabled=Central Repository is not enabled."})
|
||||
public boolean valid() {
|
||||
lbWarningMsg.setText("");
|
||||
EamDb dbManager = EamDb.getInstance();
|
||||
if (!EamDb.isEnabled()) {
|
||||
lbWarningMsg.setText(Bundle.ImportHashDatabaseDialog_validation_notEnabled());
|
||||
return false;
|
||||
@ -244,7 +255,7 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog {
|
||||
buttonGroup1 = new javax.swing.ButtonGroup();
|
||||
okButton = new javax.swing.JButton();
|
||||
cancelButton = new javax.swing.JButton();
|
||||
databasePathTextField = new javax.swing.JTextField();
|
||||
tfFilePath = new javax.swing.JTextField();
|
||||
openButton = new javax.swing.JButton();
|
||||
knownRadioButton = new javax.swing.JRadioButton();
|
||||
knownBadRadioButton = new javax.swing.JRadioButton();
|
||||
@ -259,6 +270,7 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog {
|
||||
tfDatabaseVersion = new javax.swing.JTextField();
|
||||
bnNewOrganization = new javax.swing.JButton();
|
||||
lbWarningMsg = new javax.swing.JLabel();
|
||||
lbInstructions = new javax.swing.JLabel();
|
||||
|
||||
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
|
||||
|
||||
@ -276,7 +288,7 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog {
|
||||
}
|
||||
});
|
||||
|
||||
databasePathTextField.setText(org.openide.util.NbBundle.getMessage(ImportHashDatabaseDialog.class, "ImportHashDatabaseDialog.databasePathTextField.text")); // NOI18N
|
||||
tfFilePath.setText(org.openide.util.NbBundle.getMessage(ImportHashDatabaseDialog.class, "ImportHashDatabaseDialog.tfFilePath.text")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(openButton, org.openide.util.NbBundle.getMessage(ImportHashDatabaseDialog.class, "ImportHashDatabaseDialog.openButton.text")); // NOI18N
|
||||
openButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
@ -294,7 +306,7 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog {
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(lbDatabaseType, org.openide.util.NbBundle.getMessage(ImportHashDatabaseDialog.class, "ImportHashDatabaseDialog.lbDatabaseType.text")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(lbDatabasePath, org.openide.util.NbBundle.getMessage(ImportHashDatabaseDialog.class, "ImportHashDatabaseDialog.lbDatabasePath.text")); // NOI18N
|
||||
org.openide.awt.Mnemonics.setLocalizedText(lbDatabasePath, org.openide.util.NbBundle.getMessage(ImportHashDatabaseDialog.class, "ImportHashDatabaseDialog.lbFilePath.text")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(lbDatabaseAttribution, org.openide.util.NbBundle.getMessage(ImportHashDatabaseDialog.class, "ImportHashDatabaseDialog.lbDatabaseAttribution.text")); // NOI18N
|
||||
|
||||
@ -325,6 +337,9 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog {
|
||||
lbWarningMsg.setFont(new java.awt.Font("Tahoma", 1, 12)); // NOI18N
|
||||
lbWarningMsg.setForeground(new java.awt.Color(255, 0, 0));
|
||||
|
||||
lbInstructions.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
|
||||
org.openide.awt.Mnemonics.setLocalizedText(lbInstructions, org.openide.util.NbBundle.getMessage(ImportHashDatabaseDialog.class, "ImportHashDatabaseDialog.lbInstructions.text")); // NOI18N
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
|
||||
getContentPane().setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
@ -332,28 +347,18 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog {
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(lbInstructions, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(lbWarningMsg, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGap(18, 18, 18)
|
||||
.addGap(0, 0, Short.MAX_VALUE)
|
||||
.addComponent(okButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(cancelButton))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(lbDatabaseType)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(19, 19, 19)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(knownRadioButton)
|
||||
.addComponent(knownBadRadioButton)))
|
||||
.addComponent(lbDatabaseAttribution))
|
||||
.addGap(0, 0, Short.MAX_VALUE))
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
|
||||
.addComponent(lbDatabasePath)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(databasePathTextField))
|
||||
.addComponent(tfFilePath))
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
|
||||
.addGap(23, 23, 23)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
@ -373,7 +378,18 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog {
|
||||
.addComponent(comboboxSourceOrganization, javax.swing.GroupLayout.Alignment.TRAILING, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(tfDatabaseName))))))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(openButton)))
|
||||
.addComponent(openButton))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(lbDatabaseType)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(19, 19, 19)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(knownRadioButton)
|
||||
.addComponent(knownBadRadioButton)))
|
||||
.addComponent(lbDatabaseAttribution))
|
||||
.addGap(0, 0, Short.MAX_VALUE))
|
||||
.addComponent(lbWarningMsg, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
@ -383,59 +399,64 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog {
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(lbInstructions, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(openButton)
|
||||
.addComponent(databasePathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(tfFilePath, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(lbDatabasePath))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(lbDatabaseType)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(knownRadioButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(knownBadRadioButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(lbDatabaseAttribution)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
|
||||
.addComponent(bnNewOrganization)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(3, 3, 3)
|
||||
.addComponent(lbSourceOrganization, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(comboboxSourceOrganization, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(18, 18, 18)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
|
||||
.addComponent(tfDatabaseName)
|
||||
.addComponent(lbDatabaseName, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(lbDatabaseVersion, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(tfDatabaseVersion, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addGap(18, 18, 18)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(lbWarningMsg, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(okButton)
|
||||
.addComponent(cancelButton)))
|
||||
.addContainerGap())
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(lbDatabaseType)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(knownRadioButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(knownBadRadioButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(lbDatabaseAttribution)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
|
||||
.addComponent(bnNewOrganization)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(3, 3, 3)
|
||||
.addComponent(lbSourceOrganization, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(comboboxSourceOrganization, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(18, 18, 18)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
|
||||
.addComponent(tfDatabaseName)
|
||||
.addComponent(lbDatabaseName, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(lbDatabaseVersion, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(tfDatabaseVersion, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(lbWarningMsg, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap(44, Short.MAX_VALUE))
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(okButton)
|
||||
.addComponent(cancelButton))
|
||||
.addContainerGap())))
|
||||
);
|
||||
|
||||
pack();
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
@Messages({"ImportHashDatabaseDialog.failedToGetDbPathMsg=Failed to get the path of the selected database.",})
|
||||
private void openButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openButtonActionPerformed
|
||||
if (fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
|
||||
File databaseFile = fileChooser.getSelectedFile();
|
||||
try {
|
||||
databasePathTextField.setText(databaseFile.getCanonicalPath());
|
||||
tfFilePath.setText(databaseFile.getCanonicalPath());
|
||||
if (databaseFile.getName().toLowerCase().contains("nsrl")) { //NON-NLS
|
||||
knownRadioButton.setSelected(true);
|
||||
}
|
||||
ModuleSettings.setConfigSetting(ModuleSettings.MAIN_SETTINGS, LAST_FILE_PATH_KEY, databaseFile.getParent());
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(ImportHashDatabaseDialog.class.getName()).log(Level.SEVERE, "Failed to get path of selected database", ex); // NON-NLS
|
||||
JOptionPane.showMessageDialog(this,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"ImportHashDatabaseDialog.failedToGetDbPathMsg")); // NON-NLS
|
||||
lbWarningMsg.setText(Bundle.ImportHashDatabaseDialog_failedToGetDbPathMsg());
|
||||
}
|
||||
}
|
||||
valid();
|
||||
@ -458,73 +479,61 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog {
|
||||
tfDatabaseName.getText().trim(),
|
||||
tfDatabaseVersion.getText().trim(),
|
||||
LocalDate.now());
|
||||
return dbManager.newGlobalSet(eamGlobalSet);
|
||||
return dbManager.newReferencelSet(eamGlobalSet);
|
||||
}
|
||||
|
||||
@Messages({"ImportHashDatabaseDialog.createGlobalSet.failedMsg.text=Failed to store attribution details.",
|
||||
"ImportHashDatabaseDialog.createGlobalSet.failedTitle.text=Import hashdb error."})
|
||||
"ImportHashDatabaseDialog.mustSelectHashDbFilePathMsg=Missing hash database file path.",
|
||||
"ImportHashDatabaseDialog.hashDbDoesNotExistMsg=The selected hash database does not exist.",
|
||||
"# {0} - selected file path",
|
||||
"ImportHashDatabaseDialog.errorMessage.failedToOpenHashDbMsg=Failed to open hash database at {0}.",
|
||||
})
|
||||
private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
|
||||
// Note that the error handlers in this method call return without disposing of the
|
||||
// dialog to allow the user to try again, if desired.
|
||||
String selectedFilePath = databasePathTextField.getText();
|
||||
String selectedFilePath = tfFilePath.getText();
|
||||
|
||||
// have valid file path
|
||||
if (selectedFilePath.isEmpty()) {
|
||||
JOptionPane.showMessageDialog(this,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"ImportHashDatabaseDialog.mustSelectHashDbFilePathMsg"),
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"ImportHashDatabaseDialog.importHashDbErr"),
|
||||
JOptionPane.ERROR_MESSAGE); // NON-NLS
|
||||
lbWarningMsg.setText(Bundle.ImportHashDatabaseDialog_mustSelectHashDbFilePathMsg());
|
||||
return;
|
||||
}
|
||||
File file = new File(selectedFilePath);
|
||||
if (!file.exists()) {
|
||||
JOptionPane.showMessageDialog(this,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"ImportHashDatabaseDialog.hashDbDoesNotExistMsg"),
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"ImportHashDatabaseDialog.importHashDbErr"),
|
||||
JOptionPane.ERROR_MESSAGE); // NON-NLS
|
||||
lbWarningMsg.setText(Bundle.ImportHashDatabaseDialog_hashDbDoesNotExistMsg());
|
||||
return;
|
||||
}
|
||||
|
||||
// create global set
|
||||
int globalSetID = -1;
|
||||
int globalSetID;
|
||||
try {
|
||||
globalSetID = createGlobalSet();
|
||||
} catch (EamDbException ex) {
|
||||
JOptionPane.showMessageDialog(this,
|
||||
Bundle.ImportHashDatabaseDialog_createGlobalSet_failedMsg_text(),
|
||||
Bundle.ImportHashDatabaseDialog_createGlobalSet_failedTitle_text(),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
LOGGER.log(Level.SEVERE, "Failed to create global set.", ex);
|
||||
lbWarningMsg.setText(Bundle.ImportHashDatabaseDialog_createGlobalSet_failedMsg_text());
|
||||
return;
|
||||
}
|
||||
|
||||
// insert hashes
|
||||
EamArtifactInstance.KnownStatus knownStatus = EamArtifactInstance.KnownStatus.UNKNOWN;
|
||||
TskData.FileKnown knownStatus = TskData.FileKnown.UNKNOWN;
|
||||
if (knownRadioButton.isSelected()) {
|
||||
knownStatus = EamArtifactInstance.KnownStatus.KNOWN;
|
||||
knownStatus = TskData.FileKnown.KNOWN;
|
||||
} else if (knownBadRadioButton.isSelected()) {
|
||||
knownStatus = EamArtifactInstance.KnownStatus.BAD;
|
||||
knownStatus = TskData.FileKnown.BAD;
|
||||
}
|
||||
|
||||
String errorMessage = NbBundle.getMessage(this.getClass(),
|
||||
"ImportHashDatabaseDialog.errorMessage.failedToOpenHashDbMsg",
|
||||
selectedFilePath); // NON-NLS
|
||||
String errorMessage = Bundle.ImportHashDatabaseDialog_errorMessage_failedToOpenHashDbMsg(selectedFilePath);
|
||||
// Future, make UI handle more than the "FILES" type.
|
||||
try {
|
||||
new ImportHashDatabaseWorker(selectedFilePath, knownStatus, globalSetID).execute();
|
||||
} catch (Throwable ex) {
|
||||
Logger.getLogger(ImportHashDatabaseDialog.class.getName()).log(Level.WARNING, errorMessage, ex);
|
||||
JOptionPane.showMessageDialog(this,
|
||||
ex.getMessage(),
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"ImportHashDatabaseDialog.importHashDbErr"),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
return;
|
||||
EamArtifact.Type contentType = EamArtifact.getDefaultCorrelationTypes().get(0); // get "FILES" type
|
||||
// run in the background and close dialog
|
||||
SwingUtilities.invokeLater(new ImportHashDatabaseWorker(selectedFilePath, knownStatus, globalSetID, contentType)::execute);
|
||||
dispose();
|
||||
} catch (EamDbException | UnknownHostException ex) {
|
||||
Logger.getLogger(ImportHashDatabaseDialog.class.getName()).log(Level.SEVERE, errorMessage, ex);
|
||||
lbWarningMsg.setText(ex.getMessage());
|
||||
}
|
||||
|
||||
dispose();
|
||||
}//GEN-LAST:event_okButtonActionPerformed
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
@ -552,38 +561,57 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog {
|
||||
}//GEN-LAST:event_comboboxSourceOrganizationActionPerformed
|
||||
|
||||
@NbBundle.Messages({"ImportHashDatabaseDialog.ImportHashDatabaseWorker.displayName=Importing Hash Database"})
|
||||
private class ImportHashDatabaseWorker extends SwingWorker<Object, Void> {
|
||||
private class ImportHashDatabaseWorker extends SwingWorker<Void, Void> {
|
||||
|
||||
private final EamDb dbManager;
|
||||
private final File file;
|
||||
private final EamArtifactInstance.KnownStatus knownStatus;
|
||||
private final TskData.FileKnown knownStatus;
|
||||
private final int globalSetID;
|
||||
private final ProgressHandle progress;
|
||||
private final EamArtifact.Type contentType;
|
||||
|
||||
public ImportHashDatabaseWorker(String filename, EamArtifactInstance.KnownStatus knownStatus, int globalSetID) throws EamDbException, UnknownHostException {
|
||||
this.dbManager = EamDb.getInstance();
|
||||
public ImportHashDatabaseWorker(String filename, TskData.FileKnown knownStatus, int globalSetID, EamArtifact.Type contentType) throws EamDbException, UnknownHostException {
|
||||
this.file = new File(filename);
|
||||
this.knownStatus = knownStatus;
|
||||
this.globalSetID = globalSetID;
|
||||
this.contentType = contentType;
|
||||
this.progress = ProgressHandle.createHandle(Bundle.ImportHashDatabaseDialog_ImportHashDatabaseWorker_displayName());
|
||||
|
||||
if (!EamDb.isEnabled()) {
|
||||
throw new EamDbException("Enterprise artifacts manager database settings were not properly initialized"); // NON-NLS
|
||||
throw new EamDbException("Central Repository database is not enabled."); // NON-NLS
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object doInBackground() throws Exception {
|
||||
ProgressHandle progress = ProgressHandle.createHandle(Bundle.ImportHashDatabaseDialog_ImportHashDatabaseWorker_displayName());
|
||||
importHashDatabase(progress);
|
||||
protected Void doInBackground() throws Exception {
|
||||
importHashDatabase();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Messages({"ImportHashDatabaseDialog.ImportHashDatabaseWorker.error=Failed to import hash database."})
|
||||
protected void done() {
|
||||
progress.finish();
|
||||
try {
|
||||
get();
|
||||
} catch (InterruptedException | ExecutionException ex) {
|
||||
Logger.getLogger(ImportHashDatabaseDialog.class.getName()).log(Level.SEVERE, Bundle.ImportHashDatabaseDialog_ImportHashDatabaseWorker_error(), ex);
|
||||
MessageNotifyUtil.Notify.show(Bundle.ImportHashDatabaseDialog_ImportHashDatabaseWorker_error(),
|
||||
ex.getMessage(),
|
||||
MessageNotifyUtil.MessageType.ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
private long numberOfLinesInFile(File f) throws IOException {
|
||||
return Files.lines(f.toPath()).count();
|
||||
}
|
||||
|
||||
private void importHashDatabase(ProgressHandle progress) throws EamDbException, IOException {
|
||||
@Messages({"# {0} - value content",
|
||||
"ImportHashDatabaseDialog.ImportHashDatabaseWorker.duplicate=Duplicate value {0} found in import file."})
|
||||
private void importHashDatabase() throws EamDbException, IOException {
|
||||
BufferedReader reader = new BufferedReader(new FileReader(file));
|
||||
String line;
|
||||
EamDb dbManager = EamDb.getInstance();
|
||||
Set<EamGlobalFileInstance> globalInstances = new HashSet<>();
|
||||
|
||||
long totalLines = numberOfLinesInFile(file);
|
||||
if (totalLines <= Integer.MAX_VALUE) {
|
||||
@ -609,11 +637,12 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog {
|
||||
knownStatus,
|
||||
"");
|
||||
|
||||
dbManager.prepareGlobalFileInstance(eamGlobalFileInstance);
|
||||
if (!globalInstances.add(eamGlobalFileInstance)) {
|
||||
throw new EamDbException(Bundle.ImportHashDatabaseDialog_ImportHashDatabaseWorker_duplicate(parts[0])); // NON-NLS
|
||||
}
|
||||
}
|
||||
|
||||
dbManager.bulkInsertGlobalFileInstances();
|
||||
progress.finish();
|
||||
dbManager.bulkInsertReferenceTypeEntries(globalInstances, contentType);
|
||||
}
|
||||
}
|
||||
|
||||
@ -622,7 +651,6 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog {
|
||||
private javax.swing.ButtonGroup buttonGroup1;
|
||||
private javax.swing.JButton cancelButton;
|
||||
private javax.swing.JComboBox<String> comboboxSourceOrganization;
|
||||
private javax.swing.JTextField databasePathTextField;
|
||||
private javax.swing.JRadioButton knownBadRadioButton;
|
||||
private javax.swing.JRadioButton knownRadioButton;
|
||||
private javax.swing.JLabel lbDatabaseAttribution;
|
||||
@ -630,11 +658,13 @@ final class ImportHashDatabaseDialog extends javax.swing.JDialog {
|
||||
private javax.swing.JLabel lbDatabasePath;
|
||||
private javax.swing.JLabel lbDatabaseType;
|
||||
private javax.swing.JLabel lbDatabaseVersion;
|
||||
private javax.swing.JLabel lbInstructions;
|
||||
private javax.swing.JLabel lbSourceOrganization;
|
||||
private javax.swing.JLabel lbWarningMsg;
|
||||
private javax.swing.JButton okButton;
|
||||
private javax.swing.JButton openButton;
|
||||
private javax.swing.JTextField tfDatabaseName;
|
||||
private javax.swing.JTextField tfDatabaseVersion;
|
||||
private javax.swing.JTextField tfFilePath;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
}
|
@ -67,7 +67,7 @@
|
||||
<Component class="javax.swing.JButton" name="okButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="ManageArtifactTypesDialog.okButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="ManageCorrelationPropertiesDialog.okButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
@ -77,7 +77,7 @@
|
||||
<Component class="javax.swing.JButton" name="cancelButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="ManageArtifactTypesDialog.cancelButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="ManageCorrelationPropertiesDialog.cancelButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
@ -100,7 +100,7 @@
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.editors2.TableModelEditor">
|
||||
<Table columnCount="2" rowCount="0">
|
||||
<Column editable="false" title="Artifact Type" type="java.lang.String"/>
|
||||
<Column editable="false" title="Correlation Properties" type="java.lang.String"/>
|
||||
<Column editable="true" title="Enable" type="java.lang.Boolean"/>
|
||||
</Table>
|
||||
</Property>
|
||||
@ -123,7 +123,7 @@
|
||||
<Color blue="0" green="0" red="ff" type="rgb"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="ManageArtifactTypesDialog.lbWarningMsg.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="ManageCorrelationPropertiesDialog.lbWarningMsg.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
@ -140,7 +140,7 @@
|
||||
<Property name="lineWrap" type="boolean" value="true"/>
|
||||
<Property name="rows" type="int" value="5"/>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="ManageArtifactTypesDialog.taInstructionsMsg.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="ManageArtifactTypesDialog.taInstructionsMsg.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="wrapStyleWord" type="boolean" value="true"/>
|
||||
<Property name="autoscrolls" type="boolean" value="false"/>
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Enterprise Artifacts Manager
|
||||
* Central Repository
|
||||
*
|
||||
* Copyright 2015-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
@ -16,7 +16,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.optionspanel;
|
||||
package org.sleuthkit.autopsy.centralrepository.optionspanel;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Toolkit;
|
||||
@ -32,30 +32,30 @@ import org.openide.util.Exceptions;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.openide.windows.WindowManager;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamArtifact;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDbException;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDb;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifact;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
|
||||
|
||||
/**
|
||||
* Dialog to handle management of artifact types handled by the enterprise
|
||||
* artifacts manager
|
||||
* Dialog to handle management of artifact types handled by the Central
|
||||
* Repository
|
||||
*/
|
||||
final class ManageArtifactTypesDialog extends javax.swing.JDialog {
|
||||
final class ManageCorrelationPropertiesDialog extends javax.swing.JDialog {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(ManageArtifactTypesDialog.class.getName());
|
||||
private static final Logger LOGGER = Logger.getLogger(ManageCorrelationPropertiesDialog.class.getName());
|
||||
|
||||
private final List<EamArtifact.Type> eamArtifactTypes;
|
||||
private final List<EamArtifact.Type> correlationTypes;
|
||||
|
||||
/**
|
||||
* Displays a dialog that allows a user to select which Type(s) should be
|
||||
* used for Correlation during ingest.
|
||||
*/
|
||||
@Messages({"ManageArtifactTypesDialog.title=Manage Artifact Types"})
|
||||
ManageArtifactTypesDialog() {
|
||||
@Messages({"ManageCorrelationPropertiesDialog.title=Manage Correlation Properties"})
|
||||
ManageCorrelationPropertiesDialog() {
|
||||
super((JFrame) WindowManager.getDefault().getMainWindow(),
|
||||
Bundle.ManageArtifactTypesDialog_title(),
|
||||
Bundle.ManageCorrelationPropertiesDialog_title(),
|
||||
true); // NON-NLS
|
||||
this.eamArtifactTypes = new ArrayList<>();
|
||||
this.correlationTypes = new ArrayList<>();
|
||||
initComponents();
|
||||
customizeComponents();
|
||||
display();
|
||||
@ -72,24 +72,24 @@ final class ManageArtifactTypesDialog extends javax.swing.JDialog {
|
||||
DefaultTableModel model = (DefaultTableModel) tbCorrelatableTypes.getModel();
|
||||
try {
|
||||
EamDb dbManager = EamDb.getInstance();
|
||||
eamArtifactTypes.clear();
|
||||
eamArtifactTypes.addAll(dbManager.getCorrelationArtifactTypes());
|
||||
correlationTypes.clear();
|
||||
correlationTypes.addAll(dbManager.getCorrelationTypes());
|
||||
} catch (EamDbException ex) {
|
||||
Exceptions.printStackTrace(ex);
|
||||
}
|
||||
|
||||
eamArtifactTypes.forEach((aType) -> {
|
||||
model.addRow(new Object[]{aType.getName(), aType.isEnabled()});
|
||||
correlationTypes.forEach((aType) -> {
|
||||
model.addRow(new Object[]{aType.getDisplayName(), aType.isEnabled()});
|
||||
});
|
||||
model.addTableModelListener(new TableModelListener() {
|
||||
@Override
|
||||
public void tableChanged(TableModelEvent evt) {
|
||||
int row = evt.getFirstRow();
|
||||
TableModel model = (TableModel) evt.getSource();
|
||||
Object typeName = model.getValueAt(row, 0);
|
||||
Object displayName = model.getValueAt(row, 0);
|
||||
Boolean enabled = (Boolean) model.getValueAt(row, 1);
|
||||
|
||||
eamArtifactTypes.stream().filter((aType) -> (aType.getName().equals(typeName))).forEachOrdered((aType) -> {
|
||||
correlationTypes.stream().filter((aType) -> (aType.getDisplayName().equals(displayName))).forEachOrdered((aType) -> {
|
||||
aType.setEnabled(enabled);
|
||||
});
|
||||
valid();
|
||||
@ -103,15 +103,15 @@ final class ManageArtifactTypesDialog extends javax.swing.JDialog {
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
@Messages({"ManageArtifactTypesDialog.noneSelected=There are no artifact types enabled."})
|
||||
@Messages({"ManageCorrelationPropertiesDialog.noneSelected=There are no correlation properties enabled."})
|
||||
private boolean valid() {
|
||||
lbWarningMsg.setText("");
|
||||
|
||||
int countEnabled = 0;
|
||||
countEnabled = eamArtifactTypes.stream().filter((aType) -> (aType.isEnabled())).map((_item) -> 1).reduce(countEnabled, Integer::sum);
|
||||
countEnabled = correlationTypes.stream().filter((aType) -> (aType.isEnabled())).map((_item) -> 1).reduce(countEnabled, Integer::sum);
|
||||
|
||||
if (0 == countEnabled) {
|
||||
lbWarningMsg.setText(Bundle.ManageArtifactTypesDialog_noneSelected());
|
||||
lbWarningMsg.setText(Bundle.ManageCorrelationPropertiesDialog_noneSelected());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -135,14 +135,14 @@ final class ManageArtifactTypesDialog extends javax.swing.JDialog {
|
||||
|
||||
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(okButton, org.openide.util.NbBundle.getMessage(ManageArtifactTypesDialog.class, "ManageArtifactTypesDialog.okButton.text")); // NOI18N
|
||||
org.openide.awt.Mnemonics.setLocalizedText(okButton, org.openide.util.NbBundle.getMessage(ManageCorrelationPropertiesDialog.class, "ManageCorrelationPropertiesDialog.okButton.text")); // NOI18N
|
||||
okButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
okButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(cancelButton, org.openide.util.NbBundle.getMessage(ManageArtifactTypesDialog.class, "ManageArtifactTypesDialog.cancelButton.text")); // NOI18N
|
||||
org.openide.awt.Mnemonics.setLocalizedText(cancelButton, org.openide.util.NbBundle.getMessage(ManageCorrelationPropertiesDialog.class, "ManageCorrelationPropertiesDialog.cancelButton.text")); // NOI18N
|
||||
cancelButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
cancelButtonActionPerformed(evt);
|
||||
@ -156,7 +156,7 @@ final class ManageArtifactTypesDialog extends javax.swing.JDialog {
|
||||
|
||||
},
|
||||
new String [] {
|
||||
"Artifact Type", "Enable"
|
||||
"Correlation Properties", "Enable"
|
||||
}
|
||||
) {
|
||||
Class[] types = new Class [] {
|
||||
@ -180,7 +180,7 @@ final class ManageArtifactTypesDialog extends javax.swing.JDialog {
|
||||
|
||||
lbWarningMsg.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
|
||||
lbWarningMsg.setForeground(new java.awt.Color(255, 0, 0));
|
||||
org.openide.awt.Mnemonics.setLocalizedText(lbWarningMsg, org.openide.util.NbBundle.getMessage(ManageArtifactTypesDialog.class, "ManageArtifactTypesDialog.lbWarningMsg.text")); // NOI18N
|
||||
org.openide.awt.Mnemonics.setLocalizedText(lbWarningMsg, org.openide.util.NbBundle.getMessage(ManageCorrelationPropertiesDialog.class, "ManageCorrelationPropertiesDialog.lbWarningMsg.text")); // NOI18N
|
||||
|
||||
taInstructions.setEditable(false);
|
||||
taInstructions.setBackground(new java.awt.Color(240, 240, 240));
|
||||
@ -188,7 +188,7 @@ final class ManageArtifactTypesDialog extends javax.swing.JDialog {
|
||||
taInstructions.setFont(new java.awt.Font("Tahoma", 0, 11)); // NOI18N
|
||||
taInstructions.setLineWrap(true);
|
||||
taInstructions.setRows(5);
|
||||
taInstructions.setText(org.openide.util.NbBundle.getMessage(ManageArtifactTypesDialog.class, "ManageArtifactTypesDialog.taInstructionsMsg.text")); // NOI18N
|
||||
taInstructions.setText(org.openide.util.NbBundle.getMessage(ManageCorrelationPropertiesDialog.class, "ManageArtifactTypesDialog.taInstructionsMsg.text")); // NOI18N
|
||||
taInstructions.setWrapStyleWord(true);
|
||||
taInstructions.setAutoscrolls(false);
|
||||
taInstructions.setBorder(null);
|
||||
@ -239,20 +239,27 @@ final class ManageArtifactTypesDialog extends javax.swing.JDialog {
|
||||
dispose();
|
||||
}//GEN-LAST:event_cancelButtonActionPerformed
|
||||
|
||||
@Messages({"ManageArtifactTypesDialog.okbutton.failure=Error saving updated selections."})
|
||||
@Messages({"ManageCorrelationPropertiesDialog.okbutton.failure=Error saving updated selections."})
|
||||
private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
|
||||
|
||||
if (0 == eamArtifactTypes.size()) {
|
||||
if (0 == correlationTypes.size()) {
|
||||
dispose();
|
||||
} else {
|
||||
EamDb dbManager = EamDb.getInstance();
|
||||
eamArtifactTypes.forEach((aType) -> {
|
||||
EamDb dbManager;
|
||||
try {
|
||||
dbManager = EamDb.getInstance();
|
||||
} catch (EamDbException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Failed to connect to Central Repository database.", ex);
|
||||
lbWarningMsg.setText(Bundle.ManageCorrelationPropertiesDialog_okbutton_failure());
|
||||
return;
|
||||
}
|
||||
correlationTypes.forEach((aType) -> {
|
||||
try {
|
||||
dbManager.updateCorrelationArtifactType(aType);
|
||||
dbManager.updateCorrelationType(aType);
|
||||
dispose();
|
||||
} catch (EamDbException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Failed to updated Enterprise Artifacts Manager artifact types with selections from dialog.", ex); // NON-NLS
|
||||
lbWarningMsg.setText(Bundle.ManageArtifactTypesDialog_okbutton_failure());
|
||||
LOGGER.log(Level.SEVERE, "Failed to update correlation properties with selections from dialog.", ex); // NON-NLS
|
||||
lbWarningMsg.setText(Bundle.ManageCorrelationPropertiesDialog_okbutton_failure());
|
||||
}
|
||||
});
|
||||
}
|
@ -28,16 +28,24 @@
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace pref="233" max="32767" attributes="0"/>
|
||||
<Component id="okButton" linkSize="1" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="cancelButton" linkSize="1" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace min="0" pref="223" max="32767" attributes="0"/>
|
||||
<Component id="okButton" linkSize="1" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="cancelButton" linkSize="1" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||
<Component id="jScrollPane1" pref="357" max="32767" attributes="0"/>
|
||||
<Component id="lbWarnings" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="jScrollPane1" min="-2" pref="367" max="-2" attributes="0"/>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
@ -45,12 +53,14 @@
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jScrollPane1" min="-2" pref="335" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="lbWarnings" pref="16" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="okButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="cancelButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
@ -59,7 +69,7 @@
|
||||
<Component class="javax.swing.JButton" name="okButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="ManageTagsDialog.okButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="ManageTagsDialog.okButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
@ -69,7 +79,7 @@
|
||||
<Component class="javax.swing.JButton" name="cancelButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/optionspanel/Bundle.properties" key="ManageTagsDialog.cancelButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="ManageTagsDialog.cancelButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
@ -95,5 +105,7 @@
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JLabel" name="lbWarnings">
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Enterprise Artifacts Manager
|
||||
* Central Repository
|
||||
*
|
||||
* Copyright 2015-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
@ -16,7 +16,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.optionspanel;
|
||||
package org.sleuthkit.autopsy.centralrepository.optionspanel;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Toolkit;
|
||||
@ -29,11 +29,11 @@ import javax.swing.JFrame;
|
||||
import javax.swing.table.DefaultTableModel;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.openide.windows.WindowManager;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.services.TagsManager;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.autopsy.experimental.enterpriseartifactsmanager.datamodel.EamDb;
|
||||
|
||||
/**
|
||||
* Instances of this class allow a user to select an existing hash database and
|
||||
@ -59,9 +59,18 @@ final class ManageTagsDialog extends javax.swing.JDialog {
|
||||
display();
|
||||
}
|
||||
|
||||
@Messages({"ManageTagsDialog.init.failedConnection.msg=Cannot connect to Central Repository.",
|
||||
"ManageTagsDialog.init.failedGettingTags.msg=Unable to retrieve list of tags."})
|
||||
private void customizeComponents() {
|
||||
//this.okButton.setEnabled(false);
|
||||
EamDb dbManager = EamDb.getInstance();
|
||||
lbWarnings.setText("");
|
||||
EamDb dbManager;
|
||||
try {
|
||||
dbManager = EamDb.getInstance();
|
||||
} catch (EamDbException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Failed to connect to Central Repository database.");
|
||||
lbWarnings.setText(Bundle.ManageTagsDialog_init_failedConnection_msg());
|
||||
return;
|
||||
}
|
||||
List<String> badTags = dbManager.getBadTags();
|
||||
|
||||
List<String> tagNames = new ArrayList<>(badTags);
|
||||
@ -73,6 +82,7 @@ final class ManageTagsDialog extends javax.swing.JDialog {
|
||||
.collect(Collectors.toList()));
|
||||
} catch (TskCoreException ex) {
|
||||
LOGGER.log(Level.WARNING, "Could not get list of tags in case", ex);
|
||||
lbWarnings.setText(Bundle.ManageTagsDialog_init_failedGettingTags_msg());
|
||||
}
|
||||
|
||||
Collections.sort(tagNames);
|
||||
@ -104,6 +114,7 @@ final class ManageTagsDialog extends javax.swing.JDialog {
|
||||
cancelButton = new javax.swing.JButton();
|
||||
jScrollPane1 = new javax.swing.JScrollPane();
|
||||
tblTagNames = new javax.swing.JTable();
|
||||
lbWarnings = new javax.swing.JLabel();
|
||||
|
||||
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
|
||||
|
||||
@ -151,14 +162,19 @@ final class ManageTagsDialog extends javax.swing.JDialog {
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap(233, Short.MAX_VALUE)
|
||||
.addComponent(okButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(cancelButton)
|
||||
.addContainerGap()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(0, 223, Short.MAX_VALUE)
|
||||
.addComponent(okButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(cancelButton))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
|
||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 357, Short.MAX_VALUE)
|
||||
.addComponent(lbWarnings, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addGap(0, 0, Short.MAX_VALUE)))
|
||||
.addContainerGap())
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 367, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(0, 0, Short.MAX_VALUE))
|
||||
);
|
||||
|
||||
layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {cancelButton, okButton});
|
||||
@ -168,11 +184,13 @@ final class ManageTagsDialog extends javax.swing.JDialog {
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 335, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(lbWarnings, javax.swing.GroupLayout.DEFAULT_SIZE, 16, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(okButton)
|
||||
.addComponent(cancelButton))
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
pack();
|
||||
@ -184,11 +202,12 @@ final class ManageTagsDialog extends javax.swing.JDialog {
|
||||
|
||||
|
||||
private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
|
||||
setBadTags();
|
||||
dispose();
|
||||
if (setBadTags()) {
|
||||
dispose();
|
||||
}
|
||||
}//GEN-LAST:event_okButtonActionPerformed
|
||||
|
||||
private void setBadTags() {
|
||||
private boolean setBadTags() {
|
||||
List<String> badTags = new ArrayList<>();
|
||||
|
||||
DefaultTableModel model = (DefaultTableModel) tblTagNames.getModel();
|
||||
@ -200,15 +219,23 @@ final class ManageTagsDialog extends javax.swing.JDialog {
|
||||
badTags.add(tagName);
|
||||
}
|
||||
}
|
||||
EamDb dbManager = EamDb.getInstance();
|
||||
dbManager.setBadTags(badTags);
|
||||
dbManager.saveSettings();
|
||||
try {
|
||||
EamDb dbManager = EamDb.getInstance();
|
||||
dbManager.setBadTags(badTags);
|
||||
dbManager.saveSettings();
|
||||
} catch (EamDbException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Failed to connect to Central Repository database."); // NON-NLS
|
||||
lbWarnings.setText(Bundle.ManageTagsDialog_init_failedConnection_msg());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.ButtonGroup buttonGroup1;
|
||||
private javax.swing.JButton cancelButton;
|
||||
private javax.swing.JScrollPane jScrollPane1;
|
||||
private javax.swing.JLabel lbWarnings;
|
||||
private javax.swing.JButton okButton;
|
||||
private javax.swing.JTable tblTagNames;
|
||||
// End of variables declaration//GEN-END:variables
|
@ -2,7 +2,7 @@ Manifest-Version: 1.0
|
||||
OpenIDE-Module: org.sleuthkit.autopsy.core/10
|
||||
OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/core/Bundle.properties
|
||||
OpenIDE-Module-Layer: org/sleuthkit/autopsy/core/layer.xml
|
||||
OpenIDE-Module-Implementation-Version: 19
|
||||
OpenIDE-Module-Implementation-Version: 20
|
||||
OpenIDE-Module-Requires: org.openide.windows.WindowManager
|
||||
AutoUpdate-Show-In-Client: true
|
||||
AutoUpdate-Essential-Module: true
|
||||
|
@ -28,5 +28,5 @@ nbm.module.author=Brian Carrier
|
||||
nbm.needs.restart=true
|
||||
source.reference.metadata-extractor-2.8.1.jar=release/modules/ext/metadata-extractor-2.8.1-src.zip!/Source/
|
||||
source.reference.curator-recipes-2.8.0.jar=release/modules/ext/curator-recipes-2.8.0-sources.jar
|
||||
spec.version.base=10.7
|
||||
spec.version.base=10.8
|
||||
|
||||
|
@ -63,6 +63,8 @@ import org.openide.util.NbBundle.Messages;
|
||||
import org.openide.util.actions.CallableSystemAction;
|
||||
import org.openide.windows.WindowManager;
|
||||
import org.sleuthkit.autopsy.actions.OpenOutputFolderAction;
|
||||
import org.sleuthkit.autopsy.appservices.AutopsyService;
|
||||
import org.sleuthkit.autopsy.appservices.AutopsyService.CaseContext;
|
||||
import org.sleuthkit.autopsy.casemodule.CaseMetadata.CaseMetadataException;
|
||||
import org.sleuthkit.autopsy.casemodule.events.AddingDataSourceEvent;
|
||||
import org.sleuthkit.autopsy.casemodule.events.AddingDataSourceFailedEvent;
|
||||
@ -92,15 +94,13 @@ import org.sleuthkit.autopsy.coreutils.Version;
|
||||
import org.sleuthkit.autopsy.events.AutopsyEvent;
|
||||
import org.sleuthkit.autopsy.events.AutopsyEventException;
|
||||
import org.sleuthkit.autopsy.events.AutopsyEventPublisher;
|
||||
import org.sleuthkit.autopsy.appservices.AutopsyService;
|
||||
import org.sleuthkit.autopsy.appservices.AutopsyService.CaseContext;
|
||||
import org.sleuthkit.autopsy.progress.LoggingProgressIndicator;
|
||||
import org.sleuthkit.autopsy.progress.ModalDialogProgressIndicator;
|
||||
import org.sleuthkit.autopsy.progress.ProgressIndicator;
|
||||
import org.sleuthkit.autopsy.ingest.IngestJob;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService;
|
||||
import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchServiceException;
|
||||
import org.sleuthkit.autopsy.progress.LoggingProgressIndicator;
|
||||
import org.sleuthkit.autopsy.progress.ModalDialogProgressIndicator;
|
||||
import org.sleuthkit.autopsy.progress.ProgressIndicator;
|
||||
import org.sleuthkit.autopsy.timeline.OpenTimelineAction;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifactTag;
|
||||
import org.sleuthkit.datamodel.CaseDbConnectionInfo;
|
||||
@ -964,23 +964,12 @@ public class Case {
|
||||
/*
|
||||
* Enable the case-specific actions.
|
||||
*/
|
||||
CallableSystemAction.get(AddImageAction.class
|
||||
).setEnabled(true);
|
||||
CallableSystemAction
|
||||
.get(CaseCloseAction.class
|
||||
).setEnabled(true);
|
||||
CallableSystemAction
|
||||
.get(CasePropertiesAction.class
|
||||
).setEnabled(true);
|
||||
CallableSystemAction
|
||||
.get(CaseDeleteAction.class
|
||||
).setEnabled(true);
|
||||
CallableSystemAction
|
||||
.get(OpenTimelineAction.class
|
||||
).setEnabled(true);
|
||||
CallableSystemAction
|
||||
.get(OpenOutputFolderAction.class
|
||||
).setEnabled(false);
|
||||
CallableSystemAction.get(AddImageAction.class).setEnabled(true);
|
||||
CallableSystemAction.get(CaseCloseAction.class).setEnabled(true);
|
||||
CallableSystemAction.get(CasePropertiesAction.class).setEnabled(true);
|
||||
CallableSystemAction.get(CaseDeleteAction.class).setEnabled(true);
|
||||
CallableSystemAction.get(OpenTimelineAction.class).setEnabled(true);
|
||||
CallableSystemAction.get(OpenOutputFolderAction.class).setEnabled(false);
|
||||
|
||||
/*
|
||||
* Add the case to the recent cases tracker that supplies a list
|
||||
|
@ -32,8 +32,14 @@ import java.util.concurrent.ExecutionException;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.SwingWorker;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.TableColumnModelEvent;
|
||||
import javax.swing.table.DefaultTableModel;
|
||||
import javax.swing.table.TableColumn;
|
||||
import javax.swing.event.TableColumnModelListener;
|
||||
import javax.swing.text.JTextComponent;
|
||||
import javax.swing.text.View;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.openide.nodes.Node;
|
||||
import org.openide.util.Lookup;
|
||||
@ -52,8 +58,8 @@ import org.netbeans.swing.etable.ETable;
|
||||
|
||||
/**
|
||||
* Instances of this class display the BlackboardArtifacts associated with the
|
||||
* Content represented by a Node. Each BlackboardArtifact is rendered displayed in a JTable
|
||||
* representation of its BlackboardAttributes.
|
||||
* Content represented by a Node. Each BlackboardArtifact is rendered displayed
|
||||
* in a JTable representation of its BlackboardAttributes.
|
||||
*/
|
||||
@ServiceProvider(service = DataContentViewer.class, position = 3)
|
||||
public class DataContentViewerArtifact extends javax.swing.JPanel implements DataContentViewer {
|
||||
@ -78,6 +84,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
|
||||
Bundle.DataContentViewerArtifact_attrsTableHeader_value(),
|
||||
Bundle.DataContentViewerArtifact_attrsTableHeader_sources()};
|
||||
private static final int[] COLUMN_WIDTHS = {100, 800, 100};
|
||||
private static final int CELL_BOTTOM_MARGIN = 5;
|
||||
|
||||
public DataContentViewerArtifact() {
|
||||
initResultsTable();
|
||||
@ -85,6 +92,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
|
||||
resultsTableScrollPane.setViewportView(resultsTable);
|
||||
customizeComponents();
|
||||
resetComponents();
|
||||
resultsTable.setDefaultRenderer(Object.class, new MultiLineTableCellRenderer());
|
||||
}
|
||||
|
||||
private void initResultsTable() {
|
||||
@ -100,11 +108,71 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
|
||||
resultsTable.getTableHeader().setReorderingAllowed(false);
|
||||
resultsTable.setColumnHidingAllowed(false);
|
||||
resultsTable.getColumnModel().getSelectionModel().setSelectionMode(javax.swing.ListSelectionModel.SINGLE_INTERVAL_SELECTION);
|
||||
updateColumnSizes();
|
||||
resultsTable.getColumnModel().addColumnModelListener(new TableColumnModelListener() {
|
||||
|
||||
@Override
|
||||
public void columnAdded(TableColumnModelEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void columnRemoved(TableColumnModelEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void columnMoved(TableColumnModelEvent e) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void columnMarginChanged(ChangeEvent e) {
|
||||
updateRowHeights(); //When the user changes column width we may need to resize row height
|
||||
}
|
||||
|
||||
@Override
|
||||
public void columnSelectionChanged(ListSelectionEvent e) {
|
||||
}
|
||||
});
|
||||
resultsTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_NEXT_COLUMN);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the row heights to the heights of the content in their Value column.
|
||||
*/
|
||||
private void updateRowHeights() {
|
||||
int valueColIndex = -1;
|
||||
for (int col = 0; col < resultsTable.getColumnCount(); col++) {
|
||||
if (resultsTable.getColumnName(col).equals(COLUMN_HEADERS[1])) {
|
||||
valueColIndex = col;
|
||||
}
|
||||
}
|
||||
if (valueColIndex != -1) {
|
||||
for (int row = 0; row < resultsTable.getRowCount(); row++) {
|
||||
Component comp = resultsTable.prepareRenderer(
|
||||
resultsTable.getCellRenderer(row, valueColIndex), row, valueColIndex);
|
||||
final int rowHeight;
|
||||
if (comp instanceof JTextComponent) {
|
||||
final JTextComponent tc = (JTextComponent) comp;
|
||||
final View rootView = tc.getUI().getRootView(tc);
|
||||
java.awt.Insets i = tc.getInsets(null);
|
||||
rootView.setSize(resultsTable.getColumnModel().getColumn(valueColIndex)
|
||||
.getPreferredWidth() - i.left - i.right,
|
||||
Integer.MAX_VALUE);
|
||||
rowHeight = (int) rootView.getPreferredSpan(View.Y_AXIS);
|
||||
} else {
|
||||
rowHeight = comp.getPreferredSize().height;
|
||||
}
|
||||
if (rowHeight > 0) {
|
||||
resultsTable.setRowHeight(row, rowHeight + CELL_BOTTOM_MARGIN);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the column widths so that the Value column has most of the space.
|
||||
*/
|
||||
private void updateColumnSizes() {
|
||||
resultsTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_NEXT_COLUMN);
|
||||
Enumeration<TableColumn> columns = resultsTable.getColumnModel().getColumns();
|
||||
while (columns.hasMoreElements()) {
|
||||
TableColumn col = columns.nextElement();
|
||||
@ -551,6 +619,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
|
||||
DefaultTableModel tModel = ((DefaultTableModel) resultsTable.getModel());
|
||||
tModel.setDataVector(viewUpdate.tableContents.getRows(), COLUMN_HEADERS);
|
||||
updateColumnSizes();
|
||||
updateRowHeights();
|
||||
resultsTable.clearSelection();
|
||||
|
||||
this.setCursor(null);
|
||||
@ -568,6 +637,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
|
||||
DefaultTableModel tModel = ((DefaultTableModel) resultsTable.getModel());
|
||||
tModel.setDataVector(waitRow, COLUMN_HEADERS);
|
||||
updateColumnSizes();
|
||||
updateRowHeights();
|
||||
resultsTable.clearSelection();
|
||||
// The output of the previous task is no longer relevant.
|
||||
if (currentTask != null) {
|
||||
@ -758,4 +828,27 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TableCellRenderer for displaying multiline text.
|
||||
*/
|
||||
private class MultiLineTableCellRenderer implements javax.swing.table.TableCellRenderer {
|
||||
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(javax.swing.JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
||||
javax.swing.JTextArea jtex = new javax.swing.JTextArea();
|
||||
if (value instanceof String) {
|
||||
jtex.setText((String) value);
|
||||
jtex.setLineWrap(true);
|
||||
jtex.setWrapStyleWord(true);
|
||||
}
|
||||
//cell backgroud color when selected
|
||||
if (isSelected) {
|
||||
jtex.setBackground(javax.swing.UIManager.getColor("Table.selectionBackground"));
|
||||
} else {
|
||||
jtex.setBackground(javax.swing.UIManager.getColor("Table.background"));
|
||||
}
|
||||
return jtex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -147,30 +147,6 @@ KeyValueNode.createSheet.name.name=Name
|
||||
KeyValueNode.createSheet.name.displayName=Name
|
||||
KeyValueNode.createSheet.name.desc=n/a
|
||||
KeyValueNode.createSheet.map.desc=n/a
|
||||
KeywordHits.kwHits.text=Keyword Hits
|
||||
KeywordHits.simpleLiteralSearch.text=Single Literal Keyword Search
|
||||
KeywordHits.singleRegexSearch.text=Single Regular Expression Search
|
||||
KeywordHits.createSheet.name.name=Name
|
||||
KeywordHits.createSheet.name.displayName=Name
|
||||
KeywordHits.createSheet.name.desc=no description
|
||||
KeywordHits.createSheet.listName.name=List Name
|
||||
KeywordHits.createSheet.listName.displayName=List Name
|
||||
KeywordHits.createSheet.listName.desc=no description
|
||||
KeywordHits.createSheet.numChildren.name=Number of Children
|
||||
KeywordHits.createSheet.numChildren.displayName=Number of Children
|
||||
KeywordHits.createSheet.numChildren.desc=no description
|
||||
KeywordHits.createSheet.filesWithHits.name=Files with Hits
|
||||
KeywordHits.createSheet.filesWithHits.displayName=Files with Hits
|
||||
KeywordHits.createSheet.filesWithHits.desc=no description
|
||||
KeywordHits.createNodeForKey.modTime.displayName=Modified Time
|
||||
KeywordHits.createNodeForKey.modTime.desc=Modified Time
|
||||
KeywordHits.createNodeForKey.accessTime.displayName=Access Time
|
||||
KeywordHits.createNodeForKey.accessTime.desc=Access Time
|
||||
KeywordHits.createNodeForKey.chgTime.displayName=Change Time
|
||||
KeywordHits.createNodeForKey.chgTime.desc=Change Time
|
||||
KeywordHits.createNodeForKey.chgTime.name=ChangeTime
|
||||
KeywordHits.createNodeForKey.accessTime.name=AccessTime
|
||||
KeywordHits.createNodeForKey.modTime.name=ModifiedTime
|
||||
LayoutFileNode.propertyType.parts=Parts
|
||||
LayoutFileNode.createSheet.name.name=Name
|
||||
LayoutFileNode.createSheet.name.displayName=Name
|
||||
|
@ -94,12 +94,15 @@ public abstract class DisplayableItemNode extends AbstractNode {
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts a DisplayableItemNodeVisitor.
|
||||
* Accepts a visitor DisplayableItemNodeVisitor that will perform an
|
||||
* operation on this artifact type and return some object as the result of
|
||||
* the operation.
|
||||
*
|
||||
* @param <T> The type parameter of the visitor.
|
||||
* @param visitor The visitor.
|
||||
* @param visitor The visitor, where the type parameter of the visitor is
|
||||
* the type of the object that will be returned as the result
|
||||
* of the visit operation.
|
||||
*
|
||||
* @return
|
||||
* @return An object of type T.
|
||||
*/
|
||||
public abstract <T> T accept(DisplayableItemNodeVisitor<T> visitor);
|
||||
|
||||
|
@ -65,13 +65,63 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
|
||||
* Listens for case and ingest invest. Updates observers when events are
|
||||
* fired. FileType and FileTypes nodes are all listening to this.
|
||||
*/
|
||||
private static class FileTypesByExtObservable extends Observable {
|
||||
static private class FileTypesByExtObservable extends Observable {
|
||||
|
||||
private FileTypesByExtObservable() {
|
||||
private boolean showCounts = true;
|
||||
private final PropertyChangeListener pcl;
|
||||
|
||||
private FileTypesByExtObservable(SleuthkitCase skCase) {
|
||||
super();
|
||||
this.pcl = (PropertyChangeEvent evt) -> {
|
||||
String eventType = evt.getPropertyName();
|
||||
if (eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString()) || eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString()) || eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) {
|
||||
/**
|
||||
* Checking for a current case is a stop gap measure until a
|
||||
* different way of handling the closing of cases is worked
|
||||
* out. Currently, remote events may be received for a case
|
||||
* that is already closed.
|
||||
*/
|
||||
try {
|
||||
Case.getCurrentCase();
|
||||
shouldShowCounts(skCase);
|
||||
update();
|
||||
} catch (IllegalStateException notUsed) {
|
||||
/**
|
||||
* Case is closed, do nothing.
|
||||
*/
|
||||
}
|
||||
} else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
|
||||
// case was closed. Remove listeners so that we don't get called with a stale case handle
|
||||
if (evt.getNewValue() == null) {
|
||||
removeListeners();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
IngestManager.getInstance().addIngestJobEventListener(pcl);
|
||||
IngestManager.getInstance().addIngestModuleEventListener(pcl);
|
||||
Case.addPropertyChangeListener(pcl);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Should the nodes show counts?
|
||||
*
|
||||
*
|
||||
* @return True, unless the DB has more than 200k rows.
|
||||
*/
|
||||
private boolean shouldShowCounts(SleuthkitCase skCase) {
|
||||
if (showCounts) {
|
||||
try {
|
||||
if (skCase.countFilesWhere("1=1") > 200000) {
|
||||
showCounts = false;
|
||||
}
|
||||
} catch (TskCoreException tskCoreException) {
|
||||
showCounts = false;
|
||||
LOGGER.log(Level.SEVERE, "Error counting files.", tskCoreException);
|
||||
}
|
||||
}
|
||||
return showCounts;
|
||||
}
|
||||
|
||||
private void removeListeners() {
|
||||
@ -81,31 +131,6 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
|
||||
Case.removePropertyChangeListener(pcl);
|
||||
}
|
||||
|
||||
private final PropertyChangeListener pcl = (PropertyChangeEvent evt) -> {
|
||||
String eventType = evt.getPropertyName();
|
||||
if (eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString()) || eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString()) || eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) {
|
||||
/**
|
||||
* Checking for a current case is a stop gap measure until a
|
||||
* different way of handling the closing of cases is worked out.
|
||||
* Currently, remote events may be received for a case that is
|
||||
* already closed.
|
||||
*/
|
||||
try {
|
||||
Case.getCurrentCase();
|
||||
update();
|
||||
} catch (IllegalStateException notUsed) {
|
||||
/**
|
||||
* Case is closed, do nothing.
|
||||
*/
|
||||
}
|
||||
} else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
|
||||
// case was closed. Remove listeners so that we don't get called with a stale case handle
|
||||
if (evt.getNewValue() == null) {
|
||||
removeListeners();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private void update() {
|
||||
setChanged();
|
||||
notifyObservers();
|
||||
@ -139,7 +164,7 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
|
||||
* @param o Observable that was created by a higher-level node that
|
||||
* provides updates on events
|
||||
*/
|
||||
private FileTypesByExtNode(SleuthkitCase skCase, FileTypesByExtension.RootFilter filter, Observable o) {
|
||||
private FileTypesByExtNode(SleuthkitCase skCase, FileTypesByExtension.RootFilter filter, FileTypesByExtObservable o) {
|
||||
super(Children.create(new FileTypesByExtNodeChildren(skCase, filter, o), true), Lookups.singleton(filter == null ? FNAME : filter.getName()));
|
||||
this.filter = filter;
|
||||
init();
|
||||
@ -199,7 +224,7 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
|
||||
|
||||
private final SleuthkitCase skCase;
|
||||
private final FileTypesByExtension.RootFilter filter;
|
||||
private final Observable notifier;
|
||||
private final FileTypesByExtObservable notifier;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -208,12 +233,12 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
|
||||
* @param o Observable that provides updates based on events
|
||||
* being fired (or null if one needs to be created)
|
||||
*/
|
||||
private FileTypesByExtNodeChildren(SleuthkitCase skCase, FileTypesByExtension.RootFilter filter, Observable o) {
|
||||
private FileTypesByExtNodeChildren(SleuthkitCase skCase, FileTypesByExtension.RootFilter filter, FileTypesByExtObservable o) {
|
||||
super();
|
||||
this.skCase = skCase;
|
||||
this.filter = filter;
|
||||
if (o == null) {
|
||||
this.notifier = new FileTypesByExtObservable();
|
||||
this.notifier = new FileTypesByExtObservable(skCase);
|
||||
} else {
|
||||
this.notifier = o;
|
||||
}
|
||||
@ -256,6 +281,7 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
|
||||
|
||||
FileTypesByExtension.SearchFilterInterface filter;
|
||||
SleuthkitCase skCase;
|
||||
private final FileTypesByExtObservable notifier;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -264,10 +290,11 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
|
||||
* @param o Observable that sends updates when the child factories
|
||||
* should refresh
|
||||
*/
|
||||
FileExtensionNode(FileTypesByExtension.SearchFilterInterface filter, SleuthkitCase skCase, Observable o) {
|
||||
FileExtensionNode(FileTypesByExtension.SearchFilterInterface filter, SleuthkitCase skCase, FileTypesByExtObservable o) {
|
||||
super(Children.create(new FileExtensionNodeChildren(filter, skCase, o), true), Lookups.singleton(filter.getDisplayName()));
|
||||
this.filter = filter;
|
||||
this.skCase = skCase;
|
||||
this.notifier = o;
|
||||
init();
|
||||
o.addObserver(new ByExtNodeObserver());
|
||||
}
|
||||
@ -288,8 +315,10 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
|
||||
}
|
||||
|
||||
private void updateDisplayName() {
|
||||
final long count = FileExtensionNodeChildren.calculateItems(skCase, filter);
|
||||
super.setDisplayName(filter.getDisplayName() + " (" + count + ")");
|
||||
final String count = notifier.shouldShowCounts(skCase)
|
||||
? " (" + Long.toString(FileExtensionNodeChildren.calculateItems(skCase, filter)) + ")"
|
||||
: "";
|
||||
super.setDisplayName(filter.getDisplayName() + count);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -63,41 +63,18 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
|
||||
private final HashMap<String, List<String>> existingMimeTypes = new HashMap<>();
|
||||
private static final Logger LOGGER = Logger.getLogger(FileTypesByMimeType.class.getName());
|
||||
|
||||
private boolean showCounts = true;
|
||||
|
||||
private void removeListeners() {
|
||||
deleteObservers();
|
||||
IngestManager.getInstance().removeIngestJobEventListener(pcl);
|
||||
Case.removePropertyChangeListener(pcl);
|
||||
}
|
||||
|
||||
/*
|
||||
* The pcl is in the class because it has the easiest mechanisms to add and
|
||||
* remove itself during its life cycles.
|
||||
*/
|
||||
private final PropertyChangeListener pcl = (PropertyChangeEvent evt) -> {
|
||||
String eventType = evt.getPropertyName();
|
||||
if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|
||||
|| eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) {
|
||||
|
||||
/**
|
||||
* Checking for a current case is a stop gap measure until a
|
||||
* different way of handling the closing of cases is worked out.
|
||||
* Currently, remote events may be received for a case that is
|
||||
* already closed.
|
||||
*/
|
||||
try {
|
||||
Case.getCurrentCase();
|
||||
populateHashMap();
|
||||
} catch (IllegalStateException notUsed) {
|
||||
/**
|
||||
* Case is closed, do nothing.
|
||||
*/
|
||||
}
|
||||
} else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
|
||||
if (evt.getNewValue() == null) {
|
||||
removeListeners();
|
||||
}
|
||||
}
|
||||
};
|
||||
private final PropertyChangeListener pcl;
|
||||
|
||||
/**
|
||||
* Retrieve the media types by retrieving the keyset from the hashmap.
|
||||
@ -132,7 +109,6 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
|
||||
existingMimeTypes.clear();
|
||||
|
||||
if (skCase == null) {
|
||||
|
||||
return;
|
||||
}
|
||||
try (SleuthkitCase.CaseDbQuery dbQuery = skCase.executeQuery(allDistinctMimeTypesQuery.toString())) {
|
||||
@ -162,12 +138,59 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
|
||||
}
|
||||
|
||||
FileTypesByMimeType(SleuthkitCase skCase) {
|
||||
this.pcl = (PropertyChangeEvent evt) -> {
|
||||
String eventType = evt.getPropertyName();
|
||||
if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|
||||
|| eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) {
|
||||
|
||||
/**
|
||||
* Checking for a current case is a stop gap measure until a
|
||||
* different way of handling the closing of cases is worked out.
|
||||
* Currently, remote events may be received for a case that is
|
||||
* already closed.
|
||||
*/
|
||||
try {
|
||||
Case.getCurrentCase();
|
||||
shouldShowCounts(skCase);
|
||||
|
||||
populateHashMap();
|
||||
} catch (IllegalStateException notUsed) {
|
||||
/**
|
||||
* Case is closed, do nothing.
|
||||
*/
|
||||
}
|
||||
} else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
|
||||
if (evt.getNewValue() == null) {
|
||||
removeListeners();
|
||||
}
|
||||
}
|
||||
};
|
||||
IngestManager.getInstance().addIngestJobEventListener(pcl);
|
||||
Case.addPropertyChangeListener(pcl);
|
||||
this.skCase = skCase;
|
||||
populateHashMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* Should the nodes show counts?
|
||||
*
|
||||
*
|
||||
* @return True, unless the DB has more than 200k rows.
|
||||
*/
|
||||
private boolean shouldShowCounts(final SleuthkitCase skCase) {
|
||||
if (showCounts) {
|
||||
try {
|
||||
if (skCase.countFilesWhere("1=1") > 200000) {
|
||||
showCounts = false;
|
||||
}
|
||||
} catch (TskCoreException tskCoreException) {
|
||||
showCounts = false;
|
||||
LOGGER.log(Level.SEVERE, "Error counting files.", tskCoreException);
|
||||
}
|
||||
}
|
||||
return showCounts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(AutopsyItemVisitor<T> v) {
|
||||
return v.visit(this);
|
||||
|
@ -33,16 +33,17 @@ import java.util.Observable;
|
||||
import java.util.Observer;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openide.nodes.ChildFactory;
|
||||
import org.openide.nodes.Children;
|
||||
import org.openide.nodes.Node;
|
||||
import org.openide.nodes.Sheet;
|
||||
import org.openide.util.Lookup;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import static org.sleuthkit.autopsy.datamodel.Bundle.*;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
@ -51,25 +52,48 @@ import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase.CaseDbQuery;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.TskException;
|
||||
|
||||
/**
|
||||
* Keyword hits node support
|
||||
*/
|
||||
public class KeywordHits implements AutopsyVisitableItem {
|
||||
|
||||
private SleuthkitCase skCase;
|
||||
private static final Logger logger = Logger.getLogger(KeywordHits.class.getName());
|
||||
private static final String KEYWORD_HITS = NbBundle.getMessage(KeywordHits.class, "KeywordHits.kwHits.text");
|
||||
|
||||
@NbBundle.Messages("KeywordHits.kwHits.text=Keyword Hits")
|
||||
private static final String KEYWORD_HITS = KeywordHits_kwHits_text();
|
||||
@NbBundle.Messages("KeywordHits.simpleLiteralSearch.text=Single Literal Keyword Search")
|
||||
private static final String SIMPLE_LITERAL_SEARCH = KeywordHits_simpleLiteralSearch_text();
|
||||
@NbBundle.Messages("KeywordHits.singleRegexSearch.text=Single Regular Expression Search")
|
||||
private static final String SIMPLE_REGEX_SEARCH = KeywordHits_singleRegexSearch_text();
|
||||
|
||||
public static final String NAME = BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getLabel();
|
||||
public static final String SIMPLE_LITERAL_SEARCH = NbBundle
|
||||
.getMessage(KeywordHits.class, "KeywordHits.simpleLiteralSearch.text");
|
||||
public static final String SIMPLE_REGEX_SEARCH = NbBundle
|
||||
.getMessage(KeywordHits.class, "KeywordHits.singleRegexSearch.text");
|
||||
|
||||
private SleuthkitCase skCase;
|
||||
private final KeywordResults keywordResults;
|
||||
// String used in the instance MAP so that exact matches and substring can fit into the same
|
||||
// data structure as regexps, even though they don't use instances.
|
||||
private final String DEFAULT_INSTANCE_NAME = "DEFAULT_INSTANCE_NAME";
|
||||
|
||||
/**
|
||||
* String used in the instance MAP so that exact matches and substring can
|
||||
* fit into the same data structure as regexps, even though they don't use
|
||||
* instances.
|
||||
*/
|
||||
private static final String DEFAULT_INSTANCE_NAME = "DEFAULT_INSTANCE_NAME";
|
||||
|
||||
/**
|
||||
* query attributes table for the ones that we need for the tree
|
||||
*/
|
||||
private static final String KEYWORD_HIT_ATTRIBUTES_QUERY = "SELECT blackboard_attributes.value_text, "//NON-NLS
|
||||
+ "blackboard_attributes.value_int32, "//NON-NLS
|
||||
+ "blackboard_attributes.artifact_id, " //NON-NLS
|
||||
+ "blackboard_attributes.attribute_type_id "//NON-NLS
|
||||
+ "FROM blackboard_attributes, blackboard_artifacts "//NON-NLS
|
||||
+ "WHERE blackboard_attributes.artifact_id = blackboard_artifacts.artifact_id "//NON-NLS
|
||||
+ " AND blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID() //NON-NLS
|
||||
+ " AND (attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()//NON-NLS
|
||||
+ " OR attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID()//NON-NLS
|
||||
+ " OR attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_SEARCH_TYPE.getTypeID()//NON-NLS
|
||||
+ " OR attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP.getTypeID()//NON-NLS
|
||||
+ ")"; //NON-NLS
|
||||
|
||||
public KeywordHits(SleuthkitCase skCase) {
|
||||
this.skCase = skCase;
|
||||
@ -94,6 +118,8 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
|
||||
/**
|
||||
* Get the list names used in searches.
|
||||
*
|
||||
* @return The list of list names.
|
||||
*/
|
||||
List<String> getListNames() {
|
||||
synchronized (topLevelMap) {
|
||||
@ -168,18 +194,9 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
* @param artifactId Artifact id of file that had hit
|
||||
*/
|
||||
void addRegExpToList(Map<String, Map<String, Set<Long>>> listMap, String regExp, String keywordInstance, Long artifactId) {
|
||||
if (listMap.containsKey(regExp) == false) {
|
||||
listMap.put(regExp, new LinkedHashMap<>());
|
||||
}
|
||||
Map<String, Set<Long>> instanceMap = listMap.get(regExp);
|
||||
|
||||
// get or create keyword instances entry.
|
||||
if (instanceMap.containsKey(keywordInstance) == false) {
|
||||
instanceMap.put(keywordInstance, new HashSet<>());
|
||||
}
|
||||
|
||||
// add this ID to the instance
|
||||
instanceMap.get(keywordInstance).add(artifactId);
|
||||
Map<String, Set<Long>> instanceMap = listMap.computeIfAbsent(regExp, r -> new LinkedHashMap<>());
|
||||
// add this ID to the instances entry, creating one if needed
|
||||
instanceMap.computeIfAbsent(keywordInstance, ki -> new HashSet<>()).add(artifactId);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -191,16 +208,10 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
* @param artifactId Artifact id of file that had hit
|
||||
*/
|
||||
void addNonRegExpMatchToList(Map<String, Map<String, Set<Long>>> listMap, String keyWord, Long artifactId) {
|
||||
if (listMap.containsKey(keyWord) == false) {
|
||||
listMap.put(keyWord, new LinkedHashMap<>());
|
||||
}
|
||||
Map<String, Set<Long>> instanceMap = listMap.get(keyWord);
|
||||
Map<String, Set<Long>> instanceMap = listMap.computeIfAbsent(keyWord, k -> new LinkedHashMap<>());
|
||||
|
||||
// Use the default instance name, since we don't need that level in the tree
|
||||
if (instanceMap.containsKey(DEFAULT_INSTANCE_NAME) == false) {
|
||||
instanceMap.put(DEFAULT_INSTANCE_NAME, new HashSet<>());
|
||||
}
|
||||
instanceMap.get(DEFAULT_INSTANCE_NAME).add(artifactId);
|
||||
instanceMap.computeIfAbsent(DEFAULT_INSTANCE_NAME, DIN -> new HashSet<>()).add(artifactId);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -231,47 +242,42 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
long id = art.getKey();
|
||||
Map<Long, String> attributes = art.getValue();
|
||||
|
||||
// I think we can use attributes.remove(...) here?
|
||||
// I think we can use attributes.remove(...) here? - why should bwe use remove?
|
||||
String listName = attributes.get(Long.valueOf(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()));
|
||||
String word = attributes.get(Long.valueOf(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID()));
|
||||
String reg = attributes.get(Long.valueOf(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP.getTypeID()));
|
||||
// new in 4.4
|
||||
String kwType = attributes.get(Long.valueOf(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_SEARCH_TYPE.getTypeID()));
|
||||
|
||||
// part of a list
|
||||
if (listName != null) {
|
||||
if (listName != null) { // part of a list
|
||||
// get or create list entry
|
||||
if (listsMap.containsKey(listName) == false) {
|
||||
listsMap.put(listName, new LinkedHashMap<>());
|
||||
}
|
||||
Map<String, Map<String, Set<Long>>> listMap = listsMap.get(listName);
|
||||
Map<String, Map<String, Set<Long>>> listMap = listsMap.computeIfAbsent(listName, ln -> new LinkedHashMap<>());
|
||||
|
||||
// substring, treated same as exact match
|
||||
// Enum for "1" is defined in KeywordSearch.java
|
||||
if ((kwType != null) && (kwType.equals("1"))) {
|
||||
// original term should be stored in reg
|
||||
if (reg != null) {
|
||||
addNonRegExpMatchToList(listMap, reg, id);
|
||||
} else {
|
||||
addNonRegExpMatchToList(listMap, word, id);
|
||||
}
|
||||
} else if (reg != null) {
|
||||
addRegExpToList(listMap, reg, word, id);
|
||||
} else {
|
||||
if ("1".equals(kwType) || reg == null) { //literal, substring or exact
|
||||
/*
|
||||
* Substring, treated same as exact match. "1" is
|
||||
* the ordinal value for substring as defined in
|
||||
* KeywordSearch.java. The original term should be
|
||||
* stored in reg
|
||||
*/
|
||||
word = (reg != null) ? reg : word; //use original term if it there.
|
||||
addNonRegExpMatchToList(listMap, word, id);
|
||||
} else {
|
||||
addRegExpToList(listMap, reg, word, id);
|
||||
}
|
||||
} // regular expression, single term
|
||||
else if (reg != null) {
|
||||
// substring is treated same as exact
|
||||
if ((kwType != null) && (kwType.equals("1"))) {
|
||||
// original term should be stored in reg
|
||||
addNonRegExpMatchToList(literalMap, reg, id);
|
||||
} else {//single term
|
||||
|
||||
if ("1".equals(kwType) || reg == null) { //literal, substring or exact
|
||||
/*
|
||||
* Substring, treated same as exact match. "1" is
|
||||
* the ordinal value for substring as defined in
|
||||
* KeywordSearch.java. The original term should be
|
||||
* stored in reg
|
||||
*/
|
||||
word = (reg != null) ? reg : word; //use original term if it there.
|
||||
addNonRegExpMatchToList(literalMap, word, id);
|
||||
} else {
|
||||
addRegExpToList(regexMap, reg, word, id);
|
||||
}
|
||||
} // literal, single term
|
||||
else {
|
||||
addNonRegExpMatchToList(literalMap, word, id);
|
||||
}
|
||||
}
|
||||
topLevelMap.putAll(listsMap);
|
||||
@ -281,7 +287,6 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
notifyObservers();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public void update() {
|
||||
// maps Artifact ID to map of attribute types to attribute values
|
||||
Map<Long, Map<Long, String>> artifactIds = new LinkedHashMap<>();
|
||||
@ -290,36 +295,21 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
return;
|
||||
}
|
||||
|
||||
// query attributes table for the ones that we need for the tree
|
||||
int setId = BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID();
|
||||
int wordId = BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID();
|
||||
int regexId = BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP.getTypeID();
|
||||
int artId = BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID();
|
||||
String query = "SELECT blackboard_attributes.value_text,blackboard_attributes.value_int32,"
|
||||
+ "blackboard_attributes.artifact_id," //NON-NLS
|
||||
+ "blackboard_attributes.attribute_type_id FROM blackboard_attributes,blackboard_artifacts WHERE " //NON-NLS
|
||||
+ "(blackboard_attributes.artifact_id=blackboard_artifacts.artifact_id AND " //NON-NLS
|
||||
+ "blackboard_artifacts.artifact_type_id=" + artId //NON-NLS
|
||||
+ ") AND (attribute_type_id=" + setId + " OR " //NON-NLS
|
||||
+ "attribute_type_id=" + wordId + " OR " //NON-NLS
|
||||
+ "attribute_type_id=" + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_SEARCH_TYPE.getTypeID() + " OR " //NON-NLS
|
||||
+ "attribute_type_id=" + regexId + ")"; //NON-NLS
|
||||
|
||||
try (CaseDbQuery dbQuery = skCase.executeQuery(query)) {
|
||||
try (CaseDbQuery dbQuery = skCase.executeQuery(KEYWORD_HIT_ATTRIBUTES_QUERY)) {
|
||||
ResultSet resultSet = dbQuery.getResultSet();
|
||||
while (resultSet.next()) {
|
||||
String valueStr = resultSet.getString("value_text"); //NON-NLS
|
||||
long artifactId = resultSet.getLong("artifact_id"); //NON-NLS
|
||||
long typeId = resultSet.getLong("attribute_type_id"); //NON-NLS
|
||||
if (!artifactIds.containsKey(artifactId)) {
|
||||
artifactIds.put(artifactId, new LinkedHashMap<>());
|
||||
}
|
||||
String valueStr = resultSet.getString("value_text"); //NON-NLS
|
||||
|
||||
//get the map of attributes for this artifact
|
||||
Map<Long, String> attributesByTypeMap = artifactIds.computeIfAbsent(artifactId, ai -> new LinkedHashMap<>());
|
||||
if (StringUtils.isNotEmpty(valueStr)) {
|
||||
artifactIds.get(artifactId).put(typeId, valueStr);
|
||||
attributesByTypeMap.put(typeId, valueStr);
|
||||
} else {
|
||||
// Keyword Search Type is an int
|
||||
Long valueLong = resultSet.getLong("value_int32");
|
||||
artifactIds.get(artifactId).put(typeId, valueLong.toString());
|
||||
attributesByTypeMap.put(typeId, valueLong.toString());
|
||||
}
|
||||
}
|
||||
} catch (TskCoreException | SQLException ex) {
|
||||
@ -356,6 +346,9 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
}
|
||||
|
||||
@Override
|
||||
@NbBundle.Messages({"KeywordHits.createSheet.name.name=Name",
|
||||
"KeywordHits.createSheet.name.displayName=Name",
|
||||
"KeywordHits.createSheet.name.desc=no description"})
|
||||
protected Sheet createSheet() {
|
||||
Sheet s = super.createSheet();
|
||||
Sheet.Set ss = s.get(Sheet.PROPERTIES);
|
||||
@ -364,9 +357,10 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
s.put(ss);
|
||||
}
|
||||
|
||||
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.name.name"),
|
||||
NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.name.displayName"),
|
||||
NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.name.desc"),
|
||||
ss.put(new NodeProperty<>(
|
||||
KeywordHits_createSheet_name_name(),
|
||||
KeywordHits_createSheet_name_displayName(),
|
||||
KeywordHits_createSheet_name_desc(),
|
||||
getName()));
|
||||
|
||||
return s;
|
||||
@ -378,10 +372,28 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
}
|
||||
}
|
||||
|
||||
private abstract class DetachableObserverChildFactory<X> extends ChildFactory.Detachable<X> implements Observer {
|
||||
|
||||
@Override
|
||||
protected void addNotify() {
|
||||
keywordResults.addObserver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeNotify() {
|
||||
keywordResults.deleteObserver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Observable o, Object arg) {
|
||||
refresh(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the list nodes
|
||||
*/
|
||||
private class ListFactory extends ChildFactory.Detachable<String> implements Observer {
|
||||
private class ListFactory extends DetachableObserverChildFactory<String> {
|
||||
|
||||
private final PropertyChangeListener pcl = new PropertyChangeListener() {
|
||||
@Override
|
||||
@ -407,9 +419,7 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
keywordResults.update();
|
||||
}
|
||||
} catch (IllegalStateException notUsed) {
|
||||
/**
|
||||
* Case is closed, do nothing.
|
||||
*/
|
||||
// Case is closed, do nothing.
|
||||
}
|
||||
} else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|
||||
|| eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) {
|
||||
@ -423,17 +433,18 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
Case.getCurrentCase();
|
||||
keywordResults.update();
|
||||
} catch (IllegalStateException notUsed) {
|
||||
/**
|
||||
* Case is closed, do nothing.
|
||||
*/
|
||||
}
|
||||
} else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
|
||||
// case was closed. Remove listeners so that we don't get called with a stale case handle
|
||||
if (evt.getNewValue() == null) {
|
||||
removeNotify();
|
||||
skCase = null;
|
||||
// Case is closed, do nothing.
|
||||
}
|
||||
} else if (eventType.equals(Case.Events.CURRENT_CASE.toString())
|
||||
&& evt.getNewValue() == null) {
|
||||
/*
|
||||
* Case was closed. Remove listeners so that we don't get
|
||||
* called with a stale case handle
|
||||
*/
|
||||
removeNotify();
|
||||
skCase = null;
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
@ -443,7 +454,7 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
IngestManager.getInstance().addIngestModuleEventListener(pcl);
|
||||
Case.addPropertyChangeListener(pcl);
|
||||
keywordResults.update();
|
||||
keywordResults.addObserver(this);
|
||||
super.addNotify();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -451,7 +462,7 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
IngestManager.getInstance().removeIngestJobEventListener(pcl);
|
||||
IngestManager.getInstance().removeIngestModuleEventListener(pcl);
|
||||
Case.removePropertyChangeListener(pcl);
|
||||
keywordResults.deleteObserver(this);
|
||||
super.removeNotify();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -464,22 +475,44 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
protected Node createNodeForKey(String key) {
|
||||
return new ListNode(key);
|
||||
}
|
||||
}
|
||||
|
||||
private abstract class KWHitsNodeBase extends DisplayableItemNode implements Observer {
|
||||
|
||||
private KWHitsNodeBase(Children children, Lookup lookup) {
|
||||
super(children, lookup);
|
||||
}
|
||||
|
||||
private KWHitsNodeBase(Children children) {
|
||||
super(children);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getItemType() {
|
||||
return getClass().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Observable o, Object arg) {
|
||||
refresh(true);
|
||||
updateDisplayName();
|
||||
}
|
||||
|
||||
final void updateDisplayName() {
|
||||
super.setDisplayName(getName() + " (" + countTotalDescendants() + ")");
|
||||
}
|
||||
|
||||
abstract int countTotalDescendants();
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the keyword search lists (or default groupings if list was not
|
||||
* given)
|
||||
*/
|
||||
public class ListNode extends DisplayableItemNode implements Observer {
|
||||
class ListNode extends KWHitsNodeBase {
|
||||
|
||||
private final String listName;
|
||||
|
||||
public ListNode(String listName) {
|
||||
private ListNode(String listName) {
|
||||
super(Children.create(new TermFactory(listName), true), Lookups.singleton(listName));
|
||||
super.setName(listName);
|
||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/keyword_hits.png"); //NON-NLS
|
||||
@ -488,18 +521,26 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
keywordResults.addObserver(this);
|
||||
}
|
||||
|
||||
private void updateDisplayName() {
|
||||
@Override
|
||||
public int countTotalDescendants() {
|
||||
int totalDescendants = 0;
|
||||
|
||||
for (String word : keywordResults.getKeywords(listName)) {
|
||||
for (String instance : keywordResults.getKeywordInstances(listName, word)) {
|
||||
Set<Long> ids = keywordResults.getArtifactIds(listName, word, instance);
|
||||
totalDescendants += ids.size();
|
||||
}
|
||||
}
|
||||
super.setDisplayName(listName + " (" + totalDescendants + ")");
|
||||
return totalDescendants;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NbBundle.Messages({"KeywordHits.createSheet.listName.name=List Name",
|
||||
"KeywordHits.createSheet.listName.displayName=List Name",
|
||||
"KeywordHits.createSheet.listName.desc=no description",
|
||||
"KeywordHits.createSheet.numChildren.name=Number of Children",
|
||||
"KeywordHits.createSheet.numChildren.displayName=Number of Children",
|
||||
"KeywordHits.createSheet.numChildren.desc=no description"})
|
||||
protected Sheet createSheet() {
|
||||
Sheet s = super.createSheet();
|
||||
Sheet.Set ss = s.get(Sheet.PROPERTIES);
|
||||
@ -508,14 +549,16 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
s.put(ss);
|
||||
}
|
||||
|
||||
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.listName.name"),
|
||||
NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.listName.displayName"),
|
||||
NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.listName.desc"),
|
||||
ss.put(new NodeProperty<>(
|
||||
KeywordHits_createSheet_listName_name(),
|
||||
KeywordHits_createSheet_listName_displayName(),
|
||||
KeywordHits_createSheet_listName_desc(),
|
||||
listName));
|
||||
|
||||
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.numChildren.name"),
|
||||
NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.numChildren.displayName"),
|
||||
NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.numChildren.desc"),
|
||||
ss.put(new NodeProperty<>(
|
||||
KeywordHits_createSheet_numChildren_name(),
|
||||
KeywordHits_createSheet_numChildren_displayName(),
|
||||
KeywordHits_createSheet_numChildren_desc(),
|
||||
keywordResults.getKeywords(listName).size()));
|
||||
|
||||
return s;
|
||||
@ -530,22 +573,12 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
|
||||
return v.visit(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Observable o, Object arg) {
|
||||
updateDisplayName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getItemType() {
|
||||
return getClass().getName();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the nodes that represent search terms
|
||||
*/
|
||||
private class TermFactory extends ChildFactory.Detachable<String> implements Observer {
|
||||
private class TermFactory extends DetachableObserverChildFactory<String> {
|
||||
|
||||
private final String setName;
|
||||
|
||||
@ -554,16 +587,6 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
this.setName = setName;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addNotify() {
|
||||
keywordResults.addObserver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeNotify() {
|
||||
keywordResults.deleteObserver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean createKeys(List<String> list) {
|
||||
list.addAll(keywordResults.getKeywords(setName));
|
||||
@ -574,22 +597,17 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
protected Node createNodeForKey(String key) {
|
||||
return new TermNode(setName, key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Observable o, Object arg) {
|
||||
refresh(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the search term or regexp that user searched for
|
||||
*/
|
||||
public class TermNode extends DisplayableItemNode implements Observer {
|
||||
class TermNode extends KWHitsNodeBase {
|
||||
|
||||
private final String setName;
|
||||
private final String keyword;
|
||||
|
||||
public TermNode(String setName, String keyword) {
|
||||
private TermNode(String setName, String keyword) {
|
||||
super(Children.create(new RegExpInstancesFactory(setName, keyword), true), Lookups.singleton(keyword));
|
||||
super.setName(keyword);
|
||||
this.setName = setName;
|
||||
@ -597,22 +615,13 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/keyword_hits.png"); //NON-NLS
|
||||
updateDisplayName();
|
||||
keywordResults.addObserver(this);
|
||||
|
||||
}
|
||||
|
||||
private void updateDisplayName() {
|
||||
super.setDisplayName(keyword + " (" + countTotalDescendants() + ")");
|
||||
}
|
||||
|
||||
private int countTotalDescendants() {
|
||||
return keywordResults.getKeywordInstances(setName, keyword).stream()
|
||||
.mapToInt(instance -> keywordResults.getArtifactIds(setName, keyword, instance).size())
|
||||
.sum();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Observable o, Object arg) {
|
||||
updateDisplayName();
|
||||
int countTotalDescendants() {
|
||||
return keywordResults.getKeywordInstances(setName, keyword).stream()
|
||||
.mapToInt(instance -> keywordResults.getArtifactIds(setName, keyword, instance).size())
|
||||
.sum();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -628,6 +637,9 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
}
|
||||
|
||||
@Override
|
||||
@NbBundle.Messages({"KeywordHits.createSheet.filesWithHits.name=Files with Hits",
|
||||
"KeywordHits.createSheet.filesWithHits.displayName=Files with Hits",
|
||||
"KeywordHits.createSheet.filesWithHits.desc=no description"})
|
||||
protected Sheet createSheet() {
|
||||
Sheet s = super.createSheet();
|
||||
Sheet.Set ss = s.get(Sheet.PROPERTIES);
|
||||
@ -635,30 +647,28 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
ss = Sheet.createPropertiesSet();
|
||||
s.put(ss);
|
||||
}
|
||||
|
||||
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.listName.name"),
|
||||
NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.listName.displayName"),
|
||||
NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.listName.desc"),
|
||||
ss.put(new NodeProperty<>(
|
||||
KeywordHits_createSheet_listName_name(),
|
||||
KeywordHits_createSheet_listName_displayName(),
|
||||
KeywordHits_createSheet_listName_desc(),
|
||||
getDisplayName()));
|
||||
|
||||
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.filesWithHits.name"),
|
||||
NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.filesWithHits.displayName"),
|
||||
NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.filesWithHits.desc"),
|
||||
ss.put(new NodeProperty<>(
|
||||
KeywordHits_createSheet_filesWithHits_name(),
|
||||
KeywordHits_createSheet_filesWithHits_displayName(),
|
||||
KeywordHits_createSheet_filesWithHits_desc(),
|
||||
countTotalDescendants()));
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getItemType() {
|
||||
return getClass().getName();
|
||||
}
|
||||
}
|
||||
|
||||
// Allows us to pass in either longs or strings
|
||||
// as they keys for different types of nodes at the
|
||||
// same level. Probably a better way to do this, but
|
||||
// it works.
|
||||
/**
|
||||
* Allows us to pass in either longs or strings as they keys for different
|
||||
* types of nodes at the same level. Probably a better way to do this, but
|
||||
* it works.
|
||||
*/
|
||||
private class RegExpInstanceKey {
|
||||
|
||||
private final boolean isRegExp;
|
||||
@ -692,29 +702,18 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
* Creates the nodes for a given regexp that represent the specific terms
|
||||
* that were found
|
||||
*/
|
||||
public class RegExpInstancesFactory extends ChildFactory.Detachable<RegExpInstanceKey> implements Observer {
|
||||
private class RegExpInstancesFactory extends DetachableObserverChildFactory<RegExpInstanceKey> {
|
||||
|
||||
private final String keyword;
|
||||
private final String setName;
|
||||
|
||||
private final Map<RegExpInstanceKey, DisplayableItemNode> nodesMap = new HashMap<>();
|
||||
|
||||
public RegExpInstancesFactory(String setName, String keyword) {
|
||||
private RegExpInstancesFactory(String setName, String keyword) {
|
||||
super();
|
||||
this.setName = setName;
|
||||
this.keyword = keyword;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addNotify() {
|
||||
keywordResults.addObserver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeNotify() {
|
||||
keywordResults.deleteObserver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean createKeys(List<RegExpInstanceKey> list) {
|
||||
List<String> instances = keywordResults.getKeywordInstances(setName, keyword);
|
||||
@ -724,17 +723,13 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
if ((instances.size() == 1) && (instances.get(0).equals(DEFAULT_INSTANCE_NAME))) {
|
||||
for (Long id : keywordResults.getArtifactIds(setName, keyword, DEFAULT_INSTANCE_NAME)) {
|
||||
RegExpInstanceKey key = new RegExpInstanceKey(id);
|
||||
if (!nodesMap.containsKey(key)) {
|
||||
nodesMap.put(key, createNode(key));
|
||||
}
|
||||
nodesMap.computeIfAbsent(key, k -> createNode(k));
|
||||
list.add(key);
|
||||
}
|
||||
} else {
|
||||
for (String instance : instances) {
|
||||
RegExpInstanceKey key = new RegExpInstanceKey(instance);
|
||||
if (!nodesMap.containsKey(key)) {
|
||||
nodesMap.put(key, createNode(key));
|
||||
}
|
||||
nodesMap.computeIfAbsent(key, k -> createNode(k));
|
||||
list.add(key);
|
||||
}
|
||||
|
||||
@ -748,32 +743,25 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
}
|
||||
|
||||
private DisplayableItemNode createNode(RegExpInstanceKey key) {
|
||||
// if it isn't a regexp, then skip the 'instance' layer of the tree
|
||||
if (key.isRegExp() == false) {
|
||||
return createBlackboardArtifactNode(key.getIdKey());
|
||||
} else {
|
||||
if (key.isRegExp()) {
|
||||
return new RegExpInstanceNode(setName, keyword, key.getRegExpKey());
|
||||
} else {
|
||||
// if it isn't a regexp, then skip the 'instance' layer of the tree
|
||||
return createBlackboardArtifactNode(key.getIdKey());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Observable o, Object arg) {
|
||||
refresh(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a specific term that was found from a regexp
|
||||
*/
|
||||
public class RegExpInstanceNode extends DisplayableItemNode implements Observer {
|
||||
class RegExpInstanceNode extends KWHitsNodeBase {
|
||||
|
||||
private final String setName;
|
||||
private final String keyword;
|
||||
private final String instance;
|
||||
|
||||
public RegExpInstanceNode(String setName, String keyword, String instance) {
|
||||
private RegExpInstanceNode(String setName, String keyword, String instance) {
|
||||
super(Children.create(new HitsFactory(setName, keyword, instance), true), Lookups.singleton(instance));
|
||||
super.setName(instance); //the instance represents the name of the keyword hit at this point as the keyword is the regex
|
||||
this.setName = setName;
|
||||
@ -784,14 +772,9 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
keywordResults.addObserver(this);
|
||||
}
|
||||
|
||||
private void updateDisplayName() {
|
||||
int totalDescendants = keywordResults.getArtifactIds(setName, keyword, instance).size();
|
||||
super.setDisplayName(instance + " (" + totalDescendants + ")");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Observable o, Object arg) {
|
||||
updateDisplayName();
|
||||
int countTotalDescendants() {
|
||||
return keywordResults.getArtifactIds(setName, keyword, instance).size();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -813,23 +796,21 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
s.put(ss);
|
||||
}
|
||||
|
||||
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.listName.name"),
|
||||
NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.listName.displayName"),
|
||||
NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.listName.desc"),
|
||||
ss.put(new NodeProperty<>(
|
||||
KeywordHits_createSheet_listName_name(),
|
||||
KeywordHits_createSheet_listName_displayName(),
|
||||
KeywordHits_createSheet_listName_desc(),
|
||||
getDisplayName()));
|
||||
|
||||
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.filesWithHits.name"),
|
||||
NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.filesWithHits.displayName"),
|
||||
NbBundle.getMessage(this.getClass(), "KeywordHits.createSheet.filesWithHits.desc"),
|
||||
ss.put(new NodeProperty<>(
|
||||
KeywordHits_createSheet_filesWithHits_name(),
|
||||
KeywordHits_createSheet_filesWithHits_displayName(),
|
||||
KeywordHits_createSheet_filesWithHits_desc(),
|
||||
keywordResults.getArtifactIds(setName, keyword, instance).size()));
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getItemType() {
|
||||
return getClass().getName();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -839,6 +820,15 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
*
|
||||
* @return Node or null on error
|
||||
*/
|
||||
@NbBundle.Messages({"KeywordHits.createNodeForKey.modTime.name=ModifiedTime",
|
||||
"KeywordHits.createNodeForKey.modTime.displayName=Modified Time",
|
||||
"KeywordHits.createNodeForKey.modTime.desc=Modified Time",
|
||||
"KeywordHits.createNodeForKey.accessTime.name=AccessTime",
|
||||
"KeywordHits.createNodeForKey.accessTime.displayName=Access Time",
|
||||
"KeywordHits.createNodeForKey.accessTime.desc=Access Time",
|
||||
"KeywordHits.createNodeForKey.chgTime.name=ChangeTime",
|
||||
"KeywordHits.createNodeForKey.chgTime.displayName=Change Time",
|
||||
"KeywordHits.createNodeForKey.chgTime.desc=Change Time"})
|
||||
private BlackboardArtifactNode createBlackboardArtifactNode(Long artifactId) {
|
||||
if (skCase == null) {
|
||||
return null;
|
||||
@ -851,40 +841,36 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
try {
|
||||
file = skCase.getAbstractFileById(art.getObjectID());
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "TskCoreException while constructing BlackboardArtifact Node from KeywordHitsKeywordChildren"); //NON-NLS
|
||||
logger.log(Level.SEVERE, "TskCoreException while constructing BlackboardArtifact Node from KeywordHitsKeywordChildren", ex); //NON-NLS
|
||||
return n;
|
||||
}
|
||||
|
||||
// It is possible to get a keyword hit on artifacts generated
|
||||
// for the underlying image in which case MAC times are not
|
||||
// available/applicable/useful.
|
||||
/*
|
||||
* It is possible to get a keyword hit on artifacts generated for
|
||||
* the underlying image in which case MAC times are not
|
||||
* available/applicable/useful.
|
||||
*/
|
||||
if (file == null) {
|
||||
return n;
|
||||
}
|
||||
|
||||
n.addNodeProperty(new NodeProperty<>(
|
||||
NbBundle.getMessage(this.getClass(), "KeywordHits.createNodeForKey.modTime.name"),
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"KeywordHits.createNodeForKey.modTime.displayName"),
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"KeywordHits.createNodeForKey.modTime.desc"),
|
||||
KeywordHits_createNodeForKey_modTime_name(),
|
||||
KeywordHits_createNodeForKey_modTime_displayName(),
|
||||
KeywordHits_createNodeForKey_modTime_desc(),
|
||||
ContentUtils.getStringTime(file.getMtime(), file)));
|
||||
n.addNodeProperty(new NodeProperty<>(
|
||||
NbBundle.getMessage(this.getClass(), "KeywordHits.createNodeForKey.accessTime.name"),
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"KeywordHits.createNodeForKey.accessTime.displayName"),
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"KeywordHits.createNodeForKey.accessTime.desc"),
|
||||
KeywordHits_createNodeForKey_accessTime_name(),
|
||||
KeywordHits_createNodeForKey_accessTime_displayName(),
|
||||
KeywordHits_createNodeForKey_accessTime_desc(),
|
||||
ContentUtils.getStringTime(file.getAtime(), file)));
|
||||
n.addNodeProperty(new NodeProperty<>(
|
||||
NbBundle.getMessage(this.getClass(), "KeywordHits.createNodeForKey.chgTime.name"),
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"KeywordHits.createNodeForKey.chgTime.displayName"),
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"KeywordHits.createNodeForKey.chgTime.desc"),
|
||||
KeywordHits_createNodeForKey_chgTime_name(),
|
||||
KeywordHits_createNodeForKey_chgTime_displayName(),
|
||||
KeywordHits_createNodeForKey_chgTime_desc(),
|
||||
ContentUtils.getStringTime(file.getCtime(), file)));
|
||||
return n;
|
||||
} catch (TskException ex) {
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, "TSK Exception occurred", ex); //NON-NLS
|
||||
}
|
||||
return null;
|
||||
@ -893,37 +879,24 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
/**
|
||||
* Creates nodes for individual files that had hits
|
||||
*/
|
||||
public class HitsFactory extends ChildFactory.Detachable<Long> implements Observer {
|
||||
private class HitsFactory extends DetachableObserverChildFactory<Long> {
|
||||
|
||||
private final String keyword;
|
||||
private final String setName;
|
||||
private final String instance;
|
||||
|
||||
private final Map<Long, BlackboardArtifactNode> nodesMap = new HashMap<>();
|
||||
|
||||
public HitsFactory(String setName, String keyword, String instance) {
|
||||
private HitsFactory(String setName, String keyword, String instance) {
|
||||
super();
|
||||
this.setName = setName;
|
||||
this.keyword = keyword;
|
||||
this.instance = instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addNotify() {
|
||||
keywordResults.addObserver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeNotify() {
|
||||
keywordResults.deleteObserver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean createKeys(List<Long> list) {
|
||||
for (Long id : keywordResults.getArtifactIds(setName, keyword, instance)) {
|
||||
if (!nodesMap.containsKey(id)) {
|
||||
nodesMap.put(id, createBlackboardArtifactNode(id));
|
||||
}
|
||||
nodesMap.computeIfAbsent(id, i -> createBlackboardArtifactNode(i));
|
||||
list.add(id);
|
||||
}
|
||||
return true;
|
||||
@ -933,10 +906,5 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
protected Node createNodeForKey(Long artifactId) {
|
||||
return nodesMap.get(artifactId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Observable o, Object arg) {
|
||||
refresh(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -20,7 +20,6 @@ package org.sleuthkit.autopsy.datamodel;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
|
||||
/**
|
||||
* Children implementation for the root node of a ContentNode tree. Accepts a
|
||||
@ -28,7 +27,7 @@ import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
*/
|
||||
public class RootContentChildren extends AbstractContentChildren<Object> {
|
||||
|
||||
private Collection<? extends Object> contentKeys;
|
||||
private final Collection<? extends Object> contentKeys;
|
||||
|
||||
/**
|
||||
* @param contentKeys root Content objects for the Node tree
|
||||
@ -55,8 +54,6 @@ public class RootContentChildren extends AbstractContentChildren<Object> {
|
||||
* but we are not ready for this.
|
||||
*/
|
||||
public void refreshContentKeys() {
|
||||
for (Object key : contentKeys) {
|
||||
refreshKey(key);
|
||||
}
|
||||
contentKeys.forEach(this::refreshKey);
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="jScrollPane1" alignment="0" pref="262" max="32767" attributes="0"/>
|
||||
<Component id="treeView" alignment="0" pref="262" max="32767" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace min="-2" pref="5" max="-2" attributes="0"/>
|
||||
<Component id="backButton" min="-2" pref="23" max="-2" attributes="0"/>
|
||||
@ -38,14 +38,14 @@
|
||||
<Component id="showRejectedCheckBox" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jScrollPane1" pref="854" max="32767" attributes="0"/>
|
||||
<Component id="treeView" pref="854" max="32767" attributes="0"/>
|
||||
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
|
||||
<Container class="javax.swing.JScrollPane" name="treeView">
|
||||
<Properties>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="null"/>
|
||||
|
@ -30,11 +30,13 @@ import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.prefs.PreferenceChangeEvent;
|
||||
import java.util.prefs.PreferenceChangeListener;
|
||||
import javax.swing.Action;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.SwingWorker;
|
||||
import javax.swing.tree.TreeSelectionModel;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openide.explorer.ExplorerManager;
|
||||
@ -114,7 +116,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
||||
initComponents();
|
||||
|
||||
// only allow one item to be selected at a time
|
||||
((BeanTreeView) jScrollPane1).setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
|
||||
getTree().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
|
||||
// remove the close button
|
||||
putClientProperty(TopComponent.PROP_CLOSING_DISABLED, Boolean.TRUE);
|
||||
setName(NbBundle.getMessage(DirectoryTreeTopComponent.class, "CTL_DirectoryTreeTopComponent"));
|
||||
@ -175,12 +177,12 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
|
||||
jScrollPane1 = new BeanTreeView();
|
||||
treeView = new BeanTreeView();
|
||||
backButton = new javax.swing.JButton();
|
||||
forwardButton = new javax.swing.JButton();
|
||||
showRejectedCheckBox = new javax.swing.JCheckBox();
|
||||
|
||||
jScrollPane1.setBorder(null);
|
||||
treeView.setBorder(null);
|
||||
|
||||
backButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/directorytree/btn_step_back.png"))); // NOI18N
|
||||
org.openide.awt.Mnemonics.setLocalizedText(backButton, org.openide.util.NbBundle.getMessage(DirectoryTreeTopComponent.class, "DirectoryTreeTopComponent.backButton.text")); // NOI18N
|
||||
@ -220,7 +222,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 262, Short.MAX_VALUE)
|
||||
.addComponent(treeView, javax.swing.GroupLayout.DEFAULT_SIZE, 262, Short.MAX_VALUE)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(5, 5, 5)
|
||||
.addComponent(backButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
@ -239,7 +241,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
||||
.addComponent(backButton, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(showRejectedCheckBox))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 854, Short.MAX_VALUE)
|
||||
.addComponent(treeView, javax.swing.GroupLayout.DEFAULT_SIZE, 854, Short.MAX_VALUE)
|
||||
.addGap(0, 0, 0))
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
@ -296,8 +298,8 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JButton backButton;
|
||||
private javax.swing.JButton forwardButton;
|
||||
private javax.swing.JScrollPane jScrollPane1;
|
||||
private javax.swing.JCheckBox showRejectedCheckBox;
|
||||
private javax.swing.JScrollPane treeView;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
/**
|
||||
@ -360,106 +362,117 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
||||
public void componentOpened() {
|
||||
// change the cursor to "waiting cursor" for this operation
|
||||
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
Case currentCase = null;
|
||||
try {
|
||||
Case currentCase = null;
|
||||
try {
|
||||
currentCase = Case.getCurrentCase();
|
||||
} catch (IllegalStateException ex) {
|
||||
/*
|
||||
* No open case.
|
||||
currentCase = Case.getCurrentCase();
|
||||
} catch (IllegalStateException ex) {
|
||||
// No open case.
|
||||
}
|
||||
|
||||
// close the top component if there's no image in this case
|
||||
if (null == currentCase || currentCase.hasData() == false) {
|
||||
getTree().setRootVisible(false); // hide the root
|
||||
} else {
|
||||
// if there's at least one image, load the image and open the top component
|
||||
final SleuthkitCase tskCase = currentCase.getSleuthkitCase();
|
||||
contentChildren = new RootContentChildren(Arrays.asList(
|
||||
new DataSources(),
|
||||
new Views(tskCase),
|
||||
new Results(tskCase),
|
||||
new Tags(),
|
||||
new Reports()));
|
||||
Node root = new AbstractNode(contentChildren) {
|
||||
//JIRA-2807: What is the point of these overrides?
|
||||
/**
|
||||
* to override the right click action in the white blank space
|
||||
* area on the directory tree window
|
||||
*/
|
||||
}
|
||||
@Override
|
||||
public Action[] getActions(boolean popup) {
|
||||
return new Action[]{};
|
||||
}
|
||||
|
||||
// close the top component if there's no image in this case
|
||||
if (null == currentCase || currentCase.hasData() == false) {
|
||||
((TreeView) this.jScrollPane1).setRootVisible(false); // hide the root
|
||||
} else {
|
||||
// if there's at least one image, load the image and open the top component
|
||||
List<Object> items = new ArrayList<>();
|
||||
final SleuthkitCase tskCase = currentCase.getSleuthkitCase();
|
||||
items.add(new DataSources());
|
||||
items.add(new Views(tskCase));
|
||||
items.add(new Results(tskCase));
|
||||
items.add(new Tags());
|
||||
items.add(new Reports());
|
||||
contentChildren = new RootContentChildren(items);
|
||||
// Overide the AbstractNode use of DefaultHandle to return
|
||||
// a handle which can be serialized without a parent
|
||||
@Override
|
||||
public Node.Handle getHandle() {
|
||||
return new Node.Handle() {
|
||||
@Override
|
||||
public Node getNode() throws IOException {
|
||||
return em.getRootContext();
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
Node root = new AbstractNode(contentChildren) {
|
||||
/**
|
||||
* to override the right click action in the white blank
|
||||
* space area on the directory tree window
|
||||
root = new DirectoryTreeFilterNode(root, true);
|
||||
|
||||
em.setRootContext(root);
|
||||
em.getRootContext().setName(currentCase.getName());
|
||||
em.getRootContext().setDisplayName(currentCase.getName());
|
||||
getTree().setRootVisible(false); // hide the root
|
||||
|
||||
// Reset the forward and back lists because we're resetting the root context
|
||||
resetHistory();
|
||||
new SwingWorker<Node[], Void>() {
|
||||
@Override
|
||||
protected Node[] doInBackground() throws Exception {
|
||||
Children rootChildren = em.getRootContext().getChildren();
|
||||
TreeView tree = getTree();
|
||||
|
||||
Node results = rootChildren.findChild(ResultsNode.NAME);
|
||||
tree.expandNode(results);
|
||||
Children resultsChildren = results.getChildren();
|
||||
Arrays.stream(resultsChildren.getNodes()).forEach(tree::expandNode);
|
||||
|
||||
Accounts accounts = resultsChildren.findChild(Accounts.NAME).getLookup().lookup(Accounts.class);
|
||||
showRejectedCheckBox.setAction(accounts.newToggleShowRejectedAction());
|
||||
showRejectedCheckBox.setSelected(false);
|
||||
|
||||
Node views = rootChildren.findChild(ViewsNode.NAME);
|
||||
Arrays.stream(views.getChildren().getNodes()).forEach(tree::expandNode);
|
||||
tree.collapseNode(views);
|
||||
/*
|
||||
* JIRA-2806: What is this supposed to do? Right now it selects
|
||||
* the data sources node, but the comment seems to indicate
|
||||
* it is supposed to select the first datasource.
|
||||
*/
|
||||
@Override
|
||||
public Action[] getActions(boolean popup) {
|
||||
return new Action[]{};
|
||||
// select the first image node, if there is one
|
||||
// (this has to happen after dataResult is opened, because the event
|
||||
// of changing the selected node fires a handler that tries to make
|
||||
// dataResult active)
|
||||
if (rootChildren.getNodesCount() > 0) {
|
||||
return new Node[]{rootChildren.getNodeAt(0)};
|
||||
}
|
||||
return new Node[]{};
|
||||
}
|
||||
|
||||
// Overide the AbstractNode use of DefaultHandle to return
|
||||
// a handle which can be serialized without a parent
|
||||
@Override
|
||||
public Node.Handle getHandle() {
|
||||
return new Node.Handle() {
|
||||
@Override
|
||||
public Node getNode() throws IOException {
|
||||
return em.getRootContext();
|
||||
}
|
||||
};
|
||||
@Override
|
||||
protected void done() {
|
||||
super.done();
|
||||
|
||||
// if the dataResult is not opened
|
||||
if (!dataResult.isOpened()) {
|
||||
dataResult.open(); // open the data result top component as well when the directory tree is opened
|
||||
}
|
||||
};
|
||||
|
||||
root = new DirectoryTreeFilterNode(root, true);
|
||||
|
||||
em.setRootContext(root);
|
||||
em.getRootContext().setName(currentCase.getName());
|
||||
em.getRootContext().setDisplayName(currentCase.getName());
|
||||
((TreeView) this.jScrollPane1).setRootVisible(false); // hide the root
|
||||
|
||||
// Reset the forward and back lists because we're resetting the root context
|
||||
resetHistory();
|
||||
|
||||
Children childNodes = em.getRootContext().getChildren();
|
||||
TreeView tree = getTree();
|
||||
|
||||
Node results = childNodes.findChild(ResultsNode.NAME);
|
||||
tree.expandNode(results);
|
||||
|
||||
Children resultsChilds = results.getChildren();
|
||||
for (Node n : resultsChilds.getNodes()) {
|
||||
tree.expandNode(n);
|
||||
}
|
||||
|
||||
Accounts accounts = resultsChilds.findChild(Accounts.NAME).getLookup().lookup(Accounts.class);
|
||||
showRejectedCheckBox.setAction(accounts.newToggleShowRejectedAction());
|
||||
showRejectedCheckBox.setSelected(false);
|
||||
|
||||
Node views = childNodes.findChild(ViewsNode.NAME);
|
||||
Children viewsChilds = views.getChildren();
|
||||
for (Node n : viewsChilds.getNodes()) {
|
||||
tree.expandNode(n);
|
||||
}
|
||||
|
||||
tree.collapseNode(views);
|
||||
|
||||
// if the dataResult is not opened
|
||||
if (!dataResult.isOpened()) {
|
||||
dataResult.open(); // open the data result top component as well when the directory tree is opened
|
||||
}
|
||||
|
||||
// select the first image node, if there is one
|
||||
// (this has to happen after dataResult is opened, because the event
|
||||
// of changing the selected node fires a handler that tries to make
|
||||
// dataResult active)
|
||||
if (childNodes.getNodesCount() > 0) {
|
||||
/*
|
||||
* JIRA-2806: What is this supposed to do?
|
||||
*/
|
||||
// select the first image node, if there is one
|
||||
// (this has to happen after dataResult is opened, because the event
|
||||
// of changing the selected node fires a handler that tries to make
|
||||
// dataResult active)
|
||||
try {
|
||||
em.setSelectedNodes(new Node[]{childNodes.getNodeAt(0)});
|
||||
em.setSelectedNodes(get());
|
||||
} catch (PropertyVetoException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error setting default selected node.", ex); //NON-NLS
|
||||
} catch (InterruptedException | ExecutionException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error expanding tree to initial state.", ex); //NON-NLS
|
||||
} finally {
|
||||
setCursor(null);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} finally {
|
||||
this.setCursor(null);
|
||||
}.execute();
|
||||
}
|
||||
}
|
||||
|
||||
@ -605,9 +618,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
||||
// We only need to trigger openCoreWindows() when the
|
||||
// first data source is added.
|
||||
if (currentCase.getDataSources().size() == 1) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
CoreComponentControl.openCoreWindows();
|
||||
});
|
||||
SwingUtilities.invokeLater(CoreComponentControl::openCoreWindows);
|
||||
}
|
||||
} catch (IllegalStateException | TskCoreException notUsed) {
|
||||
/**
|
||||
@ -749,19 +760,14 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
||||
* @return tree the BeanTreeView
|
||||
*/
|
||||
public BeanTreeView getTree() {
|
||||
return (BeanTreeView) this.jScrollPane1;
|
||||
return (BeanTreeView) this.treeView;
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the content node part of the dir tree safely in the EDT thread
|
||||
*/
|
||||
public void refreshContentTreeSafe() {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
refreshDataSourceTree();
|
||||
}
|
||||
});
|
||||
SwingUtilities.invokeLater(this::refreshDataSourceTree);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -801,7 +807,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
||||
ArrayList<String> selectedNodePath = new ArrayList<>(Arrays.asList(previouslySelectedNodePath));
|
||||
while (null == selectedNode && !selectedNodePath.isEmpty()) {
|
||||
try {
|
||||
selectedNode = NodeOp.findPath(em.getRootContext(), selectedNodePath.toArray(new String[0]));
|
||||
selectedNode = NodeOp.findPath(em.getRootContext(), selectedNodePath.toArray(new String[selectedNodePath.size()]));
|
||||
} catch (NodeNotFoundException ex) {
|
||||
// The selected node may have been deleted (e.g., a deleted tag), so truncate the path and try again.
|
||||
if (selectedNodePath.size() > 1) {
|
||||
@ -1028,7 +1034,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
||||
}
|
||||
treeNode = binChildren.findChild(binName);
|
||||
} else { //default account type
|
||||
treeNode = accountRootChilds.findChild(accountType);;
|
||||
treeNode = accountRootChilds.findChild(accountType);
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
LOGGER.log(Level.WARNING, "Error retrieving attributes", ex); //NON-NLS
|
||||
|
@ -55,7 +55,7 @@ import org.sleuthkit.datamodel.VolumeSystem;
|
||||
* selecting the parent in the tree view, then selecting the content in the
|
||||
* results view.
|
||||
*/
|
||||
public final class ViewContextAction extends AbstractAction {
|
||||
public class ViewContextAction extends AbstractAction {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger logger = Logger.getLogger(ViewContextAction.class.getName());
|
||||
|
@ -49,7 +49,7 @@ package org.sleuthkit.autopsy.ingest;
|
||||
* implementations must be marked with the following NetBeans Service provider
|
||||
* annotation:
|
||||
*
|
||||
* <pre>@ServiceProvider(service=IngestModuleFactory.class)</pre>
|
||||
* <pre>\@ServiceProvider(service=IngestModuleFactory.class)</pre>
|
||||
* <p>
|
||||
* IMPORTANT TIP: If an implementation of IngestModuleFactory does not need to
|
||||
* provide implementations of all of the IngestModuleFactory methods, it can
|
||||
|
@ -42,6 +42,7 @@ import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.logging.Level;
|
||||
import javax.imageio.ImageIO;
|
||||
@ -622,7 +623,7 @@ class ReportHTML implements TableReportModule {
|
||||
*
|
||||
* @param images
|
||||
*/
|
||||
public void addThumbnailRows(List<Content> images) {
|
||||
public void addThumbnailRows(Set<Content> images) {
|
||||
List<String> currentRow = new ArrayList<>();
|
||||
int totalCount = 0;
|
||||
int pages = 1;
|
||||
|
@ -59,7 +59,7 @@ class TableReportGenerator {
|
||||
private final List<BlackboardArtifact.Type> artifactTypes = new ArrayList<>();
|
||||
private final HashSet<String> tagNamesFilter = new HashSet<>();
|
||||
|
||||
private final List<Content> images = new ArrayList<>();
|
||||
private final Set<Content> images = new HashSet<>();
|
||||
private final ReportProgressPanel progressPanel;
|
||||
private final TableReportModule tableReport;
|
||||
private final Map<Integer, List<Column>> columnHeaderMap;
|
||||
|
@ -13,17 +13,13 @@
|
||||
|
||||
<target name="resolve">
|
||||
<ivy:settings file="ivysettings.xml" />
|
||||
<ivy:resolve file="ivy.xml" conf="experimental, eam"/>
|
||||
<ivy:resolve file="ivy.xml" conf="experimental"/>
|
||||
</target>
|
||||
|
||||
<target name="retrieve-experimental" depends="resolve">
|
||||
<ivy:retrieve conf="experimental" pattern="${basedir}/release/modules/ext/[artifact]-[revision](-[classifier]).[ext]" />
|
||||
</target>
|
||||
|
||||
<target name="retrieve-eam" depends="resolve">
|
||||
<ivy:retrieve conf="eam" pattern="${basedir}/release/modules/ext/[artifact]-[revision](-[classifier]).[ext]" />
|
||||
</target>
|
||||
|
||||
<target name="retrieve-all" depends="resolve">
|
||||
<ivy:retrieve conf="*" pattern="${basedir}/release/modules/ext/[artifact]-[revision](-[classifier]).[ext]" />
|
||||
</target>
|
||||
|
@ -3,8 +3,6 @@
|
||||
<configurations >
|
||||
<!-- module dependencies -->
|
||||
<conf name="experimental"/>
|
||||
|
||||
<conf name="eam"/>
|
||||
</configurations>
|
||||
<dependencies>
|
||||
<dependency conf="experimental->default" org="com.github.lgooddatepicker" name="LGoodDatePicker" rev="4.3.1"/>
|
||||
@ -13,13 +11,5 @@
|
||||
<dependency conf="experimental->default" org="com.mchange" name="c3p0" rev="0.9.5"/>
|
||||
<dependency conf="experimental->default" org="com.fasterxml.jackson.core" name="jackson-core" rev="2.7.0"/>
|
||||
<dependency conf="experimental->default" org="org.swinglabs.swingx" name="swingx-all" rev="1.6.4"/>
|
||||
|
||||
<!-- for enterprise artifacts manager -->
|
||||
<dependency conf="eam->default" org="org.apache.commons" name="commons-dbcp2" rev="2.1.1"/>
|
||||
<dependency conf="eam->default" org="commons-logging" name="commons-logging" rev="1.2"/>
|
||||
<dependency conf="eam->default" org="org.apache.commons" name="commons-pool2" rev="2.4.2"/>
|
||||
<dependency conf="eam->default" org="org.postgresql" name="postgresql" rev="42.1.1"/>
|
||||
<dependency conf="eam->default" org="org.xerial" name="sqlite-jdbc" rev="3.16.1"/>
|
||||
|
||||
</dependencies>
|
||||
</ivy-module>
|
||||
|
@ -4,4 +4,3 @@ OpenIDE-Module: org.sleuthkit.autopsy.experimental
|
||||
OpenIDE-Module-Layer: org/sleuthkit/autopsy/experimental/autoingest/layer.xml
|
||||
OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties
|
||||
OpenIDE-Module-Specification-Version: 1.0
|
||||
OpenIDE-Module-Install: org/sleuthkit/autopsy/experimental/enterpriseartifactsmanager/eventlisteners/Installer.class
|
@ -110,7 +110,7 @@
|
||||
<compile-dependency/>
|
||||
<run-dependency>
|
||||
<release-version>10</release-version>
|
||||
<specification-version>10.7</specification-version>
|
||||
<specification-version>10.8</specification-version>
|
||||
</run-dependency>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@ -156,26 +156,6 @@
|
||||
<runtime-relative-path>ext/c3p0-0.9.5.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/c3p0-0.9.5.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/commons-dbcp2-2.1.1.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/commons-dbcp2-2.1.1.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/commons-logging-1.2.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/commons-logging-1.2.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/commons-pool2-2.4.2.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/commons-pool2-2.4.2.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/postgresql-42.0.0.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/postgresql-42.0.0.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/sqlite-jdbc-3.16.1.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/sqlite-jdbc-3.16.1.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
</data>
|
||||
</configuration>
|
||||
</project>
|
||||
|
@ -774,8 +774,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Removes a set of auto ingest jobs from a collection of jobs.
|
||||
*
|
||||
@ -915,8 +913,11 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
AutoIngestManager.this.completedJobs = newCompletedJobsList;
|
||||
|
||||
} catch (Exception ex) {
|
||||
/* NOTE: Need to catch all exceptions here. Otherwise uncaught exceptions will
|
||||
propagate up to the calling thread and may stop it from running.*/
|
||||
/*
|
||||
* NOTE: Need to catch all exceptions here. Otherwise
|
||||
* uncaught exceptions will propagate up to the calling
|
||||
* thread and may stop it from running.
|
||||
*/
|
||||
SYS_LOGGER.log(Level.SEVERE, String.format("Error scanning the input directory %s", rootInputDirectory), ex);
|
||||
}
|
||||
}
|
||||
@ -2274,6 +2275,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
* is shutting down.
|
||||
*/
|
||||
ingestLock.wait();
|
||||
SYS_LOGGER.log(Level.INFO, "Finished ingest modules analysis for {0} ", manifestPath);
|
||||
IngestJob.ProgressSnapshot jobSnapshot = ingestJob.getSnapshot();
|
||||
for (IngestJob.ProgressSnapshot.DataSourceProcessingSnapshot snapshot : jobSnapshot.getDataSourceSnapshots()) {
|
||||
if (!snapshot.isCancelled()) {
|
||||
@ -2505,9 +2507,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
String eventType = event.getPropertyName();
|
||||
if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) {
|
||||
synchronized (ingestLock) {
|
||||
if (!IngestManager.getInstance().isIngestRunning()) {
|
||||
ingestLock.notify();
|
||||
}
|
||||
ingestLock.notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ public class SharedConfiguration {
|
||||
private static final String HASHDB_CONFIG_FILE_NAME = "hashLookup.settings"; //NON-NLS
|
||||
private static final String HASHDB_CONFIG_FILE_NAME_LEGACY = "hashsets.xml"; //NON-NLS
|
||||
public static final String FILE_EXPORTER_SETTINGS_FILE = "fileexporter.settings"; //NON-NLS
|
||||
private static final String ENTERPRISE_ARTIFACTS_MANAGER_PROPERTIES_FILE = "EnterpriseArtifactsManager.properties"; //NON-NLS
|
||||
private static final String CENTRAL_REPOSITORY_PROPERTIES_FILE = "CentralRepository.properties"; //NON-NLS
|
||||
private static final String SHARED_CONFIG_VERSIONS = "SharedConfigVersions.txt"; //NON-NLS
|
||||
|
||||
// Folders
|
||||
@ -206,7 +206,7 @@ public class SharedConfiguration {
|
||||
uploadMultiUserAndGeneralSettings(remoteFolder);
|
||||
uploadHashDbSettings(remoteFolder);
|
||||
uploadFileExporterSettings(remoteFolder);
|
||||
uploadEnterpriseArtifactsManagerSettings(remoteFolder);
|
||||
uploadCentralRepositorySettings(remoteFolder);
|
||||
|
||||
try {
|
||||
Files.deleteIfExists(uploadInProgress.toPath());
|
||||
@ -271,7 +271,7 @@ public class SharedConfiguration {
|
||||
downloadFileExtMismatchSettings(remoteFolder);
|
||||
downloadAndroidTriageSettings(remoteFolder);
|
||||
downloadFileExporterSettings(remoteFolder);
|
||||
downloadEnterpriseArtifactsManagerSettings(remoteFolder);
|
||||
downloadCentralRepositorySettings(remoteFolder);
|
||||
|
||||
// Download general settings, then restore the current
|
||||
// values for the unshared fields
|
||||
@ -778,27 +778,27 @@ public class SharedConfiguration {
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload Enterprise Artifacts Manager settings.
|
||||
* Upload Central Repository settings.
|
||||
*
|
||||
* @param remoteFolder Shared settings folder
|
||||
*
|
||||
* @throws SharedConfigurationException
|
||||
*/
|
||||
private void uploadEnterpriseArtifactsManagerSettings(File remoteFolder) throws SharedConfigurationException {
|
||||
publishTask("Uploading Enterprise Artifacts Manager configuration");
|
||||
copyToRemoteFolder(ENTERPRISE_ARTIFACTS_MANAGER_PROPERTIES_FILE, moduleDirPath, remoteFolder, true);
|
||||
private void uploadCentralRepositorySettings(File remoteFolder) throws SharedConfigurationException {
|
||||
publishTask("Uploading Central Repository configuration");
|
||||
copyToRemoteFolder(CENTRAL_REPOSITORY_PROPERTIES_FILE, moduleDirPath, remoteFolder, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Download Enterprise Artifacts Manager settings.
|
||||
* Download Central Repository settings.
|
||||
*
|
||||
* @param remoteFolder Shared settings folder
|
||||
*
|
||||
* @throws SharedConfigurationException
|
||||
*/
|
||||
private void downloadEnterpriseArtifactsManagerSettings(File remoteFolder) throws SharedConfigurationException {
|
||||
publishTask("Downloading Enterprise Artifacts Manager configuration");
|
||||
copyToLocalFolder(ENTERPRISE_ARTIFACTS_MANAGER_PROPERTIES_FILE, moduleDirPath, remoteFolder, true);
|
||||
private void downloadCentralRepositorySettings(File remoteFolder) throws SharedConfigurationException {
|
||||
publishTask("Downloading Central Repository configuration");
|
||||
copyToLocalFolder(CENTRAL_REPOSITORY_PROPERTIES_FILE, moduleDirPath, remoteFolder, true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,7 +0,0 @@
|
||||
OpenIDE-Module-Display-Category=Ingest Module
|
||||
OpenIDE-Module-Name=Enterprise Artifacts Manager
|
||||
OpenIDE-Module-Short-Description=Enterprise Artifacts Manager Ingest Module
|
||||
OpenIDE-Module-Long-Description=\
|
||||
Enterprise Artifacts Manager ingest module. \n\n\
|
||||
This ingest module stores artifacts of selected types into a central database.\n\
|
||||
Stored artifacts are used by future cases to compare and analyzes file and artifacts during ingest.
|
@ -1,283 +0,0 @@
|
||||
/*
|
||||
* Enterprise Artifacts Manager
|
||||
*
|
||||
* Copyright 2015-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> 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.experimental.enterpriseartifactsmanager.datamodel;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
*
|
||||
* Used to store info about a specific artifact.
|
||||
*/
|
||||
public class EamArtifact implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String ID;
|
||||
private String artifactValue;
|
||||
private Type artifactType;
|
||||
private final List<EamArtifactInstance> artifactInstances;
|
||||
|
||||
/**
|
||||
* Load the default correlation artifact types
|
||||
*/
|
||||
public static List<EamArtifact.Type> getDefaultArtifactTypes() {
|
||||
List<EamArtifact.Type> DEFAULT_ARTIFACT_TYPES = new ArrayList<>();
|
||||
DEFAULT_ARTIFACT_TYPES.add(new EamArtifact.Type("FILES", true, true)); // NON-NLS
|
||||
DEFAULT_ARTIFACT_TYPES.add(new EamArtifact.Type("DOMAIN", true, false)); // NON-NLS
|
||||
DEFAULT_ARTIFACT_TYPES.add(new EamArtifact.Type("EMAIL", true, false)); // NON-NLS
|
||||
DEFAULT_ARTIFACT_TYPES.add(new EamArtifact.Type("PHONE", true, false)); // NON-NLS
|
||||
DEFAULT_ARTIFACT_TYPES.add(new EamArtifact.Type("USBID", true, false)); // NON-NLS
|
||||
return DEFAULT_ARTIFACT_TYPES;
|
||||
}
|
||||
|
||||
public EamArtifact(Type artifactType, String artifactValue) {
|
||||
this.ID = "";
|
||||
this.artifactType = artifactType;
|
||||
this.artifactValue = artifactValue;
|
||||
this.artifactInstances = new ArrayList<>();
|
||||
}
|
||||
|
||||
public Boolean equals(EamArtifact otherArtifact) {
|
||||
return ((this.getID().equals(otherArtifact.getID()))
|
||||
&& (this.getArtifactType().equals(otherArtifact.getArtifactType()))
|
||||
&& (this.getArtifactValue().equals(otherArtifact.getArtifactValue()))
|
||||
&& (this.getInstances().equals(otherArtifact.getInstances())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String result = this.getID()
|
||||
+ this.getArtifactType().toString()
|
||||
+ this.getArtifactValue();
|
||||
result = this.getInstances().stream().map((inst) -> inst.toString()).reduce(result, String::concat);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the ID
|
||||
*/
|
||||
public String getID() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ID the ID to set
|
||||
*/
|
||||
public void setID(String ID) {
|
||||
this.ID = ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the artifactValue
|
||||
*/
|
||||
public String getArtifactValue() {
|
||||
return artifactValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param artifactValue the artifactValue to set
|
||||
*/
|
||||
public void setArtifactValue(String artifactValue) {
|
||||
this.artifactValue = artifactValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the artifact Type
|
||||
*/
|
||||
public Type getArtifactType() {
|
||||
return artifactType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param artifactType the artifact Type to set
|
||||
*/
|
||||
public void setArtifactType(Type artifactType) {
|
||||
this.artifactType = artifactType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the List of artifactInstances; empty list of none have been
|
||||
* added.
|
||||
*/
|
||||
public List<EamArtifactInstance> getInstances() {
|
||||
return new ArrayList<>(artifactInstances);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param artifactInstances the List of artifactInstances to set.
|
||||
*/
|
||||
public void setInstances(List<EamArtifactInstance> artifactInstances) {
|
||||
this.artifactInstances.clear();
|
||||
if (null != artifactInstances) {
|
||||
this.artifactInstances.addAll(artifactInstances);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param instance the instance to add
|
||||
*/
|
||||
public void addInstance(EamArtifactInstance artifactInstance) {
|
||||
this.artifactInstances.add(artifactInstance);
|
||||
}
|
||||
|
||||
public static class Type implements Serializable {
|
||||
|
||||
private int id;
|
||||
private String name;
|
||||
private Boolean supported;
|
||||
private Boolean enabled;
|
||||
|
||||
public Type(int id, String name, Boolean supported, Boolean enabled) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.supported = supported;
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public Type(String name, Boolean supported, Boolean enabled) {
|
||||
this(-1, name, supported, enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if 2 Type objects are equal based on having the same
|
||||
* Type.name.
|
||||
*
|
||||
* @param otherType Type object for comparison.
|
||||
*
|
||||
* @return true or false
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object that) {
|
||||
if (this == that) {
|
||||
return true;
|
||||
} else if (!(that instanceof EamArtifact.Type)) {
|
||||
return false;
|
||||
} else {
|
||||
return ((EamArtifact.Type) that).sameType(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the content of this artifact type object is equivalent
|
||||
* to the content of another artifact type object.
|
||||
*
|
||||
* @param that the other type
|
||||
*
|
||||
* @return true if it is the same type
|
||||
*/
|
||||
private boolean sameType(EamArtifact.Type that) {
|
||||
return this.id == that.getId()
|
||||
&& this.name.equals(that.getName())
|
||||
&& Objects.equals(this.supported, that.isSupported())
|
||||
&& Objects.equals(this.enabled, that.isEnabled());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 7;
|
||||
hash = 67 * hash + Objects.hashCode(this.id);
|
||||
hash = 67 * hash + Objects.hashCode(this.name);
|
||||
hash = 67 * hash + Objects.hashCode(this.supported);
|
||||
hash = 67 * hash + Objects.hashCode(this.enabled);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder str = new StringBuilder();
|
||||
str.append("(id=").append(id);
|
||||
str.append(", name=").append(name);
|
||||
str.append(", supported=").append(supported.toString());
|
||||
str.append(", enabled=").append(enabled.toString());
|
||||
str.append(")");
|
||||
return str.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the id
|
||||
*/
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param id the id to set
|
||||
*/
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of this Artifact Type.
|
||||
*
|
||||
* @return the name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name of this Artifact Type
|
||||
*
|
||||
* @param name the name to set
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this Artifact Type is supported.
|
||||
*
|
||||
* @return true or false
|
||||
*/
|
||||
public Boolean isSupported() {
|
||||
return supported;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this Artifact Type as supported or not supported.
|
||||
*
|
||||
* @param supported the supported to set
|
||||
*/
|
||||
public void setSupported(Boolean supported) {
|
||||
this.supported = supported;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this Artifact Type is enabled.
|
||||
*
|
||||
* @return true or false
|
||||
*/
|
||||
public Boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this Artifact Type as enabled or not enabled.
|
||||
*
|
||||
* @param enabled the enabled to set
|
||||
*/
|
||||
public void setEnabled(Boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,140 +0,0 @@
|
||||
# Configuration
|
||||
|
||||
## Database Setup
|
||||
|
||||
There are 2 choices for database platforms: SQLite and PostgreSQL.
|
||||
1. SQLite is a database in a file stored locally on the same host that is running Autopsy.
|
||||
There is nothing to do to setup this database. It will be created by Autopsy on your
|
||||
behalf, if it doesn't already exist.
|
||||
2. PostgreSQL is a database server that can be run either on the same host that is
|
||||
running Autopsy or on a remote server. To use PostgreSQL with the EnterpriseArtifactManager module,
|
||||
you will need the server to be running, have an existing database named "enterpriseartifactmanagerdb"
|
||||
and have an existing user/pass with ownership of the enterpriseartifactmanagerdb database.
|
||||
The tables and indices will be automatically created by Autopsy.
|
||||
See the [Autopsy multi-user settings documentation[(http://sleuthkit.org/autopsy/docs/user-docs/4.3/install_postgresql.html) for help setting up your PostgreSQL server.
|
||||
|
||||
## Enable Module and Configure Database Settings
|
||||
|
||||
In the menu go to: Tools -> Options -> EnterpriseArtifactManager
|
||||
|
||||
1. Check the box to Enable Enterprise Artifact Manager. This will enable the Database Platform dropdown and Configure button.
|
||||
2. In the dropdown, select the database platform that you want to use.
|
||||
3. Click the Configure button to configure the settings for the chosen database platform.
|
||||
4. Click the Apply button to save your database configuration settings.
|
||||
|
||||
### Configure SQLite Database Settings
|
||||
|
||||
There is only one step here, to specify the path and filename for the database.
|
||||
You can accept the default value or use the Open button to choose another path.
|
||||
The database file name can be called anything you want, but it is convenient to
|
||||
give it a ".db" suffix.
|
||||
|
||||
Once you have selected the path, click the Test Connection button.
|
||||
If you see a green check next to the button, everything is ready to go.
|
||||
If you see a red check next to the button, there is a problem with the path
|
||||
you selected and you'll have to resolve that problem.
|
||||
|
||||
Once the test passes, click the Save button to save your selection and close the window.
|
||||
|
||||
### Configure PostgreSQL Database Settings
|
||||
|
||||
For PostgreSQL all values are required, but some defaults are provided for convenience.
|
||||
|
||||
1. Host Name/IP is the hostname or IP of your PostgreSQL server.
|
||||
2. Port is the port that the PostgreSQL server is listening on; default is 5432.
|
||||
3. Database name is the name of the database you are using for this module; default is enterpriseartifactmanagerdb.
|
||||
4. User Name is the PostgreSQL user that owns and has full permissions to the database specified in step 3.
|
||||
5. User Password is the password for the user.
|
||||
|
||||
Once all values have been entered, click the Test Connection button.
|
||||
If you see a green check next to the button, everything is ready to go.
|
||||
If you see a red check next to the button, there is a problem with the values
|
||||
you entered and you'll have to resolve that problem.
|
||||
|
||||
Once the test passes, click the Save button to save your selection and close the window.
|
||||
|
||||
## Import Globally Known Artifacts
|
||||
|
||||
The purpose of this feature is to store any Known or Known Bad Artifacts in
|
||||
the database. Think of this feature like a dynamic Hash List.
|
||||
These artifacts are used during Ingest to flag files as Interesting.
|
||||
They are also displayed in the Content Viewer when a file or artifact is selected that is
|
||||
associated with one of the globally known artifacts.
|
||||
|
||||
When importing a hash database, all fields are required.
|
||||
|
||||
1. Select the Database Path using the Open button. This is the file containing
|
||||
the hash values that you want to import. You can import multiple files, but only
|
||||
one at a time. The format of these files must be the same format as used by
|
||||
the hash database module.
|
||||
2. Select the database type. The type of content in the database being imported.
|
||||
3. Define the attribution for this database.
|
||||
a. Select the Source Organization in the dropdown list.
|
||||
This is the organization that provided the hash database to you.
|
||||
b. If you do not see the Organization in the list, use the [Add New Organization](FEATURES.md#adding-a-new-organization) button to add it.
|
||||
Once you add it, you can then select it in the dropdown list.
|
||||
c. Enter a name for the dataset. This can be anything you want, but is often something like "child porn", "drugs", "malware", "corp hashlist", etc.
|
||||
d. Enter a version number for that dataset. This can be anything you want, but is often something like "1.0", "1.1a", 20170505", etc.
|
||||
4. Click the OK button to start the import.
|
||||
|
||||
## Manage Correlatable Tags
|
||||
|
||||
In Autopsy, you are allowed to define your own Tag names, tag files and artifacts,
|
||||
and add comments when you tag a file or artifact.
|
||||
|
||||
The purpose of this feature is to associate one or more of those tags with this module
|
||||
to be used for Correlation.
|
||||
By default there is a tag called "Evidence" as the only tag associated with this module.
|
||||
|
||||
To associate one or more tag(s) with this module, check the Correlate box next to the tag
|
||||
name(s) and click OK.
|
||||
|
||||
### What does it mean for a tag to be associated with this module?
|
||||
|
||||
Any file or artifact that a user tags with one of the associated tags will be
|
||||
added to the database as a file or artifact of interest.
|
||||
Any future data source ingest, where this module is enabled, will use those
|
||||
files or artifacts as if they were part of the Known Bad list, causing matching files
|
||||
from that ingest to be added to the Interesting Artifacts list in that currently open case.
|
||||
|
||||
The term Correlate means that files processed during a future ingest will be correlated
|
||||
with files existing in the database.
|
||||
|
||||
As an example, I have a case open and I tag an image called "evilphoto.png" with the
|
||||
default "Evidence" tag. That image will be stored in the database as a file of interest.
|
||||
In the next data source that I ingest for the same case or a future case,
|
||||
if an image with the same MD5 hash as "evilphoto.png"
|
||||
is found, it will be automatically added to the Interesting Files tree and assumed
|
||||
to be evidence.
|
||||
This makes it easy to find and flag things in future cases that you know are
|
||||
Interesting.
|
||||
|
||||
## Manage Correlation Types
|
||||
|
||||
This feature allows the user to control how much data is being stored in the database
|
||||
to use for correlation and analysis.
|
||||
By default, only FILES is enabled.
|
||||
Select the types that you want to enable and click OK.
|
||||
|
||||
The meaning of each type is as follows:
|
||||
|
||||
* FILES - file path and MD5 hash
|
||||
* DOMAIN - domain name
|
||||
* EMAIL - email address
|
||||
* PHONE - phone number
|
||||
* USBID - device ID of connected USB devices.
|
||||
|
||||
### What does Correlation mean?
|
||||
|
||||
Artifacts stored in the database are available for this module to use for analysis.
|
||||
That analysis comes in many forms.
|
||||
When a file or artifact is extracted during ingest, this module will use the database
|
||||
to find other files or artifacts that match it, to determine if that new file should be
|
||||
flagged as an Interesting File.
|
||||
|
||||
If that file or artifact does not exist in the database, and that Correlation Type
|
||||
is enabled, then it will be added to the database.
|
||||
|
||||
Having more data in the database will obviously allow this module to be more thorough,
|
||||
but for some, database size is a concern, so we allow them to select a subset of data
|
||||
to collect and use for analysis.
|
@ -1,61 +0,0 @@
|
||||
# Instructions for doing development of Autopsy Modules
|
||||
|
||||
## On Windows, Setup your development environment with Autopsy sources and javadocs
|
||||
|
||||
* Install x64 PostgreSQL and setup:
|
||||
* http://sleuthkit.org/autopsy/docs/user-docs/4.3/install_postgresql.html
|
||||
|
||||
* Install Oracle Java SE JDK 8 - Windows x64 from Oracle:
|
||||
* http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
|
||||
|
||||
* Install NetBeans (choose the 'All' version):
|
||||
* https://netbeans.org/downloads/
|
||||
|
||||
* Install Git for Windows x64:
|
||||
* https://git-scm.com/downloads
|
||||
|
||||
* Install doxygen and make sure it is added to your PATH
|
||||
* http://www.stack.nl/~dimitri/doxygen/download.html
|
||||
|
||||
* Sleuthkit and the DataModel java bindings
|
||||
* Clone sleuthkit repo and set TSK_HOME environment variable.
|
||||
* For the java bindings, there are two ways to get these
|
||||
1. [build Sleuthkit and then the java bindings](https://github.com/sleuthkit/sleuthkit/blob/develop/win32/BUILDING.txt), requiring Visual Studio and several
|
||||
dependant libraries.
|
||||
2. download the [Autopsy dev platform zip](https://github.com/sleuthkit/autopsy/releases/download/autopsy-4.4.0/autopsy-4.4.0-devplatform.zip) and copy autopsy-4.4.0-devplatform/autopsy/modules/ext/Tsk_DataModel_PostgreSQL.jar to TSK_HOME/bindings/java/dist/
|
||||
* Set up environment variables, sample values:
|
||||
- JAVA_HOME=C:\Program Files\Java\jdk1.8.0_121
|
||||
- JDK_HOME=C:\Program Files\Java\jdk1.8.0_121
|
||||
- JRE_HOME_64=C:\Program Files\Java\jre1.8.0_121
|
||||
- LIBEWF_HOME=C:\libewf_64bit (only needed if you chose option #1 above)
|
||||
- LIBVHDI_HOME=C:\libvhdi_64bit (only needed if you chose option #1 above)
|
||||
- POSTGRESQL_HOME_64=c:\Program Files\PostgreSQL\9.6 (only needed if you chose option #1 above)
|
||||
- TSK_HOME=c:\sleuthkit
|
||||
- PATH=...;C:\Program Files\Java\jdk1.8.0_121\bin;C:\Program Files\NetBeans 8.2\extide\ant\bin;C:\Program Files\doxygen\bin
|
||||
|
||||
* Build Autopsy platform:
|
||||
* Reference: https://github.com/sleuthkit/autopsy/blob/develop/BUILDING.txt
|
||||
* Clone Autopsy project
|
||||
* git clone git@github.com:sleuthkit/autopsy.git
|
||||
* git checkout develop
|
||||
* Add Autopsy project to NetBeans
|
||||
* File -> Open Project
|
||||
* Build the top level Autopsy project
|
||||
* Generate javadoc and add doc folder in the documentation tab
|
||||
|
||||
If the project builds correctly, everything is installed correctly.
|
||||
|
||||
## How to build disk images for development/testing
|
||||
|
||||
Refer to MS technet instructions for creating/using a VHD: https://technet.microsoft.com/en-us/library/gg318052(v=ws.10).aspx
|
||||
|
||||
But here is the general idea:
|
||||
* On Windows, use Disk Management tool to create a Virtual Hard Disk (.vhd) using the "dynamically expanding" disk format. Choose a small-ish disk size if you want the testing to be quick.
|
||||
* Initialize the disk (Initialize Disk).
|
||||
* Format the disk (New Simple Volume).
|
||||
* Mount that disk (Attach VHD)
|
||||
* Copy some files onto the disk.
|
||||
* Umount that disk (Detach VHD). Do NOT delete the disk when detaching!
|
||||
|
||||
Repeat the above steps to create additional disk images.
|
||||
|
@ -1,116 +0,0 @@
|
||||
# Features
|
||||
|
||||
Once you have configured everything, created a case, and have run the ingest of at least one data source,
|
||||
you can make use of some other exciting features that are described below.
|
||||
|
||||
## Content Viewer
|
||||
|
||||
This module adds a new tab to the [Content Viewer](http://sleuthkit.org/autopsy/docs/user-docs/4.3/content_viewer_page.html).
|
||||
The tab for this module is called "Other Cases".
|
||||
It can display data that is found in other cases, other data sources for the same case, or imported global artifacts.
|
||||
|
||||
If at least one other case or data source has been ingested with this module enabled,
|
||||
there is a potential that data will be displayed in the Other Cases content viewer.
|
||||
If the selected file or artifact is associated by one of the supported Correlation Types,
|
||||
to one or more file(s) or artifact(s) in the database, the associated files/artifacts will be displayed.
|
||||
Note: the Content Viewer will display ALL associated files and artifacts available in the database.
|
||||
It ignores the user's [enabled/disabled Correlation Types](CONFIG.md#manage-correlation-types).
|
||||
|
||||
If the user right-clicks on a row, a menu will be displayed.
|
||||
This menu has several options.
|
||||
1. [Show Commonality Details](FEATURES.md#show-commonality-details)
|
||||
2. [Save to CSV](FEATURES.md#save-to-csv)
|
||||
3. [Show Case Details](FEATURES.md#show-case-details)
|
||||
4. [Select All](FEATURES.md#select-all)
|
||||
|
||||
Click option for more details.
|
||||
|
||||
### Rows in the table
|
||||
|
||||
By default, the rows in the content viewer will have background colors to indicate if they
|
||||
are known to be of interest.
|
||||
Files/artifacts that are Known Bad will have a Red background, Unknown will have Yellow background,
|
||||
and Known will have a White background.
|
||||
|
||||
The user can click on any column heading to sort by the values in that column.
|
||||
|
||||
### Show Commonality Details
|
||||
|
||||
The concept of Commonality simply means, how common is the selected file.
|
||||
The value is the percentage of case/data source tuples that have the selected file or artifact.
|
||||
|
||||
### Save to CSV
|
||||
|
||||
This option will save ALL SELECTED rows in the Content Viewer table to a CSV file.
|
||||
By default, the CSV file is saved into the Export directory inside the currently open Autopsy case,
|
||||
but the user is free to select a different location.
|
||||
|
||||
Note: if you want to copy/paste rows, it is usually possible to use CTRL+C to copy the
|
||||
selected rows and then CTRL+V to paste them into a file, but it will not be CSV formatted.
|
||||
|
||||
### Show Case Details
|
||||
|
||||
This option will open a dialog that displays all of the relevant details for the selected case.
|
||||
The details will include:
|
||||
1. Case UUID
|
||||
2. Case Name
|
||||
3. Case Creation Date
|
||||
4. Case Examiner contact information
|
||||
5. Case Examiner's notes
|
||||
|
||||
These details would have been entered by the examiner of the selected case, by visiting
|
||||
the Case -> Enterprise Artifact Manager Case Details menu, when that case was open.
|
||||
|
||||
### Select All
|
||||
|
||||
This option will select all rows in the Content Viewer table.
|
||||
|
||||
## Interesting Items tree
|
||||
|
||||
In the Results tree of an open case is an entry called Interesting Items.
|
||||
When this module is enabled, all of the enabled Correlatable Types will cause
|
||||
matching files to be added to this Interesting Items tree during ingest.
|
||||
|
||||
As an example, if the FILES Correlatable Type is enabled, and the ingest is
|
||||
currently processing a file, for example "badfile.exe", and the MD5 hash for that
|
||||
file already exists in the database as a KNOWN BAD file, then an entry in the Interesting Items tree
|
||||
will be added for the current instance of "badfile.exe" in the data source currently being ingested.
|
||||
|
||||
The same type of thing will happen for each [enabled Correlatable Type](CONFIG.md#manage-correlation-types).
|
||||
|
||||
In the case of the PHONE correlatable type, the Interesting Items tree will start
|
||||
a sub-tree for each phone number. The sub-tree will then contain each instance of that
|
||||
Known Bad phone number.
|
||||
|
||||
## Edit Enterprise Artifact Manager Case Details
|
||||
|
||||
By default, Autopsy lets you edit Case Details in the Case menu.
|
||||
When this module is enabled, there is an additional option in the Case menu,
|
||||
called "Enterprise Artifact Manager Case Details".
|
||||
|
||||
This is where the examiner can store a number of details about the case.
|
||||
1. The organization of the case examiner.
|
||||
2. The contact information of the case examiner.
|
||||
3. The case examiner's case notes.
|
||||
|
||||
To define the organization of the case examiner, simply select the organization name
|
||||
from the dropdown box.
|
||||
If the organization is not listed, you can click [Add New Organization](FEATURES.md#adding-a-new-organization) button.
|
||||
Once the new organization is added, it should be available in the dropdown box.
|
||||
|
||||
## Adding a New Organization
|
||||
|
||||
An Organization can have two purposes in this module.
|
||||
|
||||
1. It defines the Organization that the forensic examiner belongs to.
|
||||
This organization is selected or added when Editing Correlation Case Details.
|
||||
2. It defines the Organization that is the source of a Globally Known Artifact List.
|
||||
This organization is selected or added during Import of a Globally Known Artifact hash list.
|
||||
|
||||
When adding a new organization, only the Organization Name is required.
|
||||
It is recommended to also include a Point of Contact for that organization.
|
||||
This will be someone that is a manager or team lead at that Organization that
|
||||
could be contacted for any questions about a case or a shared Globally Known Artifact
|
||||
hash list.
|
||||
|
||||
Click OK to save the new Organization.
|
@ -127,7 +127,7 @@
|
||||
<compile-dependency/>
|
||||
<run-dependency>
|
||||
<release-version>10</release-version>
|
||||
<specification-version>10.7</specification-version>
|
||||
<specification-version>10.8</specification-version>
|
||||
</run-dependency>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
@ -18,14 +18,15 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.imagegallery;
|
||||
|
||||
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||
import com.google.common.util.concurrent.MoreExecutors;
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.Observable;
|
||||
@ -86,69 +87,57 @@ import org.sleuthkit.datamodel.TskData;
|
||||
* Connects different parts of ImageGallery together and is hub for flow of
|
||||
* control.
|
||||
*/
|
||||
public final class ImageGalleryController implements Executor {
|
||||
|
||||
private final Executor execDelegate = Executors.newSingleThreadExecutor();
|
||||
private Runnable showTree;
|
||||
private Toolbar toolbar;
|
||||
|
||||
@Override
|
||||
public void execute(Runnable command) {
|
||||
execDelegate.execute(command);
|
||||
}
|
||||
public final class ImageGalleryController {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(ImageGalleryController.class.getName());
|
||||
|
||||
private final Region infoOverLayBackground = new Region() {
|
||||
{
|
||||
setBackground(new Background(new BackgroundFill(Color.GREY, CornerRadii.EMPTY, Insets.EMPTY)));
|
||||
setOpacity(.4);
|
||||
}
|
||||
};
|
||||
|
||||
private static ImageGalleryController instance;
|
||||
|
||||
public static synchronized ImageGalleryController getDefault() {
|
||||
if (instance == null) {
|
||||
instance = new ImageGalleryController();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private final History<GroupViewState> historyManager = new History<>();
|
||||
private final UndoRedoManager undoManager = new UndoRedoManager();
|
||||
|
||||
/**
|
||||
* true if Image Gallery should listen to ingest events, false if it should
|
||||
* not listen to speed up ingest
|
||||
*/
|
||||
private final SimpleBooleanProperty listeningEnabled = new SimpleBooleanProperty(false);
|
||||
|
||||
private final ReadOnlyBooleanWrapper regroupDisabled = new ReadOnlyBooleanWrapper(false);
|
||||
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
|
||||
private final ReadOnlyBooleanWrapper stale = new ReadOnlyBooleanWrapper(false);
|
||||
|
||||
private final ReadOnlyBooleanWrapper metaDataCollapsed = new ReadOnlyBooleanWrapper(false);
|
||||
private final ReadOnlyDoubleWrapper thumbnailSize = new ReadOnlyDoubleWrapper(100);
|
||||
private final ReadOnlyBooleanWrapper regroupDisabled = new ReadOnlyBooleanWrapper(false);
|
||||
private final ReadOnlyIntegerWrapper dbTaskQueueSize = new ReadOnlyIntegerWrapper(0);
|
||||
|
||||
private final FileIDSelectionModel selectionModel = new FileIDSelectionModel(this);
|
||||
|
||||
private DBWorkerThread dbWorkerThread;
|
||||
|
||||
private DrawableDB db;
|
||||
|
||||
private final History<GroupViewState> historyManager = new History<>();
|
||||
private final UndoRedoManager undoManager = new UndoRedoManager();
|
||||
private final GroupManager groupManager = new GroupManager(this);
|
||||
private final HashSetManager hashSetManager = new HashSetManager();
|
||||
private final CategoryManager categoryManager = new CategoryManager(this);
|
||||
private final DrawableTagsManager tagsManager = new DrawableTagsManager(null);
|
||||
|
||||
private Runnable showTree;
|
||||
private Toolbar toolbar;
|
||||
private StackPane fullUIStackPane;
|
||||
|
||||
private StackPane centralStackPane;
|
||||
|
||||
private Node infoOverlay;
|
||||
private final Region infoOverLayBackground = new Region() {
|
||||
{
|
||||
setBackground(new Background(new BackgroundFill(Color.GREY, CornerRadii.EMPTY, Insets.EMPTY)));
|
||||
setOpacity(.4);
|
||||
}
|
||||
};
|
||||
|
||||
private ListeningExecutorService dbExecutor;
|
||||
|
||||
private SleuthkitCase sleuthKitCase;
|
||||
private DrawableDB db;
|
||||
|
||||
public static synchronized ImageGalleryController getDefault() {
|
||||
if (instance == null) {
|
||||
instance = new ImageGalleryController();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
public ReadOnlyBooleanProperty getMetaDataCollapsed() {
|
||||
return metaDataCollapsed.getReadOnlyProperty();
|
||||
@ -223,7 +212,7 @@ public final class ImageGalleryController implements Executor {
|
||||
//if we just turned on listening and a case is open and that case is not up to date
|
||||
if (newValue && !oldValue && Case.isCaseOpen() && ImageGalleryModule.isDrawableDBStale(Case.getCurrentCase())) {
|
||||
//populate the db
|
||||
queueDBWorkerTask(new CopyAnalyzedFiles(instance, db, sleuthKitCase));
|
||||
queueDBTask(new CopyAnalyzedFiles(instance, db, sleuthKitCase));
|
||||
}
|
||||
});
|
||||
|
||||
@ -258,7 +247,7 @@ public final class ImageGalleryController implements Executor {
|
||||
ingestManager.addIngestModuleEventListener(ingestEventHandler);
|
||||
ingestManager.addIngestJobEventListener(ingestEventHandler);
|
||||
|
||||
queueSizeProperty.addListener(obs -> this.updateRegroupDisabled());
|
||||
dbTaskQueueSize.addListener(obs -> this.updateRegroupDisabled());
|
||||
}
|
||||
|
||||
public ReadOnlyBooleanProperty getCanAdvance() {
|
||||
@ -287,7 +276,7 @@ public final class ImageGalleryController implements Executor {
|
||||
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
|
||||
private void updateRegroupDisabled() {
|
||||
regroupDisabled.set((queueSizeProperty.get() > 0) || IngestManager.getInstance().isIngestRunning());
|
||||
regroupDisabled.set((dbTaskQueueSize.get() > 0) || IngestManager.getInstance().isIngestRunning());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -309,7 +298,7 @@ public final class ImageGalleryController implements Executor {
|
||||
synchronized private void checkForGroups() {
|
||||
if (groupManager.getAnalyzedGroups().isEmpty()) {
|
||||
if (IngestManager.getInstance().isIngestRunning()) {
|
||||
if (listeningEnabled.get() == false) {
|
||||
if (listeningEnabled.not().get()) {
|
||||
replaceNotification(fullUIStackPane,
|
||||
new NoGroupsDialog(Bundle.ImageGalleryController_noGroupsDlg_msg1()));
|
||||
} else {
|
||||
@ -318,12 +307,12 @@ public final class ImageGalleryController implements Executor {
|
||||
new ProgressIndicator()));
|
||||
}
|
||||
|
||||
} else if (queueSizeProperty.get() > 0) {
|
||||
} else if (dbTaskQueueSize.get() > 0) {
|
||||
replaceNotification(fullUIStackPane,
|
||||
new NoGroupsDialog(Bundle.ImageGalleryController_noGroupsDlg_msg3(),
|
||||
new ProgressIndicator()));
|
||||
} else if (db != null && db.countAllFiles() <= 0) { // there are no files in db
|
||||
if (listeningEnabled.get() == false) {
|
||||
if (listeningEnabled.not().get()) {
|
||||
replaceNotification(fullUIStackPane,
|
||||
new NoGroupsDialog(Bundle.ImageGalleryController_noGroupsDlg_msg4()));
|
||||
} else {
|
||||
@ -363,23 +352,15 @@ public final class ImageGalleryController implements Executor {
|
||||
}
|
||||
}
|
||||
|
||||
synchronized private DBWorkerThread restartWorker() {
|
||||
if (dbWorkerThread == null) {
|
||||
dbWorkerThread = new DBWorkerThread(this);
|
||||
dbWorkerThread.start();
|
||||
} else {
|
||||
// Keep using the same worker thread if one exists
|
||||
}
|
||||
return dbWorkerThread;
|
||||
}
|
||||
|
||||
/**
|
||||
* configure the controller for a specific case.
|
||||
*
|
||||
* @param theNewCase the case to configure the controller for
|
||||
*/
|
||||
public synchronized void setCase(Case theNewCase) {
|
||||
if (Objects.nonNull(theNewCase)) {
|
||||
if (null == theNewCase) {
|
||||
reset();
|
||||
} else {
|
||||
this.sleuthKitCase = theNewCase.getSleuthkitCase();
|
||||
this.db = DrawableDB.getDrawableDB(ImageGalleryModule.getModuleOutputDir(theNewCase), this);
|
||||
|
||||
@ -388,7 +369,6 @@ public final class ImageGalleryController implements Executor {
|
||||
|
||||
// if we add this line icons are made as files are analyzed rather than on demand.
|
||||
// db.addUpdatedFileListener(IconCache.getDefault());
|
||||
restartWorker();
|
||||
historyManager.clear();
|
||||
groupManager.setDB(db);
|
||||
hashSetManager.setDb(db);
|
||||
@ -396,9 +376,8 @@ public final class ImageGalleryController implements Executor {
|
||||
tagsManager.setAutopsyTagsManager(theNewCase.getServices().getTagsManager());
|
||||
tagsManager.registerListener(groupManager);
|
||||
tagsManager.registerListener(categoryManager);
|
||||
|
||||
} else {
|
||||
reset();
|
||||
shutDownDBExecutor();
|
||||
dbExecutor = getNewDBExecutor();
|
||||
}
|
||||
}
|
||||
|
||||
@ -415,9 +394,7 @@ public final class ImageGalleryController implements Executor {
|
||||
tagsManager.clearFollowUpTagName();
|
||||
tagsManager.unregisterListener(groupManager);
|
||||
tagsManager.unregisterListener(categoryManager);
|
||||
dbWorkerThread.cancel();
|
||||
dbWorkerThread = null;
|
||||
dbWorkerThread = restartWorker();
|
||||
shutDownDBExecutor();
|
||||
|
||||
if (toolbar != null) {
|
||||
toolbar.reset();
|
||||
@ -429,16 +406,42 @@ public final class ImageGalleryController implements Executor {
|
||||
db = null;
|
||||
}
|
||||
|
||||
synchronized private void shutDownDBExecutor() {
|
||||
if (dbExecutor != null) {
|
||||
dbExecutor.shutdownNow();
|
||||
try {
|
||||
dbExecutor.awaitTermination(30, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException ex) {
|
||||
LOGGER.log(Level.WARNING, "Image Gallery failed to shutdown DB Task Executor in a timely fashion.", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static ListeningExecutorService getNewDBExecutor() {
|
||||
return MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor(
|
||||
new ThreadFactoryBuilder().setNameFormat("DB-Worker-Thread-%d").build()));
|
||||
}
|
||||
|
||||
/**
|
||||
* add InnerTask to the queue that the worker thread gets its work from
|
||||
*
|
||||
* @param innerTask
|
||||
* @param bgTask
|
||||
*/
|
||||
public synchronized void queueDBWorkerTask(BackgroundTask innerTask) {
|
||||
if (dbWorkerThread == null) {
|
||||
dbWorkerThread = restartWorker();
|
||||
public synchronized void queueDBTask(BackgroundTask bgTask) {
|
||||
if (dbExecutor == null || dbExecutor.isShutdown()) {
|
||||
dbExecutor = getNewDBExecutor();
|
||||
}
|
||||
dbWorkerThread.addTask(innerTask);
|
||||
incrementQueueSize();
|
||||
dbExecutor.submit(bgTask).addListener(this::decrementQueueSize, MoreExecutors.directExecutor());
|
||||
|
||||
}
|
||||
|
||||
private void incrementQueueSize() {
|
||||
Platform.runLater(() -> dbTaskQueueSize.set(dbTaskQueueSize.get() + 1));
|
||||
}
|
||||
|
||||
private void decrementQueueSize() {
|
||||
Platform.runLater(() -> dbTaskQueueSize.set(dbTaskQueueSize.get() - 1));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@ -502,77 +505,7 @@ public final class ImageGalleryController implements Executor {
|
||||
}
|
||||
|
||||
public ReadOnlyIntegerProperty getDBTasksQueueSizeProperty() {
|
||||
return queueSizeProperty.getReadOnlyProperty();
|
||||
}
|
||||
private final ReadOnlyIntegerWrapper queueSizeProperty = new ReadOnlyIntegerWrapper(0);
|
||||
|
||||
// @@@ review this class for synchronization issues (i.e. reset and cancel being called, add, etc.)
|
||||
static private class DBWorkerThread extends Thread implements Cancellable {
|
||||
|
||||
private final ImageGalleryController controller;
|
||||
|
||||
DBWorkerThread(ImageGalleryController controller) {
|
||||
super("DB-Worker-Thread");
|
||||
setDaemon(false);
|
||||
this.controller = controller;
|
||||
}
|
||||
|
||||
// true if the process was requested to stop. Currently no way to reset it
|
||||
private volatile boolean cancelled = false;
|
||||
|
||||
// list of tasks to run
|
||||
private final BlockingQueue<BackgroundTask> workQueue = new LinkedBlockingQueue<>();
|
||||
|
||||
/**
|
||||
* Cancel all of the queued up tasks and the currently scheduled task.
|
||||
* Note that after you cancel, you cannot submit new jobs to this
|
||||
* thread.
|
||||
*/
|
||||
@Override
|
||||
public boolean cancel() {
|
||||
cancelled = true;
|
||||
for (BackgroundTask it : workQueue) {
|
||||
it.cancel();
|
||||
}
|
||||
workQueue.clear();
|
||||
int size = workQueue.size();
|
||||
Platform.runLater(() -> controller.queueSizeProperty.set(size));
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a task for the worker thread to perform
|
||||
*
|
||||
* @param it
|
||||
*/
|
||||
public void addTask(BackgroundTask it) {
|
||||
workQueue.add(it);
|
||||
int size = workQueue.size();
|
||||
Platform.runLater(() -> controller.queueSizeProperty.set(size));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
// nearly infinite loop waiting for tasks
|
||||
while (true) {
|
||||
if (cancelled || isInterrupted()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
BackgroundTask it = workQueue.take();
|
||||
|
||||
if (it.isCancelled() == false) {
|
||||
it.run();
|
||||
}
|
||||
int size = workQueue.size();
|
||||
Platform.runLater(() -> controller.queueSizeProperty.set(size));
|
||||
|
||||
} catch (InterruptedException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Failed to run DB worker thread", ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
}
|
||||
return dbTaskQueueSize.getReadOnlyProperty();
|
||||
}
|
||||
|
||||
public synchronized SleuthkitCase getSleuthKitCase() {
|
||||
@ -643,7 +576,7 @@ public final class ImageGalleryController implements Executor {
|
||||
/**
|
||||
* Abstract base class for tasks associated with a file in the database
|
||||
*/
|
||||
static public abstract class FileTask extends BackgroundTask {
|
||||
static abstract class FileTask extends BackgroundTask {
|
||||
|
||||
private final AbstractFile file;
|
||||
private final DrawableDB taskDB;
|
||||
@ -713,7 +646,6 @@ public final class ImageGalleryController implements Executor {
|
||||
Logger.getLogger(RemoveFileTask.class.getName()).log(Level.SEVERE, "Case was closed out from underneath RemoveFile task"); //NON-NLS
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -775,7 +707,7 @@ public final class ImageGalleryController implements Executor {
|
||||
DrawableDB.DrawableTransaction tr = taskDB.beginTransaction();
|
||||
int workDone = 0;
|
||||
for (final AbstractFile f : files) {
|
||||
if (isCancelled()) {
|
||||
if (isCancelled() || Thread.interrupted()) {
|
||||
LOGGER.log(Level.WARNING, "Task cancelled: not all contents may be transfered to drawable database."); //NON-NLS
|
||||
progressHandle.finish();
|
||||
break;
|
||||
@ -954,11 +886,11 @@ public final class ImageGalleryController implements Executor {
|
||||
synchronized (ImageGalleryController.this) {
|
||||
if (ImageGalleryModule.isDrawableAndNotKnown(file)) {
|
||||
//this file should be included and we don't already know about it from hash sets (NSRL)
|
||||
queueDBWorkerTask(new UpdateFileTask(file, db));
|
||||
queueDBTask(new UpdateFileTask(file, db));
|
||||
} else if (FileTypeUtils.getAllSupportedExtensions().contains(file.getNameExtension())) {
|
||||
//doing this check results in fewer tasks queued up, and faster completion of db update
|
||||
//this file would have gotten scooped up in initial grab, but actually we don't need it
|
||||
queueDBWorkerTask(new RemoveFileTask(file, db));
|
||||
queueDBTask(new RemoveFileTask(file, db));
|
||||
}
|
||||
}
|
||||
} catch (TskCoreException | FileTypeDetector.FileTypeDetectorInitException ex) {
|
||||
@ -992,19 +924,19 @@ public final class ImageGalleryController implements Executor {
|
||||
switch (Case.Events.valueOf(evt.getPropertyName())) {
|
||||
case CURRENT_CASE:
|
||||
Case newCase = (Case) evt.getNewValue();
|
||||
if (newCase != null) { // case has been opened
|
||||
setCase(newCase); //connect db, groupmanager, start worker thread
|
||||
} else { // case is closing
|
||||
if (newCase == null) { // case is closing
|
||||
//close window, reset everything
|
||||
SwingUtilities.invokeLater(ImageGalleryTopComponent::closeTopComponent);
|
||||
reset();
|
||||
} else { // a new case has been opened
|
||||
setCase(newCase); //connect db, groupmanager, start worker thread
|
||||
}
|
||||
break;
|
||||
case DATA_SOURCE_ADDED:
|
||||
//copy all file data to drawable databse
|
||||
Content newDataSource = (Content) evt.getNewValue();
|
||||
if (isListeningEnabled()) {
|
||||
queueDBWorkerTask(new PrePopulateDataSourceFiles(newDataSource, ImageGalleryController.this, getDatabase(), getSleuthKitCase()));
|
||||
queueDBTask(new PrePopulateDataSourceFiles(newDataSource, ImageGalleryController.this, getDatabase(), getSleuthKitCase()));
|
||||
} else {//TODO: keep track of what we missed for later
|
||||
setStale(true);
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ public class CategorizeAction extends Action {
|
||||
|
||||
final void addCatToFiles(Set<Long> ids) {
|
||||
Logger.getAnonymousLogger().log(Level.INFO, "categorizing{0} as {1}", new Object[]{ids.toString(), cat.getDisplayName()}); //NON-NLS
|
||||
controller.queueDBWorkerTask(new CategorizeTask(ids, cat, createUndo));
|
||||
controller.queueDBTask(new CategorizeTask(ids, cat, createUndo));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013-15 Basis Technology Corp.
|
||||
* Copyright 2011-17 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -21,22 +21,23 @@ package org.sleuthkit.autopsy.imagegallery.actions;
|
||||
import java.util.Optional;
|
||||
import javafx.beans.Observable;
|
||||
import javafx.beans.binding.ObjectExpression;
|
||||
import javafx.concurrent.Task;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.image.ImageView;
|
||||
import org.controlsfx.control.action.Action;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
|
||||
import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.DrawableGroup;
|
||||
import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.GroupManager;
|
||||
import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.GroupViewState;
|
||||
|
||||
/**
|
||||
* Marks the currently fisplayed group as "seen" and advances to the next unseen
|
||||
* Marks the currently displayed group as "seen" and advances to the next unseen
|
||||
* group
|
||||
*/
|
||||
@NbBundle.Messages({"NextUnseenGroup.markGroupSeen=Mark Group Seen",
|
||||
"NextUnseenGroup.nextUnseenGroup=Next Unseen group"})
|
||||
"NextUnseenGroup.nextUnseenGroup=Next Unseen group"})
|
||||
public class NextUnseenGroup extends Action {
|
||||
|
||||
private static final Image END =
|
||||
@ -47,54 +48,41 @@ public class NextUnseenGroup extends Action {
|
||||
private static final String MARK_GROUP_SEEN = Bundle.NextUnseenGroup_markGroupSeen();
|
||||
private static final String NEXT_UNSEEN_GROUP = Bundle.NextUnseenGroup_nextUnseenGroup();
|
||||
|
||||
private final ImageGalleryController controller;
|
||||
private final GroupManager groupManager;
|
||||
private final ObservableList<DrawableGroup> unSeenGroups;
|
||||
private final ObservableList<DrawableGroup> analyzedGroups;
|
||||
|
||||
public NextUnseenGroup(ImageGalleryController controller) {
|
||||
super(NEXT_UNSEEN_GROUP);
|
||||
this.controller = controller;
|
||||
groupManager = controller.getGroupManager();
|
||||
unSeenGroups = groupManager.getUnSeenGroups();
|
||||
analyzedGroups = groupManager.getAnalyzedGroups();
|
||||
setGraphic(new ImageView(ADVANCE));
|
||||
|
||||
//TODO: do we need both these listeners?
|
||||
controller.getGroupManager().getAnalyzedGroups().addListener((Observable observable) -> {
|
||||
updateButton();
|
||||
analyzedGroups.addListener((Observable o) -> this.updateButton());
|
||||
unSeenGroups.addListener((Observable o) -> this.updateButton());
|
||||
|
||||
});
|
||||
controller.getGroupManager().getUnSeenGroups().addListener((Observable observable) -> {
|
||||
updateButton();
|
||||
});
|
||||
|
||||
setEventHandler((ActionEvent t) -> {
|
||||
setEventHandler(event -> {
|
||||
//fx-thread
|
||||
//if there is a group assigned to the view, mark it as seen
|
||||
Optional.ofNullable(controller.viewState())
|
||||
.map(ObjectExpression<GroupViewState>::getValue)
|
||||
.map(GroupViewState::getGroup)
|
||||
.ifPresent(group -> controller.getGroupManager().markGroupSeen(group, true));
|
||||
controller.execute(new Task<Void>() {
|
||||
.ifPresent(group -> groupManager.markGroupSeen(group, true));
|
||||
|
||||
@Override
|
||||
protected Void call() throws Exception {
|
||||
if (false == controller.getGroupManager().getUnSeenGroups().isEmpty()) {
|
||||
controller.advance(GroupViewState.tile(controller.getGroupManager().getUnSeenGroups().get(0)), true);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void succeeded() {
|
||||
super.succeeded();
|
||||
updateButton();
|
||||
}
|
||||
});
|
||||
if (unSeenGroups.isEmpty() == false) {
|
||||
controller.advance(GroupViewState.tile(unSeenGroups.get(0)), true);
|
||||
updateButton();
|
||||
}
|
||||
});
|
||||
|
||||
updateButton();
|
||||
}
|
||||
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
|
||||
private void updateButton() {
|
||||
setDisabled(controller.getGroupManager().getUnSeenGroups().isEmpty());
|
||||
if (controller.getGroupManager().getUnSeenGroups().size() <= 1) {
|
||||
setDisabled(unSeenGroups.isEmpty());
|
||||
if (unSeenGroups.size() <= 1) {
|
||||
setText(MARK_GROUP_SEEN);
|
||||
setGraphic(new ImageView(END));
|
||||
} else {
|
||||
|
@ -119,7 +119,7 @@
|
||||
<compile-dependency/>
|
||||
<run-dependency>
|
||||
<release-version>10</release-version>
|
||||
<specification-version>10.7</specification-version>
|
||||
<specification-version>10.8</specification-version>
|
||||
</run-dependency>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
@ -236,10 +236,10 @@ KeywordSearchGlobalLanguageSettingsPanel.ingestSettingsLabel.text=Ingest setting
|
||||
KeywordSearchGlobalLanguageSettingsPanel.enableUTF16Checkbox.text=Enable UTF16LE and UTF16BE string extraction
|
||||
KeywordSearchGlobalLanguageSettingsPanel.languagesLabel.text=Enabled scripts (languages):
|
||||
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton1.toolTipText=20 mins. (fastest ingest time)
|
||||
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton1.text=20 minutes
|
||||
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton1.text=20 minutes (slowest feedback, fastest ingest)
|
||||
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton2.toolTipText=10 minutes (faster overall ingest time than default)
|
||||
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton2.text=10 minutes
|
||||
KeywordSearchGlobalSearchSettingsPanel.frequencyLabel.text=Results update frequency during ingest (we have not seen significant performance differences between 5, 10, or 20 minute intervals):
|
||||
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton2.text=10 minutes (slower feedback, faster ingest)
|
||||
KeywordSearchGlobalSearchSettingsPanel.frequencyLabel.text=Results update frequency during ingest:
|
||||
KeywordSearchGlobalSearchSettingsPanel.skipNSRLCheckBox.toolTipText=Requires Hash DB service to had run previously, or be selected for next ingest.
|
||||
KeywordSearchGlobalSearchSettingsPanel.skipNSRLCheckBox.text=Do not add files in NSRL (known files) to keyword index during ingest
|
||||
KeywordSearchGlobalSearchSettingsPanel.informationLabel.text=Information
|
||||
@ -249,7 +249,7 @@ KeywordSearchGlobalSearchSettingsPanel.filesIndexedLabel.text=Files in keyword i
|
||||
KeywordSearchGlobalSearchSettingsPanel.showSnippetsCB.text=Show Keyword Preview in Keyword Search Results (will result in longer search times)
|
||||
KeywordSearchGlobalSearchSettingsPanel.chunksValLabel.text=0
|
||||
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton4.toolTipText=1 minute (overall ingest time will be longest)
|
||||
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton4.text_1=1 minute
|
||||
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton4.text_1=1 minute (faster feedback, longest ingest)
|
||||
KeywordSearchGlobalSearchSettingsPanel.chunksLabel.text=Chunks in keyword index:
|
||||
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton3.toolTipText=5 minutes (overall ingest time will be longer)
|
||||
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton3.text=5 minutes (default)
|
||||
|
@ -161,10 +161,10 @@ public final class KeywordSearchIngestModule implements FileIngestModule {
|
||||
try {
|
||||
Index indexInfo = server.getIndexInfo();
|
||||
if (!IndexFinder.getCurrentSolrVersion().equals(indexInfo.getSolrVersion())) {
|
||||
throw new IngestModuleException(Bundle.KeywordSearchIngestModule_startupException_indexSolrVersionNotSupported(indexInfo.getSolrVersion()));
|
||||
throw new IngestModuleException(Bundle.KeywordSearchIngestModule_startupException_indexSolrVersionNotSupported(indexInfo.getSolrVersion()));
|
||||
}
|
||||
if (!IndexFinder.getCurrentSchemaVersion().equals(indexInfo.getSchemaVersion())) {
|
||||
throw new IngestModuleException(Bundle.KeywordSearchIngestModule_startupException_indexSchemaNotSupported(indexInfo.getSchemaVersion()));
|
||||
throw new IngestModuleException(Bundle.KeywordSearchIngestModule_startupException_indexSchemaNotSupported(indexInfo.getSchemaVersion()));
|
||||
}
|
||||
} catch (NoOpenCoreException ex) {
|
||||
throw new IngestModuleException(Bundle.KeywordSearchIngestModule_startupMessage_failedToGetIndexSchema(), ex);
|
||||
@ -249,7 +249,7 @@ public final class KeywordSearchIngestModule implements FileIngestModule {
|
||||
public ProcessResult process(AbstractFile abstractFile) {
|
||||
if (initialized == false) //error initializing indexing/Solr
|
||||
{
|
||||
logger.log(Level.WARNING, "Skipping processing, module not initialized, file: {0}", abstractFile.getName()); //NON-NLS
|
||||
logger.log(Level.SEVERE, "Skipping processing, module not initialized, file: {0}", abstractFile.getName()); //NON-NLS
|
||||
putIngestStatus(jobId, abstractFile.getId(), IngestStatus.SKIPPED_ERROR_INDEXING);
|
||||
return ProcessResult.OK;
|
||||
}
|
||||
@ -293,14 +293,16 @@ public final class KeywordSearchIngestModule implements FileIngestModule {
|
||||
*/
|
||||
@Override
|
||||
public void shutDown() {
|
||||
logger.log(Level.INFO, "Instance {0}", instanceNum); //NON-NLS
|
||||
logger.log(Level.INFO, "Keyword search ingest module instance {0} shutting down", instanceNum); //NON-NLS
|
||||
|
||||
if ((initialized == false) || (context == null)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (context.fileIngestIsCancelled()) {
|
||||
stop();
|
||||
logger.log(Level.INFO, "Keyword search ingest module instance {0} stopping search job due to ingest cancellation", instanceNum); //NON-NLS
|
||||
SearchRunner.getInstance().stopJob(jobId);
|
||||
cleanup();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -309,34 +311,20 @@ public final class KeywordSearchIngestModule implements FileIngestModule {
|
||||
|
||||
// We only need to post the summary msg from the last module per job
|
||||
if (refCounter.decrementAndGet(jobId) == 0) {
|
||||
try {
|
||||
final int numIndexedFiles = KeywordSearch.getServer().queryNumIndexedFiles();
|
||||
logger.log(Level.INFO, "Indexed files count: {0}", numIndexedFiles); //NON-NLS
|
||||
final int numIndexedChunks = KeywordSearch.getServer().queryNumIndexedChunks();
|
||||
logger.log(Level.INFO, "Indexed file chunks count: {0}", numIndexedChunks); //NON-NLS
|
||||
} catch (NoOpenCoreException | KeywordSearchModuleException ex) {
|
||||
logger.log(Level.SEVERE, "Error executing Solr queries to check number of indexed files and file chunks", ex); //NON-NLS
|
||||
}
|
||||
postIndexSummary();
|
||||
synchronized (ingestStatus) {
|
||||
ingestStatus.remove(jobId);
|
||||
}
|
||||
}
|
||||
|
||||
//log number of files / chunks in index
|
||||
//signal a potential change in number of text_ingested files
|
||||
try {
|
||||
final int numIndexedFiles = KeywordSearch.getServer().queryNumIndexedFiles();
|
||||
final int numIndexedChunks = KeywordSearch.getServer().queryNumIndexedChunks();
|
||||
logger.log(Level.INFO, "Indexed files count: {0}", numIndexedFiles); //NON-NLS
|
||||
logger.log(Level.INFO, "Indexed file chunks count: {0}", numIndexedChunks); //NON-NLS
|
||||
} catch (NoOpenCoreException | KeywordSearchModuleException ex) {
|
||||
logger.log(Level.WARNING, "Error executing Solr query to check number of indexed files/chunks: ", ex); //NON-NLS
|
||||
}
|
||||
|
||||
cleanup();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle stop event (ingest interrupted) Cleanup resources, threads, timers
|
||||
*/
|
||||
private void stop() {
|
||||
logger.log(Level.INFO, "stop()"); //NON-NLS
|
||||
|
||||
SearchRunner.getInstance().stopJob(jobId);
|
||||
|
||||
cleanup();
|
||||
}
|
||||
|
||||
|
@ -131,6 +131,7 @@ public final class SearchRunner {
|
||||
}
|
||||
|
||||
if (readyForFinalSearch) {
|
||||
logger.log(Level.INFO, "Commiting search index before final search for search job {0}", job.getJobId()); //NON-NLS
|
||||
commit();
|
||||
doFinalSearch(job); //this will block until it's done
|
||||
}
|
||||
@ -189,7 +190,7 @@ public final class SearchRunner {
|
||||
final int numIndexedFiles = KeywordSearch.getServer().queryNumIndexedFiles();
|
||||
KeywordSearch.fireNumIndexedFilesChange(null, numIndexedFiles);
|
||||
} catch (NoOpenCoreException | KeywordSearchModuleException ex) {
|
||||
logger.log(Level.WARNING, "Error executing Solr query to check number of indexed files: ", ex); //NON-NLS
|
||||
logger.log(Level.SEVERE, "Error executing Solr query to check number of indexed files", ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
|
||||
@ -201,21 +202,25 @@ public final class SearchRunner {
|
||||
*/
|
||||
private void doFinalSearch(SearchJobInfo job) {
|
||||
// Run one last search as there are probably some new files committed
|
||||
logger.log(Level.INFO, "Running final search for jobid {0}", job.getJobId()); //NON-NLS
|
||||
logger.log(Level.INFO, "Starting final search for search job {0}", job.getJobId()); //NON-NLS
|
||||
if (!job.getKeywordListNames().isEmpty()) {
|
||||
try {
|
||||
// In case this job still has a worker running, wait for it to finish
|
||||
logger.log(Level.INFO, "Checking for previous search for search job {0} before executing final search", job.getJobId()); //NON-NLS
|
||||
job.waitForCurrentWorker();
|
||||
|
||||
SearchRunner.Searcher finalSearcher = new SearchRunner.Searcher(job, true);
|
||||
job.setCurrentSearcher(finalSearcher); //save the ref
|
||||
logger.log(Level.INFO, "Kicking off final search for search job {0}", job.getJobId()); //NON-NLS
|
||||
finalSearcher.execute(); //start thread
|
||||
|
||||
// block until the search is complete
|
||||
logger.log(Level.INFO, "Waiting for final search for search job {0}", job.getJobId()); //NON-NLS
|
||||
finalSearcher.get();
|
||||
logger.log(Level.INFO, "Final search for search job {0} completed", job.getJobId()); //NON-NLS
|
||||
|
||||
} catch (InterruptedException | CancellationException ex) {
|
||||
logger.log(Level.INFO, "Final search for search job {1} interrupted or cancelled", job.getJobId()); //NON-NLS
|
||||
logger.log(Level.INFO, "Final search for search job {0} interrupted or cancelled", job.getJobId()); //NON-NLS
|
||||
} catch (ExecutionException ex) {
|
||||
logger.log(Level.SEVERE, String.format("Final search for search job %d failed", job.getJobId()), ex); //NON-NLS
|
||||
}
|
||||
@ -246,6 +251,7 @@ public final class SearchRunner {
|
||||
SearchJobInfo job = j.getValue();
|
||||
// If no lists or the worker is already running then skip it
|
||||
if (!job.getKeywordListNames().isEmpty() && !job.isWorkerRunning()) {
|
||||
logger.log(Level.INFO, "Executing periodic search for search job {0}", job.getJobId());
|
||||
Searcher searcher = new Searcher(job);
|
||||
job.setCurrentSearcher(searcher); //save the ref
|
||||
searcher.execute(); //start thread
|
||||
@ -341,7 +347,9 @@ public final class SearchRunner {
|
||||
private void waitForCurrentWorker() throws InterruptedException {
|
||||
synchronized (finalSearchLock) {
|
||||
while (workerRunning) {
|
||||
logger.log(Level.INFO, "Waiting for previous worker to finish"); //NON-NLS
|
||||
finalSearchLock.wait(); //wait() releases the lock
|
||||
logger.log(Level.INFO, "Notified previous worker finished"); //NON-NLS
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -351,6 +359,7 @@ public final class SearchRunner {
|
||||
*/
|
||||
private void searchNotify() {
|
||||
synchronized (finalSearchLock) {
|
||||
logger.log(Level.INFO, "Notifying after finishing search"); //NON-NLS
|
||||
workerRunning = false;
|
||||
finalSearchLock.notify();
|
||||
}
|
||||
@ -505,8 +514,7 @@ public final class SearchRunner {
|
||||
try {
|
||||
finalizeSearcher();
|
||||
stopWatch.stop();
|
||||
|
||||
logger.log(Level.INFO, "Searcher took to run: {0} secs.", stopWatch.getElapsedTimeSecs()); //NON-NLS
|
||||
logger.log(Level.INFO, "Searcher took {0} secs to run (final = {1})", new Object[]{stopWatch.getElapsedTimeSecs(), this.finalRun}); //NON-NLS
|
||||
} finally {
|
||||
// In case a thread is waiting on this worker to be done
|
||||
job.searchNotify();
|
||||
@ -520,7 +528,9 @@ public final class SearchRunner {
|
||||
protected void done() {
|
||||
// call get to see if there were any errors
|
||||
try {
|
||||
logger.log(Level.INFO, "Searcher calling get() on itself in done()"); //NON-NLS
|
||||
get();
|
||||
logger.log(Level.INFO, "Searcher finished calling get() on itself in done()"); //NON-NLS
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
logger.log(Level.SEVERE, "Error performing keyword search: " + e.getMessage()); //NON-NLS
|
||||
services.postMessage(IngestMessage.createErrorMessage(KeywordSearchModuleFactory.getModuleName(),
|
||||
@ -566,17 +576,18 @@ public final class SearchRunner {
|
||||
}
|
||||
|
||||
/**
|
||||
* This method filters out all of the hits found in earlier
|
||||
* periodic searches and returns only the results found by the most
|
||||
* recent search.
|
||||
* This method filters out all of the hits found in earlier periodic
|
||||
* searches and returns only the results found by the most recent
|
||||
* search.
|
||||
*
|
||||
* This method will only return hits for objects for which we haven't
|
||||
* previously seen a hit for the keyword.
|
||||
*
|
||||
*
|
||||
* @param queryResult The results returned by a keyword search.
|
||||
* @return A unique set of hits found by the most recent search for objects
|
||||
* that have not previously had a hit. The hits will be for the lowest
|
||||
* numbered chunk associated with the object.
|
||||
*
|
||||
* @return A unique set of hits found by the most recent search for
|
||||
* objects that have not previously had a hit. The hits will be
|
||||
* for the lowest numbered chunk associated with the object.
|
||||
*
|
||||
*/
|
||||
private QueryResults filterResults(QueryResults queryResult) {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user