Merge branch 'develop' of github.com:sleuthkit/autopsy into 3701_service

This commit is contained in:
esaunders 2018-06-18 16:58:37 -04:00
commit 4f6a2f3500
222 changed files with 4869 additions and 1624 deletions

View File

@ -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"/>
@ -89,17 +84,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=1O5D09fFCFpXZqw0uLEs8kVLtfYTxqXAd" dest="${test-input}/commonfiles_image1_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=1rMP1QTI0LdppzdypbG-4BDwkKcR3tHXc" dest="${test-input}/commonfiles_image2_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=1OdwyJ2lru55ZPdvwzj3pq6sXIys27i4x" dest="${test-input}/commonfiles_image3_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=1GoF2x0km5AyFvE926ttN20lrMX1oLN7E" dest="${test-input}/commonfiles_image4_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">

View File

@ -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

View File

@ -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>

View File

@ -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"

View File

@ -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",

View File

@ -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;
@ -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());
@ -101,6 +104,7 @@ abstract class AddTagAction extends AbstractAction implements Presenter.Popup {
// Create a menu item for each of the existing and visible tags. // Create a menu item for each of the existing and visible tags.
// Selecting one of these menu items adds a tag with the associated tag name. // Selecting one of these menu items adds a tag with the associated tag name.
List<JMenuItem> standardTagMenuitems = new ArrayList<>();
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();
@ -115,14 +119,25 @@ abstract class AddTagAction extends AbstractAction implements Presenter.Popup {
getAndAddTag(entry.getKey(), entry.getValue(), NO_COMMENT); getAndAddTag(entry.getKey(), entry.getValue(), NO_COMMENT);
}); });
// Show custom tags before predefined tags in the menu
if (standardTagNames.contains(tagDisplayName)) {
standardTagMenuitems.add(tagNameItem);
} else {
add(tagNameItem); add(tagNameItem);
} }
} }
}
if (getItemCount() > 0) { if (getItemCount() > 0) {
addSeparator(); addSeparator();
} }
standardTagMenuitems.forEach((menuItem) -> {
add(menuItem);
});
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
// optional comment and adds a tag with the resulting name. // optional comment and adds a tag with the resulting name.

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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"

View File

@ -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, &quot;{key}&quot;)"/>
</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, &quot;{key}&quot;)"/>
</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, &quot;{key}&quot;)"/>
</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, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Container>
</SubComponents> </SubComponents>
</Form> </Form>

View File

@ -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;
@ -50,7 +54,8 @@ import org.sleuthkit.datamodel.TskData;
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 {
@ -105,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);
} }
@ -144,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());
@ -174,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) {
@ -203,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) {
@ -213,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(
@ -222,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))
@ -232,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())
); );
@ -247,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)
@ -282,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);
} }
@ -291,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;

View File

@ -0,0 +1,126 @@
/*
* 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
*/
@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) {
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);
} 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);
}
}

View File

@ -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) {
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);
} 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);
}
}

View File

@ -0,0 +1,188 @@
/*
* 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
* @param newTagName
*/
abstract protected void replaceTag(T oldTag, TagName newTagName);
/**
* 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());
});
});
// 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);
});
}
});
add(newTagMenuItem);
}
}
}

View File

@ -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();
} }

View File

@ -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;

View File

@ -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

View File

@ -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 {
/** /**

View File

@ -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());

View File

@ -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().

View File

@ -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;

View File

@ -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")

View File

@ -46,6 +46,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());

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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());

View File

@ -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());

View File

@ -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());
} }
} }

View File

@ -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;

View File

@ -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;

View File

@ -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(() -> {

View File

@ -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();

View File

@ -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;

View File

@ -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.
* *

View File

@ -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 connecting to Central Repository database.", 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());
}
}

View File

@ -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

View 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, &quot;{key}&quot;)"/>
</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, &quot;{key}&quot;)"/>
</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, &quot;{key}&quot;)"/>
</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, &quot;{key}&quot;)"/>
</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, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Form>

View 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
}

View File

@ -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;
}
}

View File

@ -3,3 +3,4 @@ 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

View File

@ -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, &quot;{key}&quot;)"/>
</Property>
</Properties>
</MenuItem>
</SubComponents> </SubComponents>
</Container> </Container>
<Component class="javax.swing.JFileChooser" name="CSVFileChooser"> <Component class="javax.swing.JFileChooser" name="CSVFileChooser">

View File

@ -18,9 +18,7 @@
*/ */
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;
@ -37,36 +35,27 @@ 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.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 +65,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 +78,7 @@ 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 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 +112,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,6 +134,7 @@ 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();
@ -150,7 +150,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()) {
@ -174,7 +175,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(),
@ -204,8 +205,8 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
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(),
@ -298,7 +299,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);
} }
} }
@ -389,7 +390,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 +436,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,7 +449,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
} }
} }
@ -456,55 +457,80 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
} }
/** /**
* Query the db for artifact instances from other cases correlated to the * Query the central repo database (if enabled) and the case database to find all
* given central repository artifact. Will not show instances from the same * artifact instances correlated to the given central repository artifact. If the
* datasource / device * 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();
@ -522,75 +548,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 +647,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);
}
}); });
} }
@ -690,159 +697,191 @@ 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(); 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)); tableStatusPanel.setPreferredSize(new java.awt.Dimension(1500, 16));
tableStatusPanelLabel.setForeground(new Color(255, 0, 51)); tableStatusPanelLabel.setForeground(new java.awt.Color(255, 0, 51));
GroupLayout tableStatusPanelLayout = new GroupLayout(tableStatusPanel); 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.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(tableStatusPanelLayout.createSequentialGroup() .addGroup(tableStatusPanelLayout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addComponent(tableStatusPanelLabel, GroupLayout.DEFAULT_SIZE, 780, Short.MAX_VALUE) .addComponent(tableStatusPanelLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 780, Short.MAX_VALUE)
.addContainerGap())) .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.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(tableStatusPanelLayout.createSequentialGroup() .addGroup(tableStatusPanelLayout.createSequentialGroup()
.addComponent(tableStatusPanelLabel, GroupLayout.PREFERRED_SIZE, 16, GroupLayout.PREFERRED_SIZE) .addComponent(tableStatusPanelLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, Short.MAX_VALUE))) .addGap(0, 0, Short.MAX_VALUE)))
); );
GroupLayout tableContainerPanelLayout = new GroupLayout(tableContainerPanel); 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) .addComponent(tableScrollPane, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(tableStatusPanel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
); );
tableContainerPanelLayout.setVerticalGroup(tableContainerPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) tableContainerPanelLayout.setVerticalGroup(
tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(tableContainerPanelLayout.createSequentialGroup() .addGroup(tableContainerPanelLayout.createSequentialGroup()
.addComponent(tableScrollPane, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(tableScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(tableStatusPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) .addComponent(tableStatusPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap()) .addContainerGap())
); );
GroupLayout otherCasesPanelLayout = new GroupLayout(otherCasesPanel); javax.swing.GroupLayout otherCasesPanelLayout = new javax.swing.GroupLayout(otherCasesPanel);
otherCasesPanel.setLayout(otherCasesPanelLayout); otherCasesPanel.setLayout(otherCasesPanelLayout);
otherCasesPanelLayout.setHorizontalGroup(otherCasesPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) otherCasesPanelLayout.setHorizontalGroup(
otherCasesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 1500, Short.MAX_VALUE) .addGap(0, 1500, Short.MAX_VALUE)
.addGroup(otherCasesPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) .addGroup(otherCasesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(tableContainerPanel, GroupLayout.Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addComponent(tableContainerPanel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
); );
otherCasesPanelLayout.setVerticalGroup(otherCasesPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) otherCasesPanelLayout.setVerticalGroup(
otherCasesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 60, Short.MAX_VALUE) .addGap(0, 60, Short.MAX_VALUE)
.addGroup(otherCasesPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) .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.PREFERRED_SIZE, 52, 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, 52, 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.JMenuItem exportToCSVMenuItem;
private JTable otherCasesTable; private javax.swing.JPanel otherCasesPanel;
private JPopupMenu rightClickPopupMenu; private javax.swing.JTable otherCasesTable;
private JMenuItem selectAllMenuItem; private javax.swing.JPopupMenu rightClickPopupMenu;
private JMenuItem showCaseDetailsMenuItem; private javax.swing.JMenuItem selectAllMenuItem;
private JMenuItem showCommonalityMenuItem; private javax.swing.JMenuItem showCaseDetailsMenuItem;
private JPanel tableContainerPanel; private javax.swing.JMenuItem showCommonalityMenuItem;
private JScrollPane tableScrollPane; private javax.swing.JPanel tableContainerPanel;
private JPanel tableStatusPanel; private javax.swing.JScrollPane tableScrollPane;
private JLabel tableStatusPanelLabel; 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 +891,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);
} }
} }

View File

@ -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();
} }

View File

@ -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;
}
}

View File

@ -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({
@ -102,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
*/ */
@ -145,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
*/ */
@ -155,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;

View File

@ -90,7 +90,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

View File

@ -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() {
} }
@ -83,7 +83,7 @@ public class EamArtifactUtil {
} }
} }
} 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
@ -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,17 +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 isSupportedAbstractFileType(AbstractFile af) { public static boolean isSupportedAbstractFileType(AbstractFile file) {
if (af == null) { if (file == null) {
return false; return false;
} }
switch (af.getType()) { switch (file.getType()) {
case UNALLOC_BLOCKS: case UNALLOC_BLOCKS:
case UNUSED_BLOCKS: case UNUSED_BLOCKS:
case SLACK: case SLACK:
@ -293,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;
} }
} }

View File

@ -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");
@ -159,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;
@ -310,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
@ -367,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;
@ -379,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;
@ -391,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;
@ -402,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;
@ -413,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;
@ -462,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;
@ -523,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
*/ */
@ -630,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;
} }

View File

@ -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);
}
} }

View File

@ -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");
}
}

View File

@ -114,7 +114,7 @@ final 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) {

View File

@ -221,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);
} }

View File

@ -124,7 +124,7 @@ final 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) {
@ -679,6 +679,22 @@ final 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.

View File

@ -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());

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2017-18 Basis Technology Corp. * Copyright 2017-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");
@ -48,6 +48,7 @@ import org.sleuthkit.datamodel.TskCoreException;
* CVTTopComponent when this tab is active allowing for context sensitive * CVTTopComponent when this tab is active allowing for context sensitive
* actions to work correctly. * actions to work correctly.
*/ */
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
public final class AccountsBrowser extends JPanel implements ExplorerManager.Provider, Lookup.Provider { public final class AccountsBrowser extends JPanel implements ExplorerManager.Provider, Lookup.Provider {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2017-18 Basis Technology Corp. * Copyright 2017-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");
@ -42,6 +42,7 @@ import org.sleuthkit.autopsy.coreutils.ThreadConfined;
@TopComponent.Registration(mode = "cvt", openAtStartup = false) @TopComponent.Registration(mode = "cvt", openAtStartup = false)
@RetainLocation("cvt") @RetainLocation("cvt")
@NbBundle.Messages("CVTTopComponent.name= Communications Visualization") @NbBundle.Messages("CVTTopComponent.name= Communications Visualization")
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
public final class CVTTopComponent extends TopComponent { public final class CVTTopComponent extends TopComponent {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2017-18 Basis Technology Corp. * Copyright 2017-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");
@ -57,6 +57,7 @@ import org.sleuthkit.datamodel.TskCoreException;
* Panel that holds the Filter control widgets and triggers queries against the * Panel that holds the Filter control widgets and triggers queries against the
* CommunicationsManager on user filtering changes. * CommunicationsManager on user filtering changes.
*/ */
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
final public class FiltersPanel extends JPanel { final public class FiltersPanel extends JPanel {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2017-18 Basis Technology Corp. * Copyright 2017-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");
@ -41,6 +41,7 @@ import org.sleuthkit.autopsy.directorytree.DataResultFilterNode;
* messages and other account details, and a ContentViewer to show individual * messages and other account details, and a ContentViewer to show individual
* messages. * messages.
*/ */
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
public final class MessageBrowser extends JPanel implements ExplorerManager.Provider, Lookup.Provider { public final class MessageBrowser extends JPanel implements ExplorerManager.Provider, Lookup.Provider {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;

View File

@ -76,6 +76,7 @@ import org.sleuthkit.datamodel.TskData;
@ServiceProviders(value = { @ServiceProviders(value = {
@ServiceProvider(service = FrameCapture.class) @ServiceProvider(service = FrameCapture.class)
}) })
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
public class FXVideoPanel extends MediaViewVideoPanel { public class FXVideoPanel extends MediaViewVideoPanel {
// Refer to https://docs.oracle.com/javafx/2/api/javafx/scene/media/package-summary.html // Refer to https://docs.oracle.com/javafx/2/api/javafx/scene/media/package-summary.html

View File

@ -36,6 +36,7 @@ import org.sleuthkit.datamodel.AbstractFile;
* Generic Application content viewer * Generic Application content viewer
*/ */
@ServiceProvider(service = DataContentViewer.class, position = 3) @ServiceProvider(service = DataContentViewer.class, position = 3)
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
public class FileViewer extends javax.swing.JPanel implements DataContentViewer { public class FileViewer extends javax.swing.JPanel implements DataContentViewer {
private static final int CONFIDENCE_LEVEL = 5; private static final int CONFIDENCE_LEVEL = 5;

View File

@ -30,6 +30,7 @@ import org.sleuthkit.datamodel.AbstractFile;
/** /**
* Media content viewer for videos, sounds and images. * Media content viewer for videos, sounds and images.
*/ */
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
class MediaFileViewer extends javax.swing.JPanel implements FileTypeViewer { class MediaFileViewer extends javax.swing.JPanel implements FileTypeViewer {
private static final Logger LOGGER = Logger.getLogger(MediaFileViewer.class.getName()); private static final Logger LOGGER = Logger.getLogger(MediaFileViewer.class.getName());

View File

@ -48,7 +48,6 @@ import org.openide.util.NbBundle;
import org.python.google.common.collect.Lists; import org.python.google.common.collect.Lists;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.ImageUtils; import org.sleuthkit.autopsy.coreutils.ImageUtils;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.FileNode; import org.sleuthkit.autopsy.datamodel.FileNode;
import org.sleuthkit.autopsy.directorytree.ExternalViewerAction; import org.sleuthkit.autopsy.directorytree.ExternalViewerAction;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
@ -60,12 +59,11 @@ import org.sleuthkit.datamodel.AbstractFile;
@NbBundle.Messages({"MediaViewImagePanel.externalViewerButton.text=Open in External Viewer", @NbBundle.Messages({"MediaViewImagePanel.externalViewerButton.text=Open in External Viewer",
"MediaViewImagePanel.errorLabel.text=Could not load file into Media View.", "MediaViewImagePanel.errorLabel.text=Could not load file into Media View.",
"MediaViewImagePanel.errorLabel.OOMText=Could not load file into Media View: insufficent memory."}) "MediaViewImagePanel.errorLabel.OOMText=Could not load file into Media View: insufficent memory."})
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPanel { class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPanel {
private static final Image EXTERNAL = new Image(MediaViewImagePanel.class.getResource("/org/sleuthkit/autopsy/images/external.png").toExternalForm()); private static final Image EXTERNAL = new Image(MediaViewImagePanel.class.getResource("/org/sleuthkit/autopsy/images/external.png").toExternalForm());
private static final Logger LOGGER = Logger.getLogger(MediaViewImagePanel.class.getName());
private final boolean fxInited; private final boolean fxInited;
private JFXPanel fxPanel; private JFXPanel fxPanel;

View File

@ -49,6 +49,7 @@ import org.openide.util.actions.Presenter;
/** /**
* Panel to display a SQLite table * Panel to display a SQLite table
*/ */
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
class SQLiteTableView extends JPanel implements ExplorerManager.Provider { class SQLiteTableView extends JPanel implements ExplorerManager.Provider {
private final org.openide.explorer.view.OutlineView outlineView; private final org.openide.explorer.view.OutlineView outlineView;

View File

@ -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");
@ -268,6 +268,19 @@ public class Installer extends ModuleInstall {
} }
} }
/**
* Make a folder in the config directory for object detection classifiers if one does not
* exist.
*/
private static void ensureClassifierFolderExists() {
File objectDetectionClassifierDir = new File(PlatformUtil.getObjectDetectionClassifierPath());
objectDetectionClassifierDir.mkdir();
}
/**
* Make a folder in the config directory for Python Modules if one does not
* exist.
*/
private static void ensurePythonModulesFolderExists() { private static void ensurePythonModulesFolderExists() {
File pythonModulesDir = new File(PlatformUtil.getUserPythonModulesPath()); File pythonModulesDir = new File(PlatformUtil.getUserPythonModulesPath());
pythonModulesDir.mkdir(); pythonModulesDir.mkdir();
@ -277,6 +290,7 @@ public class Installer extends ModuleInstall {
public void restored() { public void restored() {
super.restored(); super.restored();
ensurePythonModulesFolderExists(); ensurePythonModulesFolderExists();
ensureClassifierFolderExists();
initJavaFx(); initJavaFx();
for (ModuleInstall mi : packageInstallers) { for (ModuleInstall mi : packageInstallers) {
try { try {

View File

@ -69,6 +69,7 @@ public final class UserPreferences {
private static final String MODE = "AutopsyMode"; // NON-NLS private static final String MODE = "AutopsyMode"; // NON-NLS
private static final String MAX_NUM_OF_LOG_FILE = "MaximumNumberOfLogFiles"; private static final String MAX_NUM_OF_LOG_FILE = "MaximumNumberOfLogFiles";
private static final int LOG_FILE_NUM_INT = 10; private static final int LOG_FILE_NUM_INT = 10;
public static final String GROUP_ITEMS_IN_TREE_BY_DATASOURCE = "GroupItemsInTreeByDataSource"; //NON-NLS
// Prevent instantiation. // Prevent instantiation.
private UserPreferences() { private UserPreferences() {
@ -187,6 +188,14 @@ public final class UserPreferences {
preferences.putInt(NUMBER_OF_FILE_INGEST_THREADS, value); preferences.putInt(NUMBER_OF_FILE_INGEST_THREADS, value);
} }
public static boolean groupItemsInTreeByDatasource() {
return preferences.getBoolean(GROUP_ITEMS_IN_TREE_BY_DATASOURCE, false);
}
public static void setGroupItemsInTreeByDatasource(boolean value) {
preferences.putBoolean(GROUP_ITEMS_IN_TREE_BY_DATASOURCE, value);
}
/** /**
* Reads persisted case database connection info. * Reads persisted case database connection info.
* *

View File

@ -1,12 +1,24 @@
/* /*
* To change this template, choose Tools | Templates * Autopsy Forensic Browser
* and open the template in the editor. *
* Copyright 2011-2018 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.sleuthkit.autopsy.corecomponents; package org.sleuthkit.autopsy.corecomponents;
import java.awt.Component; import java.awt.Component;
import java.awt.Dimension;
import java.awt.Toolkit;
import javax.swing.JFrame; import javax.swing.JFrame;
import javax.swing.JPanel; import javax.swing.JPanel;
import org.openide.windows.WindowManager; import org.openide.windows.WindowManager;
@ -16,6 +28,7 @@ import org.openide.windows.WindowManager;
* the panel given to it. No additional buttons or features, except the default * the panel given to it. No additional buttons or features, except the default
* close operation, which is set to dispose. * close operation, which is set to dispose.
*/ */
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
public class AdvancedConfigurationCleanDialog extends javax.swing.JDialog { public class AdvancedConfigurationCleanDialog extends javax.swing.JDialog {
/** /**
@ -27,6 +40,8 @@ public class AdvancedConfigurationCleanDialog extends javax.swing.JDialog {
/** /**
* Creates new form AdvancedConfigurationDialog * Creates new form AdvancedConfigurationDialog
*
* @param resizable Is the dialog resizable?
*/ */
public AdvancedConfigurationCleanDialog(boolean resizable) { public AdvancedConfigurationCleanDialog(boolean resizable) {
super((JFrame) WindowManager.getDefault().getMainWindow(), true); super((JFrame) WindowManager.getDefault().getMainWindow(), true);

View File

@ -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");
@ -16,26 +16,18 @@
* 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.
*/ */
/*
* AdvancedConfigurationDialog.java
*
* Created on Feb 28, 2012, 4:47:31 PM
*/
package org.sleuthkit.autopsy.corecomponents; package org.sleuthkit.autopsy.corecomponents;
import java.awt.Component; import java.awt.Component;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import javax.swing.JFrame; import javax.swing.JFrame;
import javax.swing.JPanel; import javax.swing.JPanel;
import org.openide.windows.WindowManager; import org.openide.windows.WindowManager;
/** /**
* * Advanced configuration dialog.
* @author dfickling
*/ */
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
public class AdvancedConfigurationDialog extends javax.swing.JDialog { public class AdvancedConfigurationDialog extends javax.swing.JDialog {
/** /**
@ -47,6 +39,8 @@ public class AdvancedConfigurationDialog extends javax.swing.JDialog {
/** /**
* Creates new form AdvancedConfigurationDialog * Creates new form AdvancedConfigurationDialog
*
* @param resizable Is the dialog resizable?
*/ */
public AdvancedConfigurationDialog(boolean resizable) { public AdvancedConfigurationDialog(boolean resizable) {
super((JFrame) WindowManager.getDefault().getMainWindow(), true); super((JFrame) WindowManager.getDefault().getMainWindow(), true);

View File

@ -26,7 +26,7 @@ LBL_Description=<div style=\"font-size: 12pt; font-family: Verdana, 'Verdana CE'
Format_OperatingSystem_Value={0} version {1} running on {2} Format_OperatingSystem_Value={0} version {1} running on {2}
LBL_Copyright=<div style\="font-size\: 12pt; font-family\: Verdana, 'Verdana CE', Arial, 'Arial CE', 'Lucida Grande CE', lucida, 'Helvetica CE', sans-serif; ">Autopsy&trade; is a digital forensics platform based on The Sleuth Kit&trade; and other tools. <br><ul><li>General Information: <a style\="color\: \#1E2A60;" href\="http\://www.sleuthkit.org">http\://www.sleuthkit.org</a>.</li><li>Training: <a style\="color\: \#1E2A60;" href\="http://www.basistech.com/autopsy-training">http://www.basistech.com/autopsy-training</a></li><li>Commercial Support: <a style\="color\: \#1E2A60;" href\="http://www.basistech.com/digital-forensics/autopsy/support/">http://www.basistech.com/digital-forensics/autopsy/support/</a></li></ul>Copyright &copy; 2003-2018. </div> LBL_Copyright=<div style\="font-size\: 12pt; font-family\: Verdana, 'Verdana CE', Arial, 'Arial CE', 'Lucida Grande CE', lucida, 'Helvetica CE', sans-serif; ">Autopsy&trade; is a digital forensics platform based on The Sleuth Kit&trade; and other tools. <br><ul><li>General Information: <a style\="color\: \#1E2A60;" href\="http\://www.sleuthkit.org">http\://www.sleuthkit.org</a>.</li><li>Training: <a style\="color\: \#1E2A60;" href\="http://www.basistech.com/autopsy-training">http://www.basistech.com/autopsy-training</a></li><li>Commercial Support: <a style\="color\: \#1E2A60;" href\="http://www.basistech.com/digital-forensics/autopsy/support/">http://www.basistech.com/digital-forensics/autopsy/support/</a></li></ul>Copyright &copy; 2003-2018. </div>
URL_ON_IMG=http://www.sleuthkit.org/ URL_ON_IMG=http://www.sleuthkit.org/
URL_ON_HELP=http://sleuthkit.org/autopsy/docs/user-docs/4.7.0/ URL_ON_HELP=http://sleuthkit.org/autopsy/docs/user-docs/4.8.0/
FILE_FOR_LOCAL_HELP=file:/// FILE_FOR_LOCAL_HELP=file:///
INDEX_FOR_LOCAL_HELP=/docs/index.html INDEX_FOR_LOCAL_HELP=/docs/index.html
LBL_Close=Close LBL_Close=Close

View File

@ -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");
@ -38,8 +38,9 @@ import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
/** /**
* * Data content panel.
*/ */
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
public class DataContentPanel extends javax.swing.JPanel implements DataContent, ChangeListener { public class DataContentPanel extends javax.swing.JPanel implements DataContent, ChangeListener {
private static Logger logger = Logger.getLogger(DataContentPanel.class.getName()); private static Logger logger = Logger.getLogger(DataContentPanel.class.getName());
@ -241,7 +242,7 @@ public class DataContentPanel extends javax.swing.JPanel implements DataContent,
private static class UpdateWrapper { private static class UpdateWrapper {
private DataContentViewer wrapped; private final DataContentViewer wrapped;
private boolean outdated; private boolean outdated;
UpdateWrapper(DataContentViewer wrapped) { UpdateWrapper(DataContentViewer wrapped) {

View File

@ -43,6 +43,7 @@ import org.sleuthkit.autopsy.coreutils.Logger;
//@TopComponent.Description(preferredID = "DataContentTopComponent") //@TopComponent.Description(preferredID = "DataContentTopComponent")
//@TopComponent.Registration(mode = "output", openAtStartup = true) //@TopComponent.Registration(mode = "output", openAtStartup = true)
//@TopComponent.OpenActionRegistration(displayName = "#CTL_DataContentAction", preferredID = "DataContentTopComponent") //@TopComponent.OpenActionRegistration(displayName = "#CTL_DataContentAction", preferredID = "DataContentTopComponent")
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
public final class DataContentTopComponent extends TopComponent implements DataContent, ExplorerManager.Provider { public final class DataContentTopComponent extends TopComponent implements DataContent, ExplorerManager.Provider {
private static final Logger logger = Logger.getLogger(DataContentTopComponent.class.getName()); private static final Logger logger = Logger.getLogger(DataContentTopComponent.class.getName());

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2013 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");
@ -63,6 +63,7 @@ import org.netbeans.swing.etable.ETable;
* in a JTable representation of its BlackboardAttributes. * in a JTable representation of its BlackboardAttributes.
*/ */
@ServiceProvider(service = DataContentViewer.class, position = 7) @ServiceProvider(service = DataContentViewer.class, position = 7)
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
public class DataContentViewerArtifact extends javax.swing.JPanel implements DataContentViewer { public class DataContentViewerArtifact extends javax.swing.JPanel implements DataContentViewer {
@NbBundle.Messages({ @NbBundle.Messages({
@ -484,7 +485,8 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
if ((artifact == null) if ((artifact == null)
|| (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID()) || (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID())
|| (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) || (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID())
|| (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID())) { || (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID())
|| (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_OBJECT_DETECTED.getTypeID())) {
return 3; return 3;
} else { } else {
return 6; return 6;

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2016 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");
@ -27,7 +27,6 @@ import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import javax.swing.JMenuItem; import javax.swing.JMenuItem;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import javax.swing.JTextPane;
import javax.swing.text.BadLocationException; import javax.swing.text.BadLocationException;
import javax.swing.text.Utilities; import javax.swing.text.Utilities;
import org.openide.nodes.Node; import org.openide.nodes.Node;
@ -40,6 +39,7 @@ import org.sleuthkit.datamodel.TskException;
/** /**
* Hex view of file contents. * Hex view of file contents.
*/ */
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
@ServiceProvider(service = DataContentViewer.class, position = 1) @ServiceProvider(service = DataContentViewer.class, position = 1)
public class DataContentViewerHex extends javax.swing.JPanel implements DataContentViewer { public class DataContentViewerHex extends javax.swing.JPanel implements DataContentViewer {

View File

@ -72,6 +72,7 @@ import org.sleuthkit.autopsy.datamodel.NodeSelectionInfo;
* (DataContentTopComponent) that is normally docked into the lower right hand * (DataContentTopComponent) that is normally docked into the lower right hand
* side of the main application window, or it could be a custom content view. * side of the main application window, or it could be a custom content view.
*/ */
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
public class DataResultPanel extends javax.swing.JPanel implements DataResult, ChangeListener, ExplorerManager.Provider { public class DataResultPanel extends javax.swing.JPanel implements DataResult, ChangeListener, ExplorerManager.Provider {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -451,7 +452,7 @@ public class DataResultPanel extends javax.swing.JPanel implements DataResult, C
} }
} }
} }
}; }
if (tabToSelect == NO_TAB_SELECTED) { if (tabToSelect == NO_TAB_SELECTED) {
tabToSelect = resultViewerTabs.getSelectedIndex(); tabToSelect = resultViewerTabs.getSelectedIndex();
if ((tabToSelect == NO_TAB_SELECTED) || (!resultViewerTabs.isEnabledAt(tabToSelect))) { if ((tabToSelect == NO_TAB_SELECTED) || (!resultViewerTabs.isEnabledAt(tabToSelect))) {

View File

@ -68,6 +68,7 @@ import org.sleuthkit.autopsy.coreutils.Logger;
* viewers to the actions global context. * viewers to the actions global context.
*/ */
@RetainLocation("editor") @RetainLocation("editor")
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
public final class DataResultTopComponent extends TopComponent implements DataResult, ExplorerManager.Provider { public final class DataResultTopComponent extends TopComponent implements DataResult, ExplorerManager.Provider {
private static final Logger logger = Logger.getLogger(DataResultTopComponent.class.getName()); private static final Logger logger = Logger.getLogger(DataResultTopComponent.class.getName());

View File

@ -77,6 +77,7 @@ import org.sleuthkit.autopsy.datamodel.NodeSelectionInfo;
* ancestor top component's explorer manager at runtime. * ancestor top component's explorer manager at runtime.
*/ */
@ServiceProvider(service = DataResultViewer.class) @ServiceProvider(service = DataResultViewer.class)
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
public final class DataResultViewerTable extends AbstractDataResultViewer { public final class DataResultViewerTable extends AbstractDataResultViewer {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;

View File

@ -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");
@ -52,8 +52,7 @@ import org.sleuthkit.autopsy.coreutils.Logger;
@Messages("CTL_OfflineHelpAction=Offline Autopsy Documentation") @Messages("CTL_OfflineHelpAction=Offline Autopsy Documentation")
public final class OfflineHelpAction implements ActionListener { public final class OfflineHelpAction implements ActionListener {
private URI uri; private static final Logger logger
private static final Logger Logger
= org.sleuthkit.autopsy.coreutils.Logger.getLogger(AboutWindowPanel.class.getName()); = org.sleuthkit.autopsy.coreutils.Logger.getLogger(AboutWindowPanel.class.getName());
@Override @Override
@ -71,6 +70,7 @@ public final class OfflineHelpAction implements ActionListener {
String fileForHelp = ""; String fileForHelp = "";
String indexForHelp = ""; String indexForHelp = "";
String currentDirectory = ""; String currentDirectory = "";
URI uri = null;
try { try {
// Match the form: file:///C:/some/directory/AutopsyXYZ/docs/index.html // Match the form: file:///C:/some/directory/AutopsyXYZ/docs/index.html
@ -79,7 +79,7 @@ public final class OfflineHelpAction implements ActionListener {
currentDirectory = System.getProperty("user.dir").replace("\\", "/").replace(" ", "%20"); //NON-NLS currentDirectory = System.getProperty("user.dir").replace("\\", "/").replace(" ", "%20"); //NON-NLS
uri = new URI(fileForHelp + currentDirectory + indexForHelp); uri = new URI(fileForHelp + currentDirectory + indexForHelp);
} catch (Exception ex) { } catch (Exception ex) {
Logger.log(Level.SEVERE, "Unable to load Offline Documentation: " logger.log(Level.SEVERE, "Unable to load Offline Documentation: "
+ fileForHelp + currentDirectory + indexForHelp, ex); //NON-NLS + fileForHelp + currentDirectory + indexForHelp, ex); //NON-NLS
} }
if (uri != null) { if (uri != null) {
@ -89,7 +89,7 @@ public final class OfflineHelpAction implements ActionListener {
try { try {
desktop.browse(uri); desktop.browse(uri);
} catch (IOException ex) { } catch (IOException ex) {
Logger.log(Level.SEVERE, "Unable to launch the system browser: " logger.log(Level.SEVERE, "Unable to launch the system browser: "
+ fileForHelp + currentDirectory + indexForHelp, ex); //NON-NLS + fileForHelp + currentDirectory + indexForHelp, ex); //NON-NLS
} }
} else { } else {
@ -98,7 +98,7 @@ public final class OfflineHelpAction implements ActionListener {
try { try {
HtmlBrowser.URLDisplayer.getDefault().showURL(uri.toURL()); HtmlBrowser.URLDisplayer.getDefault().showURL(uri.toURL());
} catch (MalformedURLException ex) { } catch (MalformedURLException ex) {
Logger.log(Level.SEVERE, "Unable to launch the built-in browser: " logger.log(Level.SEVERE, "Unable to launch the built-in browser: "
+ fileForHelp + currentDirectory + indexForHelp, ex); //NON-NLS + fileForHelp + currentDirectory + indexForHelp, ex); //NON-NLS
} }
} }

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-17 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");
@ -29,6 +29,7 @@ import org.sleuthkit.autopsy.coreutils.ThreadConfined;
* A dialog that allows the user to choose sort criteria for the thumbnail * A dialog that allows the user to choose sort criteria for the thumbnail
* viewer. * viewer.
*/ */
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
final class SortChooser extends javax.swing.JPanel { final class SortChooser extends javax.swing.JPanel {
/** /**

View File

@ -59,10 +59,11 @@ import javax.imageio.stream.ImageInputStream;
import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.concurrent.BasicThreadFactory; import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.opencv.core.Core;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
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.corelibs.OpenCvLoader;
import org.sleuthkit.autopsy.corelibs.ScalrWrapper; import org.sleuthkit.autopsy.corelibs.ScalrWrapper;
import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector;
import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector.FileTypeDetectorInitException; import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector.FileTypeDetectorInitException;
@ -96,7 +97,7 @@ public class ImageUtils {
private static final List<String> SUPPORTED_IMAGE_EXTENSIONS = new ArrayList<>(); private static final List<String> SUPPORTED_IMAGE_EXTENSIONS = new ArrayList<>();
private static final SortedSet<String> SUPPORTED_IMAGE_MIME_TYPES; private static final SortedSet<String> SUPPORTED_IMAGE_MIME_TYPES;
private static final boolean OPEN_CV_LOADED; private static final boolean FFMPEG_LOADED;
/** /**
* Map from tsk object id to Java File object. Used to get the same File for * Map from tsk object id to Java File object. Used to get the same File for
@ -105,6 +106,8 @@ public class ImageUtils {
* *
* NOTE: Must be cleared when the case is changed. * NOTE: Must be cleared when the case is changed.
*/ */
@Messages({"ImageUtils.ffmpegLoadedError.title=OpenCV FFMpeg",
"ImageUtils.ffmpegLoadedError.msg=OpenCV FFMpeg library failed to load, see log for more details"})
private static final ConcurrentHashMap<Long, File> cacheFileMap = new ConcurrentHashMap<>(); private static final ConcurrentHashMap<Long, File> cacheFileMap = new ConcurrentHashMap<>();
static { static {
@ -117,25 +120,23 @@ public class ImageUtils {
tempImage = null; tempImage = null;
} }
DEFAULT_THUMBNAIL = tempImage; DEFAULT_THUMBNAIL = tempImage;
boolean tempFfmpegLoaded = false;
//load opencv libraries if (OpenCvLoader.isOpenCvLoaded()) {
boolean openCVLoadedTemp;
try { try {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
if (System.getProperty("os.arch").equals("amd64") || System.getProperty("os.arch").equals("x86_64")) { //NON-NLS if (System.getProperty("os.arch").equals("amd64") || System.getProperty("os.arch").equals("x86_64")) { //NON-NLS
System.loadLibrary("opencv_ffmpeg248_64"); //NON-NLS System.loadLibrary("opencv_ffmpeg2413_64"); //NON-NLS
} else { } else {
System.loadLibrary("opencv_ffmpeg248"); //NON-NLS System.loadLibrary("opencv_ffmpeg2413"); //NON-NLS
} }
tempFfmpegLoaded = true;
openCVLoadedTemp = true;
} catch (UnsatisfiedLinkError e) { } catch (UnsatisfiedLinkError e) {
openCVLoadedTemp = false; tempFfmpegLoaded = false;
LOGGER.log(Level.SEVERE, "OpenCV Native code library failed to load", e); //NON-NLS LOGGER.log(Level.SEVERE, Bundle.ImageUtils_ffmpegLoadedError_msg(), e); //NON-NLS
MessageNotifyUtil.Notify.show("Open CV", "OpenCV native library failed to load, see log for more details", MessageNotifyUtil.MessageType.WARNING); MessageNotifyUtil.Notify.show(Bundle.ImageUtils_ffmpegLoadedError_title(), Bundle.ImageUtils_ffmpegLoadedError_msg(), MessageNotifyUtil.MessageType.WARNING);
} }
}
FFMPEG_LOADED = tempFfmpegLoaded;
OPEN_CV_LOADED = openCVLoadedTemp;
SUPPORTED_IMAGE_EXTENSIONS.addAll(Arrays.asList(ImageIO.getReaderFileSuffixes())); SUPPORTED_IMAGE_EXTENSIONS.addAll(Arrays.asList(ImageIO.getReaderFileSuffixes()));
SUPPORTED_IMAGE_EXTENSIONS.add("tec"); // Add JFIF .tec files SUPPORTED_IMAGE_EXTENSIONS.add("tec"); // Add JFIF .tec files
SUPPORTED_IMAGE_EXTENSIONS.removeIf("db"::equals); // remove db files SUPPORTED_IMAGE_EXTENSIONS.removeIf("db"::equals); // remove db files
@ -165,8 +166,8 @@ public class ImageUtils {
/** /**
* Thread/Executor that saves generated thumbnails to disk in the background * Thread/Executor that saves generated thumbnails to disk in the background
*/ */
private static final Executor imageSaver = private static final Executor imageSaver
Executors.newSingleThreadExecutor(new BasicThreadFactory.Builder() = Executors.newSingleThreadExecutor(new BasicThreadFactory.Builder()
.namingPattern("thumbnail-saver-%d").build()); //NON-NLS .namingPattern("thumbnail-saver-%d").build()); //NON-NLS
public static List<String> getSupportedImageExtensions() { public static List<String> getSupportedImageExtensions() {
@ -687,7 +688,7 @@ public class ImageUtils {
//There was no correctly-sized cached thumbnail so make one. //There was no correctly-sized cached thumbnail so make one.
BufferedImage thumbnail = null; BufferedImage thumbnail = null;
if (VideoUtils.isVideoThumbnailSupported(file)) { if (VideoUtils.isVideoThumbnailSupported(file)) {
if (OPEN_CV_LOADED) { if (FFMPEG_LOADED) {
updateMessage(Bundle.GetOrGenerateThumbnailTask_generatingPreviewFor(file.getName())); updateMessage(Bundle.GetOrGenerateThumbnailTask_generatingPreviewFor(file.getName()));
if (isCancelled()) { if (isCancelled()) {
return null; return null;

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2012-2014 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");
@ -51,6 +51,7 @@ import org.sleuthkit.datamodel.TskCoreException;
public class PlatformUtil { public class PlatformUtil {
private static final String PYTHON_MODULES_SUBDIRECTORY = "python_modules"; //NON-NLS private static final String PYTHON_MODULES_SUBDIRECTORY = "python_modules"; //NON-NLS
private static final String CLASSIFIERS_SUBDIRECTORY = "object_detection_classifiers"; //NON-NLS
private static String javaPath = null; private static String javaPath = null;
public static final String OS_NAME_UNKNOWN = NbBundle.getMessage(PlatformUtil.class, "PlatformUtil.nameUnknown"); public static final String OS_NAME_UNKNOWN = NbBundle.getMessage(PlatformUtil.class, "PlatformUtil.nameUnknown");
public static final String OS_VERSION_UNKNOWN = NbBundle.getMessage(PlatformUtil.class, "PlatformUtil.verUnknown"); public static final String OS_VERSION_UNKNOWN = NbBundle.getMessage(PlatformUtil.class, "PlatformUtil.verUnknown");
@ -116,6 +117,15 @@ public class PlatformUtil {
return getUserDirectory().getAbsolutePath() + File.separator + PYTHON_MODULES_SUBDIRECTORY; return getUserDirectory().getAbsolutePath() + File.separator + PYTHON_MODULES_SUBDIRECTORY;
} }
/**
* Get root path where the user's object detection classifiers are stored.
*
* @return Absolute path to the object detection classifiers root directory.
*/
public static String getObjectDetectionClassifierPath() {
return getUserDirectory().getAbsolutePath() + File.separator + CLASSIFIERS_SUBDIRECTORY;
}
/** /**
* get file path to the java executable binary use embedded java if * get file path to the java executable binary use embedded java if
* available, otherwise use system java in PATH no validation is done if * available, otherwise use system java in PATH no validation is done if
@ -311,10 +321,9 @@ public class PlatformUtil {
} }
} }
/** /**
* Attempts to determine whether the JVM is 64-bit or 32-bit. * Attempts to determine whether the JVM is 64-bit or 32-bit. May not be
* May not be completely reliable for non-Windows operating systems. * completely reliable for non-Windows operating systems.
* *
* @return True if the JVM is 64-bit. False otherwise. * @return True if the JVM is 64-bit. False otherwise.
*/ */
@ -322,7 +331,6 @@ public class PlatformUtil {
return (System.getProperty("sun.arch.data.model").equals("64")); return (System.getProperty("sun.arch.data.model").equals("64"));
} }
/** /**
* Get a list of all physical drives attached to the client's machine. Error * Get a list of all physical drives attached to the client's machine. Error
* threshold of 4 non-existent physical drives before giving up. * threshold of 4 non-existent physical drives before giving up.

View File

@ -21,12 +21,14 @@ package org.sleuthkit.autopsy.datamodel;
import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet; import java.util.EnumSet;
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.logging.Level; import java.util.logging.Level;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.swing.Action;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.openide.nodes.Children; import org.openide.nodes.Children;
import org.openide.nodes.Sheet; import org.openide.nodes.Sheet;
@ -36,6 +38,9 @@ import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent; import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent;
import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent; import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent;
import org.sleuthkit.autopsy.centralrepository.AddEditCentralRepoCommentAction;
import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifactUtil;
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbUtil;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import static org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode.AbstractFilePropertyType.*; import static org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode.AbstractFilePropertyType.*;
import static org.sleuthkit.autopsy.datamodel.Bundle.*; import static org.sleuthkit.autopsy.datamodel.Bundle.*;

View File

@ -162,12 +162,12 @@ abstract class AbstractContentChildren<T> extends Keys<T> {
@Override @Override
public AbstractNode visit(DeletedContent dc) { public AbstractNode visit(DeletedContent dc) {
return new DeletedContent.DeletedContentsNode(dc.getSleuthkitCase()); return new DeletedContent.DeletedContentsNode(dc.getSleuthkitCase(), dc.filteringDataSourceObjId());
} }
@Override @Override
public AbstractNode visit(FileSize dc) { public AbstractNode visit(FileSize dc) {
return new FileSize.FileSizeRootNode(dc.getSleuthkitCase()); return new FileSize.FileSizeRootNode(dc.getSleuthkitCase(), dc.filteringDataSourceObjId());
} }
@Override @Override
@ -192,22 +192,27 @@ abstract class AbstractContentChildren<T> extends Keys<T> {
@Override @Override
public AbstractNode visit(Tags tagsNodeKey) { public AbstractNode visit(Tags tagsNodeKey) {
return tagsNodeKey.new RootNode(); return tagsNodeKey.new RootNode(tagsNodeKey.filteringDataSourceObjId());
} }
@Override @Override
public AbstractNode visit(DataSources i) { public AbstractNode visit(DataSources i) {
return new DataSourcesNode(); return new DataSourcesNode(i.filteringDataSourceObjId());
}
@Override
public AbstractNode visit(DataSourceGrouping datasourceGrouping) {
return new DataSourceGroupingNode(datasourceGrouping.getDataSource());
} }
@Override @Override
public AbstractNode visit(Views v) { public AbstractNode visit(Views v) {
return new ViewsNode(v.getSleuthkitCase()); return new ViewsNode(v.getSleuthkitCase(), v.filteringDataSourceObjId());
} }
@Override @Override
public AbstractNode visit(Results r) { public AbstractNode visit(Results results) {
return new ResultsNode(r.getSleuthkitCase()); return new ResultsNode(results.getSleuthkitCase(), results.filteringDataSourceObjId() );
} }
@Override @Override

View File

@ -29,6 +29,8 @@ public interface AutopsyItemVisitor<T> {
T visit(DataSources i); T visit(DataSources i);
T visit(DataSourceGrouping datasourceGrouping);
T visit(Views v); T visit(Views v);
T visit(FileTypesByExtension sf); T visit(FileTypesByExtension sf);
@ -173,6 +175,11 @@ public interface AutopsyItemVisitor<T> {
return defaultVisit(v); return defaultVisit(v);
} }
@Override
public T visit(DataSourceGrouping datasourceGrouping) {
return defaultVisit(datasourceGrouping);
}
@Override @Override
public T visit(Results r) { public T visit(Results r) {
return defaultVisit(r); return defaultVisit(r);

View File

@ -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.datamodel;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.List;
import java.util.logging.Level;
import org.openide.nodes.ChildFactory;
import org.openide.nodes.Node;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.DataSource;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.SleuthkitVisitableItem;
import org.sleuthkit.datamodel.TskCoreException;
/**
* Child factory to create the top level children of the autopsy tree
*
*/
public class AutopsyTreeChildrenFactory extends ChildFactory.Detachable<Object> {
private static final Logger logger = Logger.getLogger(AutopsyTreeChildrenFactory.class.getName());
private final SleuthkitCase tskCase;
/**
* Constructs the child factory
* @param tskCase
*/
public AutopsyTreeChildrenFactory(SleuthkitCase tskCase) {
this.tskCase = tskCase;
}
/**
* Listener for handling DATA_SOURCE_ADDED events.
*/
private final PropertyChangeListener pcl = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
String eventType = evt.getPropertyName();
if (eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) {
refreshChildren();
}
}
};
@Override
protected void addNotify() {
super.addNotify();
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.DATA_SOURCE_ADDED), pcl);
}
@Override
protected void removeNotify() {
super.removeNotify();
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.DATA_SOURCE_ADDED), pcl);
}
/**
* Creates keys for the top level children.
*
* @param list list of keys created
* @return true, indicating that the key list is complete
*/
@Override
protected boolean createKeys(List<Object> list) {
try {
if (UserPreferences.groupItemsInTreeByDatasource()) {
List<DataSource> dataSources = tskCase.getDataSources();
List<DataSourceGrouping> keys = new ArrayList<>();
dataSources.forEach((datasource) -> {
keys.add(new DataSourceGrouping(datasource));
});
list.addAll(keys);
list.add(new Reports());
} else {
List<AutopsyVisitableItem> keys = new ArrayList<>(Arrays.asList(
new DataSources(),
new Views(tskCase),
new Results(tskCase),
new Tags(),
new Reports()));
list.addAll(keys);
}
} catch (TskCoreException tskCoreException) {
logger.log(Level.SEVERE, "Error getting datas sources list from the database.", tskCoreException);
}
return true;
}
/**
* Creates nodes for the top level Key
*
* @param key
*
* @return Node for the key, null if key is unknown.
*/
@Override
protected Node createNodeForKey(Object key) {
if (key instanceof SleuthkitVisitableItem) {
return ((SleuthkitVisitableItem) key).accept(new RootContentChildren.CreateSleuthkitNodeVisitor());
} else if (key instanceof AutopsyVisitableItem) {
return ((AutopsyVisitableItem) key).accept(new RootContentChildren.CreateAutopsyNodeVisitor());
}
else {
logger.log(Level.SEVERE, "Unknown key type ", key.getClass().getName());
return null;
}
}
/**
* Refresh the children
*/
public void refreshChildren() {
refresh(true);
}
}

View File

@ -48,6 +48,8 @@ import org.sleuthkit.autopsy.casemodule.events.BlackBoardArtifactTagAddedEvent;
import org.sleuthkit.autopsy.casemodule.events.BlackBoardArtifactTagDeletedEvent; import org.sleuthkit.autopsy.casemodule.events.BlackBoardArtifactTagDeletedEvent;
import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent; import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent;
import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent; import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent;
import org.sleuthkit.autopsy.centralrepository.AddEditCentralRepoCommentAction;
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbUtil;
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 static org.sleuthkit.autopsy.datamodel.DisplayableItemNode.findLinked; import static org.sleuthkit.autopsy.datamodel.DisplayableItemNode.findLinked;
@ -68,7 +70,7 @@ import org.sleuthkit.datamodel.TskCoreException;
*/ */
public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifact> { public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifact> {
private static final Logger LOGGER = Logger.getLogger(BlackboardArtifactNode.class.getName()); private static final Logger logger = Logger.getLogger(BlackboardArtifactNode.class.getName());
private static final Set<Case.Events> CASE_EVENTS_OF_INTEREST = EnumSet.of(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED, private static final Set<Case.Events> CASE_EVENTS_OF_INTEREST = EnumSet.of(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED,
Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED, Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED,
Case.Events.CONTENT_TAG_ADDED, Case.Events.CONTENT_TAG_ADDED,
@ -217,6 +219,7 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
public Action[] getActions(boolean context) { public Action[] getActions(boolean context) {
List<Action> actionsList = new ArrayList<>(); List<Action> actionsList = new ArrayList<>();
actionsList.addAll(Arrays.asList(super.getActions(context))); actionsList.addAll(Arrays.asList(super.getActions(context)));
AbstractFile file = getLookup().lookup(AbstractFile.class);
//if this artifact has a time stamp add the action to view it in the timeline //if this artifact has a time stamp add the action to view it in the timeline
try { try {
@ -224,7 +227,7 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
actionsList.add(new ViewArtifactInTimelineAction(artifact)); actionsList.add(new ViewArtifactInTimelineAction(artifact));
} }
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
LOGGER.log(Level.SEVERE, MessageFormat.format("Error getting arttribute(s) from blackboard artifact{0}.", artifact.getArtifactID()), ex); //NON-NLS logger.log(Level.SEVERE, MessageFormat.format("Error getting arttribute(s) from blackboard artifact{0}.", artifact.getArtifactID()), ex); //NON-NLS
MessageNotifyUtil.Notify.error(Bundle.BlackboardArtifactNode_getAction_errorTitle(), Bundle.BlackboardArtifactNode_getAction_resultErrorMessage()); MessageNotifyUtil.Notify.error(Bundle.BlackboardArtifactNode_getAction_errorTitle(), Bundle.BlackboardArtifactNode_getAction_resultErrorMessage());
} }
@ -235,12 +238,11 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
actionsList.add(ViewFileInTimelineAction.createViewFileAction(c)); actionsList.add(ViewFileInTimelineAction.createViewFileAction(c));
} }
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
LOGGER.log(Level.SEVERE, MessageFormat.format("Error getting linked file from blackboard artifact{0}.", artifact.getArtifactID()), ex); //NON-NLS logger.log(Level.SEVERE, MessageFormat.format("Error getting linked file from blackboard artifact{0}.", artifact.getArtifactID()), ex); //NON-NLS
MessageNotifyUtil.Notify.error(Bundle.BlackboardArtifactNode_getAction_errorTitle(), Bundle.BlackboardArtifactNode_getAction_linkedFileMessage()); MessageNotifyUtil.Notify.error(Bundle.BlackboardArtifactNode_getAction_errorTitle(), Bundle.BlackboardArtifactNode_getAction_linkedFileMessage());
} }
//if this artifact has associated content, add the action to view the content in the timeline //if the artifact has associated content, add the action to view the content in the timeline
AbstractFile file = getLookup().lookup(AbstractFile.class);
if (null != file) { if (null != file) {
actionsList.add(ViewFileInTimelineAction.createViewSourceFileAction(file)); actionsList.add(ViewFileInTimelineAction.createViewSourceFileAction(file));
} }
@ -391,7 +393,7 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
try { try {
sourcePath = associated.getUniquePath(); sourcePath = associated.getUniquePath();
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
LOGGER.log(Level.WARNING, "Failed to get unique path from: {0}", associated.getName()); //NON-NLS logger.log(Level.WARNING, "Failed to get unique path from: {0}", associated.getName()); //NON-NLS
} }
if (sourcePath.isEmpty() == false) { if (sourcePath.isEmpty() == false) {
@ -439,7 +441,7 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
dataSourceStr = getRootParentName(); dataSourceStr = getRootParentName();
} }
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
LOGGER.log(Level.WARNING, "Failed to get image name from {0}", associated.getName()); //NON-NLS logger.log(Level.WARNING, "Failed to get image name from {0}", associated.getName()); //NON-NLS
} }
if (dataSourceStr.isEmpty() == false) { if (dataSourceStr.isEmpty() == false) {
@ -472,7 +474,7 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
tags.addAll(Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsByArtifact(artifact)); tags.addAll(Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsByArtifact(artifact));
tags.addAll(Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsByContent(associated)); tags.addAll(Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsByContent(associated));
} catch (TskCoreException | NoCurrentCaseException ex) { } catch (TskCoreException | NoCurrentCaseException ex) {
LOGGER.log(Level.SEVERE, "Failed to get tags for artifact " + artifact.getDisplayName(), ex); logger.log(Level.SEVERE, "Failed to get tags for artifact " + artifact.getDisplayName(), ex);
} }
sheetSet.put(new NodeProperty<>("Tags", Bundle.BlackboardArtifactNode_createSheet_tags_displayName(), sheetSet.put(new NodeProperty<>("Tags", Bundle.BlackboardArtifactNode_createSheet_tags_displayName(),
NO_DESCR, tags.stream().map(t -> t.getName().getDisplayName()).collect(Collectors.joining(", ")))); NO_DESCR, tags.stream().map(t -> t.getName().getDisplayName()).collect(Collectors.joining(", "))));
@ -490,7 +492,7 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
parentName = parent.getName(); parentName = parent.getName();
} }
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
LOGGER.log(Level.WARNING, "Failed to get parent name from {0}", associated.getName()); //NON-NLS logger.log(Level.WARNING, "Failed to get parent name from {0}", associated.getName()); //NON-NLS
return ""; return "";
} }
return parentName; return parentName;
@ -551,7 +553,7 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
} }
} }
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
LOGGER.log(Level.SEVERE, "Getting attributes failed", ex); //NON-NLS logger.log(Level.SEVERE, "Getting attributes failed", ex); //NON-NLS
} }
} }
@ -614,7 +616,7 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
return Lookups.fixed(artifact, content); return Lookups.fixed(artifact, content);
} }
} catch (ExecutionException ex) { } catch (ExecutionException ex) {
LOGGER.log(Level.WARNING, "Getting associated content for artifact failed", ex); //NON-NLS logger.log(Level.WARNING, "Getting associated content for artifact failed", ex); //NON-NLS
return Lookups.fixed(artifact); return Lookups.fixed(artifact);
} }
} }

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2013-2016 Basis Technology Corp. * Copyright 2013-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,7 +28,6 @@ import org.openide.nodes.Children;
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.openide.util.lookup.Lookups;
import org.sleuthkit.autopsy.actions.DeleteBlackboardArtifactTagAction;
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.timeline.actions.ViewArtifactInTimelineAction; import org.sleuthkit.autopsy.timeline.actions.ViewArtifactInTimelineAction;
@ -132,8 +131,8 @@ public class BlackboardArtifactTagNode extends DisplayableItemNode {
actions.add(ViewFileInTimelineAction.createViewSourceFileAction(file)); actions.add(ViewFileInTimelineAction.createViewSourceFileAction(file));
} }
actions.add(new ViewTaggedArtifactAction(BlackboardArtifactTagNode_viewSourceArtifact_text(), artifact)); actions.add(new ViewTaggedArtifactAction(BlackboardArtifactTagNode_viewSourceArtifact_text(), artifact));
actions.addAll(DataModelActionsFactory.getActions(tag.getContent(), true)); actions.addAll(DataModelActionsFactory.getActions(tag, true));
actions.add(DeleteBlackboardArtifactTagAction.getInstance());
return actions.toArray(new Action[0]); return actions.toArray(new Action[0]);
} }

View File

@ -56,6 +56,7 @@ DataModelActionsFactory.viewNewWin.text=View in New Window
DataModelActionsFactory.openExtViewer.text=Open in External Viewer DataModelActionsFactory.openExtViewer.text=Open in External Viewer
DataModelActionsFactory.srfFileSameMD5.text=Search for files with the same MD5 hash DataModelActionsFactory.srfFileSameMD5.text=Search for files with the same MD5 hash
DataSourcesNode.name=Data Sources DataSourcesNode.name=Data Sources
DataSourcesNode.group_by_datasource.name=Data Source Files
DataSourcesNode.createSheet.name.name=Name DataSourcesNode.createSheet.name.name=Name
DataSourcesNode.createSheet.name.displayName=Name DataSourcesNode.createSheet.name.displayName=Name
DataSourcesNode.createSheet.name.desc=no description DataSourcesNode.createSheet.name.desc=no description

View File

@ -57,6 +57,7 @@ DataModelActionsFactory.viewNewWin.text=\u65b0\u898f\u30a6\u30a3\u30f3\u30c9\u30
DataModelActionsFactory.openExtViewer.text=\u5916\u90e8\u30d3\u30e5\u30fc\u30a2\u306b\u8868\u793a DataModelActionsFactory.openExtViewer.text=\u5916\u90e8\u30d3\u30e5\u30fc\u30a2\u306b\u8868\u793a
DataModelActionsFactory.srfFileSameMD5.text=\u540c\u3058MD5\u30cf\u30c3\u30b7\u30e5\u3092\u6301\u3064\u30d5\u30a1\u30a4\u30eb\u3092\u691c\u7d22 DataModelActionsFactory.srfFileSameMD5.text=\u540c\u3058MD5\u30cf\u30c3\u30b7\u30e5\u3092\u6301\u3064\u30d5\u30a1\u30a4\u30eb\u3092\u691c\u7d22
DataSourcesNode.name=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9 DataSourcesNode.name=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9
DataSourcesNode.group_by_datasource.name=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb
DataSourcesNode.createSheet.name.name=\u540d\u524d DataSourcesNode.createSheet.name.name=\u540d\u524d
DataSourcesNode.createSheet.name.displayName=\u540d\u524d DataSourcesNode.createSheet.name.displayName=\u540d\u524d
DataSourcesNode.createSheet.name.desc=\u8aac\u660e\u304c\u3042\u308a\u307e\u305b\u3093 DataSourcesNode.createSheet.name.desc=\u8aac\u660e\u304c\u3042\u308a\u307e\u305b\u3093

View File

@ -29,7 +29,6 @@ import org.openide.nodes.Sheet;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
import org.openide.util.lookup.Lookups; import org.openide.util.lookup.Lookups;
import org.sleuthkit.autopsy.actions.DeleteContentTagAction;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.timeline.actions.ViewFileInTimelineAction; import org.sleuthkit.autopsy.timeline.actions.ViewFileInTimelineAction;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
@ -128,8 +127,9 @@ class ContentTagNode extends DisplayableItemNode {
if (file != null) { if (file != null) {
actions.add(ViewFileInTimelineAction.createViewFileAction(file)); actions.add(ViewFileInTimelineAction.createViewFileAction(file));
} }
actions.addAll(DataModelActionsFactory.getActions(tag.getContent(), false));
actions.add(DeleteContentTagAction.getInstance()); actions.addAll(DataModelActionsFactory.getActions(tag, false));
return actions.toArray(new Action[actions.size()]); return actions.toArray(new Action[actions.size()]);
} }

View File

@ -28,8 +28,12 @@ import org.openide.util.NbBundle;
import org.openide.util.Utilities; import org.openide.util.Utilities;
import org.sleuthkit.autopsy.actions.AddBlackboardArtifactTagAction; import org.sleuthkit.autopsy.actions.AddBlackboardArtifactTagAction;
import org.sleuthkit.autopsy.actions.AddContentTagAction; import org.sleuthkit.autopsy.actions.AddContentTagAction;
import org.sleuthkit.autopsy.actions.DeleteBlackboardArtifactTagAction;
import org.sleuthkit.autopsy.actions.DeleteContentTagAction;
import org.sleuthkit.autopsy.actions.DeleteFileBlackboardArtifactTagAction; import org.sleuthkit.autopsy.actions.DeleteFileBlackboardArtifactTagAction;
import org.sleuthkit.autopsy.actions.DeleteFileContentTagAction; import org.sleuthkit.autopsy.actions.DeleteFileContentTagAction;
import org.sleuthkit.autopsy.actions.ReplaceBlackboardArtifactTagAction;
import org.sleuthkit.autopsy.actions.ReplaceContentTagAction;
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint; import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
import org.sleuthkit.autopsy.datamodel.Reports.ReportNode; import org.sleuthkit.autopsy.datamodel.Reports.ReportNode;
import org.sleuthkit.autopsy.directorytree.ExternalViewerAction; import org.sleuthkit.autopsy.directorytree.ExternalViewerAction;
@ -39,7 +43,9 @@ import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
import org.sleuthkit.autopsy.directorytree.ViewContextAction; import org.sleuthkit.autopsy.directorytree.ViewContextAction;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardArtifactTag;
import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.ContentTag;
import org.sleuthkit.datamodel.DerivedFile; import org.sleuthkit.datamodel.DerivedFile;
import org.sleuthkit.datamodel.Directory; import org.sleuthkit.datamodel.Directory;
import org.sleuthkit.datamodel.File; import org.sleuthkit.datamodel.File;
@ -351,6 +357,80 @@ public class DataModelActionsFactory {
return actionsList; return actionsList;
} }
public static List<Action> getActions(ContentTag contentTag, boolean isArtifactSource) {
List<Action> actionsList = new ArrayList<>();
actionsList.add(new ViewContextAction((isArtifactSource ? VIEW_SOURCE_FILE_IN_DIR : VIEW_FILE_IN_DIR), contentTag.getContent()));
final ContentTagNode tagNode = new ContentTagNode(contentTag);
actionsList.add(null); // creates a menu separator
actionsList.add(new NewWindowViewAction(VIEW_IN_NEW_WINDOW, tagNode));
actionsList.add(new ExternalViewerAction(OPEN_IN_EXTERNAL_VIEWER, tagNode));
actionsList.add(null); // creates a menu separator
actionsList.add(ExtractAction.getInstance());
actionsList.add(new HashSearchAction(SEARCH_FOR_FILES_SAME_MD5, tagNode));
actionsList.add(null); // creates a menu separator
actionsList.add(AddContentTagAction.getInstance());
if (isArtifactSource) {
actionsList.add(AddBlackboardArtifactTagAction.getInstance());
}
final Collection<AbstractFile> selectedFilesList =
new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class));
if(selectedFilesList.size() == 1) {
actionsList.add(DeleteFileContentTagAction.getInstance());
}
if(isArtifactSource) {
final Collection<BlackboardArtifact> selectedArtifactsList =
new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class));
if(selectedArtifactsList.size() == 1) {
actionsList.add(DeleteFileBlackboardArtifactTagAction.getInstance());
}
}
actionsList.add(DeleteContentTagAction.getInstance());
actionsList.add(ReplaceContentTagAction.getInstance());
actionsList.addAll(ContextMenuExtensionPoint.getActions());
return actionsList;
}
public static List<Action> getActions(BlackboardArtifactTag artifactTag, boolean isArtifactSource) {
List<Action> actionsList = new ArrayList<>();
actionsList.add(new ViewContextAction((isArtifactSource ? VIEW_SOURCE_FILE_IN_DIR : VIEW_FILE_IN_DIR), artifactTag.getContent()));
final BlackboardArtifactTagNode tagNode = new BlackboardArtifactTagNode(artifactTag);
actionsList.add(null); // creates a menu separator
actionsList.add(new NewWindowViewAction(VIEW_IN_NEW_WINDOW, tagNode));
actionsList.add(new ExternalViewerAction(OPEN_IN_EXTERNAL_VIEWER, tagNode));
actionsList.add(null); // creates a menu separator
actionsList.add(ExtractAction.getInstance());
actionsList.add(new HashSearchAction(SEARCH_FOR_FILES_SAME_MD5, tagNode));
actionsList.add(null); // creates a menu separator
actionsList.add(AddContentTagAction.getInstance());
if (isArtifactSource) {
actionsList.add(AddBlackboardArtifactTagAction.getInstance());
}
final Collection<AbstractFile> selectedFilesList =
new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class));
if(selectedFilesList.size() == 1) {
actionsList.add(DeleteFileContentTagAction.getInstance());
}
if(isArtifactSource) {
final Collection<BlackboardArtifact> selectedArtifactsList =
new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class));
if(selectedArtifactsList.size() == 1) {
actionsList.add(DeleteFileBlackboardArtifactTagAction.getInstance());
}
}
actionsList.add(DeleteBlackboardArtifactTagAction.getInstance());
actionsList.add(ReplaceBlackboardArtifactTagAction.getInstance());
actionsList.addAll(ContextMenuExtensionPoint.getActions());
return actionsList;
}
public static List<Action> getActions(Content content, boolean isArtifactSource) { public static List<Action> getActions(Content content, boolean isArtifactSource) {
if (content instanceof File) { if (content instanceof File) {
return getActions((File) content, isArtifactSource); return getActions((File) content, isArtifactSource);

View File

@ -0,0 +1,45 @@
/*
* 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.datamodel;
import org.sleuthkit.datamodel.DataSource;
/**
* A top level UI grouping of Files, Views, Results, Tags
* for 'Group by Data Source' view of the tree.
*
*/
public class DataSourceGrouping implements AutopsyVisitableItem {
private final DataSource dataSource;
public DataSourceGrouping(DataSource dataSource) {
this.dataSource = dataSource;
}
DataSource getDataSource() {
return this.dataSource;
}
@Override
public <T> T accept(AutopsyItemVisitor<T> visitor) {
return visitor.visit(this);
}
}

View File

@ -0,0 +1,99 @@
/*
* 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.datamodel;
import java.util.Arrays;
import java.util.Collections;
import java.util.Optional;
import java.util.logging.Level;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.DataSource;
import org.sleuthkit.datamodel.Image;
import org.sleuthkit.datamodel.LocalFilesDataSource;
/**
* Data source grouping node - an optional grouping node in the data tree view
*
*/
class DataSourceGroupingNode extends DisplayableItemNode {
private static final Logger logger = Logger.getLogger(DataSourceGroupingNode.class.getName());
/**
* Creates a data source grouping node for the given data source.
*
* @param dataSource specifies the data source
*/
DataSourceGroupingNode(DataSource dataSource) {
super (Optional.ofNullable(createDSGroupingNodeChildren(dataSource))
.orElse(new RootContentChildren(Arrays.asList(Collections.EMPTY_LIST))));
if (dataSource instanceof Image) {
Image image = (Image) dataSource;
super.setName(image.getName());
super.setDisplayName(image.getName());
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/image.png");
} else if (dataSource instanceof LocalFilesDataSource) {
LocalFilesDataSource localFilesDataSource = (LocalFilesDataSource) dataSource;
super.setName(localFilesDataSource.getName());
super.setDisplayName(localFilesDataSource.getName());
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/fileset-icon-16.png");
}
}
@Override
public boolean isLeafTypeNode() {
return false;
}
private static RootContentChildren createDSGroupingNodeChildren(DataSource dataSource) {
long dsObjId = dataSource.getId();
try {
return new RootContentChildren(Arrays.asList(
new DataSources(dsObjId),
new Views(Case.getCurrentCaseThrows().getSleuthkitCase(), dsObjId),
new Results(Case.getCurrentCaseThrows().getSleuthkitCase(), dsObjId),
new Tags(dsObjId) )
);
} catch (NoCurrentCaseException ex) {
logger.log(Level.SEVERE, "Error getting open case.", ex); //NON-NLS
return null;
}
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
public String getItemType() {
return getClass().getName();
}
}

View File

@ -23,7 +23,18 @@ package org.sleuthkit.autopsy.datamodel;
*/ */
public class DataSources implements AutopsyVisitableItem { public class DataSources implements AutopsyVisitableItem {
private final long datasourceObjId;
public DataSources() { public DataSources() {
this(0);
}
public DataSources(long datasourceObjId) {
this.datasourceObjId = datasourceObjId;
}
long filteringDataSourceObjId() {
return this.datasourceObjId;
} }
@Override @Override

View File

@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.datamodel;
import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.List; import java.util.List;
@ -33,6 +34,7 @@ import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskDataException;
/** /**
* Nodes for the images * Nodes for the images
@ -40,22 +42,27 @@ import org.sleuthkit.datamodel.TskCoreException;
public class DataSourcesNode extends DisplayableItemNode { public class DataSourcesNode extends DisplayableItemNode {
public static final String NAME = NbBundle.getMessage(DataSourcesNode.class, "DataSourcesNode.name"); public static final String NAME = NbBundle.getMessage(DataSourcesNode.class, "DataSourcesNode.name");
private final String displayName;
// NOTE: The images passed in via argument will be ignored. // NOTE: The images passed in via argument will be ignored.
@Deprecated @Deprecated
public DataSourcesNode(List<Content> images) { public DataSourcesNode(List<Content> images) {
super(new DataSourcesNodeChildren(), Lookups.singleton(NAME)); this(0);
init();
} }
public DataSourcesNode() { public DataSourcesNode() {
super(new DataSourcesNodeChildren(), Lookups.singleton(NAME)); this(0);
}
public DataSourcesNode(long dsObjId) {
super(new DataSourcesNodeChildren(dsObjId), Lookups.singleton(NAME));
displayName = (dsObjId > 0) ? NbBundle.getMessage(DataSourcesNode.class, "DataSourcesNode.group_by_datasource.name") : NAME;
init(); init();
} }
private void init() { private void init() {
setName(NAME); setName(NAME);
setDisplayName(NAME); setDisplayName(displayName);
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/image.png"); //NON-NLS this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/image.png"); //NON-NLS
} }
@ -70,12 +77,18 @@ public class DataSourcesNode extends DisplayableItemNode {
public static class DataSourcesNodeChildren extends AbstractContentChildren<Content> { public static class DataSourcesNodeChildren extends AbstractContentChildren<Content> {
private static final Logger logger = Logger.getLogger(DataSourcesNodeChildren.class.getName()); private static final Logger logger = Logger.getLogger(DataSourcesNodeChildren.class.getName());
private final long datasourceObjId;
List<Content> currentKeys; List<Content> currentKeys;
public DataSourcesNodeChildren() { public DataSourcesNodeChildren() {
this(0);
}
public DataSourcesNodeChildren(long dsObjId) {
super(); super();
this.currentKeys = new ArrayList<>(); this.currentKeys = new ArrayList<>();
this.datasourceObjId = dsObjId;
} }
private final PropertyChangeListener pcl = new PropertyChangeListener() { private final PropertyChangeListener pcl = new PropertyChangeListener() {
@ -103,9 +116,15 @@ public class DataSourcesNode extends DisplayableItemNode {
private void reloadKeys() { private void reloadKeys() {
try { try {
if (datasourceObjId == 0) {
currentKeys = Case.getCurrentCaseThrows().getDataSources(); currentKeys = Case.getCurrentCaseThrows().getDataSources();
}
else {
Content content = Case.getCurrentCaseThrows().getSleuthkitCase().getDataSource(datasourceObjId);
currentKeys = new ArrayList<>(Arrays.asList(content));
}
setKeys(currentKeys); setKeys(currentKeys);
} catch (TskCoreException | NoCurrentCaseException ex) { } catch (TskCoreException | NoCurrentCaseException | TskDataException ex) {
logger.log(Level.SEVERE, "Error getting data sources: {0}", ex.getMessage()); // NON-NLS logger.log(Level.SEVERE, "Error getting data sources: {0}", ex.getMessage()); // NON-NLS
setKeys(Collections.<Content>emptySet()); setKeys(Collections.<Content>emptySet());
} }

View File

@ -61,6 +61,7 @@ import org.sleuthkit.datamodel.TskData;
public class DeletedContent implements AutopsyVisitableItem { public class DeletedContent implements AutopsyVisitableItem {
private SleuthkitCase skCase; private SleuthkitCase skCase;
private final long datasourceObjId;
@NbBundle.Messages({"DeletedContent.fsDelFilter.text=File System", @NbBundle.Messages({"DeletedContent.fsDelFilter.text=File System",
"DeletedContent.allDelFilter.text=All"}) "DeletedContent.allDelFilter.text=All"})
@ -101,7 +102,16 @@ public class DeletedContent implements AutopsyVisitableItem {
} }
public DeletedContent(SleuthkitCase skCase) { public DeletedContent(SleuthkitCase skCase) {
this(skCase, 0);
}
public DeletedContent(SleuthkitCase skCase, long dsObjId) {
this.skCase = skCase; this.skCase = skCase;
this.datasourceObjId = dsObjId;
}
long filteringDataSourceObjId() {
return this.datasourceObjId;
} }
@Override @Override
@ -118,8 +128,8 @@ public class DeletedContent implements AutopsyVisitableItem {
@NbBundle.Messages("DeletedContent.deletedContentsNode.name=Deleted Files") @NbBundle.Messages("DeletedContent.deletedContentsNode.name=Deleted Files")
private static final String NAME = Bundle.DeletedContent_deletedContentsNode_name(); private static final String NAME = Bundle.DeletedContent_deletedContentsNode_name();
DeletedContentsNode(SleuthkitCase skCase) { DeletedContentsNode(SleuthkitCase skCase, long datasourceObjId) {
super(Children.create(new DeletedContentsChildren(skCase), true), Lookups.singleton(NAME)); super(Children.create(new DeletedContentsChildren(skCase, datasourceObjId), true), Lookups.singleton(NAME));
super.setName(NAME); super.setName(NAME);
super.setDisplayName(NAME); super.setDisplayName(NAME);
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-icon-deleted.png"); //NON-NLS this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-icon-deleted.png"); //NON-NLS
@ -164,11 +174,13 @@ public class DeletedContent implements AutopsyVisitableItem {
private SleuthkitCase skCase; private SleuthkitCase skCase;
private Observable notifier; private Observable notifier;
private final long datasourceObjId;
// true if we have already told user that not all files will be shown // true if we have already told user that not all files will be shown
private static volatile boolean maxFilesDialogShown = false; private static volatile boolean maxFilesDialogShown = false;
public DeletedContentsChildren(SleuthkitCase skCase) { public DeletedContentsChildren(SleuthkitCase skCase, long dsObjId) {
this.skCase = skCase; this.skCase = skCase;
this.datasourceObjId = dsObjId;
this.notifier = new DeletedContentsChildrenObservable(); this.notifier = new DeletedContentsChildrenObservable();
} }
@ -257,24 +269,27 @@ public class DeletedContent implements AutopsyVisitableItem {
@Override @Override
protected Node createNodeForKey(DeletedContent.DeletedContentFilter key) { protected Node createNodeForKey(DeletedContent.DeletedContentFilter key) {
return new DeletedContentNode(skCase, key, notifier); return new DeletedContentNode(skCase, key, notifier, datasourceObjId);
} }
public class DeletedContentNode extends DisplayableItemNode { public class DeletedContentNode extends DisplayableItemNode {
private final DeletedContent.DeletedContentFilter filter; private final DeletedContent.DeletedContentFilter filter;
private final long datasourceObjId;
// Use version that has observer for updates // Use version that has observer for updates
@Deprecated @Deprecated
DeletedContentNode(SleuthkitCase skCase, DeletedContent.DeletedContentFilter filter) { DeletedContentNode(SleuthkitCase skCase, DeletedContent.DeletedContentFilter filter, long dsObjId) {
super(Children.create(new DeletedContentChildren(filter, skCase, null), true), Lookups.singleton(filter.getDisplayName())); super(Children.create(new DeletedContentChildren(filter, skCase, null, dsObjId ), true), Lookups.singleton(filter.getDisplayName()));
this.filter = filter; this.filter = filter;
this.datasourceObjId = dsObjId;
init(); init();
} }
DeletedContentNode(SleuthkitCase skCase, DeletedContent.DeletedContentFilter filter, Observable o) { DeletedContentNode(SleuthkitCase skCase, DeletedContent.DeletedContentFilter filter, Observable o, long dsObjId) {
super(Children.create(new DeletedContentChildren(filter, skCase, o), true), Lookups.singleton(filter.getDisplayName())); super(Children.create(new DeletedContentChildren(filter, skCase, o, dsObjId), true), Lookups.singleton(filter.getDisplayName()));
this.filter = filter; this.filter = filter;
this.datasourceObjId = dsObjId;
init(); init();
o.addObserver(new DeletedContentNodeObserver()); o.addObserver(new DeletedContentNodeObserver());
} }
@ -299,7 +314,7 @@ public class DeletedContent implements AutopsyVisitableItem {
private void updateDisplayName() { private void updateDisplayName() {
//get count of children without preloading all children nodes //get count of children without preloading all children nodes
final long count = DeletedContentChildren.calculateItems(skCase, filter); final long count = DeletedContentChildren.calculateItems(skCase, filter, datasourceObjId);
//final long count = getChildren().getNodesCount(true); //final long count = getChildren().getNodesCount(true);
super.setDisplayName(filter.getDisplayName() + " (" + count + ")"); super.setDisplayName(filter.getDisplayName() + " (" + count + ")");
} }
@ -351,11 +366,13 @@ public class DeletedContent implements AutopsyVisitableItem {
private static final Logger logger = Logger.getLogger(DeletedContentChildren.class.getName()); private static final Logger logger = Logger.getLogger(DeletedContentChildren.class.getName());
private static final int MAX_OBJECTS = 10001; private static final int MAX_OBJECTS = 10001;
private final Observable notifier; private final Observable notifier;
private final long datasourceObjId;
DeletedContentChildren(DeletedContent.DeletedContentFilter filter, SleuthkitCase skCase, Observable o) { DeletedContentChildren(DeletedContent.DeletedContentFilter filter, SleuthkitCase skCase, Observable o, long datasourceObjId) {
this.skCase = skCase; this.skCase = skCase;
this.filter = filter; this.filter = filter;
this.notifier = o; this.notifier = o;
this.datasourceObjId = datasourceObjId;
} }
private final Observer observer = new DeletedContentChildrenObserver(); private final Observer observer = new DeletedContentChildrenObserver();
@ -405,7 +422,7 @@ public class DeletedContent implements AutopsyVisitableItem {
return true; return true;
} }
static private String makeQuery(DeletedContent.DeletedContentFilter filter) { static private String makeQuery(DeletedContent.DeletedContentFilter filter, long filteringDSObjId) {
String query = ""; String query = "";
switch (filter) { switch (filter) {
case FS_DELETED_FILTER: case FS_DELETED_FILTER:
@ -443,6 +460,10 @@ public class DeletedContent implements AutopsyVisitableItem {
+ " OR known IS NULL)"; //NON-NLS + " OR known IS NULL)"; //NON-NLS
} }
if (UserPreferences.groupItemsInTreeByDatasource()) {
query += " AND data_source_obj_id = " + filteringDSObjId;
}
query += " LIMIT " + MAX_OBJECTS; //NON-NLS query += " LIMIT " + MAX_OBJECTS; //NON-NLS
return query; return query;
} }
@ -450,7 +471,7 @@ public class DeletedContent implements AutopsyVisitableItem {
private List<AbstractFile> runFsQuery() { private List<AbstractFile> runFsQuery() {
List<AbstractFile> ret = new ArrayList<>(); List<AbstractFile> ret = new ArrayList<>();
String query = makeQuery(filter); String query = makeQuery(filter, datasourceObjId);
try { try {
ret = skCase.findAllFilesWhere(query); ret = skCase.findAllFilesWhere(query);
} catch (TskCoreException e) { } catch (TskCoreException e) {
@ -469,9 +490,9 @@ public class DeletedContent implements AutopsyVisitableItem {
* *
* @return * @return
*/ */
static long calculateItems(SleuthkitCase sleuthkitCase, DeletedContent.DeletedContentFilter filter) { static long calculateItems(SleuthkitCase sleuthkitCase, DeletedContent.DeletedContentFilter filter, long datasourceObjId) {
try { try {
return sleuthkitCase.countFilesWhere(makeQuery(filter)); return sleuthkitCase.countFilesWhere(makeQuery(filter, datasourceObjId));
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error getting deleted files search view count", ex); //NON-NLS logger.log(Level.SEVERE, "Error getting deleted files search view count", ex); //NON-NLS
return 0; return 0;

View File

@ -61,6 +61,8 @@ public interface DisplayableItemNodeVisitor<T> {
*/ */
T visit(ViewsNode vn); T visit(ViewsNode vn);
T visit(DataSourceGroupingNode dataSourceGroupingNode);
T visit(org.sleuthkit.autopsy.datamodel.FileTypesByExtension.FileExtensionNode fsfn); T visit(org.sleuthkit.autopsy.datamodel.FileTypesByExtension.FileExtensionNode fsfn);
T visit(DeletedContentNode dcn); T visit(DeletedContentNode dcn);
@ -336,6 +338,11 @@ public interface DisplayableItemNodeVisitor<T> {
return defaultVisit(vn); return defaultVisit(vn);
} }
@Override
public T visit(DataSourceGroupingNode dataSourceGroupingNode) {
return defaultVisit(dataSourceGroupingNode);
}
@Override @Override
public T visit(ResultsNode rn) { public T visit(ResultsNode rn) {
return defaultVisit(rn); return defaultVisit(rn);

View File

@ -40,6 +40,7 @@ import org.openide.util.NbBundle;
import org.openide.util.lookup.Lookups; 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.core.UserPreferences;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.autopsy.ingest.ModuleDataEvent; import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
@ -86,10 +87,29 @@ public class EmailExtracted implements AutopsyVisitableItem {
} }
private SleuthkitCase skCase; private SleuthkitCase skCase;
private final EmailResults emailResults; private final EmailResults emailResults;
private final long datasourceObjId;
/**
* Constructor
*
* @param skCase Case DB
*/
public EmailExtracted(SleuthkitCase skCase) { public EmailExtracted(SleuthkitCase skCase) {
this(skCase, 0);
}
/**
* Constructor
*
* @param skCase Case DB
* @param objId Object id of the data source
*
*/
public EmailExtracted(SleuthkitCase skCase, long objId) {
this.skCase = skCase; this.skCase = skCase;
this.datasourceObjId = objId;
emailResults = new EmailResults(); emailResults = new EmailResults();
} }
@ -141,6 +161,9 @@ public class EmailExtracted implements AutopsyVisitableItem {
+ "attribute_type_id=" + pathAttrId //NON-NLS + "attribute_type_id=" + pathAttrId //NON-NLS
+ " AND blackboard_attributes.artifact_id=blackboard_artifacts.artifact_id" //NON-NLS + " AND blackboard_attributes.artifact_id=blackboard_artifacts.artifact_id" //NON-NLS
+ " AND blackboard_artifacts.artifact_type_id=" + artId; //NON-NLS + " AND blackboard_artifacts.artifact_type_id=" + artId; //NON-NLS
if (UserPreferences.groupItemsInTreeByDatasource()) {
query += " AND blackboard_artifacts.data_source_obj_id = " + datasourceObjId;
}
try (CaseDbQuery dbQuery = skCase.executeQuery(query)) { try (CaseDbQuery dbQuery = skCase.executeQuery(query)) {
ResultSet resultSet = dbQuery.getResultSet(); ResultSet resultSet = dbQuery.getResultSet();

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