Merge branch 'develop' of github.com:sleuthkit/autopsy into 6461_nb_upgrade

This commit is contained in:
esaunders 2020-08-25 15:09:20 -04:00
commit b4a7bc6dc3
221 changed files with 16916 additions and 3105 deletions

1
.gitignore vendored
View File

@ -81,6 +81,7 @@ hs_err_pid*.log
/thunderbirdparser/release/
/RecentActivity/release/
/CentralRepository/release/
/Tika/release
.idea/
*.iml

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="BootstrapIvy" default="all" basedir="." xmlns:ivy="antlib:org.apache.ivy.ant">
<property name="ivy.install.version" value="2.3.0-rc2" />
<property name="ivy.install.version" value="2.5.0" />
<condition property="ivy.home" value="${env.IVY_HOME}">
<isset property="env.IVY_HOME" />
</condition>
@ -9,18 +9,13 @@
<property name="ivy.jar.file" value="${ivy.jar.dir}/ivy.jar" />
<target name="download-ivy" unless="offline">
<available file="${ivy.jar.file}" property="ivy.available"/>
<antcall target="-download-ivy" />
</target>
<target name="-download-ivy" unless="ivy.available">
<mkdir dir="${ivy.jar.dir}"/>
<get src="https://repo1.maven.org/maven2/org/apache/ivy/ivy/${ivy.install.version}/ivy-${ivy.install.version}.jar"
dest="${ivy.jar.file}" usetimestamp="true"/>
</target>
<!-- init-ivy will bootstrap Ivy if the user doesn't have it already -->
<target name="init-ivy" depends="download-ivy" unless="ivy.lib.path">
<target name="init-ivy" depends="download-ivy">
<path id="ivy.lib.path">
<fileset dir="${ivy.jar.dir}" includes="*.jar"/>
</path>

View File

@ -63,6 +63,11 @@
<copy todir="${basedir}/release/OfficialHashSets" >
<fileset dir="${thirdparty.dir}/OfficialHashSets"/>
</copy>
<!--Copy ImageMagick to release-->
<copy todir="${basedir}/release/ImageMagick-7.0.10-27-portable-Q16-x64" >
<fileset dir="${thirdparty.dir}/ImageMagick-7.0.10-27-portable-Q16-x64"/>
</copy>
<!-- The 'libgstlibav.dll' file is too big to store on GitHub, so we
have it stored in a ZIP file. We'll extract it in place and remove

View File

@ -1,5 +1,5 @@
<ivy-module version="2.0">
<info organisation="org.sleuthkit.autopsy" module="emailparser"/>
<info organisation="org.sleuthkit.autopsy" module="core"/>
<configurations >
<!-- module dependencies -->
<conf name="core"/>
@ -14,16 +14,6 @@
<dependency conf="core->default" org="org.apache.curator" name="curator-recipes" rev="2.8.0"/>
<dependency conf="core->default" org="org.python" name="jython-standalone" rev="2.7.0" />
<dependency conf="core->default" org="org.apache.tika" name="tika-core" rev="1.20"/>
<!-- Exclude the version of cxf-rt-rs-client from Tika 1.20, one of its depedencies breaks Ivy -->
<dependency conf="core->default" org="org.apache.tika" name="tika-parsers" rev="1.20">
<exclude module="cxf-rt-rs-client"/>
<exclude module="cleartk-ml"/>
</dependency>
<!-- Pull down the latest cxf-rt-rs-client which has the Ivy fix -->
<dependency conf="core->default" org="org.apache.cxf" name="cxf-rt-rs-client" rev="3.3.0"/>
<dependency conf="core->default" org="org.cleartk" name="cleartk-ml" rev="2.0.0"/>
<dependency conf="core->default" org="com.adobe.xmp" name="xmpcore" rev="5.1.2"/>
<dependency conf="core->default" org="org.apache.zookeeper" name="zookeeper" rev="3.4.6"/>
@ -37,25 +27,27 @@
<dependency conf="core->default" org="org.jsoup" name="jsoup" rev="1.10.3"/>
<dependency conf="core->default" org="com.fasterxml.jackson.core" name="jackson-core" rev="2.9.7"/>
<dependency conf="core->default" org="com.fasterxml.jackson.core" name="jackson-databind" rev="2.9.7"/>
<dependency conf="core->default" org="com.drewnoakes" name="metadata-extractor" rev="2.11.0"/>
<dependency conf="core->default" org="com.google.cloud" name="google-cloud-translate" rev="1.70.0"/>
<dependency conf="core->default" org="org.apache.opennlp" name="opennlp-tools" rev="1.9.1"/>
<dependency conf="core->default" org="com.ethteck.decodetect" name="decodetect-core" rev="0.3"/>
<dependency conf="core->default" org="com.beetstra.jutf7" name="jutf7" rev="1.0.0"/>
<dependency org="org.sejda.webp-imageio" name="webp-imageio-sejda" rev="0.1.0"/>
<dependency org="com.googlecode.libphonenumber" name="libphonenumber" rev="3.5" />
<dependency conf="core->default" org="org.sejda.webp-imageio" name="webp-imageio-sejda" rev="0.1.0"/>
<dependency conf="core->default" org="com.googlecode.libphonenumber" name="libphonenumber" rev="3.5" />
<dependency conf="core->default" org="commons-validator" name="commons-validator" rev="1.6"/>
<dependency conf="core->default" org="net.htmlparser.jericho" name="jericho-html" rev="3.3"/>
<dependency org="com.squareup.okhttp" name="okhttp" rev="2.7.5"/>
<dependency conf="core->default" org="com.squareup.okhttp" name="okhttp" rev="2.7.5"/>
<dependency conf="core->default" org="org.jfree" name="jfreechart" rev="1.0.19"/>
<!-- map support for geolocation -->
<dependency conf="core->default" org="org.jxmapviewer" name="jxmapviewer2" rev="2.4"/>
<!-- https://mvnrepository.com/artifact/javax.ws.rs/javax.ws.rs-api -->
<dependency org="javax.ws.rs" name="javax.ws.rs-api" rev="2.0"/>
<dependency conf="core->default" org="javax.ws.rs" name="javax.ws.rs-api" rev="2.0"/>
<override org="jakarta.ws.rs" module="jakarta.ws.rs-api" rev="2.1.5"/>
</dependencies>
</ivy-module>

View File

@ -1,143 +1,123 @@
file.reference.activemq-all-5.11.1.jar=release/modules/ext/activemq-all-5.11.1.jar
file.reference.apache-mime4j-core-0.8.2.jar=release\\modules\\ext\\apache-mime4j-core-0.8.2.jar
file.reference.apache-mime4j-dom-0.8.2.jar=release\\modules\\ext\\apache-mime4j-dom-0.8.2.jar
file.reference.asm-7.0.jar=release\\modules\\ext\\asm-7.0.jar
file.reference.batik-awt-util-1.6.jar=release/modules/ext/batik-awt-util-1.6.jar
file.reference.batik-dom-1.6.jar=release/modules/ext/batik-dom-1.6.jar
file.reference.batik-svg-dom-1.6.jar=release/modules/ext/batik-svg-dom-1.6.jar
file.reference.batik-svggen-1.6.jar=release/modules/ext/batik-svggen-1.6.jar
file.reference.batik-util-1.6.jar=release/modules/ext/batik-util-1.6.jar
file.reference.batik-xml-1.6.jar=release/modules/ext/batik-xml-1.6.jar
file.reference.bcmail-jdk15on-1.60.jar=release\\modules\\ext\\bcmail-jdk15on-1.60.jar
file.reference.bcpkix-jdk15on-1.60.jar=release\\modules\\ext\\bcpkix-jdk15on-1.60.jar
file.reference.bcprov-ext-jdk15on-1.54.jar=release/modules/ext/bcprov-ext-jdk15on-1.54.jar
file.reference.bcprov-jdk15on-1.60.jar=release\\modules\\ext\\bcprov-jdk15on-1.60.jar
file.reference.boilerpipe-1.1.0.jar=release\\modules\\ext\\boilerpipe-1.1.0.jar
file.reference.c3p0-0.9.5.jar=release/modules/ext/c3p0-0.9.5.jar
file.reference.cdm-4.5.5.jar=release\\modules\\ext\\cdm-4.5.5.jar
file.reference.activemq-all-5.11.1.jar=release\\modules\\ext\\activemq-all-5.11.1.jar
file.reference.animal-sniffer-annotations-1.17.jar=release\\modules\\ext\\animal-sniffer-annotations-1.17.jar
file.reference.api-common-1.7.0.jar=release\\modules\\ext\\api-common-1.7.0.jar
file.reference.batik-awt-util-1.6.jar=release\\modules\\ext\\batik-awt-util-1.6.jar
file.reference.batik-dom-1.6.jar=release\\modules\\ext\\batik-dom-1.6.jar
file.reference.batik-svg-dom-1.6.jar=release\\modules\\ext\\batik-svg-dom-1.6.jar
file.reference.batik-svggen-1.6.jar=release\\modules\\ext\\batik-svggen-1.6.jar
file.reference.batik-util-1.6.jar=release\\modules\\ext\\batik-util-1.6.jar
file.reference.batik-xml-1.6.jar=release\\modules\\ext\\batik-xml-1.6.jar
file.reference.bcpkix-jdk15on-1.54.jar=release\\modules\\ext\\bcpkix-jdk15on-1.54.jar
file.reference.bcprov-ext-jdk15on-1.54.jar=release\\modules\\ext\\bcprov-ext-jdk15on-1.54.jar
file.reference.bcprov-jdk15on-1.52.jar=release\\modules\\ext\\bcprov-jdk15on-1.52.jar
file.reference.bcprov-jdk15on-1.54.jar=release\\modules\\ext\\bcprov-jdk15on-1.54.jar
file.reference.c3p0-0.9.5.jar=release\\modules\\ext\\c3p0-0.9.5.jar
file.reference.checker-compat-qual-2.5.3.jar=release\\modules\\ext\\checker-compat-qual-2.5.3.jar
file.reference.commons-beanutils-1.9.2.jar=release\\modules\\ext\\commons-beanutils-1.9.2.jar
file.reference.commons-codec-1.11.jar=release\\modules\\ext\\commons-codec-1.11.jar
file.reference.commons-collections4-4.2.jar=release\\modules\\ext\\commons-collections4-4.2.jar
file.reference.commons-csv-1.6.jar=release\\modules\\ext\\commons-csv-1.6.jar
file.reference.commons-dbcp2-2.1.1.jar=release/modules/ext/commons-dbcp2-2.1.1.jar
file.reference.commons-exec-1.3.jar=release\\modules\\ext\\commons-exec-1.3.jar
file.reference.commons-io-2.6.jar=release\\modules\\ext\\commons-io-2.6.jar
file.reference.commons-lang3-3.8.1.jar=release\\modules\\ext\\commons-lang3-3.8.1.jar
file.reference.commons-pool2-2.4.2.jar=release/modules/ext/commons-pool2-2.4.2.jar
file.reference.cxf-rt-rs-client-3.3.0.jar=release\\modules\\ext\\cxf-rt-rs-client-3.3.0.jar
file.reference.DatCon.jar=release/modules/ext/DatCon.jar
file.reference.dec-0.1.2.jar=release\\modules\\ext\\dec-0.1.2.jar
file.reference.decodetect-core-0.3.jar=release/modules/ext/decodetect-core-0.3.jar
file.reference.fontbox-2.0.13.jar=release\\modules\\ext\\fontbox-2.0.13.jar
file.reference.geoapi-3.0.1.jar=release\\modules\\ext\\geoapi-3.0.1.jar
file.reference.grib-4.5.5.jar=release\\modules\\ext\\grib-4.5.5.jar
file.reference.httpclient-4.5.6.jar=release\\modules\\ext\\httpclient-4.5.6.jar
file.reference.httpmime-4.5.6.jar=release\\modules\\ext\\httpmime-4.5.6.jar
file.reference.httpservices-4.5.5.jar=release\\modules\\ext\\httpservices-4.5.5.jar
file.reference.icepdf-core-6.2.2.jar=release/modules/ext/icepdf-core-6.2.2.jar
file.reference.icepdf-viewer-6.2.2.jar=release/modules/ext/icepdf-viewer-6.2.2.jar
file.reference.isoparser-1.1.22.jar=release\\modules\\ext\\isoparser-1.1.22.jar
file.reference.commons-collections-3.2.2.jar=release\\modules\\ext\\commons-collections-3.2.2.jar
file.reference.commons-dbcp2-2.1.1.jar=release\\modules\\ext\\commons-dbcp2-2.1.1.jar
file.reference.commons-digester-1.8.1.jar=release\\modules\\ext\\commons-digester-1.8.1.jar
file.reference.commons-lang-2.6.jar=release\\modules\\ext\\commons-lang-2.6.jar
file.reference.commons-lang3-3.5.jar=release\\modules\\ext\\commons-lang3-3.5.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.commons-validator-1.6.jar=release\\modules\\ext\\commons-validator-1.6.jar
file.reference.curator-client-2.8.0.jar=release\\modules\\ext\\curator-client-2.8.0.jar
file.reference.curator-framework-2.8.0.jar=release\\modules\\ext\\curator-framework-2.8.0.jar
file.reference.curator-recipes-2.8.0.jar=release\\modules\\ext\\curator-recipes-2.8.0.jar
file.reference.DatCon.jar=release\\modules\\ext\\DatCon.jar
file.reference.decodetect-core-0.3.jar=release\\modules\\ext\\decodetect-core-0.3.jar
file.reference.error_prone_annotations-2.3.2.jar=release\\modules\\ext\\error_prone_annotations-2.3.2.jar
file.reference.failureaccess-1.0.1.jar=release\\modules\\ext\\failureaccess-1.0.1.jar
file.reference.gax-1.44.0.jar=release\\modules\\ext\\gax-1.44.0.jar
file.reference.gax-grpc-1.44.0.jar=release\\modules\\ext\\gax-grpc-1.44.0.jar
file.reference.gax-httpjson-0.61.0.jar=release\\modules\\ext\\gax-httpjson-0.61.0.jar
file.reference.google-api-client-1.27.0.jar=release\\modules\\ext\\google-api-client-1.27.0.jar
file.reference.google-api-services-translate-v2-rev20170525-1.27.0.jar=release\\modules\\ext\\google-api-services-translate-v2-rev20170525-1.27.0.jar
file.reference.google-auth-library-credentials-0.15.0.jar=release\\modules\\ext\\google-auth-library-credentials-0.15.0.jar
file.reference.google-auth-library-oauth2-http-0.15.0.jar=release\\modules\\ext\\google-auth-library-oauth2-http-0.15.0.jar
file.reference.google-cloud-core-1.70.0.jar=release\\modules\\ext\\google-cloud-core-1.70.0.jar
file.reference.google-cloud-core-grpc-1.70.0.jar=release\\modules\\ext\\google-cloud-core-grpc-1.70.0.jar
file.reference.google-cloud-core-http-1.70.0.jar=release\\modules\\ext\\google-cloud-core-http-1.70.0.jar
file.reference.google-cloud-translate-1.70.0.jar=release\\modules\\ext\\google-cloud-translate-1.70.0.jar
file.reference.google-http-client-1.29.0.jar=release\\modules\\ext\\google-http-client-1.29.0.jar
file.reference.google-http-client-appengine-1.29.0.jar=release\\modules\\ext\\google-http-client-appengine-1.29.0.jar
file.reference.google-http-client-jackson2-1.29.0.jar=release\\modules\\ext\\google-http-client-jackson2-1.29.0.jar
file.reference.google-oauth-client-1.28.0.jar=release\\modules\\ext\\google-oauth-client-1.28.0.jar
file.reference.grpc-alts-1.19.0.jar=release\\modules\\ext\\grpc-alts-1.19.0.jar
file.reference.grpc-auth-1.19.0.jar=release\\modules\\ext\\grpc-auth-1.19.0.jar
file.reference.grpc-context-1.19.0.jar=release\\modules\\ext\\grpc-context-1.19.0.jar
file.reference.grpc-core-1.19.0.jar=release\\modules\\ext\\grpc-core-1.19.0.jar
file.reference.grpc-grpclb-1.19.0.jar=release\\modules\\ext\\grpc-grpclb-1.19.0.jar
file.reference.grpc-netty-shaded-1.19.0.jar=release\\modules\\ext\\grpc-netty-shaded-1.19.0.jar
file.reference.grpc-protobuf-1.19.0.jar=release\\modules\\ext\\grpc-protobuf-1.19.0.jar
file.reference.grpc-protobuf-lite-1.19.0.jar=release\\modules\\ext\\grpc-protobuf-lite-1.19.0.jar
file.reference.grpc-stub-1.19.0.jar=release\\modules\\ext\\grpc-stub-1.19.0.jar
file.reference.gson-2.7.jar=release\\modules\\ext\\gson-2.7.jar
file.reference.guava-27.1-android.jar=release\\modules\\ext\\guava-27.1-android.jar
file.reference.httpclient-4.5.5.jar=release\\modules\\ext\\httpclient-4.5.5.jar
file.reference.httpcore-4.4.9.jar=release\\modules\\ext\\httpcore-4.4.9.jar
file.reference.icepdf-core-6.2.2.jar=release\\modules\\ext\\icepdf-core-6.2.2.jar
file.reference.icepdf-viewer-6.2.2.jar=release\\modules\\ext\\icepdf-viewer-6.2.2.jar
file.reference.j2objc-annotations-1.1.jar=release\\modules\\ext\\j2objc-annotations-1.1.jar
file.reference.jackcess-2.2.0.jar=release\\modules\\ext\\jackcess-2.2.0.jar
file.reference.jackcess-encrypt-2.1.4.jar=release\\modules\\ext\\jackcess-encrypt-2.1.4.jar
file.reference.jackson-annotations-2.9.7.jar=release\\modules\\ext\\jackson-annotations-2.9.7.jar
file.reference.jackson-annotations-2.9.0.jar=release\\modules\\ext\\jackson-annotations-2.9.0.jar
file.reference.jackson-core-2.9.7.jar=release\\modules\\ext\\jackson-core-2.9.7.jar
file.reference.jackson-databind-2.9.7.jar=release\\modules\\ext\\jackson-databind-2.9.7.jar
file.reference.jai-imageio-core-1.4.0.jar=release\\modules\\ext\\jai-imageio-core-1.4.0.jar
file.reference.jai_core-1.1.3.jar=release/modules/ext/jai_core-1.1.3.jar
file.reference.jai_imageio-1.1.jar=release/modules/ext/jai_imageio-1.1.jar
file.reference.java-libpst-0.8.1.jar=release\\modules\\ext\\java-libpst-0.8.1.jar
file.reference.javax.activation-1.2.0.jar=release\\modules\\ext\\javax.activation-1.2.0.jar
file.reference.jai_core-1.1.3.jar=release\\modules\\ext\\jai_core-1.1.3.jar
file.reference.jai_imageio-1.1.jar=release\\modules\\ext\\jai_imageio-1.1.jar
file.reference.javax.annotation-api-1.3.2.jar=release\\modules\\ext\\javax.annotation-api-1.3.2.jar
file.reference.jbig2-imageio-3.0.2.jar=release\\modules\\ext\\jbig2-imageio-3.0.2.jar
file.reference.jcl-over-slf4j-1.7.25.jar=release\\modules\\ext\\jcl-over-slf4j-1.7.25.jar
file.reference.jdom-2.0.5-contrib.jar=release/modules/ext/jdom-2.0.5-contrib.jar
file.reference.jdom-2.0.5.jar=release/modules/ext/jdom-2.0.5.jar
file.reference.jdom2-2.0.6.jar=release\\modules\\ext\\jdom2-2.0.6.jar
file.reference.jempbox-1.8.16.jar=release\\modules\\ext\\jempbox-1.8.16.jar
file.reference.jericho-html-3.3.jar=release/modules/ext/jericho-html-3.3.jar
file.reference.jgraphx-4.1.0.jar=release/modules/ext/jgraphx-4.1.0.jar
file.reference.jhighlight-1.0.3.jar=release\\modules\\ext\\jhighlight-1.0.3.jar
file.reference.jmatio-1.5.jar=release\\modules\\ext\\jmatio-1.5.jar
file.reference.json-simple-1.1.1.jar=release\\modules\\ext\\json-simple-1.1.1.jar
file.reference.jsoup-1.11.3.jar=release\\modules\\ext\\jsoup-1.11.3.jar
file.reference.jul-to-slf4j-1.7.25.jar=release\\modules\\ext\\jul-to-slf4j-1.7.25.jar
file.reference.juniversalchardet-1.0.3.jar=release\\modules\\ext\\juniversalchardet-1.0.3.jar
file.reference.junrar-2.0.0.jar=release\\modules\\ext\\junrar-2.0.0.jar
file.reference.jutf7-1.0.0.jar=release/modules/ext/jutf7-1.0.0.jar
file.reference.jxmapviewer2-2.4.jar=release/modules/ext/jxmapviewer2-2.4.jar
file.reference.jython-standalone-2.7.0.jar=release/modules/ext/jython-standalone-2.7.0.jar
file.reference.libphonenumber-3.5.jar=release/modules/ext/libphonenumber-3.5.jar
file.reference.mchange-commons-java-0.2.9.jar=release/modules/ext/mchange-commons-java-0.2.9.jar
file.reference.javax.ws.rs-api-2.0.jar=release\\modules\\ext\\javax.ws.rs-api-2.0.jar
file.reference.jdom-2.0.5-contrib.jar=release\\modules\\ext\\jdom-2.0.5-contrib.jar
file.reference.jdom-2.0.5.jar=release\\modules\\ext\\jdom-2.0.5.jar
file.reference.jericho-html-3.3.jar=release\\modules\\ext\\jericho-html-3.3.jar
file.reference.jgraphx-4.1.0.jar=release\\modules\\ext\\jgraphx-4.1.0.jar
file.reference.jline-0.9.94.jar=release\\modules\\ext\\jline-0.9.94.jar
file.reference.jsoup-1.10.3.jar=release\\modules\\ext\\jsoup-1.10.3.jar
file.reference.jsr305-3.0.2.jar=release\\modules\\ext\\jsr305-3.0.2.jar
file.reference.junit-3.8.1.jar=release\\modules\\ext\\junit-3.8.1.jar
file.reference.jutf7-1.0.0.jar=release\\modules\\ext\\jutf7-1.0.0.jar
file.reference.jxmapviewer2-2.4.jar=release\\modules\\ext\\jxmapviewer2-2.4.jar
file.reference.jython-standalone-2.7.0.jar=release\\modules\\ext\\jython-standalone-2.7.0.jar
file.reference.libphonenumber-3.5.jar=release\\modules\\ext\\libphonenumber-3.5.jar
file.reference.listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar=release\\modules\\ext\\listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar
file.reference.log4j-1.2.16.jar=release\\modules\\ext\\log4j-1.2.16.jar
file.reference.mchange-commons-java-0.2.9.jar=release\\modules\\ext\\mchange-commons-java-0.2.9.jar
file.reference.metadata-extractor-2.11.0.jar=release\\modules\\ext\\metadata-extractor-2.11.0.jar
file.reference.netcdf4-4.5.5.jar=release\\modules\\ext\\netcdf4-4.5.5.jar
file.reference.openjson-1.0.10.jar=release\\modules\\ext\\openjson-1.0.10.jar
file.reference.netty-3.7.0.Final.jar=release\\modules\\ext\\netty-3.7.0.Final.jar
file.reference.okhttp-2.7.5.jar=release\\modules\\ext\\okhttp-2.7.5.jar
file.reference.okio-1.6.0.jar=release\\modules\\ext\\okio-1.6.0.jar
file.reference.opencensus-api-0.19.2.jar=release\\modules\\ext\\opencensus-api-0.19.2.jar
file.reference.opencensus-contrib-grpc-metrics-0.19.2.jar=release\\modules\\ext\\opencensus-contrib-grpc-metrics-0.19.2.jar
file.reference.opencensus-contrib-http-util-0.19.2.jar=release\\modules\\ext\\opencensus-contrib-http-util-0.19.2.jar
file.reference.opennlp-tools-1.9.1.jar=release\\modules\\ext\\opennlp-tools-1.9.1.jar
file.reference.parso-2.0.10.jar=release\\modules\\ext\\parso-2.0.10.jar
file.reference.pdfbox-2.0.13.jar=release\\modules\\ext\\pdfbox-2.0.13.jar
file.reference.pdfbox-tools-2.0.13.jar=release\\modules\\ext\\pdfbox-tools-2.0.13.jar
file.reference.postgresql-9.4.1211.jre7.jar=release/modules/ext/postgresql-9.4.1211.jre7.jar
file.reference.Rejistry-1.1-SNAPSHOT.jar=release/modules/ext/Rejistry-1.1-SNAPSHOT.jar
file.reference.rome-1.12.0.jar=release\\modules\\ext\\rome-1.12.0.jar
file.reference.sentiment-analysis-parser-0.1.jar=release\\modules\\ext\\sentiment-analysis-parser-0.1.jar
file.reference.sevenzipjbinding-AllPlatforms.jar=release/modules/ext/sevenzipjbinding-AllPlatforms.jar
file.reference.sevenzipjbinding.jar=release/modules/ext/sevenzipjbinding.jar
file.reference.sis-metadata-0.8.jar=release\\modules\\ext\\sis-metadata-0.8.jar
file.reference.sis-netcdf-0.8.jar=release\\modules\\ext\\sis-netcdf-0.8.jar
file.reference.sis-utility-0.8.jar=release\\modules\\ext\\sis-utility-0.8.jar
file.reference.sleuthkit-caseuco-4.10.0.jar=release/modules/ext/sleuthkit-caseuco-4.10.0.jar
file.reference.slf4j-api-1.7.25.jar=release\\modules\\ext\\slf4j-api-1.7.25.jar
file.reference.sqlite-jdbc-3.25.2.jar=release/modules/ext/sqlite-jdbc-3.25.2.jar
file.reference.StixLib.jar=release/modules/ext/StixLib.jar
file.reference.javax.ws.rs-api-2.0.1.jar=release/modules/ext/javax.ws.rs-api-2.0.1.jar
file.reference.cxf-core-3.0.16.jar=release/modules/ext/cxf-core-3.0.16.jar
file.reference.cxf-rt-frontend-jaxrs-3.0.16.jar=release/modules/ext/cxf-rt-frontend-jaxrs-3.0.16.jar
file.reference.cxf-rt-transports-http-3.0.16.jar=release/modules/ext/cxf-rt-transports-http-3.0.16.jar
file.reference.sleuthkit-4.10.0.jar=release/modules/ext/sleuthkit-4.10.0.jar
file.reference.curator-client-2.8.0.jar=release/modules/ext/curator-client-2.8.0.jar
file.reference.curator-framework-2.8.0.jar=release/modules/ext/curator-framework-2.8.0.jar
file.reference.curator-recipes-2.8.0.jar=release/modules/ext/curator-recipes-2.8.0.jar
file.reference.tagsoup-1.2.1.jar=release\\modules\\ext\\tagsoup-1.2.1.jar
file.reference.tika-core-1.20.jar=release\\modules\\ext\\tika-core-1.20.jar
file.reference.tika-parsers-1.20.jar=release\\modules\\ext\\tika-parsers-1.20.jar
file.reference.uimafit-core-2.4.0.jar=release\\modules\\ext\\uimafit-core-2.4.0.jar
file.reference.uimaj-core-3.0.1.jar=release\\modules\\ext\\uimaj-core-3.0.1.jar
file.reference.vorbis-java-core-0.8.jar=release\\modules\\ext\\vorbis-java-core-0.8.jar
file.reference.vorbis-java-tika-0.8.jar=release\\modules\\ext\\vorbis-java-tika-0.8.jar
file.reference.webp-imageio-sejda-0.1.0.jar=release/modules/ext/webp-imageio-sejda-0.1.0.jar
file.reference.xmlbeans-3.0.2.jar=release\\modules\\ext\\xmlbeans-3.0.2.jar
file.reference.xmpcore-5.1.3.jar=release/modules/ext/xmpcore-5.1.3.jar
file.reference.xz-1.8.jar=release\\modules\\ext\\xz-1.8.jar
file.reference.zookeeper-3.4.6.jar=release/modules/ext/zookeeper-3.4.6.jar
file.reference.SparseBitSet-1.1.jar=release/modules/ext/SparseBitSet-1.1.jar
file.reference.commons-validator-1.6.jar=release/modules/ext/commons-validator-1.6.jar
file.reference.api-common-1.7.0.jar=release/modules/ext/api-common-1.7.0.jar
file.reference.gax-1.44.0.jar=release/modules/ext/gax-1.44.0.jar
file.reference.gax-grpc-1.44.0.jar=release/modules/ext/gax-grpc-1.44.0.jar
file.reference.gax-httpjson-0.61.0.jar=release/modules/ext/gax-httpjson-0.61.0.jar
file.reference.google-api-client-1.27.0.jar=release/modules/ext/google-api-client-1.27.0.jar
file.reference.google-api-services-translate-v2-rev20170525-1.27.0.jar=release/modules/ext/google-api-services-translate-v2-rev20170525-1.27.0.jar
file.reference.google-auth-library-credentials-0.15.0.jar=release/modules/ext/google-auth-library-credentials-0.15.0.jar
file.reference.google-auth-library-oauth2-http-0.15.0.jar=release/modules/ext/google-auth-library-oauth2-http-0.15.0.jar
file.reference.google-cloud-core-1.70.0.jar=release/modules/ext/google-cloud-core-1.70.0.jar
file.reference.google-cloud-core-http-1.70.0.jar=release/modules/ext/google-cloud-core-http-1.70.0.jar
file.reference.google-cloud-translate-1.70.0.jar=release/modules/ext/google-cloud-translate-1.70.0.jar
file.reference.google-http-client-1.29.0.jar=release/modules/ext/google-http-client-1.29.0.jar
file.reference.google-http-client-appengine-1.29.0.jar=release/modules/ext/google-http-client-appengine-1.29.0.jar
file.reference.google-http-client-jackson2-1.29.0.jar=release/modules/ext/google-http-client-jackson2-1.29.0.jar
file.reference.grpc-context-1.19.0.jar=release/modules/ext/grpc-context-1.19.0.jar
file.reference.opencensus-api-0.19.2.jar=release/modules/ext/opencensus-api-0.19.2.jar
file.reference.opencensus-contrib-http-util-0.19.2.jar=release/modules/ext/opencensus-contrib-http-util-0.19.2.jar
file.reference.threetenbp-1.3.3.jar=release/modules/ext/threetenbp-1.3.3.jar
file.reference.okhttp-2.7.5-javadoc.jar=release/modules/ext/okhttp-2.7.5-javadoc.jar
file.reference.okhttp-2.7.5-sources.jar=release/modules/ext/okhttp-2.7.5-sources.jar
file.reference.okhttp-2.7.5.jar=release/modules/ext/okhttp-2.7.5.jar
file.reference.okio-1.6.0.jar=release/modules/ext/okio-1.6.0.jar
file.reference.datcon.jar=release/modules/ext/DatCon.jar
file.reference.postgresql-9.4.1211.jre7.jar=release\\modules\\ext\\postgresql-9.4.1211.jre7.jar
file.reference.proto-google-cloud-translate-v3beta1-0.53.0.jar=release\\modules\\ext\\proto-google-cloud-translate-v3beta1-0.53.0.jar
file.reference.proto-google-common-protos-1.15.0.jar=release\\modules\\ext\\proto-google-common-protos-1.15.0.jar
file.reference.proto-google-iam-v1-0.12.0.jar=release\\modules\\ext\\proto-google-iam-v1-0.12.0.jar
file.reference.protobuf-java-3.7.0.jar=release\\modules\\ext\\protobuf-java-3.7.0.jar
file.reference.protobuf-java-util-3.7.0.jar=release\\modules\\ext\\protobuf-java-util-3.7.0.jar
file.reference.Rejistry-1.1-SNAPSHOT.jar=release\\modules\\ext\\Rejistry-1.1-SNAPSHOT.jar
file.reference.sevenzipjbinding-AllPlatforms.jar=release\\modules\\ext\\sevenzipjbinding-AllPlatforms.jar
file.reference.sevenzipjbinding.jar=release\\modules\\ext\\sevenzipjbinding.jar
file.reference.sleuthkit-4.10.0.jar=release\\modules\\ext\\sleuthkit-4.10.0.jar
file.reference.sleuthkit-caseuco-4.10.0.jar=release\\modules\\ext\\sleuthkit-caseuco-4.10.0.jar
file.reference.slf4j-api-1.7.6.jar=release\\modules\\ext\\slf4j-api-1.7.6.jar
file.reference.slf4j-log4j12-1.7.6.jar=release\\modules\\ext\\slf4j-log4j12-1.7.6.jar
file.reference.SparseBitSet-1.1.jar=release\\modules\\ext\\SparseBitSet-1.1.jar
file.reference.sqlite-jdbc-3.25.2.jar=release\\modules\\ext\\sqlite-jdbc-3.25.2.jar
file.reference.StixLib.jar=release\\modules\\ext\\StixLib.jar
file.reference.threetenbp-1.3.3.jar=release\\modules\\ext\\threetenbp-1.3.3.jar
file.reference.webp-imageio-sejda-0.1.0.jar=release\\modules\\ext\\webp-imageio-sejda-0.1.0.jar
file.reference.xmpcore-5.1.3.jar=release\\modules\\ext\\xmpcore-5.1.3.jar
file.reference.zookeeper-3.4.6.jar=release\\modules\\ext\\zookeeper-3.4.6.jar
javac.source=1.8
javac.compilerargs=-Xlint -Xlint:-serial
license.file=../LICENSE-2.0.txt
nbm.homepage=http://www.sleuthkit.org/
nbm.module.author=Brian Carrier
nbm.needs.restart=true
source.reference.curator-recipes-2.8.0.jar=release/modules/ext/curator-recipes-2.8.0-sources.jar
spec.version.base=10.20

View File

@ -227,6 +227,14 @@
<specification-version>6.55.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.sleuthkit.autopsy.Tika</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>1.0</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.sleuthkit.autopsy.corelibs</code-name-base>
<build-prerequisite/>
@ -291,8 +299,6 @@
<package>net.sf.sevenzipjbinding.impl</package>
<package>net.sf.sevenzipjbinding.simple</package>
<package>net.sf.sevenzipjbinding.simple.impl</package>
<package>org.apache.tika</package>
<package>org.apache.tika.io</package>
<package>org.sleuthkit.autopsy.actions</package>
<package>org.sleuthkit.autopsy.appservices</package>
<package>org.sleuthkit.autopsy.casemodule</package>
@ -334,100 +340,88 @@
<package>org.sleuthkit.datamodel.blackboardutils.attributes</package>
</public-packages>
<class-path-extension>
<runtime-relative-path>ext/commons-lang3-3.8.1.jar</runtime-relative-path>
<binary-origin>release\modules\ext\commons-lang3-3.8.1.jar</binary-origin>
<runtime-relative-path>ext/batik-xml-1.6.jar</runtime-relative-path>
<binary-origin>release\modules\ext\batik-xml-1.6.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/batik-xml-1.6.jar</runtime-relative-path>
<binary-origin>release/modules/ext/batik-xml-1.6.jar</binary-origin>
<runtime-relative-path>ext/commons-digester-1.8.1.jar</runtime-relative-path>
<binary-origin>release\modules\ext\commons-digester-1.8.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jai_core-1.1.3.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jai_core-1.1.3.jar</binary-origin>
<binary-origin>release\modules\ext\jai_core-1.1.3.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/gax-grpc-1.44.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/gax-grpc-1.44.0.jar</binary-origin>
<binary-origin>release\modules\ext\gax-grpc-1.44.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/cdm-4.5.5.jar</runtime-relative-path>
<binary-origin>release\modules\ext\cdm-4.5.5.jar</binary-origin>
<runtime-relative-path>ext/failureaccess-1.0.1.jar</runtime-relative-path>
<binary-origin>release\modules\ext\failureaccess-1.0.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/sis-utility-0.8.jar</runtime-relative-path>
<binary-origin>release\modules\ext\sis-utility-0.8.jar</binary-origin>
<runtime-relative-path>ext/grpc-protobuf-1.19.0.jar</runtime-relative-path>
<binary-origin>release\modules\ext\grpc-protobuf-1.19.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/opencensus-api-0.19.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/opencensus-api-0.19.2.jar</binary-origin>
<binary-origin>release\modules\ext\opencensus-api-0.19.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/batik-svg-dom-1.6.jar</runtime-relative-path>
<binary-origin>release/modules/ext/batik-svg-dom-1.6.jar</binary-origin>
<binary-origin>release\modules\ext\batik-svg-dom-1.6.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/gax-httpjson-0.61.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/gax-httpjson-0.61.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/boilerpipe-1.1.0.jar</runtime-relative-path>
<binary-origin>release\modules\ext\boilerpipe-1.1.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jsoup-1.11.3.jar</runtime-relative-path>
<binary-origin>release\modules\ext\jsoup-1.11.3.jar</binary-origin>
<binary-origin>release\modules\ext\gax-httpjson-0.61.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/sevenzipjbinding.jar</runtime-relative-path>
<binary-origin>release/modules/ext/sevenzipjbinding.jar</binary-origin>
<binary-origin>release\modules\ext\sevenzipjbinding.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/mchange-commons-java-0.2.9.jar</runtime-relative-path>
<binary-origin>release/modules/ext/mchange-commons-java-0.2.9.jar</binary-origin>
<binary-origin>release\modules\ext\mchange-commons-java-0.2.9.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/api-common-1.7.0.jar</runtime-relative-path>
<binary-origin>release\modules\ext\api-common-1.7.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jackson-databind-2.9.7.jar</runtime-relative-path>
<binary-origin>release\modules\ext\jackson-databind-2.9.7.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jai-imageio-core-1.4.0.jar</runtime-relative-path>
<binary-origin>release\modules\ext\jai-imageio-core-1.4.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/api-common-1.7.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/api-common-1.7.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jcl-over-slf4j-1.7.25.jar</runtime-relative-path>
<binary-origin>release\modules\ext\jcl-over-slf4j-1.7.25.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/okhttp-2.7.5.jar</runtime-relative-path>
<binary-origin>release/modules/ext/okhttp-2.7.5.jar</binary-origin>
<binary-origin>release\modules\ext\okhttp-2.7.5.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/proto-google-cloud-translate-v3beta1-0.53.0.jar</runtime-relative-path>
<binary-origin>release\modules\ext\proto-google-cloud-translate-v3beta1-0.53.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/error_prone_annotations-2.3.2.jar</runtime-relative-path>
<binary-origin>release\modules\ext\error_prone_annotations-2.3.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/libphonenumber-3.5.jar</runtime-relative-path>
<binary-origin>release/modules/ext/libphonenumber-3.5.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/tika-core-1.20.jar</runtime-relative-path>
<binary-origin>release\modules\ext\tika-core-1.20.jar</binary-origin>
<binary-origin>release\modules\ext\libphonenumber-3.5.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/StixLib.jar</runtime-relative-path>
<binary-origin>release/modules/ext/StixLib.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/bcprov-jdk15on-1.60.jar</runtime-relative-path>
<binary-origin>release\modules\ext\bcprov-jdk15on-1.60.jar</binary-origin>
<binary-origin>release\modules\ext\StixLib.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/google-auth-library-credentials-0.15.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/google-auth-library-credentials-0.15.0.jar</binary-origin>
<binary-origin>release\modules\ext\google-auth-library-credentials-0.15.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/json-simple-1.1.1.jar</runtime-relative-path>
<binary-origin>release\modules\ext\json-simple-1.1.1.jar</binary-origin>
<runtime-relative-path>ext/grpc-auth-1.19.0.jar</runtime-relative-path>
<binary-origin>release\modules\ext\grpc-auth-1.19.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/j2objc-annotations-1.1.jar</runtime-relative-path>
<binary-origin>release\modules\ext\j2objc-annotations-1.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/metadata-extractor-2.11.0.jar</runtime-relative-path>
@ -437,157 +431,137 @@
<runtime-relative-path>ext/commons-codec-1.11.jar</runtime-relative-path>
<binary-origin>release\modules\ext\commons-codec-1.11.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jmatio-1.5.jar</runtime-relative-path>
<binary-origin>release\modules\ext\jmatio-1.5.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/tika-parsers-1.20.jar</runtime-relative-path>
<binary-origin>release\modules\ext\tika-parsers-1.20.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/asm-7.0.jar</runtime-relative-path>
<binary-origin>release\modules\ext\asm-7.0.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>
<binary-origin>release\modules\ext\commons-pool2-2.4.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jxmapviewer2-2.4.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jxmapviewer2-2.4.jar</binary-origin>
<binary-origin>release\modules\ext\jxmapviewer2-2.4.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jfreechart-1.0.19.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jfreechart-1.0.19.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jcommon-1.0.23.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jcommon-1.0.23.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jdom-2.0.5-contrib.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jdom-2.0.5-contrib.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/openjson-1.0.10.jar</runtime-relative-path>
<binary-origin>release\modules\ext\openjson-1.0.10.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/isoparser-1.1.22.jar</runtime-relative-path>
<binary-origin>release\modules\ext\isoparser-1.1.22.jar</binary-origin>
<binary-origin>release\modules\ext\jdom-2.0.5-contrib.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/xmpcore-5.1.3.jar</runtime-relative-path>
<binary-origin>release/modules/ext/xmpcore-5.1.3.jar</binary-origin>
<binary-origin>release\modules\ext\xmpcore-5.1.3.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/batik-util-1.6.jar</runtime-relative-path>
<binary-origin>release/modules/ext/batik-util-1.6.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/javax.activation-1.2.0.jar</runtime-relative-path>
<binary-origin>release\modules\ext\javax.activation-1.2.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/rome-1.12.0.jar</runtime-relative-path>
<binary-origin>release\modules\ext\rome-1.12.0.jar</binary-origin>
<binary-origin>release\modules\ext\batik-util-1.6.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/javax.annotation-api-1.3.2.jar</runtime-relative-path>
<binary-origin>release\modules\ext\javax.annotation-api-1.3.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/vorbis-java-core-0.8.jar</runtime-relative-path>
<binary-origin>release\modules\ext\vorbis-java-core-0.8.jar</binary-origin>
<runtime-relative-path>ext/jgraphx-4.1.0.jar</runtime-relative-path>
<binary-origin>release\modules\ext\jgraphx-4.1.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jgraphx-4.1.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jgraphx-4.1.0.jar</binary-origin>
<runtime-relative-path>ext/jline-0.9.94.jar</runtime-relative-path>
<binary-origin>release\modules\ext\jline-0.9.94.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/DatCon.jar</runtime-relative-path>
<binary-origin>release/modules/ext/DatCon.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/java-libpst-0.8.1.jar</runtime-relative-path>
<binary-origin>release\modules\ext\java-libpst-0.8.1.jar</binary-origin>
<binary-origin>release\modules\ext\DatCon.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/okio-1.6.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/okio-1.6.0.jar</binary-origin>
<binary-origin>release\modules\ext\okio-1.6.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/bcprov-jdk15on-1.54.jar</runtime-relative-path>
<binary-origin>release\modules\ext\bcprov-jdk15on-1.54.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/curator-framework-2.8.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/curator-framework-2.8.0.jar</binary-origin>
<binary-origin>release\modules\ext\curator-framework-2.8.0.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>
<binary-origin>release\modules\ext\commons-dbcp2-2.1.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/google-http-client-appengine-1.29.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/google-http-client-appengine-1.29.0.jar</binary-origin>
<binary-origin>release\modules\ext\google-http-client-appengine-1.29.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/uimafit-core-2.4.0.jar</runtime-relative-path>
<binary-origin>release\modules\ext\uimafit-core-2.4.0.jar</binary-origin>
<runtime-relative-path>ext/proto-google-iam-v1-0.12.0.jar</runtime-relative-path>
<binary-origin>release\modules\ext\proto-google-iam-v1-0.12.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jackcess-encrypt-2.1.4.jar</runtime-relative-path>
<binary-origin>release\modules\ext\jackcess-encrypt-2.1.4.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/junrar-2.0.0.jar</runtime-relative-path>
<binary-origin>release\modules\ext\junrar-2.0.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/google-http-client-1.29.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/google-http-client-1.29.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/bcpkix-jdk15on-1.60.jar</runtime-relative-path>
<binary-origin>release\modules\ext\bcpkix-jdk15on-1.60.jar</binary-origin>
<binary-origin>release\modules\ext\google-http-client-1.29.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/opennlp-tools-1.9.1.jar</runtime-relative-path>
<binary-origin>release\modules\ext\opennlp-tools-1.9.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/slf4j-api-1.7.25.jar</runtime-relative-path>
<binary-origin>release\modules\ext\slf4j-api-1.7.25.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/bcprov-ext-jdk15on-1.54.jar</runtime-relative-path>
<binary-origin>release/modules/ext/bcprov-ext-jdk15on-1.54.jar</binary-origin>
<binary-origin>release\modules\ext\bcprov-ext-jdk15on-1.54.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/google-cloud-core-1.70.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/google-cloud-core-1.70.0.jar</binary-origin>
<binary-origin>release\modules\ext\google-cloud-core-1.70.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/geoapi-3.0.1.jar</runtime-relative-path>
<binary-origin>release\modules\ext\geoapi-3.0.1.jar</binary-origin>
<runtime-relative-path>ext/protobuf-java-3.7.0.jar</runtime-relative-path>
<binary-origin>release\modules\ext\protobuf-java-3.7.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/httpmime-4.5.6.jar</runtime-relative-path>
<binary-origin>release\modules\ext\httpmime-4.5.6.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jdom2-2.0.6.jar</runtime-relative-path>
<binary-origin>release\modules\ext\jdom2-2.0.6.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/uimaj-core-3.0.1.jar</runtime-relative-path>
<binary-origin>release\modules\ext\uimaj-core-3.0.1.jar</binary-origin>
<runtime-relative-path>ext/bcpkix-jdk15on-1.54.jar</runtime-relative-path>
<binary-origin>release\modules\ext\bcpkix-jdk15on-1.54.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/sqlite-jdbc-3.25.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/sqlite-jdbc-3.25.2.jar</binary-origin>
<binary-origin>release\modules\ext\sqlite-jdbc-3.25.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/cxf-rt-rs-client-3.3.0.jar</runtime-relative-path>
<binary-origin>release\modules\ext\cxf-rt-rs-client-3.3.0.jar</binary-origin>
<runtime-relative-path>ext/grpc-protobuf-lite-1.19.0.jar</runtime-relative-path>
<binary-origin>release\modules\ext\grpc-protobuf-lite-1.19.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/pdfbox-tools-2.0.13.jar</runtime-relative-path>
<binary-origin>release\modules\ext\pdfbox-tools-2.0.13.jar</binary-origin>
<runtime-relative-path>ext/httpcore-4.4.9.jar</runtime-relative-path>
<binary-origin>release\modules\ext\httpcore-4.4.9.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/grib-4.5.5.jar</runtime-relative-path>
<binary-origin>release\modules\ext\grib-4.5.5.jar</binary-origin>
<runtime-relative-path>ext/guava-27.1-android.jar</runtime-relative-path>
<binary-origin>release\modules\ext\guava-27.1-android.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/bcprov-jdk15on-1.52.jar</runtime-relative-path>
<binary-origin>release\modules\ext\bcprov-jdk15on-1.52.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/checker-compat-qual-2.5.3.jar</runtime-relative-path>
<binary-origin>release\modules\ext\checker-compat-qual-2.5.3.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/sleuthkit-4.10.0.jar</runtime-relative-path>
<binary-origin>release\modules\ext\sleuthkit-4.10.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/animal-sniffer-annotations-1.17.jar</runtime-relative-path>
<binary-origin>release\modules\ext\animal-sniffer-annotations-1.17.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/sleuthkit-caseuco-4.10.0.jar</runtime-relative-path>
<binary-origin>release\modules\ext\sleuthkit-caseuco-4.10.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/sleuthkit-4.10.0.jar</runtime-relative-path>
@ -599,243 +573,247 @@
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/gax-1.44.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/gax-1.44.0.jar</binary-origin>
<binary-origin>release\modules\ext\gax-1.44.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jempbox-1.8.16.jar</runtime-relative-path>
<binary-origin>release\modules\ext\jempbox-1.8.16.jar</binary-origin>
<runtime-relative-path>ext/jsoup-1.10.3.jar</runtime-relative-path>
<binary-origin>release\modules\ext\jsoup-1.10.3.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/grpc-context-1.19.0.jar</runtime-relative-path>
<binary-origin>release\modules\ext\grpc-context-1.19.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jackcess-2.2.0.jar</runtime-relative-path>
<binary-origin>release\modules\ext\jackcess-2.2.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/grpc-context-1.19.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/grpc-context-1.19.0.jar</binary-origin>
<runtime-relative-path>ext/slf4j-log4j12-1.7.6.jar</runtime-relative-path>
<binary-origin>release\modules\ext\slf4j-log4j12-1.7.6.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jericho-html-3.3.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jericho-html-3.3.jar</binary-origin>
<binary-origin>release\modules\ext\jericho-html-3.3.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/httpservices-4.5.5.jar</runtime-relative-path>
<binary-origin>release\modules\ext\httpservices-4.5.5.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/xz-1.8.jar</runtime-relative-path>
<binary-origin>release\modules\ext\xz-1.8.jar</binary-origin>
<runtime-relative-path>ext/google-cloud-core-grpc-1.70.0.jar</runtime-relative-path>
<binary-origin>release\modules\ext\google-cloud-core-grpc-1.70.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/commons-validator-1.6.jar</runtime-relative-path>
<binary-origin>release/modules/ext/commons-validator-1.6.jar</binary-origin>
<binary-origin>release\modules\ext\commons-validator-1.6.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/slf4j-api-1.7.6.jar</runtime-relative-path>
<binary-origin>release\modules\ext\slf4j-api-1.7.6.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/decodetect-core-0.3.jar</runtime-relative-path>
<binary-origin>release/modules/ext/decodetect-core-0.3.jar</binary-origin>
<binary-origin>release\modules\ext\decodetect-core-0.3.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jbig2-imageio-3.0.2.jar</runtime-relative-path>
<binary-origin>release\modules\ext\jbig2-imageio-3.0.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/apache-mime4j-dom-0.8.2.jar</runtime-relative-path>
<binary-origin>release\modules\ext\apache-mime4j-dom-0.8.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/pdfbox-2.0.13.jar</runtime-relative-path>
<binary-origin>release\modules\ext\pdfbox-2.0.13.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/xmlbeans-3.0.2.jar</runtime-relative-path>
<binary-origin>release\modules\ext\xmlbeans-3.0.2.jar</binary-origin>
<runtime-relative-path>ext/httpclient-4.5.5.jar</runtime-relative-path>
<binary-origin>release\modules\ext\httpclient-4.5.5.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/curator-recipes-2.8.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/curator-recipes-2.8.0.jar</binary-origin>
<binary-origin>release\modules\ext\curator-recipes-2.8.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/tagsoup-1.2.1.jar</runtime-relative-path>
<binary-origin>release\modules\ext\tagsoup-1.2.1.jar</binary-origin>
<runtime-relative-path>ext/jackson-annotations-2.9.0.jar</runtime-relative-path>
<binary-origin>release\modules\ext\jackson-annotations-2.9.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jackson-core-2.9.7.jar</runtime-relative-path>
<binary-origin>release\modules\ext\jackson-core-2.9.7.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/sis-metadata-0.8.jar</runtime-relative-path>
<binary-origin>release\modules\ext\sis-metadata-0.8.jar</binary-origin>
<runtime-relative-path>ext/commons-lang3-3.5.jar</runtime-relative-path>
<binary-origin>release\modules\ext\commons-lang3-3.5.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/parso-2.0.10.jar</runtime-relative-path>
<binary-origin>release\modules\ext\parso-2.0.10.jar</binary-origin>
<runtime-relative-path>ext/log4j-1.2.16.jar</runtime-relative-path>
<binary-origin>release\modules\ext\log4j-1.2.16.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/apache-mime4j-core-0.8.2.jar</runtime-relative-path>
<binary-origin>release\modules\ext\apache-mime4j-core-0.8.2.jar</binary-origin>
<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-io-2.6.jar</runtime-relative-path>
<binary-origin>release\modules\ext\commons-io-2.6.jar</binary-origin>
<runtime-relative-path>ext/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar</runtime-relative-path>
<binary-origin>release\modules\ext\listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/protobuf-java-util-3.7.0.jar</runtime-relative-path>
<binary-origin>release\modules\ext\protobuf-java-util-3.7.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/commons-collections-3.2.2.jar</runtime-relative-path>
<binary-origin>release\modules\ext\commons-collections-3.2.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/SparseBitSet-1.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/SparseBitSet-1.1.jar</binary-origin>
<binary-origin>release\modules\ext\SparseBitSet-1.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/grpc-grpclb-1.19.0.jar</runtime-relative-path>
<binary-origin>release\modules\ext\grpc-grpclb-1.19.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/batik-svggen-1.6.jar</runtime-relative-path>
<binary-origin>release/modules/ext/batik-svggen-1.6.jar</binary-origin>
<binary-origin>release\modules\ext\batik-svggen-1.6.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/c3p0-0.9.5.jar</runtime-relative-path>
<binary-origin>release/modules/ext/c3p0-0.9.5.jar</binary-origin>
<binary-origin>release\modules\ext\c3p0-0.9.5.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/zookeeper-3.4.6.jar</runtime-relative-path>
<binary-origin>release/modules/ext/zookeeper-3.4.6.jar</binary-origin>
<binary-origin>release\modules\ext\zookeeper-3.4.6.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/commons-csv-1.6.jar</runtime-relative-path>
<binary-origin>release\modules\ext\commons-csv-1.6.jar</binary-origin>
<runtime-relative-path>ext/grpc-alts-1.19.0.jar</runtime-relative-path>
<binary-origin>release\modules\ext\grpc-alts-1.19.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jdom-2.0.5.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jdom-2.0.5.jar</binary-origin>
<binary-origin>release\modules\ext\jdom-2.0.5.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jackson-annotations-2.9.7.jar</runtime-relative-path>
<binary-origin>release\modules\ext\jackson-annotations-2.9.7.jar</binary-origin>
<runtime-relative-path>ext/gson-2.7.jar</runtime-relative-path>
<binary-origin>release\modules\ext\gson-2.7.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/google-api-client-1.27.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/google-api-client-1.27.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/netcdf4-4.5.5.jar</runtime-relative-path>
<binary-origin>release\modules\ext\netcdf4-4.5.5.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/sis-netcdf-0.8.jar</runtime-relative-path>
<binary-origin>release\modules\ext\sis-netcdf-0.8.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/sentiment-analysis-parser-0.1.jar</runtime-relative-path>
<binary-origin>release\modules\ext\sentiment-analysis-parser-0.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/commons-collections4-4.2.jar</runtime-relative-path>
<binary-origin>release\modules\ext\commons-collections4-4.2.jar</binary-origin>
<binary-origin>release\modules\ext\google-api-client-1.27.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/opencensus-contrib-http-util-0.19.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/opencensus-contrib-http-util-0.19.2.jar</binary-origin>
<binary-origin>release\modules\ext\opencensus-contrib-http-util-0.19.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/google-auth-library-oauth2-http-0.15.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/google-auth-library-oauth2-http-0.15.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/juniversalchardet-1.0.3.jar</runtime-relative-path>
<binary-origin>release\modules\ext\juniversalchardet-1.0.3.jar</binary-origin>
<binary-origin>release\modules\ext\google-auth-library-oauth2-http-0.15.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jython-standalone-2.7.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jython-standalone-2.7.0.jar</binary-origin>
<binary-origin>release\modules\ext\jython-standalone-2.7.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jhighlight-1.0.3.jar</runtime-relative-path>
<binary-origin>release\modules\ext\jhighlight-1.0.3.jar</binary-origin>
<runtime-relative-path>ext/commons-lang-2.6.jar</runtime-relative-path>
<binary-origin>release\modules\ext\commons-lang-2.6.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jul-to-slf4j-1.7.25.jar</runtime-relative-path>
<binary-origin>release\modules\ext\jul-to-slf4j-1.7.25.jar</binary-origin>
<runtime-relative-path>ext/jsr305-3.0.2.jar</runtime-relative-path>
<binary-origin>release\modules\ext\jsr305-3.0.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/postgresql-9.4.1211.jre7.jar</runtime-relative-path>
<binary-origin>release/modules/ext/postgresql-9.4.1211.jre7.jar</binary-origin>
<runtime-relative-path>ext/proto-google-common-protos-1.15.0.jar</runtime-relative-path>
<binary-origin>release\modules\ext\proto-google-common-protos-1.15.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/netty-3.7.0.Final.jar</runtime-relative-path>
<binary-origin>release\modules\ext\netty-3.7.0.Final.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/opencensus-contrib-grpc-metrics-0.19.2.jar</runtime-relative-path>
<binary-origin>release\modules\ext\opencensus-contrib-grpc-metrics-0.19.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jai_imageio-1.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jai_imageio-1.1.jar</binary-origin>
<binary-origin>release\modules\ext\jai_imageio-1.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/httpclient-4.5.6.jar</runtime-relative-path>
<binary-origin>release\modules\ext\httpclient-4.5.6.jar</binary-origin>
<runtime-relative-path>ext/postgresql-9.4.1211.jre7.jar</runtime-relative-path>
<binary-origin>release\modules\ext\postgresql-9.4.1211.jre7.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/junit-3.8.1.jar</runtime-relative-path>
<binary-origin>release\modules\ext\junit-3.8.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/curator-client-2.8.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/curator-client-2.8.0.jar</binary-origin>
<binary-origin>release\modules\ext\curator-client-2.8.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/fontbox-2.0.13.jar</runtime-relative-path>
<binary-origin>release\modules\ext\fontbox-2.0.13.jar</binary-origin>
<runtime-relative-path>ext/grpc-core-1.19.0.jar</runtime-relative-path>
<binary-origin>release\modules\ext\grpc-core-1.19.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/javax.ws.rs-api-2.0.jar</runtime-relative-path>
<binary-origin>release\modules\ext\javax.ws.rs-api-2.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/icepdf-core-6.2.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/icepdf-core-6.2.2.jar</binary-origin>
<binary-origin>release\modules\ext\icepdf-core-6.2.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/activemq-all-5.11.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/activemq-all-5.11.1.jar</binary-origin>
<binary-origin>release\modules\ext\activemq-all-5.11.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/google-cloud-core-http-1.70.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/google-cloud-core-http-1.70.0.jar</binary-origin>
<binary-origin>release\modules\ext\google-cloud-core-http-1.70.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/Rejistry-1.1-SNAPSHOT.jar</runtime-relative-path>
<binary-origin>release/modules/ext/Rejistry-1.1-SNAPSHOT.jar</binary-origin>
<binary-origin>release\modules\ext\Rejistry-1.1-SNAPSHOT.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/dec-0.1.2.jar</runtime-relative-path>
<binary-origin>release\modules\ext\dec-0.1.2.jar</binary-origin>
<runtime-relative-path>ext/commons-beanutils-1.9.2.jar</runtime-relative-path>
<binary-origin>release\modules\ext\commons-beanutils-1.9.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/batik-dom-1.6.jar</runtime-relative-path>
<binary-origin>release/modules/ext/batik-dom-1.6.jar</binary-origin>
<binary-origin>release\modules\ext\batik-dom-1.6.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/google-http-client-jackson2-1.29.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/google-http-client-jackson2-1.29.0.jar</binary-origin>
<binary-origin>release\modules\ext\google-http-client-jackson2-1.29.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/threetenbp-1.3.3.jar</runtime-relative-path>
<binary-origin>release/modules/ext/threetenbp-1.3.3.jar</binary-origin>
<binary-origin>release\modules\ext\threetenbp-1.3.3.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/google-cloud-translate-1.70.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/google-cloud-translate-1.70.0.jar</binary-origin>
<binary-origin>release\modules\ext\google-cloud-translate-1.70.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/grpc-stub-1.19.0.jar</runtime-relative-path>
<binary-origin>release\modules\ext\grpc-stub-1.19.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/google-oauth-client-1.28.0.jar</runtime-relative-path>
<binary-origin>release\modules\ext\google-oauth-client-1.28.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/sevenzipjbinding-AllPlatforms.jar</runtime-relative-path>
<binary-origin>release/modules/ext/sevenzipjbinding-AllPlatforms.jar</binary-origin>
<binary-origin>release\modules\ext\sevenzipjbinding-AllPlatforms.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jutf7-1.0.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jutf7-1.0.0.jar</binary-origin>
<binary-origin>release\modules\ext\jutf7-1.0.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/batik-awt-util-1.6.jar</runtime-relative-path>
<binary-origin>release/modules/ext/batik-awt-util-1.6.jar</binary-origin>
<binary-origin>release\modules\ext\batik-awt-util-1.6.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/google-api-services-translate-v2-rev20170525-1.27.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/google-api-services-translate-v2-rev20170525-1.27.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/webp-imageio-sejda-0.1.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/webp-imageio-sejda-0.1.0.jar</binary-origin>
<binary-origin>release\modules\ext\google-api-services-translate-v2-rev20170525-1.27.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/icepdf-viewer-6.2.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/icepdf-viewer-6.2.2.jar</binary-origin>
<binary-origin>release\modules\ext\icepdf-viewer-6.2.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/bcmail-jdk15on-1.60.jar</runtime-relative-path>
<binary-origin>release\modules\ext\bcmail-jdk15on-1.60.jar</binary-origin>
<runtime-relative-path>ext/webp-imageio-sejda-0.1.0.jar</runtime-relative-path>
<binary-origin>release\modules\ext\webp-imageio-sejda-0.1.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/vorbis-java-tika-0.8.jar</runtime-relative-path>
<binary-origin>release\modules\ext\vorbis-java-tika-0.8.jar</binary-origin>
<runtime-relative-path>ext/grpc-netty-shaded-1.19.0.jar</runtime-relative-path>
<binary-origin>release\modules\ext\grpc-netty-shaded-1.19.0.jar</binary-origin>
</class-path-extension>
</data>
</configuration>

View File

@ -70,7 +70,7 @@ 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.datasourcesummary.DataSourceSummaryAction;
import org.sleuthkit.autopsy.datasourcesummary.ui.DataSourceSummaryAction;
import org.sleuthkit.autopsy.casemodule.events.AddingDataSourceEvent;
import org.sleuthkit.autopsy.casemodule.events.AddingDataSourceFailedEvent;
import org.sleuthkit.autopsy.casemodule.events.BlackBoardArtifactTagAddedEvent;
@ -141,6 +141,7 @@ import org.sleuthkit.datamodel.TskUnsupportedSchemaVersionException;
*/
public class Case {
private static final String CASE_TEMP_DIR = Case.class.getSimpleName();
private static final int CASE_LOCK_TIMEOUT_MINS = 1;
private static final int CASE_RESOURCES_LOCK_TIMEOUT_HOURS = 1;
private static final String SINGLE_USER_CASE_DB_NAME = "autopsy.db";
@ -150,7 +151,6 @@ public class Case {
private static final String LOG_FOLDER = "Log"; //NON-NLS
private static final String REPORTS_FOLDER = "Reports"; //NON-NLS
private static final String CONFIG_FOLDER = "Config"; // NON-NLS
private static final String TEMP_FOLDER = "Temp"; //NON-NLS
private static final String MODULE_FOLDER = "ModuleOutput"; //NON-NLS
private static final String CASE_ACTION_THREAD_NAME = "%s-case-action";
private static final String CASE_RESOURCES_THREAD_NAME = "%s-manage-case-resources";
@ -988,11 +988,6 @@ public class Case {
throw new CaseActionException(NbBundle.getMessage(Case.class, "Case.createCaseDir.exception.cantCreateCaseDir", logsDir));
}
Path tempDir = Paths.get(caseDirPath, hostPathComponent, TEMP_FOLDER);
if (!tempDir.toFile().mkdirs()) {
throw new CaseActionException(NbBundle.getMessage(Case.class, "Case.createCaseDir.exception.cantCreateCaseDir", tempDir));
}
Path cacheDir = Paths.get(caseDirPath, hostPathComponent, CACHE_FOLDER);
if (!cacheDir.toFile().mkdirs()) {
throw new CaseActionException(NbBundle.getMessage(Case.class, "Case.createCaseDir.exception.cantCreateCaseDir", cacheDir));
@ -1196,25 +1191,6 @@ public class Case {
}
}
/**
* Empties the temp subdirectory for the current case.
*/
private static void clearTempSubDir(String tempSubDirPath) {
File tempFolder = new File(tempSubDirPath);
if (tempFolder.isDirectory()) {
File[] files = tempFolder.listFiles();
if (files.length > 0) {
for (File file : files) {
if (file.isDirectory()) {
FileUtil.deleteDir(file);
} else {
file.delete();
}
}
}
}
}
/**
* Gets the case database.
*
@ -1352,7 +1328,16 @@ public class Case {
* @return The temp subdirectory path.
*/
public String getTempDirectory() {
return getOrCreateSubdirectory(TEMP_FOLDER);
// get temp folder scoped to the combination of case name and timestamp
// provided by getName()
Path path = Paths.get(UserPreferences.getAppTempDirectory(), CASE_TEMP_DIR, getName());
File f = path.toFile();
// verify that the folder exists
if (!f.exists()) {
f.mkdirs();
}
return path.toAbsolutePath().toString();
}
/**
@ -1563,9 +1548,9 @@ public class Case {
*
* This should not be called from the event dispatch thread (EDT)
*
* @param newTag The added ContentTag.
* @param deletedTagList List of ContentTags that were removed as a result
* of the addition of newTag.
* @param newTag The added ContentTag.
* @param deletedTagList List of ContentTags that were removed as a result
* of the addition of newTag.
*/
public void notifyContentTagAdded(ContentTag newTag, List<ContentTag> deletedTagList) {
eventPublisher.publish(new ContentTagAddedEvent(newTag, deletedTagList));
@ -1628,9 +1613,9 @@ public class Case {
*
* This should not be called from the event dispatch thread (EDT)
*
* @param newTag The added ContentTag.
* @param removedTagList List of ContentTags that were removed as a result
* of the addition of newTag.
* @param newTag The added ContentTag.
* @param removedTagList List of ContentTags that were removed as a result
* of the addition of newTag.
*/
public void notifyBlackBoardArtifactTagAdded(BlackboardArtifactTag newTag, List<BlackboardArtifactTag> removedTagList) {
eventPublisher.publish(new BlackBoardArtifactTagAddedEvent(newTag, removedTagList));
@ -2120,7 +2105,7 @@ public class Case {
*/
private void openFileSystems(List<Image> images) throws TskCoreException, InterruptedException {
byte[] tempBuff = new byte[512];
for (Image image : images) {
String imageStr = image.getName();
@ -2144,12 +2129,12 @@ public class Case {
if (images == null) {
return;
}
if (images.size() > MAX_IMAGE_THRESHOLD) {
// If we have a large number of images, don't try to preload anything
logger.log(
Level.INFO,
String.format("Skipping background load of file systems due to large number of images in case (%d)", images.size()));
Level.INFO,
String.format("Skipping background load of file systems due to large number of images in case (%d)", images.size()));
return;
}
@ -2396,7 +2381,7 @@ public class Case {
* Clear the temp subdirectory of the case directory.
*/
progressIndicator.progress(Bundle.Case_progressMessage_clearingTempDirectory());
Case.clearTempSubDir(this.getTempDirectory());
FileUtil.deleteDir(new File(this.getTempDirectory()));
}
/**
@ -2506,7 +2491,7 @@ public class Case {
* specific to this case.
*
* @param progressIndicator A progress indicator.
* @param isNewCase True if case is new
* @param isNewCase True if case is new
*
* @throws CaseActionException If there is a problem completing the
* operation. The exception will have a
@ -2764,6 +2749,11 @@ public class Case {
caseDb.close();
}
/**
* Delete files from temp directory if any exist.
*/
deleteTempfilesFromCaseDirectory(progressIndicator);
/*
* Switch the log directory.
*/

View File

@ -31,7 +31,9 @@ import javax.swing.JOptionPane;
import javax.swing.event.ListSelectionEvent;
import javax.swing.table.AbstractTableModel;
import org.openide.util.NbBundle.Messages;
import static org.sleuthkit.autopsy.casemodule.Case.Events.CURRENT_CASE;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.events.AutopsyEvent;
import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.datamodel.IngestJobInfo;
import org.sleuthkit.datamodel.IngestModuleInfo;
@ -47,6 +49,8 @@ public final class IngestJobInfoPanel extends javax.swing.JPanel {
private static final Logger logger = Logger.getLogger(IngestJobInfoPanel.class.getName());
private static final Set<IngestManager.IngestJobEvent> INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.STARTED, IngestManager.IngestJobEvent.CANCELLED, IngestManager.IngestJobEvent.COMPLETED);
private static final Set<Case.Events> CASE_EVENTS_OF_INTEREST = EnumSet.of(Case.Events.CURRENT_CASE);
private List<IngestJobInfo> ingestJobs;
private final List<IngestJobInfo> ingestJobsForSelectedDataSource = new ArrayList<>();
private IngestJobTableModel ingestJobTableModel = new IngestJobTableModel();
@ -79,6 +83,16 @@ public final class IngestJobInfoPanel extends javax.swing.JPanel {
refresh();
}
});
Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, (PropertyChangeEvent evt) -> {
if (!(evt instanceof AutopsyEvent) || (((AutopsyEvent) evt).getSourceType() != AutopsyEvent.SourceType.LOCAL)) {
return;
}
if (CURRENT_CASE == Case.Events.valueOf(evt.getPropertyName())) {
refresh();
}
});
}
/**
@ -110,9 +124,15 @@ public final class IngestJobInfoPanel extends javax.swing.JPanel {
*/
private void refresh() {
try {
SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
this.ingestJobs = skCase.getIngestJobs();
setDataSource(selectedDataSource);
if (Case.isCaseOpen()) {
SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
this.ingestJobs = skCase.getIngestJobs();
setDataSource(selectedDataSource);
} else {
this.ingestJobs = new ArrayList<>();
setDataSource(null);
}
} catch (TskCoreException | NoCurrentCaseException ex) {
logger.log(Level.SEVERE, "Failed to load ingest jobs.", ex);
JOptionPane.showMessageDialog(this, Bundle.IngestJobInfoPanel_loadIngestJob_error_text(), Bundle.IngestJobInfoPanel_loadIngestJob_error_title(), JOptionPane.ERROR_MESSAGE);

View File

@ -0,0 +1,66 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2020 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.casemodule;
import java.io.File;
import java.util.logging.Level;
import org.apache.commons.lang.StringUtils;
import org.openide.modules.ModuleInstall;
import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.autopsy.coreutils.FileUtil;
import org.sleuthkit.autopsy.coreutils.Logger;
/**
* Installer for casemodule that cleans out user specified temp directory.
*/
public final class Installer extends ModuleInstall {
private static final Logger logger = Logger.getLogger(Installer.class.getName());
private static final long serialVersionUID = 1L;
private static Installer instance;
public synchronized static Installer getDefault() {
if (instance == null) {
instance = new Installer();
}
return instance;
}
private Installer() {
}
@Override
public void restored() {
String tempDirStr = null;
try {
tempDirStr = UserPreferences.getAppTempDirectory();
if (StringUtils.isNotBlank(tempDirStr)) {
File tempDir = new File(tempDirStr);
if (tempDir.exists()) {
FileUtil.deleteDir(tempDir);
}
}
} catch (Exception ex) {
// This is a firewall exception should any issues occur
// during temp directory deletion
logger.log(Level.WARNING, "There was an error while cleaning up temp directory: " + (tempDirStr == null ? "<null>" : tempDirStr), ex);
}
}
}

View File

@ -24,6 +24,7 @@ import java.util.logging.Level;
import org.netbeans.spi.sendopts.OptionProcessor;
import org.openide.util.Lookup;
import org.sleuthkit.autopsy.commandlineingest.CommandLineIngestManager;
import org.sleuthkit.autopsy.commandlineingest.CommandLineOpenCaseManager;
import org.sleuthkit.autopsy.commandlineingest.CommandLineOptionProcessor;
import org.sleuthkit.autopsy.commandlineingest.CommandLineStartupWindow;
import org.sleuthkit.autopsy.coreutils.Logger;
@ -58,6 +59,12 @@ public class StartupWindowProvider implements StartupWindowInterface {
private void init() {
if (startupWindowToUse == null) {
if (openCaseInUI()) {
new CommandLineOpenCaseManager().start();
return;
}
// first check whether we are running from command line
if (isRunningFromCommandLine()) {
// Autopsy is running from command line
@ -131,6 +138,28 @@ public class StartupWindowProvider implements StartupWindowInterface {
return false;
}
/**
* Checks whether Autopsy was launched from the command line with the option
* to open an existing case.
*
* @return True if opening an existing case.
*/
private boolean openCaseInUI() {
// first look up all OptionProcessors and see if running from command line option is set
Collection<? extends OptionProcessor> optionProcessors = Lookup.getDefault().lookupAll(OptionProcessor.class);
Iterator<? extends OptionProcessor> optionsIterator = optionProcessors.iterator();
while (optionsIterator.hasNext()) {
// find CommandLineOptionProcessor
OptionProcessor processor = optionsIterator.next();
if ((processor instanceof OpenFromArguments)) {
// check if we are running from command line
String arg = ((OpenFromArguments) processor).getDefaultArg();
return arg != null && !arg.isEmpty();
}
}
return false;
}
@Override
public void open() {
if (startupWindowToUse != null) {

View File

@ -1,366 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019 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.casemodule.datasourcesummary;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Set;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.TskData;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.DataSource;
/**
* Utilities for getting information about a data source or all data sources
* from the case database.
*/
final class DataSourceInfoUtilities {
private static final Logger logger = Logger.getLogger(DataSourceInfoUtilities.class.getName());
/**
* Get a map containing the TSK_DATA_SOURCE_USAGE description attributes
* associated with each data source in the current case.
*
* @return Collection which maps datasource id to a String which displays a
* comma seperated list of values of data source usage types
* expected to be in the datasource
*/
static Map<Long, String> getDataSourceTypes() {
try {
SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
List<BlackboardArtifact> listOfArtifacts = skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_DATA_SOURCE_USAGE);
Map<Long, String> typeMap = new HashMap<>();
for (BlackboardArtifact typeArtifact : listOfArtifacts) {
BlackboardAttribute descriptionAttr = typeArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DESCRIPTION));
if (typeArtifact.getDataSource() != null && descriptionAttr != null) {
long dsId = typeArtifact.getDataSource().getId();
String type = typeMap.get(typeArtifact.getDataSource().getId());
if (type == null) {
type = descriptionAttr.getValueString();
} else {
type = type + ", " + descriptionAttr.getValueString();
}
typeMap.put(dsId, type);
}
}
return typeMap;
} catch (TskCoreException | NoCurrentCaseException ex) {
logger.log(Level.WARNING, "Unable to get types of files for all datasources, providing empty results", ex);
return Collections.emptyMap();
}
}
/**
* Get a map containing the number of files in each data source in the
* current case.
*
* @return Collection which maps datasource id to a count for the number of
* files in the datasource, will only contain entries for
* datasources which have at least 1 file
*/
static Map<Long, Long> getCountsOfFiles() {
try {
final String countFilesQuery = "data_source_obj_id, COUNT(*) AS value"
+ " FROM tsk_files WHERE type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType()
+ " AND dir_type<>" + TskData.TSK_FS_NAME_TYPE_ENUM.VIRT_DIR.getValue()
+ " AND name<>'' GROUP BY data_source_obj_id"; //NON-NLS
return getValuesMap(countFilesQuery);
} catch (TskCoreException | NoCurrentCaseException ex) {
logger.log(Level.WARNING, "Unable to get counts of files for all datasources, providing empty results", ex);
return Collections.emptyMap();
}
}
/**
* Get a map containing the number of artifacts in each data source in the
* current case.
*
* @return Collection which maps datasource id to a count for the number of
* artifacts in the datasource, will only contain entries for
* datasources which have at least 1 artifact
*/
static Map<Long, Long> getCountsOfArtifacts() {
try {
final String countArtifactsQuery = "data_source_obj_id, COUNT(*) AS value"
+ " FROM blackboard_artifacts WHERE review_status_id !=" + BlackboardArtifact.ReviewStatus.REJECTED.getID()
+ " GROUP BY data_source_obj_id"; //NON-NLS
return getValuesMap(countArtifactsQuery);
} catch (TskCoreException | NoCurrentCaseException ex) {
logger.log(Level.WARNING, "Unable to get counts of artifacts for all datasources, providing empty results", ex);
return Collections.emptyMap();
}
}
/**
* Get a map containing the number of tags which have been applied in each
* data source in the current case. Not necessarily the same as the number
* of items tagged, as an item can have any number of tags.
*
* @return Collection which maps datasource id to a count for the number of
* tags which have been applied in the datasource, will only contain
* entries for datasources which have at least 1 item tagged.
*/
static Map<Long, Long> getCountsOfTags() {
try {
final String countFileTagsQuery = "data_source_obj_id, COUNT(*) AS value"
+ " FROM content_tags as content_tags, tsk_files as tsk_files"
+ " WHERE content_tags.obj_id = tsk_files.obj_id"
+ " GROUP BY data_source_obj_id"; //NON-NLS
//new hashmap so it can be modifiable
Map<Long, Long> tagCountMap = new HashMap<>(getValuesMap(countFileTagsQuery));
final String countArtifactTagsQuery = "data_source_obj_id, COUNT(*) AS value"
+ " FROM blackboard_artifact_tags as artifact_tags, blackboard_artifacts AS arts"
+ " WHERE artifact_tags.artifact_id = arts.artifact_id"
+ " GROUP BY data_source_obj_id"; //NON-NLS
//combine the results from the count artifact tags query into the copy of the mapped results from the count file tags query
getValuesMap(countArtifactTagsQuery).forEach((key, value) -> tagCountMap.merge(key, value, (value1, value2) -> value1 + value2));
return tagCountMap;
} catch (TskCoreException | NoCurrentCaseException ex) {
logger.log(Level.WARNING, "Unable to get counts of tags for all datasources, providing empty results", ex);
return Collections.emptyMap();
}
}
/**
* Get a map containing the names of operating systems joined in a comma
* seperated list to the Data Source they exist on in the current case. No
* item will exist in the map for data sources which do not contain
* TS_OS_INFO artifacts which have a program name.
*
* @return Collection which maps datasource id to a String which is a comma
* seperated list of Operating system names found on the data
* source.
*/
static Map<Long, String> getOperatingSystems() {
Map<Long, String> osDetailMap = new HashMap<>();
try {
SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
ArrayList<BlackboardArtifact> osInfoArtifacts = skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_OS_INFO);
for (BlackboardArtifact osInfo : osInfoArtifacts) {
BlackboardAttribute programName = osInfo.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME));
if (programName != null) {
String currentOsString = osDetailMap.get(osInfo.getDataSource().getId());
if (currentOsString == null || currentOsString.isEmpty()) {
currentOsString = programName.getValueString();
} else {
currentOsString = currentOsString + ", " + programName.getValueString();
}
osDetailMap.put(osInfo.getDataSource().getId(), currentOsString);
}
}
} catch (TskCoreException | NoCurrentCaseException ex) {
logger.log(Level.SEVERE, "Failed to load OS info artifacts.", ex);
}
return osDetailMap;
}
/**
* Get the number of files in the case database for the current data source
* which have the specified mimetypes.
*
* @param currentDataSource the data source which we are finding a file
* count
*
* @param setOfMimeTypes the set of mime types which we are finding the
* number of occurences of
*
* @return a Long value which represents the number of occurrences of the
* specified mime types in the current case for the specified data
* source, null if no count was retrieved
*/
static Long getCountOfFilesForMimeTypes(DataSource currentDataSource, Set<String> setOfMimeTypes) {
if (currentDataSource != null) {
try {
String inClause = String.join("', '", setOfMimeTypes);
SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
return skCase.countFilesWhere("data_source_obj_id=" + currentDataSource.getId()
+ " AND type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType()
+ " AND dir_type<>" + TskData.TSK_FS_NAME_TYPE_ENUM.VIRT_DIR.getValue()
+ " AND mime_type IN ('" + inClause + "')"
+ " AND name<>''");
} catch (TskCoreException | NoCurrentCaseException ex) {
logger.log(Level.WARNING, "Unable to get count of files for specified mime types", ex);
//unable to get count of files for the specified mimetypes cell will be displayed as empty
}
}
return null;
}
/**
* Get a map containing the number of unallocated files in each data source
* in the current case.
*
* @return Collection which maps datasource id to a count for the number of
* unallocated files in the datasource, will only contain entries
* for datasources which have at least 1 unallocated file
*/
static Map<Long, Long> getCountsOfUnallocatedFiles() {
try {
final String countUnallocatedFilesQuery = "data_source_obj_id, COUNT(*) AS value"
+ " FROM tsk_files WHERE type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType()
+ " AND dir_type<>" + TskData.TSK_FS_NAME_TYPE_ENUM.VIRT_DIR.getValue()
+ " AND dir_flags=" + TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC.getValue()
+ " AND name<>'' GROUP BY data_source_obj_id"; //NON-NLS
return getValuesMap(countUnallocatedFilesQuery);
} catch (TskCoreException | NoCurrentCaseException ex) {
logger.log(Level.WARNING, "Unable to get counts of unallocated files for all datasources, providing empty results", ex);
return Collections.emptyMap();
}
}
/**
* Get a map containing the total size of unallocated files in each data
* source in the current case.
*
* @return Collection which maps datasource id to a total size in bytes of
* unallocated files in the datasource, will only contain entries
* for datasources which have at least 1 unallocated file
*/
static Map<Long, Long> getSizeOfUnallocatedFiles() {
try {
final String countUnallocatedFilesQuery = "data_source_obj_id, sum(size) AS value"
+ " FROM tsk_files WHERE type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType()
+ " AND dir_type<>" + TskData.TSK_FS_NAME_TYPE_ENUM.VIRT_DIR.getValue()
+ " AND dir_flags=" + TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC.getValue()
+ " AND name<>'' GROUP BY data_source_obj_id"; //NON-NLS
return getValuesMap(countUnallocatedFilesQuery);
} catch (TskCoreException | NoCurrentCaseException ex) {
logger.log(Level.WARNING, "Unable to get size of unallocated files for all datasources, providing empty results", ex);
return Collections.emptyMap();
}
}
/**
* Get a map containing the number of directories in each data source in the
* current case.
*
* @return Collection which maps datasource id to a count for the number of
* directories in the datasource, will only contain entries for
* datasources which have at least 1 directory
*/
static Map<Long, Long> getCountsOfDirectories() {
try {
final String countDirectoriesQuery = "data_source_obj_id, COUNT(*) AS value"
+ " FROM tsk_files WHERE type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType()
+ " AND dir_type<>" + TskData.TSK_FS_NAME_TYPE_ENUM.VIRT_DIR.getValue()
+ " AND meta_type=" + TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR.getValue()
+ " AND name<>'' GROUP BY data_source_obj_id"; //NON-NLS
return getValuesMap(countDirectoriesQuery);
} catch (TskCoreException | NoCurrentCaseException ex) {
logger.log(Level.WARNING, "Unable to get counts of directories for all datasources, providing empty results", ex);
return Collections.emptyMap();
}
}
/**
* Get a map containing the number of slack files in each data source in the
* current case.
*
* @return Collection which maps datasource id to a count for the number of
* slack files in the datasource, will only contain entries for
* datasources which have at least 1 slack file
*/
static Map<Long, Long> getCountsOfSlackFiles() {
try {
final String countSlackFilesQuery = "data_source_obj_id, COUNT(*) AS value"
+ " FROM tsk_files WHERE type=" + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.getFileType()
+ " AND dir_type<>" + TskData.TSK_FS_NAME_TYPE_ENUM.VIRT_DIR.getValue()
+ " AND name<>'' GROUP BY data_source_obj_id"; //NON-NLS
return getValuesMap(countSlackFilesQuery);
} catch (TskCoreException | NoCurrentCaseException ex) {
logger.log(Level.WARNING, "Unable to get counts of slack files for all datasources, providing empty results", ex);
return Collections.emptyMap();
}
}
/**
* Get a map containing maps which map artifact type to the number of times
* it exosts in each data source in the current case.
*
* @return Collection which maps datasource id to maps of artifact display
* name to number of occurences in the datasource, will only contain
* entries for artifacts which have at least one occurence in the
* data source.
*/
static Map<Long, Map<String, Long>> getCountsOfArtifactsByType() {
try {
final String countArtifactsQuery = "blackboard_artifacts.data_source_obj_id, blackboard_artifact_types.display_name AS label, COUNT(*) AS value"
+ " FROM blackboard_artifacts, blackboard_artifact_types"
+ " WHERE blackboard_artifacts.artifact_type_id = blackboard_artifact_types.artifact_type_id"
+ " GROUP BY blackboard_artifacts.data_source_obj_id, blackboard_artifact_types.display_name";
return getLabeledValuesMap(countArtifactsQuery);
} catch (TskCoreException | NoCurrentCaseException ex) {
logger.log(Level.WARNING, "Unable to get counts of all artifact types for all datasources, providing empty results", ex);
return Collections.emptyMap();
}
}
/**
* Helper method to execute a select query with a
* DataSourceLabeledValueCallback.
*
* @param query the portion of the query which should follow the SELECT
*
* @return a map of datasource object IDs to maps of String labels to the
* values associated with them.
*
* @throws TskCoreException
* @throws NoCurrentCaseException
*/
private static Map<Long, Map<String, Long>> getLabeledValuesMap(String query) throws TskCoreException, NoCurrentCaseException {
SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
DataSourceLabeledValueCallback callback = new DataSourceLabeledValueCallback();
skCase.getCaseDbAccessManager().select(query, callback);
return callback.getMapOfLabeledValues();
}
/**
* Helper method to execute a select query with a
* DataSourceSingleValueCallback.
*
* @param query the portion of the query which should follow the SELECT
*
* @return a map of datasource object ID to a value of type Long
*
* @throws TskCoreException
* @throws NoCurrentCaseException
*/
private static Map<Long, Long> getValuesMap(String query) throws TskCoreException, NoCurrentCaseException {
SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
DataSourceSingleValueCallback callback = new DataSourceSingleValueCallback();
skCase.getCaseDbAccessManager().select(query, callback);
return callback.getMapOfValues();
}
/**
* Empty private constructor
*/
private DataSourceInfoUtilities() {
}
}

View File

@ -1,139 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Component id="fileCountsByMimeTypeScrollPane" linkSize="1" pref="140" max="32767" attributes="0"/>
<Component id="byMimeTypeLabel" max="32767" attributes="0"/>
</Group>
<EmptySpace type="separate" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="byCategoryLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="fileCountsByCategoryScrollPane" linkSize="1" alignment="0" min="-2" pref="82" max="-2" attributes="0"/>
</Group>
<EmptySpace type="separate" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jLabel1" min="-2" pref="79" max="-2" attributes="0"/>
<Component id="artifactCountsScrollPane" min="-2" pref="244" max="-2" attributes="0"/>
</Group>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="byMimeTypeLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="byCategoryLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jLabel1" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="artifactCountsScrollPane" alignment="1" pref="0" max="32767" attributes="0"/>
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="fileCountsByMimeTypeScrollPane" linkSize="2" min="-2" pref="107" max="-2" attributes="0"/>
<Component id="fileCountsByCategoryScrollPane" linkSize="2" min="-2" pref="86" max="-2" attributes="0"/>
</Group>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JScrollPane" name="fileCountsByMimeTypeScrollPane">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTable" name="fileCountsByMimeTypeTable">
<Properties>
<Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="filesByMimeTypeTableModel" type="code"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JLabel" name="byMimeTypeLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourceSummary/Bundle.properties" key="DataSourceSummaryCountsPanel.byMimeTypeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Container class="javax.swing.JScrollPane" name="fileCountsByCategoryScrollPane">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTable" name="fileCountsByCategoryTable">
<Properties>
<Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="filesByCategoryTableModel" type="code"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JLabel" name="byCategoryLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourceSummary/Bundle.properties" key="DataSourceSummaryCountsPanel.byCategoryLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel1">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourceSummary/Bundle.properties" key="DataSourceSummaryCountsPanel.jLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Container class="javax.swing.JScrollPane" name="artifactCountsScrollPane">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTable" name="artifactCountsTable">
<Properties>
<Property name="autoCreateRowSorter" type="boolean" value="true"/>
<Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.editors2.TableModelEditor">
<Table columnCount="2" rowCount="0">
<Column editable="false" title="Result Type" type="java.lang.Object"/>
<Column editable="false" title="Count" type="java.lang.Object"/>
</Table>
</Property>
</Properties>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Form>

View File

@ -1,395 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019 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.casemodule.datasourcesummary;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.sleuthkit.autopsy.coreutils.Logger;
import javax.swing.JLabel;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.coreutils.FileTypeUtils;
import org.sleuthkit.datamodel.DataSource;
/**
* Panel for displaying summary information on the known files present in the
* specified DataSource
*/
class DataSourceSummaryCountsPanel extends javax.swing.JPanel {
private static final long serialVersionUID = 1L;
private FilesByMimeTypeTableModel filesByMimeTypeTableModel = new FilesByMimeTypeTableModel(null);
private FilesByCategoryTableModel filesByCategoryTableModel = new FilesByCategoryTableModel(null);
private static final Logger logger = Logger.getLogger(DataSourceSummaryCountsPanel.class.getName());
private final Map<Long, Long> allFilesCountsMap;
private final Map<Long, Long> slackFilesCountsMap;
private final Map<Long, Long> directoriesCountsMap;
private final Map<Long, Long> unallocatedFilesCountsMap;
private final Map<Long, Map<String, Long>> artifactsByTypeCountsMap;
private final DefaultTableCellRenderer rightAlignedRenderer = new DefaultTableCellRenderer();
/**
* Creates new form DataSourceSummaryCountsPanel
*/
DataSourceSummaryCountsPanel(Map<Long, Long> fileCountsMap) {
this.allFilesCountsMap = fileCountsMap;
this.slackFilesCountsMap = DataSourceInfoUtilities.getCountsOfSlackFiles();
this.directoriesCountsMap = DataSourceInfoUtilities.getCountsOfDirectories();
this.unallocatedFilesCountsMap = DataSourceInfoUtilities.getCountsOfUnallocatedFiles();
this.artifactsByTypeCountsMap = DataSourceInfoUtilities.getCountsOfArtifactsByType();
rightAlignedRenderer.setHorizontalAlignment(JLabel.RIGHT);
initComponents();
fileCountsByMimeTypeTable.getTableHeader().setReorderingAllowed(false);
fileCountsByCategoryTable.getTableHeader().setReorderingAllowed(false);
}
/**
* Specify the DataSource to display file information for
*
* @param selectedDataSource the DataSource to display file information for
*/
void updateCountsTableData(DataSource selectedDataSource) {
filesByMimeTypeTableModel = new FilesByMimeTypeTableModel(selectedDataSource);
fileCountsByMimeTypeTable.setModel(filesByMimeTypeTableModel);
fileCountsByMimeTypeTable.getColumnModel().getColumn(1).setCellRenderer(rightAlignedRenderer);
fileCountsByMimeTypeTable.getColumnModel().getColumn(0).setPreferredWidth(130);
filesByCategoryTableModel = new FilesByCategoryTableModel(selectedDataSource);
fileCountsByCategoryTable.setModel(filesByCategoryTableModel);
fileCountsByCategoryTable.getColumnModel().getColumn(1).setCellRenderer(rightAlignedRenderer);
fileCountsByCategoryTable.getColumnModel().getColumn(0).setPreferredWidth(130);
updateArtifactCounts(selectedDataSource);
this.repaint();
}
/**
* Helper method to update the artifact specific counts by clearing the
* table and adding counts for the artifacts which exist in the selected
* data source.
*
* @param selectedDataSource the data source to display artifact counts for
*/
private void updateArtifactCounts(DataSource selectedDataSource) {
((DefaultTableModel) artifactCountsTable.getModel()).setRowCount(0);
if (selectedDataSource != null && artifactsByTypeCountsMap.get(selectedDataSource.getId()) != null) {
Map<String, Long> artifactCounts = artifactsByTypeCountsMap.get(selectedDataSource.getId());
for (String key : artifactCounts.keySet()) {
((DefaultTableModel) artifactCountsTable.getModel()).addRow(new Object[]{key, artifactCounts.get(key)});
}
}
artifactCountsTable.getColumnModel().getColumn(0).setPreferredWidth(230);
artifactCountsTable.getColumnModel().getColumn(1).setCellRenderer(rightAlignedRenderer);
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
fileCountsByMimeTypeScrollPane = new javax.swing.JScrollPane();
fileCountsByMimeTypeTable = new javax.swing.JTable();
byMimeTypeLabel = new javax.swing.JLabel();
fileCountsByCategoryScrollPane = new javax.swing.JScrollPane();
fileCountsByCategoryTable = new javax.swing.JTable();
byCategoryLabel = new javax.swing.JLabel();
jLabel1 = new javax.swing.JLabel();
artifactCountsScrollPane = new javax.swing.JScrollPane();
artifactCountsTable = new javax.swing.JTable();
fileCountsByMimeTypeTable.setModel(filesByMimeTypeTableModel);
fileCountsByMimeTypeScrollPane.setViewportView(fileCountsByMimeTypeTable);
org.openide.awt.Mnemonics.setLocalizedText(byMimeTypeLabel, org.openide.util.NbBundle.getMessage(DataSourceSummaryCountsPanel.class, "DataSourceSummaryCountsPanel.byMimeTypeLabel.text")); // NOI18N
fileCountsByCategoryTable.setModel(filesByCategoryTableModel);
fileCountsByCategoryScrollPane.setViewportView(fileCountsByCategoryTable);
org.openide.awt.Mnemonics.setLocalizedText(byCategoryLabel, org.openide.util.NbBundle.getMessage(DataSourceSummaryCountsPanel.class, "DataSourceSummaryCountsPanel.byCategoryLabel.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(DataSourceSummaryCountsPanel.class, "DataSourceSummaryCountsPanel.jLabel1.text")); // NOI18N
artifactCountsTable.setAutoCreateRowSorter(true);
artifactCountsTable.setModel(new javax.swing.table.DefaultTableModel(
new Object [][] {
},
new String [] {
"Result Type", "Count"
}
) {
boolean[] canEdit = new boolean [] {
false, false
};
public boolean isCellEditable(int rowIndex, int columnIndex) {
return canEdit [columnIndex];
}
});
artifactCountsScrollPane.setViewportView(artifactCountsTable);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(fileCountsByMimeTypeScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 140, Short.MAX_VALUE)
.addComponent(byMimeTypeLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGap(18, 18, 18)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(byCategoryLabel)
.addComponent(fileCountsByCategoryScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 82, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(18, 18, 18)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 79, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(artifactCountsScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 244, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {fileCountsByCategoryScrollPane, fileCountsByMimeTypeScrollPane});
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(byMimeTypeLabel)
.addComponent(byCategoryLabel)
.addComponent(jLabel1))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(artifactCountsScrollPane, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(fileCountsByMimeTypeScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 107, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(fileCountsByCategoryScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 86, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(0, 0, Short.MAX_VALUE)))
.addContainerGap())
);
layout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {fileCountsByCategoryScrollPane, fileCountsByMimeTypeScrollPane});
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JScrollPane artifactCountsScrollPane;
private javax.swing.JTable artifactCountsTable;
private javax.swing.JLabel byCategoryLabel;
private javax.swing.JLabel byMimeTypeLabel;
private javax.swing.JScrollPane fileCountsByCategoryScrollPane;
private javax.swing.JTable fileCountsByCategoryTable;
private javax.swing.JScrollPane fileCountsByMimeTypeScrollPane;
private javax.swing.JTable fileCountsByMimeTypeTable;
private javax.swing.JLabel jLabel1;
// End of variables declaration//GEN-END:variables
/**
* Table model for the files table model to display counts of specific file
* types by mime type found in the currently selected data source.
*/
@Messages({"DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.type.header=File Type",
"DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.count.header=Count"})
private class FilesByMimeTypeTableModel extends AbstractTableModel {
private static final long serialVersionUID = 1L;
private final DataSource currentDataSource;
private final List<String> columnHeaders = new ArrayList<>();
private static final int IMAGES_ROW_INDEX = 0;
private static final int VIDEOS_ROW_INDEX = 1;
private static final int AUDIO_ROW_INDEX = 2;
private static final int DOCUMENTS_ROW_INDEX = 3;
private static final int EXECUTABLES_ROW_INDEX = 4;
/**
* Create a FilesByMimeTypeTableModel for the speicified datasource.
*
* @param selectedDataSource the datasource which this
* FilesByMimeTypeTablemodel will represent
*/
FilesByMimeTypeTableModel(DataSource selectedDataSource) {
columnHeaders.add(Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_type_header());
columnHeaders.add(Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_count_header());
currentDataSource = selectedDataSource;
}
@Override
public int getRowCount() {
//should be kept equal to the number of types we are displaying in the tables
return 5;
}
@Override
public int getColumnCount() {
return columnHeaders.size();
}
@Messages({
"DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.images.row=Images",
"DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.videos.row=Videos",
"DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.audio.row=Audio",
"DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.documents.row=Documents",
"DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.executables.row=Executables"
})
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
if (columnIndex == 0) {
switch (rowIndex) {
case IMAGES_ROW_INDEX:
return Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_images_row();
case VIDEOS_ROW_INDEX:
return Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_videos_row();
case AUDIO_ROW_INDEX:
return Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_audio_row();
case DOCUMENTS_ROW_INDEX:
return Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_documents_row();
case EXECUTABLES_ROW_INDEX:
return Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_executables_row();
default:
break;
}
} else if (columnIndex == 1) {
switch (rowIndex) {
case 0:
return DataSourceInfoUtilities.getCountOfFilesForMimeTypes(currentDataSource, FileTypeUtils.FileTypeCategory.IMAGE.getMediaTypes());
case 1:
return DataSourceInfoUtilities.getCountOfFilesForMimeTypes(currentDataSource, FileTypeUtils.FileTypeCategory.VIDEO.getMediaTypes());
case 2:
return DataSourceInfoUtilities.getCountOfFilesForMimeTypes(currentDataSource, FileTypeUtils.FileTypeCategory.AUDIO.getMediaTypes());
case 3:
return DataSourceInfoUtilities.getCountOfFilesForMimeTypes(currentDataSource, FileTypeUtils.FileTypeCategory.DOCUMENTS.getMediaTypes());
case 4:
return DataSourceInfoUtilities.getCountOfFilesForMimeTypes(currentDataSource, FileTypeUtils.FileTypeCategory.EXECUTABLE.getMediaTypes());
default:
break;
}
}
return null;
}
@Override
public String getColumnName(int column) {
return columnHeaders.get(column);
}
}
/**
* Table model for the files table model to display counts of specific file
* types by category found in the currently selected data source.
*/
@Messages({"DataSourceSummaryCountsPanel.FilesByCategoryTableModel.type.header=File Type",
"DataSourceSummaryCountsPanel.FilesByCategoryTableModel.count.header=Count"})
private class FilesByCategoryTableModel extends AbstractTableModel {
private static final long serialVersionUID = 1L;
private final DataSource currentDataSource;
private final List<String> columnHeaders = new ArrayList<>();
private static final int ALL_FILES_ROW_INDEX = 0;
private static final int ALLOCATED_FILES_ROW_INDEX = 1;
private static final int UNALLOCATED_FILES_ROW_INDEX = 2;
private static final int SLACK_FILES_ROW_INDEX = 3;
private static final int DIRECTORIES_ROW_INDEX = 4;
/**
* Create a FilesByCategoryTableModel for the speicified datasource.
*
* @param selectedDataSource the datasource which this
* FilesByCategoryTablemodel will represent
*/
FilesByCategoryTableModel(DataSource selectedDataSource) {
columnHeaders.add(Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_type_header());
columnHeaders.add(Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_count_header());
currentDataSource = selectedDataSource;
}
@Override
public int getRowCount() {
//should be kept equal to the number of types we are displaying in the tables
return 5;
}
@Override
public int getColumnCount() {
return columnHeaders.size();
}
@Messages({
"DataSourceSummaryCountsPanel.FilesByCategoryTableModel.all.row=All",
"DataSourceSummaryCountsPanel.FilesByCategoryTableModel.allocated.row=Allocated",
"DataSourceSummaryCountsPanel.FilesByCategoryTableModel.unallocated.row=Unallocated",
"DataSourceSummaryCountsPanel.FilesByCategoryTableModel.slack.row=Slack",
"DataSourceSummaryCountsPanel.FilesByCategoryTableModel.directory.row=Directory"
})
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
if (columnIndex == 0) {
switch (rowIndex) {
case ALL_FILES_ROW_INDEX:
return Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_all_row();
case ALLOCATED_FILES_ROW_INDEX:
return Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_allocated_row();
case UNALLOCATED_FILES_ROW_INDEX:
return Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_unallocated_row();
case SLACK_FILES_ROW_INDEX:
return Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_slack_row();
case DIRECTORIES_ROW_INDEX:
return Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_directory_row();
default:
break;
}
} else if (columnIndex == 1 && currentDataSource != null) {
switch (rowIndex) {
case 0:
return allFilesCountsMap.get(currentDataSource.getId()) == null ? 0 : allFilesCountsMap.get(currentDataSource.getId());
case 1:
//All files should be either allocated or unallocated as dir_flags only has two values so any file that isn't unallocated is allocated
Long unallocatedFilesCount = unallocatedFilesCountsMap.get(currentDataSource.getId());
Long allFilesCount = allFilesCountsMap.get(currentDataSource.getId());
if (allFilesCount == null) {
return 0;
} else if (unallocatedFilesCount == null) {
return allFilesCount;
} else {
return allFilesCount - unallocatedFilesCount;
}
case 2:
return unallocatedFilesCountsMap.get(currentDataSource.getId()) == null ? 0 : unallocatedFilesCountsMap.get(currentDataSource.getId());
case 3:
return slackFilesCountsMap.get(currentDataSource.getId()) == null ? 0 : slackFilesCountsMap.get(currentDataSource.getId());
case 4:
return directoriesCountsMap.get(currentDataSource.getId()) == null ? 0 : directoriesCountsMap.get(currentDataSource.getId());
default:
break;
}
}
return null;
}
@Override
public String getColumnName(int column) {
return columnHeaders.get(column);
}
}
}

View File

@ -12,7 +12,6 @@ CentralRepoDbChoice.PostgreSQL.Text=Custom PostgreSQL
CentralRepoDbChoice.PostgreSQL_Multiuser.Text=PostgreSQL using multi-user settings
CentralRepoDbChoice.Sqlite.Text=SQLite
CentralRepoDbManager.connectionErrorMsg.text=Failed to connect to central repository database.
CentralRepositoryService.progressMsg.updatingDataSourcesTable=Checking for v1.2 data updates...
CentralRepositoryService.progressMsg.updatingSchema=Updating schema...
CentralRepositoryService.serviceName=Central Repository Service
CorrelationAttributeInstance.invalidName.message=Invalid database table name. Name must start with a lowercase letter and can only contain lowercase letters, numbers, and '_'.

View File

@ -42,8 +42,8 @@ public class CentralRepositoryService implements AutopsyService {
}
@NbBundle.Messages({
"CentralRepositoryService.progressMsg.updatingSchema=Updating schema...",
"CentralRepositoryService.progressMsg.updatingDataSourcesTable=Checking for v1.2 data updates...",})
"CentralRepositoryService.progressMsg.updatingSchema=Updating schema..."
})
@Override
public void openCaseResources(CaseContext context) throws AutopsyServiceException {
if (!CentralRepository.isEnabled()) {
@ -58,7 +58,6 @@ public class CentralRepositoryService implements AutopsyService {
return;
}
progress.progress(Bundle.CentralRepositoryService_progressMsg_updatingDataSourcesTable());
dataUpgradeForVersion1dot2(context.getCase());
}

View File

@ -2,11 +2,16 @@ OpenIDE-Module-Name=CommandLineAutopsy
OptionsCategory_Keywords_Command_Line_Ingest_Settings=Command Line Ingest Settings
OptionsCategory_Keywords_General=Options
OptionsCategory_Name_Command_Line_Ingest=Command Line Ingest
CommandLinePanel.jLabel1.text=Ingest is running from command line
CommandLinePanel.jLabel1.text=Running command line taks.
CommandLineStartupWindow.title.text=Running in Command Line Mode
CommandLineIngestSettingsPanel.bnEditIngestSettings.text=Configure Ingest
CommandLineIngestSettingsPanel.bnEditIngestSettings.text=Configure
CommandLineIngestSettingsPanel.bnEditReportSettings.actionCommand=Report Module Settings
CommandLineIngestSettingsPanel.bnEditReportSettings.toolTipText=Report generation settings for the command line processing mode context.
CommandLineIngestSettingsPanel.bnEditReportSettings.text=Configure Reporting
CommandLineIngestSettingsPanel.jLabelDescription.text=<html>You can create cases, add data sources, run ingest modules, and generate reports from the command line.<br>This options panel allows you to configure the settings to use when running ingest modules and generating reports.<br>See the user documentation for details.</html>
CommandLineIngestSettingsPanel.bnEditReportSettings.text=Configure
CommandLineIngestSettingsPanel.bnEditIngestSettings.toolTipText=Ingest job settings for the command line processing mode context.
CommandLineIngestSettingsPanel.ingestDescriptionTextPane.text=Configure the profiles to use from the command line.
CommandLineIngestSettingsPanel.reportDescriptionTextPane.text=Report profiles define which report module and configuration to use.
CommandLineIngestSettingsPanel.reportProfileLabel.text=Report Profile:
CommandLineIngestSettingsPanel.ingestProfileLabel.text=Ingest Profile:
CommandLineIngestSettingsPanel.bnEditReportSettings.AccessibleContext.accessibleName=Configure
CommandLineIngestSettingsPanel.jTextPane1.text=Ingest profiles define which ingest filters, modules and configuration to use.

View File

@ -1,12 +1,22 @@
CommandLineIngestSettingPanel_empty_report_name_mgs=Report profile name was empty, no profile created.
CommandLineIngestSettingPanel_existing_report_name_mgs=Report profile name was already exists, no profile created.
CommandListIngestSettingsPanel_Default_Report_DisplayName=Default
CommandListIngestSettingsPanel_Make_Config=Make new profile...
CommandListIngestSettingsPanel_Report_Name_Msg=Please supply a report profile name:
OpenIDE-Module-Name=CommandLineAutopsy
OptionsCategory_Keywords_Command_Line_Ingest_Settings=Command Line Ingest Settings
OptionsCategory_Keywords_General=Options
OptionsCategory_Name_Command_Line_Ingest=Command Line Ingest
CommandLinePanel.jLabel1.text=Ingest is running from command line
CommandLinePanel.jLabel1.text=Running command line taks.
CommandLineStartupWindow.title.text=Running in Command Line Mode
CommandLineIngestSettingsPanel.bnEditIngestSettings.text=Configure Ingest
CommandLineIngestSettingsPanel.bnEditIngestSettings.text=Configure
CommandLineIngestSettingsPanel.bnEditReportSettings.actionCommand=Report Module Settings
CommandLineIngestSettingsPanel.bnEditReportSettings.toolTipText=Report generation settings for the command line processing mode context.
CommandLineIngestSettingsPanel.bnEditReportSettings.text=Configure Reporting
CommandLineIngestSettingsPanel.jLabelDescription.text=<html>You can create cases, add data sources, run ingest modules, and generate reports from the command line.<br>This options panel allows you to configure the settings to use when running ingest modules and generating reports.<br>See the user documentation for details.</html>
CommandLineIngestSettingsPanel.bnEditReportSettings.text=Configure
CommandLineIngestSettingsPanel.bnEditIngestSettings.toolTipText=Ingest job settings for the command line processing mode context.
CommandLineIngestSettingsPanel.ingestDescriptionTextPane.text=Configure the profiles to use from the command line.
CommandLineIngestSettingsPanel.reportDescriptionTextPane.text=Report profiles define which report module and configuration to use.
CommandLineIngestSettingsPanel.reportProfileLabel.text=Report Profile:
CommandLineIngestSettingsPanel.ingestProfileLabel.text=Ingest Profile:
CommandLineIngestSettingsPanel.bnEditReportSettings.AccessibleContext.accessibleName=Configure
CommandLineIngestSettingsPanel.jTextPane1.text=Ingest profiles define which ingest filters, modules and configuration to use.

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019-2019 Basis Technology Corp.
* Copyright 2019-2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -34,7 +34,8 @@ class CommandLineCommand {
ADD_DATA_SOURCE,
RUN_INGEST,
LIST_ALL_DATA_SOURCES,
GENERATE_REPORTS;
GENERATE_REPORTS,
OPEN_CASE_IN_UI;
}
/**
@ -47,7 +48,8 @@ class CommandLineCommand {
CASE_FOLDER_PATH,
DATA_SOURCE_PATH,
DATA_SOURCE_ID,
INGEST_PROFILE_NAME;
INGEST_PROFILE_NAME,
REPORT_PROFILE_NAME;
}
private final CommandType type;

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019-2019 Basis Technology Corp.
* Copyright 2019-2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -42,7 +42,6 @@ import org.sleuthkit.autopsy.casemodule.Case.CaseType;
import org.sleuthkit.autopsy.casemodule.CaseActionException;
import org.sleuthkit.autopsy.casemodule.CaseDetails;
import org.sleuthkit.autopsy.casemodule.CaseMetadata;
import static org.sleuthkit.autopsy.casemodule.CaseMetadata.getFileExtension;
import org.sleuthkit.autopsy.core.RuntimeProperties;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
import static org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS;
@ -74,7 +73,7 @@ import org.sleuthkit.datamodel.TskCoreException;
* cause Autopsy to create a case, add a specified data source, run ingest on
* that data source, list all data sources in the case, and generate reports.
*/
public class CommandLineIngestManager {
public class CommandLineIngestManager extends CommandLineManager{
private static final Logger LOGGER = Logger.getLogger(CommandLineIngestManager.class.getName());
private static final Set<IngestManager.IngestJobEvent> INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.CANCELLED, IngestManager.IngestJobEvent.COMPLETED);
@ -166,7 +165,7 @@ public class CommandLineIngestManager {
openCase(baseCaseName, rootOutputDirectory, caseType);
String outputDirPath = getOutputDirPath(caseForJob);
OutputGenerator.saveCreateCaseOutput(caseForJob, outputDirPath, baseCaseName);
OutputGenerator.saveCreateCaseOutput(caseForJob, outputDirPath, baseCaseName);
} catch (CaseActionException ex) {
String baseCaseName = command.getInputs().get(CommandLineCommand.InputType.CASE_NAME.name());
LOGGER.log(Level.SEVERE, "Error creating or opening case " + baseCaseName, ex);
@ -184,7 +183,7 @@ public class CommandLineIngestManager {
// open the case, if it hasn't been already opened by CREATE_CASE command
if (caseForJob == null) {
String caseDirPath = inputs.get(CommandLineCommand.InputType.CASE_FOLDER_PATH.name());
openCase(caseDirPath);
caseForJob = CommandLineIngestManager.this.openCase(caseDirPath);
}
String dataSourcePath = inputs.get(CommandLineCommand.InputType.DATA_SOURCE_PATH.name());
@ -210,7 +209,7 @@ public class CommandLineIngestManager {
// open the case, if it hasn't been already opened by CREATE_CASE or ADD_DATA_SOURCE commands
if (caseForJob == null) {
String caseDirPath = inputs.get(CommandLineCommand.InputType.CASE_FOLDER_PATH.name());
openCase(caseDirPath);
caseForJob = CommandLineIngestManager.this.openCase(caseDirPath);
}
// populate the AutoIngestDataSource structure, if that hasn't been done by ADD_DATA_SOURCE command
@ -265,7 +264,7 @@ public class CommandLineIngestManager {
// open the case, if it hasn't been already opened by previous command
if (caseForJob == null) {
String caseDirPath = inputs.get(CommandLineCommand.InputType.CASE_FOLDER_PATH.name());
openCase(caseDirPath);
caseForJob = CommandLineIngestManager.this.openCase(caseDirPath);
}
String outputDirPath = getOutputDirPath(caseForJob);
@ -288,12 +287,17 @@ public class CommandLineIngestManager {
// open the case, if it hasn't been already opened by previous command
if (caseForJob == null) {
String caseDirPath = inputs.get(CommandLineCommand.InputType.CASE_FOLDER_PATH.name());
openCase(caseDirPath);
caseForJob = CommandLineIngestManager.this.openCase(caseDirPath);
}
// generate reports
String reportName = inputs.get(CommandLineCommand.InputType.REPORT_PROFILE_NAME.name());
if (reportName == null) {
reportName = CommandLineIngestSettingsPanel.getDefaultReportingConfigName();
}
// generate reports
ReportProgressIndicator progressIndicator = new ReportProgressIndicator(new LoggingProgressIndicator());
ReportGenerator generator = new ReportGenerator(CommandLineIngestSettingsPanel.getReportingConfigName(), progressIndicator);
ReportGenerator generator = new ReportGenerator(reportName, progressIndicator);
generator.generateReports();
} catch (CaseActionException ex) {
String caseDirPath = command.getInputs().get(CommandLineCommand.InputType.CASE_FOLDER_PATH.name());
@ -343,7 +347,7 @@ public class CommandLineIngestManager {
* @param baseCaseName Case name
* @param rootOutputDirectory Full path to directory in which case
* output folder will be created
* @param caseType Type of case being created
* @param caseType Type of case being created
*
* @throws CaseActionException
*/
@ -369,55 +373,6 @@ public class CommandLineIngestManager {
LOGGER.log(Level.INFO, "Opened case {0}", caseForJob.getName());
}
/**
* Opens existing case.
*
* @param caseFolderPath full path to case directory
*
* @throws CaseActionException
*/
private void openCase(String caseFolderPath) throws CaseActionException {
LOGGER.log(Level.INFO, "Opening case in directory {0}", caseFolderPath);
String metadataFilePath = findAutFile(caseFolderPath);
Case.openAsCurrentCase(metadataFilePath);
caseForJob = Case.getCurrentCase();
LOGGER.log(Level.INFO, "Opened case {0}", caseForJob.getName());
}
/**
* Finds the path to the .aut file for the specified case directory.
*
* @param caseDirectory the directory to check for a .aut file
*
* @return the path to the first .aut file found in the directory
*
* @throws CaseActionException if there was an issue finding a .aut file
*/
private String findAutFile(String caseDirectory) throws CaseActionException {
File caseFolder = Paths.get(caseDirectory).toFile();
if (caseFolder.exists()) {
/*
* Search for '*.aut' files.
*/
File[] fileArray = caseFolder.listFiles();
if (fileArray == null) {
throw new CaseActionException("No files found in case directory");
}
String autFilePath = null;
for (File file : fileArray) {
String name = file.getName().toLowerCase();
if (autFilePath == null && name.endsWith(getFileExtension())) {
return file.getAbsolutePath();
}
}
throw new CaseActionException("No .aut files found in case directory");
}
throw new CaseActionException("Case directory was not found");
}
/**
* Passes the data source for the current job through a data source
* processor that adds it to the case database.
@ -425,17 +380,11 @@ public class CommandLineIngestManager {
* @param caseForJob The case
* @param dataSource The data source.
*
* @throws
* AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorExceptioif
* there
* was
* a
* DSP
* processing
* error
* @throws AutoIngestDataSourceProcessorException if there was a DSP
* processing error.
*
* @throws ead running the job processing task is interrupted while
* blocked, i.e., if auto ingest is shutting down.
* @throws InterruptedException running the job processing task while
* blocking, i.e., if auto ingest is shutting down.
*/
private void runDataSourceProcessor(Case caseForJob, AutoIngestDataSource dataSource) throws InterruptedException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException {

View File

@ -16,113 +16,207 @@
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,1,-112"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="nodeScrollPane" alignment="1" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="nodeScrollPane" alignment="0" pref="421" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
<SubComponents>
<Container class="javax.swing.JScrollPane" name="nodeScrollPane">
<Container class="javax.swing.JPanel" name="nodePanel">
<Properties>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[0, 0]"/>
<Dimension value="[100, 100]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[803, 553]"/>
<Dimension value="[801, 551]"/>
</Property>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
<BorderConstraints direction="Center"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="nodePanel">
<Component class="javax.swing.JButton" name="bnEditIngestSettings">
<Properties>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[100, 100]"/>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/commandlineingest/Bundle.properties" key="CommandLineIngestSettingsPanel.bnEditIngestSettings.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[801, 551]"/>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/commandlineingest/Bundle.properties" key="CommandLineIngestSettingsPanel.bnEditIngestSettings.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="actionCommand" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/commandlineingest/Bundle.properties" key="CommandLineIngestSettingsPanel.bnEditIngestSettings.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="bnEditIngestSettings" alignment="0" min="-2" pref="155" max="-2" attributes="0"/>
<Component id="jLabelDescription" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="bnEditReportSettings" alignment="0" min="-2" pref="155" max="-2" attributes="0"/>
</Group>
<EmptySpace pref="-34" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="27" max="-2" attributes="0"/>
<Component id="jLabelDescription" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="bnEditIngestSettings" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="bnEditReportSettings" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="381" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JButton" name="bnEditIngestSettings">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/commandlineingest/Bundle.properties" key="CommandLineIngestSettingsPanel.bnEditIngestSettings.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/commandlineingest/Bundle.properties" key="CommandLineIngestSettingsPanel.bnEditIngestSettings.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="actionCommand" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/commandlineingest/Bundle.properties" key="CommandLineIngestSettingsPanel.bnEditIngestSettings.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnEditIngestSettingsActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="jLabelDescription">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/commandlineingest/Bundle.properties" key="CommandLineIngestSettingsPanel.jLabelDescription.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="bnEditReportSettings">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/commandlineingest/Bundle.properties" key="CommandLineIngestSettingsPanel.bnEditReportSettings.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/commandlineingest/Bundle.properties" key="CommandLineIngestSettingsPanel.bnEditReportSettings.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="actionCommand" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/commandlineingest/Bundle.properties" key="CommandLineIngestSettingsPanel.bnEditReportSettings.actionCommand" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnEditReportSettingsActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Container>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnEditIngestSettingsActionPerformed"/>
</Events>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="2" gridY="2" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="9" insetsBottom="0" insetsRight="0" anchor="18" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JButton" name="bnEditReportSettings">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/commandlineingest/Bundle.properties" key="CommandLineIngestSettingsPanel.bnEditReportSettings.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/commandlineingest/Bundle.properties" key="CommandLineIngestSettingsPanel.bnEditReportSettings.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="actionCommand" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/commandlineingest/Bundle.properties" key="CommandLineIngestSettingsPanel.bnEditReportSettings.actionCommand" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<AccessibilityProperties>
<Property name="AccessibleContext.accessibleName" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/commandlineingest/Bundle.properties" key="CommandLineIngestSettingsPanel.bnEditReportSettings.AccessibleContext.accessibleName" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</AccessibilityProperties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnEditReportSettingsActionPerformed"/>
</Events>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="2" gridY="4" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="9" insetsBottom="0" insetsRight="0" anchor="18" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JTextPane" name="ingestDescriptionTextPane">
<Properties>
<Property name="editable" type="boolean" value="false"/>
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="f0" green="f0" id="Label.background" palette="3" red="f0" type="palette"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/commandlineingest/Bundle.properties" key="CommandLineIngestSettingsPanel.ingestDescriptionTextPane.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="0" gridWidth="3" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="5" insetsLeft="5" insetsBottom="10" insetsRight="5" anchor="18" weightX="1.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JLabel" name="ingestProfileLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/commandlineingest/Bundle.properties" key="CommandLineIngestSettingsPanel.ingestProfileLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="2" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="25" insetsBottom="0" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JComboBox" name="ingestProfileCB">
<Properties>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
<StringArray count="1">
<StringItem index="0" value="Default"/>
</StringArray>
</Property>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="&lt;String&gt;"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="2" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="5" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JTextPane" name="reportDescriptionTextPane">
<Properties>
<Property name="editable" type="boolean" value="false"/>
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="f0" green="f0" id="Label.background" palette="3" red="f0" type="palette"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/commandlineingest/Bundle.properties" key="CommandLineIngestSettingsPanel.reportDescriptionTextPane.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="3" gridWidth="3" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="15" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="10" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JLabel" name="reportProfileLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/commandlineingest/Bundle.properties" key="CommandLineIngestSettingsPanel.reportProfileLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="4" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="25" insetsBottom="0" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JComboBox" name="reportProfileCB">
<Properties>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
<StringArray count="0"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="&lt;String&gt;"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="4" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="5" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.Box$Filler" name="bottomFiller">
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="5" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="1.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JTextPane" name="jTextPane1">
<Properties>
<Property name="editable" type="boolean" value="false"/>
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="f0" green="f0" id="Label.background" palette="3" red="f0" type="palette"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/commandlineingest/Bundle.properties" key="CommandLineIngestSettingsPanel.jTextPane1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="1" gridWidth="3" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="10" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="17" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
</SubComponents>
</Container>
</SubComponents>

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019-2019 Basis Technology Corp.
* Copyright 2019-2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -21,12 +21,16 @@ package org.sleuthkit.autopsy.commandlineingest;
import java.awt.BorderLayout;
import java.awt.Cursor;
import java.util.List;
import java.util.Set;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JOptionPane;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.ingest.IngestJobSettings;
import org.sleuthkit.autopsy.ingest.IngestJobSettingsPanel;
import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.coreutils.Logger;
import static org.sleuthkit.autopsy.report.infrastructure.ReportWizardAction.doReportWizard;
import org.sleuthkit.autopsy.report.infrastructure.ReportWizardAction;
/**
* Configuration panel for auto ingest settings.
@ -36,7 +40,7 @@ public class CommandLineIngestSettingsPanel extends javax.swing.JPanel {
private static final long serialVersionUID = 1L;
private static final Logger logger = Logger.getLogger(CommandLineIngestSettingsPanel.class.getName());
private static final String REPORTING_CONFIGURATION_NAME = "CommandLineIngest";
private static final boolean DISPLAY_CASE_SPECIFIC_DATA = false; // do not try to display case specific data
private static final boolean RUN_REPORTS = false; // do not generate reports as part of running the report wizard
@ -48,12 +52,13 @@ public class CommandLineIngestSettingsPanel extends javax.swing.JPanel {
*/
public CommandLineIngestSettingsPanel(CommandLineIngestSettingsPanelController theController) {
initComponents();
setupReportList();
}
/**
* @return the REPORTING_CONFIGURATION_NAME
*/
public static String getReportingConfigName() {
public static String getDefaultReportingConfigName() {
return REPORTING_CONFIGURATION_NAME;
}
@ -87,6 +92,58 @@ public class CommandLineIngestSettingsPanel extends javax.swing.JPanel {
}
}
@Messages({
"CommandListIngestSettingsPanel_Default_Report_DisplayName=Default",
"CommandListIngestSettingsPanel_Make_Config=Make new profile..."
})
/**
* Initializes the report profile list combo box.
*/
private void setupReportList() {
Set<String> configNames = ReportWizardAction.getReportConfigNames();
configNames.remove(REPORTING_CONFIGURATION_NAME);
DefaultComboBoxModel<String> model = new DefaultComboBoxModel<>();
model.addElement(Bundle.CommandListIngestSettingsPanel_Default_Report_DisplayName());
for (String name : configNames) {
model.addElement(name);
}
model.addElement(Bundle.CommandListIngestSettingsPanel_Make_Config());
reportProfileCB.setModel(model);
reportProfileCB.setSelectedIndex(0);
}
/**
* Checks to see if there is currently a profile define with the given name.
*
* @param name Profile name to check.
*
* @return True if there is a report with the given name.
*/
private boolean doesReportProfileNameExist(String name) {
Set<String> configNames = ReportWizardAction.getReportConfigNames();
return configNames.contains(name);
}
/**
* Returns the currently selected report profile name from the cb. For backwards
* compatibility if Default is selected, the existing default
* profile name of CommandLineIngest will be returned.
*
* @return The selected profile name.
*/
private String getReportName() {
String reportName = (String) reportProfileCB.getSelectedItem();
if (reportName.equals(Bundle.CommandListIngestSettingsPanel_Default_Report_DisplayName())) {
reportName = REPORTING_CONFIGURATION_NAME;
}
return reportName;
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
@ -95,20 +152,26 @@ public class CommandLineIngestSettingsPanel extends javax.swing.JPanel {
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
java.awt.GridBagConstraints gridBagConstraints;
nodeScrollPane = new javax.swing.JScrollPane();
nodePanel = new javax.swing.JPanel();
bnEditIngestSettings = new javax.swing.JButton();
jLabelDescription = new javax.swing.JLabel();
bnEditReportSettings = new javax.swing.JButton();
javax.swing.JTextPane ingestDescriptionTextPane = new javax.swing.JTextPane();
javax.swing.JLabel ingestProfileLabel = new javax.swing.JLabel();
ingestProfileCB = new javax.swing.JComboBox<>();
javax.swing.JTextPane reportDescriptionTextPane = new javax.swing.JTextPane();
javax.swing.JLabel reportProfileLabel = new javax.swing.JLabel();
reportProfileCB = new javax.swing.JComboBox<>();
javax.swing.Box.Filler bottomFiller = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0));
jTextPane1 = new javax.swing.JTextPane();
setPreferredSize(new java.awt.Dimension(810, 422));
nodeScrollPane.setMinimumSize(new java.awt.Dimension(0, 0));
nodeScrollPane.setPreferredSize(new java.awt.Dimension(803, 553));
setLayout(new java.awt.BorderLayout());
nodePanel.setMinimumSize(new java.awt.Dimension(100, 100));
nodePanel.setPreferredSize(new java.awt.Dimension(801, 551));
nodePanel.setLayout(new java.awt.GridBagLayout());
org.openide.awt.Mnemonics.setLocalizedText(bnEditIngestSettings, org.openide.util.NbBundle.getMessage(CommandLineIngestSettingsPanel.class, "CommandLineIngestSettingsPanel.bnEditIngestSettings.text")); // NOI18N
bnEditIngestSettings.setToolTipText(org.openide.util.NbBundle.getMessage(CommandLineIngestSettingsPanel.class, "CommandLineIngestSettingsPanel.bnEditIngestSettings.toolTipText")); // NOI18N
@ -118,8 +181,12 @@ public class CommandLineIngestSettingsPanel extends javax.swing.JPanel {
bnEditIngestSettingsActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(jLabelDescription, org.openide.util.NbBundle.getMessage(CommandLineIngestSettingsPanel.class, "CommandLineIngestSettingsPanel.jLabelDescription.text")); // NOI18N
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 2;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new java.awt.Insets(0, 9, 0, 0);
nodePanel.add(bnEditIngestSettings, gridBagConstraints);
org.openide.awt.Mnemonics.setLocalizedText(bnEditReportSettings, org.openide.util.NbBundle.getMessage(CommandLineIngestSettingsPanel.class, "CommandLineIngestSettingsPanel.bnEditReportSettings.text")); // NOI18N
bnEditReportSettings.setToolTipText(org.openide.util.NbBundle.getMessage(CommandLineIngestSettingsPanel.class, "CommandLineIngestSettingsPanel.bnEditReportSettings.toolTipText")); // NOI18N
@ -129,48 +196,120 @@ public class CommandLineIngestSettingsPanel extends javax.swing.JPanel {
bnEditReportSettingsActionPerformed(evt);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 4;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new java.awt.Insets(0, 9, 0, 0);
nodePanel.add(bnEditReportSettings, gridBagConstraints);
bnEditReportSettings.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(CommandLineIngestSettingsPanel.class, "CommandLineIngestSettingsPanel.bnEditReportSettings.AccessibleContext.accessibleName")); // NOI18N
javax.swing.GroupLayout nodePanelLayout = new javax.swing.GroupLayout(nodePanel);
nodePanel.setLayout(nodePanelLayout);
nodePanelLayout.setHorizontalGroup(
nodePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(nodePanelLayout.createSequentialGroup()
.addContainerGap()
.addGroup(nodePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(bnEditIngestSettings, javax.swing.GroupLayout.PREFERRED_SIZE, 155, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jLabelDescription, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(bnEditReportSettings, javax.swing.GroupLayout.PREFERRED_SIZE, 155, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
nodePanelLayout.setVerticalGroup(
nodePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(nodePanelLayout.createSequentialGroup()
.addGap(27, 27, 27)
.addComponent(jLabelDescription, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(bnEditIngestSettings)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(bnEditReportSettings)
.addContainerGap(381, Short.MAX_VALUE))
);
ingestDescriptionTextPane.setEditable(false);
ingestDescriptionTextPane.setBackground(javax.swing.UIManager.getDefaults().getColor("Label.background"));
ingestDescriptionTextPane.setText(org.openide.util.NbBundle.getMessage(CommandLineIngestSettingsPanel.class, "CommandLineIngestSettingsPanel.ingestDescriptionTextPane.text")); // NOI18N
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.gridwidth = 3;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.insets = new java.awt.Insets(5, 5, 10, 5);
nodePanel.add(ingestDescriptionTextPane, gridBagConstraints);
nodeScrollPane.setViewportView(nodePanel);
org.openide.awt.Mnemonics.setLocalizedText(ingestProfileLabel, org.openide.util.NbBundle.getMessage(CommandLineIngestSettingsPanel.class, "CommandLineIngestSettingsPanel.ingestProfileLabel.text")); // NOI18N
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 2;
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
gridBagConstraints.insets = new java.awt.Insets(0, 25, 0, 0);
nodePanel.add(ingestProfileLabel, gridBagConstraints);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(nodeScrollPane, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(nodeScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 421, Short.MAX_VALUE)
);
ingestProfileCB.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "Default" }));
ingestProfileCB.setEnabled(false);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 2;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.insets = new java.awt.Insets(0, 5, 0, 0);
nodePanel.add(ingestProfileCB, gridBagConstraints);
reportDescriptionTextPane.setEditable(false);
reportDescriptionTextPane.setBackground(javax.swing.UIManager.getDefaults().getColor("Label.background"));
reportDescriptionTextPane.setText(org.openide.util.NbBundle.getMessage(CommandLineIngestSettingsPanel.class, "CommandLineIngestSettingsPanel.reportDescriptionTextPane.text")); // NOI18N
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 3;
gridBagConstraints.gridwidth = 3;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.insets = new java.awt.Insets(15, 5, 5, 5);
nodePanel.add(reportDescriptionTextPane, gridBagConstraints);
org.openide.awt.Mnemonics.setLocalizedText(reportProfileLabel, org.openide.util.NbBundle.getMessage(CommandLineIngestSettingsPanel.class, "CommandLineIngestSettingsPanel.reportProfileLabel.text")); // NOI18N
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 4;
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
gridBagConstraints.insets = new java.awt.Insets(0, 25, 0, 0);
nodePanel.add(reportProfileLabel, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 4;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.insets = new java.awt.Insets(0, 5, 0, 0);
nodePanel.add(reportProfileCB, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 5;
gridBagConstraints.weighty = 1.0;
nodePanel.add(bottomFiller, gridBagConstraints);
jTextPane1.setEditable(false);
jTextPane1.setBackground(javax.swing.UIManager.getDefaults().getColor("Label.background"));
jTextPane1.setText(org.openide.util.NbBundle.getMessage(CommandLineIngestSettingsPanel.class, "CommandLineIngestSettingsPanel.jTextPane1.text")); // NOI18N
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 1;
gridBagConstraints.gridwidth = 3;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
gridBagConstraints.insets = new java.awt.Insets(10, 5, 5, 5);
nodePanel.add(jTextPane1, gridBagConstraints);
add(nodePanel, java.awt.BorderLayout.CENTER);
}// </editor-fold>//GEN-END:initComponents
@Messages({
"CommandListIngestSettingsPanel_Report_Name_Msg=Please supply a report profile name:",
"CommandLineIngestSettingPanel_empty_report_name_mgs=Report profile name was empty, no profile created.",
"CommandLineIngestSettingPanel_existing_report_name_mgs=Report profile name was already exists, no profile created."
})
private void bnEditReportSettingsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnEditReportSettingsActionPerformed
String reportName = getReportName();
if (reportName.equals(Bundle.CommandListIngestSettingsPanel_Make_Config())) {
reportName = JOptionPane.showInputDialog(this, Bundle.CommandListIngestSettingsPanel_Report_Name_Msg());
// User hit cancel
if (reportName == null) {
return;
} else if (reportName.isEmpty()) {
JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(), Bundle.CommandLineIngestSettingPanel_empty_report_name_mgs());
return;
} else if (doesReportProfileNameExist(reportName)) {
JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(), Bundle.CommandLineIngestSettingPanel_existing_report_name_mgs());
return;
}
}
this.getParent().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
doReportWizard(getReportingConfigName(), DISPLAY_CASE_SPECIFIC_DATA, RUN_REPORTS);
doReportWizard(reportName, DISPLAY_CASE_SPECIFIC_DATA, RUN_REPORTS);
setupReportList();
if (((DefaultComboBoxModel) reportProfileCB.getModel()).getIndexOf(reportName) >= 0) {
reportProfileCB.setSelectedItem(reportName);
}
this.getParent().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}//GEN-LAST:event_bnEditReportSettingsActionPerformed
@ -181,8 +320,9 @@ public class CommandLineIngestSettingsPanel extends javax.swing.JPanel {
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton bnEditIngestSettings;
private javax.swing.JButton bnEditReportSettings;
private javax.swing.JLabel jLabelDescription;
private javax.swing.JComboBox<String> ingestProfileCB;
private javax.swing.JTextPane jTextPane1;
private javax.swing.JPanel nodePanel;
private javax.swing.JScrollPane nodeScrollPane;
private javax.swing.JComboBox<String> reportProfileCB;
// End of variables declaration//GEN-END:variables
}

View File

@ -0,0 +1,87 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2020 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.commandlineingest;
import java.io.File;
import java.nio.file.Paths;
import java.util.logging.Level;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.CaseActionException;
import static org.sleuthkit.autopsy.casemodule.CaseMetadata.getFileExtension;
import org.sleuthkit.autopsy.coreutils.Logger;
/**
* Base class for the command line managers.
*/
class CommandLineManager {
private static final Logger LOGGER = Logger.getLogger(CommandLineOpenCaseManager.class.getName());
/**
* Opens existing case.
*
* @param caseFolderPath full path to case directory
*
* @throws CaseActionException
*/
Case openCase(String caseFolderPath) throws CaseActionException {
LOGGER.log(Level.INFO, "Opening case in directory {0}", caseFolderPath);
String metadataFilePath = findAutFile(caseFolderPath);
Case.openAsCurrentCase(metadataFilePath);
Case newCase = Case.getCurrentCase();
LOGGER.log(Level.INFO, "Opened case {0}", newCase.getName());
return newCase;
}
/**
* Finds the path to the .aut file for the specified case directory.
*
* @param caseDirectory the directory to check for a .aut file
*
* @return the path to the first .aut file found in the directory
*
* @throws CaseActionException if there was an issue finding a .aut file
*/
private String findAutFile(String caseDirectory) throws CaseActionException {
File caseFolder = Paths.get(caseDirectory).toFile();
if (caseFolder.exists()) {
/*
* Search for '*.aut' files.
*/
File[] fileArray = caseFolder.listFiles();
if (fileArray == null) {
throw new CaseActionException("No files found in case directory");
}
String autFilePath = null;
for (File file : fileArray) {
String name = file.getName().toLowerCase();
if (autFilePath == null && name.endsWith(getFileExtension())) {
return file.getAbsolutePath();
}
}
throw new CaseActionException("No .aut files found in case directory");
}
throw new CaseActionException("Case directory was not found");
}
}

View File

@ -0,0 +1,85 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2020 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.commandlineingest;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.Iterator;
import java.util.logging.Level;
import org.netbeans.spi.sendopts.OptionProcessor;
import org.openide.util.Lookup;
import org.sleuthkit.autopsy.casemodule.CaseActionException;
import org.sleuthkit.autopsy.casemodule.OpenFromArguments;
import org.sleuthkit.autopsy.coreutils.Logger;
/**
* Handles the opening of a case from the command line.
*
*/
public class CommandLineOpenCaseManager extends CommandLineManager {
private static final Logger LOGGER = Logger.getLogger(CommandLineOpenCaseManager.class.getName());
/**
* Starts the thread to open the case.
*/
public void start() {
new Thread(new CommandLineOpenCaseManager.JobProcessingTask()).start();
}
/**
* A runnable class that open the given class in the list of command line
* options.
*/
private final class JobProcessingTask implements Runnable {
@Override
public void run() {
String casePath = "";
// first look up all OptionProcessors and get input data from CommandLineOptionProcessor
Collection<? extends OptionProcessor> optionProcessors = Lookup.getDefault().lookupAll(OptionProcessor.class);
Iterator<? extends OptionProcessor> optionsIterator = optionProcessors.iterator();
while (optionsIterator.hasNext()) {
// find CommandLineOptionProcessor
OptionProcessor processor = optionsIterator.next();
if (processor instanceof OpenFromArguments) {
// check if we are running from command line
casePath = Paths.get(((OpenFromArguments) processor).getDefaultArg()).toAbsolutePath().toString();
break;
}
}
if (casePath == null || casePath.isEmpty()) {
LOGGER.log(Level.SEVERE, "No command line commands specified");
System.err.println("No command line commands specified");
return;
}
try {
CommandLineOpenCaseManager.this.openCase(casePath);
LOGGER.log(Level.INFO, "Opening case at " + casePath);
} catch (CaseActionException ex) {
LOGGER.log(Level.SEVERE, "Error opening case from command line ", ex);
System.err.println("Error opening case ");
}
}
}
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019-2019 Basis Technology Corp.
* Copyright 2019-2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -51,7 +51,7 @@ public class CommandLineOptionProcessor extends OptionProcessor {
private final Option runIngestCommandOption = Option.withoutArgument('r', "runIngest");
private final Option ingestProfileOption = Option.requiredArgument('p', "ingestProfile");
private final Option listAllDataSourcesCommandOption = Option.withoutArgument('l', "listAllDataSources");
private final Option generateReportsOption = Option.withoutArgument('g', "generateReports");
private final Option generateReportsOption = Option.optionalArgument('g', "generateReports");
private boolean runFromCommandLine = false;
@ -59,7 +59,7 @@ public class CommandLineOptionProcessor extends OptionProcessor {
final static String CASETYPE_MULTI = "multi";
final static String CASETYPE_SINGLE = "single";
@Override
protected Set<Option> getOptions() {
Set<Option> set = new HashSet<>();
@ -113,7 +113,6 @@ public class CommandLineOptionProcessor extends OptionProcessor {
}
}
String caseType = "";
if (values.containsKey(caseTypeOption)) {
argDirs = values.get(caseTypeOption);
@ -134,16 +133,16 @@ public class CommandLineOptionProcessor extends OptionProcessor {
if (!caseType.equalsIgnoreCase(CASETYPE_MULTI) && !caseType.equalsIgnoreCase(CASETYPE_SINGLE)) {
logger.log(Level.SEVERE, "'caseType' argument is invalid");
System.err.println("'caseType' argument is invalid");
return;
return;
}
if (caseType.equalsIgnoreCase(CASETYPE_MULTI) && !FeatureAccessUtils.canCreateMultiUserCases()) {
logger.log(Level.SEVERE, "Unable to create multi user case.");
System.err.println("Unable to create multi user case. Confirm that multi user settings are configured correctly.");
return;
return;
}
}
String caseBaseDir = "";
if (values.containsKey(caseBaseDirOption)) {
argDirs = values.get(caseBaseDirOption);
@ -356,8 +355,9 @@ public class CommandLineOptionProcessor extends OptionProcessor {
commands.add(newCommand);
runFromCommandLine = true;
}
// Add "GENERATE_REPORTS" command, if present
String reportProfile = null;
if (values.containsKey(generateReportsOption)) {
// 'caseDir' must only be specified if the case is not being created during the current run
@ -369,11 +369,29 @@ public class CommandLineOptionProcessor extends OptionProcessor {
return;
}
argDirs = values.get(generateReportsOption);
if (argDirs.length > 0) {
reportProfile = argDirs[0];
}
// If the user doesn't supply an options for generateReports the
// argsDirs length will be 0, so if reportProfile is empty
// something is not right.
if (reportProfile != null && reportProfile.isEmpty()) {
logger.log(Level.SEVERE, "'generateReports' argument is empty");
System.err.println("'generateReports' argument is empty");
runFromCommandLine = false;
return;
}
CommandLineCommand newCommand = new CommandLineCommand(CommandLineCommand.CommandType.GENERATE_REPORTS);
newCommand.addInputValue(CommandLineCommand.InputType.CASE_FOLDER_PATH.name(), caseDir);
if (reportProfile != null) {
newCommand.addInputValue(CommandLineCommand.InputType.REPORT_PROFILE_NAME.name(), reportProfile);
}
commands.add(newCommand);
runFromCommandLine = true;
}
}
}
/**

View File

@ -26,7 +26,7 @@
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<EmptySpace min="-2" pref="20" max="-2" attributes="0"/>
<Component id="jLabel1" pref="305" max="32767" attributes="0"/>
<Component id="jLabel1" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019-2019 Basis Technology Corp.
* Copyright 2019-2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -52,7 +52,7 @@ class CommandLinePanel extends JPanel {
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGap(20, 20, 20)
.addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, 305, Short.MAX_VALUE)
.addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addContainerGap())
);
layout.setVerticalGroup(

View File

@ -35,8 +35,12 @@ import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.NodeProperty;
import org.sleuthkit.datamodel.Account;
import org.sleuthkit.datamodel.AccountDeviceInstance;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME;
import org.sleuthkit.datamodel.CommunicationsFilter;
import org.sleuthkit.datamodel.CommunicationsManager;
import org.sleuthkit.datamodel.TskCoreException;
/**
* Node to represent an Account Device Instance in the CVT
@ -49,6 +53,8 @@ final class AccountDeviceInstanceNode extends AbstractNode {
private final CommunicationsManager commsManager;
private final Account account;
private static final BlackboardAttribute.Type NAME_ATTRIBUTE = new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.fromID(TSK_NAME.getTypeID()));
AccountDeviceInstanceNode(AccountDeviceInstanceKey accountDeviceInstanceKey, CommunicationsManager commsManager) {
super(Children.LEAF, Lookups.fixed(accountDeviceInstanceKey, commsManager));
this.accountDeviceInstanceKey = accountDeviceInstanceKey;
@ -122,15 +128,17 @@ final class AccountDeviceInstanceNode extends AbstractNode {
@Override
public String getShortDescription() {
List<PersonaAccount> personaList;
List<BlackboardArtifact> contactArtifactList;
try {
personaList = CVTPersonaCache.getPersonaAccounts(account);
contactArtifactList = ContactCache.getContacts(account);
} catch (ExecutionException ex) {
logger.log(Level.WARNING, "Failed to retrieve Persona details for node.", ex);
return getDisplayName();
}
String personaName;
if (!personaList.isEmpty()) {
if (personaList != null && !personaList.isEmpty()) {
personaName = personaList.get(0).getPersona().getName();
if (personaList.size() > 1) {
personaName += Bundle.AccountInstanceNode_Tooltip_suffix(Integer.toString(personaList.size()));
@ -139,6 +147,19 @@ final class AccountDeviceInstanceNode extends AbstractNode {
personaName = "None";
}
return Bundle.AccountInstanceNode_Tooltip_Template(getDisplayName(), personaName);
String contactName = getDisplayName();
if (contactArtifactList != null && !contactArtifactList.isEmpty()) {
try {
BlackboardArtifact contactArtifact = contactArtifactList.get(0);
BlackboardAttribute attribute = contactArtifact.getAttribute(NAME_ATTRIBUTE);
if (attribute != null) {
contactName = attribute.getValueString();
}
} catch (TskCoreException ex) {
logger.log(Level.WARNING, "Failed to retrive name attribute from contact artifact.", ex);
}
}
return Bundle.AccountInstanceNode_Tooltip_Template(contactName, personaName);
}
}

View File

@ -21,7 +21,6 @@ CVTTopComponent.accountsBrowser.TabConstraints.tabTitle_1=Browse
CVTTopComponent.browseVisualizeTabPane.AccessibleContext.accessibleName=Visualize
CVTTopComponent.vizPanel.TabConstraints.tabTitle_1=Visualize
VisualizationPanel.fitGraphButton.text=
VisualizationPanel.jTextArea1.text=Right-click an account in the Browse Accounts table, and select 'Visualize' to begin.
VisualizationPanel.fitZoomButton.toolTipText=Fit visualization to available space.
VisualizationPanel.fitZoomButton.text=
VisualizationPanel.zoomActualButton.toolTipText=Reset visualization default zoom state.
@ -51,3 +50,4 @@ VisualizationPanel.zoomLabel.text=Zoom:
VisualizationPanel.snapshotButton.toolTipText=Generate Snapshot report.
CVTTopComponent.filtersPane.TabConstraints.tabTitle=Filters
CVTTopComponent.filterTabPanel.TabConstraints.tabTitle=Filters
VisualizationPanel.jTextPane1.text=Right-click an account in the Browse Accounts table, and select 'Visualize' to begin.

View File

@ -61,7 +61,6 @@ CVTTopComponent.accountsBrowser.TabConstraints.tabTitle_1=Browse
CVTTopComponent.browseVisualizeTabPane.AccessibleContext.accessibleName=Visualize
CVTTopComponent.vizPanel.TabConstraints.tabTitle_1=Visualize
VisualizationPanel.fitGraphButton.text=
VisualizationPanel.jTextArea1.text=Right-click an account in the Browse Accounts table, and select 'Visualize' to begin.
VisualizationPanel.fitZoomButton.toolTipText=Fit visualization to available space.
VisualizationPanel.fitZoomButton.text=
# {0} - layout name
@ -99,6 +98,7 @@ VisualizationPanel.zoomLabel.text=Zoom:
VisualizationPanel.snapshotButton.toolTipText=Generate Snapshot report.
CVTTopComponent.filtersPane.TabConstraints.tabTitle=Filters
CVTTopComponent.filterTabPanel.TabConstraints.tabTitle=Filters
VisualizationPanel.jTextPane1.text=Right-click an account in the Browse Accounts table, and select 'Visualize' to begin.
VisualizationPanel_action_dialogs_title=Communications
VisualizationPanel_action_name_text=Snapshot Report
VisualizationPanel_module_name=Communications

View File

@ -56,7 +56,7 @@ CVTTopComponent.accountsBrowser.TabConstraints.tabTitle_1=\u53c2\u7167
CVTTopComponent.browseVisualizeTabPane.AccessibleContext.accessibleName=\u53ef\u8996\u5316
CVTTopComponent.vizPanel.TabConstraints.tabTitle_1=\u53ef\u8996\u5316
VisualizationPanel.fitGraphButton.text=
VisualizationPanel.jTextArea1.text=[\u30a2\u30ab\u30a6\u30f3\u30c8\u53c2\u7167] \u30c6\u30fc\u30d6\u30eb\u3067\u30a2\u30ab\u30a6\u30f3\u30c8\u3092\u53f3\u30af\u30ea\u30c3\u30af\u3057\u3001[\u53ef\u8996\u5316] \u3092\u9078\u629e\u3057\u3066\u958b\u59cb\u3057\u307e\u3059\u3002
VisualizationPanel.jTextPane1.text=[\u30a2\u30ab\u30a6\u30f3\u30c8\u53c2\u7167] \u30c6\u30fc\u30d6\u30eb\u3067\u30a2\u30ab\u30a6\u30f3\u30c8\u3092\u53f3\u30af\u30ea\u30c3\u30af\u3057\u3001[\u53ef\u8996\u5316] \u3092\u9078\u629e\u3057\u3066\u958b\u59cb\u3057\u307e\u3059\u3002
# {0} - \u30ec\u30a4\u30a2\u30a6\u30c8\u540d
VisualizationPanel.layoutFail.text={0} \u30ec\u30a4\u30a2\u30a6\u30c8\u304c\u5931\u6557\u3057\u307e\u3057\u305f\u3002\u5225\u306e\u30ec\u30a4\u30a2\u30a6\u30c8\u3092\u304a\u8a66\u3057\u304f\u3060\u3055\u3044\u3002
# {0} - \u30ec\u30a4\u30a2\u30a6\u30c8\u540d

View File

@ -0,0 +1,166 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2020 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.communications;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.ingest.IngestManager;
import static org.sleuthkit.autopsy.ingest.IngestManager.IngestModuleEvent.DATA_ADDED;
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
import org.sleuthkit.datamodel.Account;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.TskCoreException;
/**
* A singleton cache of the Contact artifacts for accounts. The map of account
* unique ids to list of contact artifacts is stored in a LoadingCache which
* expires after 10 of non-use.
*
*/
final class ContactCache {
private static final Logger logger = Logger.getLogger(ContactCache.class.getName());
private static ContactCache instance;
private final LoadingCache<String, Map<String, List<BlackboardArtifact>>> accountMap;
/**
* Returns the list of Contacts for the given Account.
*
* @param account Account instance.
*
* @return List of TSK_CONTACT artifacts that references the given Account.
* An empty list is returned if no contacts are found.
*
* @throws ExecutionException
*/
static synchronized List<BlackboardArtifact> getContacts(Account account) throws ExecutionException {
return getInstance().accountMap.get("realMap").get(account.getTypeSpecificID());
}
/**
* Force the cache to invalidate all entries.
*/
static synchronized void invalidateCache() {
getInstance().accountMap.invalidateAll();
}
/**
* Construct a new instance.
*/
private ContactCache() {
accountMap = CacheBuilder.newBuilder().expireAfterAccess(10, TimeUnit.MINUTES).build(
new CacheLoader<String, Map<String, List<BlackboardArtifact>>>() {
@Override
public Map<String, List<BlackboardArtifact>> load(String key) {
try {
return buildMap();
} catch (SQLException | TskCoreException ex) {
logger.log(Level.WARNING, "Failed to build account to contact map", ex);
}
return new HashMap<>(); // Return an empty map if there is an exception to avoid NPE and continual trying.
}
});
PropertyChangeListener ingestListener = pce -> {
String eventType = pce.getPropertyName();
if (eventType.equals(DATA_ADDED.toString())) {
ModuleDataEvent eventData = (ModuleDataEvent) pce.getOldValue();
if (eventData.getBlackboardArtifactType().getTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT.getTypeID()) {
invalidateCache();
}
}
};
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), (PropertyChangeEvent event) -> {
if (event.getNewValue() == null) {
invalidateCache();
}
});
IngestManager.getInstance().addIngestModuleEventListener(EnumSet.of(DATA_ADDED), ingestListener);
}
/**
* Returns the singleton instance of the cache object.
*
* @return AccountCache instance.
*/
private static synchronized ContactCache getInstance() {
if (instance == null) {
instance = new ContactCache();
}
return instance;
}
/**
* Builds the map of account IDs to contacts that reference them.
*
* @return A map of account IDs to contact artifacts.
*
* @throws TskCoreException
* @throws SQLException
*/
private Map<String, List<BlackboardArtifact>> buildMap() throws TskCoreException, SQLException {
Map<String, List<BlackboardArtifact>> acctMap = new HashMap<>();
List<BlackboardArtifact> contactList = Case.getCurrentCase().getSleuthkitCase().getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT);
for (BlackboardArtifact contactArtifact : contactList) {
List<BlackboardAttribute> contactAttributes = contactArtifact.getAttributes();
for (BlackboardAttribute attribute : contactAttributes) {
String typeName = attribute.getAttributeType().getTypeName();
if (typeName.startsWith("TSK_EMAIL")
|| typeName.startsWith("TSK_PHONE")
|| typeName.startsWith("TSK_NAME")
|| typeName.startsWith("TSK_ID")) {
String accountID = attribute.getValueString();
List<BlackboardArtifact> artifactList = acctMap.getOrDefault(accountID, new ArrayList<>());
acctMap.put(accountID, artifactList);
if (!artifactList.contains(contactArtifact)) {
artifactList.add(contactArtifact);
}
}
}
}
return acctMap;
}
}

View File

@ -18,9 +18,12 @@
*/
package org.sleuthkit.autopsy.communications;
import java.awt.Component;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.TimeZone;
import javax.swing.table.TableCellRenderer;
import org.netbeans.swing.outline.Outline;
import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.autopsy.datamodel.accounts.Accounts;
import org.sleuthkit.datamodel.Account;
@ -47,5 +50,29 @@ public final class Utils {
static public final String getIconFilePath(Account.Type type) {
return Accounts.getIconFilePath(type);
}
static public void setColumnWidths(Outline outline) {
int margin = 4;
int padding = 8;
final int rows = Math.min(100, outline.getRowCount());
for (int column = 0; column < outline.getColumnCount(); column++) {
int columnWidthLimit = 500;
int columnWidth = 0;
// find the maximum width needed to fit the values for the first 100 rows, at most
for (int row = 0; row < rows; row++) {
TableCellRenderer renderer = outline.getCellRenderer(row, column);
Component comp = outline.prepareRenderer(renderer, row, column);
columnWidth = Math.max(comp.getPreferredSize().width, columnWidth);
}
columnWidth += 2 * margin + padding; // add margin and regular padding
columnWidth = Math.min(columnWidth, columnWidthLimit);
outline.getColumnModel().getColumn(column).setPreferredWidth(columnWidth);
}
}
}

View File

@ -32,39 +32,21 @@
</Constraint>
</Constraints>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace pref="316" max="32767" attributes="0"/>
<Component id="jTextArea1" min="-2" pref="424" max="-2" attributes="0"/>
<EmptySpace pref="481" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="32767" attributes="0"/>
<Component id="jTextArea1" min="-2" pref="47" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Component class="javax.swing.JTextArea" name="jTextArea1">
<Component class="javax.swing.JTextPane" name="jTextPane1">
<Properties>
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="f0" green="f0" red="f0" type="rgb"/>
</Property>
<Property name="columns" type="int" value="20"/>
<Property name="lineWrap" type="boolean" value="true"/>
<Property name="rows" type="int" value="5"/>
<Property name="editable" type="boolean" value="false"/>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="VisualizationPanel.jTextArea1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="VisualizationPanel.jTextPane1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="opaque" type="boolean" value="false"/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="-1" gridY="-1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="50" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="11" weightX="0.0" weightY="1.0"/>
</Constraint>
</Constraints>
</Component>
</SubComponents>
</Container>

View File

@ -46,7 +46,10 @@ import java.awt.Dimension;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
@ -86,8 +89,8 @@ import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.JToolBar;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
@ -370,10 +373,11 @@ final public class VisualizationPanel extends JPanel {
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
GridBagConstraints gridBagConstraints;
borderLayoutPanel = new JPanel();
placeHolderPanel = new JPanel();
jTextArea1 = new JTextArea();
jTextPane1 = new JTextPane();
notificationsJFXPanel = new JFXPanel();
toolbar = new JToolBar();
backButton = new JButton();
@ -395,26 +399,16 @@ final public class VisualizationPanel extends JPanel {
borderLayoutPanel.setLayout(new BorderLayout());
jTextArea1.setBackground(new Color(240, 240, 240));
jTextArea1.setColumns(20);
jTextArea1.setLineWrap(true);
jTextArea1.setRows(5);
jTextArea1.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.jTextArea1.text")); // NOI18N
placeHolderPanel.setLayout(new GridBagLayout());
GroupLayout placeHolderPanelLayout = new GroupLayout(placeHolderPanel);
placeHolderPanel.setLayout(placeHolderPanelLayout);
placeHolderPanelLayout.setHorizontalGroup(placeHolderPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addGroup(placeHolderPanelLayout.createSequentialGroup()
.addContainerGap(316, Short.MAX_VALUE)
.addComponent(jTextArea1, GroupLayout.PREFERRED_SIZE, 424, GroupLayout.PREFERRED_SIZE)
.addContainerGap(481, Short.MAX_VALUE))
);
placeHolderPanelLayout.setVerticalGroup(placeHolderPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addGroup(placeHolderPanelLayout.createSequentialGroup()
.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jTextArea1, GroupLayout.PREFERRED_SIZE, 47, GroupLayout.PREFERRED_SIZE)
.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
jTextPane1.setEditable(false);
jTextPane1.setText(NbBundle.getMessage(VisualizationPanel.class, "VisualizationPanel.jTextPane1.text")); // NOI18N
jTextPane1.setOpaque(false);
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.anchor = GridBagConstraints.NORTH;
gridBagConstraints.weighty = 1.0;
gridBagConstraints.insets = new Insets(50, 0, 0, 0);
placeHolderPanel.add(jTextPane1, gridBagConstraints);
borderLayoutPanel.add(placeHolderPanel, BorderLayout.CENTER);
borderLayoutPanel.add(notificationsJFXPanel, BorderLayout.PAGE_END);
@ -854,7 +848,7 @@ final public class VisualizationPanel extends JPanel {
private JToolBar.Separator jSeparator1;
private JToolBar.Separator jSeparator2;
private JToolBar.Separator jSeparator3;
private JTextArea jTextArea1;
private JTextPane jTextPane1;
private JFXPanel notificationsJFXPanel;
private JPanel placeHolderPanel;
private JButton snapshotButton;

View File

@ -73,5 +73,5 @@ SummaryViewer.referencesLabel.text=Communication References:
SummaryViewer.referencesDataLabel.text=<reference count>
SummaryViewer.contactsLabel.text=Book Entries:
SummaryViewer.accountCountry.text=<account country>
SummaryViewer.fileRefPane.border.title=File Referernce(s) in Current Case
SummaryViewer.fileRefPane.border.title=File References in Current Case
SummaryViewer.selectAccountFileRefLabel.text=<Select a single account to see File References>

View File

@ -38,6 +38,8 @@ import javax.swing.JPanel;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import static javax.swing.SwingUtilities.isDescendingFrom;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import org.netbeans.swing.outline.DefaultOutlineModel;
import org.netbeans.swing.outline.Outline;
import org.openide.explorer.ExplorerManager;
@ -50,6 +52,7 @@ import org.openide.nodes.Node.PropertySet;
import org.openide.util.Lookup;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.communications.ModifiableProxyLookup;
import org.sleuthkit.autopsy.communications.Utils;
import org.sleuthkit.autopsy.coreutils.Logger;
/**
@ -115,6 +118,13 @@ final class MessageViewer extends JPanel implements RelationshipsViewer {
showSelectedThread();
}
});
rootTablePane.getOutlineView().getOutline().getModel().addTableModelListener(new TableModelListener() {
@Override
public void tableChanged(TableModelEvent e) {
Utils.setColumnWidths(rootTablePane.getOutlineView().getOutline());
}
});
threadMessagesPanel.setChildFactory(threadMessageNodeFactory);

View File

@ -26,6 +26,9 @@ CallLogArtifactViewer_label_from=From
CallLogArtifactViewer_label_to=To
CallLogArtifactViewer_suffix_local=(Local)
CallLogArtifactViewer_value_unknown=Unknown
#{0} - contact name
CommunicationArtifactViewerHelper_contact_label=Contact: {0}
CommunicationArtifactViewerHelper_contact_label_unknown=Unknown
CommunicationArtifactViewerHelper_menuitem_copy=Copy
CommunicationArtifactViewerHelper_persona_button_create=Create
CommunicationArtifactViewerHelper_persona_button_view=View
@ -51,7 +54,6 @@ ContactArtifactViewer_persona_no_match=No matches found
ContactArtifactViewer_persona_searching=Searching...
ContactArtifactViewer_persona_unknown=Unknown
ContactArtifactViewer_phones_header=Phone
ContactArtifactViewer_plural_suffix=s
DataContentViewerArtifact.failedToGetAttributes.message=Failed to get some or all attributes from case database
DataContentViewerArtifact.failedToGetSourcePath.message=Failed to get source file path from case database
DefaultArtifactContentViewer.attrsTableHeader.sources=Source(s)
@ -61,6 +63,7 @@ DefaultArtifactContentViewer.copyMenuItem.text=Copy
DefaultArtifactContentViewer.selectAllMenuItem.text=Select All
MessageAccountPanel_button_create_label=Create
MessageAccountPanel_button_view_label=View
MessageAccountPanel_contact_label=Contact:
MessageAccountPanel_no_matches=No matches found.
MessageAccountPanel_persona_label=Persona:
MessageAccountPanel_unknown_label=Unknown

View File

@ -36,6 +36,7 @@ import org.openide.util.NbBundle;
import org.openide.util.lookup.ServiceProvider;
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.guiutils.ContactCache;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.Content;
@ -66,7 +67,7 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac
private GridBagLayout m_gridBagLayout = new GridBagLayout();
private GridBagConstraints m_constraints = new GridBagConstraints();
private PersonaAccountFetcher currentAccountFetcher = null;
/**
@ -106,9 +107,9 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac
// update the view with the call log data
if (callLogViewData != null) {
List<AccountPersonaSearcherData> personaSearchDataList = updateView(callLogViewData);
if(!personaSearchDataList.isEmpty()) {
if (!personaSearchDataList.isEmpty()) {
currentAccountFetcher = new PersonaAccountFetcher(artifact, personaSearchDataList, this);
currentAccountFetcher.execute();
currentAccountFetcher.execute();
} else {
currentAccountFetcher = null;
}
@ -143,6 +144,8 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac
String fromAccountIdentifier = null;
String toAccountIdentifier = null;
List<String> otherParties = null;
List<String> toContactNames = null;
List<String> fromContactNames = null;
Content dataSource = artifact.getDataSource();
String deviceId = ((DataSource) dataSource).getDeviceId();
@ -186,6 +189,7 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac
String fromAccountAttrValue = fromAccountAttr.getValueString();
if (fromAccountAttrValue.equalsIgnoreCase(deviceId) == false) {
fromAccountIdentifier = fromAccountAttrValue;
fromContactNames = ContactCache.getContactNameList(fromAccountIdentifier);
}
}
@ -195,6 +199,7 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac
String toAccountAttrValue = StringUtils.trim(numbers[0]);
if (toAccountAttrValue.equalsIgnoreCase(deviceId) == false) {
toAccountIdentifier = toAccountAttrValue;
toContactNames = ContactCache.getContactNameList(toAccountIdentifier);
}
// if more than one To address, then stick the rest of them in the
@ -228,6 +233,9 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac
}
callLogViewData.setOtherAttributes(extractOtherAttributes(artifact));
callLogViewData.setFromContactNameList(fromContactNames);
callLogViewData.setToContactNameList(toContactNames);
}
return callLogViewData;
@ -237,9 +245,9 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac
* Extract the call time and duration from the artifact and saves in the
* CallLogViewData.
*
* @param artifact Call log artifact.
* @param artifact Call log artifact.
* @param callLogViewData CallLogViewData object to save the time & duration
* in.
* in.
*
* @throws TskCoreException
*/
@ -290,7 +298,7 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac
* Update the viewer with the call log data.
*
* @param callLogViewData Call log data to update the view with.
*
*
* @return List of AccountPersonaSearcherData objects.
*/
@NbBundle.Messages({
@ -312,8 +320,13 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac
String accountDisplayString = getAccountDisplayString(callLogViewData.getFromAccount(), callLogViewData);
CommunicationArtifactViewerHelper.addValue(this, m_gridBagLayout, this.m_constraints, accountDisplayString);
List<String> contactNames = callLogViewData.getFromContactNameList();
for (String name : contactNames) {
CommunicationArtifactViewerHelper.addContactRow(this, m_gridBagLayout, m_constraints, name);
}
// show persona
dataList.addAll( CommunicationArtifactViewerHelper.addPersonaRow(this, m_gridBagLayout, this.m_constraints, callLogViewData.getFromAccount()));
dataList.addAll(CommunicationArtifactViewerHelper.addPersonaRow(this, m_gridBagLayout, this.m_constraints, callLogViewData.getFromAccount()));
} else {
CommunicationArtifactViewerHelper.addValue(this, m_gridBagLayout, this.m_constraints, Bundle.CallLogArtifactViewer_value_unknown());
}
@ -324,8 +337,13 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac
String accountDisplayString = getAccountDisplayString(callLogViewData.getToAccount(), callLogViewData);
CommunicationArtifactViewerHelper.addValue(this, m_gridBagLayout, this.m_constraints, accountDisplayString);
dataList.addAll( CommunicationArtifactViewerHelper.addPersonaRow(this, m_gridBagLayout, this.m_constraints, callLogViewData.getToAccount()));
List<String> contactNames = callLogViewData.getToContactNameList();
for (String name : contactNames) {
CommunicationArtifactViewerHelper.addContactRow(this, m_gridBagLayout, m_constraints, name);
}
dataList.addAll(CommunicationArtifactViewerHelper.addPersonaRow(this, m_gridBagLayout, this.m_constraints, callLogViewData.getToAccount()));
} else {
CommunicationArtifactViewerHelper.addValue(this, m_gridBagLayout, this.m_constraints, Bundle.CallLogArtifactViewer_value_unknown());
}
@ -335,7 +353,7 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac
CommunicationArtifactViewerHelper.addKey(this, m_gridBagLayout, this.m_constraints, Bundle.CallLogArtifactViewer_label_to());
CommunicationArtifactViewerHelper.addValue(this, m_gridBagLayout, this.m_constraints, otherParty);
dataList.addAll( CommunicationArtifactViewerHelper.addPersonaRow(this, m_gridBagLayout, this.m_constraints, otherParty));
dataList.addAll(CommunicationArtifactViewerHelper.addPersonaRow(this, m_gridBagLayout, this.m_constraints, otherParty));
}
updateMetadataView(callLogViewData);
@ -353,7 +371,7 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac
this.setLayout(m_gridBagLayout);
this.revalidate();
this.repaint();
return dataList;
}
@ -441,7 +459,7 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac
* local account, if it is known. If it is, it appends a "(Local)" suffix to
* account display string.
*
* @param accountIdentifier Account identifier to check.
* @param accountIdentifier Account identifier to check.
* @param callLogViewDataNew Call log data which may have the lock account.
*
* @return Account string to display.
@ -474,7 +492,7 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac
private void resetComponent() {
// cancel any outstanding persona searching threads.
if(currentAccountFetcher != null && !currentAccountFetcher.isDone()) {
if (currentAccountFetcher != null && !currentAccountFetcher.isDone()) {
currentAccountFetcher.cancel(true);
currentAccountFetcher = null;
}

View File

@ -22,6 +22,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
@ -47,11 +48,14 @@ final class CallLogViewData {
private String dataSourceName = null;
private List<String> toContactNameList = null;
private List<String> fromContactNameList = null;
/**
* Constructor.
*
* @param fromAccount From account identifier, may be null;
* @param toAccount To account identifier, may be null;
* @param toAccount To account identifier, may be null;
*/
CallLogViewData(String fromAccount, String toAccount) {
this(fromAccount, toAccount, null);
@ -61,8 +65,8 @@ final class CallLogViewData {
* Constructor.
*
* @param fromAccount From account identifier, may be null;
* @param toAccount To account identifier, may be null;
* @param direction Direction, may be null.
* @param toAccount To account identifier, may be null;
* @param direction Direction, may be null.
*/
CallLogViewData(String fromAccount, String toAccount, String direction) {
this.fromAccount = fromAccount;
@ -146,4 +150,28 @@ final class CallLogViewData {
this.localAccountId = localAccountId;
}
public void setToContactNameList(List<String> contactNameList) {
if (contactNameList != null) {
this.toContactNameList = new ArrayList<>(contactNameList);
} else {
this.toContactNameList = new ArrayList<>();
}
}
public List<String> getToContactNameList() {
return Collections.unmodifiableList(this.toContactNameList);
}
public void setFromContactNameList(List<String> contactNameList) {
if (contactNameList != null) {
this.fromContactNameList = new ArrayList<>(contactNameList);
} else {
this.fromContactNameList = new ArrayList<>();
}
}
public List<String> getFromContactNameList() {
return Collections.unmodifiableList(this.fromContactNameList);
}
}

View File

@ -378,7 +378,7 @@ final class CommunicationArtifactViewerHelper {
"CommunicationArtifactViewerHelper_persona_button_view=View",
"CommunicationArtifactViewerHelper_persona_button_create=Create"
})
static List<AccountPersonaSearcherData> addPersonaRow(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints, String accountIdentifier) {
List<AccountPersonaSearcherData> dataList = new ArrayList<>();
@ -428,6 +428,35 @@ final class CommunicationArtifactViewerHelper {
return dataList;
}
/**
* Adds a contact row to the panel.
*
* @param panel Panel to update.
* @param gridbagLayout Layout to use.
* @param constraints Constrains to use.
* @param contactId Contact name to display.
*
* @return A JLabel with the contact information.
*/
@NbBundle.Messages({
"#{0} - contact name",
"CommunicationArtifactViewerHelper_contact_label=Contact: {0}",
"CommunicationArtifactViewerHelper_contact_label_unknown=Unknown"
})
static JLabel addContactRow(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints, String contactId) {
// Increase the y value because we are not calling the addKey
constraints.gridy++;
//Don't change the origian constraints, just make a copy to modify
GridBagConstraints indentedConstraints = (GridBagConstraints) constraints.clone();
// Add an indent to match persona labels
indentedConstraints.insets = new java.awt.Insets(0, 2 * LEFT_INSET, 0, 0);
String contactInfo = Bundle.CommunicationArtifactViewerHelper_contact_label(contactId != null && !contactId.isEmpty() ? contactId : Bundle.CommunicationArtifactViewerHelper_contact_label_unknown());
return addValueAtCol(panel, gridbagLayout, indentedConstraints, contactInfo, 1);
}
/**
* Event handler for mouse click event. Attaches a 'Copy' menu item to right

View File

@ -293,8 +293,6 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac
* @param contactPanelConstraints Layout constraints.
*
*/
@NbBundle.Messages({
"ContactArtifactViewer_plural_suffix=s",})
private void updateContactMethodSection(List<BlackboardAttribute> sectionAttributesList, String sectionHeader, GridBagLayout contactPanelLayout, GridBagConstraints contactPanelConstraints) {
// If there are no attributes for this section, do nothing
@ -302,11 +300,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac
return;
}
String sectionHeaderString = sectionHeader;
if (sectionAttributesList.size() > 1) {
sectionHeaderString = sectionHeaderString.concat(Bundle.ContactArtifactViewer_plural_suffix());
}
CommunicationArtifactViewerHelper.addHeader(this, contactPanelLayout, contactPanelConstraints, sectionHeaderString);
CommunicationArtifactViewerHelper.addHeader(this, contactPanelLayout, contactPanelConstraints, sectionHeader);
for (BlackboardAttribute bba : sectionAttributesList) {
CommunicationArtifactViewerHelper.addKey(this, contactPanelLayout, contactPanelConstraints, bba.getAttributeType().getDisplayName());
CommunicationArtifactViewerHelper.addValue(this, contactPanelLayout, contactPanelConstraints, bba.getDisplayString());

View File

@ -16,7 +16,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.contentviewers.artifactviewers;
import java.awt.event.ActionEvent;
@ -39,6 +38,7 @@ import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
import org.sleuthkit.autopsy.centralrepository.datamodel.Persona;
import org.sleuthkit.autopsy.centralrepository.datamodel.PersonaAccount;
import org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsDialog;
@ -46,8 +46,10 @@ import org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsDialogCallb
import org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsMode;
import org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsPanel;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.guiutils.ContactCache;
import org.sleuthkit.datamodel.Account;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.CommunicationsManager;
import org.sleuthkit.datamodel.TskCoreException;
@ -113,13 +115,24 @@ final class MessageAccountPanel extends JPanel {
return new ArrayList<>();
}
Collection<PersonaAccount> personAccounts = PersonaAccount.getPersonaAccountsForAccount(account);
if (personAccounts != null && !personAccounts.isEmpty()) {
for (PersonaAccount personaAccount : PersonaAccount.getPersonaAccountsForAccount(account)) {
dataList.add(new AccountContainer(account, personaAccount));
List<BlackboardArtifact> contactList = ContactCache.getContacts(account);
BlackboardArtifact contact = null;
if (contactList != null && !contactList.isEmpty()) {
contact = contactList.get(0);
}
if (CentralRepository.isEnabled()) {
Collection<PersonaAccount> personAccounts = PersonaAccount.getPersonaAccountsForAccount(account);
if (personAccounts != null && !personAccounts.isEmpty()) {
for (PersonaAccount personaAccount : PersonaAccount.getPersonaAccountsForAccount(account)) {
dataList.add(new AccountContainer(account, personaAccount, contact));
}
} else {
dataList.add(new AccountContainer(account, null, contact));
}
} else {
dataList.add(new AccountContainer(account, null));
dataList.add(new AccountContainer(account, null, contact));
}
}
@ -127,8 +140,7 @@ final class MessageAccountPanel extends JPanel {
}
@Messages({
"MessageAccountPanel_no_matches=No matches found.",
})
"MessageAccountPanel_no_matches=No matches found.",})
@Override
protected void done() {
try {
@ -199,6 +211,7 @@ final class MessageAccountPanel extends JPanel {
for (AccountContainer o : data) {
group.addGap(5)
.addComponent(o.getAccountLabel())
.addGroup(o.getContactLineVerticalGroup(layout))
.addGroup(o.getPersonLineVerticalGroup(layout));
}
@ -234,6 +247,7 @@ final class MessageAccountPanel extends JPanel {
group.addGap(10);
for (AccountContainer o : data) {
pgroup.addGroup(o.getPersonaSequentialGroup(layout));
pgroup.addGroup(o.getContactSequentialGroup(layout));
}
group.addGap(10)
.addGroup(pgroup)
@ -253,10 +267,13 @@ final class MessageAccountPanel extends JPanel {
private final Account account;
private Persona persona = null;
private final String contactName;
private JLabel accountLabel;
private JLabel personaHeader;
private JLabel personaDisplayName;
private JLabel contactHeader;
private JLabel contactDisplayName;
private JButton button;
/**
@ -265,16 +282,22 @@ final class MessageAccountPanel extends JPanel {
* @param account
* @param personaAccount
*/
AccountContainer(Account account, PersonaAccount personaAccount) {
AccountContainer(Account account, PersonaAccount personaAccount, BlackboardArtifact contactArtifact) throws TskCoreException {
if (contactArtifact != null && contactArtifact.getArtifactTypeID() != BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT.getTypeID()) {
throw new IllegalArgumentException("Failed to create AccountContainer object, passed in artifact was not a TSK_CONTACT");
}
this.account = account;
this.persona = personaAccount != null ? personaAccount.getPersona() : null;
this.contactName = getNameFromContactArtifact(contactArtifact);
}
@Messages({
"MessageAccountPanel_persona_label=Persona:",
"MessageAccountPanel_unknown_label=Unknown",
"MessageAccountPanel_button_view_label=View",
"MessageAccountPanel_button_create_label=Create"
"MessageAccountPanel_button_create_label=Create",
"MessageAccountPanel_contact_label=Contact:"
})
/**
* Swing components will not be initialized until this method is called.
@ -282,16 +305,29 @@ final class MessageAccountPanel extends JPanel {
private void initalizeSwingControls() {
accountLabel = new JLabel();
personaHeader = new JLabel(Bundle.MessageAccountPanel_persona_label());
contactHeader = new JLabel(Bundle.MessageAccountPanel_contact_label());
personaDisplayName = new JLabel();
contactDisplayName = new JLabel();
button = new JButton();
button.addActionListener(new PersonaButtonListener(this));
accountLabel.setText(account.getTypeSpecificID());
contactDisplayName.setText(contactName);
personaDisplayName.setText(persona != null ? persona.getName() : Bundle.MessageAccountPanel_unknown_label());
button.setText(persona != null ? Bundle.MessageAccountPanel_button_view_label() : Bundle.MessageAccountPanel_button_create_label());
}
private String getNameFromContactArtifact(BlackboardArtifact contactArtifact) throws TskCoreException {
if (contactArtifact != null) {
BlackboardAttribute attribute = contactArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME));
if (attribute != null) {
return attribute.getValueString();
}
}
return Bundle.MessageAccountPanel_unknown_label();
}
/**
* Sets a new persona for this object and update the controls.
*
@ -365,6 +401,17 @@ final class MessageAccountPanel extends JPanel {
return group;
}
private SequentialGroup getContactSequentialGroup(GroupLayout layout) {
SequentialGroup group = layout.createSequentialGroup();
group
.addComponent(contactHeader)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(contactDisplayName);
return group;
}
/**
* Generates the vertical layout code for the persona line.
@ -379,6 +426,12 @@ final class MessageAccountPanel extends JPanel {
.addComponent(personaDisplayName)
.addComponent(button);
}
private ParallelGroup getContactLineVerticalGroup(GroupLayout layout) {
return layout.createParallelGroup(Alignment.BASELINE)
.addComponent(contactHeader)
.addComponent(contactDisplayName);
}
}
/**

View File

@ -447,10 +447,8 @@ public class MessageArtifactViewer extends javax.swing.JPanel implements Artifac
resetComponent();
}
msgbodyTabbedPane.setEnabledAt(ACCT_TAB_INDEX, CentralRepository.isEnabled());
if(CentralRepository.isEnabled()) {
accountsPanel.setArtifact(artifact);
}
msgbodyTabbedPane.setEnabledAt(ACCT_TAB_INDEX, true);
accountsPanel.setArtifact(artifact);
}
/**

View File

@ -230,6 +230,7 @@ public class Installer extends ModuleInstall {
packageInstallers.add(org.sleuthkit.autopsy.ingest.Installer.getDefault());
packageInstallers.add(org.sleuthkit.autopsy.centralrepository.eventlisteners.Installer.getDefault());
packageInstallers.add(org.sleuthkit.autopsy.healthmonitor.Installer.getDefault());
packageInstallers.add(org.sleuthkit.autopsy.casemodule.Installer.getDefault());
/**
* This is a temporary workaround for the following bug in Tika that

View File

@ -26,6 +26,7 @@ import java.util.prefs.PreferenceChangeListener;
import java.util.prefs.Preferences;
import org.openide.util.NbPreferences;
import org.python.icu.util.TimeZone;
import org.sleuthkit.autopsy.machinesettings.UserMachinePreferences;
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
import org.sleuthkit.autopsy.coreutils.TextConverterException;
import org.sleuthkit.autopsy.coreutils.Version;
@ -83,7 +84,7 @@ public final class UserPreferences {
private static final String GEO_OSM_TILE_ZIP_PATH = "GeolocationOsmZipPath";
private static final String GEO_OSM_SERVER_ADDRESS = "GeolocationOsmServerAddress";
private static final String GEO_MBTILES_FILE_PATH = "GeolcoationMBTilesFilePath";
// Prevent instantiation.
private UserPreferences() {
}
@ -612,4 +613,14 @@ public final class UserPreferences {
public static String getGeolocationMBTilesFilePath() {
return preferences.get(GEO_MBTILES_FILE_PATH, "");
}
/**
* Retrieves the root application temp directory.
*
* @return The absolute path to the application temp directory.
*/
public static String getAppTempDirectory() {
return Paths.get(UserMachinePreferences.getBaseTempDirectory(), getAppName())
.toAbsolutePath().toString();
}
}

View File

@ -11,7 +11,7 @@
</NonVisualComponents>
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[1022, 488]"/>
<Dimension value="null"/>
</Property>
</Properties>
<AuxValues>
@ -29,15 +29,12 @@
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jScrollPane1" alignment="0" max="32767" attributes="0"/>
<Component id="jScrollPane1" alignment="0" pref="648" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="jScrollPane1" max="32767" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
<Component id="jScrollPane1" alignment="0" pref="382" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
@ -48,7 +45,7 @@
<Border info="null"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[1022, 407]"/>
<Dimension value="null"/>
</Property>
</Properties>
@ -56,21 +53,24 @@
<SubComponents>
<Container class="javax.swing.JPanel" name="jPanel1">
<Properties>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[648, 382]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[1022, 407]"/>
<Dimension value="null"/>
</Property>
</Properties>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="runtimePanel" max="32767" attributes="0"/>
<Component id="logoPanel" alignment="0" pref="1002" max="32767" attributes="0"/>
<Group type="103" groupAlignment="1" max="-2" attributes="0">
<Component id="logoPanel" max="32767" attributes="0"/>
<Component id="tempDirectoryPanel" alignment="0" max="32767" attributes="0"/>
<Component id="runtimePanel" min="-2" pref="631" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -79,9 +79,11 @@
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="runtimePanel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="3" max="-2" attributes="0"/>
<Component id="tempDirectoryPanel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="logoPanel" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="171" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -96,9 +98,6 @@
</TitledBorder>
</Border>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[533, 87]"/>
</Property>
</Properties>
<Layout>
@ -112,16 +111,16 @@
</Group>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="agencyLogoPathFieldValidationLabel" min="-2" max="-2" attributes="0"/>
<Group type="102" attributes="0">
<Component id="agencyLogoPathField" min="-2" pref="259" max="-2" attributes="0"/>
<Component id="agencyLogoPathField" min="-2" pref="270" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="browseLogosButton" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="agencyLogoPathFieldValidationLabel" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="agencyLogoPreview" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="456" max="32767" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -142,7 +141,7 @@
</Group>
<Group type="102" alignment="1" attributes="0">
<Component id="agencyLogoPreview" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
<EmptySpace min="0" pref="12" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -266,18 +265,18 @@
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="23" max="-2" attributes="0"/>
<Component id="memFieldValidationLabel" min="-2" pref="478" max="-2" attributes="0"/>
<EmptySpace pref="246" max="32767" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="18" max="-2" attributes="0"/>
<Component id="solrJVMHeapWarning" pref="717" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="solrJVMHeapWarning" min="-2" pref="331" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="44" max="-2" attributes="0"/>
<Component id="logNumAlert" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</Group>
<Component id="restartNecessaryWarning" alignment="0" pref="994" max="32767" attributes="0"/>
<Component id="restartNecessaryWarning" alignment="0" min="-2" pref="615" max="-2" attributes="0"/>
</Group>
</Group>
</Group>
@ -317,7 +316,7 @@
</Group>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="restartNecessaryWarning" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -438,6 +437,87 @@
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="tempDirectoryPanel">
<Properties>
<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="Temp Directory">
<ResourceString PropertyName="titleX" bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="AutopsyOptionsPanel.tempDirectoryPanel.border.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</TitledBorder>
</Border>
</Property>
<Property name="name" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="AutopsyOptionsPanel.tempDirectoryPanel.name" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<AccessibilityProperties>
<Property name="AccessibleContext.accessibleName" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="AutopsyOptionsPanel.tempDirectoryPanel.AccessibleContext.accessibleName" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</AccessibilityProperties>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="tempDirectoryWarningLabel" min="-2" pref="615" max="-2" attributes="0"/>
<Group type="102" attributes="0">
<Component id="tempDirectoryField" min="-2" pref="367" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="tempDirectoryBrowseButton" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="tempDirectoryField" alignment="3" max="32767" attributes="0"/>
<Component id="tempDirectoryBrowseButton" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="tempDirectoryWarningLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JTextField" name="tempDirectoryField">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="AutopsyOptionsPanel.tempDirectoryField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="tempDirectoryBrowseButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="AutopsyOptionsPanel.tempDirectoryBrowseButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="tempDirectoryBrowseButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="tempDirectoryWarningLabel">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/corecomponents/warning16.png"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="AutopsyOptionsPanel.tempDirectoryWarningLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Container>
</SubComponents>

View File

@ -24,6 +24,7 @@ import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
@ -34,13 +35,17 @@ import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import org.netbeans.spi.options.OptionsPanelController;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.GeneralFilter;
import org.sleuthkit.autopsy.machinesettings.UserMachinePreferences;
import org.sleuthkit.autopsy.machinesettings.UserMachinePreferencesException;
import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
@ -70,7 +75,8 @@ import org.sleuthkit.autopsy.report.ReportBranding;
final class AutopsyOptionsPanel extends javax.swing.JPanel {
private static final long serialVersionUID = 1L;
private final JFileChooser fileChooser;
private final JFileChooser logoFileChooser;
private final JFileChooser tempDirChooser;
private final TextFieldListener textFieldListener;
private static final String ETC_FOLDER_NAME = "etc";
private static final String CONFIG_FILE_EXTENSION = ".conf";
@ -85,11 +91,16 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
*/
AutopsyOptionsPanel() {
initComponents();
fileChooser = new JFileChooser();
fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
fileChooser.setMultiSelectionEnabled(false);
fileChooser.setAcceptAllFileFilterUsed(false);
fileChooser.setFileFilter(new GeneralFilter(GeneralFilter.GRAPHIC_IMAGE_EXTS, GeneralFilter.GRAPHIC_IMG_DECR));
logoFileChooser = new JFileChooser();
logoFileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
logoFileChooser.setMultiSelectionEnabled(false);
logoFileChooser.setAcceptAllFileFilterUsed(false);
logoFileChooser.setFileFilter(new GeneralFilter(GeneralFilter.GRAPHIC_IMAGE_EXTS, GeneralFilter.GRAPHIC_IMG_DECR));
tempDirChooser = new JFileChooser();
tempDirChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
tempDirChooser.setMultiSelectionEnabled(false);
if (!PlatformUtil.is64BitJVM() || Version.getBuildType() == Version.Type.DEVELOPMENT) {
//32 bit JVM has a max heap size of 1.4 gb to 4 gb depending on OS
//So disabling the setting of heap size when the JVM is not 64 bit
@ -102,10 +113,11 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
// The cast to int in the following is to ensure that the correct SpinnerNumberModel
// constructor is called.
solrMaxHeapSpinner.setModel(new javax.swing.SpinnerNumberModel(UserPreferences.getMaxSolrVMSize(),
512, ((int)getSystemMemoryInGB()) * MEGA_IN_GIGA, 512));
512, ((int) getSystemMemoryInGB()) * MEGA_IN_GIGA, 512));
textFieldListener = new TextFieldListener();
agencyLogoPathField.getDocument().addDocumentListener(textFieldListener);
tempDirectoryField.getDocument().addDocumentListener(textFieldListener);
logFileCount.setText(String.valueOf(UserPreferences.getLogFileCount()));
}
@ -296,8 +308,10 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
specifyLogoRB.setSelected(!useDefault);
agencyLogoPathField.setEnabled(!useDefault);
browseLogosButton.setEnabled(!useDefault);
tempDirectoryField.setText(UserMachinePreferences.getBaseTempDirectory());
logFileCount.setText(String.valueOf(UserPreferences.getLogFileCount()));
solrMaxHeapSpinner.setValue(UserPreferences.getMaxSolrVMSize());
tempDirectoryField.setText(UserMachinePreferences.getBaseTempDirectory());
try {
updateAgencyLogo(path);
} catch (IOException ex) {
@ -312,10 +326,17 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
}
memField.setText(initialMemValue);
}
setTempDirEnabled();
valid(); //ensure the error messages are up to date
}
private void setTempDirEnabled() {
boolean enabled = !Case.isCaseOpen();
this.tempDirectoryBrowseButton.setEnabled(enabled);
this.tempDirectoryField.setEnabled(enabled);
this.tempDirectoryWarningLabel.setVisible(!enabled);
}
/**
* Update the agency logo with the image specified by the path.
*
@ -342,11 +363,34 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
agencyLogoPreview.repaint();
}
@Messages({
"AutopsyOptionsPanel_storeTempDir_onError_title=Error Saving Temporary Directory",
"# {0} - path",
"AutopsyOptionsPanel_storeTempDir_onError_description=There was an error creating the temporary directory on the filesystem at: {0}.",})
private void storeTempDir() {
String tempDirectoryPath = tempDirectoryField.getText();
if (!UserMachinePreferences.getBaseTempDirectory().equals(tempDirectoryPath)) {
try {
UserMachinePreferences.setBaseTempDirectory(tempDirectoryPath);
} catch (UserMachinePreferencesException ex) {
logger.log(Level.WARNING, "There was an error creating the temporary directory defined by the user: " + tempDirectoryPath, ex);
SwingUtilities.invokeLater(() -> {
JOptionPane.showMessageDialog(this,
String.format("<html>%s</html>", Bundle.AutopsyOptionsPanel_storeTempDir_onError_description(tempDirectoryPath)),
Bundle.AutopsyOptionsPanel_storeTempDir_onError_title(),
JOptionPane.ERROR_MESSAGE);
});
}
}
}
/**
* Store the current user preferences.
*/
void store() {
UserPreferences.setLogFileCount(Integer.parseInt(logFileCount.getText()));
storeTempDir();
if (!agencyLogoPathField.getText().isEmpty()) {
File file = new File(agencyLogoPathField.getText());
if (file.exists()) {
@ -355,7 +399,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
} else {
ModuleSettings.setConfigSetting(ReportBranding.MODULE_NAME, ReportBranding.AGENCY_LOGO_PATH_PROP, "");
}
UserPreferences.setMaxSolrVMSize((int)solrMaxHeapSpinner.getValue());
UserPreferences.setMaxSolrVMSize((int) solrMaxHeapSpinner.getValue());
if (memField.isEnabled()) { //if the field could of been changed we need to try and save it
try {
writeEtcConfFile();
@ -372,7 +416,6 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
*/
boolean valid() {
boolean valid = true;
if (!isAgencyLogoPathValid()) {
valid = false;
}
@ -425,7 +468,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
return valid;
}
/**
* Checks that if the mem field is enabled it has a valid value.
*
@ -466,7 +509,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
/**
* Check if the logFileCount field is valid.
*
*
* @return true if the logFileCount is valid false if it is not
*/
private boolean isLogNumFieldValid() {
@ -482,8 +525,9 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
logNumAlert.setText(Bundle.AutopsyOptionsPanel_logNumAlert_invalidInput_text());
return false;
}
return true;
return true;
}
/**
* Listens for registered text fields that have changed and fires a
* PropertyChangeEvent accordingly.
@ -542,16 +586,20 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
maxMemoryUnitsLabel2 = new javax.swing.JLabel();
solrMaxHeapSpinner = new javax.swing.JSpinner();
solrJVMHeapWarning = new javax.swing.JLabel();
tempDirectoryPanel = new javax.swing.JPanel();
tempDirectoryField = new javax.swing.JTextField();
tempDirectoryBrowseButton = new javax.swing.JButton();
tempDirectoryWarningLabel = new javax.swing.JLabel();
setPreferredSize(new java.awt.Dimension(1022, 488));
setPreferredSize(null);
jScrollPane1.setBorder(null);
jScrollPane1.setPreferredSize(new java.awt.Dimension(1022, 407));
jScrollPane1.setPreferredSize(null);
jPanel1.setPreferredSize(new java.awt.Dimension(1022, 407));
jPanel1.setMinimumSize(new java.awt.Dimension(648, 382));
jPanel1.setPreferredSize(null);
logoPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.logoPanel.border.title"))); // NOI18N
logoPanel.setPreferredSize(new java.awt.Dimension(533, 87));
agencyLogoPathField.setText(org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.agencyLogoPathField.text")); // NOI18N
@ -599,14 +647,14 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
.addComponent(defaultLogoRB))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(logoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(agencyLogoPathFieldValidationLabel)
.addGroup(logoPanelLayout.createSequentialGroup()
.addComponent(agencyLogoPathField, javax.swing.GroupLayout.PREFERRED_SIZE, 259, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(agencyLogoPathField, javax.swing.GroupLayout.PREFERRED_SIZE, 270, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(browseLogosButton))
.addComponent(agencyLogoPathFieldValidationLabel))
.addComponent(browseLogosButton)))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(agencyLogoPreview, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(456, Short.MAX_VALUE))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
logoPanelLayout.setVerticalGroup(
logoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -622,7 +670,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
.addComponent(browseLogosButton)))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, logoPanelLayout.createSequentialGroup()
.addComponent(agencyLogoPreview, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, Short.MAX_VALUE))
.addGap(0, 12, Short.MAX_VALUE))
);
runtimePanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.runtimePanel.border.title"))); // NOI18N
@ -703,14 +751,14 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
.addGroup(runtimePanelLayout.createSequentialGroup()
.addGap(23, 23, 23)
.addComponent(memFieldValidationLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 478, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(246, Short.MAX_VALUE))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGroup(runtimePanelLayout.createSequentialGroup()
.addGap(18, 18, 18)
.addComponent(solrJVMHeapWarning, javax.swing.GroupLayout.DEFAULT_SIZE, 717, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(solrJVMHeapWarning, javax.swing.GroupLayout.PREFERRED_SIZE, 331, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(44, 44, 44)
.addComponent(logNumAlert)
.addContainerGap())))
.addComponent(restartNecessaryWarning, javax.swing.GroupLayout.DEFAULT_SIZE, 994, Short.MAX_VALUE)))
.addComponent(restartNecessaryWarning, javax.swing.GroupLayout.PREFERRED_SIZE, 615, javax.swing.GroupLayout.PREFERRED_SIZE)))
);
runtimePanelLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {maxLogFileCount, maxMemoryLabel, totalMemoryLabel});
@ -746,7 +794,48 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
.addComponent(logFileCount, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(restartNecessaryWarning)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addContainerGap())
);
tempDirectoryPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.tempDirectoryPanel.border.title"))); // NOI18N
tempDirectoryPanel.setName(org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.tempDirectoryPanel.name")); // NOI18N
tempDirectoryField.setText(org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.tempDirectoryField.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(tempDirectoryBrowseButton, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.tempDirectoryBrowseButton.text")); // NOI18N
tempDirectoryBrowseButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
tempDirectoryBrowseButtonActionPerformed(evt);
}
});
tempDirectoryWarningLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/warning16.png"))); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(tempDirectoryWarningLabel, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.tempDirectoryWarningLabel.text")); // NOI18N
javax.swing.GroupLayout tempDirectoryPanelLayout = new javax.swing.GroupLayout(tempDirectoryPanel);
tempDirectoryPanel.setLayout(tempDirectoryPanelLayout);
tempDirectoryPanelLayout.setHorizontalGroup(
tempDirectoryPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(tempDirectoryPanelLayout.createSequentialGroup()
.addContainerGap()
.addGroup(tempDirectoryPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(tempDirectoryWarningLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 615, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(tempDirectoryPanelLayout.createSequentialGroup()
.addComponent(tempDirectoryField, javax.swing.GroupLayout.PREFERRED_SIZE, 367, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(tempDirectoryBrowseButton)))
.addGap(0, 0, Short.MAX_VALUE))
);
tempDirectoryPanelLayout.setVerticalGroup(
tempDirectoryPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(tempDirectoryPanelLayout.createSequentialGroup()
.addContainerGap()
.addGroup(tempDirectoryPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(tempDirectoryField)
.addComponent(tempDirectoryBrowseButton))
.addGap(18, 18, 18)
.addComponent(tempDirectoryWarningLabel)
.addContainerGap())
);
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
@ -755,54 +844,63 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(runtimePanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(logoPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 1002, Short.MAX_VALUE))
.addContainerGap())
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
.addComponent(logoPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(tempDirectoryPanel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(runtimePanel, javax.swing.GroupLayout.PREFERRED_SIZE, 631, javax.swing.GroupLayout.PREFERRED_SIZE)))
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addComponent(runtimePanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGap(3, 3, 3)
.addComponent(tempDirectoryPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(logoPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(171, Short.MAX_VALUE))
.addContainerGap())
);
tempDirectoryPanel.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.tempDirectoryPanel.AccessibleContext.accessibleName")); // NOI18N
jScrollPane1.setViewportView(jPanel1);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 648, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGap(0, 0, Short.MAX_VALUE))
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 382, Short.MAX_VALUE)
);
}// </editor-fold>//GEN-END:initComponents
private void logFileCountKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_logFileCountKeyReleased
String count = logFileCount.getText();
if (count.equals(String.valueOf(UserPreferences.getDefaultLogFileCount()))) {
//if it is still the default value don't fire change
return;
@Messages({
"AutopsyOptionsPanel_tempDirectoryBrowseButtonActionPerformed_onInvalidPath_title=Path cannot be used",
"# {0} - path",
"AutopsyOptionsPanel_tempDirectoryBrowseButtonActionPerformed_onInvalidPath_description=Unable to create temporary directory within specified path: {0}",})
private void tempDirectoryBrowseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_tempDirectoryBrowseButtonActionPerformed
int returnState = tempDirChooser.showOpenDialog(this);
if (returnState == JFileChooser.APPROVE_OPTION) {
String specifiedPath = tempDirChooser.getSelectedFile().getPath();
try {
File f = new File(specifiedPath);
if (!f.exists() && !f.mkdirs()) {
throw new InvalidPathException(specifiedPath, "Unable to create parent directories leading to " + specifiedPath);
}
tempDirectoryField.setText(specifiedPath);
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
} catch (InvalidPathException ex) {
logger.log(Level.WARNING, "Unable to create temporary directory in " + specifiedPath, ex);
JOptionPane.showMessageDialog(this,
Bundle.AutopsyOptionsPanel_tempDirectoryBrowseButtonActionPerformed_onInvalidPath_description(specifiedPath),
Bundle.AutopsyOptionsPanel_tempDirectoryBrowseButtonActionPerformed_onInvalidPath_title(),
JOptionPane.ERROR_MESSAGE);
}
}
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}//GEN-LAST:event_logFileCountKeyReleased
private void memFieldKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_memFieldKeyReleased
String memText = memField.getText();
if (memText.equals(initialMemValue)) {
//if it is still the initial value don't fire change
return;
}
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}//GEN-LAST:event_memFieldKeyReleased
}//GEN-LAST:event_tempDirectoryBrowseButtonActionPerformed
private void specifyLogoRBActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_specifyLogoRBActionPerformed
agencyLogoPathField.setEnabled(true);
@ -834,18 +932,18 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
private void browseLogosButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseLogosButtonActionPerformed
String oldLogoPath = agencyLogoPathField.getText();
int returnState = fileChooser.showOpenDialog(this);
int returnState = logoFileChooser.showOpenDialog(this);
if (returnState == JFileChooser.APPROVE_OPTION) {
String path = fileChooser.getSelectedFile().getPath();
String path = logoFileChooser.getSelectedFile().getPath();
try {
updateAgencyLogo(path);
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
} catch (IOException | IndexOutOfBoundsException ex) {
JOptionPane.showMessageDialog(this,
NbBundle.getMessage(this.getClass(),
"AutopsyOptionsPanel.invalidImageFile.msg"),
NbBundle.getMessage(this.getClass(), "AutopsyOptionsPanel.invalidImageFile.title"),
JOptionPane.ERROR_MESSAGE);
NbBundle.getMessage(this.getClass(),
"AutopsyOptionsPanel.invalidImageFile.msg"),
NbBundle.getMessage(this.getClass(), "AutopsyOptionsPanel.invalidImageFile.title"),
JOptionPane.ERROR_MESSAGE);
try {
updateAgencyLogo(oldLogoPath); //restore previous setting if new one is invalid
} catch (IOException ex1) {
@ -856,7 +954,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
}//GEN-LAST:event_browseLogosButtonActionPerformed
private void solrMaxHeapSpinnerStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_solrMaxHeapSpinnerStateChanged
int value = (int)solrMaxHeapSpinner.getValue();
int value = (int) solrMaxHeapSpinner.getValue();
if (value == UserPreferences.getMaxSolrVMSize()) {
// if the value hasn't changed there's nothing to do.
return;
@ -864,6 +962,24 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}//GEN-LAST:event_solrMaxHeapSpinnerStateChanged
private void logFileCountKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_logFileCountKeyReleased
String count = logFileCount.getText();
if (count.equals(String.valueOf(UserPreferences.getDefaultLogFileCount()))) {
//if it is still the default value don't fire change
return;
}
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}//GEN-LAST:event_logFileCountKeyReleased
private void memFieldKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_memFieldKeyReleased
String memText = memField.getText();
if (memText.equals(initialMemValue)) {
//if it is still the initial value don't fire change
return;
}
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}//GEN-LAST:event_memFieldKeyReleased
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JTextField agencyLogoPathField;
private javax.swing.JLabel agencyLogoPathFieldValidationLabel;
@ -892,6 +1008,10 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
private javax.swing.JSpinner solrMaxHeapSpinner;
private javax.swing.JRadioButton specifyLogoRB;
private javax.swing.JLabel systemMemoryTotal;
private javax.swing.JButton tempDirectoryBrowseButton;
private javax.swing.JTextField tempDirectoryField;
private javax.swing.JPanel tempDirectoryPanel;
private javax.swing.JLabel tempDirectoryWarningLabel;
private javax.swing.JLabel totalMemoryLabel;
// End of variables declaration//GEN-END:variables

View File

@ -120,26 +120,12 @@ MultiUserSettingsPanel.lbTestDbWarning.text=
MultiUserSettingsPanel.KeywordSearchNull=Cannot find keyword search service
MultiUserSettingsPanel.InvalidPortNumber=Invalid port number
AutopsyOptionsPanel.agencyLogoImageLabel.toolTipText=
AutopsyOptionsPanel.agencyLogoPathField.text=
SortChooserDialog.label=remove
SortChooser.addCriteriaButton.text=Add Sort Criteria
DataResultViewerThumbnail.sortButton.text=Sort
CriterionChooser.ascendingRadio.text=\u25b2 Ascending\n
CriterionChooser.removeButton.text=Remove
CriterionChooser.descendingRadio.text=\u25bc Descending
AutopsyOptionsPanel.agencyLogoPathFieldValidationLabel.text=
AutopsyOptionsPanel.logNumAlert.text=
AutopsyOptionsPanel.totalMemoryLabel.text=Total System Memory:
AutopsyOptionsPanel.maxMemoryLabel.text=Maximum JVM Memory:
AutopsyOptionsPanel.maxLogFileCount.text=Maximum Log Files:
AutopsyOptionsPanel.maxMemoryUnitsLabel.text=GB
AutopsyOptionsPanel.restartNecessaryWarning.text=A restart is necessary for any memory changes to take effect.
AutopsyOptionsPanel.browseLogosButton.text=Browse
AutopsyOptionsPanel.defaultLogoRB.text=Use default
AutopsyOptionsPanel.specifyLogoRB.text=Specify a logo
AutopsyOptionsPanel.agencyLogoPreview.text=<html><div style='text-align: center;'>No logo<br>selected</div></html>
AutopsyOptionsPanel.logoPanel.border.title=Logo
AutopsyOptionsPanel.runtimePanel.border.title=Runtime
DataResultPanel.matchLabel.text=Results
DataResultPanel.numberOfChildNodesLabel.text=0
DataResultPanel.descriptionLabel.text=directoryPath
@ -199,9 +185,6 @@ ExternalViewerGlobalSettingsPanel.deleteRuleButton.text_1=Delete Rule
ExternalViewerGlobalSettingsPanel.externalViewerTitleLabel.text_1=Set aplication viewer to use for files with specific mime types/extensions:
ExternalViewerGlobalSettingsPanel.jTable1.columnModel.title1_1=Application
ExternalViewerGlobalSettingsPanel.jTable1.columnModel.title0_1=Mime type/Extension
AutopsyOptionsPanel.maxSolrMemoryLabel.text=Maximum Solr JVM Memory:
AutopsyOptionsPanel.maxMemoryUnitsLabel2.text=MB
AutopsyOptionsPanel.solrJVMHeapWarning.text=NOTE: Setting this too large may impact overall performance.
DataResultViewerTable.gotoPageTextField.text=
DataResultViewerTable.gotoPageLabel.AccessibleContext.accessibleName=
DataResultViewerTable.gotoPageLabel.text=Go to Page:
@ -216,3 +199,27 @@ DataResultViewerTable.exportCSVButton.text=Save Table as CSV
ViewPreferencesPanel.scoColumnsCheckbox.text=S(core), C(omments), and O(ccurences)
ViewPreferencesPanel.scoColumnsWrapAroundText.text=to reduce loading times
ViewPreferencesPanel.scoColumnsLabel.text=Do not add columns for:
AutopsyOptionsPanel.logoPanel.border.title=Logo
AutopsyOptionsPanel.agencyLogoPathFieldValidationLabel.text=
AutopsyOptionsPanel.specifyLogoRB.text=Specify a logo
AutopsyOptionsPanel.defaultLogoRB.text=Use default
AutopsyOptionsPanel.agencyLogoPreview.text=<html><div style='text-align: center;'>No logo<br>selected</div></html>
AutopsyOptionsPanel.browseLogosButton.text=Browse
AutopsyOptionsPanel.agencyLogoPathField.text=
AutopsyOptionsPanel.tempDirectoryField.text=
AutopsyOptionsPanel.tempDirectoryBrowseButton.text=Browse
AutopsyOptionsPanel.a.AccessibleContext.accessibleName=Temp Directory
AutopsyOptionsPanel.tempDirectoryPanel.AccessibleContext.accessibleName=Temp Directory
AutopsyOptionsPanel.tempDirectoryPanel.name=Temp Directory
AutopsyOptionsPanel.tempDirectoryPanel.border.title=Temp Directory
AutopsyOptionsPanel.tempDirectoryWarningLabel.text=Close the current case to change the temporary directory.
AutopsyOptionsPanel.solrJVMHeapWarning.text=NOTE: Setting this too large may impact overall performance.
AutopsyOptionsPanel.maxMemoryUnitsLabel2.text=MB
AutopsyOptionsPanel.maxSolrMemoryLabel.text=Maximum Solr JVM Memory:
AutopsyOptionsPanel.logNumAlert.text=
AutopsyOptionsPanel.maxLogFileCount.text=Maximum Log Files:
AutopsyOptionsPanel.restartNecessaryWarning.text=A restart is necessary for any memory changes to take effect.
AutopsyOptionsPanel.totalMemoryLabel.text=Total System Memory:
AutopsyOptionsPanel.maxMemoryUnitsLabel.text=GB
AutopsyOptionsPanel.maxMemoryLabel.text=Maximum JVM Memory:
AutopsyOptionsPanel.runtimePanel.border.title=Runtime

View File

@ -12,6 +12,12 @@ AutopsyOptionsPanel.memFieldValidationLabel.noValueEntered.text=No value entered
AutopsyOptionsPanel.memFieldValidationLabel.overMaxMemory.text=Value must be less than the total system memory of {0}GB
# {0} - minimumMemory
AutopsyOptionsPanel.memFieldValidationLabel.underMinMemory.text=Value must be at least {0}GB
# {0} - path
AutopsyOptionsPanel_storeTempDir_onError_description=There was an error creating the temporary directory on the filesystem at: {0}.
AutopsyOptionsPanel_storeTempDir_onError_title=Error Saving Temporary Directory
# {0} - path
AutopsyOptionsPanel_tempDirectoryBrowseButtonActionPerformed_onInvalidPath_description=Unable to create temporary directory within specified path: {0}
AutopsyOptionsPanel_tempDirectoryBrowseButtonActionPerformed_onInvalidPath_title=Path cannot be used
CTL_DataContentAction=DataContent
CTL_DataContentTopComponent=Data Content
CTL_CustomAboutAction=About
@ -169,26 +175,12 @@ MultiUserSettingsPanel.lbTestDbWarning.text=
MultiUserSettingsPanel.KeywordSearchNull=Cannot find keyword search service
MultiUserSettingsPanel.InvalidPortNumber=Invalid port number
AutopsyOptionsPanel.agencyLogoImageLabel.toolTipText=
AutopsyOptionsPanel.agencyLogoPathField.text=
SortChooserDialog.label=remove
SortChooser.addCriteriaButton.text=Add Sort Criteria
DataResultViewerThumbnail.sortButton.text=Sort
CriterionChooser.ascendingRadio.text=\u25b2 Ascending\n
CriterionChooser.removeButton.text=Remove
CriterionChooser.descendingRadio.text=\u25bc Descending
AutopsyOptionsPanel.agencyLogoPathFieldValidationLabel.text=
AutopsyOptionsPanel.logNumAlert.text=
AutopsyOptionsPanel.totalMemoryLabel.text=Total System Memory:
AutopsyOptionsPanel.maxMemoryLabel.text=Maximum JVM Memory:
AutopsyOptionsPanel.maxLogFileCount.text=Maximum Log Files:
AutopsyOptionsPanel.maxMemoryUnitsLabel.text=GB
AutopsyOptionsPanel.restartNecessaryWarning.text=A restart is necessary for any memory changes to take effect.
AutopsyOptionsPanel.browseLogosButton.text=Browse
AutopsyOptionsPanel.defaultLogoRB.text=Use default
AutopsyOptionsPanel.specifyLogoRB.text=Specify a logo
AutopsyOptionsPanel.agencyLogoPreview.text=<html><div style='text-align: center;'>No logo<br>selected</div></html>
AutopsyOptionsPanel.logoPanel.border.title=Logo
AutopsyOptionsPanel.runtimePanel.border.title=Runtime
DataResultPanel.matchLabel.text=Results
DataResultPanel.numberOfChildNodesLabel.text=0
DataResultPanel.descriptionLabel.text=directoryPath
@ -250,9 +242,6 @@ ExternalViewerGlobalSettingsPanel.deleteRuleButton.text_1=Delete Rule
ExternalViewerGlobalSettingsPanel.externalViewerTitleLabel.text_1=Set aplication viewer to use for files with specific mime types/extensions:
ExternalViewerGlobalSettingsPanel.jTable1.columnModel.title1_1=Application
ExternalViewerGlobalSettingsPanel.jTable1.columnModel.title0_1=Mime type/Extension
AutopsyOptionsPanel.maxSolrMemoryLabel.text=Maximum Solr JVM Memory:
AutopsyOptionsPanel.maxMemoryUnitsLabel2.text=MB
AutopsyOptionsPanel.solrJVMHeapWarning.text=NOTE: Setting this too large may impact overall performance.
DataResultViewerTable.gotoPageTextField.text=
DataResultViewerTable.gotoPageLabel.AccessibleContext.accessibleName=
DataResultViewerTable.gotoPageLabel.text=Go to Page:
@ -267,3 +256,27 @@ DataResultViewerTable.exportCSVButton.text=Save Table as CSV
ViewPreferencesPanel.scoColumnsCheckbox.text=S(core), C(omments), and O(ccurences)
ViewPreferencesPanel.scoColumnsWrapAroundText.text=to reduce loading times
ViewPreferencesPanel.scoColumnsLabel.text=Do not add columns for:
AutopsyOptionsPanel.logoPanel.border.title=Logo
AutopsyOptionsPanel.agencyLogoPathFieldValidationLabel.text=
AutopsyOptionsPanel.specifyLogoRB.text=Specify a logo
AutopsyOptionsPanel.defaultLogoRB.text=Use default
AutopsyOptionsPanel.agencyLogoPreview.text=<html><div style='text-align: center;'>No logo<br>selected</div></html>
AutopsyOptionsPanel.browseLogosButton.text=Browse
AutopsyOptionsPanel.agencyLogoPathField.text=
AutopsyOptionsPanel.tempDirectoryField.text=
AutopsyOptionsPanel.tempDirectoryBrowseButton.text=Browse
AutopsyOptionsPanel.a.AccessibleContext.accessibleName=Temp Directory
AutopsyOptionsPanel.tempDirectoryPanel.AccessibleContext.accessibleName=Temp Directory
AutopsyOptionsPanel.tempDirectoryPanel.name=Temp Directory
AutopsyOptionsPanel.tempDirectoryPanel.border.title=Temp Directory
AutopsyOptionsPanel.tempDirectoryWarningLabel.text=Close the current case to change the temporary directory.
AutopsyOptionsPanel.solrJVMHeapWarning.text=NOTE: Setting this too large may impact overall performance.
AutopsyOptionsPanel.maxMemoryUnitsLabel2.text=MB
AutopsyOptionsPanel.maxSolrMemoryLabel.text=Maximum Solr JVM Memory:
AutopsyOptionsPanel.logNumAlert.text=
AutopsyOptionsPanel.maxLogFileCount.text=Maximum Log Files:
AutopsyOptionsPanel.restartNecessaryWarning.text=A restart is necessary for any memory changes to take effect.
AutopsyOptionsPanel.totalMemoryLabel.text=Total System Memory:
AutopsyOptionsPanel.maxMemoryUnitsLabel.text=GB
AutopsyOptionsPanel.maxMemoryLabel.text=Maximum JVM Memory:
AutopsyOptionsPanel.runtimePanel.border.title=Runtime

View File

@ -36,7 +36,7 @@ import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.DeleteDataSourceAction;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.casemodule.datasourcesummary.ViewSummaryInformationAction;
import org.sleuthkit.autopsy.datasourcesummary.ui.ViewSummaryInformationAction;
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
import org.sleuthkit.autopsy.corecomponents.DataResultViewerTable;
import org.sleuthkit.autopsy.coreutils.Logger;

View File

@ -24,7 +24,7 @@ import java.util.List;
import javax.swing.Action;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.DeleteDataSourceAction;
import org.sleuthkit.autopsy.casemodule.datasourcesummary.ViewSummaryInformationAction;
import org.sleuthkit.autopsy.datasourcesummary.ui.ViewSummaryInformationAction;
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
import org.sleuthkit.autopsy.directorytree.ExportCSVAction;
import org.sleuthkit.autopsy.directorytree.ExtractAction;

View File

@ -0,0 +1,168 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2020 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.datasourcesummary.datamodel;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskData;
/**
* Provides methods to query for information for all datasources in a case.
*/
public class CaseDataSourcesSummary {
private static final Logger logger = Logger.getLogger(CaseDataSourcesSummary.class.getName());
/**
* Get a map containing the TSK_DATA_SOURCE_USAGE description attributes
* associated with each data source in the current case.
*
* @return Collection which maps datasource id to a String which displays a
* comma seperated list of values of data source usage types
* expected to be in the datasource
*/
public static Map<Long, String> getDataSourceTypes() {
try {
SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
List<BlackboardArtifact> listOfArtifacts = skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_DATA_SOURCE_USAGE);
Map<Long, String> typeMap = new HashMap<>();
for (BlackboardArtifact typeArtifact : listOfArtifacts) {
BlackboardAttribute descriptionAttr = typeArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DESCRIPTION));
if (typeArtifact.getDataSource() != null && descriptionAttr != null) {
long dsId = typeArtifact.getDataSource().getId();
String type = typeMap.get(typeArtifact.getDataSource().getId());
if (type == null) {
type = descriptionAttr.getValueString();
} else {
type = type + ", " + descriptionAttr.getValueString();
}
typeMap.put(dsId, type);
}
}
return typeMap;
} catch (TskCoreException | NoCurrentCaseException ex) {
logger.log(Level.WARNING, "Unable to get types of files for all datasources, providing empty results", ex);
return Collections.emptyMap();
}
}
/**
* Get a map containing the number of files in each data source in the
* current case.
*
* @return Collection which maps datasource id to a count for the number of
* files in the datasource, will only contain entries for
* datasources which have at least 1 file
*/
public static Map<Long, Long> getCountsOfFiles() {
try {
final String countFilesQuery = "data_source_obj_id, COUNT(*) AS value FROM tsk_files"
+ " WHERE meta_type=" + TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG.getValue()
+ " AND type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType()
+ " AND dir_type<>" + TskData.TSK_FS_NAME_TYPE_ENUM.VIRT_DIR.getValue()
+ " AND name<>''"
+ " GROUP BY data_source_obj_id"; //NON-NLS
return getValuesMap(countFilesQuery);
} catch (TskCoreException | NoCurrentCaseException ex) {
logger.log(Level.WARNING, "Unable to get counts of files for all datasources, providing empty results", ex);
return Collections.emptyMap();
}
}
/**
* Get a map containing the number of artifacts in each data source in the
* current case.
*
* @return Collection which maps datasource id to a count for the number of
* artifacts in the datasource, will only contain entries for
* datasources which have at least 1 artifact
*/
public static Map<Long, Long> getCountsOfArtifacts() {
try {
final String countArtifactsQuery = "data_source_obj_id, COUNT(*) AS value"
+ " FROM blackboard_artifacts WHERE review_status_id !=" + BlackboardArtifact.ReviewStatus.REJECTED.getID()
+ " GROUP BY data_source_obj_id"; //NON-NLS
return getValuesMap(countArtifactsQuery);
} catch (TskCoreException | NoCurrentCaseException ex) {
logger.log(Level.WARNING, "Unable to get counts of artifacts for all datasources, providing empty results", ex);
return Collections.emptyMap();
}
}
/**
* Get a map containing the number of tags which have been applied in each
* data source in the current case. Not necessarily the same as the number
* of items tagged, as an item can have any number of tags.
*
* @return Collection which maps datasource id to a count for the number of
* tags which have been applied in the datasource, will only contain
* entries for datasources which have at least 1 item tagged.
*/
public static Map<Long, Long> getCountsOfTags() {
try {
final String countFileTagsQuery = "data_source_obj_id, COUNT(*) AS value"
+ " FROM content_tags as content_tags, tsk_files as tsk_files"
+ " WHERE content_tags.obj_id = tsk_files.obj_id"
+ " GROUP BY data_source_obj_id"; //NON-NLS
//new hashmap so it can be modifiable
Map<Long, Long> tagCountMap = new HashMap<>(getValuesMap(countFileTagsQuery));
final String countArtifactTagsQuery = "data_source_obj_id, COUNT(*) AS value"
+ " FROM blackboard_artifact_tags as artifact_tags, blackboard_artifacts AS arts"
+ " WHERE artifact_tags.artifact_id = arts.artifact_id"
+ " GROUP BY data_source_obj_id"; //NON-NLS
//combine the results from the count artifact tags query into the copy of the mapped results from the count file tags query
getValuesMap(countArtifactTagsQuery).forEach((key, value) -> tagCountMap.merge(key, value, (value1, value2) -> value1 + value2));
return tagCountMap;
} catch (TskCoreException | NoCurrentCaseException ex) {
logger.log(Level.WARNING, "Unable to get counts of tags for all datasources, providing empty results", ex);
return Collections.emptyMap();
}
}
/**
* Helper method to execute a select query with a
* DataSourceSingleValueCallback.
*
* @param query the portion of the query which should follow the SELECT
*
* @return a map of datasource object ID to a value of type Long
*
* @throws TskCoreException
* @throws NoCurrentCaseException
*/
private static Map<Long, Long> getValuesMap(String query) throws TskCoreException, NoCurrentCaseException {
SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
DataSourceSingleValueCallback callback = new DataSourceSingleValueCallback();
skCase.getCaseDbAccessManager().select(query, callback);
return callback.getMapOfValues();
}
private CaseDataSourcesSummary() {
}
}

View File

@ -0,0 +1,160 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019 - 2020 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.datasourcesummary.datamodel;
import java.sql.SQLException;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataSourceInfoUtilities.ResultSetHandler;
import org.sleuthkit.datamodel.DataSource;
import org.sleuthkit.datamodel.TskData;
/**
* Provides information for the DataSourceSummaryCountsPanel.
*/
public class DataSourceCountsSummary {
private static final Logger logger = Logger.getLogger(DataSourceCountsSummary.class.getName());
/**
* Get count of regular files (not directories) in a data source.
*
* @param currentDataSource The data source.
*
* @return The count.
*/
public static Long getCountOfFiles(DataSource currentDataSource) {
return DataSourceInfoUtilities.getCountOfRegularFiles(currentDataSource, null,
"Unable to get count of files, providing empty results");
}
/**
* Get count of allocated files in a data source.
*
* @param currentDataSource The data source.
*
* @return The count.
*/
public static Long getCountOfAllocatedFiles(DataSource currentDataSource) {
return DataSourceInfoUtilities.getCountOfRegularFiles(currentDataSource,
DataSourceInfoUtilities.getMetaFlagsContainsStatement(TskData.TSK_FS_META_FLAG_ENUM.ALLOC),
"Unable to get counts of unallocated files for datasource, providing empty results");
}
/**
* Get count of unallocated files in a data source.
*
* @param currentDataSource The data source.
*
* @return The count.
*/
public static Long getCountOfUnallocatedFiles(DataSource currentDataSource) {
return DataSourceInfoUtilities.getCountOfRegularFiles(currentDataSource,
DataSourceInfoUtilities.getMetaFlagsContainsStatement(TskData.TSK_FS_META_FLAG_ENUM.UNALLOC)
+ " AND type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.getFileType(),
"Unable to get counts of unallocated files for datasource, providing empty results");
}
/**
* Get count of directories in a data source.
*
* @param currentDataSource The data source.
*
* @return The count.
*/
public static Long getCountOfDirectories(DataSource currentDataSource) {
return DataSourceInfoUtilities.getCountOfTskFiles(currentDataSource,
"meta_type=" + TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR.getValue()
+ " AND type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType(),
"Unable to get count of directories for datasource, providing empty results");
}
/**
* Get count of slack files in a data source.
*
* @param currentDataSource The data source.
*
* @return The count.
*/
public static Long getCountOfSlackFiles(DataSource currentDataSource) {
return DataSourceInfoUtilities.getCountOfRegularFiles(currentDataSource,
DataSourceInfoUtilities.getMetaFlagsContainsStatement(TskData.TSK_FS_META_FLAG_ENUM.UNALLOC)
+ " AND type=" + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.getFileType(),
"Unable to get count of slack files for datasources, providing empty results");
}
/**
* Retrieves counts for each artifact type in a data source.
*
* @param selectedDataSource The data source.
*
* @return A mapping of artifact type name to the counts or null if there
* was an error executing the query.
*/
public static Map<String, Long> getCountsOfArtifactsByType(DataSource selectedDataSource) {
if (selectedDataSource == null) {
return Collections.emptyMap();
}
final String nameParam = "name";
final String valueParam = "value";
String query
= "SELECT bbt.display_name AS " + nameParam + ", COUNT(*) AS " + valueParam
+ " FROM blackboard_artifacts bba "
+ " INNER JOIN blackboard_artifact_types bbt ON bba.artifact_type_id = bbt.artifact_type_id"
+ " WHERE bba.data_source_obj_id =" + selectedDataSource.getId()
+ " GROUP BY bbt.display_name";
String errorMessage = "Unable to get artifact type counts; returning null.";
return DataSourceInfoUtilities.getBaseQueryResult(query,
getStringLongResultSetHandler(nameParam, valueParam),
errorMessage);
}
/**
* Generates a result set handler that will return a map of string to long.
*
* @param keyParam The named parameter in the result set representing the
* key.
* @param valueParam The named parameter in the result set representing the
* value.
*
* @return The result set handler to generate the map of string to long.
*/
private static ResultSetHandler<LinkedHashMap<String, Long>> getStringLongResultSetHandler(String keyParam, String valueParam) {
return (resultSet) -> {
LinkedHashMap<String, Long> toRet = new LinkedHashMap<>();
while (resultSet.next()) {
try {
toRet.put(resultSet.getString(keyParam), resultSet.getLong(valueParam));
} catch (SQLException ex) {
logger.log(Level.WARNING, "Failed to get a result pair from the result set.", ex);
}
}
return toRet;
};
}
private DataSourceCountsSummary() {
}
}

View File

@ -0,0 +1,178 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2020 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.datasourcesummary.datamodel;
import java.sql.SQLException;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import static org.sleuthkit.autopsy.datasourcesummary.datamodel.DataSourceInfoUtilities.getBaseQueryResult;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.DataSource;
import org.sleuthkit.datamodel.TskData;
/**
* Provides methods to query for data source overview details.
*/
public class DataSourceDetailsSummary {
private static final Logger logger = Logger.getLogger(DataSourceDetailsSummary.class.getName());
/**
* Gets the size of unallocated files in a particular datasource.
*
* @param currentDataSource The data source.
*
* @return The size or null if the query could not be executed.
*/
public static Long getSizeOfUnallocatedFiles(DataSource currentDataSource) {
if (currentDataSource == null) {
return null;
}
final String valueParam = "value";
final String countParam = "count";
String query = "SELECT SUM(size) AS " + valueParam + ", COUNT(*) AS " + countParam
+ " FROM tsk_files"
+ " WHERE " + DataSourceInfoUtilities.getMetaFlagsContainsStatement(TskData.TSK_FS_META_FLAG_ENUM.UNALLOC)
+ " AND type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.getFileType()
+ " AND type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType()
+ " AND dir_type<>" + TskData.TSK_FS_NAME_TYPE_ENUM.VIRT_DIR.getValue()
+ " AND name<>''"
+ " AND data_source_obj_id=" + currentDataSource.getId();
DataSourceInfoUtilities.ResultSetHandler<Long> handler = (resultSet) -> {
if (resultSet.next()) {
// ensure that there is an unallocated count result that is attached to this data source
long resultCount = resultSet.getLong(valueParam);
return (resultCount > 0) ? resultSet.getLong(valueParam) : null;
} else {
return null;
}
};
String errorMessage = "Unable to get size of unallocated files; returning null.";
return DataSourceInfoUtilities.getBaseQueryResult(query, handler, errorMessage);
}
/**
* Retrieves the concatenation of operating system attributes for a
* particular data source.
*
* @param dataSource The data source.
*
* @return The concatenated value or null if the query could not be
* executed.
*/
public static String getOperatingSystems(DataSource dataSource) {
if (dataSource == null) {
return null;
}
return getConcattedAttrValue(dataSource.getId(),
BlackboardArtifact.ARTIFACT_TYPE.TSK_OS_INFO.getTypeID(),
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID());
}
/**
* Retrieves the concatenation of data source usage for a particular data
* source.
*
* @param dataSource The data source.
*
* @return The concatenated value or null if the query could not be
* executed.
*/
public static String getDataSourceType(DataSource dataSource) {
if (dataSource == null) {
return null;
}
return getConcattedAttrValue(dataSource.getId(),
BlackboardArtifact.ARTIFACT_TYPE.TSK_DATA_SOURCE_USAGE.getTypeID(),
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DESCRIPTION.getTypeID());
}
/**
* Generates a string which is a concatenation of the value received from
* the result set.
*
* @param query The query.
* @param valueParam The parameter for the value in the result set.
* @param separator The string separator used in concatenation.
* @param errorMessage The error message if the result set could not
* be received.
* @param singleErrorMessage The error message if a single result could not
* be obtained.
*
* @return The concatenated string or null if the query could not be
* executed.
*/
private static String getConcattedStringsResult(String query, String valueParam, String separator, String errorMessage, String singleErrorMessage) {
DataSourceInfoUtilities.ResultSetHandler<String> handler = (resultSet) -> {
String toRet = "";
boolean first = true;
while (resultSet.next()) {
try {
if (first) {
first = false;
} else {
toRet += separator;
}
toRet += resultSet.getString(valueParam);
} catch (SQLException ex) {
logger.log(Level.WARNING, singleErrorMessage, ex);
}
}
return toRet;
};
return getBaseQueryResult(query, handler, errorMessage);
}
/**
* Generates a concatenated string value based on the text value of a
* particular attribute in a particular artifact for a specific data source.
*
* @param dataSourceId The data source id.
* @param artifactTypeId The artifact type id.
* @param attributeTypeId The attribute type id.
*
* @return The concatenated value or null if the query could not be
* executed.
*/
private static String getConcattedAttrValue(long dataSourceId, int artifactTypeId, int attributeTypeId) {
final String valueParam = "concatted_attribute_value";
String query = "SELECT attr.value_text AS " + valueParam
+ " FROM blackboard_artifacts bba "
+ " INNER JOIN blackboard_attributes attr ON bba.artifact_id = attr.artifact_id "
+ " WHERE bba.data_source_obj_id = " + dataSourceId
+ " AND bba.artifact_type_id = " + artifactTypeId
+ " AND attr.attribute_type_id = " + attributeTypeId;
String errorMessage = "Unable to execute query to retrieve concatted attribute values.";
String singleErrorMessage = "There was an error retrieving one of the results. That result will be omitted from concatted value.";
String separator = ", ";
return getConcattedStringsResult(query, valueParam, separator, errorMessage, singleErrorMessage);
}
private DataSourceDetailsSummary() {
}
}

View File

@ -0,0 +1,141 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019 - 2020 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.datasourcesummary.datamodel;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
import org.apache.commons.lang.StringUtils;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.datamodel.TskData;
import org.sleuthkit.datamodel.DataSource;
import org.sleuthkit.datamodel.TskData.TSK_FS_META_FLAG_ENUM;
import org.sleuthkit.datamodel.TskData.TSK_FS_META_TYPE_ENUM;
/**
* Utilities for getting information about a data source or all data sources
* from the case database.
*/
final class DataSourceInfoUtilities {
private static final Logger logger = Logger.getLogger(DataSourceInfoUtilities.class.getName());
/**
* Gets a count of tsk_files for a particular datasource where dir_type is
* not a virtual directory and has a name.
*
* @param currentDataSource The datasource.
* @param additionalWhere Additional sql where clauses.
* @param onError The message to log on error.
*
* @return The count of files or null on error.
*/
static Long getCountOfTskFiles(DataSource currentDataSource, String additionalWhere, String onError) {
if (currentDataSource != null) {
try {
SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
return skCase.countFilesWhere(
"data_source_obj_id=" + currentDataSource.getId()
+ " AND dir_type<>" + TskData.TSK_FS_NAME_TYPE_ENUM.VIRT_DIR.getValue()
+ " AND name<>''"
+ (StringUtils.isBlank(additionalWhere) ? "" : (" AND " + additionalWhere)));
} catch (TskCoreException | NoCurrentCaseException ex) {
logger.log(Level.WARNING, onError, ex);
//unable to get count of files for the specified types cell will be displayed as empty
}
}
return null;
}
/**
* Gets a count of regular files for a particular datasource where the
* dir_type and type are not a virtual directory and has a name.
*
* @param currentDataSource The datasource.
* @param additionalWhere Additional sql where clauses.
* @param onError The message to log on error.
*
* @return The count of files or null on error.
*/
static Long getCountOfRegularFiles(DataSource currentDataSource, String additionalWhere, String onError) {
String whereClause = "meta_type=" + TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG.getValue()
+ " AND type<>" + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType();
if (StringUtils.isNotBlank(additionalWhere)) {
whereClause += " AND " + additionalWhere;
}
return getCountOfTskFiles(currentDataSource, whereClause, onError);
}
/**
* An interface for handling a result set and returning a value.
*/
interface ResultSetHandler<T> {
T process(ResultSet resultset) throws SQLException;
}
/**
* Retrieves a result based on the provided query.
*
* @param query The query.
* @param processor The result set handler.
* @param errorMessage The error message to display if there is an error
* retrieving the resultset.
*
* @return The ResultSetHandler value or null if no ResultSet could be
* obtained.
*/
static <T> T getBaseQueryResult(String query, ResultSetHandler<T> processor, String errorMessage) {
try (SleuthkitCase.CaseDbQuery dbQuery = Case.getCurrentCaseThrows().getSleuthkitCase().executeQuery(query)) {
ResultSet resultSet = dbQuery.getResultSet();
try {
return processor.process(resultSet);
} catch (SQLException ex) {
logger.log(Level.WARNING, errorMessage, ex);
}
} catch (TskCoreException | NoCurrentCaseException ex) {
logger.log(Level.WARNING, errorMessage, ex);
}
return null;
}
/**
* Creates sql where clause that does a bitwise check to see if flag is
* present.
*
* @param flag The flag for which to check.
*
* @return The clause.
*/
static String getMetaFlagsContainsStatement(TSK_FS_META_FLAG_ENUM flag) {
return "meta_flags & " + flag.getValue() + " > 0";
}
/**
* Empty private constructor
*/
private DataSourceInfoUtilities() {
}
}

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.casemodule.datasourcesummary;
package org.sleuthkit.autopsy.datasourcesummary.datamodel;
import java.sql.ResultSet;
import java.sql.SQLException;

View File

@ -0,0 +1,107 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2020 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.datasourcesummary.datamodel;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.sleuthkit.datamodel.DataSource;
/**
* Provides methods to query for datasource files by mime type.
*/
public class DataSourceMimeTypeSummary {
/**
* Get the number of files in the case database for the current data source
* which have the specified mimetypes.
*
* @param currentDataSource the data source which we are finding a file
* count
*
* @param setOfMimeTypes the set of mime types which we are finding the
* number of occurences of
*
* @return a Long value which represents the number of occurrences of the
* specified mime types in the current case for the specified data
* source, null if no count was retrieved
*/
public static Long getCountOfFilesForMimeTypes(DataSource currentDataSource, Set<String> setOfMimeTypes) {
return DataSourceInfoUtilities.getCountOfRegularFiles(currentDataSource,
"mime_type IN " + getSqlSet(setOfMimeTypes),
"Unable to get count of files for specified mime types");
}
/**
* Get the number of files in the case database for the current data source
* which do not have the specified mimetypes.
*
* @param currentDataSource the data source which we are finding a file
* count
*
* @param setOfMimeTypes the set of mime types that should be excluded.
*
* @return a Long value which represents the number of files that do not
* have the specific mime type, but do have a mime type.
*/
public static Long getCountOfFilesNotInMimeTypes(DataSource currentDataSource, Set<String> setOfMimeTypes) {
return DataSourceInfoUtilities.getCountOfRegularFiles(currentDataSource,
"mime_type NOT IN " + getSqlSet(setOfMimeTypes)
+ " AND mime_type IS NOT NULL AND mime_type <> '' ",
"Unable to get count of files without specified mime types");
}
/**
* Gets the number of files in the data source with no assigned mime type.
*
* @param currentDataSource The data source.
*
* @return The number of files with no mime type or null if there is an
* issue searching the data source.
*
*/
public static Long getCountOfFilesWithNoMimeType(DataSource currentDataSource) {
return DataSourceInfoUtilities.getCountOfRegularFiles(currentDataSource,
"(mime_type IS NULL OR mime_type = '') ",
"Unable to get count of files without a mime type");
}
/**
* Derives a sql set string (i.e. "('val1', 'val2', 'val3')"). A naive
* attempt is made to sanitize the strings by removing single quotes from
* values.
*
* @param setValues The values that should be present in the set. Single
* quotes are removed.
*
* @return The sql set string.
*/
private static String getSqlSet(Set<String> setValues) {
List<String> quotedValues = setValues
.stream()
.map(str -> String.format("'%s'", str.replace("'", "")))
.collect(Collectors.toList());
String commaSeparatedQuoted = String.join(", ", quotedValues);
return String.format("(%s) ", commaSeparatedQuoted);
}
private DataSourceMimeTypeSummary() {
}
}

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.casemodule.datasourcesummary;
package org.sleuthkit.autopsy.datasourcesummary.datamodel;
import java.sql.ResultSet;
import java.sql.SQLException;

View File

@ -0,0 +1,295 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2020 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.datasourcesummary.datamodel;
import java.io.File;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.function.Function;
import java.util.logging.Level;
import java.util.stream.Collectors;
import org.apache.commons.lang.StringUtils;
import org.sleuthkit.autopsy.coreutils.Logger;
import static org.sleuthkit.autopsy.datasourcesummary.datamodel.DataSourceInfoUtilities.getBaseQueryResult;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.DataSource;
/**
* Provides information to populate Top Programs Summary queries.
*/
public class DataSourceTopProgramsSummary {
private static final Logger logger = Logger.getLogger(DataSourceTopProgramsSummary.class.getName());
/**
* A SQL join type.
*/
private enum JoinType {
LEFT,
RIGHT,
INNER,
OUTER
}
/**
* A blackboard attribute value column.
*/
private enum AttributeColumn {
value_text,
value_int32,
value_int64
}
/**
* The suffix joined to a key name for use as an identifier of a query.
*/
private static final String QUERY_SUFFIX = "_query";
/**
* Creates a sql statement querying the blackboard attributes table for a
* particular attribute type and returning a specified value. That query
* also joins with the blackboard artifact table.
*
* @param joinType The type of join statement to create.
* @param attributeColumn The blackboard attribute column that should be
* returned.
* @param attrType The attribute type to query for.
* @param keyName The aliased name of the attribute to return. This
* is also used to calculate the alias of the query
* same as getFullKey.
* @param bbaName The blackboard artifact table alias.
*
* @return The generated sql statement.
*/
private static String getAttributeJoin(JoinType joinType, AttributeColumn attributeColumn, BlackboardAttribute.ATTRIBUTE_TYPE attrType, String keyName, String bbaName) {
String queryName = keyName + QUERY_SUFFIX;
String innerQueryName = "inner_attribute_" + queryName;
return "\n" + joinType + " JOIN (\n"
+ " SELECT \n"
+ " " + innerQueryName + ".artifact_id,\n"
+ " " + innerQueryName + "." + attributeColumn + " AS " + keyName + "\n"
+ " FROM blackboard_attributes " + innerQueryName + "\n"
+ " WHERE " + innerQueryName + ".attribute_type_id = " + attrType.getTypeID() + " -- " + attrType.name() + "\n"
+ ") " + queryName + " ON " + queryName + ".artifact_id = " + bbaName + ".artifact_id\n";
}
/**
* Given a column key, creates the full name for the column key.
*
* @param key The column key.
*
* @return The full identifier for the column key.
*/
private static String getFullKey(String key) {
return key + QUERY_SUFFIX + "." + key;
}
/**
* Constructs a SQL 'where' statement from a list of clauses and puts
* parenthesis around each clause.
*
* @param clauses The clauses
*
* @return The generated 'where' statement.
*/
private static String getWhereString(List<String> clauses) {
if (clauses.isEmpty()) {
return "";
}
List<String> parenthesized = clauses.stream()
.map(c -> "(" + c + ")")
.collect(Collectors.toList());
return "\nWHERE " + String.join("\n AND ", parenthesized) + "\n";
}
/**
* Generates a [column] LIKE sql clause.
*
* @param column The column identifier.
* @param likeString The string that will be used as column comparison.
* @param isLike if false, the statement becomes NOT LIKE.
*
* @return The generated statement.
*/
private static String getLikeClause(String column, String likeString, boolean isLike) {
return column + (isLike ? "" : " NOT") + " LIKE '" + likeString + "'";
}
/**
* Retrieves a list of the top programs used on the data source. Currently
* determines this based off of which prefetch results return the highest
* count.
*
* @param dataSource The data source.
* @param count The number of programs to return.
*
* @return
*/
public static List<TopProgramsResult> getTopPrograms(DataSource dataSource, int count) {
if (dataSource == null || count <= 0) {
return Collections.emptyList();
}
// ntosboot should be ignored
final String ntosBootIdentifier = "NTOSBOOT";
// programs in windows directory to be ignored
final String windowsDir = "/WINDOWS%";
final String nameParam = "name";
final String pathParam = "path";
final String runCountParam = "run_count";
final String lastRunParam = "last_run";
String bbaQuery = "bba";
final String query = "SELECT\n"
+ " " + getFullKey(nameParam) + " AS " + nameParam + ",\n"
+ " " + getFullKey(pathParam) + " AS " + pathParam + ",\n"
+ " MAX(" + getFullKey(runCountParam) + ") AS " + runCountParam + ",\n"
+ " MAX(" + getFullKey(lastRunParam) + ") AS " + lastRunParam + "\n"
+ "FROM blackboard_artifacts " + bbaQuery + "\n"
+ getAttributeJoin(JoinType.INNER, AttributeColumn.value_text, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME, nameParam, bbaQuery)
+ getAttributeJoin(JoinType.LEFT, AttributeColumn.value_text, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH, pathParam, bbaQuery)
+ getAttributeJoin(JoinType.LEFT, AttributeColumn.value_int32, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COUNT, runCountParam, bbaQuery)
+ getAttributeJoin(JoinType.LEFT, AttributeColumn.value_int64, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, lastRunParam, bbaQuery)
+ getWhereString(Arrays.asList(
bbaQuery + ".artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_PROG_RUN.getTypeID(),
bbaQuery + ".data_source_obj_id = " + dataSource.getId(),
// exclude ntosBootIdentifier from results
getLikeClause(getFullKey(nameParam), ntosBootIdentifier, false),
// exclude windows directory items from results
getFullKey(pathParam) + " IS NULL OR " + getLikeClause(getFullKey(pathParam), windowsDir, false)
))
+ "GROUP BY " + getFullKey(nameParam) + ", " + getFullKey(pathParam) + "\n"
+ "ORDER BY \n"
+ " MAX(" + getFullKey(runCountParam) + ") DESC,\n"
+ " MAX(" + getFullKey(lastRunParam) + ") DESC,\n"
+ " " + getFullKey(nameParam) + " ASC";
final String errorMessage = "Unable to get top program results; returning null.";
DataSourceInfoUtilities.ResultSetHandler<List<TopProgramsResult>> handler = (resultSet) -> {
List<TopProgramsResult> progResults = new ArrayList<>();
boolean quitAtCount = false;
while (resultSet.next() && (!quitAtCount || progResults.size() < count)) {
try {
long lastRunEpoch = resultSet.getLong(lastRunParam);
Date lastRun = (resultSet.wasNull()) ? null : new Date(lastRunEpoch * 1000);
Long runCount = resultSet.getLong(runCountParam);
if (resultSet.wasNull()) {
runCount = null;
}
if (lastRun != null || runCount != null) {
quitAtCount = true;
}
progResults.add(new TopProgramsResult(
resultSet.getString(nameParam),
resultSet.getString(pathParam),
runCount,
lastRun));
} catch (SQLException ex) {
logger.log(Level.WARNING, "Failed to get a top program result from the result set.", ex);
}
}
return progResults;
};
return getBaseQueryResult(query, handler, errorMessage);
}
/**
* Functions that determine the folder name of a list of path elements. If
* not matched, function returns null.
*/
private static final List<Function<List<String>, String>> SHORT_FOLDER_MATCHERS = Arrays.asList(
// handle Program Files and Program Files (x86) - if true, return the next folder
(pathList) -> {
if (pathList.size() < 2) {
return null;
}
String rootParent = pathList.get(0).toUpperCase();
if ("PROGRAM FILES".equals(rootParent) || "PROGRAM FILES (X86)".equals(rootParent)) {
return pathList.get(1);
} else {
return null;
}
},
// if there is a folder named "APPLICATION DATA" or "APPDATA"
(pathList) -> {
for (String pathEl : pathList) {
String uppered = pathEl.toUpperCase();
if ("APPLICATION DATA".equals(uppered) || "APPDATA".equals(uppered)) {
return "AppData";
}
}
return null;
}
);
/**
* Determines a short folder name if any. Otherwise, returns empty string.
*
* @param strPath The string path.
*
* @return The short folder name or empty string if not found.
*/
public static String getShortFolderName(String strPath, String applicationName) {
if (strPath == null) {
return "";
}
List<String> pathEls = new ArrayList<>(Arrays.asList(applicationName));
File file = new File(strPath);
while (file != null && StringUtils.isNotBlank(file.getName())) {
pathEls.add(file.getName());
file = file.getParentFile();
}
Collections.reverse(pathEls);
for (Function<List<String>, String> matchEntry : SHORT_FOLDER_MATCHERS) {
String result = matchEntry.apply(pathEls);
if (StringUtils.isNotBlank(result)) {
return result;
}
}
return "";
}
private DataSourceTopProgramsSummary() {
}
}

View File

@ -0,0 +1,74 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2020 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.datasourcesummary.datamodel;
import java.util.Date;
/**
* Describes a result of a program run on a datasource.
*/
public class TopProgramsResult {
private final String programName;
private final String programPath;
private final Long runTimes;
private final Date lastRun;
/**
* Main constructor.
*
* @param programName The name of the program.
* @param programPath The path of the program.
* @param runTimes The number of runs.
*/
TopProgramsResult(String programName, String programPath, Long runTimes, Date lastRun) {
this.programName = programName;
this.programPath = programPath;
this.runTimes = runTimes;
this.lastRun = lastRun;
}
/**
* @return The name of the program
*/
public String getProgramName() {
return programName;
}
/**
* @return The path of the program.
*/
public String getProgramPath() {
return programPath;
}
/**
* @return The number of run times or null if not present.
*/
public Long getRunTimes() {
return runTimes;
}
/**
* @return The last time the program was run or null if not present.
*/
public Date getLastRun() {
return lastRun;
}
}

View File

@ -33,6 +33,6 @@ DataSourceSummaryDetailsPanel.acquisitionDetailsTextArea.text=
DataSourceSummaryDetailsPanel.acquisitionDetailsLabel.text=Acquisition Details:
DataSourceSummaryDetailsPanel.unallocatedSizeLabel.text=Unallocated Space:
DataSourceSummaryDetailsPanel.unallocatedSizeValue.text=
DataSourceSummaryCountsPanel.byMimeTypeLabel.text=Files by MIME Type
DataSourceSummaryCountsPanel.byCategoryLabel.text=Files by Category
DataSourceSummaryCountsPanel.jLabel1.text=Results by Type
DataSourceSummaryCountsPanel.resultsByTypeLabel.text=Results by Type
DataSourceSummaryUserActivityPanel.programsRunLabel.text=Top Programs Run

View File

@ -1,4 +1,7 @@
CTL_DataSourceSummaryAction=Data Source Summary
DataSourceSummaryCountsPanel.ArtifactCountsTableModel.count.header=Count
DataSourceSummaryCountsPanel.ArtifactCountsTableModel.type.header=Result Type
DataSourceSummaryCountsPanel.byMimeTypeLabel.text=Files by MIME Type
DataSourceSummaryCountsPanel.FilesByCategoryTableModel.all.row=All
DataSourceSummaryCountsPanel.FilesByCategoryTableModel.allocated.row=Allocated
DataSourceSummaryCountsPanel.FilesByCategoryTableModel.count.header=Count
@ -7,12 +10,12 @@ DataSourceSummaryCountsPanel.FilesByCategoryTableModel.slack.row=Slack
DataSourceSummaryCountsPanel.FilesByCategoryTableModel.type.header=File Type
DataSourceSummaryCountsPanel.FilesByCategoryTableModel.unallocated.row=Unallocated
DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.audio.row=Audio
DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.count.header=Count
DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.documents.row=Documents
DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.executables.row=Executables
DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.images.row=Images
DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.type.header=File Type
DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.videos.row=Videos
DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_notAnalyzed_label=Not Analyzed
DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_other_label=Other
DataSourceSummaryDetailsPanel.getDataSources.error.text=Failed to get the list of datasources for the current case.
DataSourceSummaryDetailsPanel.getDataSources.error.title=Load Failure
DataSourceSummaryDetailsPanel.units.bytes=\ bytes
@ -56,12 +59,8 @@ DataSourceSummaryDetailsPanel.acquisitionDetailsTextArea.text=
DataSourceSummaryDetailsPanel.acquisitionDetailsLabel.text=Acquisition Details:
DataSourceSummaryDetailsPanel.unallocatedSizeLabel.text=Unallocated Space:
DataSourceSummaryDetailsPanel.unallocatedSizeValue.text=
DataSourceSummaryCountsPanel.byMimeTypeLabel.text=Files by MIME Type
DataSourceSummaryCountsPanel.byCategoryLabel.text=Files by Category
DataSourceSummaryCountsPanel.jLabel1.text=Results by Type
DataSourceSummaryDialog.countsTab.title=Counts
DataSourceSummaryDialog.detailsTab.title=Details
DataSourceSummaryDialog.ingestHistoryTab.title=Ingest History
DataSourceSummaryCountsPanel.resultsByTypeLabel.text=Results by Type
DataSourceSummaryDialog.window.title=Data Sources Summary
DataSourceSummaryNode.column.dataSourceName.header=Data Source Name
DataSourceSummaryNode.column.files.header=Files
@ -70,4 +69,14 @@ DataSourceSummaryNode.column.status.header=Ingest Status
DataSourceSummaryNode.column.tags.header=Tags
DataSourceSummaryNode.column.type.header=Type
DataSourceSummaryNode.viewDataSourceAction.text=Go to Data Source
DataSourceSummaryTabbedPane_countsTab_title=Counts
DataSourceSummaryTabbedPane_detailsTab_title=Details
DataSourceSummaryTabbedPane_ingestHistoryTab_title=Ingest History
DataSourceSummaryTabbedPane_userActivityTab_title=User Activity
DataSourceSummaryUserActivityPanel.programsRunLabel.text=Top Programs Run
DataSourceSummaryUserActivityPanel_tab_title=User Activity
DataSourceSummaryUserActivityPanel_TopProgramsTableModel_count_header=Run Times
DataSourceSummaryUserActivityPanel_TopProgramsTableModel_folder_header=Folder
DataSourceSummaryUserActivityPanel_TopProgramsTableModel_lastrun_header=Last Run
DataSourceSummaryUserActivityPanel_TopProgramsTableModel_name_header=Program
ViewSummaryInformationAction.name.text=View Summary Information

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.casemodule.datasourcesummary;
package org.sleuthkit.autopsy.datasourcesummary.ui;
import java.awt.EventQueue;
import java.beans.PropertyVetoException;
@ -35,10 +35,11 @@ import javax.swing.event.ListSelectionListener;
import org.openide.nodes.Node;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.casemodule.datasourcesummary.DataSourceSummaryNode.DataSourceSummaryEntryNode;
import org.sleuthkit.autopsy.datasourcesummary.ui.DataSourceSummaryNode.DataSourceSummaryEntryNode;
import static javax.swing.SwingConstants.RIGHT;
import javax.swing.SwingUtilities;
import javax.swing.table.TableColumn;
import org.sleuthkit.autopsy.datasourcesummary.datamodel.CaseDataSourcesSummary;
import org.sleuthkit.datamodel.DataSource;
import org.sleuthkit.datamodel.IngestJobInfo;
import org.sleuthkit.datamodel.SleuthkitCase;
@ -152,8 +153,8 @@ final class DataSourceBrowser extends javax.swing.JPanel implements ExplorerMana
private List<DataSourceSummary> getDataSourceSummaryList(Map<Long, String> usageMap, Map<Long, Long> fileCountsMap) {
List<DataSourceSummary> summaryList = new ArrayList<>();
final Map<Long, Long> artifactCountsMap = DataSourceInfoUtilities.getCountsOfArtifacts();
final Map<Long, Long> tagCountsMap = DataSourceInfoUtilities.getCountsOfTags();
final Map<Long, Long> artifactCountsMap = CaseDataSourcesSummary.getCountsOfArtifacts();
final Map<Long, Long> tagCountsMap = CaseDataSourcesSummary.getCountsOfTags();
try {
SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
for (DataSource dataSource : skCase.getDataSources()) {

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.casemodule.datasourcesummary;
package org.sleuthkit.autopsy.datasourcesummary.ui;
import java.sql.ResultSet;
import java.sql.SQLException;

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.casemodule.datasourcesummary;
package org.sleuthkit.autopsy.datasourcesummary.ui;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
@ -28,6 +28,7 @@ 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.datasourcesummary.ui.Bundle;
@ActionID(category = "Case", id = "org.sleuthkit.autopsy.casemodule.datasourcesummary.DataSourceSummaryAction")
@ActionRegistration(displayName = "#CTL_DataSourceSummaryAction", lazy = false)

View File

@ -0,0 +1,222 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.8" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="scrollParent" alignment="0" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="scrollParent" alignment="0" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JScrollPane" name="scrollParent">
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="parentPanel">
<Properties>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[840, 320]"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="fileTypePiePanel" min="-2" pref="400" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="fileCountsByCategoryScrollPane" alignment="0" min="-2" pref="140" max="-2" attributes="0"/>
<Component id="byCategoryLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="filesByCatParent" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="resultsByTypeLabel" min="-2" pref="79" max="-2" attributes="0"/>
<Group type="102" attributes="0">
<Component id="artifactCountsScrollPane" min="-2" pref="244" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="resultsByTypeParent" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="fileTypePiePanel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="3" attributes="0">
<Component id="byCategoryLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="resultsByTypeLabel" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<EmptySpace max="32767" attributes="0"/>
<Component id="resultsByTypeParent" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="148" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="artifactCountsScrollPane" pref="0" max="32767" attributes="0"/>
<Group type="102" attributes="0">
<Component id="fileCountsByCategoryScrollPane" min="-2" pref="107" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="31" max="-2" attributes="0"/>
<Component id="filesByCatParent" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</Group>
</Group>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JScrollPane" name="fileCountsByCategoryScrollPane">
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTable" name="fileCountsByCategoryTable">
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JLabel" name="byCategoryLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryCountsPanel.byCategoryLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
</Component>
<Component class="javax.swing.JLabel" name="resultsByTypeLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryCountsPanel.resultsByTypeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
</Component>
<Container class="javax.swing.JScrollPane" name="artifactCountsScrollPane">
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTable" name="artifactCountsTable">
<Properties>
<Property name="autoCreateRowSorter" type="boolean" value="true"/>
</Properties>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="fileTypePiePanel">
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[400, 300]"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="fileTypePieChart"/>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignFlowLayout"/>
</Container>
<Container class="javax.swing.JPanel" name="filesByCatParent">
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
</Container>
<Container class="javax.swing.JPanel" name="resultsByTypeParent">
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
</Container>
</SubComponents>
</Container>
</SubComponents>
</Container>
</SubComponents>
</Form>

View File

@ -0,0 +1,304 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019 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.datasourcesummary.ui;
import java.util.Map;
import javax.swing.JLabel;
import javax.swing.table.DefaultTableCellRenderer;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataSourceCountsSummary;
import org.sleuthkit.datamodel.DataSource;
/**
* Panel for displaying summary information on the known files present in the
* specified DataSource
*/
@Messages({
"DataSourceSummaryCountsPanel.ArtifactCountsTableModel.type.header=Result Type",
"DataSourceSummaryCountsPanel.ArtifactCountsTableModel.count.header=Count",
"DataSourceSummaryCountsPanel.FilesByCategoryTableModel.type.header=File Type",
"DataSourceSummaryCountsPanel.FilesByCategoryTableModel.count.header=Count"
})
final class DataSourceSummaryCountsPanel extends javax.swing.JPanel {
private static final long serialVersionUID = 1L;
// Result returned for a data model if no data found.
private static final Object[][] EMPTY_PAIRS = new Object[][]{};
// column headers for file by category table
private static final Object[] FILE_BY_CATEGORY_COLUMN_HEADERS = new Object[]{
Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_type_header(),
Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_count_header()
};
// column headers for artifact counts table
private static final Object[] ARTIFACT_COUNTS_COLUMN_HEADERS = new Object[]{
Bundle.DataSourceSummaryCountsPanel_ArtifactCountsTableModel_type_header(),
Bundle.DataSourceSummaryCountsPanel_ArtifactCountsTableModel_count_header()
};
private final DefaultTableCellRenderer rightAlignedRenderer = new DefaultTableCellRenderer();
private final FileTypePieChart fileTypePieChart = new FileTypePieChart();
private DataSource dataSource;
/**
* Creates new form DataSourceSummaryCountsPanel
*/
DataSourceSummaryCountsPanel() {
rightAlignedRenderer.setHorizontalAlignment(JLabel.RIGHT);
initComponents();
fileCountsByCategoryTable.getTableHeader().setReorderingAllowed(false);
artifactCountsTable.getTableHeader().setReorderingAllowed(false);
setDataSource(null);
}
/**
* The datasource currently used as the model in this panel.
*
* @return The datasource currently being used as the model in this panel.
*/
public DataSource getDataSource() {
return dataSource;
}
/**
* Sets datasource to visualize in the panel.
*
* @param dataSource The datasource to use in this panel.
*/
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
if (dataSource == null || !Case.isCaseOpen()) {
updateCountsTableData(EMPTY_PAIRS, EMPTY_PAIRS);
} else {
updateCountsTableData(getFileCategoryModel(dataSource), getArtifactCountsModel(dataSource));
}
this.fileTypePieChart.setDataSource(dataSource);
}
/**
* Specify the DataSource to display file information for.
*
* @param fileCategoryDataModel The file category data model.
* @param artifactDataModel The artifact type data model.
*/
private void updateCountsTableData(Object[][] fileCategoryDataModel, Object[][] artifactDataModel) {
fileCountsByCategoryTable.setModel(new NonEditableTableModel(fileCategoryDataModel, FILE_BY_CATEGORY_COLUMN_HEADERS));
fileCountsByCategoryTable.getColumnModel().getColumn(1).setCellRenderer(rightAlignedRenderer);
fileCountsByCategoryTable.getColumnModel().getColumn(0).setPreferredWidth(130);
artifactCountsTable.setModel(new NonEditableTableModel(artifactDataModel, ARTIFACT_COUNTS_COLUMN_HEADERS));
artifactCountsTable.getColumnModel().getColumn(0).setPreferredWidth(230);
artifactCountsTable.getColumnModel().getColumn(1).setCellRenderer(rightAlignedRenderer);
this.repaint();
}
/**
* Determines the JTable data model for datasource file categories.
*
* @param dataSource The DataSource.
*
* @return The model to be used with a JTable.
*/
@Messages({
"DataSourceSummaryCountsPanel.FilesByCategoryTableModel.all.row=All",
"DataSourceSummaryCountsPanel.FilesByCategoryTableModel.allocated.row=Allocated",
"DataSourceSummaryCountsPanel.FilesByCategoryTableModel.unallocated.row=Unallocated",
"DataSourceSummaryCountsPanel.FilesByCategoryTableModel.slack.row=Slack",
"DataSourceSummaryCountsPanel.FilesByCategoryTableModel.directory.row=Directory"
})
private static Object[][] getFileCategoryModel(DataSource selectedDataSource) {
Long fileCount = zeroIfNull(DataSourceCountsSummary.getCountOfFiles(selectedDataSource));
Long unallocatedFiles = zeroIfNull(DataSourceCountsSummary.getCountOfUnallocatedFiles(selectedDataSource));
Long allocatedFiles = zeroIfNull(DataSourceCountsSummary.getCountOfAllocatedFiles(selectedDataSource));
Long slackFiles = zeroIfNull(DataSourceCountsSummary.getCountOfSlackFiles(selectedDataSource));
Long directories = zeroIfNull(DataSourceCountsSummary.getCountOfDirectories(selectedDataSource));
return new Object[][]{
new Object[]{Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_all_row(), fileCount},
new Object[]{Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_allocated_row(), allocatedFiles},
new Object[]{Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_unallocated_row(), unallocatedFiles},
new Object[]{Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_slack_row(), slackFiles},
new Object[]{Bundle.DataSourceSummaryCountsPanel_FilesByCategoryTableModel_directory_row(), directories}
};
}
/**
* Returns 0 if value is null.
*
* @param origValue The original value.
*
* @return The value or 0 if null.
*/
private static Long zeroIfNull(Long origValue) {
return origValue == null ? 0 : origValue;
}
/**
* The counts of different artifact types found in a DataSource.
*
* @param selectedDataSource The DataSource.
*
* @return The JTable data model of counts of artifact types.
*/
private static Object[][] getArtifactCountsModel(DataSource selectedDataSource) {
Map<String, Long> artifactMapping = DataSourceCountsSummary.getCountsOfArtifactsByType(selectedDataSource);
if (artifactMapping == null) {
return EMPTY_PAIRS;
}
return artifactMapping.entrySet().stream()
.filter((entrySet) -> entrySet != null && entrySet.getKey() != null)
.sorted((a, b) -> a.getKey().compareTo(b.getKey()))
.map((entrySet) -> new Object[]{entrySet.getKey(), entrySet.getValue()})
.toArray(Object[][]::new);
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
javax.swing.JScrollPane scrollParent = new javax.swing.JScrollPane();
javax.swing.JPanel parentPanel = new javax.swing.JPanel();
javax.swing.JScrollPane fileCountsByCategoryScrollPane = new javax.swing.JScrollPane();
fileCountsByCategoryTable = new javax.swing.JTable();
javax.swing.JLabel byCategoryLabel = new javax.swing.JLabel();
javax.swing.JLabel resultsByTypeLabel = new javax.swing.JLabel();
javax.swing.JScrollPane artifactCountsScrollPane = new javax.swing.JScrollPane();
artifactCountsTable = new javax.swing.JTable();
javax.swing.JPanel fileTypePiePanel = fileTypePieChart;
javax.swing.JPanel filesByCatParent = new javax.swing.JPanel();
javax.swing.JPanel resultsByTypeParent = new javax.swing.JPanel();
parentPanel.setMinimumSize(new java.awt.Dimension(840, 320));
fileCountsByCategoryScrollPane.setViewportView(fileCountsByCategoryTable);
org.openide.awt.Mnemonics.setLocalizedText(byCategoryLabel, org.openide.util.NbBundle.getMessage(DataSourceSummaryCountsPanel.class, "DataSourceSummaryCountsPanel.byCategoryLabel.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(resultsByTypeLabel, org.openide.util.NbBundle.getMessage(DataSourceSummaryCountsPanel.class, "DataSourceSummaryCountsPanel.resultsByTypeLabel.text")); // NOI18N
artifactCountsTable.setAutoCreateRowSorter(true);
artifactCountsScrollPane.setViewportView(artifactCountsTable);
fileTypePiePanel.setPreferredSize(new java.awt.Dimension(400, 300));
javax.swing.GroupLayout filesByCatParentLayout = new javax.swing.GroupLayout(filesByCatParent);
filesByCatParent.setLayout(filesByCatParentLayout);
filesByCatParentLayout.setHorizontalGroup(
filesByCatParentLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 0, Short.MAX_VALUE)
);
filesByCatParentLayout.setVerticalGroup(
filesByCatParentLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 0, Short.MAX_VALUE)
);
javax.swing.GroupLayout resultsByTypeParentLayout = new javax.swing.GroupLayout(resultsByTypeParent);
resultsByTypeParent.setLayout(resultsByTypeParentLayout);
resultsByTypeParentLayout.setHorizontalGroup(
resultsByTypeParentLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 0, Short.MAX_VALUE)
);
resultsByTypeParentLayout.setVerticalGroup(
resultsByTypeParentLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 0, Short.MAX_VALUE)
);
javax.swing.GroupLayout parentPanelLayout = new javax.swing.GroupLayout(parentPanel);
parentPanel.setLayout(parentPanelLayout);
parentPanelLayout.setHorizontalGroup(
parentPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(parentPanelLayout.createSequentialGroup()
.addContainerGap()
.addComponent(fileTypePiePanel, javax.swing.GroupLayout.PREFERRED_SIZE, 400, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addGroup(parentPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(fileCountsByCategoryScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 140, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(byCategoryLabel)
.addComponent(filesByCatParent, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(18, 18, 18)
.addGroup(parentPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(resultsByTypeLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 79, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(parentPanelLayout.createSequentialGroup()
.addComponent(artifactCountsScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 244, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(resultsByTypeParent, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
parentPanelLayout.setVerticalGroup(
parentPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(parentPanelLayout.createSequentialGroup()
.addContainerGap()
.addGroup(parentPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(parentPanelLayout.createSequentialGroup()
.addComponent(fileTypePiePanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGroup(parentPanelLayout.createSequentialGroup()
.addGroup(parentPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(byCategoryLabel)
.addComponent(resultsByTypeLabel))
.addGroup(parentPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, parentPanelLayout.createSequentialGroup()
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(resultsByTypeParent, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(148, 148, 148))
.addGroup(parentPanelLayout.createSequentialGroup()
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(parentPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(artifactCountsScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
.addGroup(parentPanelLayout.createSequentialGroup()
.addComponent(fileCountsByCategoryScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 107, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(31, 31, 31)
.addComponent(filesByCatParent, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, Short.MAX_VALUE)))
.addContainerGap())))))
);
scrollParent.setViewportView(parentPanel);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(scrollParent)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(scrollParent)
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JTable artifactCountsTable;
private javax.swing.JTable fileCountsByCategoryTable;
// End of variables declaration//GEN-END:variables
}

View File

@ -40,7 +40,7 @@
<Component class="javax.swing.JLabel" name="operatingSystemLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.operatingSystemLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.operatingSystemLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
@ -52,7 +52,7 @@
<Component class="javax.swing.JLabel" name="displayNameLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.displayNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.displayNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
@ -64,7 +64,7 @@
<Component class="javax.swing.JLabel" name="originalNameLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.originalNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.originalNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
@ -76,7 +76,7 @@
<Component class="javax.swing.JLabel" name="sha1HashValue">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.sha1HashValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.sha1HashValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
@ -88,10 +88,10 @@
<Component class="javax.swing.JLabel" name="operatingSystemValue">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.operatingSystemValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.operatingSystemValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.operatingSystemValue.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.operatingSystemValue.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
@ -103,7 +103,7 @@
<Component class="javax.swing.JLabel" name="displayNameValue">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.displayNameValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.displayNameValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
@ -115,7 +115,7 @@
<Component class="javax.swing.JLabel" name="sha256HashValue">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.sha256HashValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.sha256HashValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
@ -127,7 +127,7 @@
<Component class="javax.swing.JLabel" name="originalNameValue">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.originalNameValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.originalNameValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
@ -139,10 +139,10 @@
<Component class="javax.swing.JLabel" name="deviceIdValue">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.deviceIdValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.deviceIdValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.deviceIdValue.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.deviceIdValue.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
@ -179,7 +179,7 @@
<TableColumnModel selectionModel="0">
<Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true">
<Title editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.filePathsTable.columnModel.title0" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.filePathsTable.columnModel.title0" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Title>
<Editor/>
<Renderer/>
@ -196,7 +196,7 @@
<Component class="javax.swing.JLabel" name="dataSourceUsageValue">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.dataSourceUsageValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.dataSourceUsageValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
@ -208,7 +208,7 @@
<Component class="javax.swing.JLabel" name="timeZoneValue">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.timeZoneValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.timeZoneValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
@ -220,10 +220,10 @@
<Component class="javax.swing.JLabel" name="imageTypeValue">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.imageTypeValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.imageTypeValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.imageTypeValue.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.imageTypeValue.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
@ -235,10 +235,10 @@
<Component class="javax.swing.JLabel" name="md5HashValue">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.md5HashValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.md5HashValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.md5HashValue.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.md5HashValue.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
@ -250,7 +250,7 @@
<Component class="javax.swing.JLabel" name="sectorSizeValue">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.sectorSizeValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.sectorSizeValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
@ -262,7 +262,7 @@
<Component class="javax.swing.JLabel" name="sizeValue">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.sizeValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.sizeValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
@ -274,7 +274,7 @@
<Component class="javax.swing.JLabel" name="filePathsLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.filePathsLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.filePathsLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
@ -286,7 +286,7 @@
<Component class="javax.swing.JLabel" name="sha256HashLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.sha256HashLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.sha256HashLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
@ -298,7 +298,7 @@
<Component class="javax.swing.JLabel" name="sha1HashLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.sha1HashLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.sha1HashLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
@ -310,7 +310,7 @@
<Component class="javax.swing.JLabel" name="md5HashLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.md5HashLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.md5HashLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
@ -322,7 +322,7 @@
<Component class="javax.swing.JLabel" name="sectorSizeLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.sectorSizeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.sectorSizeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
@ -334,7 +334,7 @@
<Component class="javax.swing.JLabel" name="sizeLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.sizeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.sizeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
@ -346,7 +346,7 @@
<Component class="javax.swing.JLabel" name="imageTypeLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.imageTypeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.imageTypeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
@ -358,7 +358,7 @@
<Component class="javax.swing.JLabel" name="acquisitionDetailsLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.acquisitionDetailsLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.acquisitionDetailsLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
@ -370,7 +370,7 @@
<Component class="javax.swing.JLabel" name="timeZoneLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.timeZoneLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.timeZoneLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
@ -382,7 +382,7 @@
<Component class="javax.swing.JLabel" name="dataSourceUsageLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.dataSourceUsageLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.dataSourceUsageLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
@ -394,7 +394,7 @@
<Component class="javax.swing.JLabel" name="deviceIdLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.deviceIdLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.deviceIdLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
@ -424,7 +424,7 @@
<Property name="columns" type="int" value="20"/>
<Property name="rows" type="int" value="4"/>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.acquisitionDetailsTextArea.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.acquisitionDetailsTextArea.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="null"/>
@ -466,7 +466,7 @@
<Component class="javax.swing.JLabel" name="unallocatedSizeLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.unallocatedSizeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.unallocatedSizeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
@ -478,7 +478,7 @@
<Component class="javax.swing.JLabel" name="unallocatedSizeValue">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDetailsPanel.unallocatedSizeValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDetailsPanel.unallocatedSizeValue.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>

View File

@ -16,15 +16,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.casemodule.datasourcesummary;
package org.sleuthkit.autopsy.datasourcesummary.ui;
import java.text.DecimalFormat;
import java.util.Map;
import java.util.HashMap;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import javax.swing.table.DefaultTableModel;
import org.apache.commons.lang3.StringUtils;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataSourceDetailsSummary;
import org.sleuthkit.datamodel.DataSource;
import org.sleuthkit.datamodel.Image;
import org.sleuthkit.datamodel.TskCoreException;
@ -36,23 +37,47 @@ class DataSourceSummaryDetailsPanel extends javax.swing.JPanel {
//Because this panel was made using the gridbaglayout and netbean's Customize Layout tool it will be best to continue to modify it through that
private static final long serialVersionUID = 1L;
private Map<Long, String> osDetailMap = new HashMap<>();
private static final Integer SIZE_COVERSION_CONSTANT = 1000;
private static final DecimalFormat APPROXIMATE_SIZE_FORMAT = new DecimalFormat("#.##");
private final Map<Long, Long> unallocatedFilesSizeMap;
private final Map<Long, String> usageMap;
private static final Logger logger = Logger.getLogger(DataSourceSummaryDetailsPanel.class.getName());
private DataSource dataSource;
/**
* Creates new form DataSourceSummaryDetailsPanel
*/
@Messages({"DataSourceSummaryDetailsPanel.getDataSources.error.text=Failed to get the list of datasources for the current case.",
"DataSourceSummaryDetailsPanel.getDataSources.error.title=Load Failure"})
DataSourceSummaryDetailsPanel(Map<Long, String> usageMap) {
DataSourceSummaryDetailsPanel() {
initComponents();
this.usageMap = usageMap;
this.unallocatedFilesSizeMap = DataSourceInfoUtilities.getSizeOfUnallocatedFiles();
osDetailMap = DataSourceInfoUtilities.getOperatingSystems();
setDataSource(null);
}
/**
* The datasource currently used as the model in this panel.
*
* @return The datasource currently being used as the model in this panel.
*/
public DataSource getDataSource() {
return dataSource;
}
/**
* Sets datasource to visualize in the panel.
*
* @param dataSource The datasource to use in this panel.
*/
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
if (dataSource == null || !Case.isCaseOpen()) {
updateDetailsPanelData(null, null, null, null);
} else {
updateDetailsPanelData(dataSource,
DataSourceDetailsSummary.getSizeOfUnallocatedFiles(dataSource),
DataSourceDetailsSummary.getOperatingSystems(dataSource),
DataSourceDetailsSummary.getDataSourceType(dataSource));
}
}
/**
@ -60,77 +85,80 @@ class DataSourceSummaryDetailsPanel extends javax.swing.JPanel {
*
* @param selectedDataSource the DataSource to display details about.
*/
void updateDetailsPanelData(DataSource selectedDataSource) {
private void updateDetailsPanelData(DataSource selectedDataSource, Long unallocatedFilesSize, String osDetails, String usage) {
clearTableValues();
if (selectedDataSource != null) {
String sizeString = "";
String sectorSizeString = "";
String md5String = "";
String sha1String = "";
String sha256String = "";
String acquisitionDetailsString = "";
String imageTypeString = "";
String[] filePaths = new String[0];
String osDetailString = osDetailMap.get(selectedDataSource.getId()) == null ? "" : osDetailMap.get(selectedDataSource.getId());
String dataSourceTypeString = usageMap.get(selectedDataSource.getId()) == null ? "" : usageMap.get(selectedDataSource.getId());
try {
acquisitionDetailsString = selectedDataSource.getAcquisitionDetails();
} catch (TskCoreException ex) {
logger.log(Level.WARNING, "Unable to get aquisition details for selected data source", ex);
}
if (selectedDataSource instanceof Image) {
imageTypeString = ((Image) selectedDataSource).getType().getName();
filePaths = ((Image) selectedDataSource).getPaths();
sizeString = getSizeString(selectedDataSource.getSize());
sectorSizeString = getSizeString(((Image) selectedDataSource).getSsize());
try {
//older databases may have null as the hash values
md5String = ((Image) selectedDataSource).getMd5();
if (md5String == null) {
md5String = "";
}
} catch (TskCoreException ex) {
logger.log(Level.WARNING, "Unable to get MD5 for selected data source", ex);
}
try {
sha1String = ((Image) selectedDataSource).getSha1();
if (sha1String == null) {
sha1String = "";
}
} catch (TskCoreException ex) {
logger.log(Level.WARNING, "Unable to get SHA1 for selected data source", ex);
}
try {
sha256String = ((Image) selectedDataSource).getSha256();
if (sha256String == null) {
sha256String = "";
}
} catch (TskCoreException ex) {
logger.log(Level.WARNING, "Unable to get SHA256 for selected data source", ex);
}
}
unallocatedSizeValue.setText(getSizeString(unallocatedFilesSize));
operatingSystemValue.setText(StringUtils.isBlank(osDetails) ? "" : osDetails);
dataSourceUsageValue.setText(StringUtils.isBlank(usage) ? "" : usage);
timeZoneValue.setText(selectedDataSource.getTimeZone());
displayNameValue.setText(selectedDataSource.getName());
originalNameValue.setText(selectedDataSource.getName());
deviceIdValue.setText(selectedDataSource.getDeviceId());
dataSourceUsageValue.setText(dataSourceTypeString);
operatingSystemValue.setText(osDetailString);
timeZoneValue.setText(selectedDataSource.getTimeZone());
acquisitionDetailsTextArea.setText(acquisitionDetailsString);
imageTypeValue.setText(imageTypeString);
sizeValue.setText(sizeString);
unallocatedSizeValue.setText(getSizeString(unallocatedFilesSizeMap.get(selectedDataSource.getId())));
sectorSizeValue.setText(sectorSizeString);
md5HashValue.setText(md5String);
sha1HashValue.setText(sha1String);
sha256HashValue.setText(sha256String);
for (String path : filePaths) {
((DefaultTableModel) filePathsTable.getModel()).addRow(new Object[]{path});
try {
acquisitionDetailsTextArea.setText(selectedDataSource.getAcquisitionDetails());
} catch (TskCoreException ex) {
logger.log(Level.WARNING, "Unable to get aquisition details for selected data source", ex);
}
if (selectedDataSource instanceof Image) {
setFieldsForImage((Image) selectedDataSource);
}
}
updateFieldVisibility();
this.repaint();
}
/**
* Sets text fields for an image. This should be called after
* clearTableValues and before updateFieldVisibility to ensure the proper
* rendering.
*
* @param selectedImage The selected image.
*/
private void setFieldsForImage(Image selectedImage) {
imageTypeValue.setText(selectedImage.getType().getName());
sizeValue.setText(getSizeString(selectedImage.getSize()));
sectorSizeValue.setText(getSizeString(selectedImage.getSsize()));
for (String path : selectedImage.getPaths()) {
((DefaultTableModel) filePathsTable.getModel()).addRow(new Object[]{path});
}
try {
//older databases may have null as the hash values
String md5String = selectedImage.getMd5();
if (md5String == null) {
md5String = "";
}
md5HashValue.setText(md5String);
} catch (TskCoreException ex) {
logger.log(Level.WARNING, "Unable to get MD5 for selected data source", ex);
}
try {
String sha1String = selectedImage.getSha1();
if (sha1String == null) {
sha1String = "";
}
sha1HashValue.setText(sha1String);
} catch (TskCoreException ex) {
logger.log(Level.WARNING, "Unable to get SHA1 for selected data source", ex);
}
try {
String sha256String = selectedImage.getSha256();
if (sha256String == null) {
sha256String = "";
}
sha256HashValue.setText(sha256String);
} catch (TskCoreException ex) {
logger.log(Level.WARNING, "Unable to get SHA256 for selected data source", ex);
}
}
/**
* Get a long size in bytes as a string formated to be read by users.
*
@ -147,7 +175,7 @@ class DataSourceSummaryDetailsPanel extends javax.swing.JPanel {
"DataSourceSummaryDetailsPanel.units.terabytes= TB",
"DataSourceSummaryDetailsPanel.units.petabytes= PB"
})
private String getSizeString(Long size) {
private static String getSizeString(Long size) {
if (size == null) {
return "";
}

View File

@ -22,7 +22,7 @@
<Group type="102" alignment="1" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="1" attributes="0">
<Component id="dataSourceSummarySplitPane" pref="668" max="32767" attributes="0"/>
<Component id="dataSourceSummarySplitPane" pref="860" max="32767" attributes="0"/>
<Group type="102" attributes="0">
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
<Component id="closeButton" min="-2" max="-2" attributes="0"/>
@ -36,7 +36,7 @@
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="dataSourceSummarySplitPane" pref="362" max="32767" attributes="0"/>
<Component id="dataSourceSummarySplitPane" pref="540" max="32767" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="closeButton" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
@ -48,7 +48,7 @@
<Component class="javax.swing.JButton" name="closeButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/datasourcesummary/Bundle.properties" key="DataSourceSummaryDialog.closeButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryDialog.closeButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
@ -68,6 +68,11 @@
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
<SubComponents>
<Container class="javax.swing.JTabbedPane" name="dataSourceTabbedPane">
<AuxValues>
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="dataSourceSummaryTabbedPane"/>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
<JSplitPaneConstraints position="right"/>

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.casemodule.datasourcesummary;
package org.sleuthkit.autopsy.datasourcesummary.ui;
import java.awt.Frame;
import java.beans.PropertyChangeEvent;
@ -27,7 +27,7 @@ import java.util.Observer;
import java.util.Set;
import javax.swing.event.ListSelectionEvent;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.IngestJobInfoPanel;
import org.sleuthkit.autopsy.datasourcesummary.datamodel.CaseDataSourcesSummary;
import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.autopsy.ingest.events.DataSourceAnalysisCompletedEvent;
import org.sleuthkit.autopsy.ingest.events.DataSourceAnalysisCompletedEvent.Reason;
@ -41,10 +41,8 @@ final class DataSourceSummaryDialog extends javax.swing.JDialog implements Obser
private static final long serialVersionUID = 1L;
private static final Set<IngestManager.IngestJobEvent> INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.DATA_SOURCE_ANALYSIS_COMPLETED);
private final DataSourceSummaryCountsPanel countsPanel;
private final DataSourceSummaryDetailsPanel detailsPanel;
private final DataSourceBrowser dataSourcesPanel;
private final IngestJobInfoPanel ingestHistoryPanel;
private final DataSourceSummaryTabbedPane dataSourceSummaryTabbedPane;
/**
* Creates new form DataSourceSummaryDialog for displaying a summary of the
@ -52,30 +50,20 @@ final class DataSourceSummaryDialog extends javax.swing.JDialog implements Obser
* datasource.
*/
@Messages({
"DataSourceSummaryDialog.window.title=Data Sources Summary",
"DataSourceSummaryDialog.countsTab.title=Counts",
"DataSourceSummaryDialog.detailsTab.title=Details",
"DataSourceSummaryDialog.ingestHistoryTab.title=Ingest History"
"DataSourceSummaryDialog.window.title=Data Sources Summary"
})
DataSourceSummaryDialog(Frame owner) {
super(owner, Bundle.DataSourceSummaryDialog_window_title(), true);
Map<Long, String> usageMap = DataSourceInfoUtilities.getDataSourceTypes();
Map<Long, Long> fileCountsMap = DataSourceInfoUtilities.getCountsOfFiles();
countsPanel = new DataSourceSummaryCountsPanel(fileCountsMap);
detailsPanel = new DataSourceSummaryDetailsPanel(usageMap);
Map<Long, String> usageMap = CaseDataSourcesSummary.getDataSourceTypes();
Map<Long, Long> fileCountsMap = CaseDataSourcesSummary.getCountsOfFiles();
dataSourcesPanel = new DataSourceBrowser(usageMap, fileCountsMap);
ingestHistoryPanel = new IngestJobInfoPanel();
dataSourceSummaryTabbedPane = new DataSourceSummaryTabbedPane();
initComponents();
dataSourceSummarySplitPane.setLeftComponent(dataSourcesPanel);
dataSourceTabbedPane.addTab(Bundle.DataSourceSummaryDialog_detailsTab_title(), detailsPanel);
dataSourceTabbedPane.addTab(Bundle.DataSourceSummaryDialog_countsTab_title(), countsPanel);
dataSourceTabbedPane.addTab(Bundle.DataSourceSummaryDialog_ingestHistoryTab_title(), ingestHistoryPanel);
dataSourcesPanel.addListSelectionListener((ListSelectionEvent e) -> {
if (!e.getValueIsAdjusting()) {
DataSource selectedDataSource = dataSourcesPanel.getSelectedDataSource();
countsPanel.updateCountsTableData(selectedDataSource);
detailsPanel.updateDetailsPanelData(selectedDataSource);
ingestHistoryPanel.setDataSource(selectedDataSource);
dataSourceSummaryTabbedPane.setDataSource(selectedDataSource);
this.repaint();
}
});
@ -116,7 +104,7 @@ final class DataSourceSummaryDialog extends javax.swing.JDialog implements Obser
closeButton = new javax.swing.JButton();
dataSourceSummarySplitPane = new javax.swing.JSplitPane();
dataSourceTabbedPane = new javax.swing.JTabbedPane();
javax.swing.JTabbedPane dataSourceTabbedPane = dataSourceSummaryTabbedPane;
org.openide.awt.Mnemonics.setLocalizedText(closeButton, org.openide.util.NbBundle.getMessage(DataSourceSummaryDialog.class, "DataSourceSummaryDialog.closeButton.text")); // NOI18N
closeButton.addActionListener(new java.awt.event.ActionListener() {
@ -138,7 +126,7 @@ final class DataSourceSummaryDialog extends javax.swing.JDialog implements Obser
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(dataSourceSummarySplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 668, Short.MAX_VALUE)
.addComponent(dataSourceSummarySplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 860, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addGap(0, 0, Short.MAX_VALUE)
.addComponent(closeButton)))
@ -148,7 +136,7 @@ final class DataSourceSummaryDialog extends javax.swing.JDialog implements Obser
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(dataSourceSummarySplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 362, Short.MAX_VALUE)
.addComponent(dataSourceSummarySplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 540, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(closeButton)
.addContainerGap())
@ -173,6 +161,5 @@ final class DataSourceSummaryDialog extends javax.swing.JDialog implements Obser
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton closeButton;
private javax.swing.JSplitPane dataSourceSummarySplitPane;
private javax.swing.JTabbedPane dataSourceTabbedPane;
// End of variables declaration//GEN-END:variables
}

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.casemodule.datasourcesummary;
package org.sleuthkit.autopsy.datasourcesummary.ui;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
@ -30,6 +30,7 @@ import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.openide.nodes.Sheet;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.datasourcesummary.ui.Bundle;
import org.sleuthkit.autopsy.datamodel.NodeProperty;
import org.sleuthkit.autopsy.directorytree.ViewContextAction;
import org.sleuthkit.datamodel.DataSource;

View File

@ -0,0 +1,82 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2020 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.datasourcesummary.ui;
import javax.swing.JTabbedPane;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.IngestJobInfoPanel;
import org.sleuthkit.autopsy.datasourcesummary.ui.Bundle;
import org.sleuthkit.datamodel.DataSource;
/**
* A tabbed pane showing the summary of a data source including tabs of:
* DataSourceSummaryCountsPanel, DataSourceSummaryDetailsPanel, and
* IngestJobInfoPanel.
*/
@Messages({
"DataSourceSummaryTabbedPane_countsTab_title=Counts",
"DataSourceSummaryTabbedPane_detailsTab_title=Details",
"DataSourceSummaryTabbedPane_userActivityTab_title=User Activity",
"DataSourceSummaryTabbedPane_ingestHistoryTab_title=Ingest History"
})
public class DataSourceSummaryTabbedPane extends JTabbedPane {
private static final long serialVersionUID = 1L;
private final DataSourceSummaryCountsPanel countsPanel = new DataSourceSummaryCountsPanel();
private final DataSourceSummaryDetailsPanel detailsPanel = new DataSourceSummaryDetailsPanel();
private final DataSourceSummaryUserActivityPanel userActivityPanel = new DataSourceSummaryUserActivityPanel();
private final IngestJobInfoPanel ingestHistoryPanel = new IngestJobInfoPanel();
private DataSource dataSource = null;
/**
* Constructs a tabbed pane showing the summary of a data source.
*/
public DataSourceSummaryTabbedPane() {
addTab(Bundle.DataSourceSummaryTabbedPane_detailsTab_title(), detailsPanel);
addTab(Bundle.DataSourceSummaryTabbedPane_countsTab_title(), countsPanel);
addTab(Bundle.DataSourceSummaryTabbedPane_userActivityTab_title(), userActivityPanel);
addTab(Bundle.DataSourceSummaryTabbedPane_ingestHistoryTab_title(), ingestHistoryPanel);
}
/**
* The datasource currently used as the model in this panel.
*
* @return The datasource currently being used as the model in this panel.
*/
public DataSource getDataSource() {
return dataSource;
}
/**
* Sets datasource to visualize in the tabbed panel.
*
* @param dataSource The datasource to use in this panel.
*/
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
detailsPanel.setDataSource(dataSource);
countsPanel.setDataSource(dataSource);
userActivityPanel.setDataSource(dataSource);
ingestHistoryPanel.setDataSource(dataSource);
}
}

View File

@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="programsRunLabel" min="-2" pref="155" max="-2" attributes="0"/>
<Component id="topProgramsScrollPane" min="-2" pref="460" max="-2" attributes="0"/>
</Group>
<EmptySpace pref="128" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="programsRunLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="topProgramsScrollPane" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="programsRunLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="DataSourceSummaryUserActivityPanel.programsRunLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
</Component>
<Container class="javax.swing.JScrollPane" name="topProgramsScrollPane">
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[750, 187]"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTable" name="topProgramsTable">
</Component>
</SubComponents>
</Container>
</SubComponents>
</Form>

View File

@ -0,0 +1,293 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2020 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.datasourcesummary.ui;
import java.awt.Component;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataSourceTopProgramsSummary;
import org.sleuthkit.autopsy.datasourcesummary.datamodel.TopProgramsResult;
import org.sleuthkit.datamodel.DataSource;
/**
* A panel to display user activity.
*/
@Messages({
"DataSourceSummaryUserActivityPanel_tab_title=User Activity",
"DataSourceSummaryUserActivityPanel_TopProgramsTableModel_name_header=Program",
"DataSourceSummaryUserActivityPanel_TopProgramsTableModel_folder_header=Folder",
"DataSourceSummaryUserActivityPanel_TopProgramsTableModel_count_header=Run Times",
"DataSourceSummaryUserActivityPanel_TopProgramsTableModel_lastrun_header=Last Run"
})
public class DataSourceSummaryUserActivityPanel extends javax.swing.JPanel {
private static final long serialVersionUID = 1L;
private static final DateFormat DATETIME_FORMAT = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss", Locale.getDefault());
private static final int TOP_PROGS_COUNT = 10;
private static final DefaultTableCellRenderer RIGHT_ALIGNED_RENDERER = new DefaultTableCellRenderer();
static {
RIGHT_ALIGNED_RENDERER.setHorizontalAlignment(JLabel.RIGHT);
}
private DataSource dataSource;
/**
* Creates new form DataSourceUserActivityPanel
*/
public DataSourceSummaryUserActivityPanel() {
initComponents();
topProgramsTable.getTableHeader().setReorderingAllowed(false);
}
/**
* The datasource currently used as the model in this panel.
*
* @return The datasource currently being used as the model in this panel.
*/
public DataSource getDataSource() {
return dataSource;
}
/**
* Sets datasource to visualize in the panel.
*
* @param dataSource The datasource to use in this panel.
*/
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
if (dataSource == null || !Case.isCaseOpen()) {
updateTopPrograms(new TopProgramsModel(null));
} else {
updateTopPrograms(getTopProgramsModel(dataSource));
}
}
/**
* Updates the Top Programs Table in the gui.
*
* @param data The data in Object[][] form to be used by the
* DefaultTableModel.
*/
private void updateTopPrograms(TopProgramsModel model) {
topProgramsTable.setModel(model);
topProgramsTable.getColumnModel().getColumn(0).setPreferredWidth(250);
topProgramsTable.getColumnModel().getColumn(0).setCellRenderer(PATH_CELL_RENDERER);
topProgramsTable.getColumnModel().getColumn(1).setPreferredWidth(150);
topProgramsTable.getColumnModel().getColumn(2).setCellRenderer(RIGHT_ALIGNED_RENDERER);
topProgramsTable.getColumnModel().getColumn(2).setPreferredWidth(80);
topProgramsTable.getColumnModel().getColumn(3).setPreferredWidth(150);
topProgramsScrollPane.getVerticalScrollBar().setValue(0);
this.repaint();
}
/**
* The counts of top programs run.
*
* @param selectedDataSource The DataSource.
*
* @return The JTable data model of counts of program runs.
*/
private static TopProgramsModel getTopProgramsModel(DataSource selectedDataSource) {
List<TopProgramsResult> topProgramList
= DataSourceTopProgramsSummary.getTopPrograms(selectedDataSource, TOP_PROGS_COUNT);
if (topProgramList == null) {
return new TopProgramsModel(null);
} else {
return new TopProgramsModel(topProgramList);
}
}
/**
* A POJO defining the values present in the name cell. Defines the name as
* well as the path for the tooltip.
*/
private static class ProgramNameCellValue {
private final String programName;
private final String programPath;
ProgramNameCellValue(String programName, String programPath) {
this.programName = programName;
this.programPath = programPath;
}
@Override
public String toString() {
// override so that the value in the cell reads as programName
return programName;
}
/**
* @return The program name.
*/
String getProgramName() {
return programName;
}
/**
* @return The path of the program.
*/
String getProgramPath() {
return programPath;
}
}
/**
* Defines a cell renderer for the first cell rendering the name as the text
* and path as the tooltip.
*/
private static TableCellRenderer PATH_CELL_RENDERER = new DefaultTableCellRenderer() {
public Component getTableCellRendererComponent(
JTable table, Object value,
boolean isSelected, boolean hasFocus,
int row, int column) {
JLabel c = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if (value instanceof ProgramNameCellValue) {
ProgramNameCellValue cellValue = (ProgramNameCellValue) value;
c.setToolTipText(cellValue.getProgramPath());
}
return c;
}
};
/**
* Defines the table model for a JTable of the programs. Accepts a list of
* TopProgramsResult objects as rows data source.
*/
private static class TopProgramsModel extends AbstractTableModel {
private static final long serialVersionUID = 1L;
// column headers for artifact counts table
private static final String[] TOP_PROGS_COLUMN_HEADERS = new String[]{
Bundle.DataSourceSummaryUserActivityPanel_TopProgramsTableModel_name_header(),
Bundle.DataSourceSummaryUserActivityPanel_TopProgramsTableModel_folder_header(),
Bundle.DataSourceSummaryUserActivityPanel_TopProgramsTableModel_count_header(),
Bundle.DataSourceSummaryUserActivityPanel_TopProgramsTableModel_lastrun_header()
};
private final List<TopProgramsResult> programResults;
/**
* Main constructor.
*
* @param programResults The results to display.
*/
TopProgramsModel(List<TopProgramsResult> programResults) {
this.programResults = programResults == null ? new ArrayList<>() : Collections.unmodifiableList(programResults);
}
@Override
public String getColumnName(int column) {
return column < 0 || column >= TOP_PROGS_COLUMN_HEADERS.length ? null : TOP_PROGS_COLUMN_HEADERS[column];
}
@Override
public int getRowCount() {
return programResults.size();
}
@Override
public int getColumnCount() {
return TOP_PROGS_COLUMN_HEADERS.length;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
if (rowIndex < 0 || rowIndex >= programResults.size()) {
return null;
}
TopProgramsResult result = programResults.get(rowIndex);
switch (columnIndex) {
case 0:
return new ProgramNameCellValue(result.getProgramName(), result.getProgramPath());
case 1:
return DataSourceTopProgramsSummary.getShortFolderName(result.getProgramPath(), result.getProgramName());
case 2:
return result.getRunTimes();
case 3:
return result.getLastRun() == null ? null : DATETIME_FORMAT.format(result.getLastRun());
default:
return null;
}
}
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
javax.swing.JLabel programsRunLabel = new javax.swing.JLabel();
topProgramsScrollPane = new javax.swing.JScrollPane();
topProgramsTable = new javax.swing.JTable();
org.openide.awt.Mnemonics.setLocalizedText(programsRunLabel, org.openide.util.NbBundle.getMessage(DataSourceSummaryUserActivityPanel.class, "DataSourceSummaryUserActivityPanel.programsRunLabel.text")); // NOI18N
topProgramsScrollPane.setPreferredSize(new java.awt.Dimension(750, 187));
topProgramsScrollPane.setViewportView(topProgramsTable);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(programsRunLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 155, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(topProgramsScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 460, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap(128, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(programsRunLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(topProgramsScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JScrollPane topProgramsScrollPane;
private javax.swing.JTable topProgramsTable;
// End of variables declaration//GEN-END:variables
}

View File

@ -0,0 +1,190 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2020 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.datasourcesummary.ui;
import java.awt.BorderLayout;
import java.awt.Font;
import javax.swing.JPanel;
import org.sleuthkit.datamodel.DataSource;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.labels.PieSectionLabelGenerator;
import org.jfree.chart.labels.StandardPieSectionLabelGenerator;
import org.jfree.chart.plot.PiePlot;
import org.jfree.data.general.DefaultPieDataset;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;
import javax.swing.JLabel;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.coreutils.FileTypeUtils;
import org.sleuthkit.autopsy.datasourcesummary.datamodel.DataSourceMimeTypeSummary;
import static org.sleuthkit.autopsy.coreutils.FileTypeUtils.FileTypeCategory;
/**
* A Pie Chart that shows file mime types in a data source.
*/
class FileTypePieChart extends JPanel {
private static final long serialVersionUID = 1L;
private static final Font DEFAULT_FONT = new JLabel().getFont();
private static final Font DEFAULT_HEADER_FONT = new Font(DEFAULT_FONT.getName(), DEFAULT_FONT.getStyle(), (int) (DEFAULT_FONT.getSize() * 1.5));
private final DefaultPieDataset dataset = new DefaultPieDataset();
private DataSource dataSource;
// used for determining mime types that fall in the 'other' category
private static final Set<String> ALL_CATEGORY_MIME_TYPES = Arrays.asList(
FileTypeCategory.IMAGE,
FileTypeCategory.VIDEO,
FileTypeCategory.AUDIO,
FileTypeCategory.DOCUMENTS,
FileTypeCategory.EXECUTABLE)
.stream()
.flatMap((cat) -> cat.getMediaTypes().stream())
.collect(Collectors.toSet());
/**
* Default constructor for the pie chart.
*/
@Messages({
"DataSourceSummaryCountsPanel.byMimeTypeLabel.text=Files by MIME Type",
"DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.audio.row=Audio",
"DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.documents.row=Documents",
"DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.executables.row=Executables",
"DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.images.row=Images",
"DataSourceSummaryCountsPanel.FilesByMimeTypeTableModel.videos.row=Videos",
"DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_other_label=Other",
"DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_notAnalyzed_label=Not Analyzed"
})
FileTypePieChart() {
// Create chart
JFreeChart chart = ChartFactory.createPieChart(
Bundle.DataSourceSummaryCountsPanel_byMimeTypeLabel_text(),
dataset,
true,
true,
false);
chart.setBackgroundPaint(null);
chart.getLegend().setItemFont(DEFAULT_FONT);
chart.getTitle().setFont(DEFAULT_HEADER_FONT);
PiePlot plot = ((PiePlot) chart.getPlot());
//Format Label
PieSectionLabelGenerator labelGenerator = new StandardPieSectionLabelGenerator(
"{0}: {1} ({2})", new DecimalFormat("0"), new DecimalFormat("0.0%"));
plot.setLabelGenerator(labelGenerator);
plot.setLabelFont(DEFAULT_FONT);
plot.setBackgroundPaint(null);
plot.setOutlinePaint(null);
// Create Panel
ChartPanel panel = new ChartPanel(chart);
this.setLayout(new BorderLayout());
this.add(panel, BorderLayout.CENTER);
}
/**
* The datasource currently used as the model with this pie chart.
*
* @return The datasource currently being used as the model in this pie
* chart.
*/
DataSource getDataSource() {
return dataSource;
}
/**
* Sets datasource to visualize in the pie chart.
*
* @param dataSource The datasource to use in this pie chart.
*/
void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
this.dataset.clear();
if (dataSource != null) {
addIfPresent(Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_images_row(),
this.dataSource, FileTypeCategory.IMAGE);
addIfPresent(Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_videos_row(),
this.dataSource, FileTypeCategory.VIDEO);
addIfPresent(Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_audio_row(),
this.dataSource, FileTypeCategory.AUDIO);
addIfPresent(Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_documents_row(),
this.dataSource, FileTypeCategory.DOCUMENTS);
addIfPresent(Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_executables_row(),
this.dataSource, FileTypeCategory.EXECUTABLE);
addIfPresent(Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_other_label(),
DataSourceMimeTypeSummary.getCountOfFilesNotInMimeTypes(this.dataSource, ALL_CATEGORY_MIME_TYPES));
addIfPresent(Bundle.DataSourceSummaryCountsPanel_FilesByMimeTypeTableModel_notAnalyzed_label(),
DataSourceMimeTypeSummary.getCountOfFilesWithNoMimeType(this.dataSource));
}
}
/**
* Adds count for file type category if there is a value. Uses fields
* 'dataSource' and 'dataset'.
*
* @param label The label for this pie slice.
* @param dataSource The data source.
* @param category The category for the pie slice.
*/
private void addIfPresent(String label, DataSource dataSource, FileTypeUtils.FileTypeCategory category) {
if (dataSource == null) {
return;
}
Long count = getCount(dataSource, category);
addIfPresent(label, count);
}
/**
* Adds count for a a label if the count is non-null and greater than 0.
*
* @param label The label.
* @param count The count.
*/
private void addIfPresent(String label, Long count) {
if (count != null && count > 0) {
this.dataset.setValue(label, count);
}
}
/**
* Retrieves the counts of files of a particular mime type for a particular
* DataSource.
*
* @param dataSource The DataSource.
* @param category The mime type category.
*
* @return The count.
*/
private static Long getCount(DataSource dataSource, FileTypeUtils.FileTypeCategory category) {
return DataSourceMimeTypeSummary.getCountOfFilesForMimeTypes(dataSource, category.getMediaTypes());
}
}

View File

@ -0,0 +1,37 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2020 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.datasourcesummary.ui;
import javax.swing.table.DefaultTableModel;
/**
* A Table model where cells are not editable.
*/
class NonEditableTableModel extends DefaultTableModel {
private static final long serialVersionUID = 1L;
NonEditableTableModel(Object[][] data, Object[] columnNames) {
super(data, columnNames);
}
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
}

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.casemodule.datasourcesummary;
package org.sleuthkit.autopsy.datasourcesummary.ui;
import java.awt.Component;
import java.lang.reflect.InvocationTargetException;

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.casemodule.datasourcesummary;
package org.sleuthkit.autopsy.datasourcesummary.ui;
import java.awt.Frame;
import java.awt.event.ActionEvent;
@ -24,6 +24,7 @@ import javax.swing.AbstractAction;
import javax.swing.SwingUtilities;
import org.openide.util.NbBundle.Messages;
import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.datasourcesummary.ui.Bundle;
/**
* ViewSummaryInformationAction action for opening a Data Sources Summary Dialog

View File

@ -19,9 +19,9 @@
package org.sleuthkit.autopsy.discovery;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.modules.exif.ExifParserModuleFactory;
import org.sleuthkit.autopsy.modules.filetypeid.FileTypeIdModuleFactory;
import org.sleuthkit.autopsy.modules.hashdatabase.HashLookupModuleFactory;
import org.sleuthkit.autopsy.modules.pictureanalyzer.PictureAnalyzerIngestModuleFactory;
import org.sleuthkit.datamodel.IngestJobInfo;
import org.sleuthkit.datamodel.IngestModuleInfo;
@ -118,7 +118,7 @@ class DataSourceModulesWrapper {
* data source.
*/
private void updateExifStatus(IngestModuleInfo moduleInfo) {
if (!exifModuleRun && moduleInfo.getDisplayName().equals(ExifParserModuleFactory.getModuleName())) {
if (!exifModuleRun && moduleInfo.getDisplayName().equals(PictureAnalyzerIngestModuleFactory.getModuleName())) {
exifModuleRun = true;
}
}

View File

@ -0,0 +1,192 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2020 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.guiutils;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import java.beans.PropertyChangeListener;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.ingest.IngestManager;
import static org.sleuthkit.autopsy.ingest.IngestManager.IngestModuleEvent.DATA_ADDED;
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
import org.sleuthkit.datamodel.Account;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME;
import org.sleuthkit.datamodel.TskCoreException;
/**
* A singleton cache of the Contact artifacts for accounts. The map of account
* unique ids to list of contact artifacts is stored in a LoadingCache which
* expires after 10 of non-use.
*
*/
public final class ContactCache {
private static final Logger logger = Logger.getLogger(ContactCache.class.getName());
private static ContactCache instance;
private final LoadingCache<String, Map<String, List<BlackboardArtifact>>> accountMap;
/**
* Returns the list of Contacts for the given Account.
*
* @param account Account instance.
*
* @return List of TSK_CONTACT artifacts that references the given Account.
* An empty list is returned if no contacts are found.
*
* @throws ExecutionException
*/
public static synchronized List<BlackboardArtifact> getContacts(Account account) throws ExecutionException {
return getInstance().accountMap.get("realMap").get(account.getTypeSpecificID());
}
/**
* Returns a list of Contact TSK_NAME values for the given account type
* specific id.
*
* @param accountTypeSpecificID Account type specific id
*
* @return List of contact string names or empty list if none were found.
*
* @throws TskCoreException
*/
public static synchronized List<String> getContactNameList(String accountTypeSpecificID) throws TskCoreException {
List<BlackboardArtifact> contactList;
try {
contactList = getInstance().accountMap.get("realMap").get(accountTypeSpecificID);
} catch (ExecutionException ex) {
throw new TskCoreException("Unable to get contact list from cache", ex);
}
List<String> contactNameList = new ArrayList<>();
if (contactList != null) {
for (BlackboardArtifact artifact : contactList) {
BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.fromID(TSK_NAME.getTypeID())));
if (attribute != null && !contactNameList.contains(attribute.getValueString())) {
contactNameList.add(attribute.getValueString());
}
}
}
return contactNameList;
}
/**
* Force the cache to invalidate all entries.
*/
static synchronized void invalidateCache() {
getInstance().accountMap.invalidateAll();
}
/**
* Construct a new instance.
*/
private ContactCache() {
accountMap = CacheBuilder.newBuilder().expireAfterAccess(10, TimeUnit.MINUTES).build(
new CacheLoader<String, Map<String, List<BlackboardArtifact>>>() {
@Override
public Map<String, List<BlackboardArtifact>> load(String key) {
try {
return buildMap();
} catch (SQLException | TskCoreException ex) {
logger.log(Level.WARNING, "Failed to build account to contact map", ex);
}
return new HashMap<>(); // Return an empty map if there is an exception to avoid NPE and continual trying.
}
});
PropertyChangeListener ingestListener = pce -> {
String eventType = pce.getPropertyName();
if (eventType.equals(DATA_ADDED.toString())) {
ModuleDataEvent eventData = (ModuleDataEvent) pce.getOldValue();
if (eventData.getBlackboardArtifactType().getTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT.getTypeID()) {
invalidateCache();
}
}
};
IngestManager.getInstance().addIngestModuleEventListener(EnumSet.of(DATA_ADDED), ingestListener);
}
/**
* Returns the singleton instance of the cache object.
*
* @return AccountCache instance.
*/
private static synchronized ContactCache getInstance() {
if (instance == null) {
instance = new ContactCache();
}
return instance;
}
/**
* Builds the map of account IDs to contacts that reference them.
*
* @return A map of account IDs to contact artifacts.
*
* @throws TskCoreException
* @throws SQLException
*/
private Map<String, List<BlackboardArtifact>> buildMap() throws TskCoreException, SQLException {
Map<String, List<BlackboardArtifact>> acctMap = new HashMap<>();
List<BlackboardArtifact> contactList = Case.getCurrentCase().getSleuthkitCase().getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT);
for (BlackboardArtifact contactArtifact : contactList) {
List<BlackboardAttribute> contactAttributes = contactArtifact.getAttributes();
for (BlackboardAttribute attribute : contactAttributes) {
String typeName = attribute.getAttributeType().getTypeName();
if (typeName.startsWith("TSK_EMAIL")
|| typeName.startsWith("TSK_PHONE")
|| typeName.startsWith("TSK_NAME")
|| typeName.startsWith("TSK_ID")) {
String accountID = attribute.getValueString();
List<BlackboardArtifact> artifactList = acctMap.get(accountID);
if (artifactList == null) {
artifactList = new ArrayList<>();
acctMap.put(accountID, artifactList);
}
if (!artifactList.contains(contactArtifact)) {
artifactList.add(contactArtifact);
}
}
}
}
return acctMap;
}
}

View File

@ -474,6 +474,9 @@ public final class IngestJobSettings {
case "Correlation Engine": //NON-NLS
moduleNames.add("Central Repository"); //NON-NLS
break;
case "Exif Parser": //NON-NLS
moduleNames.add("Picture Analyzer"); //NON-NLS
break;
default:
moduleNames.add(name);
}

View File

@ -31,7 +31,6 @@ import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.examples.SampleIngestModuleFactory;
import org.sleuthkit.autopsy.modules.dataSourceIntegrity.DataSourceIntegrityModuleFactory;
import org.sleuthkit.autopsy.modules.exif.ExifParserModuleFactory;
import org.sleuthkit.autopsy.modules.fileextmismatch.FileExtMismatchDetectorModuleFactory;
import org.sleuthkit.autopsy.modules.filetypeid.FileTypeIdModuleFactory;
import org.sleuthkit.autopsy.modules.hashdatabase.HashLookupModuleFactory;
@ -40,6 +39,7 @@ import org.sleuthkit.autopsy.modules.photoreccarver.PhotoRecCarverIngestModuleFa
import org.sleuthkit.autopsy.modules.embeddedfileextractor.EmbeddedFileExtractorModuleFactory;
import org.sleuthkit.autopsy.modules.encryptiondetection.EncryptionDetectionModuleFactory;
import org.sleuthkit.autopsy.centralrepository.ingestmodule.CentralRepoIngestModuleFactory;
import org.sleuthkit.autopsy.modules.pictureanalyzer.PictureAnalyzerIngestModuleFactory;
import org.sleuthkit.autopsy.modules.vmextractor.VMExtractorIngestModuleFactory;
import org.sleuthkit.autopsy.python.JythonModuleLoader;
@ -60,7 +60,7 @@ final class IngestModuleFactoryLoader {
add(FileTypeIdModuleFactory.class.getCanonicalName());
add(FileExtMismatchDetectorModuleFactory.class.getCanonicalName());
add(EmbeddedFileExtractorModuleFactory.class.getCanonicalName());
add(ExifParserModuleFactory.class.getCanonicalName());
add(PictureAnalyzerIngestModuleFactory.class.getCanonicalName());
add("org.sleuthkit.autopsy.keywordsearch.KeywordSearchModuleFactory"); //NON-NLS
add("org.sleuthkit.autopsy.thunderbirdparser.EmailParserModuleFactory"); //NON-NLS
add(EncryptionDetectionModuleFactory.class.getCanonicalName());

View File

@ -0,0 +1,4 @@
# {0} - path
UserMachinePreferences_validateTempDirectory_errorOnCreate_text=There was an error creating the temp directory for path: {0}
# {0} - path
UserMachinePreferences_validateTempDirectory_errorOnReadWrite_text=There was an error reading or writing to temp directory path: {0}

View File

@ -0,0 +1,108 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2020 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.machinesettings;
import java.io.File;
import java.nio.file.Paths;
import java.util.prefs.Preferences;
import org.apache.commons.lang3.StringUtils;
import org.openide.util.NbBundle;
import org.openide.util.NbPreferences;
import org.sleuthkit.autopsy.coreutils.FileUtil;
/**
* Provides case-specific settings like the user-specified temp folder.
*/
public final class UserMachinePreferences {
private static final Preferences preferences = NbPreferences.forModule(UserMachinePreferences.class);
private static final String TEMP_DIR_KEY = "TempDirectory";
/**
* Retrieves a default temporary directory that is a subdirectory of
* java.io.tmpdir.
*
* @return The absolute path to the temp directory.
*/
private static String getDefaultTempDirectory() {
return Paths.get(System.getProperty("java.io.tmpdir")).toAbsolutePath().toString();
}
/**
* Retrieves the base user-specified temporary directory.
*
* @return The base user-specified temporary directory.
*/
public static String getBaseTempDirectory() {
String tempDir = preferences.get(TEMP_DIR_KEY, null);
return StringUtils.isBlank(tempDir) ? getDefaultTempDirectory() : tempDir;
}
/**
* Checks to see if temporary directory location can be created and is
* read/write.
*
* @param path The location.
*
* @return True if this is a valid location for a temp directory.
*
* @throws UserMachinePreferencesException If path could not be validated
* due to mkdirs failure or the
* directory is not read/write.
*/
@NbBundle.Messages({
"# {0} - path",
"UserMachinePreferences_validateTempDirectory_errorOnCreate_text=There was an error creating the temp directory for path: {0}",
"# {0} - path",
"UserMachinePreferences_validateTempDirectory_errorOnReadWrite_text=There was an error reading or writing to temp directory path: {0}"
})
private static boolean validateTempDirectory(String path) throws UserMachinePreferencesException {
if (StringUtils.isBlank(path)) {
// in this instance, the default path will be used.
return true;
}
File f = new File(path);
if (!f.exists() && !f.mkdirs()) {
throw new UserMachinePreferencesException(Bundle.UserMachinePreferences_validateTempDirectory_errorOnCreate_text(path));
}
if (!FileUtil.hasReadWriteAccess(Paths.get(path))) {
throw new UserMachinePreferencesException(Bundle.UserMachinePreferences_validateTempDirectory_errorOnReadWrite_text(path));
}
return true;
}
/**
* Sets the base user-specified temporary directory.
*
* @param path The path to the directory.
*
* @throws UserMachinePreferencesException If the directory cannot be
* accessed or created.
*/
public static void setBaseTempDirectory(String path) throws UserMachinePreferencesException {
validateTempDirectory(path);
preferences.put(TEMP_DIR_KEY, path);
}
private UserMachinePreferences() {
}
}

View File

@ -0,0 +1,45 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2020 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.machinesettings;
/**
* Exception class for UserMachinePreferences.
*/
public class UserMachinePreferencesException extends Exception {
private static final long serialVersionUID = 1L;
/**
* Main constructor.
*
* @param string The message for the exception.
*/
UserMachinePreferencesException(String string) {
super(string);
}
/**
* Main constructor.
*
* @param string The message for the exception.
* @param thrwbl The inner exception.
*/
UserMachinePreferencesException(String string, Throwable thrwbl) {
super(string, thrwbl);
}
}

View File

@ -1,8 +0,0 @@
OpenIDE-Module-Display-Category=Ingest Module
OpenIDE-Module-Long-Description=\
Exif metadata ingest module. \n\n\
The ingest module analyzes image files, extracts Exif information and posts the Exif data as results.
OpenIDE-Module-Name=ExifParser
OpenIDE-Module-Short-Description=Exif metadata ingest module
ExifParserFileIngestModule.moduleName.text=Exif Parser
ExifParserFileIngestModule.getDesc.text=Ingests JPEG files and retrieves their EXIF metadata.

View File

@ -1,11 +0,0 @@
CannotRunFileTypeDetection=Cannot run file type detection.
ExifParserFileIngestModule.indexError.message=Failed to post EXIF Metadata artifact(s).
ExifParserFileIngestModule.userContent.description=EXIF metadata exists for this file.
OpenIDE-Module-Display-Category=Ingest Module
OpenIDE-Module-Long-Description=\
Exif metadata ingest module. \n\n\
The ingest module analyzes image files, extracts Exif information and posts the Exif data as results.
OpenIDE-Module-Name=ExifParser
OpenIDE-Module-Short-Description=Exif metadata ingest module
ExifParserFileIngestModule.moduleName.text=Exif Parser
ExifParserFileIngestModule.getDesc.text=Ingests JPEG files and retrieves their EXIF metadata.

View File

@ -1,10 +0,0 @@
CannotRunFileTypeDetection=\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7\u306e\u691c\u51fa\u3092\u5b9f\u884c\u3067\u304d\u307e\u305b\u3093\u3002
ExifParserFileIngestModule.indexError.message=\u30ad\u30fc\u30ef\u30fc\u30c9\u3092\u691c\u7d22\u3059\u308b\u305f\u3081\u306e\u3001EXIF\u30e1\u30bf\u30c7\u30fc\u30bf\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u3092\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002
OpenIDE-Module-Display-Category=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb
OpenIDE-Module-Long-Description=\
EXIF\u30e1\u30bf\u30c7\u30fc\u30bf\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u3067\u3059\u3002 \n\n\
\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u30a4\u30e1\u30fc\u30b8\u30d5\u30a1\u30a4\u30eb\u3092\u89e3\u6790\u3057\u3001Exif\u60c5\u5831\u3092\u62bd\u51fa\u3057\u3001Exif\u30c7\u30fc\u30bf\u3092\u7d50\u679c\u3068\u3057\u3066\u6295\u7a3f\u3057\u307e\u3059\u3002
OpenIDE-Module-Name=ExifParser
OpenIDE-Module-Short-Description=Exif\u30e1\u30bf\u30c7\u30fc\u30bf\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u3067\u3059\u3002
ExifParserFileIngestModule.moduleName.text=Exif\u89e3\u6790\u30c4\u30fc\u30eb
ExifParserFileIngestModule.getDesc.text=Ingests JPEG\u30d5\u30a1\u30a4\u30eb\u3092\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u3057\u3001EXIF\u30e1\u30bf\u30c7\u30fc\u30bf\u3092\u56de\u53ce\u3057\u307e\u3059\u3002

View File

@ -1,249 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2018 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.modules.exif;
import com.drew.imaging.ImageMetadataReader;
import com.drew.imaging.ImageProcessingException;
import com.drew.lang.GeoLocation;
import com.drew.lang.Rational;
import com.drew.metadata.Metadata;
import com.drew.metadata.exif.ExifIFD0Directory;
import com.drew.metadata.exif.ExifSubIFDDirectory;
import com.drew.metadata.exif.GpsDirectory;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.TimeZone;
import java.util.logging.Level;
import org.apache.commons.lang3.StringUtils;
import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.ingest.FileIngestModule;
import org.sleuthkit.autopsy.ingest.IngestJobContext;
import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter;
import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Blackboard;
import org.sleuthkit.datamodel.BlackboardArtifact;
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_METADATA_EXIF;
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_USER_CONTENT_SUSPECTED;
import org.sleuthkit.datamodel.BlackboardAttribute;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DEVICE_MAKE;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DEVICE_MODEL;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.Image;
import org.sleuthkit.datamodel.ReadContentInputStream;
import org.sleuthkit.datamodel.ReadContentInputStream.ReadContentInputStreamException;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskData;
import org.sleuthkit.datamodel.TskData.TSK_DB_FILES_TYPE_ENUM;
/**
* Ingest module to parse image Exif metadata. Currently only supports JPEG
* files. Ingests an image file and, if available, adds it's date, latitude,
* longitude, altitude, device model, and device make to a blackboard artifact.
*/
@NbBundle.Messages({"CannotRunFileTypeDetection=Cannot run file type detection."})
public final class ExifParserFileIngestModule implements FileIngestModule {
private static final Logger logger = Logger.getLogger(ExifParserFileIngestModule.class.getName());
private static final String MODULE_NAME = ExifParserModuleFactory.getModuleName();
private long jobId;
private static final IngestModuleReferenceCounter refCounter = new IngestModuleReferenceCounter();
private FileTypeDetector fileTypeDetector;
private final HashSet<String> supportedMimeTypes = new HashSet<>();
private TimeZone timeZone = null;
private Blackboard blackboard;
ExifParserFileIngestModule() {
supportedMimeTypes.add("audio/x-wav"); //NON-NLS
supportedMimeTypes.add("image/jpeg"); //NON-NLS
supportedMimeTypes.add("image/tiff"); //NON-NLS
}
@Override
public void startUp(IngestJobContext context) throws IngestModuleException {
jobId = context.getJobId();
refCounter.incrementAndGet(jobId);
try {
fileTypeDetector = new FileTypeDetector();
} catch (FileTypeDetector.FileTypeDetectorInitException ex) {
throw new IngestModuleException(Bundle.CannotRunFileTypeDetection(), ex);
}
}
@Messages({"ExifParserFileIngestModule.indexError.message=Failed to post EXIF Metadata artifact(s)."})
@Override
public ProcessResult process(AbstractFile content) {
try {
blackboard = Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboard();
} catch (NoCurrentCaseException ex) {
logger.log(Level.INFO, "Exception while getting open case.", ex); //NON-NLS
return ProcessResult.ERROR;
}
//skip unalloc
if ((content.getType().equals(TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS)
|| (content.getType().equals(TSK_DB_FILES_TYPE_ENUM.SLACK)))) {
return ProcessResult.OK;
}
if (content.isFile() == false) {
return ProcessResult.OK;
}
// skip known
if (content.getKnown().equals(TskData.FileKnown.KNOWN)) {
return ProcessResult.OK;
}
//skip unsupported
if (!parsableFormat(content)) {
return ProcessResult.OK;
}
return processFile(content);
}
@Messages({"ExifParserFileIngestModule.userContent.description=EXIF metadata exists for this file."})
private ProcessResult processFile(AbstractFile file) {
try (BufferedInputStream bin = new BufferedInputStream(new ReadContentInputStream(file));) {
Collection<BlackboardAttribute> attributes = new ArrayList<>();
Metadata metadata = ImageMetadataReader.readMetadata(bin);
// Date
ExifSubIFDDirectory exifDir = metadata.getFirstDirectoryOfType(ExifSubIFDDirectory.class);
if (exifDir != null) {
// set the timeZone for the current datasource.
if (timeZone == null) {
try {
Content dataSource = file.getDataSource();
if ((dataSource != null) && (dataSource instanceof Image)) {
Image image = (Image) dataSource;
timeZone = TimeZone.getTimeZone(image.getTimeZone());
}
} catch (TskCoreException ex) {
logger.log(Level.INFO, "Error getting time zones", ex); //NON-NLS
}
}
Date date = exifDir.getDate(ExifSubIFDDirectory.TAG_DATETIME_ORIGINAL, timeZone);
if (date != null) {
attributes.add(new BlackboardAttribute(TSK_DATETIME_CREATED, MODULE_NAME, date.getTime() / 1000));
}
}
// GPS Stuff
GpsDirectory gpsDir = metadata.getFirstDirectoryOfType(GpsDirectory.class);
if (gpsDir != null) {
GeoLocation loc = gpsDir.getGeoLocation();
if (loc != null) {
attributes.add(new BlackboardAttribute(TSK_GEO_LATITUDE, MODULE_NAME, loc.getLatitude()));
attributes.add(new BlackboardAttribute(TSK_GEO_LONGITUDE, MODULE_NAME, loc.getLongitude()));
}
Rational altitude = gpsDir.getRational(GpsDirectory.TAG_ALTITUDE);
if (altitude != null) {
attributes.add(new BlackboardAttribute(TSK_GEO_ALTITUDE, MODULE_NAME, altitude.doubleValue()));
}
}
// Device info
ExifIFD0Directory devDir = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
if (devDir != null) {
String model = devDir.getString(ExifIFD0Directory.TAG_MODEL);
if (StringUtils.isNotBlank(model)) {
attributes.add(new BlackboardAttribute(TSK_DEVICE_MODEL, MODULE_NAME, model));
}
String make = devDir.getString(ExifIFD0Directory.TAG_MAKE);
if (StringUtils.isNotBlank(make)) {
attributes.add(new BlackboardAttribute(TSK_DEVICE_MAKE, MODULE_NAME, make));
}
}
// Add the attributes, if there are any, to a new artifact
if (!attributes.isEmpty()) {
// Create artifact if it doesn't already exist.
if (!blackboard.artifactExists(file, TSK_METADATA_EXIF, attributes)) {
BlackboardArtifact bba = file.newArtifact(TSK_METADATA_EXIF);
BlackboardArtifact bba2 = file.newArtifact(TSK_USER_CONTENT_SUSPECTED);
bba.addAttributes(attributes);
bba2.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT, MODULE_NAME, Bundle.ExifParserFileIngestModule_userContent_description()));
try {
// index the artifact for keyword search
blackboard.postArtifact(bba, MODULE_NAME);
blackboard.postArtifact(bba2, MODULE_NAME);
} catch (Blackboard.BlackboardException ex) {
logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bba.getArtifactID(), ex); //NON-NLS
MessageNotifyUtil.Notify.error(
Bundle.ExifParserFileIngestModule_indexError_message(), bba.getDisplayName());
}
}
}
return ProcessResult.OK;
} catch (TskCoreException ex) {
logger.log(Level.WARNING, "Failed to create blackboard artifact for exif metadata ({0}).", ex.getLocalizedMessage()); //NON-NLS
return ProcessResult.ERROR;
} catch (ImageProcessingException ex) {
logger.log(Level.WARNING, String.format("Failed to process the image file '%s/%s' (id=%d).", file.getParentPath(), file.getName(), file.getId()), ex);
return ProcessResult.ERROR;
} catch (ReadContentInputStreamException ex) {
logger.log(Level.WARNING, String.format("Error while trying to read image file '%s/%s' (id=%d).", file.getParentPath(), file.getName(), file.getId()), ex); //NON-NLS
return ProcessResult.ERROR;
} catch (IOException ex) {
logger.log(Level.WARNING, String.format("IOException when parsing image file '%s/%s' (id=%d).", file.getParentPath(), file.getName(), file.getId()), ex); //NON-NLS
return ProcessResult.ERROR;
}
}
/**
* Checks if should try to attempt to extract exif. Currently checks if
* JPEG, TIFF or X-WAV (by signature)
*
* @param f file to be checked
*
* @return true if to be processed
*/
private boolean parsableFormat(AbstractFile f) {
String mimeType = fileTypeDetector.getMIMEType(f);
return supportedMimeTypes.contains(mimeType);
}
@Override
public void shutDown() {
// We only need to check for this final event on the last module per job
if (refCounter.decrementAndGet(jobId) == 0) {
timeZone = null;
}
}
}

View File

@ -1,3 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" "http://www.netbeans.org/dtds/filesystem-1_2.dtd">
<filesystem />

View File

@ -72,7 +72,10 @@ public final class HashDatabaseOptionsPanelController extends OptionsPanelContro
*/
@Override
public void cancel() {
getPanel().cancel();
if(changed) {
getPanel().cancel();
changed = false;
}
}
@Override

View File

@ -326,17 +326,19 @@ public class HashDbManager implements PropertyChangeListener {
}
// Add the hash database to the collection
hashSets.add(db);
// Let any external listeners know that there's a new set
try {
changeSupport.firePropertyChange(SetEvt.DB_ADDED.toString(), null, hashSetName);
} catch (Exception e) {
logger.log(Level.SEVERE, "HashDbManager listener threw exception", e); //NON-NLS
MessageNotifyUtil.Notify.show(
NbBundle.getMessage(this.getClass(), "HashDbManager.moduleErr"),
NbBundle.getMessage(this.getClass(), "HashDbManager.moduleErrorListeningToUpdatesMsg"),
MessageNotifyUtil.MessageType.ERROR);
if(!hashSets.contains(db)) {
hashSets.add(db);
// Let any external listeners know that there's a new set
try {
changeSupport.firePropertyChange(SetEvt.DB_ADDED.toString(), null, hashSetName);
} catch (Exception e) {
logger.log(Level.SEVERE, "HashDbManager listener threw exception", e); //NON-NLS
MessageNotifyUtil.Notify.show(
NbBundle.getMessage(this.getClass(), "HashDbManager.moduleErr"),
NbBundle.getMessage(this.getClass(), "HashDbManager.moduleErrorListeningToUpdatesMsg"),
MessageNotifyUtil.MessageType.ERROR);
}
}
return db;

View File

@ -18,14 +18,17 @@
*/
package org.sleuthkit.autopsy.modules.hashdatabase;
import java.awt.Component;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableColumn;
import org.apache.commons.lang.StringUtils;
import org.sleuthkit.autopsy.coreutils.Logger;
@ -78,6 +81,7 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe
if (i == 0) {
column.setPreferredWidth(((int) (width1 * 0.07)));
} else {
column.setCellRenderer(new HashSetTableCellRenderer());
column.setPreferredWidth(((int) (width1 * 0.92)));
}
}
@ -225,6 +229,24 @@ public final class HashLookupModuleSettingsPanel extends IngestModuleIngestJobSe
return valid;
}
}
/**
* Simple TableCellRenderer to add tool tips to the cells
*/
private static final class HashSetTableCellRenderer extends DefaultTableCellRenderer{
private static final long serialVersionUID = 1L;
@Override
public Component getTableCellRendererComponent(
JTable table, Object value,
boolean isSelected, boolean hasFocus,
int row, int column) {
JLabel label = (JLabel)super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
label.setToolTipText(label.getText());
return label;
}
}
private static final class HashSetsTableModel extends AbstractTableModel {

View File

@ -18,13 +18,16 @@
*/
package org.sleuthkit.autopsy.modules.interestingitems;
import java.awt.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import java.util.TreeMap;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableColumn;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
@ -110,6 +113,7 @@ final class FilesIdentifierIngestJobSettingsPanel extends IngestModuleIngestJobS
if (i == 0) {
column.setPreferredWidth(((int) (width * 0.07)));
} else {
column.setCellRenderer(new FileSetsTableCellRenderer());
column.setPreferredWidth(((int) (width * 0.92)));
}
}
@ -158,6 +162,24 @@ final class FilesIdentifierIngestJobSettingsPanel extends IngestModuleIngestJobS
// Cache the snapshot so it will be avaialble for the next update.
this.filesSetSnapshot = newFilesSetSnapshot;
}
/**
* Simple TableCellRenderer to add tool tips to cells.
*/
private static final class FileSetsTableCellRenderer extends DefaultTableCellRenderer {
private static final long serialVersionUID = 1L;
@Override
public Component getTableCellRendererComponent(
JTable table, Object value,
boolean isSelected, boolean hasFocus,
int row, int column) {
JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
label.setToolTipText(label.getText());
return label;
}
}
/**
* Table model for a JTable component that allows users to enable and

View File

@ -19,3 +19,10 @@ PhotoRecIngestModule.error.msg=Error processing {0} with PhotoRec carver.
PhotoRecIngestModule.complete.numberOfErrors=Number of Errors while Carving:
PhotoRecCarverIngestJobSettingsPanel.detectionSettingsLabel.text=PhotoRec Settings
PhotoRecCarverIngestJobSettingsPanel.keepCorruptedFilesCheckbox.text=Keep corrupted files
PhotoRecCarverIngestJobSettingsPanel.includeExcludeCheckbox.text=Focus on certain file types
PhotoRecCarverIngestJobSettingsPanel.fullListOfTypesLabel.text=Full List of Types:
PhotoRecCarverIngestJobSettingsPanel.exampleLabel.text=Example: jpg,png,zip
PhotoRecCarverIngestJobSettingsPanel.extensionListTextfield.text=
PhotoRecCarverIngestJobSettingsPanel.extensionListLabel.text=Types (comma separated list of extensions)
PhotoRecCarverIngestJobSettingsPanel.excludeRadioButton.text=Exclude the specified types
PhotoRecCarverIngestJobSettingsPanel.includeRadioButton.text=Include only the specified types

View File

@ -8,6 +8,9 @@ OpenIDE-Module-Long-Description=PhotoRec Carver ingest module. \n\n Carves unall
OpenIDE-Module-Short-Description=Carves unallocated space and feeds carved files back into the system for processing.
moduleDisplayName.text=PhotoRec Carver
moduleDescription.text=Runs PhotoRec carver against unallocated space in the data source.
# {0} - extensions
PhotoRecCarverFileIngestModule_startUp_invalidExtensions_description=The following extensions are invalid: {0}
PhotoRecCarverFileIngestModule_startUp_noExtensionsProvided_description=No extensions provided for PhotoRec to carve.
PhotoRecIngestModule.nonHostnameUNCPathUsed=PhotoRec cannot operate with a UNC path containing IP addresses.
PhotoRecIngestModule.PermissionsNotSufficient=Insufficient permissions accessing
PhotoRecIngestModule.PermissionsNotSufficientSeeReference=See 'Shared Drive Authentication' in Autopsy help.
@ -26,5 +29,12 @@ PhotoRecIngestModule.error.msg=Error processing {0} with PhotoRec carver.
PhotoRecIngestModule.complete.numberOfErrors=Number of Errors while Carving:
PhotoRecCarverIngestJobSettingsPanel.detectionSettingsLabel.text=PhotoRec Settings
PhotoRecCarverIngestJobSettingsPanel.keepCorruptedFilesCheckbox.text=Keep corrupted files
PhotoRecCarverIngestJobSettingsPanel.includeExcludeCheckbox.text=Focus on certain file types
PhotoRecCarverIngestJobSettingsPanel.fullListOfTypesLabel.text=Full List of Types:
PhotoRecCarverIngestJobSettingsPanel.exampleLabel.text=Example: jpg,png,zip
PhotoRecCarverIngestJobSettingsPanel.extensionListTextfield.text=
PhotoRecCarverIngestJobSettingsPanel.extensionListLabel.text=Types (comma separated list of extensions)
PhotoRecCarverIngestJobSettingsPanel.excludeRadioButton.text=Exclude the specified types
PhotoRecCarverIngestJobSettingsPanel.includeRadioButton.text=Include only the specified types
unallocatedSpaceProcessingSettingsError.message=The selected file ingest filter ignores unallocated space. This module carves unallocated space. Please choose a filter which does not ignore unallocated space or disable this module.
unsupportedOS.message=PhotoRec module is supported on Windows platforms only.

View File

@ -29,6 +29,7 @@ import java.nio.file.Paths;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
@ -36,6 +37,7 @@ import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level;
import java.util.stream.Collectors;
import org.openide.modules.InstalledFileLocator;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case;
@ -79,7 +81,12 @@ import org.sleuthkit.datamodel.TskData;
final class PhotoRecCarverFileIngestModule implements FileIngestModule {
static final boolean DEFAULT_CONFIG_KEEP_CORRUPTED_FILES = false;
static final PhotoRecCarverIngestJobSettings.ExtensionFilterOption DEFAULT_CONFIG_EXTENSION_FILTER
= PhotoRecCarverIngestJobSettings.ExtensionFilterOption.NO_FILTER;
static final boolean DEFAULT_CONFIG_INCLUDE_ELSE_EXCLUDE = false;
private static final String PHOTOREC_TEMP_SUBDIR = "Photorec";
private static final String PHOTOREC_DIRECTORY = "photorec_exec"; //NON-NLS
private static final String PHOTOREC_SUBDIRECTORY = "bin"; //NON-NLS
private static final String PHOTOREC_EXECUTABLE = "photorec_win.exe"; //NON-NLS
@ -88,7 +95,6 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule {
private static final String PHOTOREC_RESULTS_EXTENDED = "results.1"; //NON-NLS
private static final String PHOTOREC_REPORT = "report.xml"; //NON-NLS
private static final String LOG_FILE = "run_log.txt"; //NON-NLS
private static final String TEMP_DIR_NAME = "temp"; // NON-NLS
private static final String SEP = System.getProperty("line.separator");
private static final Logger logger = Logger.getLogger(PhotoRecCarverFileIngestModule.class.getName());
private static final HashMap<Long, IngestJobTotals> totalsForIngestJobs = new HashMap<>();
@ -96,26 +102,74 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule {
private static final Map<Long, WorkingPaths> pathsByJob = new ConcurrentHashMap<>();
private IngestJobContext context;
private Path rootOutputDirPath;
private Path rootTempDirPath;
private File executableFile;
private IngestServices services;
private final UNCPathUtilities uncPathUtilities = new UNCPathUtilities();
private final PhotoRecCarverIngestJobSettings settings;
private String optionsString;
private long jobId;
private final boolean keepCorruptedFiles;
private static class IngestJobTotals {
private final AtomicLong totalItemsRecovered = new AtomicLong(0);
private final AtomicLong totalItemsWithErrors = new AtomicLong(0);
private final AtomicLong totalWritetime = new AtomicLong(0);
private final AtomicLong totalParsetime = new AtomicLong(0);
}
/**
* Create a PhotoRec Carver ingest module instance.
*
*
* @param settings Ingest job settings used to configure the module.
*/
PhotoRecCarverFileIngestModule(PhotoRecCarverIngestJobSettings settings) {
keepCorruptedFiles = settings.isKeepCorruptedFiles();
this.settings = settings;
}
/**
* Creates a photorec command line options string based on the settings.
*
* @param settings The settings.
*
* @return The options string to be provided to Photorec on the command
* line.
*/
private String getPhotorecOptions(PhotoRecCarverIngestJobSettings settings) {
List<String> toRet = new ArrayList<String>();
if (settings.isKeepCorruptedFiles()) {
toRet.addAll(Arrays.asList("options", "keep_corrupted_file"));
}
if (settings.getExtensionFilterOption()
!= PhotoRecCarverIngestJobSettings.ExtensionFilterOption.NO_FILTER) {
// add the file opt menu item
toRet.add("fileopt");
String enable = "enable";
String disable = "disable";
// if we are including file extensions, then we are excluding
// everything else and vice-versa.
String everythingEnable = settings.getExtensionFilterOption()
== PhotoRecCarverIngestJobSettings.ExtensionFilterOption.INCLUDE
? disable : enable;
toRet.addAll(Arrays.asList("everything", everythingEnable));
final String itemEnable = settings.getExtensionFilterOption()
== PhotoRecCarverIngestJobSettings.ExtensionFilterOption.INCLUDE
? enable : disable;
settings.getExtensions().forEach((extension) -> {
toRet.addAll(Arrays.asList(extension, itemEnable));
});
}
toRet.add("search");
return String.join(",", toRet);
}
private static synchronized IngestJobTotals getTotalsForIngestJobs(long ingestJobId) {
@ -136,7 +190,34 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule {
* @inheritDoc
*/
@Override
@NbBundle.Messages({
"# {0} - extensions",
"PhotoRecCarverFileIngestModule_startUp_invalidExtensions_description=The following extensions are invalid: {0}",
"PhotoRecCarverFileIngestModule_startUp_noExtensionsProvided_description=No extensions provided for PhotoRec to carve."
})
public void startUp(IngestJobContext context) throws IngestModule.IngestModuleException {
// validate settings
if (this.settings.getExtensionFilterOption() != PhotoRecCarverIngestJobSettings.ExtensionFilterOption.NO_FILTER) {
if (this.settings.getExtensions().isEmpty()
&& this.settings.getExtensionFilterOption() == PhotoRecCarverIngestJobSettings.ExtensionFilterOption.INCLUDE) {
throw new IngestModule.IngestModuleException(
Bundle.PhotoRecCarverFileIngestModule_startUp_noExtensionsProvided_description());
}
List<String> invalidExtensions = this.settings.getExtensions().stream()
.filter((ext) -> !PhotoRecCarverFileOptExtensions.isValidExtension(ext))
.collect(Collectors.toList());
if (!invalidExtensions.isEmpty()) {
throw new IngestModule.IngestModuleException(
Bundle.PhotoRecCarverFileIngestModule_startUp_invalidExtensions_description(
String.join(",", invalidExtensions)));
}
}
this.optionsString = getPhotorecOptions(this.settings);
this.context = context;
this.services = IngestServices.getInstance();
this.jobId = this.context.getJobId();
@ -150,9 +231,10 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule {
}
this.rootOutputDirPath = createModuleOutputDirectoryForCase();
this.rootTempDirPath = createTempOutputDirectoryForCase();
//Set photorec executable directory based on operating system.
executableFile = locateExecutable();
executableFile = locateExecutable();
if (PhotoRecCarverFileIngestModule.refCounter.incrementAndGet(this.jobId) == 1) {
try {
@ -164,7 +246,7 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule {
Files.createDirectories(outputDirPath);
// A temp subdirectory is also created as a location for writing unallocated space files to disk.
Path tempDirPath = Paths.get(outputDirPath.toString(), PhotoRecCarverFileIngestModule.TEMP_DIR_NAME);
Path tempDirPath = Paths.get(this.rootTempDirPath.toString(), folder);
Files.createDirectory(tempDirPath);
// Save the directories for the current job.
@ -242,12 +324,9 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule {
outputDirPath.toAbsolutePath().toString() + File.separator + PHOTOREC_RESULTS_BASE,
"/cmd", // NON-NLS
tempFilePath.toFile().toString());
if (keepCorruptedFiles) {
processAndSettings.command().add("options,keep_corrupted_file,search"); // NON-NLS
} else {
processAndSettings.command().add("search"); // NON-NLS
}
processAndSettings.command().add(this.optionsString);
// Add environment variable to force PhotoRec to run with the same permissions Autopsy uses
processAndSettings.environment().put("__COMPAT_LAYER", "RunAsInvoker"); //NON-NLS
processAndSettings.redirectErrorStream(true);
@ -389,8 +468,7 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule {
try {
// The last instance of this module for an ingest job cleans out
// the working paths map entry for the job and deletes the temp dir.
WorkingPaths paths = PhotoRecCarverFileIngestModule.pathsByJob.remove(this.jobId);
FileUtil.deleteDir(new File(paths.getTempDirPath().toString()));
FileUtil.deleteDir(this.rootTempDirPath.toFile());
postSummary(jobId);
} catch (SecurityException ex) {
logger.log(Level.SEVERE, "Error shutting down PhotoRec carver module", ex); // NON-NLS
@ -418,20 +496,51 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule {
}
/**
* Creates the output directory for this module for the current case, if it
* does not already exist.
* Creates the output directory for this module for the current case's temp
* directory, if it does not already exist.
*
* @return The absolute path of the output directory.
*
* @throws org.sleuthkit.autopsy.ingest.IngestModule.IngestModuleException
*/
synchronized Path createTempOutputDirectoryForCase() throws IngestModule.IngestModuleException {
try {
Path path = Paths.get(Case.getCurrentCaseThrows().getTempDirectory(), PHOTOREC_TEMP_SUBDIR);
return createOutputDirectoryForCase(path);
} catch (NoCurrentCaseException ex) {
throw new IngestModule.IngestModuleException(Bundle.cannotCreateOutputDir_message(ex.getLocalizedMessage()), ex);
}
}
/**
* Creates the output directory for this module for the current case's
* module directory, if it does not already exist.
*
* @return The absolute path of the output directory.
*
* @throws org.sleuthkit.autopsy.ingest.IngestModule.IngestModuleException
*/
synchronized Path createModuleOutputDirectoryForCase() throws IngestModule.IngestModuleException {
Path path;
try {
path = Paths.get(Case.getCurrentCaseThrows().getModuleDirectory(), PhotoRecCarverIngestModuleFactory.getModuleName());
Path path = Paths.get(Case.getCurrentCaseThrows().getModuleDirectory(), PhotoRecCarverIngestModuleFactory.getModuleName());
return createOutputDirectoryForCase(path);
} catch (NoCurrentCaseException ex) {
throw new IngestModule.IngestModuleException(Bundle.cannotCreateOutputDir_message(ex.getLocalizedMessage()), ex);
}
}
/**
* Creates the output directory for this module for the current case, if it
* does not already exist.
*
* @param providedPath The absolute path to be created.
*
* @return The absolute path of the output directory.
*
* @throws org.sleuthkit.autopsy.ingest.IngestModule.IngestModuleException
*/
private synchronized Path createOutputDirectoryForCase(Path providedPath) throws IngestModule.IngestModuleException {
Path path = providedPath;
try {
Files.createDirectory(path);
if (UNCPathUtilities.isUNC(path)) {
@ -455,7 +564,6 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule {
return path;
}
/**
* Finds and returns the path to the executable, if able.
*
@ -477,9 +585,9 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule {
File usrLocalBin = new File("/usr/local/bin/photorec");
if (usrBin.canExecute() && usrBin.exists() && !usrBin.isDirectory()) {
photorec_linux_directory = "/usr/bin";
}else if(usrLocalBin.canExecute() && usrLocalBin.exists() && !usrLocalBin.isDirectory()){
} else if (usrLocalBin.canExecute() && usrLocalBin.exists() && !usrLocalBin.isDirectory()) {
photorec_linux_directory = "/usr/local/bin";
}else{
} else {
throw new IngestModule.IngestModuleException("Photorec not found");
}
execName = Paths.get(photorec_linux_directory, PHOTOREC_LINUX_EXECUTABLE);
@ -489,8 +597,7 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule {
if (null == exeFile) {
throw new IngestModule.IngestModuleException(Bundle.missingExecutable_message());
}
if (!exeFile.canExecute()) {
throw new IngestModule.IngestModuleException(Bundle.cannotRunExecutable_message());
}

Some files were not shown because too many files have changed in this diff Show More