mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-12 07:56:16 +00:00
Merge branch 'develop' of github.com:sleuthkit/autopsy into 3701_service
This commit is contained in:
commit
4f6a2f3500
@ -21,11 +21,6 @@
|
||||
</target>
|
||||
|
||||
<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 todir="${basedir}/release/photorec_exec" >
|
||||
<fileset dir="${thirdparty.dir}/photorec_exec"/>
|
||||
@ -89,17 +84,17 @@
|
||||
|
||||
<target name="getTestDataFiles">
|
||||
<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=1JACMDyH4y54ypGzFWl82ZzMQf3qbrioP" dest="${test-input}/encryption_detection_bitlocker_test.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=0BxdBkzm5VKGNT0dGY0dqcHVsU3M" dest="${test-input}/filter_test1.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=1BrSiUQ1fzxFS9vIaK4mYKX6qIVp9kRWT" dest="${test-input}/password_detection_test.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=1O5D09fFCFpXZqw0uLEs8kVLtfYTxqXAd" dest="${test-input}/commonfiles_image1_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=1OdwyJ2lru55ZPdvwzj3pq6sXIys27i4x" dest="${test-input}/commonfiles_image3_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=1dLYGctuvRQMmnzfXPppTM_9gB49eLc_g" dest="${test-input}/EmbeddedIM_img1_v1.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}/SqlCipherDetection_img1_v1.vhd" 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}/IngestFilters_local1_v1.zip" 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}/VeracryptDetection_img1_v1.vhd" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=1mr9waEDG5H8GBBn_yXwMUQ6senwC1goL" dest="${test-input}/CommonFiles_img1_v1.vhd" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=1-vmbmAAb2HBLbf58GpAA97ozGUFiYHbN" dest="${test-input}/CommonFiles_img2_v1.vhd" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=1ghDjm0NhI3ShMQ38E-4o7XrGeexpjdJb" dest="${test-input}/CommonFiles_img3_v1.vhd" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=1SJYJFjiumKEtQmeMPsQ6G3xmABarbKm_" dest="${test-input}/CommonFiles_img4_v1.vhd" skipexisting="true"/>
|
||||
</target>
|
||||
|
||||
<target name="get-deps" depends="init-ivy,getTSKJars,get-thirdparty-dependencies,get-InternalPythonModules, download-binlist,getTestDataFiles">
|
||||
|
@ -3,7 +3,7 @@ file.reference.c3p0-0.9.5.jar=release/modules/ext/c3p0-0.9.5.jar
|
||||
file.reference.commons-compress-1.14.jar=release/modules/ext/commons-compress-1.14.jar
|
||||
file.reference.commons-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.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.jar=release/modules/ext/jdom-2.0.5.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.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.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.sevenzipjbinding-AllPlatforms.jar=release/modules/ext/sevenzipjbinding-AllPlatforms.jar
|
||||
file.reference.sevenzipjbinding.jar=release/modules/ext/sevenzipjbinding.jar
|
||||
|
@ -339,6 +339,10 @@
|
||||
<package>org.sleuthkit.autopsy.report</package>
|
||||
<package>org.sleuthkit.datamodel</package>
|
||||
</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>
|
||||
<runtime-relative-path>ext/zookeeper-3.4.6.jar</runtime-relative-path>
|
||||
<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>
|
||||
</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>
|
||||
<runtime-relative-path>ext/opencv-248.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/opencv-248.jar</binary-origin>
|
||||
<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/curator-framework-2.8.0.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/curator-framework-2.8.0.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/commons-dbcp2-2.1.1.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/commons-dbcp2-2.1.1.jar</binary-origin>
|
||||
</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>
|
||||
<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/commons-compress-1.14.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/commons-compress-1.14.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/commons-dbcp2-2.1.1.jar</runtime-relative-path>
|
||||
<binary-origin>release\modules\ext\commons-dbcp2-2.1.1.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/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>
|
||||
<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>
|
||||
@ -387,6 +391,14 @@
|
||||
<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>
|
||||
</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>
|
||||
<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>
|
||||
@ -399,6 +411,10 @@
|
||||
<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>
|
||||
</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>
|
||||
<runtime-relative-path>ext/tika-core-1.17.jar</runtime-relative-path>
|
||||
<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>
|
||||
<binary-origin>release/modules/ext/curator-client-2.8.0.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/bcprov-jdk15on-1.54.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/bcprov-jdk15on-1.54.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/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>
|
||||
<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>
|
||||
</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>
|
||||
<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>
|
||||
</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/sqlite-jdbc-3.8.11.jar</runtime-relative-path>
|
||||
<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>
|
||||
<binary-origin>release/modules/ext/dd-plist-1.20.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/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/sevenzipjbinding-AllPlatforms.jar</runtime-relative-path>
|
||||
<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>
|
||||
<binary-origin>release\modules\ext\commons-pool2-2.4.2.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/jsoup-1.10.3.jar</runtime-relative-path>
|
||||
<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>
|
||||
<binary-origin>release/modules/ext/jdom-2.0.5-contrib.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>
|
||||
<runtime-relative-path>ext/c3p0-0.9.5.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/c3p0-0.9.5.jar</binary-origin>
|
||||
|
@ -37,8 +37,8 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
* Instances of this Action allow users to apply tags to blackboard artifacts.
|
||||
*/
|
||||
@NbBundle.Messages({
|
||||
"AddBlackboardArtifactTagAction.singularTagResult=Tag Result",
|
||||
"AddBlackboardArtifactTagAction.pluralTagResult=Tag Results",
|
||||
"AddBlackboardArtifactTagAction.singularTagResult=Add Result Tag",
|
||||
"AddBlackboardArtifactTagAction.pluralTagResult=Add Result Tags",
|
||||
"# {0} - artifactName",
|
||||
"AddBlackboardArtifactTagAction.unableToTag.msg=Unable to tag {0}.",
|
||||
"AddBlackboardArtifactTagAction.taggingErr=Tagging Error"
|
||||
|
@ -38,8 +38,8 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
* Instances of this Action allow users to apply tags to content.
|
||||
*/
|
||||
@NbBundle.Messages({
|
||||
"AddContentTagAction.singularTagFile=Tag File",
|
||||
"AddContentTagAction.pluralTagFile=Tag Files",
|
||||
"AddContentTagAction.singularTagFile=Add File Tag",
|
||||
"AddContentTagAction.pluralTagFile=Add File Tags",
|
||||
"# {0} - fileName",
|
||||
"AddContentTagAction.unableToTag.msg=Unable to tag {0}, not a regular file.",
|
||||
"AddContentTagAction.cannotApplyTagErr=Cannot Apply Tag",
|
||||
|
@ -19,6 +19,8 @@
|
||||
package org.sleuthkit.autopsy.actions;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.logging.Level;
|
||||
@ -92,6 +94,7 @@ abstract class AddTagAction extends AbstractAction implements Presenter.Popup {
|
||||
|
||||
// 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());
|
||||
@ -101,6 +104,7 @@ abstract class AddTagAction extends AbstractAction implements Presenter.Popup {
|
||||
|
||||
// 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.
|
||||
List<JMenuItem> standardTagMenuitems = new ArrayList<>();
|
||||
if (null != tagNamesMap && !tagNamesMap.isEmpty()) {
|
||||
for (Map.Entry<String, TagName> entry : tagNamesMap.entrySet()) {
|
||||
String tagDisplayName = entry.getKey();
|
||||
@ -114,15 +118,26 @@ abstract class AddTagAction extends AbstractAction implements Presenter.Popup {
|
||||
tagNameItem.addActionListener((ActionEvent e) -> {
|
||||
getAndAddTag(entry.getKey(), entry.getValue(), NO_COMMENT);
|
||||
});
|
||||
|
||||
add(tagNameItem);
|
||||
|
||||
// Show custom tags before predefined tags in the menu
|
||||
if (standardTagNames.contains(tagDisplayName)) {
|
||||
standardTagMenuitems.add(tagNameItem);
|
||||
} else {
|
||||
add(tagNameItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (getItemCount() > 0) {
|
||||
addSeparator();
|
||||
}
|
||||
|
||||
|
||||
standardTagMenuitems.forEach((menuItem) -> {
|
||||
add(menuItem);
|
||||
});
|
||||
|
||||
addSeparator();
|
||||
|
||||
// Create a "Choose Tag and Comment..." menu item. Selecting this item initiates
|
||||
// a dialog that can be used to create or select a tag name with an
|
||||
// optional comment and adds a tag with the resulting name.
|
||||
|
@ -20,7 +20,7 @@ AddTagAction.newTag=New Tag...
|
||||
AddTagAction.tagAndComment=Tag and Comment...
|
||||
AddBookmarkTagAction.bookmark.text=Bookmark
|
||||
GetTagNameAndCommentDialog.noTags=No Tags
|
||||
GetTagNameAndCommentDialog.createTag=Create Tag
|
||||
GetTagNameAndCommentDialog.selectTag=Select Tag
|
||||
GetTagNameAndCommentDialog.cancelName=cancel
|
||||
GetTagNameDialog.createTag=Create Tag
|
||||
GetTagNameDialog.cancelName=Cancel
|
||||
|
@ -23,7 +23,7 @@ AddTagAction.noTags=\u30bf\u30b0\u7121\u3057
|
||||
AddTagAction.newTag=\u65b0\u898f\u30bf\u30b0\u2026
|
||||
AddTagAction.tagAndComment=\u30bf\u30b0\u3068\u30b3\u30e1\u30f3\u30c8\u3092\u8ffd\u52a0\u2026
|
||||
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
|
||||
GetTagNameDialog.createTag=\u30bf\u30b0\u3092\u4f5c\u6210
|
||||
GetTagNameDialog.cancelName=\u30ad\u30e3\u30f3\u30bb\u30eb
|
||||
|
@ -38,7 +38,7 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
* artifacts.
|
||||
*/
|
||||
@NbBundle.Messages({
|
||||
"DeleteBlackboardArtifactTagAction.deleteTag=Delete Tag",
|
||||
"DeleteBlackboardArtifactTagAction.deleteTag=Remove Selected Tag(s)",
|
||||
"# {0} - tagName",
|
||||
"DeleteBlackboardArtifactTagAction.unableToDelTag.msg=Unable to delete tag {0}.",
|
||||
"DeleteBlackboardArtifactTagAction.tagDelErr=Tag Deletion Error"
|
||||
|
@ -37,7 +37,7 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
* Instances of this Action allow users to delete tags applied to content.
|
||||
*/
|
||||
@NbBundle.Messages({
|
||||
"DeleteContentTagAction.deleteTag=Delete Tag",
|
||||
"DeleteContentTagAction.deleteTag=Remove Selected Tag(s)",
|
||||
"# {0} - tagName",
|
||||
"DeleteContentTagAction.unableToDelTag.msg=Unable to delete tag {0}.",
|
||||
"DeleteContentTagAction.tagDelErr=Tag Deletion Error"
|
||||
|
@ -24,11 +24,11 @@
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" 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="102" alignment="1" 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"/>
|
||||
<EmptySpace 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="tagLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" min="-2" max="-2" 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="jScrollPane1" pref="318" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
@ -58,11 +58,11 @@
|
||||
<Component id="tagLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="commentLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="commentText" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="commentLabel" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jScrollPane1" min="-2" pref="51" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace pref="37" max="32767" attributes="0"/>
|
||||
<EmptySpace pref="22" max="32767" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="cancelButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="okButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
@ -125,16 +125,6 @@
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="commentText">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/actions/Bundle.properties" key="GetTagNameAndCommentDialog.commentText.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/actions/Bundle.properties" key="GetTagNameAndCommentDialog.commentText.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="newTagButton">
|
||||
<Properties>
|
||||
<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"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
|
||||
<AuxValues>
|
||||
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JTextArea" name="commentText">
|
||||
<Properties>
|
||||
<Property name="columns" type="int" value="20"/>
|
||||
<Property name="rows" type="int" value="5"/>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/actions/Bundle.properties" key="GetTagNameAndCommentDialog.commentText.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/actions/Bundle.properties" key="GetTagNameAndCommentDialog.commentText.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
@ -22,9 +22,13 @@ import java.awt.Component;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.logging.Level;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.ActionMap;
|
||||
import javax.swing.DefaultListCellRenderer;
|
||||
@ -50,7 +54,8 @@ import org.sleuthkit.datamodel.TskData;
|
||||
public class GetTagNameAndCommentDialog extends JDialog {
|
||||
|
||||
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;
|
||||
|
||||
public static class TagNameAndComment {
|
||||
@ -105,7 +110,7 @@ public class GetTagNameAndCommentDialog extends JDialog {
|
||||
|
||||
private GetTagNameAndCommentDialog(Window owner) {
|
||||
super(owner,
|
||||
NbBundle.getMessage(GetTagNameAndCommentDialog.class, "GetTagNameAndCommentDialog.createTag"),
|
||||
NbBundle.getMessage(GetTagNameAndCommentDialog.class, "GetTagNameAndCommentDialog.selectTag"),
|
||||
ModalityType.APPLICATION_MODAL);
|
||||
}
|
||||
|
||||
@ -144,16 +149,29 @@ public class GetTagNameAndCommentDialog extends JDialog {
|
||||
// not exist in the database).
|
||||
try {
|
||||
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) {
|
||||
Logger.getLogger(GetTagNameAndCommentDialog.class
|
||||
.getName()).log(Level.SEVERE, "Failed to get tag names", ex); //NON-NLS
|
||||
}
|
||||
for (TagName tag : tagNamesSet) {
|
||||
|
||||
tagNamesList.forEach((tag) -> {
|
||||
tagCombo.addItem(tag);
|
||||
}
|
||||
});
|
||||
|
||||
standardTagNamesList.forEach((tag) -> {
|
||||
tagCombo.addItem(tag);
|
||||
});
|
||||
|
||||
// Center and show the dialog box.
|
||||
this.setLocationRelativeTo(this.getOwner());
|
||||
@ -174,8 +192,9 @@ public class GetTagNameAndCommentDialog extends JDialog {
|
||||
tagCombo = new javax.swing.JComboBox<TagName>();
|
||||
tagLabel = new javax.swing.JLabel();
|
||||
commentLabel = new javax.swing.JLabel();
|
||||
commentText = new javax.swing.JTextField();
|
||||
newTagButton = new javax.swing.JButton();
|
||||
jScrollPane1 = new javax.swing.JScrollPane();
|
||||
commentText = new javax.swing.JTextArea();
|
||||
|
||||
addWindowListener(new java.awt.event.WindowAdapter() {
|
||||
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
|
||||
|
||||
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
|
||||
newTagButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
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());
|
||||
getContentPane().setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
@ -222,7 +244,7 @@ public class GetTagNameAndCommentDialog extends JDialog {
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||
.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)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(cancelButton))
|
||||
@ -232,8 +254,8 @@ public class GetTagNameAndCommentDialog extends JDialog {
|
||||
.addComponent(tagLabel))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.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())
|
||||
);
|
||||
|
||||
@ -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(tagLabel))
|
||||
.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(commentText, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 37, Short.MAX_VALUE)
|
||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 51, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 22, Short.MAX_VALUE)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(cancelButton)
|
||||
.addComponent(okButton)
|
||||
@ -282,7 +304,7 @@ public class GetTagNameAndCommentDialog extends JDialog {
|
||||
private void newTagButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newTagButtonActionPerformed
|
||||
TagName newTagName = GetTagNameDialog.doDialog(this);
|
||||
if (newTagName != null) {
|
||||
tagNamesSet.add(newTagName);
|
||||
tagNamesList.add(newTagName);
|
||||
tagCombo.addItem(newTagName);
|
||||
tagCombo.setSelectedItem(newTagName);
|
||||
}
|
||||
@ -291,7 +313,8 @@ public class GetTagNameAndCommentDialog extends JDialog {
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JButton cancelButton;
|
||||
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 okButton;
|
||||
private javax.swing.JComboBox<TagName> tagCombo;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
188
Core/src/org/sleuthkit/autopsy/actions/ReplaceTagAction.java
Normal file
188
Core/src/org/sleuthkit/autopsy/actions/ReplaceTagAction.java
Normal 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);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011 Basis Technology Corp.
|
||||
* Copyright 2011-2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -18,15 +18,22 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.casemodule;
|
||||
|
||||
import java.awt.Frame;
|
||||
import javax.swing.JDialog;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* @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);
|
||||
initComponents();
|
||||
}
|
||||
|
@ -57,6 +57,7 @@ import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
* {@link AddImageWizardIngestConfigPanel} (which is a bit weird if you ask m
|
||||
* -jm)
|
||||
*/
|
||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||
class AddImageWizardAddingProgressPanel extends ShortcutWizardDescriptorPanel {
|
||||
|
||||
private boolean readyToIngest = false;
|
||||
@ -79,7 +80,7 @@ class AddImageWizardAddingProgressPanel extends ShortcutWizardDescriptorPanel {
|
||||
*/
|
||||
private AddImageWizardAddingProgressVisual component;
|
||||
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 IngestJobSettings ingestJobSettings;
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2012 Basis Technology Corp.
|
||||
* Copyright 2012-2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -19,16 +19,14 @@
|
||||
package org.sleuthkit.autopsy.casemodule;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import javax.swing.JProgressBar;
|
||||
import org.openide.WizardDescriptor;
|
||||
import org.openide.util.NbBundle;
|
||||
|
||||
/**
|
||||
* visual component to display progress bar and status updates while adding an
|
||||
* image in the wizard
|
||||
*/
|
||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||
class AddImageWizardAddingProgressVisual extends javax.swing.JPanel {
|
||||
|
||||
private static final String ADDING_DATA_SOURCE_COMPLETE = NbBundle
|
||||
|
@ -39,6 +39,7 @@ import org.sleuthkit.autopsy.ingest.runIngestModuleWizard.ShortcutWizardDescript
|
||||
* The "Add Image" wizard panel1 handling the logic of selecting image file(s)
|
||||
* 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 {
|
||||
|
||||
/**
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Copyright 2011-2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* 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
|
||||
* 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 {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(AddImageWizardDataSourceSettingsVisual.class.getName());
|
||||
|
@ -40,10 +40,11 @@ import org.sleuthkit.autopsy.ingest.runIngestModuleWizard.ShortcutWizardDescript
|
||||
* TODO: review this for dead code. think about moving logic of adding image to
|
||||
* 3rd panel( {@link AddImageWizardAddingProgressPanel}) separate class -jm
|
||||
*/
|
||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||
class AddImageWizardIngestConfigPanel extends ShortcutWizardDescriptorPanel {
|
||||
|
||||
@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
|
||||
* component from this class, just use getComponent().
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2014 Basis Technology Corp.
|
||||
* Copyright 2011-2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* 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
|
||||
* wizard.
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||
class AddImageWizardIngestConfigVisual extends JPanel {
|
||||
|
||||
private final JPanel ingestPanel;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Copyright 2011-2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* 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
|
||||
* DataSourceProcessor
|
||||
*/
|
||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||
final class AddImageWizardSelectDspPanel extends ShortcutWizardDescriptorPanel implements PropertyChangeListener {
|
||||
|
||||
@NbBundle.Messages("SelectDataSourceProcessorPanel.name.text=Select Type of Data Source To Add")
|
||||
|
@ -46,6 +46,7 @@ import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
* Panel which displays the available DataSourceProcessors and allows selection
|
||||
* of one
|
||||
*/
|
||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||
final class AddImageWizardSelectDspVisual extends JPanel {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(AddImageWizardSelectDspVisual.class.getName());
|
||||
|
@ -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
|
||||
* them.
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||
class CaseBrowser extends javax.swing.JPanel implements ExplorerManager.Provider {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Copyright 2011-2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* 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
|
||||
* ingest job history.
|
||||
*/
|
||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||
class CaseInformationPanel extends javax.swing.JPanel {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
@ -35,6 +35,7 @@ import org.openide.windows.WindowManager;
|
||||
/*
|
||||
* 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 {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Copyright 2011-2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author wschaefer
|
||||
* Panel to allow examiner to edit option case properties.
|
||||
*/
|
||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||
class EditOptionalCasePropertiesPanel extends javax.swing.JPanel {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
@ -31,7 +31,6 @@ import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
import javax.swing.filechooser.FileFilter;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openide.util.Exceptions;
|
||||
import org.openide.util.NbBundle;
|
||||
import static org.sleuthkit.autopsy.casemodule.Bundle.*;
|
||||
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
|
||||
* files in FAT32.
|
||||
*/
|
||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||
public class ImageFilePanel extends JPanel implements DocumentListener {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(ImageFilePanel.class.getName());
|
||||
|
@ -34,6 +34,10 @@ import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
|
||||
import org.sleuthkit.autopsy.imagewriter.ImageWriterSettings;
|
||||
|
||||
/**
|
||||
* ImageTypePanel for adding a local disk or partition such as PhysicalDrive0 or
|
||||
* C:.
|
||||
*/
|
||||
@NbBundle.Messages({
|
||||
"LocalDiskPanel.errorMessage.noOpenCaseTitle=No open case available",
|
||||
"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.localDiskMessage.unspecified=Unspecified"
|
||||
})
|
||||
/**
|
||||
* ImageTypePanel for adding a local disk or partition such as PhysicalDrive0 or
|
||||
* C:.
|
||||
*/
|
||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||
final class LocalDiskPanel extends JPanel {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(LocalDiskPanel.class.getName());
|
||||
|
@ -35,6 +35,7 @@ import org.sleuthkit.autopsy.coreutils.PathValidator;
|
||||
/**
|
||||
* A panel which allows the user to select local files and/or directories.
|
||||
*/
|
||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||
final class LocalFilesPanel extends javax.swing.JPanel {
|
||||
|
||||
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
|
||||
*/
|
||||
@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) {
|
||||
errorLabel.setVisible(false);
|
||||
|
||||
@ -288,13 +292,13 @@ final class LocalFilesPanel extends javax.swing.JPanel {
|
||||
for (String currentPath : pathsList) {
|
||||
if (!PathValidator.isValid(currentPath, currentCaseType)) {
|
||||
errorLabel.setVisible(true);
|
||||
errorLabel.setText(NbBundle.getMessage(this.getClass(), "DataSourceOnCDriveError.text"));
|
||||
errorLabel.setText(Bundle.LocalFilesPanel_pathValidation_dataSourceOnCDriveError());
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (NoCurrentCaseException ex) {
|
||||
errorLabel.setVisible(true);
|
||||
errorLabel.setText(Bundle.LocalFilesPanel_pathValidation_error());
|
||||
errorLabel.setText(Bundle.LocalFilesPanel_pathValidation_getOpenCase());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,13 +28,14 @@ import org.openide.util.NbBundle;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
|
||||
|
||||
/**
|
||||
* Add input wizard subpanel for adding local files / dirs to the case
|
||||
*/
|
||||
@Messages({
|
||||
"LogicalFilesDspPanel.subTypeComboBox.localFilesOption.text=Local files and folders",
|
||||
"LogicalFilesDspPanel.subTypeComboBox.l01FileOption.text=Logical evidence file (L01)"
|
||||
})
|
||||
/**
|
||||
* Add input wizard subpanel for adding local files / dirs to the case
|
||||
*/
|
||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||
final class LogicalFilesDspPanel extends JPanel {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Copyright 2011-2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||
final class MultiUserCasesDialog extends JDialog {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Copyright 2011-2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||
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 final JDialog parentDialog;
|
||||
private final CaseBrowser caseBrowserPanel;
|
||||
@ -98,7 +99,7 @@ final class MultiUserCasesPanel extends JPanel{
|
||||
Case.openAsCurrentCase(caseMetadataFilePath);
|
||||
} catch (CaseActionException ex) {
|
||||
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());
|
||||
}
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2015 Basis Technology Corp.
|
||||
* Copyright 2011-2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -18,9 +18,9 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.casemodule;
|
||||
|
||||
import java.awt.Component;
|
||||
import org.openide.util.NbBundle;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import javax.swing.JFileChooser;
|
||||
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.
|
||||
*/
|
||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||
final class NewCaseVisualPanel1 extends JPanel implements DocumentListener {
|
||||
|
||||
private final JFileChooser fileChooser = new JFileChooser();
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Copyright 2011-2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -16,20 +16,14 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* NewCaseVisualPanel2.java
|
||||
*
|
||||
* Created on Mar 7, 2012, 11:01:48 AM
|
||||
*/
|
||||
package org.sleuthkit.autopsy.casemodule;
|
||||
|
||||
import org.openide.util.NbBundle;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author dfickling
|
||||
* The JPanel for the second page of the new case wizard.
|
||||
*/
|
||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||
final class NewCaseVisualPanel2 extends javax.swing.JPanel {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
@ -121,6 +121,15 @@ public class TagsManager implements Closeable {
|
||||
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
|
||||
* content and artifact tags to the case database.
|
||||
@ -157,6 +166,21 @@ public class TagsManager implements Closeable {
|
||||
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.
|
||||
* 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
@ -421,6 +463,23 @@ public class TagsManager implements Closeable {
|
||||
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.
|
||||
*
|
||||
@ -522,6 +581,24 @@ public class TagsManager implements Closeable {
|
||||
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.
|
||||
*
|
||||
@ -553,6 +630,24 @@ public class TagsManager implements Closeable {
|
||||
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.
|
||||
*
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
@ -5,3 +5,8 @@ OpenIDE-Module-Long-Description=\
|
||||
Correlation Engine ingest module and central database. \n\n\
|
||||
The Correlation Engine ingest module stores attributes of artifacts matching selected correlation types into a central database.\n\
|
||||
Stored attributes are used in future cases to correlate and analyzes files and artifacts during ingest.
|
||||
CentralRepoCommentDialog.fileLabel.text=File:
|
||||
CentralRepoCommentDialog.commentLabel.text=Comment:
|
||||
CentralRepoCommentDialog.pathLabel.text=
|
||||
CentralRepoCommentDialog.okButton.text=&OK
|
||||
CentralRepoCommentDialog.cancelButton.text=C&ancel
|
||||
|
138
Core/src/org/sleuthkit/autopsy/centralrepository/CentralRepoCommentDialog.form
Executable file
138
Core/src/org/sleuthkit/autopsy/centralrepository/CentralRepoCommentDialog.form
Executable file
@ -0,0 +1,138 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JDialogFormInfo">
|
||||
<Properties>
|
||||
<Property name="defaultCloseOperation" type="int" value="2"/>
|
||||
<Property name="size" type="java.awt.Dimension" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||
<Connection component="Form" name="preferredSize" type="property"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<SyntheticProperties>
|
||||
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
|
||||
<SyntheticProperty name="generateCenter" type="boolean" value="false"/>
|
||||
</SyntheticProperties>
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="jScrollPane1" pref="500" max="32767" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="fileLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="pathLabel" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="commentLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="451" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
<Component id="okButton" min="-2" pref="75" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="cancelButton" min="-2" pref="75" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="fileLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="pathLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="19" max="-2" attributes="0"/>
|
||||
<Component id="commentLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jScrollPane1" max="32767" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="okButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="cancelButton" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
|
||||
<AuxValues>
|
||||
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JTextArea" name="commentTextArea">
|
||||
<Properties>
|
||||
<Property name="columns" type="int" value="20"/>
|
||||
<Property name="lineWrap" type="boolean" value="true"/>
|
||||
<Property name="rows" type="int" value="5"/>
|
||||
<Property name="tabSize" type="int" value="4"/>
|
||||
<Property name="wrapStyleWord" type="boolean" value="true"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JButton" name="okButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/Bundle.properties" key="CentralRepoCommentDialog.okButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="okButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="cancelButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/Bundle.properties" key="CentralRepoCommentDialog.cancelButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cancelButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="fileLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/Bundle.properties" key="CentralRepoCommentDialog.fileLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="pathLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/Bundle.properties" key="CentralRepoCommentDialog.pathLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="commentLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/Bundle.properties" key="CentralRepoCommentDialog.commentLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
203
Core/src/org/sleuthkit/autopsy/centralrepository/CentralRepoCommentDialog.java
Executable file
203
Core/src/org/sleuthkit/autopsy/centralrepository/CentralRepoCommentDialog.java
Executable file
@ -0,0 +1,203 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.centralrepository;
|
||||
|
||||
import org.openide.windows.WindowManager;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttribute;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
|
||||
|
||||
/**
|
||||
* Dialog to allow Central Repository file instance comments to be added and
|
||||
* modified.
|
||||
*/
|
||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||
final class CentralRepoCommentDialog extends javax.swing.JDialog {
|
||||
|
||||
private final CorrelationAttribute correlationAttribute;
|
||||
private boolean commentUpdated = false;
|
||||
private String currentComment = "";
|
||||
|
||||
/**
|
||||
* Create an instance.
|
||||
*
|
||||
* @param correlationAttribute The correlation attribute to be modified.
|
||||
* @param title The title to assign the dialog.
|
||||
*/
|
||||
CentralRepoCommentDialog(CorrelationAttribute correlationAttribute, String title) {
|
||||
super(WindowManager.getDefault().getMainWindow(), title);
|
||||
|
||||
initComponents();
|
||||
|
||||
CorrelationAttributeInstance instance = correlationAttribute.getInstances().get(0);
|
||||
|
||||
// Store the original comment
|
||||
if (instance.getComment() != null) {
|
||||
currentComment = instance.getComment();
|
||||
}
|
||||
|
||||
pathLabel.setText(instance.getFilePath());
|
||||
commentTextArea.setText(instance.getComment());
|
||||
|
||||
this.correlationAttribute = correlationAttribute;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the dialog.
|
||||
*/
|
||||
void display() {
|
||||
setModal(true);
|
||||
setSize(getPreferredSize());
|
||||
setLocationRelativeTo(this.getParent());
|
||||
setAlwaysOnTop(false);
|
||||
pack();
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Has the comment been updated?
|
||||
*
|
||||
* @return True if the comment has been updated; otherwise false.
|
||||
*/
|
||||
boolean isCommentUpdated() {
|
||||
return commentUpdated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current comment.
|
||||
* If the user hit OK, this will be the new comment.
|
||||
* If the user canceled, this will be the original comment.
|
||||
* @return the comment
|
||||
*/
|
||||
String getComment() {
|
||||
return currentComment;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called from within the constructor to initialize the form.
|
||||
* WARNING: Do NOT modify this code. The content of this method is always
|
||||
* regenerated by the Form Editor.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
|
||||
jScrollPane1 = new javax.swing.JScrollPane();
|
||||
commentTextArea = new javax.swing.JTextArea();
|
||||
okButton = new javax.swing.JButton();
|
||||
cancelButton = new javax.swing.JButton();
|
||||
fileLabel = new javax.swing.JLabel();
|
||||
pathLabel = new javax.swing.JLabel();
|
||||
commentLabel = new javax.swing.JLabel();
|
||||
|
||||
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
|
||||
setSize(getPreferredSize());
|
||||
|
||||
commentTextArea.setColumns(20);
|
||||
commentTextArea.setLineWrap(true);
|
||||
commentTextArea.setRows(5);
|
||||
commentTextArea.setTabSize(4);
|
||||
commentTextArea.setWrapStyleWord(true);
|
||||
jScrollPane1.setViewportView(commentTextArea);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(okButton, org.openide.util.NbBundle.getMessage(CentralRepoCommentDialog.class, "CentralRepoCommentDialog.okButton.text")); // NOI18N
|
||||
okButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
okButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(cancelButton, org.openide.util.NbBundle.getMessage(CentralRepoCommentDialog.class, "CentralRepoCommentDialog.cancelButton.text")); // NOI18N
|
||||
cancelButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
cancelButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(fileLabel, org.openide.util.NbBundle.getMessage(CentralRepoCommentDialog.class, "CentralRepoCommentDialog.fileLabel.text")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(pathLabel, org.openide.util.NbBundle.getMessage(CentralRepoCommentDialog.class, "CentralRepoCommentDialog.pathLabel.text")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(commentLabel, org.openide.util.NbBundle.getMessage(CentralRepoCommentDialog.class, "CentralRepoCommentDialog.commentLabel.text")); // NOI18N
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
|
||||
getContentPane().setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 500, Short.MAX_VALUE)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(fileLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(pathLabel))
|
||||
.addComponent(commentLabel))
|
||||
.addGap(0, 451, Short.MAX_VALUE))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(0, 0, Short.MAX_VALUE)
|
||||
.addComponent(okButton, javax.swing.GroupLayout.PREFERRED_SIZE, 75, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(cancelButton, javax.swing.GroupLayout.PREFERRED_SIZE, 75, javax.swing.GroupLayout.PREFERRED_SIZE)))
|
||||
.addContainerGap())
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(fileLabel)
|
||||
.addComponent(pathLabel))
|
||||
.addGap(19, 19, 19)
|
||||
.addComponent(commentLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jScrollPane1)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(okButton)
|
||||
.addComponent(cancelButton))
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
pack();
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed
|
||||
dispose();
|
||||
}//GEN-LAST:event_cancelButtonActionPerformed
|
||||
|
||||
private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
|
||||
currentComment = commentTextArea.getText();
|
||||
correlationAttribute.getInstances().get(0).setComment(currentComment);
|
||||
commentUpdated = true;
|
||||
|
||||
dispose();
|
||||
}//GEN-LAST:event_okButtonActionPerformed
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JButton cancelButton;
|
||||
private javax.swing.JLabel commentLabel;
|
||||
private javax.swing.JTextArea commentTextArea;
|
||||
private javax.swing.JLabel fileLabel;
|
||||
private javax.swing.JScrollPane jScrollPane1;
|
||||
private javax.swing.JButton okButton;
|
||||
private javax.swing.JLabel pathLabel;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Central Repository
|
||||
*
|
||||
* Copyright 2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.centralrepository;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import javax.swing.Action;
|
||||
import org.openide.util.Utilities;
|
||||
import org.openide.util.lookup.ServiceProvider;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifactUtil;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbUtil;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.ContextMenuActionsProvider;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
|
||||
/**
|
||||
* This creates a single context menu item for adding or editing a Central
|
||||
* Repository comment.
|
||||
*/
|
||||
@ServiceProvider(service = ContextMenuActionsProvider.class)
|
||||
public class CentralRepoContextMenuActionsProvider implements ContextMenuActionsProvider {
|
||||
|
||||
@Override
|
||||
public List<Action> getActions() {
|
||||
ArrayList<Action> actions = new ArrayList<>();
|
||||
Collection<? extends AbstractFile> selectedFiles = Utilities.actionsGlobalContext().lookupAll(AbstractFile.class);
|
||||
|
||||
if (selectedFiles.size() != 1) {
|
||||
return actions;
|
||||
}
|
||||
|
||||
for (AbstractFile file : selectedFiles) {
|
||||
if (EamDbUtil.useCentralRepo() && EamArtifactUtil.isSupportedAbstractFileType(file) && file.isFile()) {
|
||||
actions.add(AddEditCentralRepoCommentAction.createAddEditCentralRepoCommentAction(file));
|
||||
}
|
||||
}
|
||||
|
||||
return actions;
|
||||
}
|
||||
}
|
@ -3,3 +3,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.exportToCSVMenuItem.text=Export Selected Rows to CSV
|
||||
DataContentViewerOtherCases.showCommonalityMenuItem.text=Show Frequency
|
||||
DataContentViewerOtherCases.addCommentMenuItem.text=Add/Edit Comment
|
||||
|
@ -3,6 +3,9 @@
|
||||
<Form version="1.6" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||
<NonVisualComponents>
|
||||
<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">
|
||||
<Property name="useNullLayout" type="boolean" value="true"/>
|
||||
@ -36,6 +39,13 @@
|
||||
</Property>
|
||||
</Properties>
|
||||
</MenuItem>
|
||||
<MenuItem class="javax.swing.JMenuItem" name="addCommentMenuItem">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/contentviewer/Bundle.properties" key="DataContentViewerOtherCases.addCommentMenuItem.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</MenuItem>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JFileChooser" name="CSVFileChooser">
|
||||
|
@ -18,9 +18,7 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.centralrepository.contentviewer;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.BufferedWriter;
|
||||
@ -37,36 +35,27 @@ import java.util.Objects;
|
||||
import java.util.logging.Level;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.swing.GroupLayout;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JOptionPane;
|
||||
import static javax.swing.JOptionPane.DEFAULT_OPTION;
|
||||
import static javax.swing.JOptionPane.PLAIN_MESSAGE;
|
||||
import static javax.swing.JOptionPane.ERROR_MESSAGE;
|
||||
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.table.TableCellRenderer;
|
||||
import javax.swing.table.TableColumn;
|
||||
import org.openide.awt.Mnemonics;
|
||||
import org.openide.nodes.Node;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.openide.util.lookup.ServiceProvider;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.centralrepository.AddEditCentralRepoCommentAction;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttribute;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifactUtil;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationCase;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationDataSource;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
@ -76,9 +65,9 @@ import org.sleuthkit.datamodel.ContentTag;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.TskException;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbUtil;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
import org.sleuthkit.datamodel.TskDataException;
|
||||
|
||||
/**
|
||||
* View correlation results from other cases
|
||||
@ -88,8 +77,8 @@ import org.sleuthkit.datamodel.TskDataException;
|
||||
@Messages({"DataContentViewerOtherCases.title=Other Occurrences",
|
||||
"DataContentViewerOtherCases.toolTip=Displays instances of the selected file/artifact from other occurrences.",})
|
||||
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 Collection<CorrelationAttribute> correlationAttributes;
|
||||
@ -123,10 +112,20 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
try {
|
||||
saveToCSV();
|
||||
} 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)) {
|
||||
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);
|
||||
showCaseDetailsMenuItem.addActionListener(actList);
|
||||
showCommonalityMenuItem.addActionListener(actList);
|
||||
addCommentMenuItem.addActionListener(actList);
|
||||
|
||||
// Set background of every nth row as light grey.
|
||||
TableCellRenderer renderer = new DataContentViewerOtherCasesTableCellRenderer();
|
||||
@ -150,7 +150,8 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
"DataContentViewerOtherCases.correlatedArtifacts.title=Attribute Frequency",
|
||||
"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() {
|
||||
if (correlationAttributes.isEmpty()) {
|
||||
@ -174,7 +175,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
Bundle.DataContentViewerOtherCases_correlatedArtifacts_title(),
|
||||
DEFAULT_OPTION, PLAIN_MESSAGE);
|
||||
} catch (EamDbException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error getting commonality details.", ex);
|
||||
logger.log(Level.SEVERE, "Error getting commonality details.", ex);
|
||||
JOptionPane.showConfirmDialog(showCommonalityMenuItem,
|
||||
Bundle.DataContentViewerOtherCases_correlatedArtifacts_failed(),
|
||||
Bundle.DataContentViewerOtherCases_correlatedArtifacts_title(),
|
||||
@ -204,8 +205,8 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
if (-1 != selectedRowViewIdx) {
|
||||
EamDb dbManager = EamDb.getInstance();
|
||||
int selectedRowModelIdx = otherCasesTable.convertRowIndexToModel(selectedRowViewIdx);
|
||||
CorrelationAttribute eamArtifact = (CorrelationAttribute) tableModel.getRow(selectedRowModelIdx);
|
||||
CorrelationCase eamCasePartial = eamArtifact.getInstances().get(0).getCorrelationCase();
|
||||
OtherOccurrenceNodeData nodeData = (OtherOccurrenceNodeData) tableModel.getRow(selectedRowModelIdx);
|
||||
CorrelationCase eamCasePartial = nodeData.getCorrelationAttributeInstance().getCorrelationCase();
|
||||
if (eamCasePartial == null) {
|
||||
JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
|
||||
Bundle.DataContentViewerOtherCases_caseDetailsDialog_noDetailsReference(),
|
||||
@ -298,7 +299,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
}
|
||||
|
||||
} 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 {
|
||||
content = nodeBbArtifact.getSleuthkitCase().getContentById(nodeBbArtifact.getObjectID());
|
||||
} 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;
|
||||
}
|
||||
|
||||
@ -435,20 +436,20 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
}
|
||||
}
|
||||
} 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 {
|
||||
try {
|
||||
// If EamDb not enabled, get the Files default correlation type to allow Other Occurances to be enabled.
|
||||
if(this.file != null) {
|
||||
if (this.file != null) {
|
||||
String md5 = this.file.getMd5Hash();
|
||||
if(md5 != null && !md5.isEmpty()) {
|
||||
ret.add(new CorrelationAttribute(CorrelationAttribute.getDefaultCorrelationTypes().get(0),md5));
|
||||
if (md5 != null && !md5.isEmpty()) {
|
||||
ret.add(new CorrelationAttribute(CorrelationAttribute.getDefaultCorrelationTypes().get(0), md5));
|
||||
}
|
||||
}
|
||||
} 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
|
||||
* given central repository artifact. Will not show instances from the same
|
||||
* datasource / device
|
||||
* Query the central repo database (if enabled) and the case database to find all
|
||||
* artifact instances correlated to the given central repository artifact. If the
|
||||
* central repo is not enabled, this will only return files from the current case
|
||||
* with matching MD5 hashes.
|
||||
*
|
||||
* @param corAttr CorrelationAttribute to query for
|
||||
* @param corAttr CorrelationAttribute to query for
|
||||
* @param dataSourceName Data source to filter results
|
||||
* @param 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
|
||||
try {
|
||||
final Case openCase = Case.getCurrentCase();
|
||||
String caseUUID = openCase.getName();
|
||||
HashMap<UniquePathKey,CorrelationAttributeInstance> artifactInstances = new HashMap<>();
|
||||
|
||||
HashMap<UniquePathKey,OtherOccurrenceNodeData> nodeDataMap = new HashMap<>();
|
||||
|
||||
if (EamDb.isEnabled()) {
|
||||
EamDb dbManager = EamDb.getInstance();
|
||||
artifactInstances.putAll(dbManager.getArtifactInstancesByTypeValue(corAttr.getCorrelationType(), corAttr.getCorrelationValue()).stream()
|
||||
.filter(artifactInstance -> !artifactInstance.getCorrelationCase().getCaseUUID().equals(caseUUID)
|
||||
|| !artifactInstance.getCorrelationDataSource().getName().equals(dataSourceName)
|
||||
|| !artifactInstance.getCorrelationDataSource().getDeviceID().equals(deviceId))
|
||||
.collect(Collectors.toMap(correlationAttr -> new UniquePathKey(correlationAttr.getCorrelationDataSource().getDeviceID(), correlationAttr.getFilePath()),
|
||||
correlationAttr -> correlationAttr)));
|
||||
}
|
||||
List<CorrelationAttributeInstance> instances = EamDb.getInstance().getArtifactInstancesByTypeValue(corAttr.getCorrelationType(), corAttr.getCorrelationValue());
|
||||
|
||||
if (corAttr.getCorrelationType().getDisplayName().equals("Files")) {
|
||||
List<AbstractFile> caseDbFiles = addCaseDbMatches(corAttr, openCase);
|
||||
for (AbstractFile caseDbFile : caseDbFiles) {
|
||||
addOrUpdateAttributeInstance(openCase, artifactInstances, caseDbFile);
|
||||
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().getDeviceID().equals(deviceId)
|
||||
|| !artifactInstance.getFilePath().equalsIgnoreCase(file.getParentPath() + file.getName())) {
|
||||
|
||||
OtherOccurrenceNodeData newNode = new OtherOccurrenceNodeData(artifactInstance, corAttr.getCorrelationType(), corAttr.getCorrelationValue());
|
||||
UniquePathKey uniquePathKey = new UniquePathKey(newNode);
|
||||
nodeDataMap.put(uniquePathKey, newNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return artifactInstances;
|
||||
if (corAttr.getCorrelationType().getDisplayName().equals("Files")) {
|
||||
List<AbstractFile> caseDbFiles = getCaseDbMatches(corAttr, openCase);
|
||||
|
||||
for (AbstractFile caseDbFile : caseDbFiles) {
|
||||
addOrUpdateNodeData(openCase, nodeDataMap, caseDbFile);
|
||||
}
|
||||
}
|
||||
|
||||
return nodeDataMap;
|
||||
} 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) {
|
||||
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) {
|
||||
// do nothing.
|
||||
// @@@ 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);
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
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 artifactInstances
|
||||
* @param nodeDataMap
|
||||
* @param newFile
|
||||
*
|
||||
* @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
|
||||
TskData.FileKnown localKnown = newFile.getKnown();
|
||||
|
||||
if (localKnown != TskData.FileKnown.BAD) {
|
||||
OtherOccurrenceNodeData newNode = new OtherOccurrenceNodeData(newFile, autopsyCase);
|
||||
|
||||
// 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);
|
||||
for (ContentTag tag : fileMatchTags) {
|
||||
TskData.FileKnown tagKnownStatus = tag.getName().getKnownStatus();
|
||||
if (tagKnownStatus.equals(TskData.FileKnown.BAD)) {
|
||||
localKnown = TskData.FileKnown.BAD;
|
||||
newNode.updateKnown(TskData.FileKnown.BAD);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// make a key to see if the file is already in the map
|
||||
String filePath = newFile.getParentPath() + newFile.getName();
|
||||
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);
|
||||
// Make a key to see if the file is already in the map
|
||||
UniquePathKey uniquePathKey = new UniquePathKey(newNode);
|
||||
|
||||
// double check that the CR version is BAD if the caseDB version is BAD.
|
||||
if (artifactInstances.containsKey(uniquePathKey)) {
|
||||
if (localKnown == TskData.FileKnown.BAD) {
|
||||
CorrelationAttributeInstance prevInstance = artifactInstances.get(uniquePathKey);
|
||||
prevInstance.setKnownStatus(localKnown);
|
||||
// If this node is already in the list, the only thing we need to do is
|
||||
// update the known status to BAD if the caseDB version had known status BAD.
|
||||
// Otherwise this is a new node so add the new node to the map.
|
||||
if (nodeDataMap.containsKey(uniquePathKey)) {
|
||||
if (newNode.getKnown() == TskData.FileKnown.BAD) {
|
||||
OtherOccurrenceNodeData prevInstance = nodeDataMap.get(uniquePathKey);
|
||||
prevInstance.updateKnown(newNode.getKnown());
|
||||
}
|
||||
}
|
||||
// add the data from the case DB by pushing data into CorrelationAttributeInstance class
|
||||
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);
|
||||
} else {
|
||||
nodeDataMap.put(uniquePathKey, newNode);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupported(Node node) {
|
||||
|
||||
// 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);
|
||||
// Is supported if this node
|
||||
// has correlatable content (File, BlackboardArtifact) OR
|
||||
// other common files across datasources.
|
||||
|
||||
if(EamDb.isEnabled()){
|
||||
if (EamDb.isEnabled()) {
|
||||
return this.file != null
|
||||
&& this.file.getSize() > 0
|
||||
&& !getCorrelationAttributesFromNode(node).isEmpty();
|
||||
} else{
|
||||
&& this.file.getSize() > 0
|
||||
&& !getCorrelationAttributesFromNode(node).isEmpty();
|
||||
} else {
|
||||
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
|
||||
correlationAttributes.addAll(getCorrelationAttributesFromNode(node));
|
||||
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
|
||||
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
|
||||
private void initComponents() {
|
||||
|
||||
rightClickPopupMenu = new JPopupMenu();
|
||||
selectAllMenuItem = new JMenuItem();
|
||||
exportToCSVMenuItem = new JMenuItem();
|
||||
showCaseDetailsMenuItem = new JMenuItem();
|
||||
showCommonalityMenuItem = new JMenuItem();
|
||||
CSVFileChooser = new JFileChooser();
|
||||
otherCasesPanel = new JPanel();
|
||||
tableContainerPanel = new JPanel();
|
||||
tableScrollPane = new JScrollPane();
|
||||
otherCasesTable = new JTable();
|
||||
tableStatusPanel = new JPanel();
|
||||
tableStatusPanelLabel = new JLabel();
|
||||
rightClickPopupMenu = new javax.swing.JPopupMenu();
|
||||
selectAllMenuItem = new javax.swing.JMenuItem();
|
||||
exportToCSVMenuItem = new javax.swing.JMenuItem();
|
||||
showCaseDetailsMenuItem = new javax.swing.JMenuItem();
|
||||
showCommonalityMenuItem = new javax.swing.JMenuItem();
|
||||
addCommentMenuItem = new javax.swing.JMenuItem();
|
||||
CSVFileChooser = new javax.swing.JFileChooser();
|
||||
otherCasesPanel = new javax.swing.JPanel();
|
||||
tableContainerPanel = new javax.swing.JPanel();
|
||||
tableScrollPane = new javax.swing.JScrollPane();
|
||||
otherCasesTable = new javax.swing.JTable();
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
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.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.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
|
||||
otherCasesTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_INTERVAL_SELECTION);
|
||||
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);
|
||||
tableStatusPanelLayout.setHorizontalGroup(tableStatusPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
tableStatusPanelLayout.setHorizontalGroup(
|
||||
tableStatusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGap(0, 0, Short.MAX_VALUE)
|
||||
.addGroup(tableStatusPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
.addGroup(tableStatusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(tableStatusPanelLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(tableStatusPanelLabel, GroupLayout.DEFAULT_SIZE, 780, Short.MAX_VALUE)
|
||||
.addComponent(tableStatusPanelLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 780, Short.MAX_VALUE)
|
||||
.addContainerGap()))
|
||||
);
|
||||
tableStatusPanelLayout.setVerticalGroup(tableStatusPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
tableStatusPanelLayout.setVerticalGroup(
|
||||
tableStatusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGap(0, 16, Short.MAX_VALUE)
|
||||
.addGroup(tableStatusPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
.addGroup(tableStatusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.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)))
|
||||
);
|
||||
|
||||
GroupLayout tableContainerPanelLayout = new GroupLayout(tableContainerPanel);
|
||||
javax.swing.GroupLayout tableContainerPanelLayout = new javax.swing.GroupLayout(tableContainerPanel);
|
||||
tableContainerPanel.setLayout(tableContainerPanelLayout);
|
||||
tableContainerPanelLayout.setHorizontalGroup(tableContainerPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
.addComponent(tableScrollPane, GroupLayout.Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(tableStatusPanel, GroupLayout.Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
tableContainerPanelLayout.setHorizontalGroup(
|
||||
tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.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()
|
||||
.addComponent(tableScrollPane, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(tableStatusPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(tableScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(tableStatusPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
GroupLayout otherCasesPanelLayout = new GroupLayout(otherCasesPanel);
|
||||
javax.swing.GroupLayout otherCasesPanelLayout = new javax.swing.GroupLayout(otherCasesPanel);
|
||||
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)
|
||||
.addGroup(otherCasesPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
.addComponent(tableContainerPanel, GroupLayout.Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addGroup(otherCasesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(tableContainerPanel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
);
|
||||
otherCasesPanelLayout.setVerticalGroup(otherCasesPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
otherCasesPanelLayout.setVerticalGroup(
|
||||
otherCasesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGap(0, 60, Short.MAX_VALUE)
|
||||
.addGroup(otherCasesPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
.addGroup(otherCasesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.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)))
|
||||
);
|
||||
|
||||
GroupLayout layout = new GroupLayout(this);
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
.addComponent(otherCasesPanel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
layout.setHorizontalGroup(
|
||||
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)
|
||||
.addComponent(otherCasesPanel, GroupLayout.DEFAULT_SIZE, 60, Short.MAX_VALUE)
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(otherCasesPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 52, Short.MAX_VALUE)
|
||||
);
|
||||
}// </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
|
||||
private JFileChooser CSVFileChooser;
|
||||
private JMenuItem exportToCSVMenuItem;
|
||||
private JPanel otherCasesPanel;
|
||||
private JTable otherCasesTable;
|
||||
private JPopupMenu rightClickPopupMenu;
|
||||
private JMenuItem selectAllMenuItem;
|
||||
private JMenuItem showCaseDetailsMenuItem;
|
||||
private JMenuItem showCommonalityMenuItem;
|
||||
private JPanel tableContainerPanel;
|
||||
private JScrollPane tableScrollPane;
|
||||
private JPanel tableStatusPanel;
|
||||
private JLabel tableStatusPanelLabel;
|
||||
private javax.swing.JFileChooser CSVFileChooser;
|
||||
private javax.swing.JMenuItem addCommentMenuItem;
|
||||
private javax.swing.JMenuItem exportToCSVMenuItem;
|
||||
private javax.swing.JPanel otherCasesPanel;
|
||||
private javax.swing.JTable otherCasesTable;
|
||||
private javax.swing.JPopupMenu rightClickPopupMenu;
|
||||
private javax.swing.JMenuItem selectAllMenuItem;
|
||||
private javax.swing.JMenuItem showCaseDetailsMenuItem;
|
||||
private javax.swing.JMenuItem showCommonalityMenuItem;
|
||||
private javax.swing.JPanel tableContainerPanel;
|
||||
private javax.swing.JScrollPane tableScrollPane;
|
||||
private javax.swing.JPanel tableStatusPanel;
|
||||
private javax.swing.JLabel tableStatusPanelLabel;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
|
||||
private final String dataSourceID;
|
||||
private final String filePath;
|
||||
private final String type;
|
||||
|
||||
UniquePathKey(String theDataSource, String theFilePath) {
|
||||
UniquePathKey(OtherOccurrenceNodeData nodeData) {
|
||||
super();
|
||||
dataSourceID = theDataSource;
|
||||
filePath = theFilePath.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the dataSourceID device ID
|
||||
*/
|
||||
String getDataSourceID() {
|
||||
return dataSourceID;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the filPath including the filename and extension.
|
||||
*/
|
||||
String getFilePath() {
|
||||
return filePath;
|
||||
dataSourceID = nodeData.getDeviceID();
|
||||
if (nodeData.getFilePath() != null) {
|
||||
filePath = nodeData.getFilePath().toLowerCase();
|
||||
} else {
|
||||
filePath = null;
|
||||
}
|
||||
type = nodeData.getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
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;
|
||||
}
|
||||
@ -852,7 +891,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
||||
//int hash = 7;
|
||||
//hash = 67 * hash + this.dataSourceID.hashCode();
|
||||
//hash = 67 * hash + this.filePath.hashCode();
|
||||
return Objects.hash(dataSourceID, filePath);
|
||||
return Objects.hash(dataSourceID, filePath, type);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,10 +68,10 @@ public class DataContentViewerOtherCasesTableModel extends AbstractTableModel {
|
||||
}
|
||||
};
|
||||
|
||||
List<CorrelationAttribute> eamArtifacts;
|
||||
List<OtherOccurrenceNodeData> nodeDataList;
|
||||
|
||||
DataContentViewerOtherCasesTableModel() {
|
||||
eamArtifacts = new ArrayList<>();
|
||||
nodeDataList = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -95,7 +95,7 @@ public class DataContentViewerOtherCasesTableModel extends AbstractTableModel {
|
||||
|
||||
@Override
|
||||
public int getRowCount() {
|
||||
return eamArtifacts.size();
|
||||
return nodeDataList.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -105,15 +105,15 @@ public class DataContentViewerOtherCasesTableModel extends AbstractTableModel {
|
||||
|
||||
@Override
|
||||
public Object getValueAt(int rowIdx, int colIdx) {
|
||||
if (0 == eamArtifacts.size()) {
|
||||
if (0 == nodeDataList.size()) {
|
||||
return Bundle.DataContentViewerOtherCasesTableModel_noData();
|
||||
}
|
||||
|
||||
return mapValueById(rowIdx, TableColumns.values()[colIdx]);
|
||||
}
|
||||
|
||||
public Object getRow(int rowIdx) {
|
||||
return eamArtifacts.get(rowIdx);
|
||||
Object getRow(int rowIdx) {
|
||||
return nodeDataList.get(rowIdx);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -125,40 +125,39 @@ public class DataContentViewerOtherCasesTableModel extends AbstractTableModel {
|
||||
* @return value in the cell
|
||||
*/
|
||||
private Object mapValueById(int rowIdx, TableColumns colId) {
|
||||
CorrelationAttribute eamArtifact = eamArtifacts.get(rowIdx);
|
||||
CorrelationAttributeInstance eamArtifactInstance = eamArtifact.getInstances().get(0);
|
||||
OtherOccurrenceNodeData nodeData = nodeDataList.get(rowIdx);
|
||||
String value = Bundle.DataContentViewerOtherCasesTableModel_noData();
|
||||
|
||||
switch (colId) {
|
||||
case CASE_NAME:
|
||||
if (null != eamArtifactInstance.getCorrelationCase()) {
|
||||
value = eamArtifactInstance.getCorrelationCase().getDisplayName();
|
||||
if (null != nodeData.getCaseName()) {
|
||||
value = nodeData.getCaseName();
|
||||
}
|
||||
break;
|
||||
case DEVICE:
|
||||
if (null != eamArtifactInstance.getCorrelationDataSource()) {
|
||||
value = eamArtifactInstance.getCorrelationDataSource().getDeviceID();
|
||||
if (null != nodeData.getDeviceID()) {
|
||||
value = nodeData.getDeviceID();
|
||||
}
|
||||
break;
|
||||
case DATA_SOURCE:
|
||||
if (null != eamArtifactInstance.getCorrelationDataSource()) {
|
||||
value = eamArtifactInstance.getCorrelationDataSource().getName();
|
||||
if (null != nodeData.getDataSourceName()) {
|
||||
value = nodeData.getDataSourceName();
|
||||
}
|
||||
break;
|
||||
case FILE_PATH:
|
||||
value = eamArtifactInstance.getFilePath();
|
||||
value = nodeData.getFilePath();
|
||||
break;
|
||||
case TYPE:
|
||||
value = eamArtifact.getCorrelationType().getDisplayName();
|
||||
value = nodeData.getType();
|
||||
break;
|
||||
case VALUE:
|
||||
value = eamArtifact.getCorrelationValue();
|
||||
value = nodeData.getValue();
|
||||
break;
|
||||
case KNOWN:
|
||||
value = eamArtifactInstance.getKnownStatus().getName();
|
||||
value = nodeData.getKnown().getName();
|
||||
break;
|
||||
case COMMENT:
|
||||
value = eamArtifactInstance.getComment();
|
||||
value = nodeData.getComment();
|
||||
break;
|
||||
}
|
||||
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
|
||||
* table
|
||||
* @param newNodeData data to add to the table
|
||||
*/
|
||||
public void addEamArtifact(CorrelationAttribute eamArtifact) {
|
||||
eamArtifacts.add(eamArtifact);
|
||||
void addNodeData(OtherOccurrenceNodeData newNodeData) {
|
||||
nodeDataList.add(newNodeData);
|
||||
fireTableDataChanged();
|
||||
}
|
||||
|
||||
public void clearTable() {
|
||||
eamArtifacts.clear();
|
||||
void clearTable() {
|
||||
nodeDataList.clear();
|
||||
fireTableDataChanged();
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,233 @@
|
||||
/*
|
||||
* Central Repository
|
||||
*
|
||||
* Copyright 2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.centralrepository.contentviewer;
|
||||
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttribute;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.DataSource;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
import org.sleuthkit.datamodel.TskDataException;
|
||||
|
||||
/**
|
||||
* Class for populating the Other Occurrences tab
|
||||
*/
|
||||
class OtherOccurrenceNodeData {
|
||||
|
||||
// For now hard code the string for the central repo files type, since
|
||||
// getting it dynamically can fail.
|
||||
private static final String FILE_TYPE_STR = "Files";
|
||||
|
||||
private final String caseName;
|
||||
private String deviceID;
|
||||
private String dataSourceName;
|
||||
private final String filePath;
|
||||
private final String typeStr;
|
||||
private final CorrelationAttribute.Type type;
|
||||
private final String value;
|
||||
private TskData.FileKnown known;
|
||||
private String comment;
|
||||
|
||||
private AbstractFile originalAbstractFile = null;
|
||||
private CorrelationAttributeInstance originalCorrelationInstance = null;
|
||||
|
||||
/**
|
||||
* Create a node from a central repo instance.
|
||||
* @param instance The central repo instance
|
||||
* @param type The type of the instance
|
||||
* @param value The value of the instance
|
||||
*/
|
||||
OtherOccurrenceNodeData(CorrelationAttributeInstance instance, CorrelationAttribute.Type type, String value) {
|
||||
caseName = instance.getCorrelationCase().getDisplayName();
|
||||
deviceID = instance.getCorrelationDataSource().getDeviceID();
|
||||
dataSourceName = instance.getCorrelationDataSource().getName();
|
||||
filePath = instance.getFilePath();
|
||||
this.typeStr = type.getDisplayName();
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
known = instance.getKnownStatus();
|
||||
comment = instance.getComment();
|
||||
|
||||
originalCorrelationInstance = instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a node from an abstract file.
|
||||
* @param newFile The abstract file
|
||||
* @param autopsyCase The current case
|
||||
* @throws EamDbException
|
||||
*/
|
||||
OtherOccurrenceNodeData(AbstractFile newFile, Case autopsyCase) throws EamDbException {
|
||||
caseName = autopsyCase.getDisplayName();
|
||||
try {
|
||||
DataSource dataSource = autopsyCase.getSleuthkitCase().getDataSource(newFile.getDataSource().getId());
|
||||
deviceID = dataSource.getDeviceId();
|
||||
dataSourceName = dataSource.getName();
|
||||
} catch (TskDataException | TskCoreException ex) {
|
||||
throw new EamDbException("Error loading data source for abstract file ID " + newFile.getId(), ex);
|
||||
}
|
||||
|
||||
filePath = newFile.getParentPath() + newFile.getName();
|
||||
typeStr = FILE_TYPE_STR;
|
||||
this.type = null;
|
||||
value = newFile.getMd5Hash();
|
||||
known = newFile.getKnown();
|
||||
comment = "";
|
||||
|
||||
originalAbstractFile = newFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this node is a "file" type
|
||||
* @return true if it is a file type
|
||||
*/
|
||||
boolean isFileType() {
|
||||
return FILE_TYPE_STR.equals(typeStr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the known status for this node
|
||||
* @param newKnownStatus The new known status
|
||||
*/
|
||||
void updateKnown(TskData.FileKnown newKnownStatus) {
|
||||
known = newKnownStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the comment for this node
|
||||
* @param newComment The new comment
|
||||
*/
|
||||
void updateComment(String newComment) {
|
||||
comment = newComment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this is a central repo node.
|
||||
* @return true if this node was created from a central repo instance, false otherwise
|
||||
*/
|
||||
boolean isCentralRepoNode() {
|
||||
return (originalCorrelationInstance != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses the saved instance plus type and value to make a new CorrelationAttribute.
|
||||
* Should only be called if isCentralRepoNode() is true.
|
||||
* @return the newly created CorrelationAttribute
|
||||
*/
|
||||
CorrelationAttribute createCorrelationAttribute() throws EamDbException {
|
||||
if (! isCentralRepoNode() ) {
|
||||
throw new EamDbException("Can not create CorrelationAttribute for non central repo node");
|
||||
}
|
||||
CorrelationAttribute attr = new CorrelationAttribute(type, value);
|
||||
attr.addInstance(originalCorrelationInstance);
|
||||
return attr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the case name
|
||||
* @return the case name
|
||||
*/
|
||||
String getCaseName() {
|
||||
return caseName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the device ID
|
||||
* @return the device ID
|
||||
*/
|
||||
String getDeviceID() {
|
||||
return deviceID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data source name
|
||||
* @return the data source name
|
||||
*/
|
||||
String getDataSourceName() {
|
||||
return dataSourceName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file path
|
||||
* @return the file path
|
||||
*/
|
||||
String getFilePath() {
|
||||
return filePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type (as a string)
|
||||
* @return the type
|
||||
*/
|
||||
String getType() {
|
||||
return typeStr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value (MD5 hash for files)
|
||||
* @return the value
|
||||
*/
|
||||
String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the known status
|
||||
* @return the known status
|
||||
*/
|
||||
TskData.FileKnown getKnown() {
|
||||
return known;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the comment
|
||||
* @return the comment
|
||||
*/
|
||||
String getComment() {
|
||||
return comment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the backing abstract file.
|
||||
* Should only be called if isCentralRepoNode() is false
|
||||
* @return the original abstract file
|
||||
*/
|
||||
AbstractFile getAbstractFile() throws EamDbException {
|
||||
if (originalCorrelationInstance == null) {
|
||||
throw new EamDbException("AbstractFile is null");
|
||||
}
|
||||
return originalAbstractFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the backing CorrelationAttributeInstance.
|
||||
* Should only be called if isCentralRepoNode() is true
|
||||
* @return the original CorrelationAttributeInstance
|
||||
* @throws EamDbException
|
||||
*/
|
||||
CorrelationAttributeInstance getCorrelationAttributeInstance() throws EamDbException {
|
||||
if (originalCorrelationInstance == null) {
|
||||
throw new EamDbException("CorrelationAttributeInstance is null");
|
||||
}
|
||||
return originalCorrelationInstance;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Central Repository
|
||||
*
|
||||
* Copyright 2015-2017 Basis Technology Corp.
|
||||
* Copyright 2015-2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* 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
|
||||
* CorrelationAttribute. Includes its data source, path, etc.
|
||||
* Used to store details about a specific instance of a CorrelationAttribute.
|
||||
* Includes its data source, path, etc.
|
||||
*
|
||||
*/
|
||||
@Messages({
|
||||
@ -70,10 +70,10 @@ public class CorrelationAttributeInstance implements Serializable {
|
||||
String comment,
|
||||
TskData.FileKnown knownStatus
|
||||
) throws EamDbException {
|
||||
if(filePath == null) {
|
||||
if (filePath == null) {
|
||||
throw new EamDbException("file path is null");
|
||||
}
|
||||
|
||||
|
||||
this.ID = ID;
|
||||
this.correlationCase = eamCase;
|
||||
this.correlationDataSource = eamDataSource;
|
||||
@ -102,6 +102,16 @@ public class CorrelationAttributeInstance implements Serializable {
|
||||
+ 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
|
||||
*/
|
||||
@ -145,9 +155,9 @@ public class CorrelationAttributeInstance implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get this knownStatus. This only indicates whether an item has been
|
||||
* tagged as notable and should never return KNOWN.
|
||||
*
|
||||
* Get this knownStatus. This only indicates whether an item has been tagged
|
||||
* as notable and should never return KNOWN.
|
||||
*
|
||||
* @return BAD if the item has been tagged as notable, UNKNOWN otherwise
|
||||
*/
|
||||
public TskData.FileKnown getKnownStatus() {
|
||||
@ -155,10 +165,11 @@ public class CorrelationAttributeInstance implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the knownStatus. This only indicates whether an item has been
|
||||
* tagged as notable and should never be set to KNOWN.
|
||||
*
|
||||
* @param knownStatus Should be BAD if the item is tagged as notable, UNKNOWN otherwise
|
||||
* Set the knownStatus. This only indicates whether an item has been tagged
|
||||
* as notable and should never be set to KNOWN.
|
||||
*
|
||||
* @param knownStatus Should be BAD if the item is tagged as notable,
|
||||
* UNKNOWN otherwise
|
||||
*/
|
||||
public void setKnownStatus(TskData.FileKnown knownStatus) {
|
||||
this.knownStatus = knownStatus;
|
||||
|
@ -90,7 +90,18 @@ public class CorrelationDataSource implements Serializable {
|
||||
} catch (TskDataException | TskCoreException ex) {
|
||||
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
|
||||
|
@ -39,7 +39,7 @@ import org.sleuthkit.datamodel.TskData;
|
||||
public class EamArtifactUtil {
|
||||
|
||||
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() {
|
||||
}
|
||||
@ -83,7 +83,7 @@ public class EamArtifactUtil {
|
||||
}
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
|
||||
@ -115,10 +115,10 @@ public class EamArtifactUtil {
|
||||
eamArtifact.addInstance(eamInstance);
|
||||
}
|
||||
} 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;
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
@ -136,7 +136,7 @@ public class EamArtifactUtil {
|
||||
* @return the new EamArtifact, or null if one was not created because
|
||||
* bbArtifact did not contain the needed data
|
||||
*/
|
||||
private static CorrelationAttribute getCorrelationAttributeFromBlackboardArtifact(CorrelationAttribute.Type correlationType,
|
||||
private static CorrelationAttribute getCorrelationAttributeFromBlackboardArtifact(CorrelationAttribute.Type correlationType,
|
||||
BlackboardArtifact bbArtifact) throws EamDbException {
|
||||
String value = null;
|
||||
int artifactTypeID = bbArtifact.getArtifactTypeID();
|
||||
@ -202,10 +202,10 @@ public class EamArtifactUtil {
|
||||
}
|
||||
|
||||
} 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;
|
||||
} catch (NoCurrentCaseException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS
|
||||
} catch (NoCurrentCaseException ex) {
|
||||
logger.log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS
|
||||
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
|
||||
* artifact can not be created - this is not necessarily an error case, it
|
||||
@ -225,7 +264,7 @@ public class EamArtifactUtil {
|
||||
*
|
||||
* Does not add the artifact to the database.
|
||||
*
|
||||
* @param content The content object
|
||||
* @param content The content object
|
||||
*
|
||||
* @return The new EamArtifact or null if creation failed
|
||||
*/
|
||||
@ -262,7 +301,7 @@ public class EamArtifactUtil {
|
||||
eamArtifact.addInstance(cei);
|
||||
return eamArtifact;
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
@ -271,17 +310,17 @@ public class EamArtifactUtil {
|
||||
* Check whether the given abstract file should be processed for the central
|
||||
* 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
|
||||
* otherwise
|
||||
*/
|
||||
public static boolean isSupportedAbstractFileType(AbstractFile af) {
|
||||
if (af == null) {
|
||||
public static boolean isSupportedAbstractFileType(AbstractFile file) {
|
||||
if (file == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (af.getType()) {
|
||||
switch (file.getType()) {
|
||||
case UNALLOC_BLOCKS:
|
||||
case UNUSED_BLOCKS:
|
||||
case SLACK:
|
||||
@ -293,9 +332,9 @@ public class EamArtifactUtil {
|
||||
case LOCAL:
|
||||
return true;
|
||||
case FS:
|
||||
return af.isMetaFlagSet(TskData.TSK_FS_META_FLAG_ENUM.ALLOC);
|
||||
return file.isMetaFlagSet(TskData.TSK_FS_META_FLAG_ENUM.ALLOC);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Central Repository
|
||||
*
|
||||
* Copyright 2015-2017 Basis Technology Corp.
|
||||
* Copyright 2015-2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -104,7 +104,7 @@ public interface EamDb {
|
||||
/**
|
||||
* Add a new name/value pair in the db_info table.
|
||||
*
|
||||
* @param name Key to set
|
||||
* @param name Key to set
|
||||
* @param value Value to set
|
||||
*
|
||||
* @throws EamDbException
|
||||
@ -125,7 +125,7 @@ public interface EamDb {
|
||||
/**
|
||||
* Update the value for a name in the name/value db_info table.
|
||||
*
|
||||
* @param name Name to find
|
||||
* @param name Name to find
|
||||
* @param value Value to assign to name.
|
||||
*
|
||||
* @throws EamDbException
|
||||
@ -159,7 +159,9 @@ public interface EamDb {
|
||||
* Retrieves Central Repo case based on an Autopsy Case
|
||||
*
|
||||
* @param autopsyCase Autopsy case to find corresponding CR case for
|
||||
*
|
||||
* @return CR Case
|
||||
*
|
||||
* @throws EamDbException
|
||||
*/
|
||||
CorrelationCase getCase(Case autopsyCase) throws EamDbException;
|
||||
@ -190,8 +192,8 @@ public interface EamDb {
|
||||
/**
|
||||
* Retrieves Data Source details based on data source device ID
|
||||
*
|
||||
* @param correlationCase the current CorrelationCase used for ensuring
|
||||
* uniqueness of DataSource
|
||||
* @param correlationCase the current CorrelationCase used for ensuring
|
||||
* uniqueness of DataSource
|
||||
* @param dataSourceDeviceId the data source device ID number
|
||||
*
|
||||
* @return The data source
|
||||
@ -228,7 +230,7 @@ public interface EamDb {
|
||||
* Retrieves eamArtifact instances from the database that are associated
|
||||
* with the aType and filePath
|
||||
*
|
||||
* @param aType EamArtifact.Type to search for
|
||||
* @param aType EamArtifact.Type to search for
|
||||
* @param filePath File path to search for
|
||||
*
|
||||
* @return List of 0 or more EamArtifactInstances
|
||||
@ -245,7 +247,7 @@ public interface EamDb {
|
||||
* @param value Value to search for
|
||||
*
|
||||
* @return Number of artifact instances having ArtifactType and
|
||||
* ArtifactValue.
|
||||
* ArtifactValue.
|
||||
*/
|
||||
Long getCountArtifactInstancesByTypeValue(CorrelationAttribute.Type aType, String value) throws EamDbException;
|
||||
|
||||
@ -282,11 +284,11 @@ public interface EamDb {
|
||||
* associated with the caseDisplayName and dataSource of the given
|
||||
* eamArtifact instance.
|
||||
*
|
||||
* @param caseUUID Case ID to search for
|
||||
* @param caseUUID Case ID to search for
|
||||
* @param dataSourceID Data source ID to search for
|
||||
*
|
||||
* @return Number of artifact instances having caseDisplayName and
|
||||
* dataSource
|
||||
* dataSource
|
||||
*/
|
||||
Long getCountArtifactInstancesByCaseDataSource(String caseUUID, String dataSourceID) throws EamDbException;
|
||||
|
||||
@ -310,6 +312,34 @@ public interface EamDb {
|
||||
*/
|
||||
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
|
||||
* exists, it is updated. If eamArtifact does not exist nothing happens
|
||||
@ -357,7 +387,7 @@ public interface EamDb {
|
||||
* @param value Value to search for
|
||||
*
|
||||
* @return List of cases containing this artifact with instances marked as
|
||||
* bad
|
||||
* bad
|
||||
*
|
||||
* @throws EamDbException
|
||||
*/
|
||||
@ -367,6 +397,7 @@ public interface EamDb {
|
||||
* Remove a reference set and all values contained in it.
|
||||
*
|
||||
* @param referenceSetID
|
||||
*
|
||||
* @throws EamDbException
|
||||
*/
|
||||
public void deleteReferenceSet(int referenceSetID) throws EamDbException;
|
||||
@ -379,7 +410,9 @@ public interface EamDb {
|
||||
* @param referenceSetID
|
||||
* @param referenceSetName
|
||||
* @param version
|
||||
*
|
||||
* @return true if a matching entry exists in the central repository
|
||||
*
|
||||
* @throws EamDbException
|
||||
*/
|
||||
public boolean referenceSetIsValid(int referenceSetID, String referenceSetName, String version) throws EamDbException;
|
||||
@ -391,7 +424,9 @@ public interface EamDb {
|
||||
*
|
||||
* @param referenceSetName
|
||||
* @param version
|
||||
*
|
||||
* @return true if a matching set is found
|
||||
*
|
||||
* @throws EamDbException
|
||||
*/
|
||||
public boolean referenceSetExists(String referenceSetName, String version) throws EamDbException;
|
||||
@ -402,7 +437,9 @@ public interface EamDb {
|
||||
*
|
||||
* @param hash
|
||||
* @param referenceSetID
|
||||
*
|
||||
* @return true if the hash is found in the reference set
|
||||
*
|
||||
* @throws EamDbException
|
||||
*/
|
||||
public boolean isFileHashInReferenceSet(String hash, int referenceSetID) throws EamDbException;
|
||||
@ -413,6 +450,7 @@ public interface EamDb {
|
||||
* @param value
|
||||
* @param referenceSetID
|
||||
* @param correlationTypeID
|
||||
*
|
||||
* @return true if the hash is found in the reference set
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @param referenceSetID ID of the reference set
|
||||
*
|
||||
* @return The organization object
|
||||
*
|
||||
* @throws EamDbException
|
||||
*/
|
||||
EamOrganization getReferenceSetOrganization(int referenceSetID) throws EamDbException;
|
||||
@ -471,7 +511,7 @@ public interface EamDb {
|
||||
* Update an existing organization.
|
||||
*
|
||||
* @param updatedOrganization the values the Organization with the same ID
|
||||
* will be updated to in the database.
|
||||
* will be updated to in the database.
|
||||
*
|
||||
* @throws EamDbException
|
||||
*/
|
||||
@ -512,7 +552,7 @@ public interface EamDb {
|
||||
* Get all reference sets
|
||||
*
|
||||
* @param correlationType Type of sets to return
|
||||
*
|
||||
*
|
||||
* @return List of all reference sets in the central repository
|
||||
*
|
||||
* @throws EamDbException
|
||||
@ -523,7 +563,8 @@ public interface EamDb {
|
||||
* Add a new reference instance
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
@ -533,8 +574,8 @@ public interface EamDb {
|
||||
* Insert the bulk collection of Global File Instances
|
||||
*
|
||||
* @param globalInstances a Set of EamGlobalFileInstances to insert into the
|
||||
* db.
|
||||
* @param contentType the Type of the global instances
|
||||
* db.
|
||||
* @param contentType the Type of the global instances
|
||||
*
|
||||
* @throws EamDbException
|
||||
*/
|
||||
@ -543,7 +584,7 @@ public interface EamDb {
|
||||
/**
|
||||
* Get all reference entries having a given correlation type and value
|
||||
*
|
||||
* @param aType Type to use for matching
|
||||
* @param aType Type to use for matching
|
||||
* @param aValue Value to use for matching
|
||||
*
|
||||
* @return List of all global file instances with a type and value
|
||||
@ -568,7 +609,7 @@ public interface EamDb {
|
||||
* used to correlate artifacts.
|
||||
*
|
||||
* @return List of EamArtifact.Type's. If none are defined in the database,
|
||||
* the default list will be returned.
|
||||
* the default list will be returned.
|
||||
*
|
||||
* @throws EamDbException
|
||||
*/
|
||||
@ -579,7 +620,7 @@ public interface EamDb {
|
||||
* artifacts.
|
||||
*
|
||||
* @return List of enabled EamArtifact.Type's. If none are defined in the
|
||||
* database, the default list will be returned.
|
||||
* database, the default list will be returned.
|
||||
*
|
||||
* @throws EamDbException
|
||||
*/
|
||||
@ -590,7 +631,7 @@ public interface EamDb {
|
||||
* correlate artifacts.
|
||||
*
|
||||
* @return List of supported EamArtifact.Type's. If none are defined in the
|
||||
* database, the default list will be returned.
|
||||
* database, the default list will be returned.
|
||||
*
|
||||
* @throws EamDbException
|
||||
*/
|
||||
@ -630,8 +671,18 @@ public interface EamDb {
|
||||
* (meaning the database is in use).
|
||||
*
|
||||
* @return the lock, or null if locking is not supported
|
||||
*
|
||||
* @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;
|
||||
|
||||
/**
|
||||
* Process the Artifact instance in the EamDb
|
||||
*
|
||||
* @param type EamArtifact.Type to search for
|
||||
* @param instanceTableCallback callback to process the instance
|
||||
* @throws EamDbException
|
||||
*/
|
||||
void processInstanceTable(CorrelationAttribute.Type type, InstanceTableCallback instanceTableCallback) throws EamDbException;
|
||||
}
|
||||
|
@ -42,18 +42,18 @@ public class EamDbUtil {
|
||||
private static final String DEFAULT_ORG_NAME = "Not Specified";
|
||||
|
||||
/**
|
||||
* Close the prepared statement.
|
||||
* Close the statement.
|
||||
*
|
||||
* @param preparedStatement
|
||||
* @param statement The statement to be closed.
|
||||
*
|
||||
* @throws EamDbException
|
||||
*/
|
||||
public static void closePreparedStatement(PreparedStatement preparedStatement) {
|
||||
if (null != preparedStatement) {
|
||||
public static void closeStatement(Statement statement) {
|
||||
if (null != statement) {
|
||||
try {
|
||||
preparedStatement.close();
|
||||
statement.close();
|
||||
} 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();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
@ -114,7 +114,7 @@ final class PostgresEamDb extends AbstractSqlEamDb {
|
||||
|
||||
String instancesTemplate = "TRUNCATE TABLE %s_instances 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()));
|
||||
// FUTURE: support other reference types
|
||||
if (type.getId() == CorrelationAttribute.FILES_TYPE_ID) {
|
||||
|
@ -221,7 +221,7 @@ public final class PostgresEamDbSettings {
|
||||
LOGGER.log(Level.SEVERE, "Failed to execute database existance query.", ex); // NON-NLS
|
||||
return false;
|
||||
} finally {
|
||||
EamDbUtil.closePreparedStatement(ps);
|
||||
EamDbUtil.closeStatement(ps);
|
||||
EamDbUtil.closeResultSet(rs);
|
||||
EamDbUtil.closeConnection(conn);
|
||||
}
|
||||
|
@ -124,7 +124,7 @@ final class SqliteEamDb extends AbstractSqlEamDb {
|
||||
|
||||
String instancesTemplate = "DELETE FROM %s_instances";
|
||||
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()));
|
||||
// FUTURE: support other reference types
|
||||
if (type.getId() == CorrelationAttribute.FILES_TYPE_ID) {
|
||||
@ -416,8 +416,8 @@ final class SqliteEamDb extends AbstractSqlEamDb {
|
||||
} finally {
|
||||
releaseSharedLock();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves eamArtifact instances from the database that are associated
|
||||
* with the aType and filePath
|
||||
@ -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.
|
||||
* Used to check for name collisions when creating reference sets.
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Central Repository
|
||||
*
|
||||
* Copyright 2015-2017 Basis Technology Corp.
|
||||
* Copyright 2015-2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -18,8 +18,6 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.centralrepository.optionspanel;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Toolkit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
@ -38,8 +36,9 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(ManageCorrelationPropertiesDialog.class.getName());
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2017-18 Basis Technology Corp.
|
||||
* Copyright 2017-2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* 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
|
||||
* 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 {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2017-18 Basis Technology Corp.
|
||||
* Copyright 2017-2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* 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)
|
||||
@RetainLocation("cvt")
|
||||
@NbBundle.Messages("CVTTopComponent.name= Communications Visualization")
|
||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||
public final class CVTTopComponent extends TopComponent {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2017-18 Basis Technology Corp.
|
||||
* Copyright 2017-2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* 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
|
||||
* CommunicationsManager on user filtering changes.
|
||||
*/
|
||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||
final public class FiltersPanel extends JPanel {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2017-18 Basis Technology Corp.
|
||||
* Copyright 2017-2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||
public final class MessageBrowser extends JPanel implements ExplorerManager.Provider, Lookup.Provider {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
@ -76,6 +76,7 @@ import org.sleuthkit.datamodel.TskData;
|
||||
@ServiceProviders(value = {
|
||||
@ServiceProvider(service = FrameCapture.class)
|
||||
})
|
||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||
public class FXVideoPanel extends MediaViewVideoPanel {
|
||||
|
||||
// Refer to https://docs.oracle.com/javafx/2/api/javafx/scene/media/package-summary.html
|
||||
|
@ -36,6 +36,7 @@ import org.sleuthkit.datamodel.AbstractFile;
|
||||
* Generic Application content viewer
|
||||
*/
|
||||
@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 {
|
||||
|
||||
private static final int CONFIDENCE_LEVEL = 5;
|
||||
|
@ -30,6 +30,7 @@ import org.sleuthkit.datamodel.AbstractFile;
|
||||
/**
|
||||
* 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 {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(MediaFileViewer.class.getName());
|
||||
|
@ -48,7 +48,6 @@ import org.openide.util.NbBundle;
|
||||
import org.python.google.common.collect.Lists;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.coreutils.ImageUtils;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.datamodel.FileNode;
|
||||
import org.sleuthkit.autopsy.directorytree.ExternalViewerAction;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
@ -60,12 +59,11 @@ import org.sleuthkit.datamodel.AbstractFile;
|
||||
@NbBundle.Messages({"MediaViewImagePanel.externalViewerButton.text=Open in External Viewer",
|
||||
"MediaViewImagePanel.errorLabel.text=Could not load file into Media View.",
|
||||
"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 {
|
||||
|
||||
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 JFXPanel fxPanel;
|
||||
|
@ -49,6 +49,7 @@ import org.openide.util.actions.Presenter;
|
||||
/**
|
||||
* Panel to display a SQLite table
|
||||
*/
|
||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||
class SQLiteTableView extends JPanel implements ExplorerManager.Provider {
|
||||
|
||||
private final org.openide.explorer.view.OutlineView outlineView;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Copyright 2011-2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -206,7 +206,7 @@ public class Installer extends ModuleInstall {
|
||||
// Prevent the Autopsy UI from shrinking on high DPI displays
|
||||
System.setProperty("sun.java2d.dpiaware", "false");
|
||||
System.setProperty("prism.allowhidpi", "false");
|
||||
|
||||
|
||||
// Update existing configuration in case of unsupported settings
|
||||
updateConfig();
|
||||
|
||||
@ -218,16 +218,16 @@ public class Installer extends ModuleInstall {
|
||||
packageInstallers.add(org.sleuthkit.autopsy.centralrepository.eventlisteners.Installer.getDefault());
|
||||
packageInstallers.add(org.sleuthkit.autopsy.healthmonitor.Installer.getDefault());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If the mode in the configuration file is 'REVIEW' (2, now invalid), this
|
||||
* method will set it to 'STANDALONE' (0) and disable auto ingest.
|
||||
*/
|
||||
private void updateConfig() {
|
||||
String mode = ModuleSettings.getConfigSetting(SETTINGS_PROPERTIES, "AutopsyMode");
|
||||
if(mode != null) {
|
||||
if (mode != null) {
|
||||
int ordinal = Integer.parseInt(mode);
|
||||
if(ordinal > 1) {
|
||||
if (ordinal > 1) {
|
||||
UserPreferences.setMode(UserPreferences.SelectedMode.STANDALONE);
|
||||
ModuleSettings.setConfigSetting(UserPreferences.SETTINGS_PROPERTIES, "JoinAutoModeCluster", Boolean.toString(false));
|
||||
}
|
||||
@ -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() {
|
||||
File pythonModulesDir = new File(PlatformUtil.getUserPythonModulesPath());
|
||||
pythonModulesDir.mkdir();
|
||||
@ -277,6 +290,7 @@ public class Installer extends ModuleInstall {
|
||||
public void restored() {
|
||||
super.restored();
|
||||
ensurePythonModulesFolderExists();
|
||||
ensureClassifierFolderExists();
|
||||
initJavaFx();
|
||||
for (ModuleInstall mi : packageInstallers) {
|
||||
try {
|
||||
|
@ -69,6 +69,7 @@ public final class UserPreferences {
|
||||
private static final String MODE = "AutopsyMode"; // NON-NLS
|
||||
private static final String MAX_NUM_OF_LOG_FILE = "MaximumNumberOfLogFiles";
|
||||
private static final int LOG_FILE_NUM_INT = 10;
|
||||
public static final String GROUP_ITEMS_IN_TREE_BY_DATASOURCE = "GroupItemsInTreeByDataSource"; //NON-NLS
|
||||
|
||||
// Prevent instantiation.
|
||||
private UserPreferences() {
|
||||
@ -187,6 +188,14 @@ public final class UserPreferences {
|
||||
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.
|
||||
*
|
||||
|
@ -1,12 +1,24 @@
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.corecomponents;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Toolkit;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JPanel;
|
||||
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
|
||||
* close operation, which is set to dispose.
|
||||
*/
|
||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||
public class AdvancedConfigurationCleanDialog extends javax.swing.JDialog {
|
||||
|
||||
/**
|
||||
@ -27,6 +40,8 @@ public class AdvancedConfigurationCleanDialog extends javax.swing.JDialog {
|
||||
|
||||
/**
|
||||
* Creates new form AdvancedConfigurationDialog
|
||||
*
|
||||
* @param resizable Is the dialog resizable?
|
||||
*/
|
||||
public AdvancedConfigurationCleanDialog(boolean resizable) {
|
||||
super((JFrame) WindowManager.getDefault().getMainWindow(), true);
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011 Basis Technology Corp.
|
||||
* Copyright 2011-2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -16,26 +16,18 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* AdvancedConfigurationDialog.java
|
||||
*
|
||||
* Created on Feb 28, 2012, 4:47:31 PM
|
||||
*/
|
||||
package org.sleuthkit.autopsy.corecomponents;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.event.ActionListener;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JPanel;
|
||||
import org.openide.windows.WindowManager;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author dfickling
|
||||
* Advanced configuration dialog.
|
||||
*/
|
||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||
public class AdvancedConfigurationDialog extends javax.swing.JDialog {
|
||||
|
||||
/**
|
||||
@ -47,6 +39,8 @@ public class AdvancedConfigurationDialog extends javax.swing.JDialog {
|
||||
|
||||
/**
|
||||
* Creates new form AdvancedConfigurationDialog
|
||||
*
|
||||
* @param resizable Is the dialog resizable?
|
||||
*/
|
||||
public AdvancedConfigurationDialog(boolean resizable) {
|
||||
super((JFrame) WindowManager.getDefault().getMainWindow(), true);
|
||||
|
@ -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}
|
||||
LBL_Copyright=<div style\="font-size\: 12pt; font-family\: Verdana, 'Verdana CE', Arial, 'Arial CE', 'Lucida Grande CE', lucida, 'Helvetica CE', sans-serif; ">Autopsy™ is a digital forensics platform based on The Sleuth Kit™ 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 © 2003-2018. </div>
|
||||
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:///
|
||||
INDEX_FOR_LOCAL_HELP=/docs/index.html
|
||||
LBL_Close=Close
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2014 Basis Technology Corp.
|
||||
* Copyright 2011-2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -38,8 +38,9 @@ import org.sleuthkit.datamodel.Content;
|
||||
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 {
|
||||
|
||||
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 DataContentViewer wrapped;
|
||||
private final DataContentViewer wrapped;
|
||||
private boolean outdated;
|
||||
|
||||
UpdateWrapper(DataContentViewer wrapped) {
|
||||
|
@ -43,6 +43,7 @@ import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
//@TopComponent.Description(preferredID = "DataContentTopComponent")
|
||||
//@TopComponent.Registration(mode = "output", openAtStartup = true)
|
||||
//@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 {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(DataContentTopComponent.class.getName());
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2013 Basis Technology Corp.
|
||||
* Copyright 2011-2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
@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 {
|
||||
|
||||
@NbBundle.Messages({
|
||||
@ -484,7 +485,8 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
|
||||
if ((artifact == null)
|
||||
|| (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_HASHSET_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;
|
||||
} else {
|
||||
return 6;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Copyright 2011-2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* 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 javax.swing.JMenuItem;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JTextPane;
|
||||
import javax.swing.text.BadLocationException;
|
||||
import javax.swing.text.Utilities;
|
||||
import org.openide.nodes.Node;
|
||||
@ -40,6 +39,7 @@ import org.sleuthkit.datamodel.TskException;
|
||||
/**
|
||||
* Hex view of file contents.
|
||||
*/
|
||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||
@ServiceProvider(service = DataContentViewer.class, position = 1)
|
||||
public class DataContentViewerHex extends javax.swing.JPanel implements DataContentViewer {
|
||||
|
||||
|
@ -72,6 +72,7 @@ import org.sleuthkit.autopsy.datamodel.NodeSelectionInfo;
|
||||
* (DataContentTopComponent) that is normally docked into the lower right hand
|
||||
* 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 {
|
||||
|
||||
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) {
|
||||
tabToSelect = resultViewerTabs.getSelectedIndex();
|
||||
if ((tabToSelect == NO_TAB_SELECTED) || (!resultViewerTabs.isEnabledAt(tabToSelect))) {
|
||||
|
@ -68,6 +68,7 @@ import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
* viewers to the actions global context.
|
||||
*/
|
||||
@RetainLocation("editor")
|
||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||
public final class DataResultTopComponent extends TopComponent implements DataResult, ExplorerManager.Provider {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(DataResultTopComponent.class.getName());
|
||||
|
@ -77,6 +77,7 @@ import org.sleuthkit.autopsy.datamodel.NodeSelectionInfo;
|
||||
* ancestor top component's explorer manager at runtime.
|
||||
*/
|
||||
@ServiceProvider(service = DataResultViewer.class)
|
||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||
public final class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2015 Basis Technology Corp.
|
||||
* Copyright 2011-2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* 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")
|
||||
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());
|
||||
|
||||
@Override
|
||||
@ -71,7 +70,8 @@ public final class OfflineHelpAction implements ActionListener {
|
||||
String fileForHelp = "";
|
||||
String indexForHelp = "";
|
||||
String currentDirectory = "";
|
||||
|
||||
URI uri = null;
|
||||
|
||||
try {
|
||||
// Match the form: file:///C:/some/directory/AutopsyXYZ/docs/index.html
|
||||
fileForHelp = NbBundle.getMessage(OfflineHelpAction.class, "FILE_FOR_LOCAL_HELP");
|
||||
@ -79,7 +79,7 @@ public final class OfflineHelpAction implements ActionListener {
|
||||
currentDirectory = System.getProperty("user.dir").replace("\\", "/").replace(" ", "%20"); //NON-NLS
|
||||
uri = new URI(fileForHelp + currentDirectory + indexForHelp);
|
||||
} 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
|
||||
}
|
||||
if (uri != null) {
|
||||
@ -89,7 +89,7 @@ public final class OfflineHelpAction implements ActionListener {
|
||||
try {
|
||||
desktop.browse(uri);
|
||||
} 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
|
||||
}
|
||||
} else {
|
||||
@ -98,7 +98,7 @@ public final class OfflineHelpAction implements ActionListener {
|
||||
try {
|
||||
HtmlBrowser.URLDisplayer.getDefault().showURL(uri.toURL());
|
||||
} 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
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-17 Basis Technology Corp.
|
||||
* Copyright 2011-2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* 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
|
||||
* viewer.
|
||||
*/
|
||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||
final class SortChooser extends javax.swing.JPanel {
|
||||
|
||||
/**
|
||||
|
@ -59,10 +59,11 @@ import javax.imageio.stream.ImageInputStream;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
|
||||
import org.opencv.core.Core;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.corelibs.OpenCvLoader;
|
||||
import org.sleuthkit.autopsy.corelibs.ScalrWrapper;
|
||||
import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector;
|
||||
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 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
|
||||
@ -105,6 +106,8 @@ public class ImageUtils {
|
||||
*
|
||||
* 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<>();
|
||||
|
||||
static {
|
||||
@ -117,25 +120,23 @@ public class ImageUtils {
|
||||
tempImage = null;
|
||||
}
|
||||
DEFAULT_THUMBNAIL = tempImage;
|
||||
|
||||
//load opencv libraries
|
||||
boolean openCVLoadedTemp;
|
||||
try {
|
||||
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
|
||||
if (System.getProperty("os.arch").equals("amd64") || System.getProperty("os.arch").equals("x86_64")) { //NON-NLS
|
||||
System.loadLibrary("opencv_ffmpeg248_64"); //NON-NLS
|
||||
} else {
|
||||
System.loadLibrary("opencv_ffmpeg248"); //NON-NLS
|
||||
boolean tempFfmpegLoaded = false;
|
||||
if (OpenCvLoader.isOpenCvLoaded()) {
|
||||
try {
|
||||
if (System.getProperty("os.arch").equals("amd64") || System.getProperty("os.arch").equals("x86_64")) { //NON-NLS
|
||||
System.loadLibrary("opencv_ffmpeg2413_64"); //NON-NLS
|
||||
} else {
|
||||
System.loadLibrary("opencv_ffmpeg2413"); //NON-NLS
|
||||
}
|
||||
tempFfmpegLoaded = true;
|
||||
} catch (UnsatisfiedLinkError e) {
|
||||
tempFfmpegLoaded = false;
|
||||
LOGGER.log(Level.SEVERE, Bundle.ImageUtils_ffmpegLoadedError_msg(), e); //NON-NLS
|
||||
MessageNotifyUtil.Notify.show(Bundle.ImageUtils_ffmpegLoadedError_title(), Bundle.ImageUtils_ffmpegLoadedError_msg(), MessageNotifyUtil.MessageType.WARNING);
|
||||
}
|
||||
|
||||
openCVLoadedTemp = true;
|
||||
} catch (UnsatisfiedLinkError e) {
|
||||
openCVLoadedTemp = false;
|
||||
LOGGER.log(Level.SEVERE, "OpenCV Native code library failed to load", e); //NON-NLS
|
||||
MessageNotifyUtil.Notify.show("Open CV", "OpenCV native library failed to load, see log for more details", MessageNotifyUtil.MessageType.WARNING);
|
||||
}
|
||||
FFMPEG_LOADED = tempFfmpegLoaded;
|
||||
|
||||
OPEN_CV_LOADED = openCVLoadedTemp;
|
||||
SUPPORTED_IMAGE_EXTENSIONS.addAll(Arrays.asList(ImageIO.getReaderFileSuffixes()));
|
||||
SUPPORTED_IMAGE_EXTENSIONS.add("tec"); // Add JFIF .tec 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
|
||||
*/
|
||||
private static final Executor imageSaver =
|
||||
Executors.newSingleThreadExecutor(new BasicThreadFactory.Builder()
|
||||
private static final Executor imageSaver
|
||||
= Executors.newSingleThreadExecutor(new BasicThreadFactory.Builder()
|
||||
.namingPattern("thumbnail-saver-%d").build()); //NON-NLS
|
||||
|
||||
public static List<String> getSupportedImageExtensions() {
|
||||
@ -687,7 +688,7 @@ public class ImageUtils {
|
||||
//There was no correctly-sized cached thumbnail so make one.
|
||||
BufferedImage thumbnail = null;
|
||||
if (VideoUtils.isVideoThumbnailSupported(file)) {
|
||||
if (OPEN_CV_LOADED) {
|
||||
if (FFMPEG_LOADED) {
|
||||
updateMessage(Bundle.GetOrGenerateThumbnailTask_generatingPreviewFor(file.getName()));
|
||||
if (isCancelled()) {
|
||||
return null;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2012-2014 Basis Technology Corp.
|
||||
* Copyright 2012-2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -51,6 +51,7 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
public class PlatformUtil {
|
||||
|
||||
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;
|
||||
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");
|
||||
@ -116,6 +117,15 @@ public class PlatformUtil {
|
||||
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
|
||||
* available, otherwise use system java in PATH no validation is done if
|
||||
@ -310,19 +320,17 @@ public class PlatformUtil {
|
||||
return (System.getProperty("os.arch").contains("64")); //NON-NLS
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Attempts to determine whether the JVM is 64-bit or 32-bit.
|
||||
* May not be completely reliable for non-Windows operating systems.
|
||||
* Attempts to determine whether the JVM is 64-bit or 32-bit. May not be
|
||||
* completely reliable for non-Windows operating systems.
|
||||
*
|
||||
* @return True if the JVM is 64-bit. False otherwise.
|
||||
*/
|
||||
public static boolean is64BitJVM() {
|
||||
return (System.getProperty("sun.arch.data.model").equals("64"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get a list of all physical drives attached to the client's machine. Error
|
||||
* threshold of 4 non-existent physical drives before giving up.
|
||||
|
@ -21,12 +21,14 @@ 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.Map;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.swing.Action;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openide.nodes.Children;
|
||||
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.events.ContentTagAddedEvent;
|
||||
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 static org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode.AbstractFilePropertyType.*;
|
||||
import static org.sleuthkit.autopsy.datamodel.Bundle.*;
|
||||
|
@ -162,12 +162,12 @@ abstract class AbstractContentChildren<T> extends Keys<T> {
|
||||
|
||||
@Override
|
||||
public AbstractNode visit(DeletedContent dc) {
|
||||
return new DeletedContent.DeletedContentsNode(dc.getSleuthkitCase());
|
||||
return new DeletedContent.DeletedContentsNode(dc.getSleuthkitCase(), dc.filteringDataSourceObjId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractNode visit(FileSize dc) {
|
||||
return new FileSize.FileSizeRootNode(dc.getSleuthkitCase());
|
||||
return new FileSize.FileSizeRootNode(dc.getSleuthkitCase(), dc.filteringDataSourceObjId());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -192,22 +192,27 @@ abstract class AbstractContentChildren<T> extends Keys<T> {
|
||||
|
||||
@Override
|
||||
public AbstractNode visit(Tags tagsNodeKey) {
|
||||
return tagsNodeKey.new RootNode();
|
||||
return tagsNodeKey.new RootNode(tagsNodeKey.filteringDataSourceObjId());
|
||||
}
|
||||
|
||||
@Override
|
||||
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
|
||||
public AbstractNode visit(Views v) {
|
||||
return new ViewsNode(v.getSleuthkitCase());
|
||||
return new ViewsNode(v.getSleuthkitCase(), v.filteringDataSourceObjId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractNode visit(Results r) {
|
||||
return new ResultsNode(r.getSleuthkitCase());
|
||||
public AbstractNode visit(Results results) {
|
||||
return new ResultsNode(results.getSleuthkitCase(), results.filteringDataSourceObjId() );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -28,6 +28,8 @@ import org.sleuthkit.autopsy.datamodel.accounts.Accounts;
|
||||
public interface AutopsyItemVisitor<T> {
|
||||
|
||||
T visit(DataSources i);
|
||||
|
||||
T visit(DataSourceGrouping datasourceGrouping);
|
||||
|
||||
T visit(Views v);
|
||||
|
||||
@ -173,6 +175,11 @@ public interface AutopsyItemVisitor<T> {
|
||||
return defaultVisit(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visit(DataSourceGrouping datasourceGrouping) {
|
||||
return defaultVisit(datasourceGrouping);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visit(Results r) {
|
||||
return defaultVisit(r);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -48,6 +48,8 @@ import org.sleuthkit.autopsy.casemodule.events.BlackBoardArtifactTagAddedEvent;
|
||||
import org.sleuthkit.autopsy.casemodule.events.BlackBoardArtifactTagDeletedEvent;
|
||||
import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent;
|
||||
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.MessageNotifyUtil;
|
||||
import static org.sleuthkit.autopsy.datamodel.DisplayableItemNode.findLinked;
|
||||
@ -68,7 +70,7 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
*/
|
||||
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,
|
||||
Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED,
|
||||
Case.Events.CONTENT_TAG_ADDED,
|
||||
@ -217,6 +219,7 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
|
||||
public Action[] getActions(boolean context) {
|
||||
List<Action> actionsList = new ArrayList<>();
|
||||
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
|
||||
try {
|
||||
@ -224,7 +227,7 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
|
||||
actionsList.add(new ViewArtifactInTimelineAction(artifact));
|
||||
}
|
||||
} 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());
|
||||
}
|
||||
|
||||
@ -235,12 +238,11 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
|
||||
actionsList.add(ViewFileInTimelineAction.createViewFileAction(c));
|
||||
}
|
||||
} 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());
|
||||
}
|
||||
|
||||
//if this artifact has associated content, add the action to view the content in the timeline
|
||||
AbstractFile file = getLookup().lookup(AbstractFile.class);
|
||||
//if the artifact has associated content, add the action to view the content in the timeline
|
||||
if (null != file) {
|
||||
actionsList.add(ViewFileInTimelineAction.createViewSourceFileAction(file));
|
||||
}
|
||||
@ -391,7 +393,7 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
|
||||
try {
|
||||
sourcePath = associated.getUniquePath();
|
||||
} 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) {
|
||||
@ -439,7 +441,7 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
|
||||
dataSourceStr = getRootParentName();
|
||||
}
|
||||
} 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) {
|
||||
@ -472,7 +474,7 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
|
||||
tags.addAll(Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsByArtifact(artifact));
|
||||
tags.addAll(Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsByContent(associated));
|
||||
} 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(),
|
||||
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();
|
||||
}
|
||||
} 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 parentName;
|
||||
@ -551,7 +553,7 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
|
||||
}
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013-2016 Basis Technology Corp.
|
||||
* Copyright 2013-2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* 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.util.NbBundle;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
import org.sleuthkit.autopsy.actions.DeleteBlackboardArtifactTagAction;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||
import org.sleuthkit.autopsy.timeline.actions.ViewArtifactInTimelineAction;
|
||||
@ -132,8 +131,8 @@ public class BlackboardArtifactTagNode extends DisplayableItemNode {
|
||||
actions.add(ViewFileInTimelineAction.createViewSourceFileAction(file));
|
||||
}
|
||||
actions.add(new ViewTaggedArtifactAction(BlackboardArtifactTagNode_viewSourceArtifact_text(), artifact));
|
||||
actions.addAll(DataModelActionsFactory.getActions(tag.getContent(), true));
|
||||
actions.add(DeleteBlackboardArtifactTagAction.getInstance());
|
||||
actions.addAll(DataModelActionsFactory.getActions(tag, true));
|
||||
|
||||
return actions.toArray(new Action[0]);
|
||||
}
|
||||
|
||||
|
@ -56,6 +56,7 @@ DataModelActionsFactory.viewNewWin.text=View in New Window
|
||||
DataModelActionsFactory.openExtViewer.text=Open in External Viewer
|
||||
DataModelActionsFactory.srfFileSameMD5.text=Search for files with the same MD5 hash
|
||||
DataSourcesNode.name=Data Sources
|
||||
DataSourcesNode.group_by_datasource.name=Data Source Files
|
||||
DataSourcesNode.createSheet.name.name=Name
|
||||
DataSourcesNode.createSheet.name.displayName=Name
|
||||
DataSourcesNode.createSheet.name.desc=no description
|
||||
|
@ -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.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.group_by_datasource.name=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb
|
||||
DataSourcesNode.createSheet.name.name=\u540d\u524d
|
||||
DataSourcesNode.createSheet.name.displayName=\u540d\u524d
|
||||
DataSourcesNode.createSheet.name.desc=\u8aac\u660e\u304c\u3042\u308a\u307e\u305b\u3093
|
||||
|
@ -29,7 +29,6 @@ import org.openide.nodes.Sheet;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
import org.sleuthkit.autopsy.actions.DeleteContentTagAction;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.timeline.actions.ViewFileInTimelineAction;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
@ -128,8 +127,9 @@ class ContentTagNode extends DisplayableItemNode {
|
||||
if (file != null) {
|
||||
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()]);
|
||||
}
|
||||
|
||||
|
@ -28,8 +28,12 @@ import org.openide.util.NbBundle;
|
||||
import org.openide.util.Utilities;
|
||||
import org.sleuthkit.autopsy.actions.AddBlackboardArtifactTagAction;
|
||||
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.DeleteFileContentTagAction;
|
||||
import org.sleuthkit.autopsy.actions.ReplaceBlackboardArtifactTagAction;
|
||||
import org.sleuthkit.autopsy.actions.ReplaceContentTagAction;
|
||||
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
|
||||
import org.sleuthkit.autopsy.datamodel.Reports.ReportNode;
|
||||
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.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifactTag;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.ContentTag;
|
||||
import org.sleuthkit.datamodel.DerivedFile;
|
||||
import org.sleuthkit.datamodel.Directory;
|
||||
import org.sleuthkit.datamodel.File;
|
||||
@ -351,6 +357,80 @@ public class DataModelActionsFactory {
|
||||
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) {
|
||||
if (content instanceof File) {
|
||||
return getActions((File) content, isArtifactSource);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -23,9 +23,20 @@ package org.sleuthkit.autopsy.datamodel;
|
||||
*/
|
||||
public class DataSources implements AutopsyVisitableItem {
|
||||
|
||||
private final long datasourceObjId;
|
||||
|
||||
public DataSources() {
|
||||
this(0);
|
||||
}
|
||||
|
||||
public DataSources(long datasourceObjId) {
|
||||
this.datasourceObjId = datasourceObjId;
|
||||
}
|
||||
|
||||
long filteringDataSourceObjId() {
|
||||
return this.datasourceObjId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(AutopsyItemVisitor<T> visitor) {
|
||||
return visitor.visit(this);
|
||||
|
@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.datamodel;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
@ -33,6 +34,7 @@ import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.TskDataException;
|
||||
|
||||
/**
|
||||
* Nodes for the images
|
||||
@ -40,22 +42,27 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
public class DataSourcesNode extends DisplayableItemNode {
|
||||
|
||||
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.
|
||||
@Deprecated
|
||||
public DataSourcesNode(List<Content> images) {
|
||||
super(new DataSourcesNodeChildren(), Lookups.singleton(NAME));
|
||||
init();
|
||||
this(0);
|
||||
}
|
||||
|
||||
public DataSourcesNode() {
|
||||
super(new DataSourcesNodeChildren(), Lookups.singleton(NAME));
|
||||
init();
|
||||
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();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
setName(NAME);
|
||||
setDisplayName(NAME);
|
||||
setDisplayName(displayName);
|
||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/image.png"); //NON-NLS
|
||||
}
|
||||
|
||||
@ -70,14 +77,20 @@ public class DataSourcesNode extends DisplayableItemNode {
|
||||
public static class DataSourcesNodeChildren extends AbstractContentChildren<Content> {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(DataSourcesNodeChildren.class.getName());
|
||||
|
||||
private final long datasourceObjId;
|
||||
|
||||
List<Content> currentKeys;
|
||||
|
||||
public DataSourcesNodeChildren() {
|
||||
super();
|
||||
this.currentKeys = new ArrayList<>();
|
||||
this(0);
|
||||
}
|
||||
|
||||
public DataSourcesNodeChildren(long dsObjId) {
|
||||
super();
|
||||
this.currentKeys = new ArrayList<>();
|
||||
this.datasourceObjId = dsObjId;
|
||||
}
|
||||
|
||||
private final PropertyChangeListener pcl = new PropertyChangeListener() {
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
@ -103,9 +116,15 @@ public class DataSourcesNode extends DisplayableItemNode {
|
||||
|
||||
private void reloadKeys() {
|
||||
try {
|
||||
currentKeys = Case.getCurrentCaseThrows().getDataSources();
|
||||
if (datasourceObjId == 0) {
|
||||
currentKeys = Case.getCurrentCaseThrows().getDataSources();
|
||||
}
|
||||
else {
|
||||
Content content = Case.getCurrentCaseThrows().getSleuthkitCase().getDataSource(datasourceObjId);
|
||||
currentKeys = new ArrayList<>(Arrays.asList(content));
|
||||
}
|
||||
setKeys(currentKeys);
|
||||
} catch (TskCoreException | NoCurrentCaseException ex) {
|
||||
} catch (TskCoreException | NoCurrentCaseException | TskDataException ex) {
|
||||
logger.log(Level.SEVERE, "Error getting data sources: {0}", ex.getMessage()); // NON-NLS
|
||||
setKeys(Collections.<Content>emptySet());
|
||||
}
|
||||
|
@ -61,6 +61,7 @@ import org.sleuthkit.datamodel.TskData;
|
||||
public class DeletedContent implements AutopsyVisitableItem {
|
||||
|
||||
private SleuthkitCase skCase;
|
||||
private final long datasourceObjId;
|
||||
|
||||
@NbBundle.Messages({"DeletedContent.fsDelFilter.text=File System",
|
||||
"DeletedContent.allDelFilter.text=All"})
|
||||
@ -101,9 +102,18 @@ public class DeletedContent implements AutopsyVisitableItem {
|
||||
}
|
||||
|
||||
public DeletedContent(SleuthkitCase skCase) {
|
||||
this.skCase = skCase;
|
||||
this(skCase, 0);
|
||||
}
|
||||
|
||||
public DeletedContent(SleuthkitCase skCase, long dsObjId) {
|
||||
this.skCase = skCase;
|
||||
this.datasourceObjId = dsObjId;
|
||||
}
|
||||
|
||||
long filteringDataSourceObjId() {
|
||||
return this.datasourceObjId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(AutopsyItemVisitor<T> visitor) {
|
||||
return visitor.visit(this);
|
||||
@ -118,8 +128,8 @@ public class DeletedContent implements AutopsyVisitableItem {
|
||||
@NbBundle.Messages("DeletedContent.deletedContentsNode.name=Deleted Files")
|
||||
private static final String NAME = Bundle.DeletedContent_deletedContentsNode_name();
|
||||
|
||||
DeletedContentsNode(SleuthkitCase skCase) {
|
||||
super(Children.create(new DeletedContentsChildren(skCase), true), Lookups.singleton(NAME));
|
||||
DeletedContentsNode(SleuthkitCase skCase, long datasourceObjId) {
|
||||
super(Children.create(new DeletedContentsChildren(skCase, datasourceObjId), true), Lookups.singleton(NAME));
|
||||
super.setName(NAME);
|
||||
super.setDisplayName(NAME);
|
||||
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 Observable notifier;
|
||||
private final long datasourceObjId;
|
||||
// true if we have already told user that not all files will be shown
|
||||
private static volatile boolean maxFilesDialogShown = false;
|
||||
|
||||
public DeletedContentsChildren(SleuthkitCase skCase) {
|
||||
public DeletedContentsChildren(SleuthkitCase skCase, long dsObjId) {
|
||||
this.skCase = skCase;
|
||||
this.datasourceObjId = dsObjId;
|
||||
this.notifier = new DeletedContentsChildrenObservable();
|
||||
}
|
||||
|
||||
@ -257,24 +269,27 @@ public class DeletedContent implements AutopsyVisitableItem {
|
||||
|
||||
@Override
|
||||
protected Node createNodeForKey(DeletedContent.DeletedContentFilter key) {
|
||||
return new DeletedContentNode(skCase, key, notifier);
|
||||
return new DeletedContentNode(skCase, key, notifier, datasourceObjId);
|
||||
}
|
||||
|
||||
public class DeletedContentNode extends DisplayableItemNode {
|
||||
|
||||
private final DeletedContent.DeletedContentFilter filter;
|
||||
private final long datasourceObjId;
|
||||
|
||||
// Use version that has observer for updates
|
||||
@Deprecated
|
||||
DeletedContentNode(SleuthkitCase skCase, DeletedContent.DeletedContentFilter filter) {
|
||||
super(Children.create(new DeletedContentChildren(filter, skCase, null), true), Lookups.singleton(filter.getDisplayName()));
|
||||
DeletedContentNode(SleuthkitCase skCase, DeletedContent.DeletedContentFilter filter, long dsObjId) {
|
||||
super(Children.create(new DeletedContentChildren(filter, skCase, null, dsObjId ), true), Lookups.singleton(filter.getDisplayName()));
|
||||
this.filter = filter;
|
||||
this.datasourceObjId = dsObjId;
|
||||
init();
|
||||
}
|
||||
|
||||
DeletedContentNode(SleuthkitCase skCase, DeletedContent.DeletedContentFilter filter, Observable o) {
|
||||
super(Children.create(new DeletedContentChildren(filter, skCase, o), true), Lookups.singleton(filter.getDisplayName()));
|
||||
DeletedContentNode(SleuthkitCase skCase, DeletedContent.DeletedContentFilter filter, Observable o, long dsObjId) {
|
||||
super(Children.create(new DeletedContentChildren(filter, skCase, o, dsObjId), true), Lookups.singleton(filter.getDisplayName()));
|
||||
this.filter = filter;
|
||||
this.datasourceObjId = dsObjId;
|
||||
init();
|
||||
o.addObserver(new DeletedContentNodeObserver());
|
||||
}
|
||||
@ -299,7 +314,7 @@ public class DeletedContent implements AutopsyVisitableItem {
|
||||
|
||||
private void updateDisplayName() {
|
||||
//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);
|
||||
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 int MAX_OBJECTS = 10001;
|
||||
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.filter = filter;
|
||||
this.notifier = o;
|
||||
this.datasourceObjId = datasourceObjId;
|
||||
}
|
||||
|
||||
private final Observer observer = new DeletedContentChildrenObserver();
|
||||
@ -366,7 +383,7 @@ public class DeletedContent implements AutopsyVisitableItem {
|
||||
@Override
|
||||
public void update(Observable o, Object arg) {
|
||||
refresh(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -405,7 +422,7 @@ public class DeletedContent implements AutopsyVisitableItem {
|
||||
return true;
|
||||
}
|
||||
|
||||
static private String makeQuery(DeletedContent.DeletedContentFilter filter) {
|
||||
static private String makeQuery(DeletedContent.DeletedContentFilter filter, long filteringDSObjId) {
|
||||
String query = "";
|
||||
switch (filter) {
|
||||
case FS_DELETED_FILTER:
|
||||
@ -443,6 +460,10 @@ public class DeletedContent implements AutopsyVisitableItem {
|
||||
+ " OR known IS NULL)"; //NON-NLS
|
||||
}
|
||||
|
||||
if (UserPreferences.groupItemsInTreeByDatasource()) {
|
||||
query += " AND data_source_obj_id = " + filteringDSObjId;
|
||||
}
|
||||
|
||||
query += " LIMIT " + MAX_OBJECTS; //NON-NLS
|
||||
return query;
|
||||
}
|
||||
@ -450,7 +471,7 @@ public class DeletedContent implements AutopsyVisitableItem {
|
||||
private List<AbstractFile> runFsQuery() {
|
||||
List<AbstractFile> ret = new ArrayList<>();
|
||||
|
||||
String query = makeQuery(filter);
|
||||
String query = makeQuery(filter, datasourceObjId);
|
||||
try {
|
||||
ret = skCase.findAllFilesWhere(query);
|
||||
} catch (TskCoreException e) {
|
||||
@ -469,9 +490,9 @@ public class DeletedContent implements AutopsyVisitableItem {
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
static long calculateItems(SleuthkitCase sleuthkitCase, DeletedContent.DeletedContentFilter filter) {
|
||||
static long calculateItems(SleuthkitCase sleuthkitCase, DeletedContent.DeletedContentFilter filter, long datasourceObjId) {
|
||||
try {
|
||||
return sleuthkitCase.countFilesWhere(makeQuery(filter));
|
||||
return sleuthkitCase.countFilesWhere(makeQuery(filter, datasourceObjId));
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error getting deleted files search view count", ex); //NON-NLS
|
||||
return 0;
|
||||
|
@ -61,6 +61,8 @@ public interface DisplayableItemNodeVisitor<T> {
|
||||
*/
|
||||
T visit(ViewsNode vn);
|
||||
|
||||
T visit(DataSourceGroupingNode dataSourceGroupingNode);
|
||||
|
||||
T visit(org.sleuthkit.autopsy.datamodel.FileTypesByExtension.FileExtensionNode fsfn);
|
||||
|
||||
T visit(DeletedContentNode dcn);
|
||||
@ -336,6 +338,11 @@ public interface DisplayableItemNodeVisitor<T> {
|
||||
return defaultVisit(vn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visit(DataSourceGroupingNode dataSourceGroupingNode) {
|
||||
return defaultVisit(dataSourceGroupingNode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visit(ResultsNode rn) {
|
||||
return defaultVisit(rn);
|
||||
|
@ -40,6 +40,7 @@ import org.openide.util.NbBundle;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
|
||||
@ -86,10 +87,29 @@ public class EmailExtracted implements AutopsyVisitableItem {
|
||||
}
|
||||
private SleuthkitCase skCase;
|
||||
private final EmailResults emailResults;
|
||||
private final long datasourceObjId;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param skCase Case DB
|
||||
*/
|
||||
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.datasourceObjId = objId;
|
||||
emailResults = new EmailResults();
|
||||
}
|
||||
|
||||
@ -141,6 +161,9 @@ public class EmailExtracted implements AutopsyVisitableItem {
|
||||
+ "attribute_type_id=" + pathAttrId //NON-NLS
|
||||
+ " AND blackboard_attributes.artifact_id=blackboard_artifacts.artifact_id" //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)) {
|
||||
ResultSet resultSet = dbQuery.getResultSet();
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user