mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-18 10:37:43 +00:00
Merge branch 'timeline-event-mgr-develop' into upstream_timeline-event-mgr
This commit is contained in:
commit
1ba8bd30c5
@ -21,11 +21,6 @@
|
|||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="get-thirdparty-dependencies" description="get third-party dependencies">
|
<target name="get-thirdparty-dependencies" description="get third-party dependencies">
|
||||||
<!--Copy openCV dependencies to release-->
|
|
||||||
<copy todir="${modules.dir}" >
|
|
||||||
<fileset dir="${thirdparty.dir}/opencv" />
|
|
||||||
</copy>
|
|
||||||
|
|
||||||
<!--Copy photorec to release-->
|
<!--Copy photorec to release-->
|
||||||
<copy todir="${basedir}/release/photorec_exec" >
|
<copy todir="${basedir}/release/photorec_exec" >
|
||||||
<fileset dir="${thirdparty.dir}/photorec_exec"/>
|
<fileset dir="${thirdparty.dir}/photorec_exec"/>
|
||||||
@ -83,6 +78,8 @@
|
|||||||
tofile="${ext.dir}/mchange-commons-java-0.2.9.jar"/>
|
tofile="${ext.dir}/mchange-commons-java-0.2.9.jar"/>
|
||||||
<copy file="${env.TSK_HOME}/bindings/java/lib/c3p0-0.9.5.jar"
|
<copy file="${env.TSK_HOME}/bindings/java/lib/c3p0-0.9.5.jar"
|
||||||
tofile="${ext.dir}/c3p0-0.9.5.jar"/>
|
tofile="${ext.dir}/c3p0-0.9.5.jar"/>
|
||||||
|
<copy file="${env.TSK_HOME}/bindings/java/lib/SparseBitSet-1.1.jar"
|
||||||
|
tofile="${ext.dir}/SparseBitSet-1.1.jar"/>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="download-binlist">
|
<target name="download-binlist">
|
||||||
@ -94,13 +91,17 @@
|
|||||||
|
|
||||||
<target name="getTestDataFiles">
|
<target name="getTestDataFiles">
|
||||||
<mkdir dir="${basedir}/test/qa-functional/data"/>
|
<mkdir dir="${basedir}/test/qa-functional/data"/>
|
||||||
<get src="https://drive.google.com/uc?id=1dLYGctuvRQMmnzfXPppTM_9gB49eLc_g" dest="${test-input}/embedded.vhd" skipexisting="true"/>
|
<get src="https://drive.google.com/uc?id=1dLYGctuvRQMmnzfXPppTM_9gB49eLc_g" dest="${test-input}/EmbeddedIM_img1_v1.vhd" skipexisting="true"/>
|
||||||
<get src="https://drive.google.com/uc?id=1JACMDyH4y54ypGzFWl82ZzMQf3qbrioP" dest="${test-input}/encryption_detection_bitlocker_test.vhd" skipexisting="true"/>
|
<get src="https://drive.google.com/uc?id=1JACMDyH4y54ypGzFWl82ZzMQf3qbrioP" dest="${test-input}/BitlockerDetection_img1_v1.vhd" skipexisting="true"/>
|
||||||
<get src="https://drive.google.com/uc?id=17sGybvmBGsWWJYo1IWKmO04oG9hKpPi3" dest="${test-input}/encryption_detection_sqlcipher_test.vhd" skipexisting="true"/>
|
<get src="https://drive.google.com/uc?id=17sGybvmBGsWWJYo1IWKmO04oG9hKpPi3" dest="${test-input}/SqlCipherDetection_img1_v1.vhd" skipexisting="true"/>
|
||||||
<get src="https://drive.google.com/uc?id=0BxdBkzm5VKGNT0dGY0dqcHVsU3M" dest="${test-input}/filter_test1.img" skipexisting="true"/>
|
<get src="https://drive.google.com/uc?id=0BxdBkzm5VKGNT0dGY0dqcHVsU3M" dest="${test-input}/IngestFilters_img1_v1.img" skipexisting="true"/>
|
||||||
<get src="https://drive.google.com/uc?id=1bghoSm7z7nhmGIxlllyY1MMlbLntxm7n" dest="${test-input}/local_files_test.zip" skipexisting="true"/>
|
<get src="https://drive.google.com/uc?id=1bghoSm7z7nhmGIxlllyY1MMlbLntxm7n" dest="${test-input}/IngestFilters_local1_v1.zip" skipexisting="true"/>
|
||||||
<get src="https://drive.google.com/uc?id=1BrSiUQ1fzxFS9vIaK4mYKX6qIVp9kRWT" dest="${test-input}/password_detection_test.img" skipexisting="true"/>
|
<get src="https://drive.google.com/uc?id=1BrSiUQ1fzxFS9vIaK4mYKX6qIVp9kRWT" dest="${test-input}/PasswordDetection_img1_v1.img" skipexisting="true"/>
|
||||||
<get src="https://drive.google.com/uc?id=1HD8s4rculgHV1qZT5g80Kg7j4m1qccrN" dest="${test-input}/veracrypt_detection_test.vhd" skipexisting="true"/>
|
<get src="https://drive.google.com/uc?id=1HD8s4rculgHV1qZT5g80Kg7j4m1qccrN" dest="${test-input}/VeracryptDetection_img1_v1.vhd" skipexisting="true"/>
|
||||||
|
<get src="https://drive.google.com/uc?id=1mr9waEDG5H8GBBn_yXwMUQ6senwC1goL" dest="${test-input}/CommonFiles_img1_v1.vhd" skipexisting="true"/>
|
||||||
|
<get src="https://drive.google.com/uc?id=1-vmbmAAb2HBLbf58GpAA97ozGUFiYHbN" dest="${test-input}/CommonFiles_img2_v1.vhd" skipexisting="true"/>
|
||||||
|
<get src="https://drive.google.com/uc?id=1ghDjm0NhI3ShMQ38E-4o7XrGeexpjdJb" dest="${test-input}/CommonFiles_img3_v1.vhd" skipexisting="true"/>
|
||||||
|
<get src="https://drive.google.com/uc?id=1SJYJFjiumKEtQmeMPsQ6G3xmABarbKm_" dest="${test-input}/CommonFiles_img4_v1.vhd" skipexisting="true"/>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="get-deps" depends="init-ivy,getTSKJars,get-thirdparty-dependencies,get-InternalPythonModules, download-binlist,getTestDataFiles">
|
<target name="get-deps" depends="init-ivy,getTSKJars,get-thirdparty-dependencies,get-InternalPythonModules, download-binlist,getTestDataFiles">
|
||||||
|
@ -3,7 +3,7 @@ file.reference.c3p0-0.9.5.jar=release/modules/ext/c3p0-0.9.5.jar
|
|||||||
file.reference.commons-compress-1.14.jar=release/modules/ext/commons-compress-1.14.jar
|
file.reference.commons-compress-1.14.jar=release/modules/ext/commons-compress-1.14.jar
|
||||||
file.reference.commons-dbcp2-2.1.1.jar=release\\modules\\ext\\commons-dbcp2-2.1.1.jar
|
file.reference.commons-dbcp2-2.1.1.jar=release\\modules\\ext\\commons-dbcp2-2.1.1.jar
|
||||||
file.reference.commons-pool2-2.4.2.jar=release\\modules\\ext\\commons-pool2-2.4.2.jar
|
file.reference.commons-pool2-2.4.2.jar=release\\modules\\ext\\commons-pool2-2.4.2.jar
|
||||||
file.reference.dd-plist-1.20.jar=release\\modules\\ext\\dd-plist-1.20.jar
|
file.reference.dd-plist-1.20.jar=release/modules/ext/dd-plist-1.20.jar
|
||||||
file.reference.jdom-2.0.5-contrib.jar=release/modules/ext/jdom-2.0.5-contrib.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.jdom-2.0.5.jar=release/modules/ext/jdom-2.0.5.jar
|
||||||
file.reference.jgraphx-v3.8.0.jar=release/modules/ext/jgraphx-v3.8.0.jar
|
file.reference.jgraphx-v3.8.0.jar=release/modules/ext/jgraphx-v3.8.0.jar
|
||||||
@ -12,7 +12,6 @@ file.reference.jython-standalone-2.7.0.jar=release/modules/ext/jython-standalone
|
|||||||
file.reference.mchange-commons-java-0.2.9.jar=release/modules/ext/mchange-commons-java-0.2.9.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.10.1.jar=release/modules/ext/metadata-extractor-2.10.1.jar
|
file.reference.metadata-extractor-2.10.1.jar=release/modules/ext/metadata-extractor-2.10.1.jar
|
||||||
file.reference.postgresql-9.4.1211.jre7.jar=release/modules/ext/postgresql-9.4.1211.jre7.jar
|
file.reference.postgresql-9.4.1211.jre7.jar=release/modules/ext/postgresql-9.4.1211.jre7.jar
|
||||||
file.reference.opencv-248.jar=release/modules/ext/opencv-248.jar
|
|
||||||
file.reference.Rejistry-1.0-SNAPSHOT.jar=release/modules/ext/Rejistry-1.0-SNAPSHOT.jar
|
file.reference.Rejistry-1.0-SNAPSHOT.jar=release/modules/ext/Rejistry-1.0-SNAPSHOT.jar
|
||||||
file.reference.sevenzipjbinding-AllPlatforms.jar=release/modules/ext/sevenzipjbinding-AllPlatforms.jar
|
file.reference.sevenzipjbinding-AllPlatforms.jar=release/modules/ext/sevenzipjbinding-AllPlatforms.jar
|
||||||
file.reference.sevenzipjbinding.jar=release/modules/ext/sevenzipjbinding.jar
|
file.reference.sevenzipjbinding.jar=release/modules/ext/sevenzipjbinding.jar
|
||||||
@ -40,6 +39,7 @@ file.reference.curator-recipes-2.8.0.jar=release/modules/ext/curator-recipes-2.8
|
|||||||
file.reference.xmpcore-5.1.3.jar=release/modules/ext/xmpcore-5.1.3.jar
|
file.reference.xmpcore-5.1.3.jar=release/modules/ext/xmpcore-5.1.3.jar
|
||||||
file.reference.xz-1.6.jar=release/modules/ext/xz-1.6.jar
|
file.reference.xz-1.6.jar=release/modules/ext/xz-1.6.jar
|
||||||
file.reference.zookeeper-3.4.6.jar=release/modules/ext/zookeeper-3.4.6.jar
|
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
|
||||||
javac.source=1.8
|
javac.source=1.8
|
||||||
javac.compilerargs=-Xlint -Xlint:-serial
|
javac.compilerargs=-Xlint -Xlint:-serial
|
||||||
license.file=../LICENSE-2.0.txt
|
license.file=../LICENSE-2.0.txt
|
||||||
|
@ -339,6 +339,10 @@
|
|||||||
<package>org.sleuthkit.autopsy.report</package>
|
<package>org.sleuthkit.autopsy.report</package>
|
||||||
<package>org.sleuthkit.datamodel</package>
|
<package>org.sleuthkit.datamodel</package>
|
||||||
</public-packages>
|
</public-packages>
|
||||||
|
<class-path-extension>
|
||||||
|
<runtime-relative-path>ext/jackcess-2.1.8.jar</runtime-relative-path>
|
||||||
|
<binary-origin>release/modules/ext/jackcess-2.1.8.jar</binary-origin>
|
||||||
|
</class-path-extension>
|
||||||
<class-path-extension>
|
<class-path-extension>
|
||||||
<runtime-relative-path>ext/zookeeper-3.4.6.jar</runtime-relative-path>
|
<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>
|
||||||
@ -348,33 +352,33 @@
|
|||||||
<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>
|
||||||
<class-path-extension>
|
<class-path-extension>
|
||||||
<runtime-relative-path>ext/sleuthkit-postgresql-4.6.1.jar</runtime-relative-path>
|
<runtime-relative-path>ext/cxf-rt-transports-http-3.0.16.jar</runtime-relative-path>
|
||||||
<binary-origin>release/modules/ext/sleuthkit-postgresql-4.6.1.jar</binary-origin>
|
<binary-origin>release/modules/ext/cxf-rt-transports-http-3.0.16.jar</binary-origin>
|
||||||
</class-path-extension>
|
|
||||||
<class-path-extension>
|
|
||||||
<runtime-relative-path>ext/opencv-248.jar</runtime-relative-path>
|
|
||||||
<binary-origin>release/modules/ext/opencv-248.jar</binary-origin>
|
|
||||||
</class-path-extension>
|
</class-path-extension>
|
||||||
<class-path-extension>
|
<class-path-extension>
|
||||||
<runtime-relative-path>ext/curator-framework-2.8.0.jar</runtime-relative-path>
|
<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>
|
||||||
<class-path-extension>
|
<class-path-extension>
|
||||||
<runtime-relative-path>ext/commons-dbcp2-2.1.1.jar</runtime-relative-path>
|
<runtime-relative-path>ext/bcprov-jdk15on-1.54.jar</runtime-relative-path>
|
||||||
<binary-origin>release/modules/ext/commons-dbcp2-2.1.1.jar</binary-origin>
|
<binary-origin>release/modules/ext/bcprov-jdk15on-1.54.jar</binary-origin>
|
||||||
</class-path-extension>
|
|
||||||
<class-path-extension>
|
|
||||||
<runtime-relative-path>ext/jgraphx-v3.8.0.jar</runtime-relative-path>
|
|
||||||
<binary-origin>release/modules/ext/jgraphx-v3.8.0.jar</binary-origin>
|
|
||||||
</class-path-extension>
|
</class-path-extension>
|
||||||
<class-path-extension>
|
<class-path-extension>
|
||||||
<runtime-relative-path>ext/commons-compress-1.14.jar</runtime-relative-path>
|
<runtime-relative-path>ext/commons-compress-1.14.jar</runtime-relative-path>
|
||||||
<binary-origin>release/modules/ext/commons-compress-1.14.jar</binary-origin>
|
<binary-origin>release/modules/ext/commons-compress-1.14.jar</binary-origin>
|
||||||
</class-path-extension>
|
</class-path-extension>
|
||||||
|
<class-path-extension>
|
||||||
|
<runtime-relative-path>ext/fontbox-2.0.8.jar</runtime-relative-path>
|
||||||
|
<binary-origin>release/modules/ext/fontbox-2.0.8.jar</binary-origin>
|
||||||
|
</class-path-extension>
|
||||||
<class-path-extension>
|
<class-path-extension>
|
||||||
<runtime-relative-path>ext/commons-dbcp2-2.1.1.jar</runtime-relative-path>
|
<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>
|
||||||
|
<class-path-extension>
|
||||||
|
<runtime-relative-path>ext/jgraphx-v3.8.0.jar</runtime-relative-path>
|
||||||
|
<binary-origin>release/modules/ext/jgraphx-v3.8.0.jar</binary-origin>
|
||||||
|
</class-path-extension>
|
||||||
<class-path-extension>
|
<class-path-extension>
|
||||||
<runtime-relative-path>ext/jython-standalone-2.7.0.jar</runtime-relative-path>
|
<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>
|
||||||
@ -387,6 +391,14 @@
|
|||||||
<runtime-relative-path>ext/mchange-commons-java-0.2.9.jar</runtime-relative-path>
|
<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>
|
||||||
|
<class-path-extension>
|
||||||
|
<runtime-relative-path>ext/cxf-core-3.0.16.jar</runtime-relative-path>
|
||||||
|
<binary-origin>release/modules/ext/cxf-core-3.0.16.jar</binary-origin>
|
||||||
|
</class-path-extension>
|
||||||
|
<class-path-extension>
|
||||||
|
<runtime-relative-path>ext/javax.ws.rs-api-2.0.1.jar</runtime-relative-path>
|
||||||
|
<binary-origin>release/modules/ext/javax.ws.rs-api-2.0.1.jar</binary-origin>
|
||||||
|
</class-path-extension>
|
||||||
<class-path-extension>
|
<class-path-extension>
|
||||||
<runtime-relative-path>ext/postgresql-9.4.1211.jre7.jar</runtime-relative-path>
|
<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>
|
<binary-origin>release/modules/ext/postgresql-9.4.1211.jre7.jar</binary-origin>
|
||||||
@ -399,6 +411,10 @@
|
|||||||
<runtime-relative-path>ext/metadata-extractor-2.10.1.jar</runtime-relative-path>
|
<runtime-relative-path>ext/metadata-extractor-2.10.1.jar</runtime-relative-path>
|
||||||
<binary-origin>release/modules/ext/metadata-extractor-2.10.1.jar</binary-origin>
|
<binary-origin>release/modules/ext/metadata-extractor-2.10.1.jar</binary-origin>
|
||||||
</class-path-extension>
|
</class-path-extension>
|
||||||
|
<class-path-extension>
|
||||||
|
<runtime-relative-path>ext/sleuthkit-postgresql-4.6.1.jar</runtime-relative-path>
|
||||||
|
<binary-origin>release/modules/ext/sleuthkit-postgresql-4.6.1.jar</binary-origin>
|
||||||
|
</class-path-extension>
|
||||||
<class-path-extension>
|
<class-path-extension>
|
||||||
<runtime-relative-path>ext/tika-core-1.17.jar</runtime-relative-path>
|
<runtime-relative-path>ext/tika-core-1.17.jar</runtime-relative-path>
|
||||||
<binary-origin>release/modules/ext/tika-core-1.17.jar</binary-origin>
|
<binary-origin>release/modules/ext/tika-core-1.17.jar</binary-origin>
|
||||||
@ -411,58 +427,18 @@
|
|||||||
<runtime-relative-path>ext/curator-client-2.8.0.jar</runtime-relative-path>
|
<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>
|
||||||
<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/jackcess-2.1.8.jar</runtime-relative-path>
|
|
||||||
<binary-origin>release/modules/ext/jackcess-2.1.8.jar</binary-origin>
|
|
||||||
</class-path-extension>
|
|
||||||
<class-path-extension>
|
|
||||||
<runtime-relative-path>ext/jackcess-encrypt-2.1.2.jar</runtime-relative-path>
|
|
||||||
<binary-origin>release/modules/ext/jackcess-encrypt-2.1.2.jar</binary-origin>
|
|
||||||
</class-path-extension>
|
|
||||||
<class-path-extension>
|
|
||||||
<runtime-relative-path>ext/jempbox-1.8.13.jar</runtime-relative-path>
|
|
||||||
<binary-origin>release/modules/ext/jempbox-1.8.13.jar</binary-origin>
|
|
||||||
</class-path-extension>
|
|
||||||
<class-path-extension>
|
|
||||||
<runtime-relative-path>ext/javax.ws.rs-api-2.0.1.jar</runtime-relative-path>
|
|
||||||
<binary-origin>release/modules/ext/javax.ws.rs-api-2.0.1.jar</binary-origin>
|
|
||||||
</class-path-extension>
|
|
||||||
<class-path-extension>
|
|
||||||
<runtime-relative-path>ext/cxf-rt-rs-client-3.0.16.jar</runtime-relative-path>
|
|
||||||
<binary-origin>release/modules/ext/cxf-rt-rs-client-3.0.16.jar</binary-origin>
|
|
||||||
</class-path-extension>
|
|
||||||
<class-path-extension>
|
|
||||||
<runtime-relative-path>ext/cxf-rt-transports-http-3.0.16.jar</runtime-relative-path>
|
|
||||||
<binary-origin>release/modules/ext/cxf-rt-transports-http-3.0.16.jar</binary-origin>
|
|
||||||
</class-path-extension>
|
|
||||||
<class-path-extension>
|
|
||||||
<runtime-relative-path>ext/cxf-core-3.0.16.jar</runtime-relative-path>
|
|
||||||
<binary-origin>release/modules/ext/cxf-core-3.0.16.jar</binary-origin>
|
|
||||||
</class-path-extension>
|
|
||||||
<class-path-extension>
|
<class-path-extension>
|
||||||
<runtime-relative-path>ext/cxf-rt-frontend-jaxrs-3.0.16.jar</runtime-relative-path>
|
<runtime-relative-path>ext/cxf-rt-frontend-jaxrs-3.0.16.jar</runtime-relative-path>
|
||||||
<binary-origin>release/modules/ext/cxf-rt-frontend-jaxrs-3.0.16.jar</binary-origin>
|
<binary-origin>release/modules/ext/cxf-rt-frontend-jaxrs-3.0.16.jar</binary-origin>
|
||||||
</class-path-extension>
|
</class-path-extension>
|
||||||
<class-path-extension>
|
|
||||||
<runtime-relative-path>ext/tika-parsers-1.17.jar</runtime-relative-path>
|
|
||||||
<binary-origin>release/modules/ext/tika-parsers-1.17.jar</binary-origin>
|
|
||||||
</class-path-extension>
|
|
||||||
<class-path-extension>
|
|
||||||
<runtime-relative-path>ext/fontbox-2.0.8.jar</runtime-relative-path>
|
|
||||||
<binary-origin>release/modules/ext/fontbox-2.0.8.jar</binary-origin>
|
|
||||||
</class-path-extension>
|
|
||||||
<class-path-extension>
|
|
||||||
<runtime-relative-path>ext/pdfbox-2.0.8.jar</runtime-relative-path>
|
|
||||||
<binary-origin>release/modules/ext/pdfbox-2.0.8.jar</binary-origin>
|
|
||||||
</class-path-extension>
|
|
||||||
<class-path-extension>
|
<class-path-extension>
|
||||||
<runtime-relative-path>ext/pdfbox-tools-2.0.8.jar</runtime-relative-path>
|
<runtime-relative-path>ext/pdfbox-tools-2.0.8.jar</runtime-relative-path>
|
||||||
<binary-origin>release/modules/ext/pdfbox-tools-2.0.8.jar</binary-origin>
|
<binary-origin>release/modules/ext/pdfbox-tools-2.0.8.jar</binary-origin>
|
||||||
</class-path-extension>
|
</class-path-extension>
|
||||||
|
<class-path-extension>
|
||||||
|
<runtime-relative-path>ext/tika-parsers-1.17.jar</runtime-relative-path>
|
||||||
|
<binary-origin>release/modules/ext/tika-parsers-1.17.jar</binary-origin>
|
||||||
|
</class-path-extension>
|
||||||
<class-path-extension>
|
<class-path-extension>
|
||||||
<runtime-relative-path>ext/sqlite-jdbc-3.8.11.jar</runtime-relative-path>
|
<runtime-relative-path>ext/sqlite-jdbc-3.8.11.jar</runtime-relative-path>
|
||||||
<binary-origin>release/modules/ext/sqlite-jdbc-3.8.11.jar</binary-origin>
|
<binary-origin>release/modules/ext/sqlite-jdbc-3.8.11.jar</binary-origin>
|
||||||
@ -483,6 +459,14 @@
|
|||||||
<runtime-relative-path>ext/dd-plist-1.20.jar</runtime-relative-path>
|
<runtime-relative-path>ext/dd-plist-1.20.jar</runtime-relative-path>
|
||||||
<binary-origin>release/modules/ext/dd-plist-1.20.jar</binary-origin>
|
<binary-origin>release/modules/ext/dd-plist-1.20.jar</binary-origin>
|
||||||
</class-path-extension>
|
</class-path-extension>
|
||||||
|
<class-path-extension>
|
||||||
|
<runtime-relative-path>ext/jempbox-1.8.13.jar</runtime-relative-path>
|
||||||
|
<binary-origin>release/modules/ext/jempbox-1.8.13.jar</binary-origin>
|
||||||
|
</class-path-extension>
|
||||||
|
<class-path-extension>
|
||||||
|
<runtime-relative-path>ext/cxf-rt-rs-client-3.0.16.jar</runtime-relative-path>
|
||||||
|
<binary-origin>release/modules/ext/cxf-rt-rs-client-3.0.16.jar</binary-origin>
|
||||||
|
</class-path-extension>
|
||||||
<class-path-extension>
|
<class-path-extension>
|
||||||
<runtime-relative-path>ext/sevenzipjbinding-AllPlatforms.jar</runtime-relative-path>
|
<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>
|
||||||
@ -491,6 +475,10 @@
|
|||||||
<runtime-relative-path>ext/commons-pool2-2.4.2.jar</runtime-relative-path>
|
<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>
|
||||||
|
<class-path-extension>
|
||||||
|
<runtime-relative-path>ext/jackcess-encrypt-2.1.2.jar</runtime-relative-path>
|
||||||
|
<binary-origin>release/modules/ext/jackcess-encrypt-2.1.2.jar</binary-origin>
|
||||||
|
</class-path-extension>
|
||||||
<class-path-extension>
|
<class-path-extension>
|
||||||
<runtime-relative-path>ext/jsoup-1.10.3.jar</runtime-relative-path>
|
<runtime-relative-path>ext/jsoup-1.10.3.jar</runtime-relative-path>
|
||||||
<binary-origin>release/modules/ext/jsoup-1.10.3.jar</binary-origin>
|
<binary-origin>release/modules/ext/jsoup-1.10.3.jar</binary-origin>
|
||||||
@ -499,6 +487,10 @@
|
|||||||
<runtime-relative-path>ext/jdom-2.0.5-contrib.jar</runtime-relative-path>
|
<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>
|
<binary-origin>release/modules/ext/jdom-2.0.5-contrib.jar</binary-origin>
|
||||||
</class-path-extension>
|
</class-path-extension>
|
||||||
|
<class-path-extension>
|
||||||
|
<runtime-relative-path>ext/pdfbox-2.0.8.jar</runtime-relative-path>
|
||||||
|
<binary-origin>release/modules/ext/pdfbox-2.0.8.jar</binary-origin>
|
||||||
|
</class-path-extension>
|
||||||
<class-path-extension>
|
<class-path-extension>
|
||||||
<runtime-relative-path>ext/c3p0-0.9.5.jar</runtime-relative-path>
|
<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>
|
||||||
@ -506,6 +498,10 @@
|
|||||||
<class-path-extension>
|
<class-path-extension>
|
||||||
<runtime-relative-path>ext/xmpcore-5.1.3.jar</runtime-relative-path>
|
<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/SparseBitSet-1.1.jar</runtime-relative-path>
|
||||||
|
<binary-origin>release/modules/ext/SparseBitSet-1.1.jar</binary-origin>
|
||||||
</class-path-extension>
|
</class-path-extension>
|
||||||
</data>
|
</data>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
@ -37,8 +37,8 @@ import org.sleuthkit.datamodel.TskCoreException;
|
|||||||
* Instances of this Action allow users to apply tags to blackboard artifacts.
|
* Instances of this Action allow users to apply tags to blackboard artifacts.
|
||||||
*/
|
*/
|
||||||
@NbBundle.Messages({
|
@NbBundle.Messages({
|
||||||
"AddBlackboardArtifactTagAction.singularTagResult=Tag Result",
|
"AddBlackboardArtifactTagAction.singularTagResult=Add Result Tag",
|
||||||
"AddBlackboardArtifactTagAction.pluralTagResult=Tag Results",
|
"AddBlackboardArtifactTagAction.pluralTagResult=Add Result Tags",
|
||||||
"# {0} - artifactName",
|
"# {0} - artifactName",
|
||||||
"AddBlackboardArtifactTagAction.unableToTag.msg=Unable to tag {0}.",
|
"AddBlackboardArtifactTagAction.unableToTag.msg=Unable to tag {0}.",
|
||||||
"AddBlackboardArtifactTagAction.taggingErr=Tagging Error"
|
"AddBlackboardArtifactTagAction.taggingErr=Tagging Error"
|
||||||
|
@ -38,8 +38,8 @@ import org.sleuthkit.datamodel.TskCoreException;
|
|||||||
* Instances of this Action allow users to apply tags to content.
|
* Instances of this Action allow users to apply tags to content.
|
||||||
*/
|
*/
|
||||||
@NbBundle.Messages({
|
@NbBundle.Messages({
|
||||||
"AddContentTagAction.singularTagFile=Tag File",
|
"AddContentTagAction.singularTagFile=Add File Tag",
|
||||||
"AddContentTagAction.pluralTagFile=Tag Files",
|
"AddContentTagAction.pluralTagFile=Add File Tags",
|
||||||
"# {0} - fileName",
|
"# {0} - fileName",
|
||||||
"AddContentTagAction.unableToTag.msg=Unable to tag {0}, not a regular file.",
|
"AddContentTagAction.unableToTag.msg=Unable to tag {0}, not a regular file.",
|
||||||
"AddContentTagAction.cannotApplyTagErr=Cannot Apply Tag",
|
"AddContentTagAction.cannotApplyTagErr=Cannot Apply Tag",
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
package org.sleuthkit.autopsy.actions;
|
package org.sleuthkit.autopsy.actions;
|
||||||
|
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
@ -83,7 +85,7 @@ abstract class AddTagAction extends AbstractAction implements Presenter.Popup {
|
|||||||
*/
|
*/
|
||||||
// @@@ This user interface has some significant usability issues and needs
|
// @@@ This user interface has some significant usability issues and needs
|
||||||
// to be reworked.
|
// to be reworked.
|
||||||
private class TagMenu extends JMenu {
|
private final class TagMenu extends JMenu {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@ -92,6 +94,7 @@ abstract class AddTagAction extends AbstractAction implements Presenter.Popup {
|
|||||||
|
|
||||||
// Get the current set of tag names.
|
// Get the current set of tag names.
|
||||||
Map<String, TagName> tagNamesMap = null;
|
Map<String, TagName> tagNamesMap = null;
|
||||||
|
List<String> standardTagNames = TagsManager.getStandardTagNames();
|
||||||
try {
|
try {
|
||||||
TagsManager tagsManager = Case.getCurrentCaseThrows().getServices().getTagsManager();
|
TagsManager tagsManager = Case.getCurrentCaseThrows().getServices().getTagsManager();
|
||||||
tagNamesMap = new TreeMap<>(tagsManager.getDisplayNamesToTagNamesMap());
|
tagNamesMap = new TreeMap<>(tagsManager.getDisplayNamesToTagNamesMap());
|
||||||
@ -99,13 +102,9 @@ abstract class AddTagAction extends AbstractAction implements Presenter.Popup {
|
|||||||
Logger.getLogger(TagsManager.class.getName()).log(Level.SEVERE, "Failed to get tag names", ex); //NON-NLS
|
Logger.getLogger(TagsManager.class.getName()).log(Level.SEVERE, "Failed to get tag names", ex); //NON-NLS
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a "Quick Tag" sub-menu.
|
// Create a menu item for each of the existing and visible tags.
|
||||||
JMenu quickTagMenu = new JMenu(NbBundle.getMessage(this.getClass(), "AddTagAction.quickTag"));
|
// Selecting one of these menu items adds a tag with the associated tag name.
|
||||||
add(quickTagMenu);
|
List<JMenuItem> standardTagMenuitems = new ArrayList<>();
|
||||||
|
|
||||||
// Each tag name in the current set of tags gets its own menu item in
|
|
||||||
// the "Quick Tags" sub-menu. Selecting one of these menu items adds
|
|
||||||
// a tag with the associated tag name.
|
|
||||||
if (null != tagNamesMap && !tagNamesMap.isEmpty()) {
|
if (null != tagNamesMap && !tagNamesMap.isEmpty()) {
|
||||||
for (Map.Entry<String, TagName> entry : tagNamesMap.entrySet()) {
|
for (Map.Entry<String, TagName> entry : tagNamesMap.entrySet()) {
|
||||||
String tagDisplayName = entry.getKey();
|
String tagDisplayName = entry.getKey();
|
||||||
@ -119,27 +118,25 @@ abstract class AddTagAction extends AbstractAction implements Presenter.Popup {
|
|||||||
tagNameItem.addActionListener((ActionEvent e) -> {
|
tagNameItem.addActionListener((ActionEvent e) -> {
|
||||||
getAndAddTag(entry.getKey(), entry.getValue(), NO_COMMENT);
|
getAndAddTag(entry.getKey(), entry.getValue(), NO_COMMENT);
|
||||||
});
|
});
|
||||||
quickTagMenu.add(tagNameItem);
|
|
||||||
}
|
// Show custom tags before predefined tags in the menu
|
||||||
|
if (standardTagNames.contains(tagDisplayName)) {
|
||||||
|
standardTagMenuitems.add(tagNameItem);
|
||||||
} else {
|
} else {
|
||||||
JMenuItem empty = new JMenuItem(NbBundle.getMessage(this.getClass(), "AddTagAction.noTags"));
|
add(tagNameItem);
|
||||||
empty.setEnabled(false);
|
}
|
||||||
quickTagMenu.add(empty);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
quickTagMenu.addSeparator();
|
if (getItemCount() > 0) {
|
||||||
|
addSeparator();
|
||||||
// The "Quick Tag" menu also gets an "Choose Tag..." menu item.
|
|
||||||
// Selecting this item initiates a dialog that can be used to create
|
|
||||||
// or select a tag name and adds a tag with the resulting name.
|
|
||||||
JMenuItem newTagMenuItem = new JMenuItem(NbBundle.getMessage(this.getClass(), "AddTagAction.newTag"));
|
|
||||||
newTagMenuItem.addActionListener((ActionEvent e) -> {
|
|
||||||
TagName tagName = GetTagNameDialog.doDialog();
|
|
||||||
if (null != tagName) {
|
|
||||||
addTag(tagName, NO_COMMENT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
standardTagMenuitems.forEach((menuItem) -> {
|
||||||
|
add(menuItem);
|
||||||
});
|
});
|
||||||
quickTagMenu.add(newTagMenuItem);
|
|
||||||
|
addSeparator();
|
||||||
|
|
||||||
// Create a "Choose Tag and Comment..." menu item. Selecting this item initiates
|
// Create a "Choose Tag and Comment..." menu item. Selecting this item initiates
|
||||||
// a dialog that can be used to create or select a tag name with an
|
// a dialog that can be used to create or select a tag name with an
|
||||||
@ -153,6 +150,19 @@ abstract class AddTagAction extends AbstractAction implements Presenter.Popup {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
add(tagAndCommentItem);
|
add(tagAndCommentItem);
|
||||||
|
|
||||||
|
// Create a "New Tag..." menu item.
|
||||||
|
// Selecting this item initiates a dialog that can be used to create
|
||||||
|
// or select a tag name and adds a tag with the resulting name.
|
||||||
|
JMenuItem newTagMenuItem = new JMenuItem(NbBundle.getMessage(this.getClass(), "AddTagAction.newTag"));
|
||||||
|
newTagMenuItem.addActionListener((ActionEvent e) -> {
|
||||||
|
TagName tagName = GetTagNameDialog.doDialog();
|
||||||
|
if (null != tagName) {
|
||||||
|
addTag(tagName, NO_COMMENT);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
add(newTagMenuItem);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -20,7 +20,7 @@ AddTagAction.newTag=New Tag...
|
|||||||
AddTagAction.tagAndComment=Tag and Comment...
|
AddTagAction.tagAndComment=Tag and Comment...
|
||||||
AddBookmarkTagAction.bookmark.text=Bookmark
|
AddBookmarkTagAction.bookmark.text=Bookmark
|
||||||
GetTagNameAndCommentDialog.noTags=No Tags
|
GetTagNameAndCommentDialog.noTags=No Tags
|
||||||
GetTagNameAndCommentDialog.createTag=Create Tag
|
GetTagNameAndCommentDialog.selectTag=Select Tag
|
||||||
GetTagNameAndCommentDialog.cancelName=cancel
|
GetTagNameAndCommentDialog.cancelName=cancel
|
||||||
GetTagNameDialog.createTag=Create Tag
|
GetTagNameDialog.createTag=Create Tag
|
||||||
GetTagNameDialog.cancelName=Cancel
|
GetTagNameDialog.cancelName=Cancel
|
||||||
|
@ -23,7 +23,7 @@ AddTagAction.noTags=\u30bf\u30b0\u7121\u3057
|
|||||||
AddTagAction.newTag=\u65b0\u898f\u30bf\u30b0\u2026
|
AddTagAction.newTag=\u65b0\u898f\u30bf\u30b0\u2026
|
||||||
AddTagAction.tagAndComment=\u30bf\u30b0\u3068\u30b3\u30e1\u30f3\u30c8\u3092\u8ffd\u52a0\u2026
|
AddTagAction.tagAndComment=\u30bf\u30b0\u3068\u30b3\u30e1\u30f3\u30c8\u3092\u8ffd\u52a0\u2026
|
||||||
GetTagNameAndCommentDialog.noTags=\u30bf\u30b0\u7121\u3057
|
GetTagNameAndCommentDialog.noTags=\u30bf\u30b0\u7121\u3057
|
||||||
GetTagNameAndCommentDialog.createTag=\u30bf\u30b0\u3092\u4f5c\u6210
|
GetTagNameAndCommentDialog.selectTag=\u30bf\u30b0\u3092\u9078\u629e
|
||||||
GetTagNameAndCommentDialog.cancelName=\u30ad\u30e3\u30f3\u30bb\u30eb
|
GetTagNameAndCommentDialog.cancelName=\u30ad\u30e3\u30f3\u30bb\u30eb
|
||||||
GetTagNameDialog.createTag=\u30bf\u30b0\u3092\u4f5c\u6210
|
GetTagNameDialog.createTag=\u30bf\u30b0\u3092\u4f5c\u6210
|
||||||
GetTagNameDialog.cancelName=\u30ad\u30e3\u30f3\u30bb\u30eb
|
GetTagNameDialog.cancelName=\u30ad\u30e3\u30f3\u30bb\u30eb
|
||||||
|
@ -38,7 +38,7 @@ import org.sleuthkit.datamodel.TskCoreException;
|
|||||||
* artifacts.
|
* artifacts.
|
||||||
*/
|
*/
|
||||||
@NbBundle.Messages({
|
@NbBundle.Messages({
|
||||||
"DeleteBlackboardArtifactTagAction.deleteTag=Delete Tag",
|
"DeleteBlackboardArtifactTagAction.deleteTag=Remove Selected Tag(s)",
|
||||||
"# {0} - tagName",
|
"# {0} - tagName",
|
||||||
"DeleteBlackboardArtifactTagAction.unableToDelTag.msg=Unable to delete tag {0}.",
|
"DeleteBlackboardArtifactTagAction.unableToDelTag.msg=Unable to delete tag {0}.",
|
||||||
"DeleteBlackboardArtifactTagAction.tagDelErr=Tag Deletion Error"
|
"DeleteBlackboardArtifactTagAction.tagDelErr=Tag Deletion Error"
|
||||||
|
@ -37,7 +37,7 @@ import org.sleuthkit.datamodel.TskCoreException;
|
|||||||
* Instances of this Action allow users to delete tags applied to content.
|
* Instances of this Action allow users to delete tags applied to content.
|
||||||
*/
|
*/
|
||||||
@NbBundle.Messages({
|
@NbBundle.Messages({
|
||||||
"DeleteContentTagAction.deleteTag=Delete Tag",
|
"DeleteContentTagAction.deleteTag=Remove Selected Tag(s)",
|
||||||
"# {0} - tagName",
|
"# {0} - tagName",
|
||||||
"DeleteContentTagAction.unableToDelTag.msg=Unable to delete tag {0}.",
|
"DeleteContentTagAction.unableToDelTag.msg=Unable to delete tag {0}.",
|
||||||
"DeleteContentTagAction.tagDelErr=Tag Deletion Error"
|
"DeleteContentTagAction.tagDelErr=Tag Deletion Error"
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
package org.sleuthkit.autopsy.actions;
|
package org.sleuthkit.autopsy.actions;
|
||||||
|
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -138,7 +139,7 @@ public class DeleteFileBlackboardArtifactTagAction extends AbstractAction implem
|
|||||||
*/
|
*/
|
||||||
@NbBundle.Messages({"# {0} - artifactID",
|
@NbBundle.Messages({"# {0} - artifactID",
|
||||||
"DeleteFileBlackboardArtifactTagAction.deleteTags.alert=Unable to untag artifact {0}."})
|
"DeleteFileBlackboardArtifactTagAction.deleteTags.alert=Unable to untag artifact {0}."})
|
||||||
private class TagMenu extends JMenu {
|
private final class TagMenu extends JMenu {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@ -153,6 +154,8 @@ public class DeleteFileBlackboardArtifactTagAction extends AbstractAction implem
|
|||||||
= selectedBlackboardArtifactsList.iterator().next();
|
= selectedBlackboardArtifactsList.iterator().next();
|
||||||
|
|
||||||
Map<String, TagName> tagNamesMap = null;
|
Map<String, TagName> tagNamesMap = null;
|
||||||
|
List<String> standardTagNames = TagsManager.getStandardTagNames();
|
||||||
|
List<JMenuItem> standardTagMenuitems = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
// Get the current set of tag names.
|
// Get the current set of tag names.
|
||||||
TagsManager tagsManager = Case.getCurrentCaseThrows().getServices().getTagsManager();
|
TagsManager tagsManager = Case.getCurrentCaseThrows().getServices().getTagsManager();
|
||||||
@ -182,16 +185,27 @@ public class DeleteFileBlackboardArtifactTagAction extends AbstractAction implem
|
|||||||
tagNameItem.addActionListener((ActionEvent e) -> {
|
tagNameItem.addActionListener((ActionEvent e) -> {
|
||||||
deleteTag(tagName, artifactTag, artifact.getArtifactID());
|
deleteTag(tagName, artifactTag, artifact.getArtifactID());
|
||||||
});
|
});
|
||||||
|
// Show custom tags before predefined tags in the menu
|
||||||
|
if (standardTagNames.contains(tagDisplayName)) {
|
||||||
|
standardTagMenuitems.add(tagNameItem);
|
||||||
|
} else {
|
||||||
add(tagNameItem);
|
add(tagNameItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} catch (TskCoreException | NoCurrentCaseException ex) {
|
} catch (TskCoreException | NoCurrentCaseException ex) {
|
||||||
Logger.getLogger(TagMenu.class.getName())
|
Logger.getLogger(TagMenu.class.getName())
|
||||||
.log(Level.SEVERE, "Error retrieving tags for TagMenu", ex); //NON-NLS
|
.log(Level.SEVERE, "Error retrieving tags for TagMenu", ex); //NON-NLS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((getItemCount() > 0) && !standardTagMenuitems.isEmpty() ){
|
||||||
|
addSeparator();
|
||||||
|
}
|
||||||
|
standardTagMenuitems.forEach((menuItem) -> {
|
||||||
|
add(menuItem);
|
||||||
|
});
|
||||||
if (getItemCount() == 0) {
|
if (getItemCount() == 0) {
|
||||||
setEnabled(false);
|
setEnabled(false);
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
package org.sleuthkit.autopsy.actions;
|
package org.sleuthkit.autopsy.actions;
|
||||||
|
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -136,7 +137,7 @@ public class DeleteFileContentTagAction extends AbstractAction implements Presen
|
|||||||
* creating or selecting a tag name for a tag and specifying an optional tag
|
* creating or selecting a tag name for a tag and specifying an optional tag
|
||||||
* comment.
|
* comment.
|
||||||
*/
|
*/
|
||||||
private class TagMenu extends JMenu {
|
private final class TagMenu extends JMenu {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@ -150,6 +151,8 @@ public class DeleteFileContentTagAction extends AbstractAction implements Presen
|
|||||||
AbstractFile file = selectedAbstractFilesList.iterator().next();
|
AbstractFile file = selectedAbstractFilesList.iterator().next();
|
||||||
|
|
||||||
Map<String, TagName> tagNamesMap = null;
|
Map<String, TagName> tagNamesMap = null;
|
||||||
|
List<String> standardTagNames = TagsManager.getStandardTagNames();
|
||||||
|
List<JMenuItem> standardTagMenuitems = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
// Get the current set of tag names.
|
// Get the current set of tag names.
|
||||||
TagsManager tagsManager = Case.getCurrentCaseThrows().getServices().getTagsManager();
|
TagsManager tagsManager = Case.getCurrentCaseThrows().getServices().getTagsManager();
|
||||||
@ -179,16 +182,29 @@ public class DeleteFileContentTagAction extends AbstractAction implements Presen
|
|||||||
tagNameItem.addActionListener((ActionEvent e) -> {
|
tagNameItem.addActionListener((ActionEvent e) -> {
|
||||||
deleteTag(tagName, contentTag, file.getId());
|
deleteTag(tagName, contentTag, file.getId());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Show custom tags before predefined tags in the menu
|
||||||
|
if (standardTagNames.contains(tagDisplayName)) {
|
||||||
|
standardTagMenuitems.add(tagNameItem);
|
||||||
|
} else {
|
||||||
add(tagNameItem);
|
add(tagNameItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} catch (TskCoreException | NoCurrentCaseException ex) {
|
} catch (TskCoreException | NoCurrentCaseException ex) {
|
||||||
Logger.getLogger(TagMenu.class.getName())
|
Logger.getLogger(TagMenu.class.getName())
|
||||||
.log(Level.SEVERE, "Error retrieving tags for TagMenu", ex); //NON-NLS
|
.log(Level.SEVERE, "Error retrieving tags for TagMenu", ex); //NON-NLS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((getItemCount() > 0) && !standardTagMenuitems.isEmpty() ){
|
||||||
|
addSeparator();
|
||||||
|
}
|
||||||
|
standardTagMenuitems.forEach((menuItem) -> {
|
||||||
|
add(menuItem);
|
||||||
|
});
|
||||||
|
|
||||||
if(getItemCount() == 0) {
|
if(getItemCount() == 0) {
|
||||||
setEnabled(false);
|
setEnabled(false);
|
||||||
}
|
}
|
||||||
|
@ -24,11 +24,11 @@
|
|||||||
<DimensionLayout dim="0">
|
<DimensionLayout dim="0">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Group type="102" attributes="0">
|
<Group type="102" attributes="0">
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Group type="102" alignment="1" attributes="0">
|
<Group type="102" alignment="1" attributes="0">
|
||||||
<Component id="newTagButton" min="-2" max="-2" attributes="0"/>
|
<Component id="newTagButton" min="-2" max="-2" attributes="0"/>
|
||||||
<EmptySpace pref="165" max="32767" attributes="0"/>
|
<EmptySpace max="32767" attributes="0"/>
|
||||||
<Component id="okButton" linkSize="1" min="-2" pref="67" max="-2" attributes="0"/>
|
<Component id="okButton" linkSize="1" min="-2" pref="67" max="-2" attributes="0"/>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Component id="cancelButton" linkSize="1" min="-2" max="-2" attributes="0"/>
|
<Component id="cancelButton" linkSize="1" min="-2" max="-2" attributes="0"/>
|
||||||
@ -38,14 +38,14 @@
|
|||||||
<Component id="commentLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
<Component id="commentLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||||
<Component id="tagLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
<Component id="tagLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Component id="commentText" max="32767" attributes="0"/>
|
|
||||||
<Component id="tagCombo" max="32767" attributes="0"/>
|
<Component id="tagCombo" max="32767" attributes="0"/>
|
||||||
|
<Component id="jScrollPane1" pref="318" max="32767" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
@ -58,11 +58,11 @@
|
|||||||
<Component id="tagLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
<Component id="tagLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Group type="103" groupAlignment="3" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Component id="commentLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
<Component id="commentLabel" min="-2" max="-2" attributes="0"/>
|
||||||
<Component id="commentText" alignment="3" min="-2" max="-2" attributes="0"/>
|
<Component id="jScrollPane1" min="-2" pref="51" max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
<EmptySpace pref="37" max="32767" attributes="0"/>
|
<EmptySpace pref="22" max="32767" attributes="0"/>
|
||||||
<Group type="103" groupAlignment="3" attributes="0">
|
<Group type="103" groupAlignment="3" attributes="0">
|
||||||
<Component id="cancelButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
<Component id="cancelButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
<Component id="okButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
<Component id="okButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
@ -125,16 +125,6 @@
|
|||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
</Component>
|
</Component>
|
||||||
<Component class="javax.swing.JTextField" name="commentText">
|
|
||||||
<Properties>
|
|
||||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
|
||||||
<ResourceString bundle="org/sleuthkit/autopsy/actions/Bundle.properties" key="GetTagNameAndCommentDialog.commentText.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
|
||||||
</Property>
|
|
||||||
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
|
||||||
<ResourceString bundle="org/sleuthkit/autopsy/actions/Bundle.properties" key="GetTagNameAndCommentDialog.commentText.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
|
||||||
</Property>
|
|
||||||
</Properties>
|
|
||||||
</Component>
|
|
||||||
<Component class="javax.swing.JButton" name="newTagButton">
|
<Component class="javax.swing.JButton" name="newTagButton">
|
||||||
<Properties>
|
<Properties>
|
||||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
@ -145,5 +135,26 @@
|
|||||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="newTagButtonActionPerformed"/>
|
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="newTagButtonActionPerformed"/>
|
||||||
</Events>
|
</Events>
|
||||||
</Component>
|
</Component>
|
||||||
|
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
|
||||||
|
<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.JTextArea" name="commentText">
|
||||||
|
<Properties>
|
||||||
|
<Property name="columns" type="int" value="20"/>
|
||||||
|
<Property name="rows" type="int" value="5"/>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/actions/Bundle.properties" key="GetTagNameAndCommentDialog.commentText.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/actions/Bundle.properties" key="GetTagNameAndCommentDialog.commentText.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
</SubComponents>
|
||||||
|
</Container>
|
||||||
</SubComponents>
|
</SubComponents>
|
||||||
</Form>
|
</Form>
|
||||||
|
@ -22,9 +22,13 @@ import java.awt.Component;
|
|||||||
import java.awt.Window;
|
import java.awt.Window;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.KeyEvent;
|
import java.awt.event.KeyEvent;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.TreeMap;
|
||||||
import javax.swing.AbstractAction;
|
import javax.swing.AbstractAction;
|
||||||
import javax.swing.ActionMap;
|
import javax.swing.ActionMap;
|
||||||
import javax.swing.DefaultListCellRenderer;
|
import javax.swing.DefaultListCellRenderer;
|
||||||
@ -43,10 +47,15 @@ import org.sleuthkit.datamodel.TagName;
|
|||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
import org.sleuthkit.datamodel.TskData;
|
import org.sleuthkit.datamodel.TskData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This dialog allows tag assignment with a comment attached.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
public class GetTagNameAndCommentDialog extends JDialog {
|
public class GetTagNameAndCommentDialog extends JDialog {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
private final Set<TagName> tagNamesSet = new HashSet<>();
|
private final List<TagName> tagNamesList = new ArrayList<>();
|
||||||
|
private final List<TagName> standardTagNamesList = new ArrayList<>();
|
||||||
private TagNameAndComment tagNameAndComment = null;
|
private TagNameAndComment tagNameAndComment = null;
|
||||||
|
|
||||||
public static class TagNameAndComment {
|
public static class TagNameAndComment {
|
||||||
@ -101,7 +110,7 @@ public class GetTagNameAndCommentDialog extends JDialog {
|
|||||||
|
|
||||||
private GetTagNameAndCommentDialog(Window owner) {
|
private GetTagNameAndCommentDialog(Window owner) {
|
||||||
super(owner,
|
super(owner,
|
||||||
NbBundle.getMessage(GetTagNameAndCommentDialog.class, "GetTagNameAndCommentDialog.createTag"),
|
NbBundle.getMessage(GetTagNameAndCommentDialog.class, "GetTagNameAndCommentDialog.selectTag"),
|
||||||
ModalityType.APPLICATION_MODAL);
|
ModalityType.APPLICATION_MODAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,16 +149,29 @@ public class GetTagNameAndCommentDialog extends JDialog {
|
|||||||
// not exist in the database).
|
// not exist in the database).
|
||||||
try {
|
try {
|
||||||
TagsManager tagsManager = Case.getCurrentCaseThrows().getServices().getTagsManager();
|
TagsManager tagsManager = Case.getCurrentCaseThrows().getServices().getTagsManager();
|
||||||
tagNamesSet.addAll(tagsManager.getAllTagNames());
|
List<String> standardTagNames = TagsManager.getStandardTagNames();
|
||||||
|
Map<String, TagName> tagNamesMap = new TreeMap<>(tagsManager.getDisplayNamesToTagNamesMap());
|
||||||
|
|
||||||
|
tagNamesMap.entrySet().stream().map((entry) -> entry.getValue()).forEachOrdered((tagName) -> {
|
||||||
|
if (standardTagNames.contains(tagName.getDisplayName())) {
|
||||||
|
standardTagNamesList.add(tagName);
|
||||||
|
} else {
|
||||||
|
tagNamesList.add(tagName);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
} catch (TskCoreException | NoCurrentCaseException ex) {
|
} catch (TskCoreException | NoCurrentCaseException ex) {
|
||||||
Logger.getLogger(GetTagNameAndCommentDialog.class
|
Logger.getLogger(GetTagNameAndCommentDialog.class
|
||||||
.getName()).log(Level.SEVERE, "Failed to get tag names", ex); //NON-NLS
|
.getName()).log(Level.SEVERE, "Failed to get tag names", ex); //NON-NLS
|
||||||
}
|
}
|
||||||
for (TagName tag : tagNamesSet) {
|
tagNamesList.forEach((tag) -> {
|
||||||
|
|
||||||
tagCombo.addItem(tag);
|
tagCombo.addItem(tag);
|
||||||
}
|
});
|
||||||
|
|
||||||
|
standardTagNamesList.forEach((tag) -> {
|
||||||
|
tagCombo.addItem(tag);
|
||||||
|
});
|
||||||
|
|
||||||
// Center and show the dialog box.
|
// Center and show the dialog box.
|
||||||
this.setLocationRelativeTo(this.getOwner());
|
this.setLocationRelativeTo(this.getOwner());
|
||||||
@ -170,8 +192,9 @@ public class GetTagNameAndCommentDialog extends JDialog {
|
|||||||
tagCombo = new javax.swing.JComboBox<TagName>();
|
tagCombo = new javax.swing.JComboBox<TagName>();
|
||||||
tagLabel = new javax.swing.JLabel();
|
tagLabel = new javax.swing.JLabel();
|
||||||
commentLabel = new javax.swing.JLabel();
|
commentLabel = new javax.swing.JLabel();
|
||||||
commentText = new javax.swing.JTextField();
|
|
||||||
newTagButton = new javax.swing.JButton();
|
newTagButton = new javax.swing.JButton();
|
||||||
|
jScrollPane1 = new javax.swing.JScrollPane();
|
||||||
|
commentText = new javax.swing.JTextArea();
|
||||||
|
|
||||||
addWindowListener(new java.awt.event.WindowAdapter() {
|
addWindowListener(new java.awt.event.WindowAdapter() {
|
||||||
public void windowClosing(java.awt.event.WindowEvent evt) {
|
public void windowClosing(java.awt.event.WindowEvent evt) {
|
||||||
@ -199,9 +222,6 @@ public class GetTagNameAndCommentDialog extends JDialog {
|
|||||||
|
|
||||||
org.openide.awt.Mnemonics.setLocalizedText(commentLabel, org.openide.util.NbBundle.getMessage(GetTagNameAndCommentDialog.class, "GetTagNameAndCommentDialog.commentLabel.text")); // NOI18N
|
org.openide.awt.Mnemonics.setLocalizedText(commentLabel, org.openide.util.NbBundle.getMessage(GetTagNameAndCommentDialog.class, "GetTagNameAndCommentDialog.commentLabel.text")); // NOI18N
|
||||||
|
|
||||||
commentText.setText(org.openide.util.NbBundle.getMessage(GetTagNameAndCommentDialog.class, "GetTagNameAndCommentDialog.commentText.text")); // NOI18N
|
|
||||||
commentText.setToolTipText(org.openide.util.NbBundle.getMessage(GetTagNameAndCommentDialog.class, "GetTagNameAndCommentDialog.commentText.toolTipText")); // NOI18N
|
|
||||||
|
|
||||||
org.openide.awt.Mnemonics.setLocalizedText(newTagButton, org.openide.util.NbBundle.getMessage(GetTagNameAndCommentDialog.class, "GetTagNameAndCommentDialog.newTagButton.text")); // NOI18N
|
org.openide.awt.Mnemonics.setLocalizedText(newTagButton, org.openide.util.NbBundle.getMessage(GetTagNameAndCommentDialog.class, "GetTagNameAndCommentDialog.newTagButton.text")); // NOI18N
|
||||||
newTagButton.addActionListener(new java.awt.event.ActionListener() {
|
newTagButton.addActionListener(new java.awt.event.ActionListener() {
|
||||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
@ -209,6 +229,12 @@ public class GetTagNameAndCommentDialog extends JDialog {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
commentText.setColumns(20);
|
||||||
|
commentText.setRows(5);
|
||||||
|
commentText.setText(org.openide.util.NbBundle.getMessage(GetTagNameAndCommentDialog.class, "GetTagNameAndCommentDialog.commentText.text")); // NOI18N
|
||||||
|
commentText.setToolTipText(org.openide.util.NbBundle.getMessage(GetTagNameAndCommentDialog.class, "GetTagNameAndCommentDialog.commentText.toolTipText")); // NOI18N
|
||||||
|
jScrollPane1.setViewportView(commentText);
|
||||||
|
|
||||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
|
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
|
||||||
getContentPane().setLayout(layout);
|
getContentPane().setLayout(layout);
|
||||||
layout.setHorizontalGroup(
|
layout.setHorizontalGroup(
|
||||||
@ -218,7 +244,7 @@ public class GetTagNameAndCommentDialog extends JDialog {
|
|||||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||||
.addComponent(newTagButton)
|
.addComponent(newTagButton)
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 165, Short.MAX_VALUE)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||||
.addComponent(okButton, javax.swing.GroupLayout.PREFERRED_SIZE, 67, javax.swing.GroupLayout.PREFERRED_SIZE)
|
.addComponent(okButton, javax.swing.GroupLayout.PREFERRED_SIZE, 67, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addComponent(cancelButton))
|
.addComponent(cancelButton))
|
||||||
@ -228,8 +254,8 @@ public class GetTagNameAndCommentDialog extends JDialog {
|
|||||||
.addComponent(tagLabel))
|
.addComponent(tagLabel))
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addComponent(commentText)
|
.addComponent(tagCombo, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||||
.addComponent(tagCombo, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
|
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 318, Short.MAX_VALUE))))
|
||||||
.addContainerGap())
|
.addContainerGap())
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -243,10 +269,10 @@ public class GetTagNameAndCommentDialog extends JDialog {
|
|||||||
.addComponent(tagCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
.addComponent(tagCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
.addComponent(tagLabel))
|
.addComponent(tagLabel))
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addComponent(commentLabel)
|
.addComponent(commentLabel)
|
||||||
.addComponent(commentText, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 51, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 37, Short.MAX_VALUE)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 22, Short.MAX_VALUE)
|
||||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||||
.addComponent(cancelButton)
|
.addComponent(cancelButton)
|
||||||
.addComponent(okButton)
|
.addComponent(okButton)
|
||||||
@ -278,7 +304,7 @@ public class GetTagNameAndCommentDialog extends JDialog {
|
|||||||
private void newTagButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newTagButtonActionPerformed
|
private void newTagButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newTagButtonActionPerformed
|
||||||
TagName newTagName = GetTagNameDialog.doDialog(this);
|
TagName newTagName = GetTagNameDialog.doDialog(this);
|
||||||
if (newTagName != null) {
|
if (newTagName != null) {
|
||||||
tagNamesSet.add(newTagName);
|
tagNamesList.add(newTagName);
|
||||||
tagCombo.addItem(newTagName);
|
tagCombo.addItem(newTagName);
|
||||||
tagCombo.setSelectedItem(newTagName);
|
tagCombo.setSelectedItem(newTagName);
|
||||||
}
|
}
|
||||||
@ -287,7 +313,8 @@ public class GetTagNameAndCommentDialog extends JDialog {
|
|||||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
private javax.swing.JButton cancelButton;
|
private javax.swing.JButton cancelButton;
|
||||||
private javax.swing.JLabel commentLabel;
|
private javax.swing.JLabel commentLabel;
|
||||||
private javax.swing.JTextField commentText;
|
private javax.swing.JTextArea commentText;
|
||||||
|
private javax.swing.JScrollPane jScrollPane1;
|
||||||
private javax.swing.JButton newTagButton;
|
private javax.swing.JButton newTagButton;
|
||||||
private javax.swing.JButton okButton;
|
private javax.swing.JButton okButton;
|
||||||
private javax.swing.JComboBox<TagName> tagCombo;
|
private javax.swing.JComboBox<TagName> tagCombo;
|
||||||
|
@ -46,8 +46,12 @@ import org.sleuthkit.datamodel.TagName;
|
|||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
import org.sleuthkit.datamodel.TskData;
|
import org.sleuthkit.datamodel.TskData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays existing tag names, and allows the creation of new tags.
|
||||||
|
*/
|
||||||
@Messages({"GetTagNameDialog.descriptionLabel.text=Description:",
|
@Messages({"GetTagNameDialog.descriptionLabel.text=Description:",
|
||||||
"GetTagNameDialog.notableCheckbox.text=Tag indicates item is notable."})
|
"GetTagNameDialog.notableCheckbox.text=Tag indicates item is notable."})
|
||||||
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
public class GetTagNameDialog extends JDialog {
|
public class GetTagNameDialog extends JDialog {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
@ -0,0 +1,127 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 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.actions;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import javafx.application.Platform;
|
||||||
|
import javafx.scene.control.Alert;
|
||||||
|
import javax.swing.SwingWorker;
|
||||||
|
import org.openide.util.NbBundle;
|
||||||
|
import org.openide.util.Utilities;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.services.TagsManager;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
import org.sleuthkit.datamodel.BlackboardArtifactTag;
|
||||||
|
import org.sleuthkit.datamodel.TagName;
|
||||||
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This Action allows users to replace a tag applied to blackboard
|
||||||
|
* artifacts, with another tag
|
||||||
|
*/
|
||||||
|
public final class ReplaceBlackboardArtifactTagAction extends ReplaceTagAction<BlackboardArtifactTag> {
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger(ReplaceBlackboardArtifactTagAction.class.getName());
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
// This class is a singleton to support multi-selection of nodes, since
|
||||||
|
// org.openide.nodes.NodeOp.findActions(Node[] nodes) will only pick up an Action if every
|
||||||
|
// node in the array returns a reference to the same action object from Node.getActions(boolean).
|
||||||
|
private static ReplaceBlackboardArtifactTagAction instance;
|
||||||
|
|
||||||
|
public static synchronized ReplaceBlackboardArtifactTagAction getInstance() {
|
||||||
|
if (null == instance) {
|
||||||
|
instance = new ReplaceBlackboardArtifactTagAction();
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ReplaceBlackboardArtifactTagAction() {
|
||||||
|
super(MENU_TEXT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces the specified tag on the given artifact with the new one
|
||||||
|
*
|
||||||
|
* @param oldArtifactTag tag to be replaced
|
||||||
|
* @param newTagName name of the tag to replace with
|
||||||
|
* @param newComment the newComment for the tag use an empty string for no newComment
|
||||||
|
*/
|
||||||
|
@NbBundle.Messages({
|
||||||
|
"# {0} - old tag name",
|
||||||
|
"# {1} - artifactID",
|
||||||
|
"ReplaceBlackboardArtifactTagAction.replaceTag.alert=Unable to replace tag {0} for artifact {1}."})
|
||||||
|
@Override
|
||||||
|
protected void replaceTag( BlackboardArtifactTag oldArtifactTag, TagName newTagName, String newComment) {
|
||||||
|
new SwingWorker<Void, Void>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground() throws Exception {
|
||||||
|
TagsManager tagsManager;
|
||||||
|
try {
|
||||||
|
tagsManager = Case.getCurrentCaseThrows().getServices().getTagsManager();
|
||||||
|
} catch (NoCurrentCaseException ex) {
|
||||||
|
logger.log(Level.SEVERE, "Error replacing artifact tag. No open case found.", ex); //NON-NLS
|
||||||
|
Platform.runLater(()
|
||||||
|
-> new Alert(Alert.AlertType.ERROR, Bundle.ReplaceBlackboardArtifactTagAction_replaceTag_alert(oldArtifactTag.getName().getDisplayName(), oldArtifactTag.getArtifact().getArtifactID())).show()
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
logger.log(Level.INFO, "Replacing tag {0} with tag {1} for artifact {2}", new Object[]{oldArtifactTag.getName().getDisplayName(), newTagName.getDisplayName(), oldArtifactTag.getContent().getName()}); //NON-NLS
|
||||||
|
|
||||||
|
tagsManager.deleteBlackboardArtifactTag(oldArtifactTag);
|
||||||
|
tagsManager.addBlackboardArtifactTag(oldArtifactTag.getArtifact(), newTagName, newComment);
|
||||||
|
|
||||||
|
} catch (TskCoreException tskCoreException) {
|
||||||
|
logger.log(Level.SEVERE, "Error replacing artifact tag", tskCoreException); //NON-NLS
|
||||||
|
Platform.runLater(()
|
||||||
|
-> new Alert(Alert.AlertType.ERROR, Bundle.ReplaceBlackboardArtifactTagAction_replaceTag_alert(oldArtifactTag.getName().getDisplayName(), oldArtifactTag.getArtifact().getArtifactID())).show()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void done() {
|
||||||
|
super.done();
|
||||||
|
try {
|
||||||
|
get();
|
||||||
|
} catch (InterruptedException | ExecutionException ex) {
|
||||||
|
logger.log(Level.SEVERE, "Unexpected exception while replacing artifact tag", ex); //NON-NLS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns list of tags selected by user to replace
|
||||||
|
*
|
||||||
|
* @return a list of tags
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
Collection<? extends BlackboardArtifactTag> getTagsToReplace() {
|
||||||
|
return Utilities.actionsGlobalContext().lookupAll(BlackboardArtifactTag.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,120 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 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.actions;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import javafx.application.Platform;
|
||||||
|
import javafx.scene.control.Alert;
|
||||||
|
import javax.swing.SwingWorker;
|
||||||
|
import org.openide.util.NbBundle;
|
||||||
|
import org.openide.util.Utilities;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.services.TagsManager;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
import org.sleuthkit.datamodel.ContentTag;
|
||||||
|
import org.sleuthkit.datamodel.TagName;
|
||||||
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This Action allow users to replace a content tag with another tag
|
||||||
|
*/
|
||||||
|
public final class ReplaceContentTagAction extends ReplaceTagAction<ContentTag> {
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger(ReplaceContentTagAction.class.getName());
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
// This class is a singleton to support multi-selection of nodes, since
|
||||||
|
// org.openide.nodes.NodeOp.findActions(Node[] nodes) will only pick up an Action if every
|
||||||
|
// node in the array returns a reference to the same action object from Node.getActions(boolean).
|
||||||
|
private static ReplaceContentTagAction instance;
|
||||||
|
|
||||||
|
public static synchronized ReplaceContentTagAction getInstance() {
|
||||||
|
if (null == instance) {
|
||||||
|
instance = new ReplaceContentTagAction();
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ReplaceContentTagAction() {
|
||||||
|
super(MENU_TEXT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NbBundle.Messages({
|
||||||
|
"# {0} - old tag name",
|
||||||
|
"# {1} - content obj id",
|
||||||
|
"ReplaceContentTagAction.replaceTag.alert=Unable to replace tag {0} for {1}."})
|
||||||
|
@Override
|
||||||
|
protected void replaceTag(ContentTag oldTag, TagName newTagName, String newComment) {
|
||||||
|
new SwingWorker<Void, Void>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground() throws Exception {
|
||||||
|
TagsManager tagsManager;
|
||||||
|
try {
|
||||||
|
tagsManager = Case.getCurrentCaseThrows().getServices().getTagsManager();
|
||||||
|
} catch (NoCurrentCaseException ex) {
|
||||||
|
logger.log(Level.SEVERE, "Error replacing artifact tag. No open case found.", ex); //NON-NLS
|
||||||
|
Platform.runLater(()
|
||||||
|
-> new Alert(Alert.AlertType.ERROR, Bundle.ReplaceContentTagAction_replaceTag_alert(oldTag.getName().getDisplayName(), oldTag.getContent().getName())).show()
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
logger.log(Level.INFO, "Replacing tag {0} with tag {1} for artifact {2}", new Object[]{oldTag.getName().getDisplayName(), newTagName.getDisplayName(), oldTag.getContent().getName()}); //NON-NLS
|
||||||
|
|
||||||
|
tagsManager.deleteContentTag(oldTag);
|
||||||
|
tagsManager.addContentTag(oldTag.getContent(), newTagName, newComment);
|
||||||
|
|
||||||
|
} catch (TskCoreException tskCoreException) {
|
||||||
|
logger.log(Level.SEVERE, "Error replacing artifact tag", tskCoreException); //NON-NLS
|
||||||
|
Platform.runLater(()
|
||||||
|
-> new Alert(Alert.AlertType.ERROR, Bundle.ReplaceContentTagAction_replaceTag_alert(oldTag.getName().getDisplayName(), oldTag.getContent().getName())).show()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void done() {
|
||||||
|
super.done();
|
||||||
|
try {
|
||||||
|
get();
|
||||||
|
} catch (InterruptedException | ExecutionException ex) {
|
||||||
|
logger.log(Level.SEVERE, "Unexpected exception while replacing content tag", ex); //NON-NLS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns list of content tags selected by user to replace
|
||||||
|
*
|
||||||
|
* @return a list of tags
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
Collection<? extends ContentTag> getTagsToReplace() {
|
||||||
|
return Utilities.actionsGlobalContext().lookupAll(ContentTag.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
201
Core/src/org/sleuthkit/autopsy/actions/ReplaceTagAction.java
Normal file
201
Core/src/org/sleuthkit/autopsy/actions/ReplaceTagAction.java
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 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.actions;
|
||||||
|
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import javax.swing.AbstractAction;
|
||||||
|
import javax.swing.JMenu;
|
||||||
|
import javax.swing.JMenuItem;
|
||||||
|
import org.openide.util.NbBundle;
|
||||||
|
import org.openide.util.actions.Presenter;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.services.TagsManager;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
import org.sleuthkit.datamodel.Tag;
|
||||||
|
import org.sleuthkit.datamodel.TagName;
|
||||||
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
import org.sleuthkit.datamodel.TskData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract class to define context action to replace a tag with another
|
||||||
|
*
|
||||||
|
* @param <T> tag type
|
||||||
|
*/
|
||||||
|
@NbBundle.Messages({
|
||||||
|
"ReplaceTagAction.replaceTag=Replace Selected Tag(s) With"
|
||||||
|
})
|
||||||
|
abstract class ReplaceTagAction<T extends Tag> extends AbstractAction implements Presenter.Popup {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
protected static final String MENU_TEXT = NbBundle.getMessage(ReplaceTagAction.class,
|
||||||
|
"ReplaceTagAction.replaceTag");
|
||||||
|
|
||||||
|
ReplaceTagAction(String menuText) {
|
||||||
|
super(menuText);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subclasses of replaceTagAction should not override actionPerformed,
|
||||||
|
* but instead override replaceTag.
|
||||||
|
*
|
||||||
|
* @param event
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("NoopMethodInAbstractClass")
|
||||||
|
public void actionPerformed(ActionEvent event) {
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getActionDisplayName() {
|
||||||
|
return MENU_TEXT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to actually replace the selected tag with the given new tag
|
||||||
|
*
|
||||||
|
* @param oldTag - the TagName which is being removed from the item
|
||||||
|
* @param newTagName - the TagName which is being added to the itme
|
||||||
|
* @param comment the comment associated with the tag, empty string for no comment
|
||||||
|
*/
|
||||||
|
abstract protected void replaceTag(T oldTag, TagName newTagName, String comment);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns elected tags which are to be replaced
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
abstract Collection<? extends T> getTagsToReplace();
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JMenuItem getPopupPresenter() {
|
||||||
|
return new ReplaceTagMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instances of this class implement a context menu user interface for
|
||||||
|
* selecting a tag name to replace the tag with
|
||||||
|
*/
|
||||||
|
private final class ReplaceTagMenu extends JMenu {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
ReplaceTagMenu() {
|
||||||
|
super(getActionDisplayName());
|
||||||
|
|
||||||
|
final Collection<? extends T> selectedTags = getTagsToReplace();
|
||||||
|
|
||||||
|
// Get the current set of tag names.
|
||||||
|
Map<String, TagName> tagNamesMap = null;
|
||||||
|
List<String> standardTagNames = TagsManager.getStandardTagNames();
|
||||||
|
try {
|
||||||
|
TagsManager tagsManager = Case.getCurrentCaseThrows().getServices().getTagsManager();
|
||||||
|
tagNamesMap = new TreeMap<>(tagsManager.getDisplayNamesToTagNamesMap());
|
||||||
|
} catch (TskCoreException | NoCurrentCaseException ex) {
|
||||||
|
Logger.getLogger(ReplaceTagMenu.class.getName()).log(Level.SEVERE, "Failed to get tag names", ex); //NON-NLS
|
||||||
|
}
|
||||||
|
|
||||||
|
List<JMenuItem> standardTagMenuitems = new ArrayList<>();
|
||||||
|
// Ideally we should'nt allow user to pick a replacement tag that's already been applied to an item
|
||||||
|
// In the very least we don't allow them to pick the same tag as the one they are trying to replace
|
||||||
|
Set<String> existingTagNames = new HashSet<>();
|
||||||
|
if (!selectedTags.isEmpty()) {
|
||||||
|
T firstTag = selectedTags.iterator().next();
|
||||||
|
existingTagNames.add(firstTag.getName().getDisplayName());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null != tagNamesMap && !tagNamesMap.isEmpty()) {
|
||||||
|
for (Map.Entry<String, TagName> entry : tagNamesMap.entrySet()) {
|
||||||
|
String tagDisplayName = entry.getKey();
|
||||||
|
String notableString = entry.getValue().getKnownStatus() == TskData.FileKnown.BAD ? TagsManager.getNotableTagLabel() : "";
|
||||||
|
JMenuItem tagNameItem = new JMenuItem(tagDisplayName + notableString);
|
||||||
|
// for the bookmark tag name only, added shortcut label
|
||||||
|
if (tagDisplayName.equals(NbBundle.getMessage(AddTagAction.class, "AddBookmarkTagAction.bookmark.text"))) {
|
||||||
|
tagNameItem.setAccelerator(AddBookmarkTagAction.BOOKMARK_SHORTCUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add action to replace the tag
|
||||||
|
tagNameItem.addActionListener((ActionEvent event) -> {
|
||||||
|
selectedTags.forEach((oldtag) -> {
|
||||||
|
replaceTag(oldtag, entry.getValue(), oldtag.getComment());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Don't allow replacing a tag with same tag.
|
||||||
|
if (existingTagNames.contains(tagDisplayName)) {
|
||||||
|
tagNameItem.setEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Show custom tags before predefined tags in the menu
|
||||||
|
if (standardTagNames.contains(tagDisplayName)) {
|
||||||
|
standardTagMenuitems.add(tagNameItem);
|
||||||
|
} else {
|
||||||
|
add(tagNameItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
JMenuItem empty = new JMenuItem(NbBundle.getMessage(this.getClass(), "AddTagAction.noTags"));
|
||||||
|
empty.setEnabled(false);
|
||||||
|
add(empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
if (this.getItemCount() > 0) {
|
||||||
|
addSeparator();
|
||||||
|
}
|
||||||
|
standardTagMenuitems.forEach((menuItem) -> {
|
||||||
|
add(menuItem);
|
||||||
|
});
|
||||||
|
|
||||||
|
addSeparator();
|
||||||
|
JMenuItem newTagMenuItem = new JMenuItem(NbBundle.getMessage(this.getClass(), "AddTagAction.newTag"));
|
||||||
|
newTagMenuItem.addActionListener((ActionEvent event) -> {
|
||||||
|
TagName newTagName = GetTagNameDialog.doDialog();
|
||||||
|
if (null != newTagName) {
|
||||||
|
selectedTags.forEach((oldtag) -> {
|
||||||
|
replaceTag(oldtag, newTagName, oldtag.getComment());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
add(newTagMenuItem);
|
||||||
|
// Create a "Choose Tag and Comment..." menu item. Selecting this item initiates
|
||||||
|
// a dialog that can be used to create or select a tag name with an
|
||||||
|
// optional comment and adds a tag with the resulting name.
|
||||||
|
JMenuItem tagAndCommentItem = new JMenuItem(NbBundle.getMessage(this.getClass(), "AddTagAction.tagAndComment"));
|
||||||
|
tagAndCommentItem.addActionListener((ActionEvent event) -> {
|
||||||
|
GetTagNameAndCommentDialog.TagNameAndComment tagNameAndComment = GetTagNameAndCommentDialog.doDialog();
|
||||||
|
if (null != tagNameAndComment) {
|
||||||
|
selectedTags.forEach((oldtag) -> {
|
||||||
|
replaceTag(oldtag, tagNameAndComment.getTagName(), tagNameAndComment.getComment());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
add(tagAndCommentItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011 Basis Technology Corp.
|
* Copyright 2011-2018 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -18,15 +18,22 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.casemodule;
|
package org.sleuthkit.autopsy.casemodule;
|
||||||
|
|
||||||
|
import java.awt.Frame;
|
||||||
|
import javax.swing.JDialog;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dialog to show add image error messages
|
* Dialog to show add image error messages
|
||||||
*/
|
*/
|
||||||
public class AddImageErrorsDialog extends javax.swing.JDialog {
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
|
public class AddImageErrorsDialog extends JDialog {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates new form AddImageErrorsDialog
|
* Creates new form AddImageErrorsDialog
|
||||||
|
*
|
||||||
|
* @param parent The parent frame.
|
||||||
|
* @param modal Does this dialog act as a modal?
|
||||||
*/
|
*/
|
||||||
public AddImageErrorsDialog(java.awt.Frame parent, boolean modal) {
|
public AddImageErrorsDialog(Frame parent, boolean modal) {
|
||||||
super(parent, modal);
|
super(parent, modal);
|
||||||
initComponents();
|
initComponents();
|
||||||
}
|
}
|
||||||
|
@ -57,6 +57,7 @@ import org.sleuthkit.autopsy.coreutils.Logger;
|
|||||||
* {@link AddImageWizardIngestConfigPanel} (which is a bit weird if you ask m
|
* {@link AddImageWizardIngestConfigPanel} (which is a bit weird if you ask m
|
||||||
* -jm)
|
* -jm)
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
class AddImageWizardAddingProgressPanel extends ShortcutWizardDescriptorPanel {
|
class AddImageWizardAddingProgressPanel extends ShortcutWizardDescriptorPanel {
|
||||||
|
|
||||||
private boolean readyToIngest = false;
|
private boolean readyToIngest = false;
|
||||||
@ -79,7 +80,7 @@ class AddImageWizardAddingProgressPanel extends ShortcutWizardDescriptorPanel {
|
|||||||
*/
|
*/
|
||||||
private AddImageWizardAddingProgressVisual component;
|
private AddImageWizardAddingProgressVisual component;
|
||||||
private final Set<ChangeListener> listeners = new HashSet<>(1); // or can use ChangeSupport in NB 6.0
|
private final Set<ChangeListener> listeners = new HashSet<>(1); // or can use ChangeSupport in NB 6.0
|
||||||
private final List<Content> newContents = Collections.synchronizedList(new ArrayList<Content>());
|
private final List<Content> newContents = Collections.synchronizedList(new ArrayList<>());
|
||||||
private final DSPProgressMonitorImpl dspProgressMonitorImpl = new DSPProgressMonitorImpl();
|
private final DSPProgressMonitorImpl dspProgressMonitorImpl = new DSPProgressMonitorImpl();
|
||||||
private IngestJobSettings ingestJobSettings;
|
private IngestJobSettings ingestJobSettings;
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2012 Basis Technology Corp.
|
* Copyright 2012-2018 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -19,16 +19,14 @@
|
|||||||
package org.sleuthkit.autopsy.casemodule;
|
package org.sleuthkit.autopsy.casemodule;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.event.ActionEvent;
|
|
||||||
import java.awt.event.ActionListener;
|
|
||||||
import javax.swing.JProgressBar;
|
import javax.swing.JProgressBar;
|
||||||
import org.openide.WizardDescriptor;
|
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* visual component to display progress bar and status updates while adding an
|
* visual component to display progress bar and status updates while adding an
|
||||||
* image in the wizard
|
* image in the wizard
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
class AddImageWizardAddingProgressVisual extends javax.swing.JPanel {
|
class AddImageWizardAddingProgressVisual extends javax.swing.JPanel {
|
||||||
|
|
||||||
private static final String ADDING_DATA_SOURCE_COMPLETE = NbBundle
|
private static final String ADDING_DATA_SOURCE_COMPLETE = NbBundle
|
||||||
|
@ -39,6 +39,7 @@ import org.sleuthkit.autopsy.ingest.runIngestModuleWizard.ShortcutWizardDescript
|
|||||||
* The "Add Image" wizard panel1 handling the logic of selecting image file(s)
|
* The "Add Image" wizard panel1 handling the logic of selecting image file(s)
|
||||||
* to add to Case, and pick the time zone.
|
* to add to Case, and pick the time zone.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
class AddImageWizardDataSourceSettingsPanel extends ShortcutWizardDescriptorPanel implements PropertyChangeListener {
|
class AddImageWizardDataSourceSettingsPanel extends ShortcutWizardDescriptorPanel implements PropertyChangeListener {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011-2017 Basis Technology Corp.
|
* Copyright 2011-2018 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -37,8 +37,8 @@ import org.sleuthkit.autopsy.coreutils.Logger;
|
|||||||
/**
|
/**
|
||||||
* visual component for the first panel of add image wizard. Allows the user to
|
* visual component for the first panel of add image wizard. Allows the user to
|
||||||
* choose the data source type and then select the data source
|
* choose the data source type and then select the data source
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
final class AddImageWizardDataSourceSettingsVisual extends JPanel {
|
final class AddImageWizardDataSourceSettingsVisual extends JPanel {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(AddImageWizardDataSourceSettingsVisual.class.getName());
|
private static final Logger logger = Logger.getLogger(AddImageWizardDataSourceSettingsVisual.class.getName());
|
||||||
|
@ -40,10 +40,11 @@ import org.sleuthkit.autopsy.ingest.runIngestModuleWizard.ShortcutWizardDescript
|
|||||||
* TODO: review this for dead code. think about moving logic of adding image to
|
* TODO: review this for dead code. think about moving logic of adding image to
|
||||||
* 3rd panel( {@link AddImageWizardAddingProgressPanel}) separate class -jm
|
* 3rd panel( {@link AddImageWizardAddingProgressPanel}) separate class -jm
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
class AddImageWizardIngestConfigPanel extends ShortcutWizardDescriptorPanel {
|
class AddImageWizardIngestConfigPanel extends ShortcutWizardDescriptorPanel {
|
||||||
|
|
||||||
@Messages("AddImageWizardIngestConfigPanel.name.text=Configure Ingest Modules")
|
@Messages("AddImageWizardIngestConfigPanel.name.text=Configure Ingest Modules")
|
||||||
private IngestJobSettingsPanel ingestJobSettingsPanel;
|
private final IngestJobSettingsPanel ingestJobSettingsPanel;
|
||||||
/**
|
/**
|
||||||
* The visual component that displays this panel. If you need to access the
|
* The visual component that displays this panel. If you need to access the
|
||||||
* component from this class, just use getComponent().
|
* component from this class, just use getComponent().
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011-2014 Basis Technology Corp.
|
* Copyright 2011-2018 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -25,8 +25,8 @@ import javax.swing.JPanel;
|
|||||||
/**
|
/**
|
||||||
* UI panel for the ingest job configuration wizard panel of the add data source
|
* UI panel for the ingest job configuration wizard panel of the add data source
|
||||||
* wizard.
|
* wizard.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
class AddImageWizardIngestConfigVisual extends JPanel {
|
class AddImageWizardIngestConfigVisual extends JPanel {
|
||||||
|
|
||||||
private final JPanel ingestPanel;
|
private final JPanel ingestPanel;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011-2017 Basis Technology Corp.
|
* Copyright 2011-2018 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -36,6 +36,7 @@ import org.sleuthkit.autopsy.ingest.runIngestModuleWizard.ShortcutWizardDescript
|
|||||||
* Create a wizard panel which contains a panel allowing the selection of the
|
* Create a wizard panel which contains a panel allowing the selection of the
|
||||||
* DataSourceProcessor
|
* DataSourceProcessor
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
final class AddImageWizardSelectDspPanel extends ShortcutWizardDescriptorPanel implements PropertyChangeListener {
|
final class AddImageWizardSelectDspPanel extends ShortcutWizardDescriptorPanel implements PropertyChangeListener {
|
||||||
|
|
||||||
@NbBundle.Messages("SelectDataSourceProcessorPanel.name.text=Select Type of Data Source To Add")
|
@NbBundle.Messages("SelectDataSourceProcessorPanel.name.text=Select Type of Data Source To Add")
|
||||||
|
@ -36,6 +36,7 @@ import javax.swing.Box.Filler;
|
|||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JTextArea;
|
import javax.swing.JTextArea;
|
||||||
import javax.swing.JToggleButton;
|
import javax.swing.JToggleButton;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
import org.openide.util.Lookup;
|
import org.openide.util.Lookup;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
|
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
|
||||||
@ -46,6 +47,7 @@ import org.sleuthkit.autopsy.coreutils.Logger;
|
|||||||
* Panel which displays the available DataSourceProcessors and allows selection
|
* Panel which displays the available DataSourceProcessors and allows selection
|
||||||
* of one
|
* of one
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
final class AddImageWizardSelectDspVisual extends JPanel {
|
final class AddImageWizardSelectDspVisual extends JPanel {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(AddImageWizardSelectDspVisual.class.getName());
|
private static final Logger logger = Logger.getLogger(AddImageWizardSelectDspVisual.class.getName());
|
||||||
@ -171,6 +173,9 @@ final class AddImageWizardSelectDspVisual extends JPanel {
|
|||||||
constraints.weighty = 1;
|
constraints.weighty = 1;
|
||||||
gridBagLayout.setConstraints(vertGlue, constraints);
|
gridBagLayout.setConstraints(vertGlue, constraints);
|
||||||
jPanel1.setLayout(gridBagLayout);
|
jPanel1.setLayout(gridBagLayout);
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
jScrollPane1.getVerticalScrollBar().setValue(0);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -132,6 +132,7 @@ public class Case {
|
|||||||
private static final String EXPORT_FOLDER = "Export"; //NON-NLS
|
private static final String EXPORT_FOLDER = "Export"; //NON-NLS
|
||||||
private static final String LOG_FOLDER = "Log"; //NON-NLS
|
private static final String LOG_FOLDER = "Log"; //NON-NLS
|
||||||
private static final String REPORTS_FOLDER = "Reports"; //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 TEMP_FOLDER = "Temp"; //NON-NLS
|
||||||
private static final String MODULE_FOLDER = "ModuleOutput"; //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_ACTION_THREAD_NAME = "%s-case-action";
|
||||||
@ -295,9 +296,10 @@ public class Case {
|
|||||||
*/
|
*/
|
||||||
ADDING_DATA_SOURCE_FAILED,
|
ADDING_DATA_SOURCE_FAILED,
|
||||||
/**
|
/**
|
||||||
* A new data source has been added to the current case. The old value
|
* A new data source or series of data sources have been added to the
|
||||||
* of the PropertyChangeEvent is null, the new value is the newly-added
|
* current case. The old value of the PropertyChangeEvent is null, the
|
||||||
* data source (type: Content). Cast the PropertyChangeEvent to
|
* new value is the newly-added data source (type: Content). Cast the
|
||||||
|
* PropertyChangeEvent to
|
||||||
* org.sleuthkit.autopsy.casemodule.events.DataSourceAddedEvent to
|
* org.sleuthkit.autopsy.casemodule.events.DataSourceAddedEvent to
|
||||||
* access additional event data.
|
* access additional event data.
|
||||||
*/
|
*/
|
||||||
@ -1115,6 +1117,10 @@ public class Case {
|
|||||||
/*
|
/*
|
||||||
* Open the top components (windows within the main application
|
* Open the top components (windows within the main application
|
||||||
* window).
|
* window).
|
||||||
|
*
|
||||||
|
* Note: If the core windows are not opened here, they will be
|
||||||
|
* opened via the DirectoryTreeTopComponent 'propertyChange()'
|
||||||
|
* method on a DATA_SOURCE_ADDED event.
|
||||||
*/
|
*/
|
||||||
if (newCurrentCase.hasData()) {
|
if (newCurrentCase.hasData()) {
|
||||||
CoreComponentControl.openCoreWindows();
|
CoreComponentControl.openCoreWindows();
|
||||||
@ -1368,6 +1374,16 @@ public class Case {
|
|||||||
return getOrCreateSubdirectory(REPORTS_FOLDER);
|
return getOrCreateSubdirectory(REPORTS_FOLDER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the full path to the config directory for this case, creating it if
|
||||||
|
* it does not exist.
|
||||||
|
*
|
||||||
|
* @return The config directory path.
|
||||||
|
*/
|
||||||
|
public String getConfigDirectory() {
|
||||||
|
return getOrCreateSubdirectory(CONFIG_FOLDER);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the full path to the module output directory for this case, creating
|
* Gets the full path to the module output directory for this case, creating
|
||||||
* it if it does not exist.
|
* it if it does not exist.
|
||||||
|
@ -49,8 +49,8 @@ import org.sleuthkit.autopsy.datamodel.EmptyNode;
|
|||||||
*
|
*
|
||||||
* Used to display a list of multi user cases and allow the user to open one of
|
* Used to display a list of multi user cases and allow the user to open one of
|
||||||
* them.
|
* them.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
class CaseBrowser extends javax.swing.JPanel implements ExplorerManager.Provider {
|
class CaseBrowser extends javax.swing.JPanel implements ExplorerManager.Provider {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011-2017 Basis Technology Corp.
|
* Copyright 2011-2018 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -32,6 +32,7 @@ import org.openide.windows.WindowManager;
|
|||||||
* Panel for displaying the case information, including both case details and
|
* Panel for displaying the case information, including both case details and
|
||||||
* ingest job history.
|
* ingest job history.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
class CaseInformationPanel extends javax.swing.JPanel {
|
class CaseInformationPanel extends javax.swing.JPanel {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011-2017 Basis Technology Corp.
|
* Copyright 2011-2018 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -31,10 +31,11 @@ import org.sleuthkit.autopsy.coreutils.Logger;
|
|||||||
* A panel that allows the user to view various properties of a case and change
|
* A panel that allows the user to view various properties of a case and change
|
||||||
* the display name of the case.
|
* the display name of the case.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
final class CasePropertiesPanel extends javax.swing.JPanel {
|
final class CasePropertiesPanel extends javax.swing.JPanel {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
private static final Logger LOGGER = Logger.getLogger(CasePropertiesPanel.class.getName());
|
private static final Logger logger = Logger.getLogger(CasePropertiesPanel.class.getName());
|
||||||
private Case theCase;
|
private Case theCase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -52,7 +53,7 @@ final class CasePropertiesPanel extends javax.swing.JPanel {
|
|||||||
try {
|
try {
|
||||||
theCase = Case.getCurrentCaseThrows();
|
theCase = Case.getCurrentCaseThrows();
|
||||||
} catch (NoCurrentCaseException ex) {
|
} catch (NoCurrentCaseException ex) {
|
||||||
LOGGER.log(Level.SEVERE, "Exception while getting open case.", ex);
|
logger.log(Level.SEVERE, "Exception while getting open case.", ex);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
lbCaseNameText.setText(theCase.getDisplayName());
|
lbCaseNameText.setText(theCase.getDisplayName());
|
||||||
@ -90,7 +91,7 @@ final class CasePropertiesPanel extends javax.swing.JPanel {
|
|||||||
currentOrg = correlationCase.getOrg();
|
currentOrg = correlationCase.getOrg();
|
||||||
}
|
}
|
||||||
} catch (EamDbException ex) {
|
} catch (EamDbException ex) {
|
||||||
LOGGER.log(Level.SEVERE, "Unable to access Correlation Case when Central Repo is enabled", ex);
|
logger.log(Level.SEVERE, "Unable to access Correlation Case when Central Repo is enabled", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (currentOrg != null) {
|
if (currentOrg != null) {
|
||||||
|
@ -35,6 +35,7 @@ import org.openide.windows.WindowManager;
|
|||||||
/*
|
/*
|
||||||
* The panel in the default Autopsy startup window.
|
* The panel in the default Autopsy startup window.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
public class CueBannerPanel extends javax.swing.JPanel {
|
public class CueBannerPanel extends javax.swing.JPanel {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011-2017 Basis Technology Corp.
|
* Copyright 2011-2018 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -22,9 +22,9 @@ import java.awt.event.ActionListener;
|
|||||||
import org.openide.util.NbBundle.Messages;
|
import org.openide.util.NbBundle.Messages;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Panel to allow examiner to edit option case properties.
|
||||||
* @author wschaefer
|
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
class EditOptionalCasePropertiesPanel extends javax.swing.JPanel {
|
class EditOptionalCasePropertiesPanel extends javax.swing.JPanel {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
@ -31,7 +31,6 @@ import javax.swing.event.DocumentEvent;
|
|||||||
import javax.swing.event.DocumentListener;
|
import javax.swing.event.DocumentListener;
|
||||||
import javax.swing.filechooser.FileFilter;
|
import javax.swing.filechooser.FileFilter;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.openide.util.Exceptions;
|
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import static org.sleuthkit.autopsy.casemodule.Bundle.*;
|
import static org.sleuthkit.autopsy.casemodule.Bundle.*;
|
||||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
|
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
|
||||||
@ -46,6 +45,7 @@ import org.sleuthkit.autopsy.coreutils.PathValidator;
|
|||||||
* to select a file as well as choose the timezone and whether to ignore orphan
|
* to select a file as well as choose the timezone and whether to ignore orphan
|
||||||
* files in FAT32.
|
* files in FAT32.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
public class ImageFilePanel extends JPanel implements DocumentListener {
|
public class ImageFilePanel extends JPanel implements DocumentListener {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(ImageFilePanel.class.getName());
|
private static final Logger logger = Logger.getLogger(ImageFilePanel.class.getName());
|
||||||
|
@ -39,6 +39,7 @@ import org.sleuthkit.datamodel.TskCoreException;
|
|||||||
/**
|
/**
|
||||||
* Panel for displaying ingest job history.
|
* Panel for displaying ingest job history.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
public final class IngestJobInfoPanel extends javax.swing.JPanel {
|
public final class IngestJobInfoPanel extends javax.swing.JPanel {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(IngestJobInfoPanel.class.getName());
|
private static final Logger logger = Logger.getLogger(IngestJobInfoPanel.class.getName());
|
||||||
@ -91,7 +92,7 @@ public final class IngestJobInfoPanel extends javax.swing.JPanel {
|
|||||||
"IngestJobInfoPanel.IngestJobTableModel.IngestStatus.header=Ingest Status"})
|
"IngestJobInfoPanel.IngestJobTableModel.IngestStatus.header=Ingest Status"})
|
||||||
private class IngestJobTableModel extends AbstractTableModel {
|
private class IngestJobTableModel extends AbstractTableModel {
|
||||||
|
|
||||||
private List<String> columnHeaders = new ArrayList<>();
|
private final List<String> columnHeaders = new ArrayList<>();
|
||||||
|
|
||||||
IngestJobTableModel() {
|
IngestJobTableModel() {
|
||||||
columnHeaders.add(Bundle.IngestJobInfoPanel_IngestJobTableModel_DataSource_header());
|
columnHeaders.add(Bundle.IngestJobInfoPanel_IngestJobTableModel_DataSource_header());
|
||||||
@ -146,8 +147,8 @@ public final class IngestJobInfoPanel extends javax.swing.JPanel {
|
|||||||
"IngestJobInfoPanel.IngestModuleTableModel.ModuleVersion.header=Module Version"})
|
"IngestJobInfoPanel.IngestModuleTableModel.ModuleVersion.header=Module Version"})
|
||||||
private class IngestModuleTableModel extends AbstractTableModel {
|
private class IngestModuleTableModel extends AbstractTableModel {
|
||||||
|
|
||||||
private List<String> columnHeaders = new ArrayList<>();
|
private final List<String> columnHeaders = new ArrayList<>();
|
||||||
private IngestJobInfo currJob;
|
private final IngestJobInfo currJob;
|
||||||
|
|
||||||
IngestModuleTableModel(IngestJobInfo currJob) {
|
IngestModuleTableModel(IngestJobInfo currJob) {
|
||||||
columnHeaders.add(Bundle.IngestJobInfoPanel_IngestModuleTableModel_ModuleName_header());
|
columnHeaders.add(Bundle.IngestJobInfoPanel_IngestModuleTableModel_ModuleName_header());
|
||||||
|
@ -34,6 +34,10 @@ import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
|||||||
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
|
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
|
||||||
import org.sleuthkit.autopsy.imagewriter.ImageWriterSettings;
|
import org.sleuthkit.autopsy.imagewriter.ImageWriterSettings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ImageTypePanel for adding a local disk or partition such as PhysicalDrive0 or
|
||||||
|
* C:.
|
||||||
|
*/
|
||||||
@NbBundle.Messages({
|
@NbBundle.Messages({
|
||||||
"LocalDiskPanel.errorMessage.noOpenCaseTitle=No open case available",
|
"LocalDiskPanel.errorMessage.noOpenCaseTitle=No open case available",
|
||||||
"LocalDiskPanel.errorMessage.noOpenCaseBody=LocalDiskPanel listener couldn't get the open case.",
|
"LocalDiskPanel.errorMessage.noOpenCaseBody=LocalDiskPanel listener couldn't get the open case.",
|
||||||
@ -45,10 +49,7 @@ import org.sleuthkit.autopsy.imagewriter.ImageWriterSettings;
|
|||||||
"LocalDiskPanel.moduleErrorMessage.body=A module caused an error listening to LocalDiskPanel updates. See log to determine which module. Some data could be incomplete.",
|
"LocalDiskPanel.moduleErrorMessage.body=A module caused an error listening to LocalDiskPanel updates. See log to determine which module. Some data could be incomplete.",
|
||||||
"LocalDiskPanel.localDiskMessage.unspecified=Unspecified"
|
"LocalDiskPanel.localDiskMessage.unspecified=Unspecified"
|
||||||
})
|
})
|
||||||
/**
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
* ImageTypePanel for adding a local disk or partition such as PhysicalDrive0 or
|
|
||||||
* C:.
|
|
||||||
*/
|
|
||||||
final class LocalDiskPanel extends JPanel {
|
final class LocalDiskPanel extends JPanel {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(LocalDiskPanel.class.getName());
|
private static final Logger logger = Logger.getLogger(LocalDiskPanel.class.getName());
|
||||||
|
@ -35,6 +35,7 @@ import org.sleuthkit.autopsy.coreutils.PathValidator;
|
|||||||
/**
|
/**
|
||||||
* A panel which allows the user to select local files and/or directories.
|
* A panel which allows the user to select local files and/or directories.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
final class LocalFilesPanel extends javax.swing.JPanel {
|
final class LocalFilesPanel extends javax.swing.JPanel {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
@ -278,7 +279,10 @@ final class LocalFilesPanel extends javax.swing.JPanel {
|
|||||||
*
|
*
|
||||||
* @param paths Absolute paths to the selected data source
|
* @param paths Absolute paths to the selected data source
|
||||||
*/
|
*/
|
||||||
@NbBundle.Messages("LocalFilesPanel.pathValidation.error=WARNING: Exception while gettting opon case.")
|
@NbBundle.Messages({
|
||||||
|
"LocalFilesPanel.pathValidation.dataSourceOnCDriveError=Warning: Path to multi-user data source is on \"C:\" drive",
|
||||||
|
"LocalFilesPanel.pathValidation.getOpenCase=WARNING: Exception while gettting open case."
|
||||||
|
})
|
||||||
private void warnIfPathIsInvalid(final List<String> pathsList) {
|
private void warnIfPathIsInvalid(final List<String> pathsList) {
|
||||||
errorLabel.setVisible(false);
|
errorLabel.setVisible(false);
|
||||||
|
|
||||||
@ -288,13 +292,13 @@ final class LocalFilesPanel extends javax.swing.JPanel {
|
|||||||
for (String currentPath : pathsList) {
|
for (String currentPath : pathsList) {
|
||||||
if (!PathValidator.isValid(currentPath, currentCaseType)) {
|
if (!PathValidator.isValid(currentPath, currentCaseType)) {
|
||||||
errorLabel.setVisible(true);
|
errorLabel.setVisible(true);
|
||||||
errorLabel.setText(NbBundle.getMessage(this.getClass(), "DataSourceOnCDriveError.text"));
|
errorLabel.setText(Bundle.LocalFilesPanel_pathValidation_dataSourceOnCDriveError());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (NoCurrentCaseException ex) {
|
} catch (NoCurrentCaseException ex) {
|
||||||
errorLabel.setVisible(true);
|
errorLabel.setVisible(true);
|
||||||
errorLabel.setText(Bundle.LocalFilesPanel_pathValidation_error());
|
errorLabel.setText(Bundle.LocalFilesPanel_pathValidation_getOpenCase());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,6 @@ import javax.swing.event.DocumentEvent;
|
|||||||
import javax.swing.event.DocumentListener;
|
import javax.swing.event.DocumentListener;
|
||||||
import org.apache.commons.io.FilenameUtils;
|
import org.apache.commons.io.FilenameUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.openide.util.Exceptions;
|
|
||||||
import org.openide.util.NbBundle.Messages;
|
import org.openide.util.NbBundle.Messages;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.coreutils.PathValidator;
|
import org.sleuthkit.autopsy.coreutils.PathValidator;
|
||||||
@ -40,6 +39,7 @@ import org.sleuthkit.autopsy.coreutils.PathValidator;
|
|||||||
/**
|
/**
|
||||||
* A panel which allows the user to select a Logical Evidence File (L01)
|
* A panel which allows the user to select a Logical Evidence File (L01)
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
final class LogicalEvidenceFilePanel extends javax.swing.JPanel implements DocumentListener {
|
final class LogicalEvidenceFilePanel extends javax.swing.JPanel implements DocumentListener {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
@ -28,13 +28,14 @@ import org.openide.util.NbBundle;
|
|||||||
import org.openide.util.NbBundle.Messages;
|
import org.openide.util.NbBundle.Messages;
|
||||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
|
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add input wizard subpanel for adding local files / dirs to the case
|
||||||
|
*/
|
||||||
@Messages({
|
@Messages({
|
||||||
"LogicalFilesDspPanel.subTypeComboBox.localFilesOption.text=Local files and folders",
|
"LogicalFilesDspPanel.subTypeComboBox.localFilesOption.text=Local files and folders",
|
||||||
"LogicalFilesDspPanel.subTypeComboBox.l01FileOption.text=Logical evidence file (L01)"
|
"LogicalFilesDspPanel.subTypeComboBox.l01FileOption.text=Logical evidence file (L01)"
|
||||||
})
|
})
|
||||||
/**
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
* Add input wizard subpanel for adding local files / dirs to the case
|
|
||||||
*/
|
|
||||||
final class LogicalFilesDspPanel extends JPanel {
|
final class LogicalFilesDspPanel extends JPanel {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
@ -35,6 +35,10 @@ import org.sleuthkit.autopsy.coreutils.Logger;
|
|||||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dialog to allow the examiner to locate an image when it cannot be found.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
class MissingImageDialog extends javax.swing.JDialog {
|
class MissingImageDialog extends javax.swing.JDialog {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(MissingImageDialog.class.getName());
|
private static final Logger logger = Logger.getLogger(MissingImageDialog.class.getName());
|
||||||
@ -50,7 +54,7 @@ class MissingImageDialog extends javax.swing.JDialog {
|
|||||||
}
|
}
|
||||||
static final String allDesc = NbBundle.getMessage(MissingImageDialog.class, "MissingImageDialog.allDesc.text");
|
static final String allDesc = NbBundle.getMessage(MissingImageDialog.class, "MissingImageDialog.allDesc.text");
|
||||||
static final GeneralFilter allFilter = new GeneralFilter(allExt, allDesc);
|
static final GeneralFilter allFilter = new GeneralFilter(allExt, allDesc);
|
||||||
private JFileChooser fc = new JFileChooser();
|
private final JFileChooser fc = new JFileChooser();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate a MissingImageDialog.
|
* Instantiate a MissingImageDialog.
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011-2017 Basis Technology Corp.
|
* Copyright 2011-2018 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -28,6 +28,7 @@ import org.openide.windows.WindowManager;
|
|||||||
/**
|
/**
|
||||||
* This class extends a JDialog and maintains the MultiUserCasesPanel.
|
* This class extends a JDialog and maintains the MultiUserCasesPanel.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
final class MultiUserCasesDialog extends JDialog {
|
final class MultiUserCasesDialog extends JDialog {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011-2017 Basis Technology Corp.
|
* Copyright 2011-2018 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -36,9 +36,10 @@ import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
|||||||
/**
|
/**
|
||||||
* A panel that allows a user to open cases created by auto ingest.
|
* A panel that allows a user to open cases created by auto ingest.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
final class MultiUserCasesPanel extends JPanel{
|
final class MultiUserCasesPanel extends JPanel{
|
||||||
|
|
||||||
private static final Logger LOGGER = Logger.getLogger(MultiUserCasesPanel.class.getName());
|
private static final Logger logger = Logger.getLogger(MultiUserCasesPanel.class.getName());
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
private final JDialog parentDialog;
|
private final JDialog parentDialog;
|
||||||
private final CaseBrowser caseBrowserPanel;
|
private final CaseBrowser caseBrowserPanel;
|
||||||
@ -98,7 +99,7 @@ final class MultiUserCasesPanel extends JPanel{
|
|||||||
Case.openAsCurrentCase(caseMetadataFilePath);
|
Case.openAsCurrentCase(caseMetadataFilePath);
|
||||||
} catch (CaseActionException ex) {
|
} catch (CaseActionException ex) {
|
||||||
if (null != ex.getCause() && !(ex.getCause() instanceof CaseActionCancelledException)) {
|
if (null != ex.getCause() && !(ex.getCause() instanceof CaseActionCancelledException)) {
|
||||||
LOGGER.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", caseMetadataFilePath), ex); //NON-NLS
|
logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", caseMetadataFilePath), ex); //NON-NLS
|
||||||
MessageNotifyUtil.Message.error(ex.getCause().getLocalizedMessage());
|
MessageNotifyUtil.Message.error(ex.getCause().getLocalizedMessage());
|
||||||
}
|
}
|
||||||
SwingUtilities.invokeLater(() -> {
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011-2015 Basis Technology Corp.
|
* Copyright 2011-2018 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -18,9 +18,9 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.casemodule;
|
package org.sleuthkit.autopsy.casemodule;
|
||||||
|
|
||||||
|
import java.awt.Component;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import javax.swing.JFileChooser;
|
import javax.swing.JFileChooser;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
@ -33,6 +33,7 @@ import org.sleuthkit.autopsy.coreutils.PathValidator;
|
|||||||
/**
|
/**
|
||||||
* The JPanel for the first page of the new case wizard.
|
* The JPanel for the first page of the new case wizard.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
final class NewCaseVisualPanel1 extends JPanel implements DocumentListener {
|
final class NewCaseVisualPanel1 extends JPanel implements DocumentListener {
|
||||||
|
|
||||||
private final JFileChooser fileChooser = new JFileChooser();
|
private final JFileChooser fileChooser = new JFileChooser();
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011-2017 Basis Technology Corp.
|
* Copyright 2011-2018 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -16,20 +16,14 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
* NewCaseVisualPanel2.java
|
|
||||||
*
|
|
||||||
* Created on Mar 7, 2012, 11:01:48 AM
|
|
||||||
*/
|
|
||||||
package org.sleuthkit.autopsy.casemodule;
|
package org.sleuthkit.autopsy.casemodule;
|
||||||
|
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* The JPanel for the second page of the new case wizard.
|
||||||
* @author dfickling
|
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
final class NewCaseVisualPanel2 extends javax.swing.JPanel {
|
final class NewCaseVisualPanel2 extends javax.swing.JPanel {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011-2017 Basis Technology Corp.
|
* Copyright 2011-2018 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -35,6 +35,7 @@ import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
|||||||
/**
|
/**
|
||||||
* Panel used by the the open recent case option of the start window.
|
* Panel used by the the open recent case option of the start window.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
class OpenRecentCasePanel extends javax.swing.JPanel {
|
class OpenRecentCasePanel extends javax.swing.JPanel {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
@ -36,9 +36,10 @@ import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
|||||||
* Panel which allows for editing and setting of the case details which are
|
* Panel which allows for editing and setting of the case details which are
|
||||||
* optional or otherwise able to be edited.
|
* optional or otherwise able to be edited.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
final class OptionalCasePropertiesPanel extends javax.swing.JPanel {
|
final class OptionalCasePropertiesPanel extends javax.swing.JPanel {
|
||||||
|
|
||||||
private final static Logger LOGGER = Logger.getLogger(OptionalCasePropertiesPanel.class.getName());
|
private final static Logger logger = Logger.getLogger(OptionalCasePropertiesPanel.class.getName());
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
private EamOrganization selectedOrg = null;
|
private EamOrganization selectedOrg = null;
|
||||||
private java.util.List<EamOrganization> orgs = null;
|
private java.util.List<EamOrganization> orgs = null;
|
||||||
@ -66,7 +67,7 @@ final class OptionalCasePropertiesPanel extends javax.swing.JPanel {
|
|||||||
try {
|
try {
|
||||||
openCase = Case.getCurrentCaseThrows();
|
openCase = Case.getCurrentCaseThrows();
|
||||||
} catch (NoCurrentCaseException ex) {
|
} catch (NoCurrentCaseException ex) {
|
||||||
LOGGER.log(Level.SEVERE, "Exception while getting open case.", ex);
|
logger.log(Level.SEVERE, "Exception while getting open case.", ex);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
caseDisplayNameTextField.setText(openCase.getDisplayName());
|
caseDisplayNameTextField.setText(openCase.getDisplayName());
|
||||||
@ -100,9 +101,9 @@ final class OptionalCasePropertiesPanel extends javax.swing.JPanel {
|
|||||||
selectedOrg = dbManager.getCase(currentCase).getOrg();
|
selectedOrg = dbManager.getCase(currentCase).getOrg();
|
||||||
}
|
}
|
||||||
} catch (EamDbException ex) {
|
} catch (EamDbException ex) {
|
||||||
LOGGER.log(Level.SEVERE, "Unable to get Organization associated with the case from Central Repo", ex);
|
logger.log(Level.SEVERE, "Unable to get Organization associated with the case from Central Repo", ex);
|
||||||
} catch (NoCurrentCaseException ex) {
|
} catch (NoCurrentCaseException ex) {
|
||||||
LOGGER.log(Level.SEVERE, "Exception while getting open case.", ex);
|
logger.log(Level.SEVERE, "Exception while getting open case.", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selectedOrg != null) {
|
if (selectedOrg != null) {
|
||||||
@ -145,7 +146,7 @@ final class OptionalCasePropertiesPanel extends javax.swing.JPanel {
|
|||||||
});
|
});
|
||||||
comboBoxOrgName.setSelectedItem(selectedBeforeLoad);
|
comboBoxOrgName.setSelectedItem(selectedBeforeLoad);
|
||||||
} catch (EamDbException ex) {
|
} catch (EamDbException ex) {
|
||||||
LOGGER.log(Level.WARNING, "Unable to populate list of Organizations from Central Repo", ex);
|
logger.log(Level.WARNING, "Unable to populate list of Organizations from Central Repo", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -598,9 +599,9 @@ final class OptionalCasePropertiesPanel extends javax.swing.JPanel {
|
|||||||
correlationCase.setNotes(taNotesText.getText());
|
correlationCase.setNotes(taNotesText.getText());
|
||||||
dbManager.updateCase(correlationCase);
|
dbManager.updateCase(correlationCase);
|
||||||
} catch (EamDbException ex) {
|
} catch (EamDbException ex) {
|
||||||
LOGGER.log(Level.SEVERE, "Error connecting to central repository database", ex); // NON-NLS
|
logger.log(Level.SEVERE, "Error connecting to central repository database", ex); // NON-NLS
|
||||||
} catch (NoCurrentCaseException ex) {
|
} catch (NoCurrentCaseException ex) {
|
||||||
LOGGER.log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS
|
logger.log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS
|
||||||
} finally {
|
} finally {
|
||||||
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
OptionsCategory_Name_TagNamesOptions=Tags
|
OptionsCategory_Name_TagNamesOptions=Tags
|
||||||
OptionsCategory_TagNames=TagNames
|
OptionsCategory_TagNames=TagNames
|
||||||
Blackboard.unableToIndexArtifact.error.msg=Unable to index blackboard artifact {0}
|
|
||||||
TagNameDialog.title.text=New Tag
|
TagNameDialog.title.text=New Tag
|
||||||
TagNameDialog.JOptionPane.tagNameIllegalCharacters.message=Tag name may not contain any of the following symbols\: \\ \: * ? " < > | , ;
|
TagNameDialog.JOptionPane.tagNameIllegalCharacters.message=Tag name may not contain any of the following symbols\: \\ \: * ? " < > | , ;
|
||||||
TagNameDialog.JOptionPane.tagNameIllegalCharacters.title=Invalid character in tag name
|
TagNameDialog.JOptionPane.tagNameIllegalCharacters.title=Invalid character in tag name
|
||||||
|
@ -54,7 +54,7 @@ final class TagNameDefinition implements Comparable<TagNameDefinition> {
|
|||||||
private static final List<String> STANDARD_TAG_DISPLAY_NAMES = Arrays.asList(Bundle.TagNameDefinition_predefTagNames_bookmark_text(), Bundle.TagNameDefinition_predefTagNames_followUp_text(),
|
private static final List<String> STANDARD_TAG_DISPLAY_NAMES = Arrays.asList(Bundle.TagNameDefinition_predefTagNames_bookmark_text(), Bundle.TagNameDefinition_predefTagNames_followUp_text(),
|
||||||
Bundle.TagNameDefinition_predefTagNames_notableItem_text(), DhsImageCategory.ONE.getDisplayName(),
|
Bundle.TagNameDefinition_predefTagNames_notableItem_text(), DhsImageCategory.ONE.getDisplayName(),
|
||||||
DhsImageCategory.TWO.getDisplayName(), DhsImageCategory.THREE.getDisplayName(),
|
DhsImageCategory.TWO.getDisplayName(), DhsImageCategory.THREE.getDisplayName(),
|
||||||
DhsImageCategory.FOUR.getDisplayName(), DhsImageCategory.FIVE.getDisplayName());
|
DhsImageCategory.FOUR.getDisplayName(), DhsImageCategory.FIVE.getDisplayName(), DhsImageCategory.ZERO.getDisplayName());
|
||||||
private final String displayName;
|
private final String displayName;
|
||||||
private final String description;
|
private final String description;
|
||||||
private final TagName.HTML_COLOR color;
|
private final TagName.HTML_COLOR color;
|
||||||
|
@ -19,8 +19,6 @@
|
|||||||
package org.sleuthkit.autopsy.casemodule.services;
|
package org.sleuthkit.autopsy.casemodule.services;
|
||||||
|
|
||||||
import java.awt.BorderLayout;
|
import java.awt.BorderLayout;
|
||||||
import java.awt.Dimension;
|
|
||||||
import java.awt.Toolkit;
|
|
||||||
import java.awt.event.WindowAdapter;
|
import java.awt.event.WindowAdapter;
|
||||||
import java.awt.event.WindowEvent;
|
import java.awt.event.WindowEvent;
|
||||||
import javax.swing.JFrame;
|
import javax.swing.JFrame;
|
||||||
@ -34,6 +32,7 @@ import org.sleuthkit.datamodel.TskData;
|
|||||||
|
|
||||||
@Messages({"TagNameDialog.descriptionLabel.text=Description:",
|
@Messages({"TagNameDialog.descriptionLabel.text=Description:",
|
||||||
"TagNameDialog.notableCheckbox.text=Tag indicates item is notable."})
|
"TagNameDialog.notableCheckbox.text=Tag indicates item is notable."})
|
||||||
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
final class TagNameDialog extends javax.swing.JDialog {
|
final class TagNameDialog extends javax.swing.JDialog {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
@ -27,7 +27,6 @@ import java.util.TreeSet;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import javax.swing.DefaultListModel;
|
import javax.swing.DefaultListModel;
|
||||||
import javax.swing.JOptionPane;
|
import javax.swing.JOptionPane;
|
||||||
import javax.swing.SwingUtilities;
|
|
||||||
import javax.swing.event.ListSelectionEvent;
|
import javax.swing.event.ListSelectionEvent;
|
||||||
import org.netbeans.spi.options.OptionsPanelController;
|
import org.netbeans.spi.options.OptionsPanelController;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
@ -43,6 +42,7 @@ import org.sleuthkit.autopsy.coreutils.Logger;
|
|||||||
/**
|
/**
|
||||||
* A panel to allow the user to create and delete custom tag types.
|
* A panel to allow the user to create and delete custom tag types.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel {
|
final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
@ -121,6 +121,15 @@ public class TagsManager implements Closeable {
|
|||||||
return tagDisplayNames;
|
return tagDisplayNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of names of standard/predefined tags
|
||||||
|
*
|
||||||
|
* @return list of predefined tag names
|
||||||
|
*/
|
||||||
|
public static List<String> getStandardTagNames() {
|
||||||
|
return TagNameDefinition.getStandardTagNames();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a per case Autopsy service that manages the addition of
|
* Constructs a per case Autopsy service that manages the addition of
|
||||||
* content and artifact tags to the case database.
|
* content and artifact tags to the case database.
|
||||||
@ -157,6 +166,21 @@ public class TagsManager implements Closeable {
|
|||||||
return caseDb.getTagNamesInUse();
|
return caseDb.getTagNamesInUse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Selects all of the rows from the tag_names table in the case database for
|
||||||
|
* which there is at least one matching row in the content_tags or
|
||||||
|
* blackboard_artifact_tags tables, for the given data source object id.
|
||||||
|
*
|
||||||
|
* @param dsObjId data source object id
|
||||||
|
*
|
||||||
|
* @return A list, possibly empty, of TagName data transfer objects (DTOs)
|
||||||
|
* for the rows.
|
||||||
|
*
|
||||||
|
* @throws TskCoreException
|
||||||
|
*/
|
||||||
|
public List<TagName> getTagNamesInUse(long dsObjId) throws TskCoreException {
|
||||||
|
return caseDb.getTagNamesInUse(dsObjId);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Gets a map of tag display names to tag name entries in the case database.
|
* Gets a map of tag display names to tag name entries in the case database.
|
||||||
* It has keys for the display names of the standard tag types, the current
|
* It has keys for the display names of the standard tag types, the current
|
||||||
@ -392,6 +416,24 @@ public class TagsManager implements Closeable {
|
|||||||
return caseDb.getContentTagsCountByTagName(tagName);
|
return caseDb.getContentTagsCountByTagName(tagName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets content tags count by tag name, for the given data source
|
||||||
|
*
|
||||||
|
* @param tagName The representation of the desired tag type in the case
|
||||||
|
* database, which can be obtained by calling getTagNames and/or addTagName.
|
||||||
|
*
|
||||||
|
* @param dsObjId data source object id
|
||||||
|
*
|
||||||
|
* @return A count of the content tags with the specified tag name, and for
|
||||||
|
* the given data source
|
||||||
|
*
|
||||||
|
* @throws TskCoreException If there is an error getting the tags count from
|
||||||
|
* the case database.
|
||||||
|
*/
|
||||||
|
public long getContentTagsCountByTagName(TagName tagName, long dsObjId) throws TskCoreException {
|
||||||
|
return caseDb.getContentTagsCountByTagName(tagName, dsObjId);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a content tag by tag id.
|
* Gets a content tag by tag id.
|
||||||
*
|
*
|
||||||
@ -421,6 +463,23 @@ public class TagsManager implements Closeable {
|
|||||||
return caseDb.getContentTagsByTagName(tagName);
|
return caseDb.getContentTagsByTagName(tagName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets content tags by tag name, for the given data source.
|
||||||
|
*
|
||||||
|
* @param tagName The tag name of interest.
|
||||||
|
*
|
||||||
|
* @param dsObjId data source object id
|
||||||
|
*
|
||||||
|
* @return A list, possibly empty, of the content tags with the specified
|
||||||
|
* tag name, and for the given data source.
|
||||||
|
*
|
||||||
|
* @throws TskCoreException If there is an error getting the tags from the
|
||||||
|
* case database.
|
||||||
|
*/
|
||||||
|
public List<ContentTag> getContentTagsByTagName(TagName tagName, long dsObjId) throws TskCoreException {
|
||||||
|
return caseDb.getContentTagsByTagName(tagName, dsObjId);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets content tags count by content.
|
* Gets content tags count by content.
|
||||||
*
|
*
|
||||||
@ -522,6 +581,24 @@ public class TagsManager implements Closeable {
|
|||||||
return caseDb.getBlackboardArtifactTagsCountByTagName(tagName);
|
return caseDb.getBlackboardArtifactTagsCountByTagName(tagName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an artifact tags count by tag name, for the given data source.
|
||||||
|
*
|
||||||
|
* @param tagName The representation of the desired tag type in the case
|
||||||
|
* database, which can be obtained by calling getTagNames
|
||||||
|
* and/or addTagName.
|
||||||
|
* @param dsObjId data source object id
|
||||||
|
*
|
||||||
|
* @return A count of the artifact tags with the specified tag name,
|
||||||
|
* for the given data source.
|
||||||
|
*
|
||||||
|
* @throws TskCoreException If there is an error getting the tags count from
|
||||||
|
* the case database.
|
||||||
|
*/
|
||||||
|
public long getBlackboardArtifactTagsCountByTagName(TagName tagName, long dsObjId) throws TskCoreException {
|
||||||
|
return caseDb.getBlackboardArtifactTagsCountByTagName(tagName, dsObjId);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets an artifact tag by tag id.
|
* Gets an artifact tag by tag id.
|
||||||
*
|
*
|
||||||
@ -553,6 +630,24 @@ public class TagsManager implements Closeable {
|
|||||||
return caseDb.getBlackboardArtifactTagsByTagName(tagName);
|
return caseDb.getBlackboardArtifactTagsByTagName(tagName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets artifact tags by tag name, for specified data source.
|
||||||
|
*
|
||||||
|
* @param tagName The representation of the desired tag type in the case
|
||||||
|
* database, which can be obtained by calling getTagNames
|
||||||
|
* and/or addTagName.
|
||||||
|
* @param dsObjId data source object id
|
||||||
|
*
|
||||||
|
* @return A list, possibly empty, of the artifact tags with the specified
|
||||||
|
* tag name, for the specified data source.
|
||||||
|
*
|
||||||
|
* @throws TskCoreException If there is an error getting the tags from the
|
||||||
|
* case database.
|
||||||
|
*/
|
||||||
|
public List<BlackboardArtifactTag> getBlackboardArtifactTagsByTagName(TagName tagName, long dsObjId) throws TskCoreException {
|
||||||
|
return caseDb.getBlackboardArtifactTagsByTagName(tagName, dsObjId);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets artifact tags for a particular artifact.
|
* Gets artifact tags for a particular artifact.
|
||||||
*
|
*
|
||||||
|
@ -0,0 +1,148 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 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.centralrepository;
|
||||||
|
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import javax.swing.AbstractAction;
|
||||||
|
import org.openide.util.NbBundle.Messages;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttribute;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifactUtil;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An AbstractAction to manage adding and modifying a Central Repository file
|
||||||
|
* instance comment.
|
||||||
|
*/
|
||||||
|
public final class AddEditCentralRepoCommentAction extends AbstractAction {
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger(AddEditCentralRepoCommentAction.class.getName());
|
||||||
|
|
||||||
|
private boolean addToDatabase;
|
||||||
|
private CorrelationAttribute correlationAttribute;
|
||||||
|
String title;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private constructor to create an instance given a CorrelationAttribute.
|
||||||
|
*
|
||||||
|
* @param correlationAttribute The correlation attribute to modify.
|
||||||
|
* @param title The text for the menu item.
|
||||||
|
*/
|
||||||
|
private AddEditCentralRepoCommentAction(CorrelationAttribute correlationAttribute, String title) {
|
||||||
|
super(title);
|
||||||
|
this.title = title;
|
||||||
|
this.correlationAttribute = correlationAttribute;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private constructor to create an instance given an AbstractFile.
|
||||||
|
*
|
||||||
|
* @param file The file from which a correlation attribute to modify is
|
||||||
|
* derived.
|
||||||
|
* @param title The text for the menu item.
|
||||||
|
*/
|
||||||
|
private AddEditCentralRepoCommentAction(AbstractFile file, String title) {
|
||||||
|
|
||||||
|
super(title);
|
||||||
|
this.title = title;
|
||||||
|
correlationAttribute = EamArtifactUtil.getCorrelationAttributeFromContent(file);
|
||||||
|
if (correlationAttribute == null) {
|
||||||
|
addToDatabase = true;
|
||||||
|
correlationAttribute = EamArtifactUtil.makeCorrelationAttributeFromContent(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent event) {
|
||||||
|
addEditCentralRepoComment();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a Add/Edit dialog for the correlation attribute file instance
|
||||||
|
* comment. The comment will be updated in the database if the file instance
|
||||||
|
* exists there, or a new file instance will be added to the database with
|
||||||
|
* the comment attached otherwise.
|
||||||
|
*
|
||||||
|
* The current comment for this instance is returned in case it is needed to
|
||||||
|
* update the display.
|
||||||
|
*
|
||||||
|
* @return the current comment for this instance
|
||||||
|
*/
|
||||||
|
public String addEditCentralRepoComment() {
|
||||||
|
CentralRepoCommentDialog centralRepoCommentDialog = new CentralRepoCommentDialog(correlationAttribute, title);
|
||||||
|
centralRepoCommentDialog.display();
|
||||||
|
|
||||||
|
if (centralRepoCommentDialog.isCommentUpdated()) {
|
||||||
|
EamDb dbManager;
|
||||||
|
|
||||||
|
try {
|
||||||
|
dbManager = EamDb.getInstance();
|
||||||
|
|
||||||
|
if (addToDatabase) {
|
||||||
|
dbManager.addArtifact(correlationAttribute);
|
||||||
|
} else {
|
||||||
|
dbManager.updateAttributeInstanceComment(correlationAttribute);
|
||||||
|
}
|
||||||
|
} catch (EamDbException ex) {
|
||||||
|
logger.log(Level.SEVERE, "Error adding comment", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return centralRepoCommentDialog.getComment();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an instance labeled "Add/Edit Central Repository Comment" given an
|
||||||
|
* AbstractFile. This is intended for the result view.
|
||||||
|
*
|
||||||
|
* @param file The file from which a correlation attribute to modify is
|
||||||
|
* derived.
|
||||||
|
*
|
||||||
|
* @return The instance.
|
||||||
|
*
|
||||||
|
* @throws EamDbException
|
||||||
|
* @throws NoCurrentCaseException
|
||||||
|
* @throws TskCoreException
|
||||||
|
*/
|
||||||
|
@Messages({"AddEditCentralRepoCommentAction.menuItemText.addEditCentralRepoComment=Add/Edit Central Repository Comment"})
|
||||||
|
public static AddEditCentralRepoCommentAction createAddEditCentralRepoCommentAction(AbstractFile file) {
|
||||||
|
|
||||||
|
return new AddEditCentralRepoCommentAction(file,
|
||||||
|
Bundle.AddEditCentralRepoCommentAction_menuItemText_addEditCentralRepoComment());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an instance labeled "Add/Edit Comment" given a
|
||||||
|
* CorrelationAttribute. This is intended for the content view.
|
||||||
|
*
|
||||||
|
* @param correlationAttribute The correlation attribute to modify.
|
||||||
|
*
|
||||||
|
* @return The instance.
|
||||||
|
*/
|
||||||
|
@Messages({"AddEditCentralRepoCommentAction.menuItemText.addEditComment=Add/Edit Comment"})
|
||||||
|
public static AddEditCentralRepoCommentAction createAddEditCommentAction(CorrelationAttribute correlationAttribute) {
|
||||||
|
|
||||||
|
return new AddEditCentralRepoCommentAction(correlationAttribute,
|
||||||
|
Bundle.AddEditCentralRepoCommentAction_menuItemText_addEditComment());
|
||||||
|
}
|
||||||
|
}
|
@ -5,3 +5,8 @@ OpenIDE-Module-Long-Description=\
|
|||||||
Correlation Engine ingest module and central database. \n\n\
|
Correlation Engine ingest module and central database. \n\n\
|
||||||
The Correlation Engine ingest module stores attributes of artifacts matching selected correlation types into a central database.\n\
|
The Correlation Engine ingest module stores attributes of artifacts matching selected correlation types into a central database.\n\
|
||||||
Stored attributes are used in future cases to correlate and analyzes files and artifacts during ingest.
|
Stored attributes are used in future cases to correlate and analyzes files and artifacts during ingest.
|
||||||
|
CentralRepoCommentDialog.fileLabel.text=File:
|
||||||
|
CentralRepoCommentDialog.commentLabel.text=Comment:
|
||||||
|
CentralRepoCommentDialog.pathLabel.text=
|
||||||
|
CentralRepoCommentDialog.okButton.text=&OK
|
||||||
|
CentralRepoCommentDialog.cancelButton.text=C&ancel
|
||||||
|
138
Core/src/org/sleuthkit/autopsy/centralrepository/CentralRepoCommentDialog.form
Executable file
138
Core/src/org/sleuthkit/autopsy/centralrepository/CentralRepoCommentDialog.form
Executable file
@ -0,0 +1,138 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
|
||||||
|
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JDialogFormInfo">
|
||||||
|
<Properties>
|
||||||
|
<Property name="defaultCloseOperation" type="int" value="2"/>
|
||||||
|
<Property name="size" type="java.awt.Dimension" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||||
|
<Connection component="Form" name="preferredSize" type="property"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<SyntheticProperties>
|
||||||
|
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
|
||||||
|
<SyntheticProperty name="generateCenter" type="boolean" value="false"/>
|
||||||
|
</SyntheticProperties>
|
||||||
|
<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="jScrollPane1" pref="500" max="32767" attributes="0"/>
|
||||||
|
<Group type="102" attributes="0">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Group type="102" alignment="0" attributes="0">
|
||||||
|
<Component id="fileLabel" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Component id="pathLabel" min="-2" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
<Component id="commentLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
<EmptySpace min="0" pref="451" max="32767" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
<Group type="102" alignment="0" attributes="0">
|
||||||
|
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||||
|
<Component id="okButton" min="-2" pref="75" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Component id="cancelButton" min="-2" pref="75" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
<EmptySpace max="-2" 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="fileLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
|
<Component id="pathLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
<EmptySpace min="-2" pref="19" max="-2" attributes="0"/>
|
||||||
|
<Component id="commentLabel" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Component id="jScrollPane1" max="32767" attributes="0"/>
|
||||||
|
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Component id="okButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||||
|
<Component id="cancelButton" min="-2" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
</DimensionLayout>
|
||||||
|
</Layout>
|
||||||
|
<SubComponents>
|
||||||
|
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
|
||||||
|
<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.JTextArea" name="commentTextArea">
|
||||||
|
<Properties>
|
||||||
|
<Property name="columns" type="int" value="20"/>
|
||||||
|
<Property name="lineWrap" type="boolean" value="true"/>
|
||||||
|
<Property name="rows" type="int" value="5"/>
|
||||||
|
<Property name="tabSize" type="int" value="4"/>
|
||||||
|
<Property name="wrapStyleWord" type="boolean" value="true"/>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
</SubComponents>
|
||||||
|
</Container>
|
||||||
|
<Component class="javax.swing.JButton" name="okButton">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/Bundle.properties" key="CentralRepoCommentDialog.okButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<Events>
|
||||||
|
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="okButtonActionPerformed"/>
|
||||||
|
</Events>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JButton" name="cancelButton">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/Bundle.properties" key="CentralRepoCommentDialog.cancelButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<Events>
|
||||||
|
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cancelButtonActionPerformed"/>
|
||||||
|
</Events>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JLabel" name="fileLabel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/Bundle.properties" key="CentralRepoCommentDialog.fileLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JLabel" name="pathLabel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/Bundle.properties" key="CentralRepoCommentDialog.pathLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JLabel" name="commentLabel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/Bundle.properties" key="CentralRepoCommentDialog.commentLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
</SubComponents>
|
||||||
|
</Form>
|
203
Core/src/org/sleuthkit/autopsy/centralrepository/CentralRepoCommentDialog.java
Executable file
203
Core/src/org/sleuthkit/autopsy/centralrepository/CentralRepoCommentDialog.java
Executable file
@ -0,0 +1,203 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 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.centralrepository;
|
||||||
|
|
||||||
|
import org.openide.windows.WindowManager;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttribute;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dialog to allow Central Repository file instance comments to be added and
|
||||||
|
* modified.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
|
final class CentralRepoCommentDialog extends javax.swing.JDialog {
|
||||||
|
|
||||||
|
private final CorrelationAttribute correlationAttribute;
|
||||||
|
private boolean commentUpdated = false;
|
||||||
|
private String currentComment = "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an instance.
|
||||||
|
*
|
||||||
|
* @param correlationAttribute The correlation attribute to be modified.
|
||||||
|
* @param title The title to assign the dialog.
|
||||||
|
*/
|
||||||
|
CentralRepoCommentDialog(CorrelationAttribute correlationAttribute, String title) {
|
||||||
|
super(WindowManager.getDefault().getMainWindow(), title);
|
||||||
|
|
||||||
|
initComponents();
|
||||||
|
|
||||||
|
CorrelationAttributeInstance instance = correlationAttribute.getInstances().get(0);
|
||||||
|
|
||||||
|
// Store the original comment
|
||||||
|
if (instance.getComment() != null) {
|
||||||
|
currentComment = instance.getComment();
|
||||||
|
}
|
||||||
|
|
||||||
|
pathLabel.setText(instance.getFilePath());
|
||||||
|
commentTextArea.setText(instance.getComment());
|
||||||
|
|
||||||
|
this.correlationAttribute = correlationAttribute;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the dialog.
|
||||||
|
*/
|
||||||
|
void display() {
|
||||||
|
setModal(true);
|
||||||
|
setSize(getPreferredSize());
|
||||||
|
setLocationRelativeTo(this.getParent());
|
||||||
|
setAlwaysOnTop(false);
|
||||||
|
pack();
|
||||||
|
setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Has the comment been updated?
|
||||||
|
*
|
||||||
|
* @return True if the comment has been updated; otherwise false.
|
||||||
|
*/
|
||||||
|
boolean isCommentUpdated() {
|
||||||
|
return commentUpdated;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current comment.
|
||||||
|
* If the user hit OK, this will be the new comment.
|
||||||
|
* If the user canceled, this will be the original comment.
|
||||||
|
* @return the comment
|
||||||
|
*/
|
||||||
|
String getComment() {
|
||||||
|
return currentComment;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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() {
|
||||||
|
|
||||||
|
jScrollPane1 = new javax.swing.JScrollPane();
|
||||||
|
commentTextArea = new javax.swing.JTextArea();
|
||||||
|
okButton = new javax.swing.JButton();
|
||||||
|
cancelButton = new javax.swing.JButton();
|
||||||
|
fileLabel = new javax.swing.JLabel();
|
||||||
|
pathLabel = new javax.swing.JLabel();
|
||||||
|
commentLabel = new javax.swing.JLabel();
|
||||||
|
|
||||||
|
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
|
||||||
|
setSize(getPreferredSize());
|
||||||
|
|
||||||
|
commentTextArea.setColumns(20);
|
||||||
|
commentTextArea.setLineWrap(true);
|
||||||
|
commentTextArea.setRows(5);
|
||||||
|
commentTextArea.setTabSize(4);
|
||||||
|
commentTextArea.setWrapStyleWord(true);
|
||||||
|
jScrollPane1.setViewportView(commentTextArea);
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(okButton, org.openide.util.NbBundle.getMessage(CentralRepoCommentDialog.class, "CentralRepoCommentDialog.okButton.text")); // NOI18N
|
||||||
|
okButton.addActionListener(new java.awt.event.ActionListener() {
|
||||||
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
|
okButtonActionPerformed(evt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(cancelButton, org.openide.util.NbBundle.getMessage(CentralRepoCommentDialog.class, "CentralRepoCommentDialog.cancelButton.text")); // NOI18N
|
||||||
|
cancelButton.addActionListener(new java.awt.event.ActionListener() {
|
||||||
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
|
cancelButtonActionPerformed(evt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(fileLabel, org.openide.util.NbBundle.getMessage(CentralRepoCommentDialog.class, "CentralRepoCommentDialog.fileLabel.text")); // NOI18N
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(pathLabel, org.openide.util.NbBundle.getMessage(CentralRepoCommentDialog.class, "CentralRepoCommentDialog.pathLabel.text")); // NOI18N
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(commentLabel, org.openide.util.NbBundle.getMessage(CentralRepoCommentDialog.class, "CentralRepoCommentDialog.commentLabel.text")); // NOI18N
|
||||||
|
|
||||||
|
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
|
||||||
|
getContentPane().setLayout(layout);
|
||||||
|
layout.setHorizontalGroup(
|
||||||
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGroup(layout.createSequentialGroup()
|
||||||
|
.addContainerGap()
|
||||||
|
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 500, Short.MAX_VALUE)
|
||||||
|
.addGroup(layout.createSequentialGroup()
|
||||||
|
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGroup(layout.createSequentialGroup()
|
||||||
|
.addComponent(fileLabel)
|
||||||
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
|
.addComponent(pathLabel))
|
||||||
|
.addComponent(commentLabel))
|
||||||
|
.addGap(0, 451, Short.MAX_VALUE))
|
||||||
|
.addGroup(layout.createSequentialGroup()
|
||||||
|
.addGap(0, 0, Short.MAX_VALUE)
|
||||||
|
.addComponent(okButton, javax.swing.GroupLayout.PREFERRED_SIZE, 75, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
|
.addComponent(cancelButton, javax.swing.GroupLayout.PREFERRED_SIZE, 75, javax.swing.GroupLayout.PREFERRED_SIZE)))
|
||||||
|
.addContainerGap())
|
||||||
|
);
|
||||||
|
layout.setVerticalGroup(
|
||||||
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGroup(layout.createSequentialGroup()
|
||||||
|
.addContainerGap()
|
||||||
|
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||||
|
.addComponent(fileLabel)
|
||||||
|
.addComponent(pathLabel))
|
||||||
|
.addGap(19, 19, 19)
|
||||||
|
.addComponent(commentLabel)
|
||||||
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
|
.addComponent(jScrollPane1)
|
||||||
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||||
|
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addComponent(okButton)
|
||||||
|
.addComponent(cancelButton))
|
||||||
|
.addContainerGap())
|
||||||
|
);
|
||||||
|
|
||||||
|
pack();
|
||||||
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
|
|
||||||
|
private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed
|
||||||
|
dispose();
|
||||||
|
}//GEN-LAST:event_cancelButtonActionPerformed
|
||||||
|
|
||||||
|
private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
|
||||||
|
currentComment = commentTextArea.getText();
|
||||||
|
correlationAttribute.getInstances().get(0).setComment(currentComment);
|
||||||
|
commentUpdated = true;
|
||||||
|
|
||||||
|
dispose();
|
||||||
|
}//GEN-LAST:event_okButtonActionPerformed
|
||||||
|
|
||||||
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
|
private javax.swing.JButton cancelButton;
|
||||||
|
private javax.swing.JLabel commentLabel;
|
||||||
|
private javax.swing.JTextArea commentTextArea;
|
||||||
|
private javax.swing.JLabel fileLabel;
|
||||||
|
private javax.swing.JScrollPane jScrollPane1;
|
||||||
|
private javax.swing.JButton okButton;
|
||||||
|
private javax.swing.JLabel pathLabel;
|
||||||
|
// End of variables declaration//GEN-END:variables
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Central Repository
|
||||||
|
*
|
||||||
|
* Copyright 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.centralrepository;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.swing.Action;
|
||||||
|
import org.openide.util.Utilities;
|
||||||
|
import org.openide.util.lookup.ServiceProvider;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifactUtil;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbUtil;
|
||||||
|
import org.sleuthkit.autopsy.corecomponentinterfaces.ContextMenuActionsProvider;
|
||||||
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This creates a single context menu item for adding or editing a Central
|
||||||
|
* Repository comment.
|
||||||
|
*/
|
||||||
|
@ServiceProvider(service = ContextMenuActionsProvider.class)
|
||||||
|
public class CentralRepoContextMenuActionsProvider implements ContextMenuActionsProvider {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Action> getActions() {
|
||||||
|
ArrayList<Action> actions = new ArrayList<>();
|
||||||
|
Collection<? extends AbstractFile> selectedFiles = Utilities.actionsGlobalContext().lookupAll(AbstractFile.class);
|
||||||
|
|
||||||
|
if (selectedFiles.size() != 1) {
|
||||||
|
return actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (AbstractFile file : selectedFiles) {
|
||||||
|
if (EamDbUtil.useCentralRepo() && EamArtifactUtil.isSupportedAbstractFileType(file) && file.isFile()) {
|
||||||
|
actions.add(AddEditCentralRepoCommentAction.createAddEditCentralRepoCommentAction(file));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return actions;
|
||||||
|
}
|
||||||
|
}
|
@ -3,3 +3,7 @@ DataContentViewerOtherCases.showCaseDetailsMenuItem.text=Show Case Details
|
|||||||
DataContentViewerOtherCases.table.toolTip.text=Click column name to sort. Right-click on the table for more options.
|
DataContentViewerOtherCases.table.toolTip.text=Click column name to sort. Right-click on the table for more options.
|
||||||
DataContentViewerOtherCases.exportToCSVMenuItem.text=Export Selected Rows to CSV
|
DataContentViewerOtherCases.exportToCSVMenuItem.text=Export Selected Rows to CSV
|
||||||
DataContentViewerOtherCases.showCommonalityMenuItem.text=Show Frequency
|
DataContentViewerOtherCases.showCommonalityMenuItem.text=Show Frequency
|
||||||
|
DataContentViewerOtherCases.addCommentMenuItem.text=Add/Edit Comment
|
||||||
|
DataContentViewerOtherCases.earliestCaseDate.text=Earliest Case Date
|
||||||
|
DataContentViewerOtherCases.earliestCaseLabel.toolTipText=
|
||||||
|
DataContentViewerOtherCases.earliestCaseLabel.text=Central Repository Starting Date:
|
||||||
|
@ -3,6 +3,9 @@
|
|||||||
<Form version="1.6" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
<Form version="1.6" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||||
<NonVisualComponents>
|
<NonVisualComponents>
|
||||||
<Container class="javax.swing.JPopupMenu" name="rightClickPopupMenu">
|
<Container class="javax.swing.JPopupMenu" name="rightClickPopupMenu">
|
||||||
|
<Events>
|
||||||
|
<EventHandler event="popupMenuWillBecomeVisible" listener="javax.swing.event.PopupMenuListener" parameters="javax.swing.event.PopupMenuEvent" handler="rightClickPopupMenuPopupMenuWillBecomeVisible"/>
|
||||||
|
</Events>
|
||||||
|
|
||||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout">
|
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout">
|
||||||
<Property name="useNullLayout" type="boolean" value="true"/>
|
<Property name="useNullLayout" type="boolean" value="true"/>
|
||||||
@ -36,6 +39,13 @@
|
|||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
<MenuItem class="javax.swing.JMenuItem" name="addCommentMenuItem">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/contentviewer/Bundle.properties" key="DataContentViewerOtherCases.addCommentMenuItem.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
</MenuItem>
|
||||||
</SubComponents>
|
</SubComponents>
|
||||||
</Container>
|
</Container>
|
||||||
<Component class="javax.swing.JFileChooser" name="CSVFileChooser">
|
<Component class="javax.swing.JFileChooser" name="CSVFileChooser">
|
||||||
@ -70,7 +80,7 @@
|
|||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
<DimensionLayout dim="1">
|
<DimensionLayout dim="1">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Component id="otherCasesPanel" pref="52" max="32767" attributes="0"/>
|
<Component id="otherCasesPanel" pref="483" max="32767" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
</Layout>
|
</Layout>
|
||||||
@ -93,10 +103,10 @@
|
|||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
<DimensionLayout dim="1">
|
<DimensionLayout dim="1">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<EmptySpace min="0" pref="60" max="32767" attributes="0"/>
|
<EmptySpace min="0" pref="483" max="32767" attributes="0"/>
|
||||||
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
|
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
|
||||||
<Group type="102" alignment="0" attributes="0">
|
<Group type="102" alignment="0" attributes="0">
|
||||||
<Component id="tableContainerPanel" pref="52" max="32767" attributes="0"/>
|
<Component id="tableContainerPanel" pref="483" max="32767" attributes="0"/>
|
||||||
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
|
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
@ -114,17 +124,36 @@
|
|||||||
<Layout>
|
<Layout>
|
||||||
<DimensionLayout dim="0">
|
<DimensionLayout dim="0">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Component id="tableScrollPane" alignment="1" max="32767" attributes="0"/>
|
<Group type="102" alignment="1" attributes="0">
|
||||||
<Component id="tableStatusPanel" alignment="1" max="32767" attributes="0"/>
|
<Component id="tableStatusPanel" pref="1282" max="32767" attributes="0"/>
|
||||||
|
<EmptySpace min="-2" pref="218" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
<Component id="tableScrollPane" alignment="0" max="32767" attributes="0"/>
|
||||||
|
<Group type="102" alignment="0" attributes="0">
|
||||||
|
<Component id="earliestCaseLabel" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Component id="earliestCaseDate" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||||
|
<Component id="tableStatusPanelLabel" max="32767" attributes="0"/>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
<DimensionLayout dim="1">
|
<DimensionLayout dim="1">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Group type="102" alignment="0" attributes="0">
|
<Group type="102" alignment="1" attributes="0">
|
||||||
<Component id="tableScrollPane" max="32767" attributes="0"/>
|
<Component id="tableScrollPane" pref="176" max="32767" attributes="0"/>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
||||||
|
<Group type="103" groupAlignment="1" attributes="0">
|
||||||
|
<Group type="103" groupAlignment="3" attributes="0">
|
||||||
|
<Component id="earliestCaseLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
|
<Component id="earliestCaseDate" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
<Component id="tableStatusPanelLabel" min="-2" pref="16" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
||||||
<Component id="tableStatusPanel" min="-2" max="-2" attributes="0"/>
|
<Component id="tableStatusPanel" min="-2" max="-2" attributes="0"/>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
@ -164,6 +193,23 @@
|
|||||||
</Component>
|
</Component>
|
||||||
</SubComponents>
|
</SubComponents>
|
||||||
</Container>
|
</Container>
|
||||||
|
<Component class="javax.swing.JLabel" name="earliestCaseLabel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/contentviewer/Bundle.properties" key="DataContentViewerOtherCases.earliestCaseLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/contentviewer/Bundle.properties" key="DataContentViewerOtherCases.earliestCaseLabel.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JLabel" name="earliestCaseDate">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/contentviewer/Bundle.properties" key="DataContentViewerOtherCases.earliestCaseDate.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
<Container class="javax.swing.JPanel" name="tableStatusPanel">
|
<Container class="javax.swing.JPanel" name="tableStatusPanel">
|
||||||
<Properties>
|
<Properties>
|
||||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
@ -175,28 +221,15 @@
|
|||||||
<DimensionLayout dim="0">
|
<DimensionLayout dim="0">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||||
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
|
|
||||||
<Group type="102" alignment="0" attributes="0">
|
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
|
||||||
<Component id="tableStatusPanelLabel" pref="780" max="32767" attributes="0"/>
|
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
|
||||||
</Group>
|
|
||||||
</Group>
|
|
||||||
</Group>
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
<DimensionLayout dim="1">
|
<DimensionLayout dim="1">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<EmptySpace min="0" pref="16" max="32767" attributes="0"/>
|
<EmptySpace min="0" pref="16" max="32767" attributes="0"/>
|
||||||
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
|
|
||||||
<Group type="102" alignment="0" attributes="0">
|
|
||||||
<Component id="tableStatusPanelLabel" min="-2" pref="16" max="-2" attributes="0"/>
|
|
||||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
|
||||||
</Group>
|
|
||||||
</Group>
|
|
||||||
</Group>
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
</Layout>
|
</Layout>
|
||||||
<SubComponents>
|
</Container>
|
||||||
<Component class="javax.swing.JLabel" name="tableStatusPanelLabel">
|
<Component class="javax.swing.JLabel" name="tableStatusPanelLabel">
|
||||||
<Properties>
|
<Properties>
|
||||||
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||||
@ -209,6 +242,4 @@
|
|||||||
</SubComponents>
|
</SubComponents>
|
||||||
</Container>
|
</Container>
|
||||||
</SubComponents>
|
</SubComponents>
|
||||||
</Container>
|
|
||||||
</SubComponents>
|
|
||||||
</Form>
|
</Form>
|
||||||
|
@ -18,55 +18,50 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.centralrepository.contentviewer;
|
package org.sleuthkit.autopsy.centralrepository.contentviewer;
|
||||||
|
|
||||||
import java.awt.Color;
|
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.Dimension;
|
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import javax.swing.GroupLayout;
|
|
||||||
import javax.swing.JFileChooser;
|
import javax.swing.JFileChooser;
|
||||||
import javax.swing.JLabel;
|
|
||||||
import javax.swing.JMenuItem;
|
import javax.swing.JMenuItem;
|
||||||
import javax.swing.JOptionPane;
|
import javax.swing.JOptionPane;
|
||||||
import static javax.swing.JOptionPane.DEFAULT_OPTION;
|
import static javax.swing.JOptionPane.DEFAULT_OPTION;
|
||||||
import static javax.swing.JOptionPane.PLAIN_MESSAGE;
|
import static javax.swing.JOptionPane.PLAIN_MESSAGE;
|
||||||
import static javax.swing.JOptionPane.ERROR_MESSAGE;
|
import static javax.swing.JOptionPane.ERROR_MESSAGE;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JPopupMenu;
|
|
||||||
import javax.swing.JScrollPane;
|
|
||||||
import javax.swing.JTable;
|
|
||||||
import javax.swing.LayoutStyle;
|
|
||||||
import javax.swing.ListSelectionModel;
|
|
||||||
import javax.swing.filechooser.FileNameExtensionFilter;
|
import javax.swing.filechooser.FileNameExtensionFilter;
|
||||||
import javax.swing.table.TableCellRenderer;
|
import javax.swing.table.TableCellRenderer;
|
||||||
import javax.swing.table.TableColumn;
|
import javax.swing.table.TableColumn;
|
||||||
import org.openide.awt.Mnemonics;
|
import org.joda.time.DateTimeZone;
|
||||||
|
import org.joda.time.LocalDateTime;
|
||||||
import org.openide.nodes.Node;
|
import org.openide.nodes.Node;
|
||||||
import org.openide.util.NbBundle;
|
|
||||||
import org.openide.util.NbBundle.Messages;
|
import org.openide.util.NbBundle.Messages;
|
||||||
import org.openide.util.lookup.ServiceProvider;
|
import org.openide.util.lookup.ServiceProvider;
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.AddEditCentralRepoCommentAction;
|
||||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer;
|
import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer;
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttribute;
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttribute;
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifactUtil;
|
import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifactUtil;
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationCase;
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationCase;
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationDataSource;
|
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
|
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
@ -76,9 +71,9 @@ import org.sleuthkit.datamodel.ContentTag;
|
|||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
import org.sleuthkit.datamodel.TskException;
|
import org.sleuthkit.datamodel.TskException;
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
|
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbUtil;
|
||||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||||
import org.sleuthkit.datamodel.TskData;
|
import org.sleuthkit.datamodel.TskData;
|
||||||
import org.sleuthkit.datamodel.TskDataException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* View correlation results from other cases
|
* View correlation results from other cases
|
||||||
@ -89,7 +84,9 @@ import org.sleuthkit.datamodel.TskDataException;
|
|||||||
"DataContentViewerOtherCases.toolTip=Displays instances of the selected file/artifact from other occurrences.",})
|
"DataContentViewerOtherCases.toolTip=Displays instances of the selected file/artifact from other occurrences.",})
|
||||||
public class DataContentViewerOtherCases extends JPanel implements DataContentViewer {
|
public class DataContentViewerOtherCases extends JPanel implements DataContentViewer {
|
||||||
|
|
||||||
private final static Logger LOGGER = Logger.getLogger(DataContentViewerOtherCases.class.getName());
|
private static final long serialVersionUID = -1L;
|
||||||
|
|
||||||
|
private final static Logger logger = Logger.getLogger(DataContentViewerOtherCases.class.getName());
|
||||||
|
|
||||||
private final DataContentViewerOtherCasesTableModel tableModel;
|
private final DataContentViewerOtherCasesTableModel tableModel;
|
||||||
private final Collection<CorrelationAttribute> correlationAttributes;
|
private final Collection<CorrelationAttribute> correlationAttributes;
|
||||||
@ -123,10 +120,20 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
try {
|
try {
|
||||||
saveToCSV();
|
saveToCSV();
|
||||||
} catch (NoCurrentCaseException ex) {
|
} catch (NoCurrentCaseException ex) {
|
||||||
LOGGER.log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS
|
logger.log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS
|
||||||
}
|
}
|
||||||
} else if (jmi.equals(showCommonalityMenuItem)) {
|
} else if (jmi.equals(showCommonalityMenuItem)) {
|
||||||
showCommonalityDetails();
|
showCommonalityDetails();
|
||||||
|
} else if (jmi.equals(addCommentMenuItem)) {
|
||||||
|
try {
|
||||||
|
OtherOccurrenceNodeData selectedNode = (OtherOccurrenceNodeData) tableModel.getRow(otherCasesTable.getSelectedRow());
|
||||||
|
AddEditCentralRepoCommentAction action = AddEditCentralRepoCommentAction.createAddEditCommentAction(selectedNode.createCorrelationAttribute());
|
||||||
|
String currentComment = action.addEditCentralRepoComment();
|
||||||
|
selectedNode.updateComment(currentComment);
|
||||||
|
otherCasesTable.repaint();
|
||||||
|
} catch (EamDbException ex) {
|
||||||
|
logger.log(Level.SEVERE, "Error performing Add/Edit Comment action", ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -135,11 +142,13 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
selectAllMenuItem.addActionListener(actList);
|
selectAllMenuItem.addActionListener(actList);
|
||||||
showCaseDetailsMenuItem.addActionListener(actList);
|
showCaseDetailsMenuItem.addActionListener(actList);
|
||||||
showCommonalityMenuItem.addActionListener(actList);
|
showCommonalityMenuItem.addActionListener(actList);
|
||||||
|
addCommentMenuItem.addActionListener(actList);
|
||||||
|
|
||||||
// Set background of every nth row as light grey.
|
// Set background of every nth row as light grey.
|
||||||
TableCellRenderer renderer = new DataContentViewerOtherCasesTableCellRenderer();
|
TableCellRenderer renderer = new DataContentViewerOtherCasesTableCellRenderer();
|
||||||
otherCasesTable.setDefaultRenderer(Object.class, renderer);
|
otherCasesTable.setDefaultRenderer(Object.class, renderer);
|
||||||
tableStatusPanelLabel.setVisible(false);
|
tableStatusPanelLabel.setVisible(false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Messages({"DataContentViewerOtherCases.correlatedArtifacts.isEmpty=There are no files or artifacts to correlate.",
|
@Messages({"DataContentViewerOtherCases.correlatedArtifacts.isEmpty=There are no files or artifacts to correlate.",
|
||||||
@ -150,7 +159,8 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
"DataContentViewerOtherCases.correlatedArtifacts.title=Attribute Frequency",
|
"DataContentViewerOtherCases.correlatedArtifacts.title=Attribute Frequency",
|
||||||
"DataContentViewerOtherCases.correlatedArtifacts.failed=Failed to get frequency details."})
|
"DataContentViewerOtherCases.correlatedArtifacts.failed=Failed to get frequency details."})
|
||||||
/**
|
/**
|
||||||
* Show how common the selected correlationAttributes are with details dialog.
|
* Show how common the selected correlationAttributes are with details
|
||||||
|
* dialog.
|
||||||
*/
|
*/
|
||||||
private void showCommonalityDetails() {
|
private void showCommonalityDetails() {
|
||||||
if (correlationAttributes.isEmpty()) {
|
if (correlationAttributes.isEmpty()) {
|
||||||
@ -159,7 +169,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
Bundle.DataContentViewerOtherCases_correlatedArtifacts_title(),
|
Bundle.DataContentViewerOtherCases_correlatedArtifacts_title(),
|
||||||
DEFAULT_OPTION, PLAIN_MESSAGE);
|
DEFAULT_OPTION, PLAIN_MESSAGE);
|
||||||
} else {
|
} else {
|
||||||
StringBuilder msg = new StringBuilder();
|
StringBuilder msg = new StringBuilder(correlationAttributes.size());
|
||||||
int percentage;
|
int percentage;
|
||||||
try {
|
try {
|
||||||
EamDb dbManager = EamDb.getInstance();
|
EamDb dbManager = EamDb.getInstance();
|
||||||
@ -174,7 +184,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
Bundle.DataContentViewerOtherCases_correlatedArtifacts_title(),
|
Bundle.DataContentViewerOtherCases_correlatedArtifacts_title(),
|
||||||
DEFAULT_OPTION, PLAIN_MESSAGE);
|
DEFAULT_OPTION, PLAIN_MESSAGE);
|
||||||
} catch (EamDbException ex) {
|
} catch (EamDbException ex) {
|
||||||
LOGGER.log(Level.SEVERE, "Error getting commonality details.", ex);
|
logger.log(Level.SEVERE, "Error getting commonality details.", ex);
|
||||||
JOptionPane.showConfirmDialog(showCommonalityMenuItem,
|
JOptionPane.showConfirmDialog(showCommonalityMenuItem,
|
||||||
Bundle.DataContentViewerOtherCases_correlatedArtifacts_failed(),
|
Bundle.DataContentViewerOtherCases_correlatedArtifacts_failed(),
|
||||||
Bundle.DataContentViewerOtherCases_correlatedArtifacts_title(),
|
Bundle.DataContentViewerOtherCases_correlatedArtifacts_title(),
|
||||||
@ -189,23 +199,14 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
"DataContentViewerOtherCases.caseDetailsDialog.noCaseNameError=Error",
|
"DataContentViewerOtherCases.caseDetailsDialog.noCaseNameError=Error",
|
||||||
"DataContentViewerOtherCases.noOpenCase.errMsg=No open case available."})
|
"DataContentViewerOtherCases.noOpenCase.errMsg=No open case available."})
|
||||||
private void showCaseDetails(int selectedRowViewIdx) {
|
private void showCaseDetails(int selectedRowViewIdx) {
|
||||||
Case openCase;
|
|
||||||
try {
|
|
||||||
openCase = Case.getCurrentCaseThrows();
|
|
||||||
} catch (NoCurrentCaseException ex) {
|
|
||||||
JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
|
|
||||||
Bundle.DataContentViewerOtherCases_noOpenCase_errMsg(),
|
|
||||||
Bundle.DataContentViewerOtherCases_noOpenCase_errMsg(),
|
|
||||||
DEFAULT_OPTION, PLAIN_MESSAGE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String caseDisplayName = Bundle.DataContentViewerOtherCases_caseDetailsDialog_noCaseNameError();
|
String caseDisplayName = Bundle.DataContentViewerOtherCases_caseDetailsDialog_noCaseNameError();
|
||||||
try {
|
try {
|
||||||
if (-1 != selectedRowViewIdx) {
|
if (-1 != selectedRowViewIdx) {
|
||||||
EamDb dbManager = EamDb.getInstance();
|
EamDb dbManager = EamDb.getInstance();
|
||||||
int selectedRowModelIdx = otherCasesTable.convertRowIndexToModel(selectedRowViewIdx);
|
int selectedRowModelIdx = otherCasesTable.convertRowIndexToModel(selectedRowViewIdx);
|
||||||
CorrelationAttribute eamArtifact = (CorrelationAttribute) tableModel.getRow(selectedRowModelIdx);
|
OtherOccurrenceNodeData nodeData = (OtherOccurrenceNodeData) tableModel.getRow(selectedRowModelIdx);
|
||||||
CorrelationCase eamCasePartial = eamArtifact.getInstances().get(0).getCorrelationCase();
|
CorrelationCase eamCasePartial = nodeData.getCorrelationAttributeInstance().getCorrelationCase();
|
||||||
if (eamCasePartial == null) {
|
if (eamCasePartial == null) {
|
||||||
JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
|
JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
|
||||||
Bundle.DataContentViewerOtherCases_caseDetailsDialog_noDetailsReference(),
|
Bundle.DataContentViewerOtherCases_caseDetailsDialog_noDetailsReference(),
|
||||||
@ -215,7 +216,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
}
|
}
|
||||||
caseDisplayName = eamCasePartial.getDisplayName();
|
caseDisplayName = eamCasePartial.getDisplayName();
|
||||||
// query case details
|
// query case details
|
||||||
CorrelationCase eamCase = dbManager.getCase(openCase);
|
CorrelationCase eamCase = dbManager.getCaseByUUID(eamCasePartial.getCaseUUID());
|
||||||
if (eamCase == null) {
|
if (eamCase == null) {
|
||||||
JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
|
JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
|
||||||
Bundle.DataContentViewerOtherCases_caseDetailsDialog_noDetails(),
|
Bundle.DataContentViewerOtherCases_caseDetailsDialog_noDetails(),
|
||||||
@ -236,6 +237,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
DEFAULT_OPTION, PLAIN_MESSAGE);
|
DEFAULT_OPTION, PLAIN_MESSAGE);
|
||||||
}
|
}
|
||||||
} catch (EamDbException ex) {
|
} catch (EamDbException ex) {
|
||||||
|
logger.log(Level.SEVERE, "Error loading case details", ex);
|
||||||
JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
|
JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
|
||||||
Bundle.DataContentViewerOtherCases_caseDetailsDialog_noDetails(),
|
Bundle.DataContentViewerOtherCases_caseDetailsDialog_noDetails(),
|
||||||
caseDisplayName,
|
caseDisplayName,
|
||||||
@ -298,7 +300,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
}
|
}
|
||||||
|
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
LOGGER.log(Level.SEVERE, "Error writing selected rows to CSV.", ex);
|
logger.log(Level.SEVERE, "Error writing selected rows to CSV.", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -309,6 +311,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
// start with empty table
|
// start with empty table
|
||||||
tableModel.clearTable();
|
tableModel.clearTable();
|
||||||
correlationAttributes.clear();
|
correlationAttributes.clear();
|
||||||
|
earliestCaseDate.setText(Bundle.DataContentViewerOtherCases_earliestCaseNotAvailable());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -389,7 +392,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
try {
|
try {
|
||||||
content = nodeBbArtifact.getSleuthkitCase().getContentById(nodeBbArtifact.getObjectID());
|
content = nodeBbArtifact.getSleuthkitCase().getContentById(nodeBbArtifact.getObjectID());
|
||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
LOGGER.log(Level.SEVERE, "Error retrieving blackboard artifact", ex); // NON-NLS
|
logger.log(Level.SEVERE, "Error retrieving blackboard artifact", ex); // NON-NLS
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -435,7 +438,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (EamDbException ex) {
|
} catch (EamDbException ex) {
|
||||||
LOGGER.log(Level.SEVERE, "Error connecting to DB", ex); // NON-NLS
|
logger.log(Level.SEVERE, "Error connecting to DB", ex); // NON-NLS
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -448,65 +451,123 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (EamDbException ex) {
|
} catch (EamDbException ex) {
|
||||||
LOGGER.log(Level.SEVERE, "Error connecting to DB", ex); // NON-NLS
|
logger.log(Level.SEVERE, "Error connecting to DB", ex); // NON-NLS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Messages({"DataContentViewerOtherCases.earliestCaseNotAvailable= Not Enabled."})
|
||||||
/**
|
/**
|
||||||
* Query the db for artifact instances from other cases correlated to the
|
* Gets the list of Eam Cases and determines the earliest case creation date.
|
||||||
* given central repository artifact. Will not show instances from the same
|
* Sets the label to display the earliest date string to the user.
|
||||||
* datasource / device
|
*/
|
||||||
|
private void setEarliestCaseDate() {
|
||||||
|
String dateStringDisplay = Bundle.DataContentViewerOtherCases_earliestCaseNotAvailable();
|
||||||
|
|
||||||
|
if (EamDb.isEnabled()) {
|
||||||
|
LocalDateTime earliestDate = LocalDateTime.now(DateTimeZone.UTC);
|
||||||
|
DateFormat datetimeFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss", Locale.US);
|
||||||
|
try {
|
||||||
|
EamDb dbManager = EamDb.getInstance();
|
||||||
|
List<CorrelationCase> cases = dbManager.getCases();
|
||||||
|
for (CorrelationCase aCase : cases) {
|
||||||
|
LocalDateTime caseDate = LocalDateTime.fromDateFields(datetimeFormat.parse(aCase.getCreationDate()));
|
||||||
|
|
||||||
|
if (caseDate.isBefore(earliestDate)) {
|
||||||
|
earliestDate = caseDate;
|
||||||
|
dateStringDisplay = aCase.getCreationDate();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (EamDbException ex) {
|
||||||
|
logger.log(Level.SEVERE, "Error getting list of cases from database.", ex); // NON-NLS
|
||||||
|
} catch (ParseException ex) {
|
||||||
|
logger.log(Level.SEVERE, "Error parsing date of cases from database.", ex); // NON-NLS
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
earliestCaseDate.setText(dateStringDisplay);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query the central repo database (if enabled) and the case database to find all
|
||||||
|
* artifact instances correlated to the given central repository artifact. If the
|
||||||
|
* central repo is not enabled, this will only return files from the current case
|
||||||
|
* with matching MD5 hashes.
|
||||||
*
|
*
|
||||||
* @param corAttr CorrelationAttribute to query for
|
* @param corAttr CorrelationAttribute to query for
|
||||||
* @param dataSourceName Data source to filter results
|
* @param dataSourceName Data source to filter results
|
||||||
* @param deviceId Device Id to filter results
|
* @param deviceId Device Id to filter results
|
||||||
*
|
*
|
||||||
* @return A collection of correlated artifact instances from other cases
|
* @return A collection of correlated artifact instances
|
||||||
*/
|
*/
|
||||||
private Map<UniquePathKey,CorrelationAttributeInstance> getCorrelatedInstances(CorrelationAttribute corAttr, String dataSourceName, String deviceId) {
|
private Map<UniquePathKey,OtherOccurrenceNodeData> getCorrelatedInstances(CorrelationAttribute corAttr, String dataSourceName, String deviceId) {
|
||||||
// @@@ Check exception
|
// @@@ Check exception
|
||||||
try {
|
try {
|
||||||
final Case openCase = Case.getCurrentCase();
|
final Case openCase = Case.getCurrentCase();
|
||||||
String caseUUID = openCase.getName();
|
String caseUUID = openCase.getName();
|
||||||
HashMap<UniquePathKey,CorrelationAttributeInstance> artifactInstances = new HashMap<>();
|
|
||||||
|
HashMap<UniquePathKey,OtherOccurrenceNodeData> nodeDataMap = new HashMap<>();
|
||||||
|
|
||||||
if (EamDb.isEnabled()) {
|
if (EamDb.isEnabled()) {
|
||||||
EamDb dbManager = EamDb.getInstance();
|
List<CorrelationAttributeInstance> instances = EamDb.getInstance().getArtifactInstancesByTypeValue(corAttr.getCorrelationType(), corAttr.getCorrelationValue());
|
||||||
artifactInstances.putAll(dbManager.getArtifactInstancesByTypeValue(corAttr.getCorrelationType(), corAttr.getCorrelationValue()).stream()
|
|
||||||
.filter(artifactInstance -> !artifactInstance.getCorrelationCase().getCaseUUID().equals(caseUUID)
|
for (CorrelationAttributeInstance artifactInstance:instances) {
|
||||||
|
|
||||||
|
// Only add the attribute if it isn't the object the user selected.
|
||||||
|
// We consider it to be a different object if at least one of the following is true:
|
||||||
|
// - the case UUID is different
|
||||||
|
// - the data source name is different
|
||||||
|
// - the data source device ID is different
|
||||||
|
// - the file path is different
|
||||||
|
if (!artifactInstance.getCorrelationCase().getCaseUUID().equals(caseUUID)
|
||||||
|| !artifactInstance.getCorrelationDataSource().getName().equals(dataSourceName)
|
|| !artifactInstance.getCorrelationDataSource().getName().equals(dataSourceName)
|
||||||
|| !artifactInstance.getCorrelationDataSource().getDeviceID().equals(deviceId))
|
|| !artifactInstance.getCorrelationDataSource().getDeviceID().equals(deviceId)
|
||||||
.collect(Collectors.toMap(correlationAttr -> new UniquePathKey(correlationAttr.getCorrelationDataSource().getDeviceID(), correlationAttr.getFilePath()),
|
|| !artifactInstance.getFilePath().equalsIgnoreCase(file.getParentPath() + file.getName())) {
|
||||||
correlationAttr -> correlationAttr)));
|
|
||||||
|
OtherOccurrenceNodeData newNode = new OtherOccurrenceNodeData(artifactInstance, corAttr.getCorrelationType(), corAttr.getCorrelationValue());
|
||||||
|
UniquePathKey uniquePathKey = new UniquePathKey(newNode);
|
||||||
|
nodeDataMap.put(uniquePathKey, newNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (corAttr.getCorrelationType().getDisplayName().equals("Files")) {
|
if (corAttr.getCorrelationType().getDisplayName().equals("Files")) {
|
||||||
List<AbstractFile> caseDbFiles = addCaseDbMatches(corAttr, openCase);
|
List<AbstractFile> caseDbFiles = getCaseDbMatches(corAttr, openCase);
|
||||||
|
|
||||||
for (AbstractFile caseDbFile : caseDbFiles) {
|
for (AbstractFile caseDbFile : caseDbFiles) {
|
||||||
addOrUpdateAttributeInstance(openCase, artifactInstances, caseDbFile);
|
addOrUpdateNodeData(openCase, nodeDataMap, caseDbFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return artifactInstances;
|
return nodeDataMap;
|
||||||
} catch (EamDbException ex) {
|
} catch (EamDbException ex) {
|
||||||
LOGGER.log(Level.SEVERE, "Error getting artifact instances from database.", ex); // NON-NLS
|
logger.log(Level.SEVERE, "Error getting artifact instances from database.", ex); // NON-NLS
|
||||||
} catch (NoCurrentCaseException ex) {
|
} catch (NoCurrentCaseException ex) {
|
||||||
LOGGER.log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS
|
logger.log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS
|
||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
// do nothing.
|
// do nothing.
|
||||||
// @@@ Review this behavior
|
// @@@ Review this behavior
|
||||||
LOGGER.log(Level.SEVERE, "Exception while querying open case.", ex); // NON-NLS
|
logger.log(Level.SEVERE, "Exception while querying open case.", ex); // NON-NLS
|
||||||
}
|
}
|
||||||
|
|
||||||
return new HashMap<>(0);
|
return new HashMap<>(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<AbstractFile> addCaseDbMatches(CorrelationAttribute corAttr, Case openCase) throws NoCurrentCaseException, TskCoreException, EamDbException {
|
/**
|
||||||
|
* Get all other abstract files in the current case with the same MD5 as the selected node.
|
||||||
|
* @param corAttr The CorrelationAttribute containing the MD5 to search for
|
||||||
|
* @param openCase The current case
|
||||||
|
* @return List of matching AbstractFile objects
|
||||||
|
* @throws NoCurrentCaseException
|
||||||
|
* @throws TskCoreException
|
||||||
|
* @throws EamDbException
|
||||||
|
*/
|
||||||
|
private List<AbstractFile> getCaseDbMatches(CorrelationAttribute corAttr, Case openCase) throws NoCurrentCaseException, TskCoreException, EamDbException {
|
||||||
String md5 = corAttr.getCorrelationValue();
|
String md5 = corAttr.getCorrelationValue();
|
||||||
|
|
||||||
SleuthkitCase tsk = openCase.getSleuthkitCase();
|
SleuthkitCase tsk = openCase.getSleuthkitCase();
|
||||||
List<AbstractFile> matches = tsk.findAllFilesWhere(String.format("md5 = '%s'", new Object[]{md5}));
|
List<AbstractFile> matches = tsk.findAllFilesWhere(String.format("md5 = '%s'", new Object[]{md5}));
|
||||||
|
|
||||||
@ -522,75 +583,64 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the file to the artifactInstances map if it does not already exist
|
* Adds the file to the nodeDataMap map if it does not already exist
|
||||||
*
|
*
|
||||||
* @param autopsyCase
|
* @param autopsyCase
|
||||||
* @param artifactInstances
|
* @param nodeDataMap
|
||||||
* @param newFile
|
* @param newFile
|
||||||
|
*
|
||||||
* @throws TskCoreException
|
* @throws TskCoreException
|
||||||
* @throws EamDbException
|
* @throws EamDbException
|
||||||
*/
|
*/
|
||||||
private void addOrUpdateAttributeInstance(final Case autopsyCase, Map<UniquePathKey,CorrelationAttributeInstance> artifactInstances, AbstractFile newFile) throws TskCoreException, EamDbException {
|
private void addOrUpdateNodeData(final Case autopsyCase, Map<UniquePathKey,OtherOccurrenceNodeData> nodeDataMap, AbstractFile newFile) throws TskCoreException, EamDbException {
|
||||||
|
|
||||||
// figure out if the casedb file is known via either hash or tags
|
OtherOccurrenceNodeData newNode = new OtherOccurrenceNodeData(newFile, autopsyCase);
|
||||||
TskData.FileKnown localKnown = newFile.getKnown();
|
|
||||||
|
|
||||||
if (localKnown != TskData.FileKnown.BAD) {
|
// If the caseDB object has a notable tag associated with it, update
|
||||||
|
// the known status to BAD
|
||||||
|
if (newNode.getKnown() != TskData.FileKnown.BAD) {
|
||||||
List<ContentTag> fileMatchTags = autopsyCase.getServices().getTagsManager().getContentTagsByContent(newFile);
|
List<ContentTag> fileMatchTags = autopsyCase.getServices().getTagsManager().getContentTagsByContent(newFile);
|
||||||
for (ContentTag tag : fileMatchTags) {
|
for (ContentTag tag : fileMatchTags) {
|
||||||
TskData.FileKnown tagKnownStatus = tag.getName().getKnownStatus();
|
TskData.FileKnown tagKnownStatus = tag.getName().getKnownStatus();
|
||||||
if (tagKnownStatus.equals(TskData.FileKnown.BAD)) {
|
if (tagKnownStatus.equals(TskData.FileKnown.BAD)) {
|
||||||
localKnown = TskData.FileKnown.BAD;
|
newNode.updateKnown(TskData.FileKnown.BAD);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// make a key to see if the file is already in the map
|
// Make a key to see if the file is already in the map
|
||||||
String filePath = newFile.getParentPath() + newFile.getName();
|
UniquePathKey uniquePathKey = new UniquePathKey(newNode);
|
||||||
String deviceId;
|
|
||||||
try {
|
|
||||||
deviceId = autopsyCase.getSleuthkitCase().getDataSource(newFile.getDataSource().getId()).getDeviceId();
|
|
||||||
} catch (TskDataException | TskCoreException ex) {
|
|
||||||
LOGGER.log(Level.WARNING, "Error getting data source info: " + ex);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
UniquePathKey uniquePathKey = new UniquePathKey(deviceId, filePath);
|
|
||||||
|
|
||||||
// double check that the CR version is BAD if the caseDB version is BAD.
|
// If this node is already in the list, the only thing we need to do is
|
||||||
if (artifactInstances.containsKey(uniquePathKey)) {
|
// update the known status to BAD if the caseDB version had known status BAD.
|
||||||
if (localKnown == TskData.FileKnown.BAD) {
|
// Otherwise this is a new node so add the new node to the map.
|
||||||
CorrelationAttributeInstance prevInstance = artifactInstances.get(uniquePathKey);
|
if (nodeDataMap.containsKey(uniquePathKey)) {
|
||||||
prevInstance.setKnownStatus(localKnown);
|
if (newNode.getKnown() == TskData.FileKnown.BAD) {
|
||||||
|
OtherOccurrenceNodeData prevInstance = nodeDataMap.get(uniquePathKey);
|
||||||
|
prevInstance.updateKnown(newNode.getKnown());
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
// add the data from the case DB by pushing data into CorrelationAttributeInstance class
|
nodeDataMap.put(uniquePathKey, newNode);
|
||||||
else {
|
|
||||||
// NOTE: If we are in here, it is likely because CR is not enabled. So, we cannot rely
|
|
||||||
// on any of the methods that query the DB.
|
|
||||||
CorrelationCase correlationCase = new CorrelationCase(autopsyCase.getName(), autopsyCase.getDisplayName());
|
|
||||||
|
|
||||||
CorrelationDataSource correlationDataSource = CorrelationDataSource.fromTSKDataSource(correlationCase, newFile.getDataSource());
|
|
||||||
|
|
||||||
CorrelationAttributeInstance caseDbInstance = new CorrelationAttributeInstance(correlationCase, correlationDataSource, filePath, "", localKnown);
|
|
||||||
artifactInstances.put(uniquePathKey, caseDbInstance);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSupported(Node node) {
|
public boolean isSupported(Node node) {
|
||||||
this.file = this.getAbstractFileFromNode(node);
|
|
||||||
// Is supported if this node
|
|
||||||
// has correlatable content (File, BlackboardArtifact) OR
|
|
||||||
// other common files across datasources.
|
|
||||||
|
|
||||||
|
// Is supported if one of the following is true:
|
||||||
|
// - The central repo is enabled and the node has correlatable content
|
||||||
|
// (either through the MD5 hash of the associated file or through a BlackboardArtifact)
|
||||||
|
// - The central repo is disabled and the backing file has a valid MD5 hash
|
||||||
|
this.file = this.getAbstractFileFromNode(node);
|
||||||
if (EamDb.isEnabled()) {
|
if (EamDb.isEnabled()) {
|
||||||
return this.file != null
|
return this.file != null
|
||||||
&& this.file.getSize() > 0
|
&& this.file.getSize() > 0
|
||||||
&& !getCorrelationAttributesFromNode(node).isEmpty();
|
&& !getCorrelationAttributesFromNode(node).isEmpty();
|
||||||
} else {
|
} else {
|
||||||
return this.file != null
|
return this.file != null
|
||||||
&& this.file.getSize() > 0;
|
&& this.file.getSize() > 0
|
||||||
|
&& ((this.file.getMd5Hash() != null) && ( ! this.file.getMd5Hash().isEmpty()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -632,22 +682,14 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
// get the attributes we can correlate on
|
// get the attributes we can correlate on
|
||||||
correlationAttributes.addAll(getCorrelationAttributesFromNode(node));
|
correlationAttributes.addAll(getCorrelationAttributesFromNode(node));
|
||||||
for (CorrelationAttribute corAttr : correlationAttributes) {
|
for (CorrelationAttribute corAttr : correlationAttributes) {
|
||||||
Map<UniquePathKey, CorrelationAttributeInstance> corAttrInstances = new HashMap<>(0);
|
Map<UniquePathKey,OtherOccurrenceNodeData> correlatedNodeDataMap = new HashMap<>(0);
|
||||||
|
|
||||||
// get correlation and reference set instances from DB
|
// get correlation and reference set instances from DB
|
||||||
corAttrInstances.putAll(getCorrelatedInstances(corAttr, dataSourceName, deviceId));
|
correlatedNodeDataMap.putAll(getCorrelatedInstances(corAttr, dataSourceName, deviceId));
|
||||||
|
|
||||||
|
correlatedNodeDataMap.values().forEach((nodeData) -> {
|
||||||
|
tableModel.addNodeData(nodeData);
|
||||||
|
|
||||||
corAttrInstances.values().forEach((corAttrInstance) -> {
|
|
||||||
try {
|
|
||||||
CorrelationAttribute newCeArtifact = new CorrelationAttribute(
|
|
||||||
corAttr.getCorrelationType(),
|
|
||||||
corAttr.getCorrelationValue()
|
|
||||||
);
|
|
||||||
newCeArtifact.addInstance(corAttrInstance);
|
|
||||||
tableModel.addEamArtifact(newCeArtifact);
|
|
||||||
} catch (EamDbException ex) {
|
|
||||||
LOGGER.log(Level.SEVERE, "Error creating correlation attribute", ex);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -660,6 +702,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
clearMessageOnTableStatusPanel();
|
clearMessageOnTableStatusPanel();
|
||||||
setColumnWidths();
|
setColumnWidths();
|
||||||
}
|
}
|
||||||
|
setEarliestCaseDate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setColumnWidths() {
|
private void setColumnWidths() {
|
||||||
@ -690,159 +733,206 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||||
private void initComponents() {
|
private void initComponents() {
|
||||||
|
|
||||||
rightClickPopupMenu = new JPopupMenu();
|
rightClickPopupMenu = new javax.swing.JPopupMenu();
|
||||||
selectAllMenuItem = new JMenuItem();
|
selectAllMenuItem = new javax.swing.JMenuItem();
|
||||||
exportToCSVMenuItem = new JMenuItem();
|
exportToCSVMenuItem = new javax.swing.JMenuItem();
|
||||||
showCaseDetailsMenuItem = new JMenuItem();
|
showCaseDetailsMenuItem = new javax.swing.JMenuItem();
|
||||||
showCommonalityMenuItem = new JMenuItem();
|
showCommonalityMenuItem = new javax.swing.JMenuItem();
|
||||||
CSVFileChooser = new JFileChooser();
|
addCommentMenuItem = new javax.swing.JMenuItem();
|
||||||
otherCasesPanel = new JPanel();
|
CSVFileChooser = new javax.swing.JFileChooser();
|
||||||
tableContainerPanel = new JPanel();
|
otherCasesPanel = new javax.swing.JPanel();
|
||||||
tableScrollPane = new JScrollPane();
|
tableContainerPanel = new javax.swing.JPanel();
|
||||||
otherCasesTable = new JTable();
|
tableScrollPane = new javax.swing.JScrollPane();
|
||||||
tableStatusPanel = new JPanel();
|
otherCasesTable = new javax.swing.JTable();
|
||||||
tableStatusPanelLabel = new JLabel();
|
earliestCaseLabel = new javax.swing.JLabel();
|
||||||
|
earliestCaseDate = new javax.swing.JLabel();
|
||||||
|
tableStatusPanel = new javax.swing.JPanel();
|
||||||
|
tableStatusPanelLabel = new javax.swing.JLabel();
|
||||||
|
|
||||||
Mnemonics.setLocalizedText(selectAllMenuItem, NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.selectAllMenuItem.text")); // NOI18N
|
rightClickPopupMenu.addPopupMenuListener(new javax.swing.event.PopupMenuListener() {
|
||||||
|
public void popupMenuCanceled(javax.swing.event.PopupMenuEvent evt) {
|
||||||
|
}
|
||||||
|
public void popupMenuWillBecomeInvisible(javax.swing.event.PopupMenuEvent evt) {
|
||||||
|
}
|
||||||
|
public void popupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent evt) {
|
||||||
|
rightClickPopupMenuPopupMenuWillBecomeVisible(evt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(selectAllMenuItem, org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.selectAllMenuItem.text")); // NOI18N
|
||||||
rightClickPopupMenu.add(selectAllMenuItem);
|
rightClickPopupMenu.add(selectAllMenuItem);
|
||||||
|
|
||||||
Mnemonics.setLocalizedText(exportToCSVMenuItem, NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.exportToCSVMenuItem.text")); // NOI18N
|
org.openide.awt.Mnemonics.setLocalizedText(exportToCSVMenuItem, org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.exportToCSVMenuItem.text")); // NOI18N
|
||||||
rightClickPopupMenu.add(exportToCSVMenuItem);
|
rightClickPopupMenu.add(exportToCSVMenuItem);
|
||||||
|
|
||||||
Mnemonics.setLocalizedText(showCaseDetailsMenuItem, NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.showCaseDetailsMenuItem.text")); // NOI18N
|
org.openide.awt.Mnemonics.setLocalizedText(showCaseDetailsMenuItem, org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.showCaseDetailsMenuItem.text")); // NOI18N
|
||||||
rightClickPopupMenu.add(showCaseDetailsMenuItem);
|
rightClickPopupMenu.add(showCaseDetailsMenuItem);
|
||||||
|
|
||||||
Mnemonics.setLocalizedText(showCommonalityMenuItem, NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.showCommonalityMenuItem.text")); // NOI18N
|
org.openide.awt.Mnemonics.setLocalizedText(showCommonalityMenuItem, org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.showCommonalityMenuItem.text")); // NOI18N
|
||||||
rightClickPopupMenu.add(showCommonalityMenuItem);
|
rightClickPopupMenu.add(showCommonalityMenuItem);
|
||||||
|
|
||||||
setMinimumSize(new Dimension(1500, 10));
|
org.openide.awt.Mnemonics.setLocalizedText(addCommentMenuItem, org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.addCommentMenuItem.text")); // NOI18N
|
||||||
|
rightClickPopupMenu.add(addCommentMenuItem);
|
||||||
|
|
||||||
|
setMinimumSize(new java.awt.Dimension(1500, 10));
|
||||||
setOpaque(false);
|
setOpaque(false);
|
||||||
setPreferredSize(new Dimension(1500, 44));
|
setPreferredSize(new java.awt.Dimension(1500, 44));
|
||||||
|
|
||||||
otherCasesPanel.setPreferredSize(new Dimension(1500, 144));
|
otherCasesPanel.setPreferredSize(new java.awt.Dimension(1500, 144));
|
||||||
|
|
||||||
tableContainerPanel.setPreferredSize(new Dimension(1500, 63));
|
tableContainerPanel.setPreferredSize(new java.awt.Dimension(1500, 63));
|
||||||
|
|
||||||
tableScrollPane.setPreferredSize(new Dimension(1500, 30));
|
tableScrollPane.setPreferredSize(new java.awt.Dimension(1500, 30));
|
||||||
|
|
||||||
otherCasesTable.setAutoCreateRowSorter(true);
|
otherCasesTable.setAutoCreateRowSorter(true);
|
||||||
otherCasesTable.setModel(tableModel);
|
otherCasesTable.setModel(tableModel);
|
||||||
otherCasesTable.setToolTipText(NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.table.toolTip.text")); // NOI18N
|
otherCasesTable.setToolTipText(org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.table.toolTip.text")); // NOI18N
|
||||||
otherCasesTable.setComponentPopupMenu(rightClickPopupMenu);
|
otherCasesTable.setComponentPopupMenu(rightClickPopupMenu);
|
||||||
otherCasesTable.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
|
otherCasesTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_INTERVAL_SELECTION);
|
||||||
tableScrollPane.setViewportView(otherCasesTable);
|
tableScrollPane.setViewportView(otherCasesTable);
|
||||||
|
|
||||||
tableStatusPanel.setPreferredSize(new Dimension(1500, 16));
|
org.openide.awt.Mnemonics.setLocalizedText(earliestCaseLabel, org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.earliestCaseLabel.text")); // NOI18N
|
||||||
|
earliestCaseLabel.setToolTipText(org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.earliestCaseLabel.toolTipText")); // NOI18N
|
||||||
|
|
||||||
tableStatusPanelLabel.setForeground(new Color(255, 0, 51));
|
org.openide.awt.Mnemonics.setLocalizedText(earliestCaseDate, org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.earliestCaseDate.text")); // NOI18N
|
||||||
|
|
||||||
GroupLayout tableStatusPanelLayout = new GroupLayout(tableStatusPanel);
|
tableStatusPanel.setPreferredSize(new java.awt.Dimension(1500, 16));
|
||||||
|
|
||||||
|
javax.swing.GroupLayout tableStatusPanelLayout = new javax.swing.GroupLayout(tableStatusPanel);
|
||||||
tableStatusPanel.setLayout(tableStatusPanelLayout);
|
tableStatusPanel.setLayout(tableStatusPanelLayout);
|
||||||
tableStatusPanelLayout.setHorizontalGroup(tableStatusPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
tableStatusPanelLayout.setHorizontalGroup(
|
||||||
|
tableStatusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addGap(0, 0, Short.MAX_VALUE)
|
.addGap(0, 0, Short.MAX_VALUE)
|
||||||
.addGroup(tableStatusPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
|
||||||
.addGroup(tableStatusPanelLayout.createSequentialGroup()
|
|
||||||
.addContainerGap()
|
|
||||||
.addComponent(tableStatusPanelLabel, GroupLayout.DEFAULT_SIZE, 780, Short.MAX_VALUE)
|
|
||||||
.addContainerGap()))
|
|
||||||
);
|
);
|
||||||
tableStatusPanelLayout.setVerticalGroup(tableStatusPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
tableStatusPanelLayout.setVerticalGroup(
|
||||||
|
tableStatusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addGap(0, 16, Short.MAX_VALUE)
|
.addGap(0, 16, Short.MAX_VALUE)
|
||||||
.addGroup(tableStatusPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
|
||||||
.addGroup(tableStatusPanelLayout.createSequentialGroup()
|
|
||||||
.addComponent(tableStatusPanelLabel, GroupLayout.PREFERRED_SIZE, 16, GroupLayout.PREFERRED_SIZE)
|
|
||||||
.addGap(0, 0, Short.MAX_VALUE)))
|
|
||||||
);
|
);
|
||||||
|
|
||||||
GroupLayout tableContainerPanelLayout = new GroupLayout(tableContainerPanel);
|
tableStatusPanelLabel.setForeground(new java.awt.Color(255, 0, 51));
|
||||||
|
|
||||||
|
javax.swing.GroupLayout tableContainerPanelLayout = new javax.swing.GroupLayout(tableContainerPanel);
|
||||||
tableContainerPanel.setLayout(tableContainerPanelLayout);
|
tableContainerPanel.setLayout(tableContainerPanelLayout);
|
||||||
tableContainerPanelLayout.setHorizontalGroup(tableContainerPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
tableContainerPanelLayout.setHorizontalGroup(
|
||||||
.addComponent(tableScrollPane, GroupLayout.Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addComponent(tableStatusPanel, GroupLayout.Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, tableContainerPanelLayout.createSequentialGroup()
|
||||||
);
|
.addComponent(tableStatusPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 1282, Short.MAX_VALUE)
|
||||||
tableContainerPanelLayout.setVerticalGroup(tableContainerPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
.addGap(218, 218, 218))
|
||||||
|
.addComponent(tableScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||||
.addGroup(tableContainerPanelLayout.createSequentialGroup()
|
.addGroup(tableContainerPanelLayout.createSequentialGroup()
|
||||||
.addComponent(tableScrollPane, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
.addComponent(earliestCaseLabel)
|
||||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addComponent(tableStatusPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
|
.addComponent(earliestCaseDate)
|
||||||
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||||
|
.addComponent(tableStatusPanelLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||||
.addContainerGap())
|
.addContainerGap())
|
||||||
);
|
);
|
||||||
|
tableContainerPanelLayout.setVerticalGroup(
|
||||||
GroupLayout otherCasesPanelLayout = new GroupLayout(otherCasesPanel);
|
tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
otherCasesPanel.setLayout(otherCasesPanelLayout);
|
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, tableContainerPanelLayout.createSequentialGroup()
|
||||||
otherCasesPanelLayout.setHorizontalGroup(otherCasesPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
.addComponent(tableScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 176, Short.MAX_VALUE)
|
||||||
.addGap(0, 1500, Short.MAX_VALUE)
|
.addGap(0, 0, 0)
|
||||||
.addGroup(otherCasesPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
.addGroup(tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||||
.addComponent(tableContainerPanel, GroupLayout.Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
.addGroup(tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||||
|
.addComponent(earliestCaseLabel)
|
||||||
|
.addComponent(earliestCaseDate))
|
||||||
|
.addComponent(tableStatusPanelLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||||
|
.addGap(0, 0, 0)
|
||||||
|
.addComponent(tableStatusPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
|
.addGap(0, 0, 0))
|
||||||
);
|
);
|
||||||
otherCasesPanelLayout.setVerticalGroup(otherCasesPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
|
||||||
.addGap(0, 60, Short.MAX_VALUE)
|
javax.swing.GroupLayout otherCasesPanelLayout = new javax.swing.GroupLayout(otherCasesPanel);
|
||||||
.addGroup(otherCasesPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
otherCasesPanel.setLayout(otherCasesPanelLayout);
|
||||||
|
otherCasesPanelLayout.setHorizontalGroup(
|
||||||
|
otherCasesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGap(0, 1500, Short.MAX_VALUE)
|
||||||
|
.addGroup(otherCasesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addComponent(tableContainerPanel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||||
|
);
|
||||||
|
otherCasesPanelLayout.setVerticalGroup(
|
||||||
|
otherCasesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGap(0, 483, Short.MAX_VALUE)
|
||||||
|
.addGroup(otherCasesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addGroup(otherCasesPanelLayout.createSequentialGroup()
|
.addGroup(otherCasesPanelLayout.createSequentialGroup()
|
||||||
.addComponent(tableContainerPanel, GroupLayout.DEFAULT_SIZE, 60, Short.MAX_VALUE)
|
.addComponent(tableContainerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 483, Short.MAX_VALUE)
|
||||||
.addGap(0, 0, 0)))
|
.addGap(0, 0, 0)))
|
||||||
);
|
);
|
||||||
|
|
||||||
GroupLayout layout = new GroupLayout(this);
|
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||||
this.setLayout(layout);
|
this.setLayout(layout);
|
||||||
layout.setHorizontalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
layout.setHorizontalGroup(
|
||||||
.addComponent(otherCasesPanel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addComponent(otherCasesPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||||
);
|
);
|
||||||
layout.setVerticalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
layout.setVerticalGroup(
|
||||||
.addComponent(otherCasesPanel, GroupLayout.DEFAULT_SIZE, 60, Short.MAX_VALUE)
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addComponent(otherCasesPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 483, Short.MAX_VALUE)
|
||||||
);
|
);
|
||||||
}// </editor-fold>//GEN-END:initComponents
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
|
|
||||||
|
private void rightClickPopupMenuPopupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent evt) {//GEN-FIRST:event_rightClickPopupMenuPopupMenuWillBecomeVisible
|
||||||
|
boolean enableCentralRepoActions = false;
|
||||||
|
|
||||||
|
if (EamDbUtil.useCentralRepo() && otherCasesTable.getSelectedRowCount() == 1) {
|
||||||
|
int rowIndex = otherCasesTable.getSelectedRow();
|
||||||
|
OtherOccurrenceNodeData selectedNode = (OtherOccurrenceNodeData) tableModel.getRow(rowIndex);
|
||||||
|
if (selectedNode.isCentralRepoNode()) {
|
||||||
|
enableCentralRepoActions = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addCommentMenuItem.setVisible(enableCentralRepoActions);
|
||||||
|
showCaseDetailsMenuItem.setVisible(enableCentralRepoActions);
|
||||||
|
showCommonalityMenuItem.setVisible(enableCentralRepoActions);
|
||||||
|
}//GEN-LAST:event_rightClickPopupMenuPopupMenuWillBecomeVisible
|
||||||
|
|
||||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
private JFileChooser CSVFileChooser;
|
private javax.swing.JFileChooser CSVFileChooser;
|
||||||
private JMenuItem exportToCSVMenuItem;
|
private javax.swing.JMenuItem addCommentMenuItem;
|
||||||
private JPanel otherCasesPanel;
|
private javax.swing.JLabel earliestCaseDate;
|
||||||
private JTable otherCasesTable;
|
private javax.swing.JLabel earliestCaseLabel;
|
||||||
private JPopupMenu rightClickPopupMenu;
|
private javax.swing.JMenuItem exportToCSVMenuItem;
|
||||||
private JMenuItem selectAllMenuItem;
|
private javax.swing.JPanel otherCasesPanel;
|
||||||
private JMenuItem showCaseDetailsMenuItem;
|
private javax.swing.JTable otherCasesTable;
|
||||||
private JMenuItem showCommonalityMenuItem;
|
private javax.swing.JPopupMenu rightClickPopupMenu;
|
||||||
private JPanel tableContainerPanel;
|
private javax.swing.JMenuItem selectAllMenuItem;
|
||||||
private JScrollPane tableScrollPane;
|
private javax.swing.JMenuItem showCaseDetailsMenuItem;
|
||||||
private JPanel tableStatusPanel;
|
private javax.swing.JMenuItem showCommonalityMenuItem;
|
||||||
private JLabel tableStatusPanelLabel;
|
private javax.swing.JPanel tableContainerPanel;
|
||||||
|
private javax.swing.JScrollPane tableScrollPane;
|
||||||
|
private javax.swing.JPanel tableStatusPanel;
|
||||||
|
private javax.swing.JLabel tableStatusPanelLabel;
|
||||||
// End of variables declaration//GEN-END:variables
|
// End of variables declaration//GEN-END:variables
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used as a key to ensure we eliminate duplicates from the result set by not overwriting CR correlation instances.
|
* Used as a key to ensure we eliminate duplicates from the result set by
|
||||||
|
* not overwriting CR correlation instances.
|
||||||
*/
|
*/
|
||||||
static final class UniquePathKey {
|
static final class UniquePathKey {
|
||||||
|
|
||||||
private final String dataSourceID;
|
private final String dataSourceID;
|
||||||
private final String filePath;
|
private final String filePath;
|
||||||
|
private final String type;
|
||||||
|
|
||||||
UniquePathKey(String theDataSource, String theFilePath) {
|
UniquePathKey(OtherOccurrenceNodeData nodeData) {
|
||||||
super();
|
super();
|
||||||
dataSourceID = theDataSource;
|
dataSourceID = nodeData.getDeviceID();
|
||||||
filePath = theFilePath.toLowerCase();
|
if (nodeData.getFilePath() != null) {
|
||||||
|
filePath = nodeData.getFilePath().toLowerCase();
|
||||||
|
} else {
|
||||||
|
filePath = null;
|
||||||
}
|
}
|
||||||
|
type = nodeData.getType();
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @return the dataSourceID device ID
|
|
||||||
*/
|
|
||||||
String getDataSourceID() {
|
|
||||||
return dataSourceID;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @return the filPath including the filename and extension.
|
|
||||||
*/
|
|
||||||
String getFilePath() {
|
|
||||||
return filePath;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object other) {
|
public boolean equals(Object other) {
|
||||||
if (other instanceof UniquePathKey) {
|
if (other instanceof UniquePathKey) {
|
||||||
return ((UniquePathKey) other).getDataSourceID().equals(dataSourceID) && ((UniquePathKey) other).getFilePath().equals(filePath);
|
UniquePathKey otherKey = (UniquePathKey)(other);
|
||||||
|
return ( Objects.equals(otherKey.dataSourceID, this.dataSourceID)
|
||||||
|
&& Objects.equals(otherKey.filePath, this.filePath)
|
||||||
|
&& Objects.equals(otherKey.type, this.type));
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -852,7 +942,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
//int hash = 7;
|
//int hash = 7;
|
||||||
//hash = 67 * hash + this.dataSourceID.hashCode();
|
//hash = 67 * hash + this.dataSourceID.hashCode();
|
||||||
//hash = 67 * hash + this.filePath.hashCode();
|
//hash = 67 * hash + this.filePath.hashCode();
|
||||||
return Objects.hash(dataSourceID, filePath);
|
return Objects.hash(dataSourceID, filePath, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,10 +68,10 @@ public class DataContentViewerOtherCasesTableModel extends AbstractTableModel {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
List<CorrelationAttribute> eamArtifacts;
|
List<OtherOccurrenceNodeData> nodeDataList;
|
||||||
|
|
||||||
DataContentViewerOtherCasesTableModel() {
|
DataContentViewerOtherCasesTableModel() {
|
||||||
eamArtifacts = new ArrayList<>();
|
nodeDataList = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -95,7 +95,7 @@ public class DataContentViewerOtherCasesTableModel extends AbstractTableModel {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getRowCount() {
|
public int getRowCount() {
|
||||||
return eamArtifacts.size();
|
return nodeDataList.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -105,15 +105,15 @@ public class DataContentViewerOtherCasesTableModel extends AbstractTableModel {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getValueAt(int rowIdx, int colIdx) {
|
public Object getValueAt(int rowIdx, int colIdx) {
|
||||||
if (0 == eamArtifacts.size()) {
|
if (0 == nodeDataList.size()) {
|
||||||
return Bundle.DataContentViewerOtherCasesTableModel_noData();
|
return Bundle.DataContentViewerOtherCasesTableModel_noData();
|
||||||
}
|
}
|
||||||
|
|
||||||
return mapValueById(rowIdx, TableColumns.values()[colIdx]);
|
return mapValueById(rowIdx, TableColumns.values()[colIdx]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getRow(int rowIdx) {
|
Object getRow(int rowIdx) {
|
||||||
return eamArtifacts.get(rowIdx);
|
return nodeDataList.get(rowIdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -125,40 +125,39 @@ public class DataContentViewerOtherCasesTableModel extends AbstractTableModel {
|
|||||||
* @return value in the cell
|
* @return value in the cell
|
||||||
*/
|
*/
|
||||||
private Object mapValueById(int rowIdx, TableColumns colId) {
|
private Object mapValueById(int rowIdx, TableColumns colId) {
|
||||||
CorrelationAttribute eamArtifact = eamArtifacts.get(rowIdx);
|
OtherOccurrenceNodeData nodeData = nodeDataList.get(rowIdx);
|
||||||
CorrelationAttributeInstance eamArtifactInstance = eamArtifact.getInstances().get(0);
|
|
||||||
String value = Bundle.DataContentViewerOtherCasesTableModel_noData();
|
String value = Bundle.DataContentViewerOtherCasesTableModel_noData();
|
||||||
|
|
||||||
switch (colId) {
|
switch (colId) {
|
||||||
case CASE_NAME:
|
case CASE_NAME:
|
||||||
if (null != eamArtifactInstance.getCorrelationCase()) {
|
if (null != nodeData.getCaseName()) {
|
||||||
value = eamArtifactInstance.getCorrelationCase().getDisplayName();
|
value = nodeData.getCaseName();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DEVICE:
|
case DEVICE:
|
||||||
if (null != eamArtifactInstance.getCorrelationDataSource()) {
|
if (null != nodeData.getDeviceID()) {
|
||||||
value = eamArtifactInstance.getCorrelationDataSource().getDeviceID();
|
value = nodeData.getDeviceID();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DATA_SOURCE:
|
case DATA_SOURCE:
|
||||||
if (null != eamArtifactInstance.getCorrelationDataSource()) {
|
if (null != nodeData.getDataSourceName()) {
|
||||||
value = eamArtifactInstance.getCorrelationDataSource().getName();
|
value = nodeData.getDataSourceName();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FILE_PATH:
|
case FILE_PATH:
|
||||||
value = eamArtifactInstance.getFilePath();
|
value = nodeData.getFilePath();
|
||||||
break;
|
break;
|
||||||
case TYPE:
|
case TYPE:
|
||||||
value = eamArtifact.getCorrelationType().getDisplayName();
|
value = nodeData.getType();
|
||||||
break;
|
break;
|
||||||
case VALUE:
|
case VALUE:
|
||||||
value = eamArtifact.getCorrelationValue();
|
value = nodeData.getValue();
|
||||||
break;
|
break;
|
||||||
case KNOWN:
|
case KNOWN:
|
||||||
value = eamArtifactInstance.getKnownStatus().getName();
|
value = nodeData.getKnown().getName();
|
||||||
break;
|
break;
|
||||||
case COMMENT:
|
case COMMENT:
|
||||||
value = eamArtifactInstance.getComment();
|
value = nodeData.getComment();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
@ -170,18 +169,17 @@ public class DataContentViewerOtherCasesTableModel extends AbstractTableModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add one local central repository artifact to the table.
|
* Add one correlated instance object to the table
|
||||||
*
|
*
|
||||||
* @param eamArtifact central repository artifact to add to the
|
* @param newNodeData data to add to the table
|
||||||
* table
|
|
||||||
*/
|
*/
|
||||||
public void addEamArtifact(CorrelationAttribute eamArtifact) {
|
void addNodeData(OtherOccurrenceNodeData newNodeData) {
|
||||||
eamArtifacts.add(eamArtifact);
|
nodeDataList.add(newNodeData);
|
||||||
fireTableDataChanged();
|
fireTableDataChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clearTable() {
|
void clearTable() {
|
||||||
eamArtifacts.clear();
|
nodeDataList.clear();
|
||||||
fireTableDataChanged();
|
fireTableDataChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,233 @@
|
|||||||
|
/*
|
||||||
|
* Central Repository
|
||||||
|
*
|
||||||
|
* Copyright 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.centralrepository.contentviewer;
|
||||||
|
|
||||||
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttribute;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
|
||||||
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
|
import org.sleuthkit.datamodel.DataSource;
|
||||||
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
import org.sleuthkit.datamodel.TskData;
|
||||||
|
import org.sleuthkit.datamodel.TskDataException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class for populating the Other Occurrences tab
|
||||||
|
*/
|
||||||
|
class OtherOccurrenceNodeData {
|
||||||
|
|
||||||
|
// For now hard code the string for the central repo files type, since
|
||||||
|
// getting it dynamically can fail.
|
||||||
|
private static final String FILE_TYPE_STR = "Files";
|
||||||
|
|
||||||
|
private final String caseName;
|
||||||
|
private String deviceID;
|
||||||
|
private String dataSourceName;
|
||||||
|
private final String filePath;
|
||||||
|
private final String typeStr;
|
||||||
|
private final CorrelationAttribute.Type type;
|
||||||
|
private final String value;
|
||||||
|
private TskData.FileKnown known;
|
||||||
|
private String comment;
|
||||||
|
|
||||||
|
private AbstractFile originalAbstractFile = null;
|
||||||
|
private CorrelationAttributeInstance originalCorrelationInstance = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a node from a central repo instance.
|
||||||
|
* @param instance The central repo instance
|
||||||
|
* @param type The type of the instance
|
||||||
|
* @param value The value of the instance
|
||||||
|
*/
|
||||||
|
OtherOccurrenceNodeData(CorrelationAttributeInstance instance, CorrelationAttribute.Type type, String value) {
|
||||||
|
caseName = instance.getCorrelationCase().getDisplayName();
|
||||||
|
deviceID = instance.getCorrelationDataSource().getDeviceID();
|
||||||
|
dataSourceName = instance.getCorrelationDataSource().getName();
|
||||||
|
filePath = instance.getFilePath();
|
||||||
|
this.typeStr = type.getDisplayName();
|
||||||
|
this.type = type;
|
||||||
|
this.value = value;
|
||||||
|
known = instance.getKnownStatus();
|
||||||
|
comment = instance.getComment();
|
||||||
|
|
||||||
|
originalCorrelationInstance = instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a node from an abstract file.
|
||||||
|
* @param newFile The abstract file
|
||||||
|
* @param autopsyCase The current case
|
||||||
|
* @throws EamDbException
|
||||||
|
*/
|
||||||
|
OtherOccurrenceNodeData(AbstractFile newFile, Case autopsyCase) throws EamDbException {
|
||||||
|
caseName = autopsyCase.getDisplayName();
|
||||||
|
try {
|
||||||
|
DataSource dataSource = autopsyCase.getSleuthkitCase().getDataSource(newFile.getDataSource().getId());
|
||||||
|
deviceID = dataSource.getDeviceId();
|
||||||
|
dataSourceName = dataSource.getName();
|
||||||
|
} catch (TskDataException | TskCoreException ex) {
|
||||||
|
throw new EamDbException("Error loading data source for abstract file ID " + newFile.getId(), ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
filePath = newFile.getParentPath() + newFile.getName();
|
||||||
|
typeStr = FILE_TYPE_STR;
|
||||||
|
this.type = null;
|
||||||
|
value = newFile.getMd5Hash();
|
||||||
|
known = newFile.getKnown();
|
||||||
|
comment = "";
|
||||||
|
|
||||||
|
originalAbstractFile = newFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if this node is a "file" type
|
||||||
|
* @return true if it is a file type
|
||||||
|
*/
|
||||||
|
boolean isFileType() {
|
||||||
|
return FILE_TYPE_STR.equals(typeStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the known status for this node
|
||||||
|
* @param newKnownStatus The new known status
|
||||||
|
*/
|
||||||
|
void updateKnown(TskData.FileKnown newKnownStatus) {
|
||||||
|
known = newKnownStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the comment for this node
|
||||||
|
* @param newComment The new comment
|
||||||
|
*/
|
||||||
|
void updateComment(String newComment) {
|
||||||
|
comment = newComment;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if this is a central repo node.
|
||||||
|
* @return true if this node was created from a central repo instance, false otherwise
|
||||||
|
*/
|
||||||
|
boolean isCentralRepoNode() {
|
||||||
|
return (originalCorrelationInstance != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uses the saved instance plus type and value to make a new CorrelationAttribute.
|
||||||
|
* Should only be called if isCentralRepoNode() is true.
|
||||||
|
* @return the newly created CorrelationAttribute
|
||||||
|
*/
|
||||||
|
CorrelationAttribute createCorrelationAttribute() throws EamDbException {
|
||||||
|
if (! isCentralRepoNode() ) {
|
||||||
|
throw new EamDbException("Can not create CorrelationAttribute for non central repo node");
|
||||||
|
}
|
||||||
|
CorrelationAttribute attr = new CorrelationAttribute(type, value);
|
||||||
|
attr.addInstance(originalCorrelationInstance);
|
||||||
|
return attr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the case name
|
||||||
|
* @return the case name
|
||||||
|
*/
|
||||||
|
String getCaseName() {
|
||||||
|
return caseName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the device ID
|
||||||
|
* @return the device ID
|
||||||
|
*/
|
||||||
|
String getDeviceID() {
|
||||||
|
return deviceID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the data source name
|
||||||
|
* @return the data source name
|
||||||
|
*/
|
||||||
|
String getDataSourceName() {
|
||||||
|
return dataSourceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the file path
|
||||||
|
* @return the file path
|
||||||
|
*/
|
||||||
|
String getFilePath() {
|
||||||
|
return filePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the type (as a string)
|
||||||
|
* @return the type
|
||||||
|
*/
|
||||||
|
String getType() {
|
||||||
|
return typeStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value (MD5 hash for files)
|
||||||
|
* @return the value
|
||||||
|
*/
|
||||||
|
String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the known status
|
||||||
|
* @return the known status
|
||||||
|
*/
|
||||||
|
TskData.FileKnown getKnown() {
|
||||||
|
return known;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the comment
|
||||||
|
* @return the comment
|
||||||
|
*/
|
||||||
|
String getComment() {
|
||||||
|
return comment;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the backing abstract file.
|
||||||
|
* Should only be called if isCentralRepoNode() is false
|
||||||
|
* @return the original abstract file
|
||||||
|
*/
|
||||||
|
AbstractFile getAbstractFile() throws EamDbException {
|
||||||
|
if (originalCorrelationInstance == null) {
|
||||||
|
throw new EamDbException("AbstractFile is null");
|
||||||
|
}
|
||||||
|
return originalAbstractFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the backing CorrelationAttributeInstance.
|
||||||
|
* Should only be called if isCentralRepoNode() is true
|
||||||
|
* @return the original CorrelationAttributeInstance
|
||||||
|
* @throws EamDbException
|
||||||
|
*/
|
||||||
|
CorrelationAttributeInstance getCorrelationAttributeInstance() throws EamDbException {
|
||||||
|
if (originalCorrelationInstance == null) {
|
||||||
|
throw new EamDbException("CorrelationAttributeInstance is null");
|
||||||
|
}
|
||||||
|
return originalCorrelationInstance;
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Central Repository
|
* Central Repository
|
||||||
*
|
*
|
||||||
* Copyright 2015-2017 Basis Technology Corp.
|
* Copyright 2015-2018 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -24,8 +24,8 @@ import org.sleuthkit.datamodel.TskData;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Used to store details about a specific instance of a
|
* Used to store details about a specific instance of a CorrelationAttribute.
|
||||||
* CorrelationAttribute. Includes its data source, path, etc.
|
* Includes its data source, path, etc.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@Messages({
|
@Messages({
|
||||||
@ -43,13 +43,6 @@ public class CorrelationAttributeInstance implements Serializable {
|
|||||||
private String comment;
|
private String comment;
|
||||||
private TskData.FileKnown knownStatus;
|
private TskData.FileKnown knownStatus;
|
||||||
|
|
||||||
public CorrelationAttributeInstance(
|
|
||||||
CorrelationCase eamCase,
|
|
||||||
CorrelationDataSource eamDataSource
|
|
||||||
) throws EamDbException {
|
|
||||||
this(-1, eamCase, eamDataSource, "", null, TskData.FileKnown.UNKNOWN);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CorrelationAttributeInstance(
|
public CorrelationAttributeInstance(
|
||||||
CorrelationCase eamCase,
|
CorrelationCase eamCase,
|
||||||
CorrelationDataSource eamDataSource,
|
CorrelationDataSource eamDataSource,
|
||||||
@ -58,14 +51,6 @@ public class CorrelationAttributeInstance implements Serializable {
|
|||||||
this(-1, eamCase, eamDataSource, filePath, null, TskData.FileKnown.UNKNOWN);
|
this(-1, eamCase, eamDataSource, filePath, null, TskData.FileKnown.UNKNOWN);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CorrelationAttributeInstance(
|
|
||||||
CorrelationCase eamCase,
|
|
||||||
CorrelationDataSource eamDataSource,
|
|
||||||
String filePath,
|
|
||||||
String comment
|
|
||||||
) throws EamDbException {
|
|
||||||
this(-1, eamCase, eamDataSource, filePath, comment, TskData.FileKnown.UNKNOWN);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CorrelationAttributeInstance(
|
public CorrelationAttributeInstance(
|
||||||
CorrelationCase eamCase,
|
CorrelationCase eamCase,
|
||||||
@ -117,6 +102,16 @@ public class CorrelationAttributeInstance implements Serializable {
|
|||||||
+ this.getComment();
|
+ this.getComment();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is this a database instance?
|
||||||
|
*
|
||||||
|
* @return True if the instance ID is greater or equal to zero; otherwise
|
||||||
|
* false.
|
||||||
|
*/
|
||||||
|
public boolean isDatabaseInstance() {
|
||||||
|
return (ID >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the database ID
|
* @return the database ID
|
||||||
*/
|
*/
|
||||||
@ -160,8 +155,8 @@ public class CorrelationAttributeInstance implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get this knownStatus. This only indicates whether an item has been
|
* Get this knownStatus. This only indicates whether an item has been tagged
|
||||||
* tagged as notable and should never return KNOWN.
|
* as notable and should never return KNOWN.
|
||||||
*
|
*
|
||||||
* @return BAD if the item has been tagged as notable, UNKNOWN otherwise
|
* @return BAD if the item has been tagged as notable, UNKNOWN otherwise
|
||||||
*/
|
*/
|
||||||
@ -170,10 +165,11 @@ public class CorrelationAttributeInstance implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the knownStatus. This only indicates whether an item has been
|
* Set the knownStatus. This only indicates whether an item has been tagged
|
||||||
* tagged as notable and should never be set to KNOWN.
|
* as notable and should never be set to KNOWN.
|
||||||
*
|
*
|
||||||
* @param knownStatus Should be BAD if the item is tagged as notable, UNKNOWN otherwise
|
* @param knownStatus Should be BAD if the item is tagged as notable,
|
||||||
|
* UNKNOWN otherwise
|
||||||
*/
|
*/
|
||||||
public void setKnownStatus(TskData.FileKnown knownStatus) {
|
public void setKnownStatus(TskData.FileKnown knownStatus) {
|
||||||
this.knownStatus = knownStatus;
|
this.knownStatus = knownStatus;
|
||||||
|
@ -40,15 +40,21 @@ public class CorrelationDataSource implements Serializable {
|
|||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* @param correlationCase CorrelationCase object data source is associated with. Must have been created by EamDB and have a valid ID.
|
||||||
* @param caseId
|
* @param deviceId User specified case-specific ID
|
||||||
* @param deviceId
|
* @param name Display name of data source
|
||||||
* @param name
|
|
||||||
*/
|
*/
|
||||||
public CorrelationDataSource(int caseId, String deviceId, String name) {
|
public CorrelationDataSource(CorrelationCase correlationCase, String deviceId, String name) {
|
||||||
this(caseId, -1, deviceId, name);
|
this(correlationCase.getID(), -1, deviceId, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param caseId Row ID for Case in DB
|
||||||
|
* @param dataSourceId Row ID for this data source in DB (or -1)
|
||||||
|
* @param deviceId User specified ID for device (unique per case)
|
||||||
|
* @param name User specified name
|
||||||
|
*/
|
||||||
CorrelationDataSource(int caseId,
|
CorrelationDataSource(int caseId,
|
||||||
int dataSourceId,
|
int dataSourceId,
|
||||||
String deviceId,
|
String deviceId,
|
||||||
@ -61,6 +67,7 @@ public class CorrelationDataSource implements Serializable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a CorrelationDataSource object from a TSK Content object.
|
* Create a CorrelationDataSource object from a TSK Content object.
|
||||||
|
* This will add it to the central repository.
|
||||||
*
|
*
|
||||||
* @param correlationCase the current CorrelationCase used for ensuring
|
* @param correlationCase the current CorrelationCase used for ensuring
|
||||||
* uniqueness of DataSource
|
* uniqueness of DataSource
|
||||||
@ -84,7 +91,18 @@ public class CorrelationDataSource implements Serializable {
|
|||||||
} catch (TskDataException | TskCoreException ex) {
|
} catch (TskDataException | TskCoreException ex) {
|
||||||
throw new EamDbException("Error getting data source info: " + ex.getMessage());
|
throw new EamDbException("Error getting data source info: " + ex.getMessage());
|
||||||
}
|
}
|
||||||
return new CorrelationDataSource(correlationCase.getID(), -1, deviceId, dataSource.getName());
|
|
||||||
|
CorrelationDataSource correlationDataSource = null;
|
||||||
|
if (EamDbUtil.useCentralRepo()) {
|
||||||
|
correlationDataSource = EamDb.getInstance().getDataSource(correlationCase, deviceId);
|
||||||
|
}
|
||||||
|
if (correlationDataSource == null) {
|
||||||
|
correlationDataSource = new CorrelationDataSource(correlationCase, deviceId, dataSource.getName());
|
||||||
|
if (EamDbUtil.useCentralRepo()) {
|
||||||
|
EamDb.getInstance().newDataSource(correlationDataSource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return correlationDataSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -102,7 +120,7 @@ public class CorrelationDataSource implements Serializable {
|
|||||||
/**
|
/**
|
||||||
* Get the database row ID
|
* Get the database row ID
|
||||||
*
|
*
|
||||||
* @return the ID
|
* @return the ID or -1 if unknown
|
||||||
*/
|
*/
|
||||||
int getID() {
|
int getID() {
|
||||||
return dataSourceID;
|
return dataSourceID;
|
||||||
|
@ -39,7 +39,7 @@ import org.sleuthkit.datamodel.TskData;
|
|||||||
public class EamArtifactUtil {
|
public class EamArtifactUtil {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
private static final Logger LOGGER = Logger.getLogger(EamArtifactUtil.class.getName());
|
private static final Logger logger = Logger.getLogger(EamArtifactUtil.class.getName());
|
||||||
|
|
||||||
public EamArtifactUtil() {
|
public EamArtifactUtil() {
|
||||||
}
|
}
|
||||||
@ -76,14 +76,14 @@ public class EamArtifactUtil {
|
|||||||
// have switch based on artifact type
|
// have switch based on artifact type
|
||||||
for (CorrelationAttribute.Type aType : EamDb.getInstance().getDefinedCorrelationTypes()) {
|
for (CorrelationAttribute.Type aType : EamDb.getInstance().getDefinedCorrelationTypes()) {
|
||||||
if ((checkEnabled && aType.isEnabled()) || !checkEnabled) {
|
if ((checkEnabled && aType.isEnabled()) || !checkEnabled) {
|
||||||
CorrelationAttribute eamArtifact = EamArtifactUtil.getCorrelationAttributeFromBlackboardArtifact(aType, bbArtifact);
|
CorrelationAttribute correlationAttribute = EamArtifactUtil.getCorrelationAttributeFromBlackboardArtifact(aType, bbArtifact);
|
||||||
if (eamArtifact != null) {
|
if (correlationAttribute != null) {
|
||||||
eamArtifacts.add(eamArtifact);
|
eamArtifacts.add(correlationAttribute);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (EamDbException ex) {
|
} catch (EamDbException ex) {
|
||||||
LOGGER.log(Level.SEVERE, "Error getting defined correlation types.", ex); // NON-NLS
|
logger.log(Level.SEVERE, "Error getting defined correlation types.", ex); // NON-NLS
|
||||||
return eamArtifacts;
|
return eamArtifacts;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,10 +115,10 @@ public class EamArtifactUtil {
|
|||||||
eamArtifact.addInstance(eamInstance);
|
eamArtifact.addInstance(eamInstance);
|
||||||
}
|
}
|
||||||
} catch (TskCoreException | EamDbException ex) {
|
} catch (TskCoreException | EamDbException ex) {
|
||||||
LOGGER.log(Level.SEVERE, "Error creating artifact instance.", ex); // NON-NLS
|
logger.log(Level.SEVERE, "Error creating artifact instance.", ex); // NON-NLS
|
||||||
return eamArtifacts;
|
return eamArtifacts;
|
||||||
} catch (NoCurrentCaseException ex) {
|
} catch (NoCurrentCaseException ex) {
|
||||||
LOGGER.log(Level.SEVERE, "Case is closed.", ex); // NON-NLS
|
logger.log(Level.SEVERE, "Case is closed.", ex); // NON-NLS
|
||||||
return eamArtifacts;
|
return eamArtifacts;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -202,10 +202,10 @@ public class EamArtifactUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
LOGGER.log(Level.SEVERE, "Error getting attribute while getting type from BlackboardArtifact.", ex); // NON-NLS
|
logger.log(Level.SEVERE, "Error getting attribute while getting type from BlackboardArtifact.", ex); // NON-NLS
|
||||||
return null;
|
return null;
|
||||||
} catch (NoCurrentCaseException ex) {
|
} catch (NoCurrentCaseException ex) {
|
||||||
LOGGER.log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS
|
logger.log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -216,6 +216,45 @@ public class EamArtifactUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve CorrelationAttribute from the given Content.
|
||||||
|
*
|
||||||
|
* @param content The content object
|
||||||
|
*
|
||||||
|
* @return The new CorrelationAttribute, or null if retrieval failed.
|
||||||
|
*/
|
||||||
|
public static CorrelationAttribute getCorrelationAttributeFromContent(Content content) {
|
||||||
|
|
||||||
|
if (!(content instanceof AbstractFile)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final AbstractFile file = (AbstractFile) content;
|
||||||
|
|
||||||
|
if (!isSupportedAbstractFileType(file)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
CorrelationAttribute correlationAttribute = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
CorrelationAttribute.Type type = EamDb.getInstance().getCorrelationTypeById(CorrelationAttribute.FILES_TYPE_ID);
|
||||||
|
CorrelationCase correlationCase = EamDb.getInstance().getCase(Case.getCurrentCaseThrows());
|
||||||
|
if (null == correlationCase) {
|
||||||
|
correlationCase = EamDb.getInstance().newCase(Case.getCurrentCaseThrows());
|
||||||
|
}
|
||||||
|
CorrelationDataSource correlationDataSource = CorrelationDataSource.fromTSKDataSource(correlationCase, file.getDataSource());
|
||||||
|
String value = file.getMd5Hash();
|
||||||
|
String filePath = (file.getParentPath() + file.getName()).toLowerCase();
|
||||||
|
|
||||||
|
correlationAttribute = EamDb.getInstance().getCorrelationAttribute(type, correlationCase, correlationDataSource, value, filePath);
|
||||||
|
} catch (TskCoreException | EamDbException | NoCurrentCaseException ex) {
|
||||||
|
logger.log(Level.SEVERE, "Error retrieving correlation attribute.", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return correlationAttribute;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an EamArtifact from the given Content. Will return null if an
|
* Create an EamArtifact from the given Content. Will return null if an
|
||||||
* artifact can not be created - this is not necessarily an error case, it
|
* artifact can not be created - this is not necessarily an error case, it
|
||||||
@ -237,7 +276,7 @@ public class EamArtifactUtil {
|
|||||||
|
|
||||||
final AbstractFile af = (AbstractFile) content;
|
final AbstractFile af = (AbstractFile) content;
|
||||||
|
|
||||||
if (!isValidCentralRepoFile(af)) {
|
if (!isSupportedAbstractFileType(af)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -262,7 +301,7 @@ public class EamArtifactUtil {
|
|||||||
eamArtifact.addInstance(cei);
|
eamArtifact.addInstance(cei);
|
||||||
return eamArtifact;
|
return eamArtifact;
|
||||||
} catch (TskCoreException | EamDbException | NoCurrentCaseException ex) {
|
} catch (TskCoreException | EamDbException | NoCurrentCaseException ex) {
|
||||||
LOGGER.log(Level.SEVERE, "Error making correlation attribute.", ex);
|
logger.log(Level.SEVERE, "Error making correlation attribute.", ex);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -271,21 +310,17 @@ public class EamArtifactUtil {
|
|||||||
* Check whether the given abstract file should be processed for the central
|
* Check whether the given abstract file should be processed for the central
|
||||||
* repository.
|
* repository.
|
||||||
*
|
*
|
||||||
* @param af The file to test
|
* @param file The file to test
|
||||||
*
|
*
|
||||||
* @return true if the file should be added to the central repo, false
|
* @return true if the file should be added to the central repo, false
|
||||||
* otherwise
|
* otherwise
|
||||||
*/
|
*/
|
||||||
public static boolean isValidCentralRepoFile(AbstractFile af) {
|
public static boolean isSupportedAbstractFileType(AbstractFile file) {
|
||||||
if (af == null) {
|
if (file == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (af.getKnown() == TskData.FileKnown.KNOWN) {
|
switch (file.getType()) {
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (af.getType()) {
|
|
||||||
case UNALLOC_BLOCKS:
|
case UNALLOC_BLOCKS:
|
||||||
case UNUSED_BLOCKS:
|
case UNUSED_BLOCKS:
|
||||||
case SLACK:
|
case SLACK:
|
||||||
@ -297,9 +332,9 @@ public class EamArtifactUtil {
|
|||||||
case LOCAL:
|
case LOCAL:
|
||||||
return true;
|
return true;
|
||||||
case FS:
|
case FS:
|
||||||
return af.isMetaFlagSet(TskData.TSK_FS_META_FLAG_ENUM.ALLOC);
|
return file.isMetaFlagSet(TskData.TSK_FS_META_FLAG_ENUM.ALLOC);
|
||||||
default:
|
default:
|
||||||
LOGGER.log(Level.WARNING, "Unexpected file type {0}", af.getType().getName());
|
logger.log(Level.WARNING, "Unexpected file type {0}", file.getType().getName());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Central Repository
|
* Central Repository
|
||||||
*
|
*
|
||||||
* Copyright 2015-2017 Basis Technology Corp.
|
* Copyright 2015-2018 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -35,6 +35,7 @@ public interface EamDb {
|
|||||||
public static final CaseDbSchemaVersionNumber CURRENT_DB_SCHEMA_VERSION
|
public static final CaseDbSchemaVersionNumber CURRENT_DB_SCHEMA_VERSION
|
||||||
= new CaseDbSchemaVersionNumber(1, 1);
|
= new CaseDbSchemaVersionNumber(1, 1);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the instance
|
* Get the instance
|
||||||
*
|
*
|
||||||
@ -158,7 +159,9 @@ public interface EamDb {
|
|||||||
* Retrieves Central Repo case based on an Autopsy Case
|
* Retrieves Central Repo case based on an Autopsy Case
|
||||||
*
|
*
|
||||||
* @param autopsyCase Autopsy case to find corresponding CR case for
|
* @param autopsyCase Autopsy case to find corresponding CR case for
|
||||||
|
*
|
||||||
* @return CR Case
|
* @return CR Case
|
||||||
|
*
|
||||||
* @throws EamDbException
|
* @throws EamDbException
|
||||||
*/
|
*/
|
||||||
CorrelationCase getCase(Case autopsyCase) throws EamDbException;
|
CorrelationCase getCase(Case autopsyCase) throws EamDbException;
|
||||||
@ -309,6 +312,34 @@ public interface EamDb {
|
|||||||
*/
|
*/
|
||||||
void bulkInsertCases(List<CorrelationCase> cases) throws EamDbException;
|
void bulkInsertCases(List<CorrelationCase> cases) throws EamDbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update a correlation attribute instance comment in the database with that
|
||||||
|
* in the associated CorrelationAttribute object.
|
||||||
|
*
|
||||||
|
* @param eamArtifact The correlation attribute whose database instance will
|
||||||
|
* be updated.
|
||||||
|
*
|
||||||
|
* @throws EamDbException
|
||||||
|
*/
|
||||||
|
void updateAttributeInstanceComment(CorrelationAttribute eamArtifact) throws EamDbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a correlation attribute in the Central Repository database given the
|
||||||
|
* instance type, case, data source, value, and file path.
|
||||||
|
*
|
||||||
|
* @param type The type of instance.
|
||||||
|
* @param correlationCase The case tied to the instance.
|
||||||
|
* @param correlationDataSource The data source tied to the instance.
|
||||||
|
* @param value The value tied to the instance.
|
||||||
|
* @param filePath The file path tied to the instance.
|
||||||
|
*
|
||||||
|
* @return The correlation attribute if it exists; otherwise null.
|
||||||
|
*
|
||||||
|
* @throws EamDbException
|
||||||
|
*/
|
||||||
|
CorrelationAttribute getCorrelationAttribute(CorrelationAttribute.Type type, CorrelationCase correlationCase,
|
||||||
|
CorrelationDataSource correlationDataSource, String value, String filePath) throws EamDbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets an eamArtifact instance to the given known status. If eamArtifact
|
* Sets an eamArtifact instance to the given known status. If eamArtifact
|
||||||
* exists, it is updated. If eamArtifact does not exist nothing happens
|
* exists, it is updated. If eamArtifact does not exist nothing happens
|
||||||
@ -329,6 +360,15 @@ public interface EamDb {
|
|||||||
*/
|
*/
|
||||||
List<CorrelationAttributeInstance> getArtifactInstancesKnownBad(CorrelationAttribute.Type aType, String value) throws EamDbException;
|
List<CorrelationAttributeInstance> getArtifactInstancesKnownBad(CorrelationAttribute.Type aType, String value) throws EamDbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets list of matching eamArtifact instances that have knownStatus =
|
||||||
|
* "Bad".
|
||||||
|
*
|
||||||
|
* @param aType EamArtifact.Type to search for
|
||||||
|
* @return List with 0 or more matching eamArtifact instances.
|
||||||
|
* @throws EamDbException
|
||||||
|
*/
|
||||||
|
List<CorrelationAttributeInstance> getArtifactInstancesKnownBad(CorrelationAttribute.Type aType) throws EamDbException;
|
||||||
/**
|
/**
|
||||||
* Count matching eamArtifacts instances that have knownStatus = "Bad".
|
* Count matching eamArtifacts instances that have knownStatus = "Bad".
|
||||||
*
|
*
|
||||||
@ -357,6 +397,7 @@ public interface EamDb {
|
|||||||
* Remove a reference set and all values contained in it.
|
* Remove a reference set and all values contained in it.
|
||||||
*
|
*
|
||||||
* @param referenceSetID
|
* @param referenceSetID
|
||||||
|
*
|
||||||
* @throws EamDbException
|
* @throws EamDbException
|
||||||
*/
|
*/
|
||||||
public void deleteReferenceSet(int referenceSetID) throws EamDbException;
|
public void deleteReferenceSet(int referenceSetID) throws EamDbException;
|
||||||
@ -369,7 +410,9 @@ public interface EamDb {
|
|||||||
* @param referenceSetID
|
* @param referenceSetID
|
||||||
* @param referenceSetName
|
* @param referenceSetName
|
||||||
* @param version
|
* @param version
|
||||||
|
*
|
||||||
* @return true if a matching entry exists in the central repository
|
* @return true if a matching entry exists in the central repository
|
||||||
|
*
|
||||||
* @throws EamDbException
|
* @throws EamDbException
|
||||||
*/
|
*/
|
||||||
public boolean referenceSetIsValid(int referenceSetID, String referenceSetName, String version) throws EamDbException;
|
public boolean referenceSetIsValid(int referenceSetID, String referenceSetName, String version) throws EamDbException;
|
||||||
@ -381,7 +424,9 @@ public interface EamDb {
|
|||||||
*
|
*
|
||||||
* @param referenceSetName
|
* @param referenceSetName
|
||||||
* @param version
|
* @param version
|
||||||
|
*
|
||||||
* @return true if a matching set is found
|
* @return true if a matching set is found
|
||||||
|
*
|
||||||
* @throws EamDbException
|
* @throws EamDbException
|
||||||
*/
|
*/
|
||||||
public boolean referenceSetExists(String referenceSetName, String version) throws EamDbException;
|
public boolean referenceSetExists(String referenceSetName, String version) throws EamDbException;
|
||||||
@ -392,7 +437,9 @@ public interface EamDb {
|
|||||||
*
|
*
|
||||||
* @param hash
|
* @param hash
|
||||||
* @param referenceSetID
|
* @param referenceSetID
|
||||||
|
*
|
||||||
* @return true if the hash is found in the reference set
|
* @return true if the hash is found in the reference set
|
||||||
|
*
|
||||||
* @throws EamDbException
|
* @throws EamDbException
|
||||||
*/
|
*/
|
||||||
public boolean isFileHashInReferenceSet(String hash, int referenceSetID) throws EamDbException;
|
public boolean isFileHashInReferenceSet(String hash, int referenceSetID) throws EamDbException;
|
||||||
@ -403,6 +450,7 @@ public interface EamDb {
|
|||||||
* @param value
|
* @param value
|
||||||
* @param referenceSetID
|
* @param referenceSetID
|
||||||
* @param correlationTypeID
|
* @param correlationTypeID
|
||||||
|
*
|
||||||
* @return true if the hash is found in the reference set
|
* @return true if the hash is found in the reference set
|
||||||
*/
|
*/
|
||||||
public boolean isValueInReferenceSet(String value, int referenceSetID, int correlationTypeID) throws EamDbException;
|
public boolean isValueInReferenceSet(String value, int referenceSetID, int correlationTypeID) throws EamDbException;
|
||||||
@ -422,11 +470,11 @@ public interface EamDb {
|
|||||||
*
|
*
|
||||||
* @param eamOrg The organization to add
|
* @param eamOrg The organization to add
|
||||||
*
|
*
|
||||||
* @return the Organization ID of the newly created organization.
|
* @return The organization with the org ID set.
|
||||||
*
|
*
|
||||||
* @throws EamDbException
|
* @throws EamDbException
|
||||||
*/
|
*/
|
||||||
long newOrganization(EamOrganization eamOrg) throws EamDbException;
|
EamOrganization newOrganization(EamOrganization eamOrg) throws EamDbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all organizations
|
* Get all organizations
|
||||||
@ -452,7 +500,9 @@ public interface EamDb {
|
|||||||
* Get the organization associated with the given reference set.
|
* Get the organization associated with the given reference set.
|
||||||
*
|
*
|
||||||
* @param referenceSetID ID of the reference set
|
* @param referenceSetID ID of the reference set
|
||||||
|
*
|
||||||
* @return The organization object
|
* @return The organization object
|
||||||
|
*
|
||||||
* @throws EamDbException
|
* @throws EamDbException
|
||||||
*/
|
*/
|
||||||
EamOrganization getReferenceSetOrganization(int referenceSetID) throws EamDbException;
|
EamOrganization getReferenceSetOrganization(int referenceSetID) throws EamDbException;
|
||||||
@ -513,7 +563,8 @@ public interface EamDb {
|
|||||||
* Add a new reference instance
|
* Add a new reference instance
|
||||||
*
|
*
|
||||||
* @param eamGlobalFileInstance The reference instance to add
|
* @param eamGlobalFileInstance The reference instance to add
|
||||||
* @param correlationType Correlation Type that this Reference Instance is
|
* @param correlationType Correlation Type that this Reference
|
||||||
|
* Instance is
|
||||||
*
|
*
|
||||||
* @throws EamDbException
|
* @throws EamDbException
|
||||||
*/
|
*/
|
||||||
@ -620,8 +671,18 @@ public interface EamDb {
|
|||||||
* (meaning the database is in use).
|
* (meaning the database is in use).
|
||||||
*
|
*
|
||||||
* @return the lock, or null if locking is not supported
|
* @return the lock, or null if locking is not supported
|
||||||
|
*
|
||||||
* @throws EamDbException if the coordination service is running but we fail
|
* @throws EamDbException if the coordination service is running but we fail
|
||||||
* to get the lock
|
* to get the lock
|
||||||
*/
|
*/
|
||||||
public CoordinationService.Lock getExclusiveMultiUserDbLock() throws EamDbException;
|
public CoordinationService.Lock getExclusiveMultiUserDbLock() throws EamDbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process the Artifact instance in the EamDb
|
||||||
|
*
|
||||||
|
* @param type EamArtifact.Type to search for
|
||||||
|
* @param instanceTableCallback callback to process the instance
|
||||||
|
* @throws EamDbException
|
||||||
|
*/
|
||||||
|
void processInstanceTable(CorrelationAttribute.Type type, InstanceTableCallback instanceTableCallback) throws EamDbException;
|
||||||
}
|
}
|
||||||
|
@ -42,18 +42,18 @@ public class EamDbUtil {
|
|||||||
private static final String DEFAULT_ORG_NAME = "Not Specified";
|
private static final String DEFAULT_ORG_NAME = "Not Specified";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Close the prepared statement.
|
* Close the statement.
|
||||||
*
|
*
|
||||||
* @param preparedStatement
|
* @param statement The statement to be closed.
|
||||||
*
|
*
|
||||||
* @throws EamDbException
|
* @throws EamDbException
|
||||||
*/
|
*/
|
||||||
public static void closePreparedStatement(PreparedStatement preparedStatement) {
|
public static void closeStatement(Statement statement) {
|
||||||
if (null != preparedStatement) {
|
if (null != statement) {
|
||||||
try {
|
try {
|
||||||
preparedStatement.close();
|
statement.close();
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
LOGGER.log(Level.SEVERE, "Error closing PreparedStatement.", ex);
|
LOGGER.log(Level.SEVERE, "Error closing Statement.", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -361,4 +361,18 @@ public class EamDbUtil {
|
|||||||
return "reference_" + type.getDbTableName();
|
return "reference_" + type.getDbTableName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close the prepared statement.
|
||||||
|
*
|
||||||
|
* @param preparedStatement The prepared statement to be closed.
|
||||||
|
*
|
||||||
|
* @deprecated Use closeStatement() instead.
|
||||||
|
*
|
||||||
|
* @throws EamDbException
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public static void closePreparedStatement(PreparedStatement preparedStatement) {
|
||||||
|
closeStatement(preparedStatement);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ public class EamOrganization {
|
|||||||
private String pocEmail;
|
private String pocEmail;
|
||||||
private String pocPhone;
|
private String pocPhone;
|
||||||
|
|
||||||
public EamOrganization(
|
EamOrganization(
|
||||||
int orgID,
|
int orgID,
|
||||||
String name,
|
String name,
|
||||||
String pocName,
|
String pocName,
|
||||||
@ -84,7 +84,7 @@ public class EamOrganization {
|
|||||||
/**
|
/**
|
||||||
* @param orgID the orgID to set
|
* @param orgID the orgID to set
|
||||||
*/
|
*/
|
||||||
public void setOrgID(int orgID) {
|
void setOrgID(int orgID) {
|
||||||
this.orgID = orgID;
|
this.orgID = orgID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* Central Repository
|
||||||
|
*
|
||||||
|
* Copyright 2015-2017 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.sleuthkit.autopsy.centralrepository.datamodel;
|
||||||
|
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CallBack Interface to process attribute instance Table. Used in EamDb.processInstanceTable
|
||||||
|
* is called only once. The implementation of this method needs to call resultset.next to
|
||||||
|
* loop through each row of attribute instance table.
|
||||||
|
*/
|
||||||
|
public interface InstanceTableCallback {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process the attribute instance
|
||||||
|
*
|
||||||
|
* @param resultSet attribute instance table.
|
||||||
|
*/
|
||||||
|
void process(ResultSet resultSet);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param resultSet attribute instance table
|
||||||
|
* @return ID of the instance
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
static int getId(ResultSet resultSet) throws SQLException{
|
||||||
|
return resultSet.getInt("id");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param resultSet attribute instance table
|
||||||
|
* @return Case ID of a given instance
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
static int getCaseId(ResultSet resultSet) throws SQLException {
|
||||||
|
return resultSet.getInt("case_id");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param resultSet attribute instance table
|
||||||
|
* @return Data source id of a particular instance
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
static int getDataSourceId(ResultSet resultSet) throws SQLException {
|
||||||
|
return resultSet.getInt("data_source_id");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param resultSet attribute instance table
|
||||||
|
* @return md5 hash value of the instance
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
static String getValue(ResultSet resultSet) throws SQLException {
|
||||||
|
return resultSet.getString("value");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param resultSet attribute instance table
|
||||||
|
* @return file path of the instance
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
static String getFilePath(ResultSet resultSet) throws SQLException {
|
||||||
|
return resultSet.getString("file_path");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param resultSet attribute instance table
|
||||||
|
* @return status integer based on whether instance is marked notable or not
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
static int getKnownStatus(ResultSet resultSet) throws SQLException {
|
||||||
|
return resultSet.getInt("known_status");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param resultSet attribute instance table
|
||||||
|
* @return previous comment made for the instance
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
static String getComment(ResultSet resultSet) throws SQLException {
|
||||||
|
return resultSet.getString("comment");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -24,8 +24,6 @@ import java.sql.Statement;
|
|||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import org.apache.commons.dbcp2.BasicDataSource;
|
import org.apache.commons.dbcp2.BasicDataSource;
|
||||||
import org.sleuthkit.autopsy.casemodule.CaseActionCancelledException;
|
|
||||||
import org.sleuthkit.autopsy.casemodule.CaseActionException;
|
|
||||||
import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
|
import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
|
||||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
@ -34,7 +32,7 @@ import org.sleuthkit.autopsy.coreutils.Logger;
|
|||||||
* Central Repository database implementation using Postgres as a
|
* Central Repository database implementation using Postgres as a
|
||||||
* backend
|
* backend
|
||||||
*/
|
*/
|
||||||
public class PostgresEamDb extends AbstractSqlEamDb {
|
final class PostgresEamDb extends AbstractSqlEamDb {
|
||||||
|
|
||||||
private final static Logger LOGGER = Logger.getLogger(PostgresEamDb.class.getName());
|
private final static Logger LOGGER = Logger.getLogger(PostgresEamDb.class.getName());
|
||||||
|
|
||||||
@ -116,7 +114,7 @@ public class PostgresEamDb extends AbstractSqlEamDb {
|
|||||||
|
|
||||||
String instancesTemplate = "TRUNCATE TABLE %s_instances RESTART IDENTITY CASCADE";
|
String instancesTemplate = "TRUNCATE TABLE %s_instances RESTART IDENTITY CASCADE";
|
||||||
String referencesTemplate = "TRUNCATE TABLE reference_%s RESTART IDENTITY CASCADE";
|
String referencesTemplate = "TRUNCATE TABLE reference_%s RESTART IDENTITY CASCADE";
|
||||||
for (CorrelationAttribute.Type type : DEFAULT_CORRELATION_TYPES) {
|
for (CorrelationAttribute.Type type : defaultCorrelationTypes) {
|
||||||
dropContent.executeUpdate(String.format(instancesTemplate, type.getDbTableName()));
|
dropContent.executeUpdate(String.format(instancesTemplate, type.getDbTableName()));
|
||||||
// FUTURE: support other reference types
|
// FUTURE: support other reference types
|
||||||
if (type.getId() == CorrelationAttribute.FILES_TYPE_ID) {
|
if (type.getId() == CorrelationAttribute.FILES_TYPE_ID) {
|
||||||
|
@ -35,6 +35,8 @@ import org.sleuthkit.autopsy.coreutils.TextConverterException;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Settings for the Postgres implementation of the Central Repository database
|
* Settings for the Postgres implementation of the Central Repository database
|
||||||
|
*
|
||||||
|
* NOTE: This is public scope because the options panel calls it directly to set/get
|
||||||
*/
|
*/
|
||||||
public final class PostgresEamDbSettings {
|
public final class PostgresEamDbSettings {
|
||||||
|
|
||||||
@ -42,7 +44,6 @@ public final class PostgresEamDbSettings {
|
|||||||
private final String DEFAULT_HOST = ""; // NON-NLS
|
private final String DEFAULT_HOST = ""; // NON-NLS
|
||||||
private final int DEFAULT_PORT = 5432;
|
private final int DEFAULT_PORT = 5432;
|
||||||
private final String DEFAULT_DBNAME = "central_repository"; // NON-NLS
|
private final String DEFAULT_DBNAME = "central_repository"; // NON-NLS
|
||||||
private final int DEFAULT_BULK_THRESHHOLD = 1000;
|
|
||||||
private final String DEFAULT_USERNAME = "";
|
private final String DEFAULT_USERNAME = "";
|
||||||
private final String DEFAULT_PASSWORD = "";
|
private final String DEFAULT_PASSWORD = "";
|
||||||
private final String VALIDATION_QUERY = "SELECT version()"; // NON-NLS
|
private final String VALIDATION_QUERY = "SELECT version()"; // NON-NLS
|
||||||
@ -89,15 +90,15 @@ public final class PostgresEamDbSettings {
|
|||||||
try {
|
try {
|
||||||
String bulkThresholdString = ModuleSettings.getConfigSetting("CentralRepository", "db.postgresql.bulkThreshold"); // NON-NLS
|
String bulkThresholdString = ModuleSettings.getConfigSetting("CentralRepository", "db.postgresql.bulkThreshold"); // NON-NLS
|
||||||
if (bulkThresholdString == null || bulkThresholdString.isEmpty()) {
|
if (bulkThresholdString == null || bulkThresholdString.isEmpty()) {
|
||||||
this.bulkThreshold = DEFAULT_BULK_THRESHHOLD;
|
this.bulkThreshold = AbstractSqlEamDb.DEFAULT_BULK_THRESHHOLD;
|
||||||
} else {
|
} else {
|
||||||
this.bulkThreshold = Integer.parseInt(bulkThresholdString);
|
this.bulkThreshold = Integer.parseInt(bulkThresholdString);
|
||||||
if (getBulkThreshold() <= 0) {
|
if (getBulkThreshold() <= 0) {
|
||||||
this.bulkThreshold = DEFAULT_BULK_THRESHHOLD;
|
this.bulkThreshold = AbstractSqlEamDb.DEFAULT_BULK_THRESHHOLD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (NumberFormatException ex) {
|
} catch (NumberFormatException ex) {
|
||||||
this.bulkThreshold = DEFAULT_BULK_THRESHHOLD;
|
this.bulkThreshold = AbstractSqlEamDb.DEFAULT_BULK_THRESHHOLD;
|
||||||
}
|
}
|
||||||
|
|
||||||
userName = ModuleSettings.getConfigSetting("CentralRepository", "db.postgresql.user"); // NON-NLS
|
userName = ModuleSettings.getConfigSetting("CentralRepository", "db.postgresql.user"); // NON-NLS
|
||||||
@ -139,7 +140,7 @@ public final class PostgresEamDbSettings {
|
|||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public String getConnectionURL(boolean usePostgresDb) {
|
String getConnectionURL(boolean usePostgresDb) {
|
||||||
StringBuilder url = new StringBuilder();
|
StringBuilder url = new StringBuilder();
|
||||||
url.append(getJDBCBaseURI());
|
url.append(getJDBCBaseURI());
|
||||||
url.append(getHost());
|
url.append(getHost());
|
||||||
@ -220,7 +221,7 @@ public final class PostgresEamDbSettings {
|
|||||||
LOGGER.log(Level.SEVERE, "Failed to execute database existance query.", ex); // NON-NLS
|
LOGGER.log(Level.SEVERE, "Failed to execute database existance query.", ex); // NON-NLS
|
||||||
return false;
|
return false;
|
||||||
} finally {
|
} finally {
|
||||||
EamDbUtil.closePreparedStatement(ps);
|
EamDbUtil.closeStatement(ps);
|
||||||
EamDbUtil.closeResultSet(rs);
|
EamDbUtil.closeResultSet(rs);
|
||||||
EamDbUtil.closeConnection(conn);
|
EamDbUtil.closeConnection(conn);
|
||||||
}
|
}
|
||||||
@ -231,7 +232,7 @@ public final class PostgresEamDbSettings {
|
|||||||
* Use the current settings and the schema version query to test the
|
* Use the current settings and the schema version query to test the
|
||||||
* database schema.
|
* database schema.
|
||||||
*
|
*
|
||||||
* @return true if successfull connection, else false.
|
* @return true if successful connection, else false.
|
||||||
*/
|
*/
|
||||||
public boolean verifyDatabaseSchema() {
|
public boolean verifyDatabaseSchema() {
|
||||||
Connection conn = getEphemeralConnection(false);
|
Connection conn = getEphemeralConnection(false);
|
||||||
@ -493,7 +494,7 @@ public final class PostgresEamDbSettings {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isChanged() {
|
boolean isChanged() {
|
||||||
String hostString = ModuleSettings.getConfigSetting("CentralRepository", "db.postgresql.host"); // NON-NLS
|
String hostString = ModuleSettings.getConfigSetting("CentralRepository", "db.postgresql.host"); // NON-NLS
|
||||||
String portString = ModuleSettings.getConfigSetting("CentralRepository", "db.postgresql.port"); // NON-NLS
|
String portString = ModuleSettings.getConfigSetting("CentralRepository", "db.postgresql.port"); // NON-NLS
|
||||||
String dbNameString = ModuleSettings.getConfigSetting("CentralRepository", "db.postgresql.dbName"); // NON-NLS
|
String dbNameString = ModuleSettings.getConfigSetting("CentralRepository", "db.postgresql.dbName"); // NON-NLS
|
||||||
@ -568,7 +569,7 @@ public final class PostgresEamDbSettings {
|
|||||||
/**
|
/**
|
||||||
* @return the bulkThreshold
|
* @return the bulkThreshold
|
||||||
*/
|
*/
|
||||||
public int getBulkThreshold() {
|
int getBulkThreshold() {
|
||||||
return bulkThreshold;
|
return bulkThreshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -622,21 +623,21 @@ public final class PostgresEamDbSettings {
|
|||||||
/**
|
/**
|
||||||
* @return the VALIDATION_QUERY
|
* @return the VALIDATION_QUERY
|
||||||
*/
|
*/
|
||||||
public String getValidationQuery() {
|
String getValidationQuery() {
|
||||||
return VALIDATION_QUERY;
|
return VALIDATION_QUERY;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the POSTGRES_DRIVER
|
* @return the POSTGRES_DRIVER
|
||||||
*/
|
*/
|
||||||
public String getDriver() {
|
String getDriver() {
|
||||||
return JDBC_DRIVER;
|
return JDBC_DRIVER;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the JDBC_BASE_URI
|
* @return the JDBC_BASE_URI
|
||||||
*/
|
*/
|
||||||
public String getJDBCBaseURI() {
|
String getJDBCBaseURI() {
|
||||||
return JDBC_BASE_URI;
|
return JDBC_BASE_URI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.centralrepository.datamodel;
|
package org.sleuthkit.autopsy.centralrepository.datamodel;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.sql.Statement;
|
import java.sql.Statement;
|
||||||
@ -38,7 +37,7 @@ import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
|
|||||||
* All methods in AbstractSqlEamDb that read or write to the database should
|
* All methods in AbstractSqlEamDb that read or write to the database should
|
||||||
* be overriden here and use appropriate locking.
|
* be overriden here and use appropriate locking.
|
||||||
*/
|
*/
|
||||||
public class SqliteEamDb extends AbstractSqlEamDb {
|
final class SqliteEamDb extends AbstractSqlEamDb {
|
||||||
|
|
||||||
private final static Logger LOGGER = Logger.getLogger(SqliteEamDb.class.getName());
|
private final static Logger LOGGER = Logger.getLogger(SqliteEamDb.class.getName());
|
||||||
|
|
||||||
@ -125,7 +124,7 @@ public class SqliteEamDb extends AbstractSqlEamDb {
|
|||||||
|
|
||||||
String instancesTemplate = "DELETE FROM %s_instances";
|
String instancesTemplate = "DELETE FROM %s_instances";
|
||||||
String referencesTemplate = "DELETE FROM global_files";
|
String referencesTemplate = "DELETE FROM global_files";
|
||||||
for (CorrelationAttribute.Type type : DEFAULT_CORRELATION_TYPES) {
|
for (CorrelationAttribute.Type type : defaultCorrelationTypes) {
|
||||||
dropContent.executeUpdate(String.format(instancesTemplate, type.getDbTableName()));
|
dropContent.executeUpdate(String.format(instancesTemplate, type.getDbTableName()));
|
||||||
// FUTURE: support other reference types
|
// FUTURE: support other reference types
|
||||||
if (type.getId() == CorrelationAttribute.FILES_TYPE_ID) {
|
if (type.getId() == CorrelationAttribute.FILES_TYPE_ID) {
|
||||||
@ -590,6 +589,24 @@ public class SqliteEamDb extends AbstractSqlEamDb {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Gets list of matching eamArtifact instances that have knownStatus =
|
||||||
|
* "Bad".
|
||||||
|
* @param aType EamArtifact.Type to search for
|
||||||
|
* @return List with 0 or more matching eamArtifact instances.
|
||||||
|
* @throws EamDbException
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<CorrelationAttributeInstance> getArtifactInstancesKnownBad(CorrelationAttribute.Type aType) throws EamDbException {
|
||||||
|
try{
|
||||||
|
acquireSharedLock();
|
||||||
|
return super.getArtifactInstancesKnownBad(aType);
|
||||||
|
} finally {
|
||||||
|
releaseSharedLock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Count matching eamArtifacts instances that have knownStatus = "Bad".
|
* Count matching eamArtifacts instances that have knownStatus = "Bad".
|
||||||
*
|
*
|
||||||
@ -662,6 +679,22 @@ public class SqliteEamDb extends AbstractSqlEamDb {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process the Artifact instance in the EamDb
|
||||||
|
*
|
||||||
|
* @param type EamArtifact.Type to search for
|
||||||
|
* @param instanceTableCallback callback to process the instance
|
||||||
|
* @throws EamDbException
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void processInstanceTable(CorrelationAttribute.Type type, InstanceTableCallback instanceTableCallback) throws EamDbException {
|
||||||
|
try {
|
||||||
|
acquireSharedLock();
|
||||||
|
super.processInstanceTable(type, instanceTableCallback);
|
||||||
|
} finally {
|
||||||
|
releaseSharedLock();
|
||||||
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Check whether a reference set with the given name/version is in the central repo.
|
* Check whether a reference set with the given name/version is in the central repo.
|
||||||
* Used to check for name collisions when creating reference sets.
|
* Used to check for name collisions when creating reference sets.
|
||||||
@ -708,7 +741,7 @@ public class SqliteEamDb extends AbstractSqlEamDb {
|
|||||||
* @throws EamDbException
|
* @throws EamDbException
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public long newOrganization(EamOrganization eamOrg) throws EamDbException {
|
public EamOrganization newOrganization(EamOrganization eamOrg) throws EamDbException {
|
||||||
try{
|
try{
|
||||||
acquireExclusiveLock();
|
acquireExclusiveLock();
|
||||||
return super.newOrganization(eamOrg);
|
return super.newOrganization(eamOrg);
|
||||||
|
@ -35,13 +35,14 @@ import org.sleuthkit.autopsy.coreutils.PlatformUtil;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Settings for the sqlite implementation of the Central Repository database
|
* Settings for the sqlite implementation of the Central Repository database
|
||||||
|
*
|
||||||
|
* NOTE: This is public scope because the options panel calls it directly to set/get
|
||||||
*/
|
*/
|
||||||
public final class SqliteEamDbSettings {
|
public final class SqliteEamDbSettings {
|
||||||
|
|
||||||
private final static Logger LOGGER = Logger.getLogger(SqliteEamDbSettings.class.getName());
|
private final static Logger LOGGER = Logger.getLogger(SqliteEamDbSettings.class.getName());
|
||||||
private final String DEFAULT_DBNAME = "central_repository.db"; // NON-NLS
|
private final String DEFAULT_DBNAME = "central_repository.db"; // NON-NLS
|
||||||
private final String DEFAULT_DBDIRECTORY = PlatformUtil.getUserDirectory() + File.separator + "central_repository"; // NON-NLS
|
private final String DEFAULT_DBDIRECTORY = PlatformUtil.getUserDirectory() + File.separator + "central_repository"; // NON-NLS
|
||||||
private final int DEFAULT_BULK_THRESHHOLD = 1000;
|
|
||||||
private final String JDBC_DRIVER = "org.sqlite.JDBC"; // NON-NLS
|
private final String JDBC_DRIVER = "org.sqlite.JDBC"; // NON-NLS
|
||||||
private final String JDBC_BASE_URI = "jdbc:sqlite:"; // NON-NLS
|
private final String JDBC_BASE_URI = "jdbc:sqlite:"; // NON-NLS
|
||||||
private final String VALIDATION_QUERY = "SELECT count(*) from sqlite_master"; // NON-NLS
|
private final String VALIDATION_QUERY = "SELECT count(*) from sqlite_master"; // NON-NLS
|
||||||
@ -75,15 +76,15 @@ public final class SqliteEamDbSettings {
|
|||||||
try {
|
try {
|
||||||
String bulkThresholdString = ModuleSettings.getConfigSetting("CentralRepository", "db.sqlite.bulkThreshold"); // NON-NLS
|
String bulkThresholdString = ModuleSettings.getConfigSetting("CentralRepository", "db.sqlite.bulkThreshold"); // NON-NLS
|
||||||
if (bulkThresholdString == null || bulkThresholdString.isEmpty()) {
|
if (bulkThresholdString == null || bulkThresholdString.isEmpty()) {
|
||||||
this.bulkThreshold = DEFAULT_BULK_THRESHHOLD;
|
this.bulkThreshold = AbstractSqlEamDb.DEFAULT_BULK_THRESHHOLD;
|
||||||
} else {
|
} else {
|
||||||
this.bulkThreshold = Integer.parseInt(bulkThresholdString);
|
this.bulkThreshold = Integer.parseInt(bulkThresholdString);
|
||||||
if (getBulkThreshold() <= 0) {
|
if (getBulkThreshold() <= 0) {
|
||||||
this.bulkThreshold = DEFAULT_BULK_THRESHHOLD;
|
this.bulkThreshold = AbstractSqlEamDb.DEFAULT_BULK_THRESHHOLD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (NumberFormatException ex) {
|
} catch (NumberFormatException ex) {
|
||||||
this.bulkThreshold = DEFAULT_BULK_THRESHHOLD;
|
this.bulkThreshold = AbstractSqlEamDb.DEFAULT_BULK_THRESHHOLD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,7 +163,7 @@ public final class SqliteEamDbSettings {
|
|||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public String getConnectionURL() {
|
String getConnectionURL() {
|
||||||
StringBuilder url = new StringBuilder();
|
StringBuilder url = new StringBuilder();
|
||||||
url.append(getJDBCBaseURI());
|
url.append(getJDBCBaseURI());
|
||||||
url.append(getFileNameWithPath());
|
url.append(getFileNameWithPath());
|
||||||
@ -439,7 +440,7 @@ public final class SqliteEamDbSettings {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isChanged() {
|
boolean isChanged() {
|
||||||
String dbNameString = ModuleSettings.getConfigSetting("CentralRepository", "db.sqlite.dbName"); // NON-NLS
|
String dbNameString = ModuleSettings.getConfigSetting("CentralRepository", "db.sqlite.dbName"); // NON-NLS
|
||||||
String dbDirectoryString = ModuleSettings.getConfigSetting("CentralRepository", "db.sqlite.dbDirectory"); // NON-NLS
|
String dbDirectoryString = ModuleSettings.getConfigSetting("CentralRepository", "db.sqlite.dbDirectory"); // NON-NLS
|
||||||
String bulkThresholdString = ModuleSettings.getConfigSetting("CentralRepository", "db.sqlite.bulkThreshold"); // NON-NLS
|
String bulkThresholdString = ModuleSettings.getConfigSetting("CentralRepository", "db.sqlite.bulkThreshold"); // NON-NLS
|
||||||
@ -474,14 +475,14 @@ public final class SqliteEamDbSettings {
|
|||||||
/**
|
/**
|
||||||
* @return the bulkThreshold
|
* @return the bulkThreshold
|
||||||
*/
|
*/
|
||||||
public int getBulkThreshold() {
|
int getBulkThreshold() {
|
||||||
return bulkThreshold;
|
return bulkThreshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param bulkThreshold the bulkThreshold to set
|
* @param bulkThreshold the bulkThreshold to set
|
||||||
*/
|
*/
|
||||||
public void setBulkThreshold(int bulkThreshold) throws EamDbException {
|
void setBulkThreshold(int bulkThreshold) throws EamDbException {
|
||||||
if (bulkThreshold > 0) {
|
if (bulkThreshold > 0) {
|
||||||
this.bulkThreshold = bulkThreshold;
|
this.bulkThreshold = bulkThreshold;
|
||||||
} else {
|
} else {
|
||||||
@ -525,21 +526,21 @@ public final class SqliteEamDbSettings {
|
|||||||
/**
|
/**
|
||||||
* @return the DRIVER
|
* @return the DRIVER
|
||||||
*/
|
*/
|
||||||
public String getDriver() {
|
String getDriver() {
|
||||||
return JDBC_DRIVER;
|
return JDBC_DRIVER;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the VALIDATION_QUERY
|
* @return the VALIDATION_QUERY
|
||||||
*/
|
*/
|
||||||
public String getValidationQuery() {
|
String getValidationQuery() {
|
||||||
return VALIDATION_QUERY;
|
return VALIDATION_QUERY;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the JDBC_BASE_URI
|
* @return the JDBC_BASE_URI
|
||||||
*/
|
*/
|
||||||
public String getJDBCBaseURI() {
|
String getJDBCBaseURI() {
|
||||||
return JDBC_BASE_URI;
|
return JDBC_BASE_URI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -450,10 +450,10 @@ final class CaseEventListener implements PropertyChangeListener {
|
|||||||
correlationCase = dbManager.newCase(openCase);
|
correlationCase = dbManager.newCase(openCase);
|
||||||
}
|
}
|
||||||
if (null == dbManager.getDataSource(correlationCase, deviceId)) {
|
if (null == dbManager.getDataSource(correlationCase, deviceId)) {
|
||||||
dbManager.newDataSource(CorrelationDataSource.fromTSKDataSource(correlationCase, newDataSource));
|
CorrelationDataSource.fromTSKDataSource(correlationCase, newDataSource);
|
||||||
}
|
}
|
||||||
} catch (EamDbException ex) {
|
} catch (EamDbException ex) {
|
||||||
LOGGER.log(Level.SEVERE, "Error connecting to Central Repository database.", ex); //NON-NLS
|
LOGGER.log(Level.SEVERE, "Error adding new data source to the central repository", ex); //NON-NLS
|
||||||
} catch (TskCoreException | TskDataException ex) {
|
} catch (TskCoreException | TskDataException ex) {
|
||||||
LOGGER.log(Level.SEVERE, "Error getting data source from DATA_SOURCE_ADDED event content.", ex); //NON-NLS
|
LOGGER.log(Level.SEVERE, "Error getting data source from DATA_SOURCE_ADDED event content.", ex); //NON-NLS
|
||||||
}
|
}
|
||||||
|
@ -276,12 +276,12 @@ public class IngestEventsListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (FALSE == eamArtifacts.isEmpty()) {
|
if (FALSE == eamArtifacts.isEmpty()) {
|
||||||
try {
|
|
||||||
for (CorrelationAttribute eamArtifact : eamArtifacts) {
|
for (CorrelationAttribute eamArtifact : eamArtifacts) {
|
||||||
|
try {
|
||||||
dbManager.addArtifact(eamArtifact);
|
dbManager.addArtifact(eamArtifact);
|
||||||
}
|
|
||||||
} catch (EamDbException ex) {
|
} catch (EamDbException ex) {
|
||||||
LOGGER.log(Level.SEVERE, "Error connecting to Central Repository database.", ex); //NON-NLS
|
LOGGER.log(Level.SEVERE, "Error adding artifact to database.", ex); //NON-NLS
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} // DATA_ADDED
|
} // DATA_ADDED
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ import org.sleuthkit.datamodel.BlackboardAttribute;
|
|||||||
import org.sleuthkit.datamodel.HashUtility;
|
import org.sleuthkit.datamodel.HashUtility;
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
import org.sleuthkit.datamodel.TskData;
|
import org.sleuthkit.datamodel.TskData;
|
||||||
import org.sleuthkit.autopsy.healthmonitor.EnterpriseHealthMonitor;
|
import org.sleuthkit.autopsy.healthmonitor.HealthMonitor;
|
||||||
import org.sleuthkit.autopsy.healthmonitor.TimingMetric;
|
import org.sleuthkit.autopsy.healthmonitor.TimingMetric;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -102,7 +102,11 @@ final class IngestModule implements FileIngestModule {
|
|||||||
return ProcessResult.ERROR;
|
return ProcessResult.ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!EamArtifactUtil.isValidCentralRepoFile(abstractFile)) {
|
if (!EamArtifactUtil.isSupportedAbstractFileType(abstractFile)) {
|
||||||
|
return ProcessResult.OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (abstractFile.getKnown() == TskData.FileKnown.KNOWN) {
|
||||||
return ProcessResult.OK;
|
return ProcessResult.OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,9 +135,9 @@ final class IngestModule implements FileIngestModule {
|
|||||||
*/
|
*/
|
||||||
if (abstractFile.getKnown() != TskData.FileKnown.KNOWN && flagTaggedNotableItems) {
|
if (abstractFile.getKnown() != TskData.FileKnown.KNOWN && flagTaggedNotableItems) {
|
||||||
try {
|
try {
|
||||||
TimingMetric timingMetric = EnterpriseHealthMonitor.getTimingMetric("Correlation Engine: Notable artifact query");
|
TimingMetric timingMetric = HealthMonitor.getTimingMetric("Correlation Engine: Notable artifact query");
|
||||||
List<String> caseDisplayNamesList = dbManager.getListCasesHavingArtifactInstancesKnownBad(filesType, md5);
|
List<String> caseDisplayNamesList = dbManager.getListCasesHavingArtifactInstancesKnownBad(filesType, md5);
|
||||||
EnterpriseHealthMonitor.submitTimingMetric(timingMetric);
|
HealthMonitor.submitTimingMetric(timingMetric);
|
||||||
if (!caseDisplayNamesList.isEmpty()) {
|
if (!caseDisplayNamesList.isEmpty()) {
|
||||||
postCorrelatedBadFileToBlackboard(abstractFile, caseDisplayNamesList);
|
postCorrelatedBadFileToBlackboard(abstractFile, caseDisplayNamesList);
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettingsPanel;
|
|||||||
/**
|
/**
|
||||||
* Ingest job settings panel for the Correlation Engine module.
|
* Ingest job settings panel for the Correlation Engine module.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
final class IngestSettingsPanel extends IngestModuleIngestJobSettingsPanel {
|
final class IngestSettingsPanel extends IngestModuleIngestJobSettingsPanel {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -36,9 +36,10 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
|
|||||||
/**
|
/**
|
||||||
* Dialog to add a new organization to the Central Repository database
|
* Dialog to add a new organization to the Central Repository database
|
||||||
*/
|
*/
|
||||||
public class AddNewOrganizationDialog extends javax.swing.JDialog {
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
|
class AddNewOrganizationDialog extends javax.swing.JDialog {
|
||||||
|
|
||||||
private static final Logger LOGGER = Logger.getLogger(AddNewOrganizationDialog.class.getName());
|
private static final Logger logger = Logger.getLogger(AddNewOrganizationDialog.class.getName());
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
private final Collection<JTextField> textBoxes;
|
private final Collection<JTextField> textBoxes;
|
||||||
@ -51,7 +52,7 @@ public class AddNewOrganizationDialog extends javax.swing.JDialog {
|
|||||||
* Creates new form AddNewOrganizationDialog
|
* Creates new form AddNewOrganizationDialog
|
||||||
*/
|
*/
|
||||||
@Messages({"AddNewOrganizationDialog.addNewOrg.msg=Add New Organization"})
|
@Messages({"AddNewOrganizationDialog.addNewOrg.msg=Add New Organization"})
|
||||||
public AddNewOrganizationDialog() {
|
AddNewOrganizationDialog() {
|
||||||
super((JFrame) WindowManager.getDefault().getMainWindow(),
|
super((JFrame) WindowManager.getDefault().getMainWindow(),
|
||||||
Bundle.AddNewOrganizationDialog_addNewOrg_msg(),
|
Bundle.AddNewOrganizationDialog_addNewOrg_msg(),
|
||||||
true); // NON-NLS
|
true); // NON-NLS
|
||||||
@ -65,6 +66,7 @@ public class AddNewOrganizationDialog extends javax.swing.JDialog {
|
|||||||
display();
|
display();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// populates the dialog with existing case information to edit
|
||||||
public AddNewOrganizationDialog(EamOrganization orgToEdit) {
|
public AddNewOrganizationDialog(EamOrganization orgToEdit) {
|
||||||
super((JFrame) WindowManager.getDefault().getMainWindow(),
|
super((JFrame) WindowManager.getDefault().getMainWindow(),
|
||||||
Bundle.AddNewOrganizationDialog_addNewOrg_msg(),
|
Bundle.AddNewOrganizationDialog_addNewOrg_msg(),
|
||||||
@ -193,10 +195,19 @@ public class AddNewOrganizationDialog extends javax.swing.JDialog {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return True if new org was added or existing org changed
|
||||||
|
*/
|
||||||
public boolean isChanged() {
|
public boolean isChanged() {
|
||||||
return hasChanged;
|
return hasChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only valid if isChanged() is true.
|
||||||
|
*
|
||||||
|
* @return Org that was added or changed. null if nothing changed
|
||||||
|
*/
|
||||||
public EamOrganization getNewOrg() {
|
public EamOrganization getNewOrg() {
|
||||||
return newOrg;
|
return newOrg;
|
||||||
}
|
}
|
||||||
@ -332,12 +343,12 @@ public class AddNewOrganizationDialog extends javax.swing.JDialog {
|
|||||||
try {
|
try {
|
||||||
EamDb dbManager = EamDb.getInstance();
|
EamDb dbManager = EamDb.getInstance();
|
||||||
if (organizationToEdit != null) {
|
if (organizationToEdit != null) {
|
||||||
//check if new name exists with ID other than the one in use here
|
// make a copy in case the update fails
|
||||||
newOrg = new EamOrganization(organizationToEdit.getOrgID(),
|
newOrg = dbManager.getOrganizationByID(organizationToEdit.getOrgID());
|
||||||
tfOrganizationName.getText(),
|
newOrg.setName(tfOrganizationName.getText());
|
||||||
tfPocName.getText(),
|
newOrg.setPocName(tfPocName.getText());
|
||||||
tfPocEmail.getText(),
|
newOrg.setPocEmail(tfPocEmail.getText());
|
||||||
tfPocPhone.getText());
|
newOrg.setPocPhone(tfPocPhone.getText());
|
||||||
dbManager.updateOrganization(newOrg);
|
dbManager.updateOrganization(newOrg);
|
||||||
} else {
|
} else {
|
||||||
newOrg = new EamOrganization(
|
newOrg = new EamOrganization(
|
||||||
@ -345,13 +356,14 @@ public class AddNewOrganizationDialog extends javax.swing.JDialog {
|
|||||||
tfPocName.getText(),
|
tfPocName.getText(),
|
||||||
tfPocEmail.getText(),
|
tfPocEmail.getText(),
|
||||||
tfPocPhone.getText());
|
tfPocPhone.getText());
|
||||||
newOrg.setOrgID((int)dbManager.newOrganization(newOrg));
|
newOrg = dbManager.newOrganization(newOrg);
|
||||||
}
|
}
|
||||||
hasChanged = true;
|
hasChanged = true;
|
||||||
dispose();
|
dispose();
|
||||||
} catch (EamDbException ex) {
|
} catch (EamDbException ex) {
|
||||||
lbWarningMsg.setText(Bundle.AddNewOrganizationDialog_bnOk_addFailed_text());
|
lbWarningMsg.setText(Bundle.AddNewOrganizationDialog_bnOk_addFailed_text());
|
||||||
LOGGER.log(Level.SEVERE, "Failed adding new organization.", ex);
|
logger.log(Level.SEVERE, "Failed adding new organization.", ex);
|
||||||
|
newOrg = null;
|
||||||
}
|
}
|
||||||
}//GEN-LAST:event_bnOKActionPerformed
|
}//GEN-LAST:event_bnOKActionPerformed
|
||||||
|
|
||||||
|
@ -65,3 +65,13 @@ GlobalSettingsPanel.manageOrganizationButton.text=Manage Organizations
|
|||||||
GlobalSettingsPanel.lbCentralRepository.text=A central repository allows you to correlate files and results between cases.
|
GlobalSettingsPanel.lbCentralRepository.text=A central repository allows you to correlate files and results between cases.
|
||||||
GlobalSettingsPanel.pnCorrelationProperties.border.title=Correlation Properties
|
GlobalSettingsPanel.pnCorrelationProperties.border.title=Correlation Properties
|
||||||
GlobalSettingsPanel.organizationPanel.border.title=Organizations
|
GlobalSettingsPanel.organizationPanel.border.title=Organizations
|
||||||
|
GlobalSettingsPanel.casesPanel.border.title=Case Details
|
||||||
|
GlobalSettingsPanel.showCasesButton.text=Show Cases
|
||||||
|
ShowCasesDialog.closeButton.AccessibleContext.accessibleName=Close
|
||||||
|
ShowCasesDialog.closeButton.actionCommand=Close
|
||||||
|
ShowCasesDialog.closeButton.text=Close
|
||||||
|
ShowCasesDialog.caseDetailsTable.toolTipText=Click column name to sort. Right-click on the table for more options.
|
||||||
|
ShowCasesDialog.title=Case Details
|
||||||
|
GlobalSettingsPanel.Case\ Details.AccessibleContext.accessibleName=Cases Details
|
||||||
|
ShowCasesDialog.caseDetailsTable.AccessibleContext.accessibleDescription=Click column name to sort.
|
||||||
|
GlobalSettingsPanel.casesTextArea.text=Display table that lists central repository case details.
|
||||||
|
@ -47,9 +47,9 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.PostgresEamDbSettings;
|
|||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.SqliteEamDbSettings;
|
import org.sleuthkit.autopsy.centralrepository.datamodel.SqliteEamDbSettings;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Configuration dialog for Central Repository database settings.
|
||||||
* @author nick
|
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
public class EamDbSettingsDialog extends JDialog {
|
public class EamDbSettingsDialog extends JDialog {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(EamDbSettingsDialog.class.getName());
|
private static final Logger logger = Logger.getLogger(EamDbSettingsDialog.class.getName());
|
||||||
@ -96,11 +96,8 @@ public class EamDbSettingsDialog extends JDialog {
|
|||||||
public boolean accept(File pathname) {
|
public boolean accept(File pathname) {
|
||||||
if (pathname.isDirectory()) {
|
if (pathname.isDirectory()) {
|
||||||
return true;
|
return true;
|
||||||
} else if (pathname.getName().toLowerCase().equals((CENTRAL_REPO_DB_NAME + CENTRAL_REPO_SQLITE_EXT).toLowerCase())) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
return pathname.getName().toLowerCase().equals((CENTRAL_REPO_DB_NAME + CENTRAL_REPO_SQLITE_EXT).toLowerCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
<DimensionLayout dim="1">
|
<DimensionLayout dim="1">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Component id="jScrollPane1" alignment="0" pref="488" max="32767" attributes="0"/>
|
<Component id="jScrollPane1" alignment="0" pref="517" max="32767" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
</Layout>
|
</Layout>
|
||||||
@ -57,23 +57,25 @@
|
|||||||
<Layout>
|
<Layout>
|
||||||
<DimensionLayout dim="0">
|
<DimensionLayout dim="0">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Component id="lbCentralRepository" max="32767" attributes="0"/>
|
<Component id="lbCentralRepository" pref="1022" max="32767" attributes="0"/>
|
||||||
<Group type="102" attributes="0">
|
<Group type="102" attributes="0">
|
||||||
<Component id="cbUseCentralRepo" min="-2" max="-2" attributes="0"/>
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
<Component id="pnDatabaseConfiguration" alignment="0" max="32767" attributes="0"/>
|
||||||
|
<Component id="pnCorrelationProperties" alignment="0" pref="1016" max="32767" attributes="0"/>
|
||||||
|
<Component id="organizationPanel" alignment="1" max="32767" attributes="0"/>
|
||||||
|
<Component id="casesPanel" alignment="0" max="32767" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
<Group type="102" attributes="0">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Component id="cbUseCentralRepo" min="-2" max="-2" attributes="0"/>
|
||||||
<Group type="102" alignment="0" attributes="0">
|
<Group type="102" alignment="0" attributes="0">
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Component id="tbOops" min="-2" pref="974" max="-2" attributes="0"/>
|
<Component id="tbOops" min="-2" pref="974" max="-2" attributes="0"/>
|
||||||
<EmptySpace pref="36" max="32767" attributes="0"/>
|
|
||||||
</Group>
|
</Group>
|
||||||
<Group type="102" alignment="1" attributes="0">
|
|
||||||
<Group type="103" groupAlignment="1" attributes="0">
|
|
||||||
<Component id="pnDatabaseConfiguration" alignment="0" max="32767" attributes="0"/>
|
|
||||||
<Component id="pnCorrelationProperties" alignment="0" pref="1012" max="32767" attributes="0"/>
|
|
||||||
<Component id="organizationPanel" max="32767" attributes="0"/>
|
|
||||||
</Group>
|
</Group>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
@ -90,8 +92,10 @@
|
|||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Component id="organizationPanel" min="-2" max="-2" attributes="0"/>
|
<Component id="organizationPanel" min="-2" max="-2" attributes="0"/>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Component id="casesPanel" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Component id="tbOops" min="-2" max="-2" attributes="0"/>
|
<Component id="tbOops" min="-2" max="-2" attributes="0"/>
|
||||||
<EmptySpace min="0" pref="92" max="32767" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
@ -328,7 +332,7 @@
|
|||||||
<Group type="102" attributes="0">
|
<Group type="102" attributes="0">
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Component id="organizationScrollPane" max="32767" attributes="0"/>
|
<Component id="organizationScrollPane" pref="992" max="32767" attributes="0"/>
|
||||||
<Group type="102" attributes="0">
|
<Group type="102" attributes="0">
|
||||||
<Component id="manageOrganizationButton" min="-2" max="-2" attributes="0"/>
|
<Component id="manageOrganizationButton" min="-2" max="-2" attributes="0"/>
|
||||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||||
@ -398,6 +402,100 @@
|
|||||||
</Container>
|
</Container>
|
||||||
</SubComponents>
|
</SubComponents>
|
||||||
</Container>
|
</Container>
|
||||||
|
<Container class="javax.swing.JPanel" name="casesPanel">
|
||||||
|
<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="Case Details">
|
||||||
|
<ResourceString PropertyName="titleX" bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="GlobalSettingsPanel.casesPanel.border.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
<Font PropertyName="font" name="Tahoma" size="12" style="0"/>
|
||||||
|
</TitledBorder>
|
||||||
|
</Border>
|
||||||
|
</Property>
|
||||||
|
<Property name="name" type="java.lang.String" value="Case Details" noResource="true"/>
|
||||||
|
</Properties>
|
||||||
|
<AccessibilityProperties>
|
||||||
|
<Property name="AccessibleContext.accessibleName" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="GlobalSettingsPanel.Case Details.AccessibleContext.accessibleName" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</AccessibilityProperties>
|
||||||
|
|
||||||
|
<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="casesScrollPane" alignment="0" max="32767" attributes="0"/>
|
||||||
|
<Group type="102" alignment="0" attributes="0">
|
||||||
|
<Component id="showCasesButton" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
</DimensionLayout>
|
||||||
|
<DimensionLayout dim="1">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Group type="102" alignment="1" attributes="0">
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Component id="casesScrollPane" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Component id="showCasesButton" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace min="-2" pref="8" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
</DimensionLayout>
|
||||||
|
</Layout>
|
||||||
|
<SubComponents>
|
||||||
|
<Component class="javax.swing.JButton" name="showCasesButton">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="GlobalSettingsPanel.showCasesButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<Events>
|
||||||
|
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="showCasesButtonActionPerformed"/>
|
||||||
|
</Events>
|
||||||
|
</Component>
|
||||||
|
<Container class="javax.swing.JScrollPane" name="casesScrollPane">
|
||||||
|
<Properties>
|
||||||
|
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||||
|
<Border info="null"/>
|
||||||
|
</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.JTextArea" name="casesTextArea">
|
||||||
|
<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" red="f0" type="rgb"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="columns" type="int" value="20"/>
|
||||||
|
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||||
|
<Font name="Tahoma" size="11" style="0"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="lineWrap" type="boolean" value="true"/>
|
||||||
|
<Property name="rows" type="int" value="2"/>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="GlobalSettingsPanel.casesTextArea.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="wrapStyleWord" type="boolean" value="true"/>
|
||||||
|
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||||
|
<Border info="null"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
</SubComponents>
|
||||||
|
</Container>
|
||||||
|
</SubComponents>
|
||||||
|
</Container>
|
||||||
<Component class="javax.swing.JTextField" name="tbOops">
|
<Component class="javax.swing.JTextField" name="tbOops">
|
||||||
<Properties>
|
<Properties>
|
||||||
<Property name="editable" type="boolean" value="false"/>
|
<Property name="editable" type="boolean" value="false"/>
|
||||||
|
@ -41,6 +41,7 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.SqliteEamDbSettings;
|
|||||||
/**
|
/**
|
||||||
* Main settings panel for the Central Repository
|
* Main settings panel for the Central Repository
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel implements OptionsPanel {
|
public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel implements OptionsPanel {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
@ -123,6 +124,10 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
|
|||||||
manageOrganizationButton = new javax.swing.JButton();
|
manageOrganizationButton = new javax.swing.JButton();
|
||||||
organizationScrollPane = new javax.swing.JScrollPane();
|
organizationScrollPane = new javax.swing.JScrollPane();
|
||||||
organizationTextArea = new javax.swing.JTextArea();
|
organizationTextArea = new javax.swing.JTextArea();
|
||||||
|
casesPanel = new javax.swing.JPanel();
|
||||||
|
showCasesButton = new javax.swing.JButton();
|
||||||
|
casesScrollPane = new javax.swing.JScrollPane();
|
||||||
|
casesTextArea = new javax.swing.JTextArea();
|
||||||
tbOops = new javax.swing.JTextField();
|
tbOops = new javax.swing.JTextField();
|
||||||
|
|
||||||
setName(""); // NOI18N
|
setName(""); // NOI18N
|
||||||
@ -275,7 +280,7 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
|
|||||||
.addGroup(organizationPanelLayout.createSequentialGroup()
|
.addGroup(organizationPanelLayout.createSequentialGroup()
|
||||||
.addContainerGap()
|
.addContainerGap()
|
||||||
.addGroup(organizationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
.addGroup(organizationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addComponent(organizationScrollPane)
|
.addComponent(organizationScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 992, Short.MAX_VALUE)
|
||||||
.addGroup(organizationPanelLayout.createSequentialGroup()
|
.addGroup(organizationPanelLayout.createSequentialGroup()
|
||||||
.addComponent(manageOrganizationButton)
|
.addComponent(manageOrganizationButton)
|
||||||
.addGap(0, 0, Short.MAX_VALUE)))
|
.addGap(0, 0, Short.MAX_VALUE)))
|
||||||
@ -291,6 +296,52 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
|
|||||||
.addGap(8, 8, 8))
|
.addGap(8, 8, 8))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
casesPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(null, org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.casesPanel.border.title"), javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Tahoma", 0, 12))); // NOI18N
|
||||||
|
casesPanel.setName("Case Details"); // NOI18N
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(showCasesButton, org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.showCasesButton.text")); // NOI18N
|
||||||
|
showCasesButton.addActionListener(new java.awt.event.ActionListener() {
|
||||||
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
|
showCasesButtonActionPerformed(evt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
casesScrollPane.setBorder(null);
|
||||||
|
|
||||||
|
casesTextArea.setEditable(false);
|
||||||
|
casesTextArea.setBackground(new java.awt.Color(240, 240, 240));
|
||||||
|
casesTextArea.setColumns(20);
|
||||||
|
casesTextArea.setFont(new java.awt.Font("Tahoma", 0, 11)); // NOI18N
|
||||||
|
casesTextArea.setLineWrap(true);
|
||||||
|
casesTextArea.setRows(2);
|
||||||
|
casesTextArea.setText(org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.casesTextArea.text")); // NOI18N
|
||||||
|
casesTextArea.setWrapStyleWord(true);
|
||||||
|
casesTextArea.setBorder(null);
|
||||||
|
casesScrollPane.setViewportView(casesTextArea);
|
||||||
|
|
||||||
|
javax.swing.GroupLayout casesPanelLayout = new javax.swing.GroupLayout(casesPanel);
|
||||||
|
casesPanel.setLayout(casesPanelLayout);
|
||||||
|
casesPanelLayout.setHorizontalGroup(
|
||||||
|
casesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGroup(casesPanelLayout.createSequentialGroup()
|
||||||
|
.addContainerGap()
|
||||||
|
.addGroup(casesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addComponent(casesScrollPane)
|
||||||
|
.addGroup(casesPanelLayout.createSequentialGroup()
|
||||||
|
.addComponent(showCasesButton)
|
||||||
|
.addGap(0, 0, Short.MAX_VALUE)))
|
||||||
|
.addContainerGap())
|
||||||
|
);
|
||||||
|
casesPanelLayout.setVerticalGroup(
|
||||||
|
casesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, casesPanelLayout.createSequentialGroup()
|
||||||
|
.addContainerGap()
|
||||||
|
.addComponent(casesScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
|
.addComponent(showCasesButton)
|
||||||
|
.addGap(8, 8, 8))
|
||||||
|
);
|
||||||
|
|
||||||
tbOops.setEditable(false);
|
tbOops.setEditable(false);
|
||||||
tbOops.setFont(tbOops.getFont().deriveFont(tbOops.getFont().getStyle() | java.awt.Font.BOLD, 12));
|
tbOops.setFont(tbOops.getFont().deriveFont(tbOops.getFont().getStyle() | java.awt.Font.BOLD, 12));
|
||||||
tbOops.setText(org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.tbOops.text")); // NOI18N
|
tbOops.setText(org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.tbOops.text")); // NOI18N
|
||||||
@ -300,20 +351,21 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
|
|||||||
jPanel1.setLayout(jPanel1Layout);
|
jPanel1.setLayout(jPanel1Layout);
|
||||||
jPanel1Layout.setHorizontalGroup(
|
jPanel1Layout.setHorizontalGroup(
|
||||||
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addComponent(lbCentralRepository, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
.addComponent(lbCentralRepository, javax.swing.GroupLayout.DEFAULT_SIZE, 1022, Short.MAX_VALUE)
|
||||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||||
|
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addComponent(pnDatabaseConfiguration, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||||
|
.addComponent(pnCorrelationProperties, javax.swing.GroupLayout.DEFAULT_SIZE, 1016, Short.MAX_VALUE)
|
||||||
|
.addComponent(organizationPanel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||||
|
.addComponent(casesPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||||
|
.addContainerGap())
|
||||||
|
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||||
|
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addComponent(cbUseCentralRepo)
|
.addComponent(cbUseCentralRepo)
|
||||||
.addGap(0, 0, Short.MAX_VALUE))
|
|
||||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||||
.addContainerGap()
|
.addContainerGap()
|
||||||
.addComponent(tbOops, javax.swing.GroupLayout.PREFERRED_SIZE, 974, javax.swing.GroupLayout.PREFERRED_SIZE)
|
.addComponent(tbOops, javax.swing.GroupLayout.PREFERRED_SIZE, 974, javax.swing.GroupLayout.PREFERRED_SIZE)))
|
||||||
.addContainerGap(36, Short.MAX_VALUE))
|
.addGap(0, 0, Short.MAX_VALUE))
|
||||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
|
|
||||||
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
|
||||||
.addComponent(pnDatabaseConfiguration, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
|
||||||
.addComponent(pnCorrelationProperties, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 1012, Short.MAX_VALUE)
|
|
||||||
.addComponent(organizationPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
|
||||||
.addContainerGap())
|
|
||||||
);
|
);
|
||||||
jPanel1Layout.setVerticalGroup(
|
jPanel1Layout.setVerticalGroup(
|
||||||
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
@ -328,10 +380,14 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
|
|||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addComponent(organizationPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
.addComponent(organizationPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
|
.addComponent(casesPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addComponent(tbOops, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
.addComponent(tbOops, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
.addGap(0, 92, Short.MAX_VALUE))
|
.addContainerGap())
|
||||||
);
|
);
|
||||||
|
|
||||||
|
casesPanel.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.Case Details.AccessibleContext.accessibleName")); // NOI18N
|
||||||
|
|
||||||
jScrollPane1.setViewportView(jPanel1);
|
jScrollPane1.setViewportView(jPanel1);
|
||||||
|
|
||||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||||
@ -342,13 +398,13 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
|
|||||||
);
|
);
|
||||||
layout.setVerticalGroup(
|
layout.setVerticalGroup(
|
||||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 488, Short.MAX_VALUE)
|
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 517, Short.MAX_VALUE)
|
||||||
);
|
);
|
||||||
}// </editor-fold>//GEN-END:initComponents
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
|
|
||||||
private void bnManageTypesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnManageTypesActionPerformed
|
private void bnManageTypesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnManageTypesActionPerformed
|
||||||
store();
|
store();
|
||||||
ManageCorrelationPropertiesDialog dialog = new ManageCorrelationPropertiesDialog();
|
ManageCorrelationPropertiesDialog manageCorrelationDialog = new ManageCorrelationPropertiesDialog();
|
||||||
firePropertyChange(OptionsPanelController.PROP_VALID, null, null);
|
firePropertyChange(OptionsPanelController.PROP_VALID, null, null);
|
||||||
}//GEN-LAST:event_bnManageTypesActionPerformed
|
}//GEN-LAST:event_bnManageTypesActionPerformed
|
||||||
|
|
||||||
@ -373,9 +429,14 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
|
|||||||
|
|
||||||
private void manageOrganizationButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_manageOrganizationButtonActionPerformed
|
private void manageOrganizationButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_manageOrganizationButtonActionPerformed
|
||||||
store();
|
store();
|
||||||
ManageOrganizationsDialog dialog = new ManageOrganizationsDialog();
|
ManageOrganizationsDialog manageOrganizationsDialog = new ManageOrganizationsDialog();
|
||||||
}//GEN-LAST:event_manageOrganizationButtonActionPerformed
|
}//GEN-LAST:event_manageOrganizationButtonActionPerformed
|
||||||
|
|
||||||
|
private void showCasesButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_showCasesButtonActionPerformed
|
||||||
|
store();
|
||||||
|
ShowCasesDialog showCasesDialog = new ShowCasesDialog();
|
||||||
|
}//GEN-LAST:event_showCasesButtonActionPerformed
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Messages({"GlobalSettingsPanel.validationerrMsg.mustConfigure=Configure the database to enable this module."})
|
@Messages({"GlobalSettingsPanel.validationerrMsg.mustConfigure=Configure the database to enable this module."})
|
||||||
public void load() {
|
public void load() {
|
||||||
@ -552,12 +613,18 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
|
|||||||
organizationPanel.setEnabled(enable && !ingestRunning);
|
organizationPanel.setEnabled(enable && !ingestRunning);
|
||||||
organizationTextArea.setEnabled(enable && !ingestRunning);
|
organizationTextArea.setEnabled(enable && !ingestRunning);
|
||||||
manageOrganizationButton.setEnabled(enable && !ingestRunning);
|
manageOrganizationButton.setEnabled(enable && !ingestRunning);
|
||||||
|
showCasesButton.setEnabled(enable && !ingestRunning);
|
||||||
|
casesPanel.setEnabled(enable && !ingestRunning);
|
||||||
|
casesTextArea.setEnabled(enable && !ingestRunning);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
private javax.swing.JButton bnDbConfigure;
|
private javax.swing.JButton bnDbConfigure;
|
||||||
private javax.swing.JButton bnManageTypes;
|
private javax.swing.JButton bnManageTypes;
|
||||||
|
private javax.swing.JPanel casesPanel;
|
||||||
|
private javax.swing.JScrollPane casesScrollPane;
|
||||||
|
private javax.swing.JTextArea casesTextArea;
|
||||||
private javax.swing.JCheckBox cbUseCentralRepo;
|
private javax.swing.JCheckBox cbUseCentralRepo;
|
||||||
private javax.swing.JScrollPane correlationPropertiesScrollPane;
|
private javax.swing.JScrollPane correlationPropertiesScrollPane;
|
||||||
private javax.swing.JTextArea correlationPropertiesTextArea;
|
private javax.swing.JTextArea correlationPropertiesTextArea;
|
||||||
@ -576,6 +643,7 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
|
|||||||
private javax.swing.JTextArea organizationTextArea;
|
private javax.swing.JTextArea organizationTextArea;
|
||||||
private javax.swing.JPanel pnCorrelationProperties;
|
private javax.swing.JPanel pnCorrelationProperties;
|
||||||
private javax.swing.JPanel pnDatabaseConfiguration;
|
private javax.swing.JPanel pnDatabaseConfiguration;
|
||||||
|
private javax.swing.JButton showCasesButton;
|
||||||
private javax.swing.JTextField tbOops;
|
private javax.swing.JTextField tbOops;
|
||||||
// End of variables declaration//GEN-END:variables
|
// End of variables declaration//GEN-END:variables
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Central Repository
|
* Central Repository
|
||||||
*
|
*
|
||||||
* Copyright 2015-2017 Basis Technology Corp.
|
* Copyright 2015-2018 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -18,8 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.centralrepository.optionspanel;
|
package org.sleuthkit.autopsy.centralrepository.optionspanel;
|
||||||
|
|
||||||
import java.awt.Dimension;
|
|
||||||
import java.awt.Toolkit;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
@ -40,6 +38,7 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
|
|||||||
* Dialog to handle management of artifact types handled by the Central
|
* Dialog to handle management of artifact types handled by the Central
|
||||||
* Repository
|
* Repository
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
final class ManageCorrelationPropertiesDialog extends javax.swing.JDialog {
|
final class ManageCorrelationPropertiesDialog extends javax.swing.JDialog {
|
||||||
|
|
||||||
private static final Logger LOGGER = Logger.getLogger(ManageCorrelationPropertiesDialog.class.getName());
|
private static final Logger LOGGER = Logger.getLogger(ManageCorrelationPropertiesDialog.class.getName());
|
||||||
|
@ -37,6 +37,10 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbUtil;
|
|||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamOrganization;
|
import org.sleuthkit.autopsy.centralrepository.datamodel.EamOrganization;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration dialog to manage organizations for the Central Repository.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
public final class ManageOrganizationsDialog extends JDialog {
|
public final class ManageOrganizationsDialog extends JDialog {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
@ -0,0 +1,169 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
|
||||||
|
<Form version="1.6" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JDialogFormInfo">
|
||||||
|
<Properties>
|
||||||
|
<Property name="title" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="ShowCasesDialog.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[545, 415]"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<SyntheticProperties>
|
||||||
|
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
|
||||||
|
<SyntheticProperty name="generateCenter" type="boolean" value="false"/>
|
||||||
|
</SyntheticProperties>
|
||||||
|
<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" attributes="0">
|
||||||
|
<EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
|
||||||
|
<Component id="showCasesPanel" pref="1188" max="32767" attributes="0"/>
|
||||||
|
<EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
<Group type="102" alignment="1" attributes="0">
|
||||||
|
<EmptySpace max="32767" attributes="0"/>
|
||||||
|
<Component id="closeButton" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
</DimensionLayout>
|
||||||
|
<DimensionLayout dim="1">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Group type="102" attributes="0">
|
||||||
|
<EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
|
||||||
|
<Component id="showCasesPanel" pref="473" max="32767" attributes="0"/>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Component id="closeButton" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
</DimensionLayout>
|
||||||
|
</Layout>
|
||||||
|
<SubComponents>
|
||||||
|
<Container class="javax.swing.JPanel" name="showCasesPanel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[527, 407]"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
|
||||||
|
<Layout>
|
||||||
|
<DimensionLayout dim="0">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<EmptySpace min="0" pref="1188" max="32767" attributes="0"/>
|
||||||
|
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
|
||||||
|
<Component id="showCasesScrollPane" alignment="0" pref="527" max="32767" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
</DimensionLayout>
|
||||||
|
<DimensionLayout dim="1">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<EmptySpace min="0" pref="473" max="32767" attributes="0"/>
|
||||||
|
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
|
||||||
|
<Component id="showCasesScrollPane" alignment="0" pref="407" max="32767" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
</DimensionLayout>
|
||||||
|
</Layout>
|
||||||
|
<SubComponents>
|
||||||
|
<Container class="javax.swing.JScrollPane" name="showCasesScrollPane">
|
||||||
|
<Properties>
|
||||||
|
<Property name="verticalScrollBarPolicy" type="int" value="21"/>
|
||||||
|
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[535, 415]"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
|
||||||
|
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||||
|
<SubComponents>
|
||||||
|
<Container class="javax.swing.JPanel" name="outCasesPane">
|
||||||
|
|
||||||
|
<Layout>
|
||||||
|
<DimensionLayout dim="0">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<EmptySpace min="0" pref="1423" max="32767" attributes="0"/>
|
||||||
|
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
|
||||||
|
<Component id="innerCaseScrollPane" alignment="0" pref="1423" max="32767" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
</DimensionLayout>
|
||||||
|
<DimensionLayout dim="1">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<EmptySpace min="0" pref="500" max="32767" attributes="0"/>
|
||||||
|
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
|
||||||
|
<Component id="innerCaseScrollPane" alignment="0" pref="500" max="32767" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
</DimensionLayout>
|
||||||
|
</Layout>
|
||||||
|
<SubComponents>
|
||||||
|
<Container class="javax.swing.JScrollPane" name="innerCaseScrollPane">
|
||||||
|
<Properties>
|
||||||
|
<Property name="horizontalScrollBarPolicy" type="int" value="31"/>
|
||||||
|
</Properties>
|
||||||
|
|
||||||
|
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||||
|
<SubComponents>
|
||||||
|
<Component class="javax.swing.JTable" name="caseDetailsTable">
|
||||||
|
<Properties>
|
||||||
|
<Property name="autoCreateRowSorter" type="boolean" value="true"/>
|
||||||
|
<Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||||
|
<Connection code="tableModel" type="code"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="ShowCasesDialog.caseDetailsTable.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="selectionModel" type="javax.swing.ListSelectionModel" editor="org.netbeans.modules.form.editors2.JTableSelectionModelEditor">
|
||||||
|
<JTableSelectionModel selectionMode="1"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="tableHeader" type="javax.swing.table.JTableHeader" editor="org.netbeans.modules.form.editors2.JTableHeaderEditor">
|
||||||
|
<TableHeader reorderingAllowed="false" resizingAllowed="true"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<AccessibilityProperties>
|
||||||
|
<Property name="AccessibleContext.accessibleDescription" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="ShowCasesDialog.caseDetailsTable.AccessibleContext.accessibleDescription" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</AccessibilityProperties>
|
||||||
|
</Component>
|
||||||
|
</SubComponents>
|
||||||
|
</Container>
|
||||||
|
</SubComponents>
|
||||||
|
</Container>
|
||||||
|
</SubComponents>
|
||||||
|
</Container>
|
||||||
|
</SubComponents>
|
||||||
|
</Container>
|
||||||
|
<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/centralrepository/optionspanel/Bundle.properties" key="ShowCasesDialog.closeButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="actionCommand" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="ShowCasesDialog.closeButton.actionCommand" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<AccessibilityProperties>
|
||||||
|
<Property name="AccessibleContext.accessibleName" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="ShowCasesDialog.closeButton.AccessibleContext.accessibleName" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</AccessibilityProperties>
|
||||||
|
<Events>
|
||||||
|
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="closeButtonActionPerformed"/>
|
||||||
|
</Events>
|
||||||
|
</Component>
|
||||||
|
</SubComponents>
|
||||||
|
</Form>
|
@ -0,0 +1,190 @@
|
|||||||
|
/*
|
||||||
|
* Central Repository
|
||||||
|
*
|
||||||
|
* Copyright 2015-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.centralrepository.optionspanel;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import javax.swing.JDialog;
|
||||||
|
import javax.swing.JFrame;
|
||||||
|
import org.openide.util.NbBundle.Messages;
|
||||||
|
import org.openide.windows.WindowManager;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationCase;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dialog to display table of CorrelationCase information from the CR tab of options.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
|
final class ShowCasesDialog extends JDialog {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private final static Logger logger = Logger.getLogger(ShowCasesDialog.class.getName());
|
||||||
|
|
||||||
|
private final ShowCasesTableModel tableModel;
|
||||||
|
@Messages({"ShowCasesDialog.title_text=All Cases Details"})
|
||||||
|
/**
|
||||||
|
* Creates new form ShowCases Panel
|
||||||
|
*/
|
||||||
|
ShowCasesDialog() {
|
||||||
|
super((JFrame) WindowManager.getDefault().getMainWindow(),
|
||||||
|
Bundle.ShowCasesDialog_title_text(),
|
||||||
|
true);
|
||||||
|
tableModel = new ShowCasesTableModel();
|
||||||
|
initComponents();
|
||||||
|
try {
|
||||||
|
EamDb dbManager = EamDb.getInstance();
|
||||||
|
List<CorrelationCase> eamCases = dbManager.getCases();
|
||||||
|
for(CorrelationCase eamCase : eamCases) {
|
||||||
|
tableModel.addEamCase(eamCase);
|
||||||
|
}
|
||||||
|
} catch (EamDbException ex) {
|
||||||
|
logger.log(Level.SEVERE, "Error getting list of cases from database.", ex); // NON-NLS
|
||||||
|
}
|
||||||
|
display();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void display() {
|
||||||
|
this.setLocationRelativeTo(WindowManager.getDefault().getMainWindow());
|
||||||
|
setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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() {
|
||||||
|
|
||||||
|
showCasesPanel = new javax.swing.JPanel();
|
||||||
|
showCasesScrollPane = new javax.swing.JScrollPane();
|
||||||
|
outCasesPane = new javax.swing.JPanel();
|
||||||
|
innerCaseScrollPane = new javax.swing.JScrollPane();
|
||||||
|
caseDetailsTable = new javax.swing.JTable();
|
||||||
|
closeButton = new javax.swing.JButton();
|
||||||
|
|
||||||
|
setTitle(org.openide.util.NbBundle.getMessage(ShowCasesDialog.class, "ShowCasesDialog.title")); // NOI18N
|
||||||
|
setMinimumSize(new java.awt.Dimension(545, 415));
|
||||||
|
|
||||||
|
showCasesPanel.setPreferredSize(new java.awt.Dimension(527, 407));
|
||||||
|
|
||||||
|
showCasesScrollPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
|
||||||
|
showCasesScrollPane.setPreferredSize(new java.awt.Dimension(535, 415));
|
||||||
|
|
||||||
|
innerCaseScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||||
|
|
||||||
|
caseDetailsTable.setAutoCreateRowSorter(true);
|
||||||
|
caseDetailsTable.setModel(tableModel);
|
||||||
|
caseDetailsTable.setToolTipText(org.openide.util.NbBundle.getMessage(ShowCasesDialog.class, "ShowCasesDialog.caseDetailsTable.toolTipText")); // NOI18N
|
||||||
|
caseDetailsTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_INTERVAL_SELECTION);
|
||||||
|
caseDetailsTable.getTableHeader().setReorderingAllowed(false);
|
||||||
|
innerCaseScrollPane.setViewportView(caseDetailsTable);
|
||||||
|
caseDetailsTable.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(ShowCasesDialog.class, "ShowCasesDialog.caseDetailsTable.AccessibleContext.accessibleDescription")); // NOI18N
|
||||||
|
|
||||||
|
javax.swing.GroupLayout outCasesPaneLayout = new javax.swing.GroupLayout(outCasesPane);
|
||||||
|
outCasesPane.setLayout(outCasesPaneLayout);
|
||||||
|
outCasesPaneLayout.setHorizontalGroup(
|
||||||
|
outCasesPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGap(0, 1423, Short.MAX_VALUE)
|
||||||
|
.addGroup(outCasesPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addComponent(innerCaseScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 1423, Short.MAX_VALUE))
|
||||||
|
);
|
||||||
|
outCasesPaneLayout.setVerticalGroup(
|
||||||
|
outCasesPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGap(0, 500, Short.MAX_VALUE)
|
||||||
|
.addGroup(outCasesPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addComponent(innerCaseScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 500, Short.MAX_VALUE))
|
||||||
|
);
|
||||||
|
|
||||||
|
showCasesScrollPane.setViewportView(outCasesPane);
|
||||||
|
|
||||||
|
javax.swing.GroupLayout showCasesPanelLayout = new javax.swing.GroupLayout(showCasesPanel);
|
||||||
|
showCasesPanel.setLayout(showCasesPanelLayout);
|
||||||
|
showCasesPanelLayout.setHorizontalGroup(
|
||||||
|
showCasesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGap(0, 1188, Short.MAX_VALUE)
|
||||||
|
.addGroup(showCasesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addComponent(showCasesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 527, Short.MAX_VALUE))
|
||||||
|
);
|
||||||
|
showCasesPanelLayout.setVerticalGroup(
|
||||||
|
showCasesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGap(0, 473, Short.MAX_VALUE)
|
||||||
|
.addGroup(showCasesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addComponent(showCasesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 407, Short.MAX_VALUE))
|
||||||
|
);
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(closeButton, org.openide.util.NbBundle.getMessage(ShowCasesDialog.class, "ShowCasesDialog.closeButton.text")); // NOI18N
|
||||||
|
closeButton.setActionCommand(org.openide.util.NbBundle.getMessage(ShowCasesDialog.class, "ShowCasesDialog.closeButton.actionCommand")); // NOI18N
|
||||||
|
closeButton.addActionListener(new java.awt.event.ActionListener() {
|
||||||
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
|
closeButtonActionPerformed(evt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
|
||||||
|
getContentPane().setLayout(layout);
|
||||||
|
layout.setHorizontalGroup(
|
||||||
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGroup(layout.createSequentialGroup()
|
||||||
|
.addGap(6, 6, 6)
|
||||||
|
.addComponent(showCasesPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 1188, Short.MAX_VALUE)
|
||||||
|
.addGap(6, 6, 6))
|
||||||
|
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||||
|
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||||
|
.addComponent(closeButton)
|
||||||
|
.addContainerGap())
|
||||||
|
);
|
||||||
|
layout.setVerticalGroup(
|
||||||
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGroup(layout.createSequentialGroup()
|
||||||
|
.addGap(6, 6, 6)
|
||||||
|
.addComponent(showCasesPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 473, Short.MAX_VALUE)
|
||||||
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
|
.addComponent(closeButton)
|
||||||
|
.addContainerGap())
|
||||||
|
);
|
||||||
|
|
||||||
|
closeButton.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(ShowCasesDialog.class, "ShowCasesDialog.closeButton.AccessibleContext.accessibleName")); // NOI18N
|
||||||
|
|
||||||
|
pack();
|
||||||
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
|
|
||||||
|
private void closeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_closeButtonActionPerformed
|
||||||
|
dispose();
|
||||||
|
}//GEN-LAST:event_closeButtonActionPerformed
|
||||||
|
|
||||||
|
|
||||||
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
|
private javax.swing.JTable caseDetailsTable;
|
||||||
|
private javax.swing.JButton closeButton;
|
||||||
|
private javax.swing.JScrollPane innerCaseScrollPane;
|
||||||
|
private javax.swing.JPanel outCasesPane;
|
||||||
|
private javax.swing.JPanel showCasesPanel;
|
||||||
|
private javax.swing.JScrollPane showCasesScrollPane;
|
||||||
|
// End of variables declaration//GEN-END:variables
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,187 @@
|
|||||||
|
/*
|
||||||
|
* Central Repository
|
||||||
|
*
|
||||||
|
* Copyright 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.centralrepository.optionspanel;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.swing.table.AbstractTableModel;
|
||||||
|
import org.openide.util.NbBundle.Messages;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Model for cells to display correlation case information
|
||||||
|
*/
|
||||||
|
class ShowCasesTableModel extends AbstractTableModel {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Messages({"ShowCasesTableModel.case=Case Name",
|
||||||
|
"ShowCasesTableModel.creationDate=Creation Date",
|
||||||
|
"ShowCasesTableModel.caseNumber=Case Number",
|
||||||
|
"ShowCasesTableModel.examinerName=Examiner Name",
|
||||||
|
"ShowCasesTableModel.examinerEmail=Examiner Email",
|
||||||
|
"ShowCasesTableModel.examinerPhone=Examiner Phone",
|
||||||
|
"ShowCasesTableModel.notes=Notes",
|
||||||
|
"ShowCasesTableModel.noData=No Cases"})
|
||||||
|
/**
|
||||||
|
* Enum which lists columns of interest from CorrelationCase.
|
||||||
|
*/
|
||||||
|
enum TableColumns {
|
||||||
|
// Ordering here determines displayed column order in Content Viewer.
|
||||||
|
// If order is changed, update the CellRenderer to ensure correct row coloring.
|
||||||
|
CASE_NAME(Bundle.ShowCasesTableModel_case(), 200),
|
||||||
|
CREATION_DATE(Bundle.ShowCasesTableModel_creationDate(), 150),
|
||||||
|
CASE_NUMBER(Bundle.ShowCasesTableModel_caseNumber(), 100),
|
||||||
|
EXAMINER_NAME(Bundle.ShowCasesTableModel_examinerName(), 200),
|
||||||
|
EXAMINER_EMAIL(Bundle.ShowCasesTableModel_examinerEmail(), 100),
|
||||||
|
EXAMINER_PHONE(Bundle.ShowCasesTableModel_examinerPhone(), 100),
|
||||||
|
NOTES(Bundle.ShowCasesTableModel_notes(), 450);
|
||||||
|
|
||||||
|
private final String columnName;
|
||||||
|
private final int columnWidth;
|
||||||
|
|
||||||
|
TableColumns(String columnName, int columnWidth) {
|
||||||
|
this.columnName = columnName;
|
||||||
|
this.columnWidth = columnWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
String columnName() {
|
||||||
|
return columnName;
|
||||||
|
}
|
||||||
|
|
||||||
|
int columnWidth() {
|
||||||
|
return columnWidth;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list of Eam Cases from central repository.
|
||||||
|
*/
|
||||||
|
private List<CorrelationCase> eamCases;
|
||||||
|
|
||||||
|
ShowCasesTableModel() {
|
||||||
|
eamCases = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getColumnCount() {
|
||||||
|
return TableColumns.values().length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the preferred width that has been configured for this column.
|
||||||
|
*
|
||||||
|
* A value of 0 means that no preferred width has been defined for this
|
||||||
|
* column.
|
||||||
|
*
|
||||||
|
* @param colIdx Column index
|
||||||
|
*
|
||||||
|
* @return preferred column width >= 0
|
||||||
|
*/
|
||||||
|
int getColumnPreferredWidth(int colIdx) {
|
||||||
|
return TableColumns.values()[colIdx].columnWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRowCount() {
|
||||||
|
return eamCases.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getColumnName(int colIdx) {
|
||||||
|
return TableColumns.values()[colIdx].columnName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getValueAt(int rowIdx, int colIdx) {
|
||||||
|
if (eamCases.isEmpty()) {
|
||||||
|
return Bundle.ShowCasesTableModel_noData();
|
||||||
|
}
|
||||||
|
|
||||||
|
return mapValueById(rowIdx, TableColumns.values()[colIdx]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Object getRow(int rowIdx) {
|
||||||
|
return eamCases.get(rowIdx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map a rowIdx and colId to the value in that cell.
|
||||||
|
*
|
||||||
|
* @param rowIdx Index of row to search
|
||||||
|
* @param colId ID of column to search
|
||||||
|
*
|
||||||
|
* @return value in the cell
|
||||||
|
*/
|
||||||
|
private Object mapValueById(int rowIdx, TableColumns colId) {
|
||||||
|
CorrelationCase eamCase = eamCases.get(rowIdx);
|
||||||
|
String value = Bundle.ShowCasesTableModel_noData();
|
||||||
|
|
||||||
|
switch (colId) {
|
||||||
|
case CASE_NAME:
|
||||||
|
value = eamCase.getDisplayName();
|
||||||
|
break;
|
||||||
|
case CREATION_DATE:
|
||||||
|
value = eamCase.getCreationDate();
|
||||||
|
break;
|
||||||
|
case CASE_NUMBER:
|
||||||
|
value = eamCase.getCaseNumber();
|
||||||
|
break;
|
||||||
|
case EXAMINER_NAME:
|
||||||
|
value = eamCase.getExaminerName();
|
||||||
|
break;
|
||||||
|
case EXAMINER_EMAIL:
|
||||||
|
value = eamCase.getExaminerEmail();
|
||||||
|
break;
|
||||||
|
case EXAMINER_PHONE:
|
||||||
|
value = eamCase.getExaminerPhone();
|
||||||
|
break;
|
||||||
|
case NOTES:
|
||||||
|
value = eamCase.getNotes();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<String> getColumnClass(int colIdx) {
|
||||||
|
return String.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add one local central repository case to the table.
|
||||||
|
*
|
||||||
|
* @param eamCase central repository case to add to the
|
||||||
|
* table
|
||||||
|
*/
|
||||||
|
void addEamCase(CorrelationCase eamCase) {
|
||||||
|
eamCases.add(eamCase);
|
||||||
|
fireTableDataChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearTable() {
|
||||||
|
eamCases.clear();
|
||||||
|
fireTableDataChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -20,13 +20,14 @@
|
|||||||
package org.sleuthkit.autopsy.commonfilesearch;
|
package org.sleuthkit.autopsy.commonfilesearch;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import org.sleuthkit.datamodel.TskData.FileKnown;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides logic for selecting common files from all data sources.
|
* Provides logic for selecting common files from all data sources.
|
||||||
*/
|
*/
|
||||||
final class AllDataSourcesCommonFilesAlgorithm extends CommonFilesMetadataBuilder {
|
final public class AllDataSourcesCommonFilesAlgorithm extends CommonFilesMetadataBuilder {
|
||||||
|
|
||||||
private static final String WHERE_CLAUSE = "%s md5 in (select md5 from tsk_files where (known != 1 OR known IS NULL)%s GROUP BY md5 HAVING COUNT(*) > 1) order by md5"; //NON-NLS
|
private static final String WHERE_CLAUSE = "%s md5 in (select md5 from tsk_files where (known != "+ FileKnown.KNOWN.getFileKnownValue() + " OR known IS NULL)%s GROUP BY md5 HAVING COUNT(DISTINCT data_source_obj_id) > 1) order by md5"; //NON-NLS
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements the algorithm for getting common files across all data
|
* Implements the algorithm for getting common files across all data
|
||||||
@ -36,7 +37,7 @@ final class AllDataSourcesCommonFilesAlgorithm extends CommonFilesMetadataBuilde
|
|||||||
* @param filterByMediaMimeType match only on files whose mime types can be broadly categorized as media types
|
* @param filterByMediaMimeType match only on files whose mime types can be broadly categorized as media types
|
||||||
* @param filterByDocMimeType match only on files whose mime types can be broadly categorized as document types
|
* @param filterByDocMimeType match only on files whose mime types can be broadly categorized as document types
|
||||||
*/
|
*/
|
||||||
AllDataSourcesCommonFilesAlgorithm(Map<Long, String> dataSourceIdMap, boolean filterByMediaMimeType, boolean filterByDocMimeType) {
|
public AllDataSourcesCommonFilesAlgorithm(Map<Long, String> dataSourceIdMap, boolean filterByMediaMimeType, boolean filterByDocMimeType) {
|
||||||
super(dataSourceIdMap, filterByMediaMimeType, filterByDocMimeType);
|
super(dataSourceIdMap, filterByMediaMimeType, filterByDocMimeType);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ CommonFilesPanel.selectedFileCategoriesButton.text=Match on the following file c
|
|||||||
CommonFilesPanel.selectedFileCategoriesButton.toolTipText=Select from the options below...
|
CommonFilesPanel.selectedFileCategoriesButton.toolTipText=Select from the options below...
|
||||||
CommonFilesPanel.pictureVideoCheckbox.text=Pictures and Videos
|
CommonFilesPanel.pictureVideoCheckbox.text=Pictures and Videos
|
||||||
CommonFilesPanel.documentsCheckbox.text=Documents
|
CommonFilesPanel.documentsCheckbox.text=Documents
|
||||||
CommonFilesPanel.commonFilesSearchLabel.text=<html>Find duplicate files in the current case.</html>
|
CommonFilesPanel.commonFilesSearchLabel.text=<html>Find files in multiple data sources in the current case.</html>
|
||||||
CommonFilesPanel.allFileCategoriesRadioButton.toolTipText=No filtering applied to results...
|
CommonFilesPanel.allFileCategoriesRadioButton.toolTipText=No filtering applied to results...
|
||||||
CommonFilesPanel.allFileCategoriesRadioButton.text=Match on all file types
|
CommonFilesPanel.allFileCategoriesRadioButton.text=Match on all file types
|
||||||
CommonFilesPanel.text=Indicate which data sources to consider while searching for duplicates:
|
CommonFilesPanel.text=Indicate which data sources to consider while searching for duplicates:
|
||||||
|
@ -20,22 +20,24 @@
|
|||||||
package org.sleuthkit.autopsy.commonfilesearch;
|
package org.sleuthkit.autopsy.commonfilesearch;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility and wrapper model around data required for Common Files Search results.
|
* Utility and wrapper model around data required for Common Files Search results.
|
||||||
* Subclass this to implement different selections of files from the case.
|
* Subclass this to implement different selections of files from the case.
|
||||||
*/
|
*/
|
||||||
final class CommonFilesMetadata {
|
final public class CommonFilesMetadata {
|
||||||
|
|
||||||
private final Map<String, Md5Metadata> metadata;
|
private final Map<Integer, List<Md5Metadata>> metadata;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create meta dat object which can be handed off to the node factories
|
* Create a metadata object which can be handed off to the node
|
||||||
|
* factories.
|
||||||
*
|
*
|
||||||
* @param metadata map of md5 to parent-level node meta data
|
* @param metadata list of Md5Metadata indexed by size of Md5Metadata
|
||||||
*/
|
*/
|
||||||
CommonFilesMetadata(Map<String, Md5Metadata> metadata) {
|
CommonFilesMetadata(Map<Integer, List<Md5Metadata>> metadata){
|
||||||
this.metadata = metadata;
|
this.metadata = metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,11 +50,11 @@ final class CommonFilesMetadata {
|
|||||||
* @param md5 key
|
* @param md5 key
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
Md5Metadata getMetadataForMd5(String md5) {
|
List<Md5Metadata> getMetadataForMd5(Integer instanceCount) {
|
||||||
return this.metadata.get(md5);
|
return this.metadata.get(instanceCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, Md5Metadata> getMetadata() {
|
public Map<Integer, List<Md5Metadata>> getMetadata() {
|
||||||
return Collections.unmodifiableMap(this.metadata);
|
return Collections.unmodifiableMap(this.metadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,10 +62,13 @@ final class CommonFilesMetadata {
|
|||||||
* How many distinct file instances exist for this metadata?
|
* How many distinct file instances exist for this metadata?
|
||||||
* @return number of file instances
|
* @return number of file instances
|
||||||
*/
|
*/
|
||||||
int size() {
|
public int size() {
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (Md5Metadata data : this.metadata.values()) {
|
for (List<Md5Metadata> data : this.metadata.values()) {
|
||||||
count += data.size();
|
for(Md5Metadata md5 : data){
|
||||||
|
count += md5.size();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ import java.util.HashSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.TreeMap;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
@ -46,12 +47,12 @@ import org.sleuthkit.datamodel.TskCoreException;
|
|||||||
* This entire thing runs on a background thread where exceptions are handled.
|
* This entire thing runs on a background thread where exceptions are handled.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("PMD.AbstractNaming")
|
@SuppressWarnings("PMD.AbstractNaming")
|
||||||
abstract class CommonFilesMetadataBuilder {
|
public abstract class CommonFilesMetadataBuilder {
|
||||||
|
|
||||||
private final Map<Long, String> dataSourceIdToNameMap;
|
private final Map<Long, String> dataSourceIdToNameMap;
|
||||||
private final boolean filterByMedia;
|
private final boolean filterByMedia;
|
||||||
private final boolean filterByDoc;
|
private final boolean filterByDoc;
|
||||||
private static final String filterByMimeTypesWhereClause = " and mime_type in (%s)"; //NON-NLS // where %s is csv list of mime_types to filter on
|
private static final String FILTER_BY_MIME_TYPES_WHERE_CLAUSE = " and mime_type in (%s)"; //NON-NLS // where %s is csv list of mime_types to filter on
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The set of the MIME types that will be checked for extension mismatches
|
* The set of the MIME types that will be checked for extension mismatches
|
||||||
@ -199,7 +200,21 @@ abstract class CommonFilesMetadataBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new CommonFilesMetadata(commonFiles);
|
Map<Integer, List<Md5Metadata>> instanceCollatedCommonFiles = new TreeMap<>();
|
||||||
|
|
||||||
|
for(Md5Metadata md5Metadata : commonFiles.values()){
|
||||||
|
Integer size = md5Metadata.size();
|
||||||
|
|
||||||
|
if(instanceCollatedCommonFiles.containsKey(size)){
|
||||||
|
instanceCollatedCommonFiles.get(size).add(md5Metadata);
|
||||||
|
} else {
|
||||||
|
ArrayList<Md5Metadata> value = new ArrayList<>();
|
||||||
|
value.add(md5Metadata);
|
||||||
|
instanceCollatedCommonFiles.put(size, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CommonFilesMetadata(instanceCollatedCommonFiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -228,7 +243,7 @@ abstract class CommonFilesMetadataBuilder {
|
|||||||
mimeTypeFilter.append("'").append(mimeType).append("',");
|
mimeTypeFilter.append("'").append(mimeType).append("',");
|
||||||
}
|
}
|
||||||
mimeTypeString = mimeTypeFilter.toString().substring(0, mimeTypeFilter.length() - 1);
|
mimeTypeString = mimeTypeFilter.toString().substring(0, mimeTypeFilter.length() - 1);
|
||||||
mimeTypeString = String.format(filterByMimeTypesWhereClause, new Object[]{mimeTypeString});
|
mimeTypeString = String.format(FILTER_BY_MIME_TYPES_WHERE_CLAUSE, new Object[]{mimeTypeString});
|
||||||
}
|
}
|
||||||
return mimeTypeString;
|
return mimeTypeString;
|
||||||
}
|
}
|
||||||
|
@ -23,20 +23,18 @@ import org.openide.nodes.ChildFactory;
|
|||||||
import org.openide.nodes.Children;
|
import org.openide.nodes.Children;
|
||||||
import org.openide.nodes.Node;
|
import org.openide.nodes.Node;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.openide.util.lookup.Lookups;
|
|
||||||
import org.sleuthkit.autopsy.datamodel.Md5Node;
|
|
||||||
import org.sleuthkit.autopsy.datamodel.DisplayableItemNode;
|
import org.sleuthkit.autopsy.datamodel.DisplayableItemNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor;
|
import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper node for <code>Md5Node</code> used to display common files search
|
* Wrapper node for <code>Md5Node</code> used to display common files search
|
||||||
* results in the top right pane. Calls <code>Md5NodeFactory</code>.
|
* results in the top right pane. Calls <code>InstanceCountNodeFactory</code>.
|
||||||
*/
|
*/
|
||||||
final public class CommonFilesNode extends DisplayableItemNode {
|
final public class CommonFilesNode extends DisplayableItemNode {
|
||||||
|
|
||||||
|
|
||||||
CommonFilesNode(CommonFilesMetadata metadataList) {
|
CommonFilesNode(CommonFilesMetadata metadataList) {
|
||||||
super(Children.create(new Md5NodeFactory(metadataList), true), Lookups.singleton(CommonFilesNode.class));
|
super(Children.create(new InstanceCountNodeFactory(metadataList), true));
|
||||||
}
|
}
|
||||||
|
|
||||||
@NbBundle.Messages({
|
@NbBundle.Messages({
|
||||||
@ -62,35 +60,31 @@ final public class CommonFilesNode extends DisplayableItemNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ChildFactory which builds CommonFileParentNodes from the
|
* Used to generate <code>InstanceCountNode</code>s.
|
||||||
* CommonFilesMetaaData models.
|
|
||||||
*/
|
*/
|
||||||
static class Md5NodeFactory extends ChildFactory<String> {
|
static class InstanceCountNodeFactory extends ChildFactory<Integer>{
|
||||||
|
|
||||||
|
private final CommonFilesMetadata metadata;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of models, each of which is a parent node matching a single md5,
|
* Build a factory which converts a <code>CommonFilesMetadata</code>
|
||||||
* containing children FileNodes.
|
* object into <code>DisplayableItemNode</code>s.
|
||||||
|
* @param metadata
|
||||||
*/
|
*/
|
||||||
private CommonFilesMetadata metadata;
|
InstanceCountNodeFactory(CommonFilesMetadata metadata){
|
||||||
|
|
||||||
Md5NodeFactory(CommonFilesMetadata metadata) {
|
|
||||||
this.metadata = metadata;
|
this.metadata = metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void removeNotify() {
|
|
||||||
metadata = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Node createNodeForKey(String md5){
|
protected boolean createKeys(List<Integer> list) {
|
||||||
Md5Metadata metadata = this.metadata.getMetadataForMd5(md5);
|
|
||||||
return new Md5Node(metadata);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean createKeys(List<String> list) {
|
|
||||||
list.addAll(this.metadata.getMetadata().keySet());
|
list.addAll(this.metadata.getMetadata().keySet());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Node createNodeForKey(Integer instanceCount){
|
||||||
|
List<Md5Metadata> md5Metadata = this.metadata.getMetadataForMd5(instanceCount);
|
||||||
|
return new InstanceCountNode(instanceCount, md5Metadata);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,12 +18,9 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.commonfilesearch;
|
package org.sleuthkit.autopsy.commonfilesearch;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.sql.ResultSet;
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
@ -31,10 +28,11 @@ import java.util.logging.Level;
|
|||||||
import javax.swing.ComboBoxModel;
|
import javax.swing.ComboBoxModel;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.SwingWorker;
|
import javax.swing.SwingWorker;
|
||||||
|
import org.netbeans.api.progress.ProgressHandle;
|
||||||
import org.openide.explorer.ExplorerManager;
|
import org.openide.explorer.ExplorerManager;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
|
||||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
|
||||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer;
|
import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer;
|
||||||
import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent;
|
import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent;
|
||||||
import org.sleuthkit.autopsy.corecomponents.DataResultViewerTable;
|
import org.sleuthkit.autopsy.corecomponents.DataResultViewerTable;
|
||||||
@ -42,8 +40,6 @@ import org.sleuthkit.autopsy.corecomponents.TableFilterNode;
|
|||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||||
import org.sleuthkit.autopsy.directorytree.DataResultFilterNode;
|
import org.sleuthkit.autopsy.directorytree.DataResultFilterNode;
|
||||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
|
||||||
import org.sleuthkit.datamodel.SleuthkitCase.CaseDbQuery;
|
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -97,10 +93,6 @@ public final class CommonFilesPanel extends javax.swing.JPanel {
|
|||||||
|
|
||||||
new SwingWorker<Map<Long, String>, Void>() {
|
new SwingWorker<Map<Long, String>, Void>() {
|
||||||
|
|
||||||
private static final String SELECT_DATA_SOURCES_LOGICAL = "select obj_id, name from tsk_files where obj_id in (SELECT obj_id FROM tsk_objects WHERE obj_id in (select obj_id from data_source_info))";
|
|
||||||
|
|
||||||
private static final String SELECT_DATA_SOURCES_IMAGE = "select obj_id, name from tsk_image_names where obj_id in (SELECT obj_id FROM tsk_objects WHERE obj_id in (select obj_id from data_source_info))";
|
|
||||||
|
|
||||||
private void updateUi() {
|
private void updateUi() {
|
||||||
|
|
||||||
String[] dataSourcesNames = new String[CommonFilesPanel.this.dataSourceMap.size()];
|
String[] dataSourcesNames = new String[CommonFilesPanel.this.dataSourceMap.size()];
|
||||||
@ -112,12 +104,15 @@ public final class CommonFilesPanel extends javax.swing.JPanel {
|
|||||||
CommonFilesPanel.this.selectDataSourceComboBox.setModel(CommonFilesPanel.this.dataSourcesList);
|
CommonFilesPanel.this.selectDataSourceComboBox.setModel(CommonFilesPanel.this.dataSourcesList);
|
||||||
|
|
||||||
boolean multipleDataSources = this.caseHasMultipleSources();
|
boolean multipleDataSources = this.caseHasMultipleSources();
|
||||||
CommonFilesPanel.this.allDataSourcesRadioButton.setEnabled(multipleDataSources);
|
|
||||||
CommonFilesPanel.this.allDataSourcesRadioButton.setSelected(multipleDataSources);
|
CommonFilesPanel.this.allDataSourcesRadioButton.setEnabled(true);
|
||||||
|
CommonFilesPanel.this.allDataSourcesRadioButton.setSelected(true);
|
||||||
|
|
||||||
if (!multipleDataSources) {
|
if (!multipleDataSources) {
|
||||||
CommonFilesPanel.this.withinDataSourceRadioButton.setSelected(true);
|
CommonFilesPanel.this.withinDataSourceRadioButton.setEnabled(false);
|
||||||
withinDataSourceSelected(true);
|
CommonFilesPanel.this.withinDataSourceRadioButton.setSelected(false);
|
||||||
|
withinDataSourceSelected(false);
|
||||||
|
CommonFilesPanel.this.selectDataSourceComboBox.setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
CommonFilesPanel.this.searchButton.setEnabled(true);
|
CommonFilesPanel.this.searchButton.setEnabled(true);
|
||||||
@ -128,51 +123,13 @@ public final class CommonFilesPanel extends javax.swing.JPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean caseHasMultipleSources() {
|
private boolean caseHasMultipleSources() {
|
||||||
return CommonFilesPanel.this.dataSourceMap.size() >= 2;
|
return CommonFilesPanel.this.dataSourceMap.size() >= 3;
|
||||||
}
|
|
||||||
|
|
||||||
private void loadLogicalSources(SleuthkitCase tskDb, Map<Long, String> dataSouceMap) throws TskCoreException, SQLException {
|
|
||||||
//try block releases resources - exceptions are handled in done()
|
|
||||||
try (
|
|
||||||
CaseDbQuery query = tskDb.executeQuery(SELECT_DATA_SOURCES_LOGICAL);
|
|
||||||
ResultSet resultSet = query.getResultSet()) {
|
|
||||||
while (resultSet.next()) {
|
|
||||||
Long objectId = resultSet.getLong(1);
|
|
||||||
String dataSourceName = resultSet.getString(2);
|
|
||||||
dataSouceMap.put(objectId, dataSourceName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadImageSources(SleuthkitCase tskDb, Map<Long, String> dataSouceMap) throws SQLException, TskCoreException {
|
|
||||||
//try block releases resources - exceptions are handled in done()
|
|
||||||
try (
|
|
||||||
CaseDbQuery query = tskDb.executeQuery(SELECT_DATA_SOURCES_IMAGE);
|
|
||||||
ResultSet resultSet = query.getResultSet()) {
|
|
||||||
|
|
||||||
while (resultSet.next()) {
|
|
||||||
Long objectId = resultSet.getLong(1);
|
|
||||||
String dataSourceName = resultSet.getString(2);
|
|
||||||
File image = new File(dataSourceName);
|
|
||||||
String dataSourceNameTrimmed = image.getName();
|
|
||||||
dataSouceMap.put(objectId, dataSourceNameTrimmed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Map<Long, String> doInBackground() throws NoCurrentCaseException, TskCoreException, SQLException {
|
protected Map<Long, String> doInBackground() throws NoCurrentCaseException, TskCoreException, SQLException {
|
||||||
|
DataSourceLoader loader = new DataSourceLoader();
|
||||||
Map<Long, String> dataSouceMap = new HashMap<>();
|
return loader.getDataSourceMap();
|
||||||
|
|
||||||
Case currentCase = Case.getCurrentCaseThrows();
|
|
||||||
SleuthkitCase tskDb = currentCase.getSleuthkitCase();
|
|
||||||
|
|
||||||
loadLogicalSources(tskDb, dataSouceMap);
|
|
||||||
|
|
||||||
loadImageSources(tskDb, dataSouceMap);
|
|
||||||
|
|
||||||
return dataSouceMap;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -212,6 +169,8 @@ public final class CommonFilesPanel extends javax.swing.JPanel {
|
|||||||
"CommonFilesPanel.search.results.titleAll=Common Files (All Data Sources)",
|
"CommonFilesPanel.search.results.titleAll=Common Files (All Data Sources)",
|
||||||
"CommonFilesPanel.search.results.titleSingle=Common Files (Match Within Data Source: %s)",
|
"CommonFilesPanel.search.results.titleSingle=Common Files (Match Within Data Source: %s)",
|
||||||
"CommonFilesPanel.search.results.pathText=Common Files Search Results",
|
"CommonFilesPanel.search.results.pathText=Common Files Search Results",
|
||||||
|
"CommonFilesPanel.search.done.searchProgressGathering=Gathering Common Files Search Results.",
|
||||||
|
"CommonFilesPanel.search.done.searchProgressDisplay=Displaying Common Files Search Results.",
|
||||||
"CommonFilesPanel.search.done.tskCoreException=Unable to run query against DB.",
|
"CommonFilesPanel.search.done.tskCoreException=Unable to run query against DB.",
|
||||||
"CommonFilesPanel.search.done.noCurrentCaseException=Unable to open case file.",
|
"CommonFilesPanel.search.done.noCurrentCaseException=Unable to open case file.",
|
||||||
"CommonFilesPanel.search.done.exception=Unexpected exception running Common Files Search.",
|
"CommonFilesPanel.search.done.exception=Unexpected exception running Common Files Search.",
|
||||||
@ -223,6 +182,7 @@ public final class CommonFilesPanel extends javax.swing.JPanel {
|
|||||||
new SwingWorker<CommonFilesMetadata, Void>() {
|
new SwingWorker<CommonFilesMetadata, Void>() {
|
||||||
|
|
||||||
private String tabTitle;
|
private String tabTitle;
|
||||||
|
private ProgressHandle progress;
|
||||||
|
|
||||||
private void setTitleForAllDataSources() {
|
private void setTitleForAllDataSources() {
|
||||||
this.tabTitle = Bundle.CommonFilesPanel_search_results_titleAll();
|
this.tabTitle = Bundle.CommonFilesPanel_search_results_titleAll();
|
||||||
@ -250,7 +210,11 @@ public final class CommonFilesPanel extends javax.swing.JPanel {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings({"BoxedValueEquality", "NumberEquality"})
|
@SuppressWarnings({"BoxedValueEquality", "NumberEquality"})
|
||||||
protected CommonFilesMetadata doInBackground() throws TskCoreException, NoCurrentCaseException, SQLException {
|
protected CommonFilesMetadata doInBackground() throws TskCoreException, NoCurrentCaseException, SQLException, EamDbException {
|
||||||
|
progress = ProgressHandle.createHandle(Bundle.CommonFilesPanel_search_done_searchProgressGathering());
|
||||||
|
progress.start();
|
||||||
|
progress.switchToIndeterminate();
|
||||||
|
|
||||||
Long dataSourceId = determineDataSourceId();
|
Long dataSourceId = determineDataSourceId();
|
||||||
|
|
||||||
CommonFilesMetadataBuilder builder;
|
CommonFilesMetadataBuilder builder;
|
||||||
@ -285,22 +249,21 @@ public final class CommonFilesPanel extends javax.swing.JPanel {
|
|||||||
protected void done() {
|
protected void done() {
|
||||||
try {
|
try {
|
||||||
super.done();
|
super.done();
|
||||||
|
|
||||||
CommonFilesMetadata metadata = get();
|
CommonFilesMetadata metadata = get();
|
||||||
|
|
||||||
CommonFilesNode commonFilesNode = new CommonFilesNode(metadata);
|
CommonFilesNode commonFilesNode = new CommonFilesNode(metadata);
|
||||||
|
|
||||||
|
//TODO this could be enumerating the children!!!
|
||||||
DataResultFilterNode dataResultFilterNode = new DataResultFilterNode(commonFilesNode, ExplorerManager.find(CommonFilesPanel.this));
|
DataResultFilterNode dataResultFilterNode = new DataResultFilterNode(commonFilesNode, ExplorerManager.find(CommonFilesPanel.this));
|
||||||
|
|
||||||
TableFilterNode tableFilterWithDescendantsNode = new TableFilterNode(dataResultFilterNode);
|
TableFilterNode tableFilterWithDescendantsNode = new TableFilterNode(dataResultFilterNode, 3);
|
||||||
|
|
||||||
DataResultViewerTable table = new DataResultViewerTable();
|
DataResultViewerTable table = new CommonFilesSearchResultsViewerTable();
|
||||||
|
|
||||||
Collection<DataResultViewer> viewers = new ArrayList<>(1);
|
Collection<DataResultViewer> viewers = new ArrayList<>(1);
|
||||||
viewers.add(table);
|
viewers.add(table);
|
||||||
|
progress.setDisplayName(Bundle.CommonFilesPanel_search_done_searchProgressDisplay());
|
||||||
DataResultTopComponent.createInstance(tabTitle, pathText, tableFilterWithDescendantsNode, metadata.size(), viewers);
|
DataResultTopComponent.createInstance(tabTitle, pathText, tableFilterWithDescendantsNode, metadata.size(), viewers);
|
||||||
|
|
||||||
} catch (InterruptedException ex) {
|
} catch (InterruptedException ex) {
|
||||||
LOGGER.log(Level.SEVERE, "Interrupted while loading Common Files", ex);
|
LOGGER.log(Level.SEVERE, "Interrupted while loading Common Files", ex);
|
||||||
MessageNotifyUtil.Message.error(Bundle.CommonFilesPanel_search_done_interupted());
|
MessageNotifyUtil.Message.error(Bundle.CommonFilesPanel_search_done_interupted());
|
||||||
@ -321,6 +284,8 @@ public final class CommonFilesPanel extends javax.swing.JPanel {
|
|||||||
errorMessage = Bundle.CommonFilesPanel_search_done_exception();
|
errorMessage = Bundle.CommonFilesPanel_search_done_exception();
|
||||||
}
|
}
|
||||||
MessageNotifyUtil.Message.error(errorMessage);
|
MessageNotifyUtil.Message.error(errorMessage);
|
||||||
|
} finally {
|
||||||
|
progress.finish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.execute();
|
}.execute();
|
||||||
|
@ -19,11 +19,13 @@
|
|||||||
package org.sleuthkit.autopsy.commonfilesearch;
|
package org.sleuthkit.autopsy.commonfilesearch;
|
||||||
|
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.util.logging.Level;
|
||||||
import org.openide.util.HelpCtx;
|
import org.openide.util.HelpCtx;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.openide.util.actions.CallableSystemAction;
|
import org.openide.util.actions.CallableSystemAction;
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.core.Installer;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encapsulates a menu action which triggers the common files search dialog.
|
* Encapsulates a menu action which triggers the common files search dialog.
|
||||||
@ -32,6 +34,7 @@ final public class CommonFilesSearchAction extends CallableSystemAction {
|
|||||||
|
|
||||||
private static CommonFilesSearchAction instance = null;
|
private static CommonFilesSearchAction instance = null;
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
private static final Logger logger = Logger.getLogger(CommonFilesSearchAction.class.getName());
|
||||||
|
|
||||||
CommonFilesSearchAction() {
|
CommonFilesSearchAction() {
|
||||||
super();
|
super();
|
||||||
@ -40,7 +43,13 @@ final public class CommonFilesSearchAction extends CallableSystemAction {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isEnabled(){
|
public boolean isEnabled(){
|
||||||
return super.isEnabled() && Case.isCaseOpen() && Installer.isJavaFxInited();
|
boolean shouldBeEnabled = false;
|
||||||
|
try {
|
||||||
|
shouldBeEnabled = Case.isCaseOpen() && Case.getCurrentCase().getDataSources().size() > 1;
|
||||||
|
} catch(TskCoreException ex) {
|
||||||
|
logger.log(Level.SEVERE, "Error getting data sources for action enabled check", ex);
|
||||||
|
}
|
||||||
|
return super.isEnabled() && shouldBeEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static synchronized CommonFilesSearchAction getDefault() {
|
public static synchronized CommonFilesSearchAction getDefault() {
|
||||||
|
@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 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.commonfilesearch;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import javax.swing.table.TableColumn;
|
||||||
|
import javax.swing.table.TableColumnModel;
|
||||||
|
import org.openide.util.NbBundle;
|
||||||
|
import org.sleuthkit.autopsy.corecomponents.DataResultViewerTable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <code>DataResultViewerTable</code> which overrides the default column header
|
||||||
|
* width calculations. The <code>CommonFilesSearchResultsViewerTable</code>
|
||||||
|
* presents multiple tiers of data which are not always present and it may not
|
||||||
|
* make sense to try to calculate the column widths for such tables by sampling
|
||||||
|
* rows and looking for wide cells. Rather, we just pick some reasonable values.
|
||||||
|
*/
|
||||||
|
public class CommonFilesSearchResultsViewerTable extends DataResultViewerTable {
|
||||||
|
|
||||||
|
private static final Map<String, Integer> COLUMN_WIDTHS;
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(CommonFilesSearchResultsViewerTable.class.getName());
|
||||||
|
|
||||||
|
private static final int DEFAULT_WIDTH = 100;
|
||||||
|
|
||||||
|
static {
|
||||||
|
Map<String, Integer> map = new HashMap<>();
|
||||||
|
map.put(Bundle.CommonFilesSearchResultsViewerTable_filesColLbl(), 260);
|
||||||
|
map.put(Bundle.CommonFilesSearchResultsViewerTable_instancesColLbl(), 65);
|
||||||
|
map.put(Bundle.CommonFilesSearchResultsViewerTable_pathColLbl(), 300);
|
||||||
|
map.put(Bundle.CommonFilesSearchResultsViewerTable_dataSourceColLbl(), 200);
|
||||||
|
map.put(Bundle.CommonFilesSearchResultsViewerTable_hashsetHitsColLbl(), 100);
|
||||||
|
map.put(Bundle.CommonFilesSearchResultsViewerTable_mimeTypeColLbl(), 130);
|
||||||
|
map.put(Bundle.CommonFilesSearchResultsViewerTable_tagsColLbl1(), 300);
|
||||||
|
|
||||||
|
COLUMN_WIDTHS = Collections.unmodifiableMap(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NbBundle.Messages({
|
||||||
|
"CommonFilesSearchResultsViewerTable.filesColLbl=Files",
|
||||||
|
"CommonFilesSearchResultsViewerTable.instancesColLbl=Instances",
|
||||||
|
"CommonFilesSearchResultsViewerTable.pathColLbl=Parent Path",
|
||||||
|
"CommonFilesSearchResultsViewerTable.hashsetHitsColLbl=Hash Set Hits",
|
||||||
|
"CommonFilesSearchResultsViewerTable.dataSourceColLbl=Data Source(s)",
|
||||||
|
"CommonFilesSearchResultsViewerTable.mimeTypeColLbl=MIME Type",
|
||||||
|
"CommonFilesSearchResultsViewerTable.tagsColLbl1=Tags"
|
||||||
|
})
|
||||||
|
@Override
|
||||||
|
protected void setColumnWidths() {
|
||||||
|
TableColumnModel model = this.getColumnModel();
|
||||||
|
|
||||||
|
Enumeration<TableColumn> columnsEnumerator = model.getColumns();
|
||||||
|
while (columnsEnumerator.hasMoreElements()) {
|
||||||
|
|
||||||
|
TableColumn column = columnsEnumerator.nextElement();
|
||||||
|
|
||||||
|
final String headerValue = column.getHeaderValue().toString();
|
||||||
|
|
||||||
|
final Integer defaultWidth = COLUMN_WIDTHS.get(headerValue);
|
||||||
|
|
||||||
|
if(defaultWidth == null){
|
||||||
|
column.setPreferredWidth(DEFAULT_WIDTH);
|
||||||
|
LOGGER.log(Level.SEVERE, String.format("Tried to set width on a column not supported by the CommonFilesSearchResultsViewerTable: %s", headerValue));
|
||||||
|
} else {
|
||||||
|
column.setPreferredWidth(defaultWidth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 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.commonfilesearch;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||||
|
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||||
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encapsulates logic required to create a mapping of data sources in the
|
||||||
|
* current case to their data source IDs.
|
||||||
|
*
|
||||||
|
* Intended to be used within the context of a SwingWorker or other background
|
||||||
|
* thread.
|
||||||
|
*/
|
||||||
|
public class DataSourceLoader {
|
||||||
|
|
||||||
|
private static final String SELECT_DATA_SOURCES_LOGICAL = "select obj_id, name from tsk_files where obj_id in (SELECT obj_id FROM tsk_objects WHERE obj_id in (select obj_id from data_source_info))";
|
||||||
|
|
||||||
|
private static final String SELECT_DATA_SOURCES_IMAGE = "select obj_id, name from tsk_image_names where obj_id in (SELECT obj_id FROM tsk_objects WHERE obj_id in (select obj_id from data_source_info))";
|
||||||
|
|
||||||
|
private void loadLogicalSources(SleuthkitCase tskDb, Map<Long, String> dataSouceMap) throws TskCoreException, SQLException {
|
||||||
|
//try block releases resources - exceptions are handled in done()
|
||||||
|
try (
|
||||||
|
SleuthkitCase.CaseDbQuery query = tskDb.executeQuery(SELECT_DATA_SOURCES_LOGICAL);
|
||||||
|
ResultSet resultSet = query.getResultSet()
|
||||||
|
) {
|
||||||
|
while (resultSet.next()) {
|
||||||
|
Long objectId = resultSet.getLong(1);
|
||||||
|
String dataSourceName = resultSet.getString(2);
|
||||||
|
dataSouceMap.put(objectId, dataSourceName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadImageSources(SleuthkitCase tskDb, Map<Long, String> dataSouceMap) throws SQLException, TskCoreException {
|
||||||
|
//try block releases resources - exceptions are handled in done()
|
||||||
|
try (
|
||||||
|
SleuthkitCase.CaseDbQuery query = tskDb.executeQuery(SELECT_DATA_SOURCES_IMAGE);
|
||||||
|
ResultSet resultSet = query.getResultSet()) {
|
||||||
|
|
||||||
|
while (resultSet.next()) {
|
||||||
|
Long objectId = resultSet.getLong(1);
|
||||||
|
String dataSourceName = resultSet.getString(2);
|
||||||
|
File image = new File(dataSourceName);
|
||||||
|
String dataSourceNameTrimmed = image.getName();
|
||||||
|
dataSouceMap.put(objectId, dataSourceNameTrimmed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a map of data source Ids to their string names for the current case.
|
||||||
|
*
|
||||||
|
* @return Map of Long (id) to String (name)
|
||||||
|
* @throws NoCurrentCaseException
|
||||||
|
* @throws TskCoreException
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
public Map<Long, String> getDataSourceMap() throws NoCurrentCaseException, TskCoreException, SQLException {
|
||||||
|
Map<Long, String> dataSouceMap = new HashMap<>();
|
||||||
|
|
||||||
|
Case currentCase = Case.getCurrentCaseThrows();
|
||||||
|
SleuthkitCase tskDb = currentCase.getSleuthkitCase();
|
||||||
|
|
||||||
|
loadLogicalSources(tskDb, dataSouceMap);
|
||||||
|
|
||||||
|
loadImageSources(tskDb, dataSouceMap);
|
||||||
|
|
||||||
|
return dataSouceMap;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 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.commonfilesearch;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.openide.nodes.Sheet;
|
||||||
|
import org.openide.util.NbBundle;
|
||||||
|
import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor;
|
||||||
|
import org.sleuthkit.autopsy.datamodel.FileNode;
|
||||||
|
import org.sleuthkit.autopsy.datamodel.NodeProperty;
|
||||||
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used by the Common Files search feature to encapsulate instances of a given
|
||||||
|
MD5s matched in the search. These nodes will be children of <code>Md5Node</code>s.
|
||||||
|
*/
|
||||||
|
public class FileInstanceNode extends FileNode {
|
||||||
|
|
||||||
|
private final String dataSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a node which can be used in a multilayer tree table and is based
|
||||||
|
* on an <code>AbstractFile</code>.
|
||||||
|
*
|
||||||
|
* @param fsContent
|
||||||
|
* @param dataSource
|
||||||
|
*/
|
||||||
|
public FileInstanceNode(AbstractFile fsContent, String dataSource) {
|
||||||
|
super(fsContent);
|
||||||
|
this.dataSource = dataSource;
|
||||||
|
|
||||||
|
this.setDisplayName(fsContent.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLeafTypeNode(){
|
||||||
|
//Not used atm - could maybe be leveraged for better use in Children objects
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
|
||||||
|
return visitor.visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
String getDataSource() {
|
||||||
|
return this.dataSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NbBundle.Messages({"FileInstanceNode.createSheet.noDescription= "})
|
||||||
|
@Override
|
||||||
|
protected Sheet createSheet() {
|
||||||
|
Sheet sheet = new Sheet();
|
||||||
|
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
|
||||||
|
if (sheetSet == null) {
|
||||||
|
sheetSet = Sheet.createPropertiesSet();
|
||||||
|
sheet.put(sheetSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
final String NO_DESCR = Bundle.FileInstanceNode_createSheet_noDescription();
|
||||||
|
|
||||||
|
sheetSet.put(new NodeProperty<>(Bundle.CommonFilesSearchResultsViewerTable_filesColLbl(), Bundle.CommonFilesSearchResultsViewerTable_filesColLbl(), NO_DESCR, this.getContent().getName()));
|
||||||
|
sheetSet.put(new NodeProperty<>(Bundle.CommonFilesSearchResultsViewerTable_pathColLbl(), Bundle.CommonFilesSearchResultsViewerTable_pathColLbl(), NO_DESCR, this.getContent().getParentPath()));
|
||||||
|
sheetSet.put(new NodeProperty<>(Bundle.CommonFilesSearchResultsViewerTable_hashsetHitsColLbl(), Bundle.CommonFilesSearchResultsViewerTable_hashsetHitsColLbl(), NO_DESCR, getHashSetHitsForFile(this.getContent())));
|
||||||
|
sheetSet.put(new NodeProperty<>(Bundle.CommonFilesSearchResultsViewerTable_dataSourceColLbl(), Bundle.CommonFilesSearchResultsViewerTable_dataSourceColLbl(), NO_DESCR, this.getDataSource()));
|
||||||
|
sheetSet.put(new NodeProperty<>(Bundle.CommonFilesSearchResultsViewerTable_mimeTypeColLbl(), Bundle.CommonFilesSearchResultsViewerTable_mimeTypeColLbl(), NO_DESCR, StringUtils.defaultString(this.getContent().getMIMEType())));
|
||||||
|
|
||||||
|
this.addTagProperty(sheetSet);
|
||||||
|
|
||||||
|
return sheet;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,146 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 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.commonfilesearch;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.openide.nodes.ChildFactory;
|
||||||
|
import org.openide.nodes.Children;
|
||||||
|
import org.openide.nodes.Node;
|
||||||
|
import org.openide.nodes.Sheet;
|
||||||
|
import org.openide.util.NbBundle;
|
||||||
|
import org.sleuthkit.autopsy.datamodel.DisplayableItemNode;
|
||||||
|
import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor;
|
||||||
|
import org.sleuthkit.autopsy.datamodel.NodeProperty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Node used to indicate the number of matches found with the MD5 children
|
||||||
|
* of this Node.
|
||||||
|
*/
|
||||||
|
final public class InstanceCountNode extends DisplayableItemNode {
|
||||||
|
|
||||||
|
final private int instanceCount;
|
||||||
|
final private List<Md5Metadata> metadataList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a node with the given number of instances, and the given
|
||||||
|
* selection of metadata.
|
||||||
|
* @param instanceCount
|
||||||
|
* @param md5Metadata
|
||||||
|
*/
|
||||||
|
@NbBundle.Messages({
|
||||||
|
"InstanceCountNode.displayName=Files with %s instances (%s)"
|
||||||
|
})
|
||||||
|
public InstanceCountNode(int instanceCount, List<Md5Metadata> md5Metadata) {
|
||||||
|
super(Children.create(new Md5NodeFactory(md5Metadata), true));
|
||||||
|
|
||||||
|
this.instanceCount = instanceCount;
|
||||||
|
this.metadataList = md5Metadata;
|
||||||
|
|
||||||
|
this.setDisplayName(String.format(Bundle.InstanceCountNode_displayName(), Integer.toString(instanceCount), md5Metadata.size()));
|
||||||
|
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/fileset-icon-16.png"); //NON-NLS
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of matches found for each of the MD5 children.
|
||||||
|
* @return int match count
|
||||||
|
*/
|
||||||
|
int getInstanceCount() {
|
||||||
|
return this.instanceCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a list of metadata for the MD5s which are children of this object.
|
||||||
|
* @return List<Md5Metadata>
|
||||||
|
*/
|
||||||
|
List<Md5Metadata> getMetadata() {
|
||||||
|
return Collections.unmodifiableList(this.metadataList);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
|
||||||
|
return visitor.visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLeafTypeNode() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getItemType() {
|
||||||
|
return getClass().getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NbBundle.Messages({"InstanceCountNode.createSheet.noDescription= "})
|
||||||
|
@Override
|
||||||
|
protected Sheet createSheet() {
|
||||||
|
Sheet sheet = new Sheet();
|
||||||
|
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
|
||||||
|
if (sheetSet == null) {
|
||||||
|
sheetSet = Sheet.createPropertiesSet();
|
||||||
|
sheet.put(sheetSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
final String NO_DESCR = Bundle.InstanceCountNode_createSheet_noDescription();
|
||||||
|
sheetSet.put(new NodeProperty<>(Bundle.CommonFilesSearchResultsViewerTable_filesColLbl(), Bundle.CommonFilesSearchResultsViewerTable_filesColLbl(), NO_DESCR, ""));
|
||||||
|
sheetSet.put(new NodeProperty<>(Bundle.CommonFilesSearchResultsViewerTable_instancesColLbl(), Bundle.CommonFilesSearchResultsViewerTable_instancesColLbl(), NO_DESCR, this.getInstanceCount()));
|
||||||
|
return sheet;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ChildFactory which builds CommonFileParentNodes from the
|
||||||
|
* CommonFilesMetaaData models.
|
||||||
|
*/
|
||||||
|
static class Md5NodeFactory extends ChildFactory<String> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of models, each of which is a parent node matching a single md5,
|
||||||
|
* containing children FileNodes.
|
||||||
|
*/
|
||||||
|
private final Map<String, Md5Metadata> metadata;
|
||||||
|
|
||||||
|
Md5NodeFactory(List<Md5Metadata> metadata) {
|
||||||
|
this.metadata = new HashMap<>();
|
||||||
|
|
||||||
|
Iterator<Md5Metadata> iterator = metadata.iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
Md5Metadata md5Metadata = iterator.next();
|
||||||
|
this.metadata.put(md5Metadata.getMd5(), md5Metadata);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Node createNodeForKey(String md5) {
|
||||||
|
Md5Metadata md5Metadata = this.metadata.get(md5);
|
||||||
|
return new Md5Node(md5Metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean createKeys(List<String> list) {
|
||||||
|
list.addAll(this.metadata.keySet());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -17,23 +17,21 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.datamodel;
|
package org.sleuthkit.autopsy.commonfilesearch;
|
||||||
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import org.openide.nodes.ChildFactory;
|
import org.openide.nodes.ChildFactory;
|
||||||
import org.openide.nodes.Children;
|
import org.openide.nodes.Children;
|
||||||
import org.openide.nodes.Node;
|
import org.openide.nodes.Node;
|
||||||
import org.openide.nodes.Sheet;
|
import org.openide.nodes.Sheet;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.openide.util.lookup.Lookups;
|
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||||
import org.sleuthkit.autopsy.commonfilesearch.FileInstanceMetadata;
|
|
||||||
import org.sleuthkit.autopsy.commonfilesearch.Md5Metadata;
|
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
import org.sleuthkit.autopsy.datamodel.DisplayableItemNode;
|
||||||
|
import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor;
|
||||||
|
import org.sleuthkit.autopsy.datamodel.NodeProperty;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
@ -52,30 +50,50 @@ public class Md5Node extends DisplayableItemNode {
|
|||||||
private final int commonFileCount;
|
private final int commonFileCount;
|
||||||
private final String dataSources;
|
private final String dataSources;
|
||||||
|
|
||||||
|
@NbBundle.Messages({
|
||||||
|
"Md5Node.Md5Node.format=MD5: %s"
|
||||||
|
})
|
||||||
|
/**
|
||||||
|
* Create a Match node whose children will all have this object in common.
|
||||||
|
* @param data the common feature, and the children
|
||||||
|
*/
|
||||||
public Md5Node(Md5Metadata data) {
|
public Md5Node(Md5Metadata data) {
|
||||||
super(Children.create(
|
super(Children.create(
|
||||||
new FileInstanceNodeFactory(data), true),
|
new FileInstanceNodeFactory(data), true));
|
||||||
Lookups.singleton(data.getMd5()));
|
|
||||||
|
|
||||||
this.commonFileCount = data.size();
|
this.commonFileCount = data.size();
|
||||||
this.dataSources = String.join(", ", data.getDataSources());
|
this.dataSources = String.join(", ", data.getDataSources());
|
||||||
this.md5Hash = data.getMd5();
|
this.md5Hash = data.getMd5();
|
||||||
|
|
||||||
this.setDisplayName(this.md5Hash);
|
this.setDisplayName(String.format(Bundle.Md5Node_Md5Node_format(), this.md5Hash));
|
||||||
|
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/fileset-icon-16.png"); //NON-NLS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How many files are in common? This will be the number of children.
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
int getCommonFileCount() {
|
int getCommonFileCount() {
|
||||||
return this.commonFileCount;
|
return this.commonFileCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Datasources where these matches occur.
|
||||||
|
* @return string delimited list of sources
|
||||||
|
*/
|
||||||
String getDataSources() {
|
String getDataSources() {
|
||||||
return this.dataSources;
|
return this.dataSources;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MD5 which is common to these matches
|
||||||
|
* @return string md5 hash
|
||||||
|
*/
|
||||||
public String getMd5() {
|
public String getMd5() {
|
||||||
return this.md5Hash;
|
return this.md5Hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NbBundle.Messages({"Md5Node.createSheet.noDescription= "})
|
||||||
@Override
|
@Override
|
||||||
protected Sheet createSheet() {
|
protected Sheet createSheet() {
|
||||||
Sheet sheet = new Sheet();
|
Sheet sheet = new Sheet();
|
||||||
@ -85,30 +103,15 @@ public class Md5Node extends DisplayableItemNode {
|
|||||||
sheet.put(sheetSet);
|
sheet.put(sheetSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, Object> map = new LinkedHashMap<>();
|
final String NO_DESCR = Bundle.Md5Node_createSheet_noDescription();
|
||||||
fillPropertyMap(map, this);
|
sheetSet.put(new NodeProperty<>(Bundle.CommonFilesSearchResultsViewerTable_filesColLbl(), Bundle.CommonFilesSearchResultsViewerTable_filesColLbl(), NO_DESCR, ""));
|
||||||
|
sheetSet.put(new NodeProperty<>(Bundle.CommonFilesSearchResultsViewerTable_pathColLbl(), Bundle.CommonFilesSearchResultsViewerTable_pathColLbl(), NO_DESCR, ""));
|
||||||
final String NO_DESCR = Bundle.AbstractFsContentNode_noDesc_text();
|
sheetSet.put(new NodeProperty<>(Bundle.CommonFilesSearchResultsViewerTable_hashsetHitsColLbl(), Bundle.CommonFilesSearchResultsViewerTable_hashsetHitsColLbl(), NO_DESCR, ""));
|
||||||
for (Md5Node.CommonFileParentPropertyType propType : Md5Node.CommonFileParentPropertyType.values()) {
|
sheetSet.put(new NodeProperty<>(Bundle.CommonFilesSearchResultsViewerTable_dataSourceColLbl(), Bundle.CommonFilesSearchResultsViewerTable_dataSourceColLbl(), NO_DESCR, this.getDataSources()));
|
||||||
final String propString = propType.toString();
|
|
||||||
sheetSet.put(new NodeProperty<>(propString, propString, NO_DESCR, map.get(propString)));
|
|
||||||
}
|
|
||||||
|
|
||||||
return sheet;
|
return sheet;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Fill map with AbstractFile properties
|
|
||||||
*
|
|
||||||
* @param map map with preserved ordering, where property names/values are
|
|
||||||
* put
|
|
||||||
* @param node The item to get properties for.
|
|
||||||
*/
|
|
||||||
static private void fillPropertyMap(Map<String, Object> map, Md5Node node) {
|
|
||||||
map.put(CommonFileParentPropertyType.File.toString(), node.getMd5());
|
|
||||||
map.put(CommonFileParentPropertyType.InstanceCount.toString(), node.getCommonFileCount());
|
|
||||||
map.put(CommonFileParentPropertyType.DataSource.toString(), node.getDataSources());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
|
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
|
||||||
@ -144,9 +147,7 @@ public class Md5Node extends DisplayableItemNode {
|
|||||||
AbstractFile abstractFile = tskDb.findAllFilesWhere(String.format("obj_id in (%s)", file.getObjectId())).get(0);
|
AbstractFile abstractFile = tskDb.findAllFilesWhere(String.format("obj_id in (%s)", file.getObjectId())).get(0);
|
||||||
|
|
||||||
return new FileInstanceNode(abstractFile, file.getDataSourceName());
|
return new FileInstanceNode(abstractFile, file.getDataSourceName());
|
||||||
} catch (NoCurrentCaseException ex) {
|
} catch (NoCurrentCaseException | TskCoreException ex) {
|
||||||
LOGGER.log(Level.SEVERE, String.format("Unable to create node for file with obj_id: %s.", new Object[]{file.getObjectId()}), ex);
|
|
||||||
} catch (TskCoreException ex) {
|
|
||||||
LOGGER.log(Level.SEVERE, String.format("Unable to create node for file with obj_id: %s.", new Object[]{file.getObjectId()}), ex);
|
LOGGER.log(Level.SEVERE, String.format("Unable to create node for file with obj_id: %s.", new Object[]{file.getObjectId()}), ex);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -159,25 +160,4 @@ public class Md5Node extends DisplayableItemNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NbBundle.Messages({
|
|
||||||
"CommonFileParentPropertyType.fileColLbl=File",
|
|
||||||
"CommonFileParentPropertyType.instanceColLbl=Instance Count",
|
|
||||||
"CommonFileParentPropertyType.dataSourceColLbl=Data Source"})
|
|
||||||
public enum CommonFileParentPropertyType {
|
|
||||||
|
|
||||||
File(Bundle.CommonFileParentPropertyType_fileColLbl()),
|
|
||||||
InstanceCount(Bundle.CommonFileParentPropertyType_instanceColLbl()),
|
|
||||||
DataSource(Bundle.CommonFileParentPropertyType_dataSourceColLbl());
|
|
||||||
|
|
||||||
final private String displayString;
|
|
||||||
|
|
||||||
private CommonFileParentPropertyType(String displayString) {
|
|
||||||
this.displayString = displayString;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return displayString;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -20,13 +20,14 @@
|
|||||||
package org.sleuthkit.autopsy.commonfilesearch;
|
package org.sleuthkit.autopsy.commonfilesearch;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import org.sleuthkit.datamodel.TskData.FileKnown;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides logic for selecting common files from a single data source.
|
* Provides logic for selecting common files from a single data source.
|
||||||
*/
|
*/
|
||||||
final class SingleDataSource extends CommonFilesMetadataBuilder {
|
final public class SingleDataSource extends CommonFilesMetadataBuilder {
|
||||||
|
|
||||||
private static final String WHERE_CLAUSE = "%s md5 in (select md5 from tsk_files where md5 in (select md5 from tsk_files where (known != 1 OR known IS NULL) and data_source_obj_id=%s%s) GROUP BY md5 HAVING COUNT(*) > 1) order by md5"; //NON-NLS
|
private static final String WHERE_CLAUSE = "%s md5 in (select md5 from tsk_files where md5 in (select md5 from tsk_files where (known != "+ FileKnown.KNOWN.getFileKnownValue() + " OR known IS NULL) and data_source_obj_id=%s%s) GROUP BY md5 HAVING COUNT(DISTINCT data_source_obj_id) > 1) order by md5"; //NON-NLS
|
||||||
private final Long selectedDataSourceId;
|
private final Long selectedDataSourceId;
|
||||||
private final String dataSourceName;
|
private final String dataSourceName;
|
||||||
|
|
||||||
@ -35,10 +36,12 @@ final class SingleDataSource extends CommonFilesMetadataBuilder {
|
|||||||
* once in the given data source
|
* once in the given data source
|
||||||
* @param dataSourceId data source id for which common files must appear at least once
|
* @param dataSourceId data source id for which common files must appear at least once
|
||||||
* @param dataSourceIdMap a map of obj_id to datasource name
|
* @param dataSourceIdMap a map of obj_id to datasource name
|
||||||
* @param filterByMediaMimeType match only on files whose mime types can be broadly categorized as media types
|
* @param filterByMediaMimeType match only on files whose mime types can be
|
||||||
* @param filterByDocMimeType match only on files whose mime types can be broadly categorized as document types
|
* broadly categorized as media types
|
||||||
|
* @param filterByDocMimeType match only on files whose mime types can be
|
||||||
|
* broadly categorized as document types
|
||||||
*/
|
*/
|
||||||
SingleDataSource(Long dataSourceId, Map<Long, String> dataSourceIdMap, boolean filterByMediaMimeType, boolean filterByDocMimeType) {
|
public SingleDataSource(Long dataSourceId, Map<Long, String> dataSourceIdMap, boolean filterByMediaMimeType, boolean filterByDocMimeType) {
|
||||||
super(dataSourceIdMap, filterByMediaMimeType, filterByDocMimeType);
|
super(dataSourceIdMap, filterByMediaMimeType, filterByDocMimeType);
|
||||||
this.selectedDataSourceId = dataSourceId;
|
this.selectedDataSourceId = dataSourceId;
|
||||||
this.dataSourceName = dataSourceIdMap.get(this.selectedDataSourceId);
|
this.dataSourceName = dataSourceIdMap.get(this.selectedDataSourceId);
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user