mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-15 09:17:42 +00:00
Merge branch 'develop' of https://github.com/sleuthkit/autopsy into 3868-normalize-cr
# Conflicts: # Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/OtherOccurrenceNodeData.java
This commit is contained in:
commit
49e53f4780
@ -86,7 +86,7 @@
|
|||||||
|
|
||||||
<target name="getTestDataFiles">
|
<target name="getTestDataFiles">
|
||||||
<mkdir dir="${basedir}/test/qa-functional/data"/>
|
<mkdir dir="${basedir}/test/qa-functional/data"/>
|
||||||
<get src="https://drive.google.com/uc?id=1_xPSnp0UDOO9sIPpvdtW_dRtD5SW9EID" dest="${test-input}/EmbeddedIM_img2_v1.vhd" skipexisting="true"/>
|
<get src="https://drive.google.com/uc?id=1FkinvA7EFqP4nOSOyTAOli5KefM67ufA" dest="${test-input}/EmbeddedIM_img1_v2.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=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=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=0BxdBkzm5VKGNT0dGY0dqcHVsU3M" dest="${test-input}/IngestFilters_img1_v1.img" skipexisting="true"/>
|
||||||
|
@ -47,7 +47,6 @@ import org.sleuthkit.datamodel.TskData;
|
|||||||
public class TagsManager implements Closeable {
|
public class TagsManager implements Closeable {
|
||||||
|
|
||||||
private static final Logger LOGGER = Logger.getLogger(TagsManager.class.getName());
|
private static final Logger LOGGER = Logger.getLogger(TagsManager.class.getName());
|
||||||
|
|
||||||
private final SleuthkitCase caseDb;
|
private final SleuthkitCase caseDb;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -71,13 +70,14 @@ public class TagsManager implements Closeable {
|
|||||||
|| tagDisplayName.contains(";"));
|
|| tagDisplayName.contains(";"));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NbBundle.Messages({"TagsManager.notableTagEnding.text= (Notable)"})
|
@NbBundle.Messages({"TagsManager.notableTagEnding.text= (Notable)"})
|
||||||
/**
|
/**
|
||||||
* Get String of text which is used to label tags as notable to the user.
|
* Get String of text which is used to label tags as notable to the user.
|
||||||
*
|
*
|
||||||
* @return Bundle message TagsManager.notableTagEnding.text
|
* @return Bundle message TagsManager.notableTagEnding.text
|
||||||
*/
|
*/
|
||||||
public static String getNotableTagLabel(){
|
public static String getNotableTagLabel() {
|
||||||
return Bundle.TagsManager_notableTagEnding_text();
|
return Bundle.TagsManager_notableTagEnding_text();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,13 +123,13 @@ public class TagsManager implements Closeable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list of names of standard/predefined tags
|
* Returns a list of names of standard/predefined tags
|
||||||
*
|
*
|
||||||
* @return list of predefined tag names
|
* @return list of predefined tag names
|
||||||
*/
|
*/
|
||||||
public static List<String> getStandardTagNames() {
|
public static List<String> getStandardTagNames() {
|
||||||
return TagNameDefinition.getStandardTagNames();
|
return TagNameDefinition.getStandardTagNames();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a per case Autopsy service that manages the addition of
|
* Constructs a per case Autopsy service that manages the addition of
|
||||||
* content and artifact tags to the case database.
|
* content and artifact tags to the case database.
|
||||||
@ -166,21 +166,79 @@ public class TagsManager implements Closeable {
|
|||||||
return caseDb.getTagNamesInUse();
|
return caseDb.getTagNamesInUse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a list of all tag names currently in use in the case database for
|
||||||
|
* tagging content or artifacts by the specified user.
|
||||||
|
*
|
||||||
|
* @param userName - the user name that you want to get tags for
|
||||||
|
*
|
||||||
|
* @return A list, possibly empty, of TagName objects.
|
||||||
|
*
|
||||||
|
* @throws TskCoreException If there is an error querying the case database.
|
||||||
|
*/
|
||||||
|
public List<TagName> getTagNamesInUseForUser(String userName) throws TskCoreException {
|
||||||
|
Set<TagName> tagNameSet = new HashSet<>();
|
||||||
|
List<BlackboardArtifactTag> artifactTags = caseDb.getAllBlackboardArtifactTags();
|
||||||
|
for (BlackboardArtifactTag tag : artifactTags) {
|
||||||
|
if (tag.getUserName().equals(userName)) {
|
||||||
|
tagNameSet.add(tag.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
List<ContentTag> contentTags = caseDb.getAllContentTags();
|
||||||
|
for (ContentTag tag : contentTags) {
|
||||||
|
if (tag.getUserName().equals(userName)) {
|
||||||
|
tagNameSet.add(tag.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new ArrayList<>(tagNameSet);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Selects all of the rows from the tag_names table in the case database for
|
* 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
|
* which there is at least one matching row in the content_tags or
|
||||||
* blackboard_artifact_tags tables, for the given data source object id.
|
* blackboard_artifact_tags tables, for the given data source object id.
|
||||||
*
|
*
|
||||||
* @param dsObjId data source object id
|
* @param dsObjId data source object id
|
||||||
*
|
*
|
||||||
* @return A list, possibly empty, of TagName data transfer objects (DTOs)
|
* @return A list, possibly empty, of TagName data transfer objects (DTOs)
|
||||||
* for the rows.
|
* for the rows.
|
||||||
*
|
*
|
||||||
* @throws TskCoreException
|
* @throws TskCoreException
|
||||||
*/
|
*/
|
||||||
public List<TagName> getTagNamesInUse(long dsObjId) throws TskCoreException {
|
public List<TagName> getTagNamesInUse(long dsObjId) throws TskCoreException {
|
||||||
return caseDb.getTagNamesInUse(dsObjId);
|
return caseDb.getTagNamesInUse(dsObjId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 and user.
|
||||||
|
*
|
||||||
|
* @param dsObjId data source object id
|
||||||
|
* @param userName - the user name that you want to get tags for
|
||||||
|
*
|
||||||
|
* @return A list, possibly empty, of TagName data transfer objects (DTOs)
|
||||||
|
* for the rows.
|
||||||
|
*
|
||||||
|
* @throws TskCoreException
|
||||||
|
*/
|
||||||
|
public List<TagName> getTagNamesInUseForUser(long dsObjId, String userName) throws TskCoreException {
|
||||||
|
Set<TagName> tagNameSet = new HashSet<>();
|
||||||
|
List<BlackboardArtifactTag> artifactTags = caseDb.getAllBlackboardArtifactTags();
|
||||||
|
for (BlackboardArtifactTag tag : artifactTags) {
|
||||||
|
if (tag.getUserName().equals(userName) && tag.getArtifact().getDataSource().getId() == dsObjId) {
|
||||||
|
tagNameSet.add(tag.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
List<ContentTag> contentTags = caseDb.getAllContentTags();
|
||||||
|
for (ContentTag tag : contentTags) {
|
||||||
|
if (tag.getUserName().equals(userName) && tag.getContent().getDataSource().getId() == dsObjId) {
|
||||||
|
tagNameSet.add(tag.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new ArrayList<>(tagNameSet);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a map of tag display names to tag name entries in the case database.
|
* Gets a map of tag display names to tag name entries in the case database.
|
||||||
* It has keys for the display names of the standard tag types, the current
|
* It has keys for the display names of the standard tag types, the current
|
||||||
@ -416,24 +474,77 @@ public class TagsManager implements Closeable {
|
|||||||
return caseDb.getContentTagsCountByTagName(tagName);
|
return caseDb.getContentTagsCountByTagName(tagName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets content tags count by tag name for the specified user.
|
||||||
|
*
|
||||||
|
* @param tagName The representation of the desired tag type in the case
|
||||||
|
* database, which can be obtained by calling getTagNames
|
||||||
|
* and/or addTagName.
|
||||||
|
* @param userName - the user name that you want to get tags for
|
||||||
|
*
|
||||||
|
* @return A count of the content tags with the specified tag name for the
|
||||||
|
* specified user.
|
||||||
|
*
|
||||||
|
* @throws TskCoreException If there is an error getting the tags count from
|
||||||
|
* the case database.
|
||||||
|
*/
|
||||||
|
public long getContentTagsCountByTagNameForUser(TagName tagName, String userName) throws TskCoreException {
|
||||||
|
long count = 0;
|
||||||
|
List<ContentTag> contentTags = getContentTagsByTagName(tagName);
|
||||||
|
for (ContentTag tag : contentTags) {
|
||||||
|
if (userName.equals(tag.getUserName())) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets content tags count by tag name, for the given data source
|
* Gets content tags count by tag name, for the given data source
|
||||||
*
|
*
|
||||||
* @param tagName The representation of the desired tag type in the case
|
* @param tagName The representation of the desired tag type in the case
|
||||||
* database, which can be obtained by calling getTagNames and/or addTagName.
|
* database, which can be obtained by calling getTagNames
|
||||||
*
|
* and/or addTagName.
|
||||||
|
*
|
||||||
* @param dsObjId data source object id
|
* @param dsObjId data source object id
|
||||||
*
|
*
|
||||||
* @return A count of the content tags with the specified tag name, and for
|
* @return A count of the content tags with the specified tag name, and for
|
||||||
* the given data source
|
* the given data source
|
||||||
*
|
*
|
||||||
* @throws TskCoreException If there is an error getting the tags count from
|
* @throws TskCoreException If there is an error getting the tags count from
|
||||||
* the case database.
|
* the case database.
|
||||||
*/
|
*/
|
||||||
public long getContentTagsCountByTagName(TagName tagName, long dsObjId) throws TskCoreException {
|
public long getContentTagsCountByTagName(TagName tagName, long dsObjId) throws TskCoreException {
|
||||||
return caseDb.getContentTagsCountByTagName(tagName, dsObjId);
|
return caseDb.getContentTagsCountByTagName(tagName, dsObjId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets content tags count by tag name, for the given data source and user
|
||||||
|
*
|
||||||
|
* @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
|
||||||
|
* @param userName - the user name that you want to get tags for
|
||||||
|
*
|
||||||
|
* @return A count of the content tags with the specified tag name, and for
|
||||||
|
* the given data source and user
|
||||||
|
*
|
||||||
|
* @throws TskCoreException If there is an error getting the tags count from
|
||||||
|
* the case database.
|
||||||
|
*/
|
||||||
|
public long getContentTagsCountByTagNameForUser(TagName tagName, long dsObjId, String userName) throws TskCoreException {
|
||||||
|
long count = 0;
|
||||||
|
List<ContentTag> contentTags = getContentTagsByTagName(tagName, dsObjId);
|
||||||
|
for (ContentTag tag : contentTags) {
|
||||||
|
if (userName.equals(tag.getUserName())) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a content tag by tag id.
|
* Gets a content tag by tag id.
|
||||||
*
|
*
|
||||||
@ -463,11 +574,11 @@ public class TagsManager implements Closeable {
|
|||||||
return caseDb.getContentTagsByTagName(tagName);
|
return caseDb.getContentTagsByTagName(tagName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets content tags by tag name, for the given data source.
|
* Gets content tags by tag name, for the given data source.
|
||||||
*
|
*
|
||||||
* @param tagName The tag name of interest.
|
* @param tagName The tag name of interest.
|
||||||
*
|
*
|
||||||
* @param dsObjId data source object id
|
* @param dsObjId data source object id
|
||||||
*
|
*
|
||||||
* @return A list, possibly empty, of the content tags with the specified
|
* @return A list, possibly empty, of the content tags with the specified
|
||||||
@ -479,7 +590,7 @@ public class TagsManager implements Closeable {
|
|||||||
public List<ContentTag> getContentTagsByTagName(TagName tagName, long dsObjId) throws TskCoreException {
|
public List<ContentTag> getContentTagsByTagName(TagName tagName, long dsObjId) throws TskCoreException {
|
||||||
return caseDb.getContentTagsByTagName(tagName, dsObjId);
|
return caseDb.getContentTagsByTagName(tagName, dsObjId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets content tags count by content.
|
* Gets content tags count by content.
|
||||||
*
|
*
|
||||||
@ -581,6 +692,31 @@ public class TagsManager implements Closeable {
|
|||||||
return caseDb.getBlackboardArtifactTagsCountByTagName(tagName);
|
return caseDb.getBlackboardArtifactTagsCountByTagName(tagName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an artifact tags count by tag name for a specific user.
|
||||||
|
*
|
||||||
|
* @param tagName The representation of the desired tag type in the case
|
||||||
|
* database, which can be obtained by calling getTagNames
|
||||||
|
* and/or addTagName.
|
||||||
|
* @param userName - the user name that you want to get tags for
|
||||||
|
*
|
||||||
|
* @return A count of the artifact tags with the specified tag name for the
|
||||||
|
* specified user.
|
||||||
|
*
|
||||||
|
* @throws TskCoreException If there is an error getting the tags count from
|
||||||
|
* the case database.
|
||||||
|
*/
|
||||||
|
public long getBlackboardArtifactTagsCountByTagNameForUser(TagName tagName, String userName) throws TskCoreException {
|
||||||
|
long count = 0;
|
||||||
|
List<BlackboardArtifactTag> artifactTags = getBlackboardArtifactTagsByTagName(tagName);
|
||||||
|
for (BlackboardArtifactTag tag : artifactTags) {
|
||||||
|
if (userName.equals(tag.getUserName())) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets an artifact tags count by tag name, for the given data source.
|
* Gets an artifact tags count by tag name, for the given data source.
|
||||||
*
|
*
|
||||||
@ -589,8 +725,8 @@ public class TagsManager implements Closeable {
|
|||||||
* and/or addTagName.
|
* and/or addTagName.
|
||||||
* @param dsObjId data source object id
|
* @param dsObjId data source object id
|
||||||
*
|
*
|
||||||
* @return A count of the artifact tags with the specified tag name,
|
* @return A count of the artifact tags with the specified tag name, for the
|
||||||
* for the given data source.
|
* given data source.
|
||||||
*
|
*
|
||||||
* @throws TskCoreException If there is an error getting the tags count from
|
* @throws TskCoreException If there is an error getting the tags count from
|
||||||
* the case database.
|
* the case database.
|
||||||
@ -598,7 +734,34 @@ public class TagsManager implements Closeable {
|
|||||||
public long getBlackboardArtifactTagsCountByTagName(TagName tagName, long dsObjId) throws TskCoreException {
|
public long getBlackboardArtifactTagsCountByTagName(TagName tagName, long dsObjId) throws TskCoreException {
|
||||||
return caseDb.getBlackboardArtifactTagsCountByTagName(tagName, dsObjId);
|
return caseDb.getBlackboardArtifactTagsCountByTagName(tagName, dsObjId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an artifact tags count by tag name, for the given data source and
|
||||||
|
* user.
|
||||||
|
*
|
||||||
|
* @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
|
||||||
|
* @param userName - the user name that you want to get tags for
|
||||||
|
*
|
||||||
|
* @return A count of the artifact tags with the specified tag name, for the
|
||||||
|
* given data source and user.
|
||||||
|
*
|
||||||
|
* @throws TskCoreException If there is an error getting the tags count from
|
||||||
|
* the case database.
|
||||||
|
*/
|
||||||
|
public long getBlackboardArtifactTagsCountByTagNameForUser(TagName tagName, long dsObjId, String userName) throws TskCoreException {
|
||||||
|
long count = 0;
|
||||||
|
List<BlackboardArtifactTag> artifactTags = getBlackboardArtifactTagsByTagName(tagName, dsObjId);
|
||||||
|
for (BlackboardArtifactTag tag : artifactTags) {
|
||||||
|
if (userName.equals(tag.getUserName())) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets an artifact tag by tag id.
|
* Gets an artifact tag by tag id.
|
||||||
*
|
*
|
||||||
@ -647,7 +810,7 @@ public class TagsManager implements Closeable {
|
|||||||
public List<BlackboardArtifactTag> getBlackboardArtifactTagsByTagName(TagName tagName, long dsObjId) throws TskCoreException {
|
public List<BlackboardArtifactTag> getBlackboardArtifactTagsByTagName(TagName tagName, long dsObjId) throws TskCoreException {
|
||||||
return caseDb.getBlackboardArtifactTagsByTagName(tagName, dsObjId);
|
return caseDb.getBlackboardArtifactTagsByTagName(tagName, dsObjId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets artifact tags for a particular artifact.
|
* Gets artifact tags for a particular artifact.
|
||||||
*
|
*
|
||||||
|
@ -5,8 +5,6 @@ OpenIDE-Module-Long-Description=\
|
|||||||
Correlation Engine ingest module and central database. \n\n\
|
Correlation Engine ingest module and central database. \n\n\
|
||||||
The Correlation Engine ingest module stores attributes of artifacts matching selected correlation types into a central database.\n\
|
The Correlation Engine ingest module stores attributes of artifacts matching selected correlation types into a central database.\n\
|
||||||
Stored attributes are used in future cases to correlate and analyzes files and artifacts during ingest.
|
Stored attributes are used in future cases to correlate and analyzes files and artifacts during ingest.
|
||||||
CentralRepoCommentDialog.fileLabel.text=File:
|
|
||||||
CentralRepoCommentDialog.commentLabel.text=Comment:
|
CentralRepoCommentDialog.commentLabel.text=Comment:
|
||||||
CentralRepoCommentDialog.pathLabel.text=
|
|
||||||
CentralRepoCommentDialog.okButton.text=&OK
|
CentralRepoCommentDialog.okButton.text=&OK
|
||||||
CentralRepoCommentDialog.cancelButton.text=C&ancel
|
CentralRepoCommentDialog.cancelButton.text=C&ancel
|
||||||
|
@ -31,14 +31,7 @@
|
|||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Component id="jScrollPane1" pref="500" max="32767" attributes="0"/>
|
<Component id="jScrollPane1" pref="500" max="32767" attributes="0"/>
|
||||||
<Group type="102" attributes="0">
|
<Group type="102" attributes="0">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Component id="commentLabel" min="-2" max="-2" 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"/>
|
<EmptySpace min="0" pref="451" max="32767" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
<Group type="102" alignment="0" attributes="0">
|
<Group type="102" alignment="0" attributes="0">
|
||||||
@ -55,21 +48,16 @@
|
|||||||
<DimensionLayout dim="1">
|
<DimensionLayout dim="1">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Group type="102" alignment="0" attributes="0">
|
<Group type="102" alignment="0" attributes="0">
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace min="-2" 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"/>
|
<Component id="commentLabel" min="-2" max="-2" attributes="0"/>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||||
<Component id="jScrollPane1" max="32767" attributes="0"/>
|
<Component id="jScrollPane1" max="32767" attributes="0"/>
|
||||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="3" attributes="0">
|
||||||
<Component id="okButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
<Component id="cancelButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
<Component id="cancelButton" min="-2" max="-2" attributes="0"/>
|
<Component id="okButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
@ -113,20 +101,6 @@
|
|||||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cancelButtonActionPerformed"/>
|
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cancelButtonActionPerformed"/>
|
||||||
</Events>
|
</Events>
|
||||||
</Component>
|
</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">
|
<Component class="javax.swing.JLabel" name="commentLabel">
|
||||||
<Properties>
|
<Properties>
|
||||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
@ -52,7 +52,6 @@ final class CentralRepoCommentDialog extends javax.swing.JDialog {
|
|||||||
currentComment = instance.getComment();
|
currentComment = instance.getComment();
|
||||||
}
|
}
|
||||||
|
|
||||||
pathLabel.setText(instance.getFilePath());
|
|
||||||
commentTextArea.setText(instance.getComment());
|
commentTextArea.setText(instance.getComment());
|
||||||
|
|
||||||
this.correlationAttribute = correlationAttribute;
|
this.correlationAttribute = correlationAttribute;
|
||||||
@ -103,8 +102,6 @@ final class CentralRepoCommentDialog extends javax.swing.JDialog {
|
|||||||
commentTextArea = new javax.swing.JTextArea();
|
commentTextArea = new javax.swing.JTextArea();
|
||||||
okButton = new javax.swing.JButton();
|
okButton = new javax.swing.JButton();
|
||||||
cancelButton = new javax.swing.JButton();
|
cancelButton = new javax.swing.JButton();
|
||||||
fileLabel = new javax.swing.JLabel();
|
|
||||||
pathLabel = new javax.swing.JLabel();
|
|
||||||
commentLabel = new javax.swing.JLabel();
|
commentLabel = new javax.swing.JLabel();
|
||||||
|
|
||||||
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
|
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
|
||||||
@ -131,10 +128,6 @@ final class CentralRepoCommentDialog extends javax.swing.JDialog {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
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
|
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());
|
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
|
||||||
@ -146,12 +139,7 @@ final class CentralRepoCommentDialog extends javax.swing.JDialog {
|
|||||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 500, Short.MAX_VALUE)
|
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 500, Short.MAX_VALUE)
|
||||||
.addGroup(layout.createSequentialGroup()
|
.addGroup(layout.createSequentialGroup()
|
||||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
.addComponent(commentLabel)
|
||||||
.addGroup(layout.createSequentialGroup()
|
|
||||||
.addComponent(fileLabel)
|
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
|
||||||
.addComponent(pathLabel))
|
|
||||||
.addComponent(commentLabel))
|
|
||||||
.addGap(0, 451, Short.MAX_VALUE))
|
.addGap(0, 451, Short.MAX_VALUE))
|
||||||
.addGroup(layout.createSequentialGroup()
|
.addGroup(layout.createSequentialGroup()
|
||||||
.addGap(0, 0, Short.MAX_VALUE)
|
.addGap(0, 0, Short.MAX_VALUE)
|
||||||
@ -164,17 +152,13 @@ final class CentralRepoCommentDialog extends javax.swing.JDialog {
|
|||||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addGroup(layout.createSequentialGroup()
|
.addGroup(layout.createSequentialGroup()
|
||||||
.addContainerGap()
|
.addContainerGap()
|
||||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
|
||||||
.addComponent(fileLabel)
|
|
||||||
.addComponent(pathLabel))
|
|
||||||
.addGap(19, 19, 19)
|
|
||||||
.addComponent(commentLabel)
|
.addComponent(commentLabel)
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addComponent(jScrollPane1)
|
.addComponent(jScrollPane1)
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||||
.addComponent(okButton)
|
.addComponent(cancelButton)
|
||||||
.addComponent(cancelButton))
|
.addComponent(okButton))
|
||||||
.addContainerGap())
|
.addContainerGap())
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -197,9 +181,7 @@ final class CentralRepoCommentDialog extends javax.swing.JDialog {
|
|||||||
private javax.swing.JButton cancelButton;
|
private javax.swing.JButton cancelButton;
|
||||||
private javax.swing.JLabel commentLabel;
|
private javax.swing.JLabel commentLabel;
|
||||||
private javax.swing.JTextArea commentTextArea;
|
private javax.swing.JTextArea commentTextArea;
|
||||||
private javax.swing.JLabel fileLabel;
|
|
||||||
private javax.swing.JScrollPane jScrollPane1;
|
private javax.swing.JScrollPane jScrollPane1;
|
||||||
private javax.swing.JButton okButton;
|
private javax.swing.JButton okButton;
|
||||||
private javax.swing.JLabel pathLabel;
|
|
||||||
// End of variables declaration//GEN-END:variables
|
// End of variables declaration//GEN-END:variables
|
||||||
}
|
}
|
||||||
|
@ -80,7 +80,7 @@
|
|||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
<DimensionLayout dim="1">
|
<DimensionLayout dim="1">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Component id="otherCasesPanel" pref="483" max="32767" attributes="0"/>
|
<Component id="otherCasesPanel" pref="59" max="32767" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
</Layout>
|
</Layout>
|
||||||
@ -106,7 +106,7 @@
|
|||||||
<EmptySpace min="0" pref="483" max="32767" attributes="0"/>
|
<EmptySpace min="0" pref="483" max="32767" attributes="0"/>
|
||||||
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
|
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
|
||||||
<Group type="102" alignment="0" attributes="0">
|
<Group type="102" alignment="0" attributes="0">
|
||||||
<Component id="tableContainerPanel" pref="483" max="32767" attributes="0"/>
|
<Component id="tableContainerPanel" pref="59" max="32767" attributes="0"/>
|
||||||
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
|
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
@ -133,23 +133,18 @@
|
|||||||
<Component id="earliestCaseLabel" min="-2" max="-2" attributes="0"/>
|
<Component id="earliestCaseLabel" min="-2" max="-2" attributes="0"/>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Component id="earliestCaseDate" min="-2" max="-2" attributes="0"/>
|
<Component id="earliestCaseDate" min="-2" max="-2" attributes="0"/>
|
||||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
<EmptySpace max="32767" attributes="0"/>
|
||||||
<Component id="tableStatusPanelLabel" max="32767" attributes="0"/>
|
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
<DimensionLayout dim="1">
|
<DimensionLayout dim="1">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Group type="102" alignment="1" attributes="0">
|
<Group type="102" alignment="1" attributes="0">
|
||||||
<Component id="tableScrollPane" pref="176" max="32767" attributes="0"/>
|
<Component id="tableScrollPane" pref="27" max="32767" attributes="0"/>
|
||||||
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
<EmptySpace min="-2" pref="2" max="-2" attributes="0"/>
|
||||||
<Group type="103" groupAlignment="1" attributes="0">
|
<Group type="103" groupAlignment="3" attributes="0">
|
||||||
<Group type="103" groupAlignment="3" attributes="0">
|
<Component id="earliestCaseLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
<Component id="earliestCaseLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
<Component id="earliestCaseDate" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
<Component id="earliestCaseDate" alignment="3" min="-2" max="-2" attributes="0"/>
|
|
||||||
</Group>
|
|
||||||
<Component id="tableStatusPanelLabel" min="-2" pref="16" max="-2" attributes="0"/>
|
|
||||||
</Group>
|
</Group>
|
||||||
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
||||||
<Component id="tableStatusPanel" min="-2" max="-2" attributes="0"/>
|
<Component id="tableStatusPanel" min="-2" max="-2" attributes="0"/>
|
||||||
@ -230,13 +225,6 @@
|
|||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
</Layout>
|
</Layout>
|
||||||
</Container>
|
</Container>
|
||||||
<Component class="javax.swing.JLabel" name="tableStatusPanelLabel">
|
|
||||||
<Properties>
|
|
||||||
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
|
||||||
<Color blue="33" green="0" red="ff" type="rgb"/>
|
|
||||||
</Property>
|
|
||||||
</Properties>
|
|
||||||
</Component>
|
|
||||||
</SubComponents>
|
</SubComponents>
|
||||||
</Container>
|
</Container>
|
||||||
</SubComponents>
|
</SubComponents>
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
package org.sleuthkit.autopsy.centralrepository.contentviewer;
|
package org.sleuthkit.autopsy.centralrepository.contentviewer;
|
||||||
|
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
|
import java.awt.FontMetrics;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
@ -87,7 +88,10 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
|
|
||||||
private static final long serialVersionUID = -1L;
|
private static final long serialVersionUID = -1L;
|
||||||
|
|
||||||
private final static Logger logger = Logger.getLogger(DataContentViewerOtherCases.class.getName());
|
private static final Logger logger = Logger.getLogger(DataContentViewerOtherCases.class.getName());
|
||||||
|
|
||||||
|
private static final int DEFAULT_MIN_CELL_WIDTH = 15;
|
||||||
|
private static final int CELL_TEXT_WIDTH_PADDING = 5;
|
||||||
|
|
||||||
private final DataContentViewerOtherCasesTableModel tableModel;
|
private final DataContentViewerOtherCasesTableModel tableModel;
|
||||||
private final Collection<CorrelationAttribute> correlationAttributes;
|
private final Collection<CorrelationAttribute> correlationAttributes;
|
||||||
@ -127,7 +131,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
showCommonalityDetails();
|
showCommonalityDetails();
|
||||||
} else if (jmi.equals(addCommentMenuItem)) {
|
} else if (jmi.equals(addCommentMenuItem)) {
|
||||||
try {
|
try {
|
||||||
OtherOccurrenceNodeData selectedNode = (OtherOccurrenceNodeData) tableModel.getRow(otherCasesTable.getSelectedRow());
|
OtherOccurrenceNodeInstanceData selectedNode = (OtherOccurrenceNodeInstanceData) tableModel.getRow(otherCasesTable.getSelectedRow());
|
||||||
AddEditCentralRepoCommentAction action = new AddEditCentralRepoCommentAction(selectedNode.createCorrelationAttribute());
|
AddEditCentralRepoCommentAction action = new AddEditCentralRepoCommentAction(selectedNode.createCorrelationAttribute());
|
||||||
action.actionPerformed(null);
|
action.actionPerformed(null);
|
||||||
String currentComment = action.getComment();
|
String currentComment = action.getComment();
|
||||||
@ -151,7 +155,6 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
// Set background of every nth row as light grey.
|
// Set background of every nth row as light grey.
|
||||||
TableCellRenderer renderer = new DataContentViewerOtherCasesTableCellRenderer();
|
TableCellRenderer renderer = new DataContentViewerOtherCasesTableCellRenderer();
|
||||||
otherCasesTable.setDefaultRenderer(Object.class, renderer);
|
otherCasesTable.setDefaultRenderer(Object.class, renderer);
|
||||||
tableStatusPanelLabel.setVisible(false);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,7 +218,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
if (-1 != selectedRowViewIdx) {
|
if (-1 != selectedRowViewIdx) {
|
||||||
EamDb dbManager = EamDb.getInstance();
|
EamDb dbManager = EamDb.getInstance();
|
||||||
int selectedRowModelIdx = otherCasesTable.convertRowIndexToModel(selectedRowViewIdx);
|
int selectedRowModelIdx = otherCasesTable.convertRowIndexToModel(selectedRowViewIdx);
|
||||||
OtherOccurrenceNodeData nodeData = (OtherOccurrenceNodeData) tableModel.getRow(selectedRowModelIdx);
|
OtherOccurrenceNodeInstanceData nodeData = (OtherOccurrenceNodeInstanceData) tableModel.getRow(selectedRowModelIdx);
|
||||||
CorrelationCase eamCasePartial = nodeData.getCorrelationAttributeInstance().getCorrelationCase();
|
CorrelationCase eamCasePartial = nodeData.getCorrelationAttributeInstance().getCorrelationCase();
|
||||||
if (eamCasePartial == null) {
|
if (eamCasePartial == null) {
|
||||||
JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
|
JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
|
||||||
@ -478,12 +481,12 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
|
|
||||||
@Messages({"DataContentViewerOtherCases.earliestCaseNotAvailable= Not Enabled."})
|
@Messages({"DataContentViewerOtherCases.earliestCaseNotAvailable= Not Enabled."})
|
||||||
/**
|
/**
|
||||||
* Gets the list of Eam Cases and determines the earliest case creation date.
|
* Gets the list of Eam Cases and determines the earliest case creation
|
||||||
* Sets the label to display the earliest date string to the user.
|
* date. Sets the label to display the earliest date string to the user.
|
||||||
*/
|
*/
|
||||||
private void setEarliestCaseDate() {
|
private void setEarliestCaseDate() {
|
||||||
String dateStringDisplay = Bundle.DataContentViewerOtherCases_earliestCaseNotAvailable();
|
String dateStringDisplay = Bundle.DataContentViewerOtherCases_earliestCaseNotAvailable();
|
||||||
|
|
||||||
if (EamDb.isEnabled()) {
|
if (EamDb.isEnabled()) {
|
||||||
LocalDateTime earliestDate = LocalDateTime.now(DateTimeZone.UTC);
|
LocalDateTime earliestDate = LocalDateTime.now(DateTimeZone.UTC);
|
||||||
DateFormat datetimeFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss", Locale.US);
|
DateFormat datetimeFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss", Locale.US);
|
||||||
@ -491,15 +494,15 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
EamDb dbManager = EamDb.getInstance();
|
EamDb dbManager = EamDb.getInstance();
|
||||||
List<CorrelationCase> cases = dbManager.getCases();
|
List<CorrelationCase> cases = dbManager.getCases();
|
||||||
for (CorrelationCase aCase : cases) {
|
for (CorrelationCase aCase : cases) {
|
||||||
LocalDateTime caseDate = LocalDateTime.fromDateFields(datetimeFormat.parse(aCase.getCreationDate()));
|
LocalDateTime caseDate = LocalDateTime.fromDateFields(datetimeFormat.parse(aCase.getCreationDate()));
|
||||||
|
|
||||||
if (caseDate.isBefore(earliestDate)) {
|
if (caseDate.isBefore(earliestDate)) {
|
||||||
earliestDate = caseDate;
|
earliestDate = caseDate;
|
||||||
dateStringDisplay = aCase.getCreationDate();
|
dateStringDisplay = aCase.getCreationDate();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (EamDbException ex) {
|
} catch (EamDbException ex) {
|
||||||
logger.log(Level.SEVERE, "Error getting list of cases from database.", ex); // NON-NLS
|
logger.log(Level.SEVERE, "Error getting list of cases from database.", ex); // NON-NLS
|
||||||
} catch (ParseException ex) {
|
} catch (ParseException ex) {
|
||||||
@ -511,10 +514,10 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Query the central repo database (if enabled) and the case database to find all
|
* Query the central repo database (if enabled) and the case database to
|
||||||
* artifact instances correlated to the given central repository artifact. If the
|
* find all artifact instances correlated to the given central repository
|
||||||
* central repo is not enabled, this will only return files from the current case
|
* artifact. If the central repo is not enabled, this will only return files
|
||||||
* with matching MD5 hashes.
|
* from the current case with matching MD5 hashes.
|
||||||
*
|
*
|
||||||
* @param corAttr CorrelationAttribute to query for
|
* @param corAttr CorrelationAttribute to query for
|
||||||
* @param dataSourceName Data source to filter results
|
* @param dataSourceName Data source to filter results
|
||||||
@ -522,19 +525,19 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
*
|
*
|
||||||
* @return A collection of correlated artifact instances
|
* @return A collection of correlated artifact instances
|
||||||
*/
|
*/
|
||||||
private Map<UniquePathKey,OtherOccurrenceNodeData> getCorrelatedInstances(CorrelationAttribute corAttr, String dataSourceName, String deviceId) {
|
private Map<UniquePathKey, OtherOccurrenceNodeInstanceData> getCorrelatedInstances(CorrelationAttribute corAttr, String dataSourceName, String deviceId) {
|
||||||
// @@@ Check exception
|
// @@@ Check exception
|
||||||
try {
|
try {
|
||||||
final Case openCase = Case.getCurrentCase();
|
final Case openCase = Case.getCurrentCase();
|
||||||
String caseUUID = openCase.getName();
|
String caseUUID = openCase.getName();
|
||||||
|
|
||||||
HashMap<UniquePathKey,OtherOccurrenceNodeData> nodeDataMap = new HashMap<>();
|
HashMap<UniquePathKey, OtherOccurrenceNodeInstanceData> nodeDataMap = new HashMap<>();
|
||||||
|
|
||||||
if (EamDb.isEnabled()) {
|
if (EamDb.isEnabled()) {
|
||||||
List<CorrelationAttributeInstance> instances = EamDb.getInstance().getArtifactInstancesByTypeValue(corAttr.getCorrelationType(), corAttr.getCorrelationValue());
|
List<CorrelationAttributeInstance> instances = EamDb.getInstance().getArtifactInstancesByTypeValue(corAttr.getCorrelationType(), corAttr.getCorrelationValue());
|
||||||
|
|
||||||
for (CorrelationAttributeInstance artifactInstance:instances) {
|
for (CorrelationAttributeInstance artifactInstance : instances) {
|
||||||
|
|
||||||
// Only add the attribute if it isn't the object the user selected.
|
// 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:
|
// We consider it to be a different object if at least one of the following is true:
|
||||||
// - the case UUID is different
|
// - the case UUID is different
|
||||||
@ -546,14 +549,14 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
|| !artifactInstance.getCorrelationDataSource().getDeviceID().equals(deviceId)
|
|| !artifactInstance.getCorrelationDataSource().getDeviceID().equals(deviceId)
|
||||||
|| !artifactInstance.getFilePath().equalsIgnoreCase(file.getParentPath() + file.getName())) {
|
|| !artifactInstance.getFilePath().equalsIgnoreCase(file.getParentPath() + file.getName())) {
|
||||||
|
|
||||||
OtherOccurrenceNodeData newNode = new OtherOccurrenceNodeData(artifactInstance, corAttr.getCorrelationType(), corAttr.getCorrelationValue());
|
OtherOccurrenceNodeInstanceData newNode = new OtherOccurrenceNodeInstanceData(artifactInstance, corAttr.getCorrelationType(), corAttr.getCorrelationValue());
|
||||||
UniquePathKey uniquePathKey = new UniquePathKey(newNode);
|
UniquePathKey uniquePathKey = new UniquePathKey(newNode);
|
||||||
nodeDataMap.put(uniquePathKey, newNode);
|
nodeDataMap.put(uniquePathKey, newNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (corAttr.getCorrelationType().getDisplayName().equals("Files")) {
|
if (corAttr.getCorrelationType().getDisplayName().equals("Files")) {
|
||||||
List<AbstractFile> caseDbFiles = getCaseDbMatches(corAttr, openCase);
|
List<AbstractFile> caseDbFiles = getCaseDbMatches(corAttr, openCase);
|
||||||
|
|
||||||
for (AbstractFile caseDbFile : caseDbFiles) {
|
for (AbstractFile caseDbFile : caseDbFiles) {
|
||||||
@ -576,13 +579,17 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all other abstract files in the current case with the same MD5 as the selected node.
|
* 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 corAttr The CorrelationAttribute containing the MD5 to search for
|
||||||
* @param openCase The current case
|
* @param openCase The current case
|
||||||
|
*
|
||||||
* @return List of matching AbstractFile objects
|
* @return List of matching AbstractFile objects
|
||||||
|
*
|
||||||
* @throws NoCurrentCaseException
|
* @throws NoCurrentCaseException
|
||||||
* @throws TskCoreException
|
* @throws TskCoreException
|
||||||
* @throws EamDbException
|
* @throws EamDbException
|
||||||
*/
|
*/
|
||||||
private List<AbstractFile> getCaseDbMatches(CorrelationAttribute corAttr, Case openCase) throws NoCurrentCaseException, TskCoreException, EamDbException {
|
private List<AbstractFile> getCaseDbMatches(CorrelationAttribute corAttr, Case openCase) throws NoCurrentCaseException, TskCoreException, EamDbException {
|
||||||
String md5 = corAttr.getCorrelationValue();
|
String md5 = corAttr.getCorrelationValue();
|
||||||
@ -602,18 +609,18 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the file to the nodeDataMap map if it does not already exist
|
* Adds the file to the nodeDataMap map if it does not already exist
|
||||||
*
|
*
|
||||||
* @param autopsyCase
|
* @param autopsyCase
|
||||||
* @param nodeDataMap
|
* @param nodeDataMap
|
||||||
* @param newFile
|
* @param newFile
|
||||||
*
|
*
|
||||||
* @throws TskCoreException
|
* @throws TskCoreException
|
||||||
* @throws EamDbException
|
* @throws EamDbException
|
||||||
*/
|
*/
|
||||||
private void addOrUpdateNodeData(final Case autopsyCase, Map<UniquePathKey,OtherOccurrenceNodeData> nodeDataMap, AbstractFile newFile) throws TskCoreException, EamDbException {
|
private void addOrUpdateNodeData(final Case autopsyCase, Map<UniquePathKey, OtherOccurrenceNodeInstanceData> nodeDataMap, AbstractFile newFile) throws TskCoreException, EamDbException {
|
||||||
|
|
||||||
OtherOccurrenceNodeData newNode = new OtherOccurrenceNodeData(newFile, autopsyCase);
|
OtherOccurrenceNodeInstanceData newNode = new OtherOccurrenceNodeInstanceData(newFile, autopsyCase);
|
||||||
|
|
||||||
// If the caseDB object has a notable tag associated with it, update
|
// If the caseDB object has a notable tag associated with it, update
|
||||||
// the known status to BAD
|
// the known status to BAD
|
||||||
if (newNode.getKnown() != TskData.FileKnown.BAD) {
|
if (newNode.getKnown() != TskData.FileKnown.BAD) {
|
||||||
@ -629,13 +636,13 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
|
|
||||||
// Make a key to see if the file is already in the map
|
// Make a key to see if the file is already in the map
|
||||||
UniquePathKey uniquePathKey = new UniquePathKey(newNode);
|
UniquePathKey uniquePathKey = new UniquePathKey(newNode);
|
||||||
|
|
||||||
// If this node is already in the list, the only thing we need to do is
|
// 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.
|
// 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.
|
// Otherwise this is a new node so add the new node to the map.
|
||||||
if (nodeDataMap.containsKey(uniquePathKey)) {
|
if (nodeDataMap.containsKey(uniquePathKey)) {
|
||||||
if (newNode.getKnown() == TskData.FileKnown.BAD) {
|
if (newNode.getKnown() == TskData.FileKnown.BAD) {
|
||||||
OtherOccurrenceNodeData prevInstance = nodeDataMap.get(uniquePathKey);
|
OtherOccurrenceNodeInstanceData prevInstance = nodeDataMap.get(uniquePathKey);
|
||||||
prevInstance.updateKnown(newNode.getKnown());
|
prevInstance.updateKnown(newNode.getKnown());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -658,7 +665,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
} else {
|
} else {
|
||||||
return this.file != null
|
return this.file != null
|
||||||
&& this.file.getSize() > 0
|
&& this.file.getSize() > 0
|
||||||
&& ((this.file.getMd5Hash() != null) && ( ! this.file.getMd5Hash().isEmpty()));
|
&& ((this.file.getMd5Hash() != null) && (!this.file.getMd5Hash().isEmpty()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -681,8 +688,10 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
*
|
*
|
||||||
* @param node The node being viewed.
|
* @param node The node being viewed.
|
||||||
*/
|
*/
|
||||||
@Messages({"DataContentViewerOtherCases.table.isempty=There are no associated artifacts or files from other occurrences to display.",
|
@Messages({
|
||||||
"DataContentViewerOtherCases.table.noArtifacts=Correlation cannot be performed on the selected file."})
|
"DataContentViewerOtherCases.table.noArtifacts=Item has no attributes with which to search.",
|
||||||
|
"DataContentViewerOtherCases.table.noResultsFound=No results found."
|
||||||
|
})
|
||||||
private void populateTable(Node node) {
|
private void populateTable(Node node) {
|
||||||
String dataSourceName = "";
|
String dataSourceName = "";
|
||||||
String deviceId = "";
|
String deviceId = "";
|
||||||
@ -700,7 +709,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
// get the attributes we can correlate on
|
// get the attributes we can correlate on
|
||||||
correlationAttributes.addAll(getCorrelationAttributesFromNode(node));
|
correlationAttributes.addAll(getCorrelationAttributesFromNode(node));
|
||||||
for (CorrelationAttribute corAttr : correlationAttributes) {
|
for (CorrelationAttribute corAttr : correlationAttributes) {
|
||||||
Map<UniquePathKey,OtherOccurrenceNodeData> correlatedNodeDataMap = new HashMap<>(0);
|
Map<UniquePathKey, OtherOccurrenceNodeInstanceData> correlatedNodeDataMap = new HashMap<>(0);
|
||||||
|
|
||||||
// get correlation and reference set instances from DB
|
// get correlation and reference set instances from DB
|
||||||
correlatedNodeDataMap.putAll(getCorrelatedInstances(corAttr, dataSourceName, deviceId));
|
correlatedNodeDataMap.putAll(getCorrelatedInstances(corAttr, dataSourceName, deviceId));
|
||||||
@ -712,36 +721,45 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (correlationAttributes.isEmpty()) {
|
if (correlationAttributes.isEmpty()) {
|
||||||
// @@@ BC: We should have a more descriptive message than this. Mention that the file didn't have a MD5, etc.
|
tableModel.addNodeData(new OtherOccurrenceNodeMessageData(Bundle.DataContentViewerOtherCases_table_noArtifacts()));
|
||||||
displayMessageOnTableStatusPanel(Bundle.DataContentViewerOtherCases_table_noArtifacts());
|
setColumnWidthToText(0, Bundle.DataContentViewerOtherCases_table_noArtifacts());
|
||||||
} else if (0 == tableModel.getRowCount()) {
|
} else if (0 == tableModel.getRowCount()) {
|
||||||
displayMessageOnTableStatusPanel(Bundle.DataContentViewerOtherCases_table_isempty());
|
tableModel.addNodeData(new OtherOccurrenceNodeMessageData(Bundle.DataContentViewerOtherCases_table_noResultsFound()));
|
||||||
|
setColumnWidthToText(0, Bundle.DataContentViewerOtherCases_table_noResultsFound());
|
||||||
} else {
|
} else {
|
||||||
clearMessageOnTableStatusPanel();
|
|
||||||
setColumnWidths();
|
setColumnWidths();
|
||||||
}
|
}
|
||||||
setEarliestCaseDate();
|
setEarliestCaseDate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adjust a given column for the text provided.
|
||||||
|
*
|
||||||
|
* @param columnIndex The index of the column to adjust.
|
||||||
|
* @param text The text whose length will be used to adjust the
|
||||||
|
* column width.
|
||||||
|
*/
|
||||||
|
private void setColumnWidthToText(int columnIndex, String text) {
|
||||||
|
TableColumn column = otherCasesTable.getColumnModel().getColumn(columnIndex);
|
||||||
|
FontMetrics fontMetrics = otherCasesTable.getFontMetrics(otherCasesTable.getFont());
|
||||||
|
int stringWidth = fontMetrics.stringWidth(text);
|
||||||
|
column.setMinWidth(stringWidth + CELL_TEXT_WIDTH_PADDING);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adjust column widths to their preferred values.
|
||||||
|
*/
|
||||||
private void setColumnWidths() {
|
private void setColumnWidths() {
|
||||||
for (int idx = 0; idx < tableModel.getColumnCount(); idx++) {
|
for (int idx = 0; idx < tableModel.getColumnCount(); idx++) {
|
||||||
TableColumn column = otherCasesTable.getColumnModel().getColumn(idx);
|
TableColumn column = otherCasesTable.getColumnModel().getColumn(idx);
|
||||||
int colWidth = tableModel.getColumnPreferredWidth(idx);
|
column.setMinWidth(DEFAULT_MIN_CELL_WIDTH);
|
||||||
if (0 < colWidth) {
|
int columnWidth = tableModel.getColumnPreferredWidth(idx);
|
||||||
column.setPreferredWidth(colWidth);
|
if (columnWidth > 0) {
|
||||||
|
column.setPreferredWidth(columnWidth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void displayMessageOnTableStatusPanel(String message) {
|
|
||||||
tableStatusPanelLabel.setText(message);
|
|
||||||
tableStatusPanelLabel.setVisible(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void clearMessageOnTableStatusPanel() {
|
|
||||||
tableStatusPanelLabel.setVisible(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is called from within the constructor to initialize the form.
|
* 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
|
* WARNING: Do NOT modify this code. The content of this method is always
|
||||||
@ -765,7 +783,6 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
earliestCaseLabel = new javax.swing.JLabel();
|
earliestCaseLabel = new javax.swing.JLabel();
|
||||||
earliestCaseDate = new javax.swing.JLabel();
|
earliestCaseDate = new javax.swing.JLabel();
|
||||||
tableStatusPanel = new javax.swing.JPanel();
|
tableStatusPanel = new javax.swing.JPanel();
|
||||||
tableStatusPanelLabel = new javax.swing.JLabel();
|
|
||||||
|
|
||||||
rightClickPopupMenu.addPopupMenuListener(new javax.swing.event.PopupMenuListener() {
|
rightClickPopupMenu.addPopupMenuListener(new javax.swing.event.PopupMenuListener() {
|
||||||
public void popupMenuCanceled(javax.swing.event.PopupMenuEvent evt) {
|
public void popupMenuCanceled(javax.swing.event.PopupMenuEvent evt) {
|
||||||
@ -827,8 +844,6 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
.addGap(0, 16, Short.MAX_VALUE)
|
.addGap(0, 16, Short.MAX_VALUE)
|
||||||
);
|
);
|
||||||
|
|
||||||
tableStatusPanelLabel.setForeground(new java.awt.Color(255, 0, 51));
|
|
||||||
|
|
||||||
javax.swing.GroupLayout tableContainerPanelLayout = new javax.swing.GroupLayout(tableContainerPanel);
|
javax.swing.GroupLayout tableContainerPanelLayout = new javax.swing.GroupLayout(tableContainerPanel);
|
||||||
tableContainerPanel.setLayout(tableContainerPanelLayout);
|
tableContainerPanel.setLayout(tableContainerPanelLayout);
|
||||||
tableContainerPanelLayout.setHorizontalGroup(
|
tableContainerPanelLayout.setHorizontalGroup(
|
||||||
@ -841,20 +856,16 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
.addComponent(earliestCaseLabel)
|
.addComponent(earliestCaseLabel)
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addComponent(earliestCaseDate)
|
.addComponent(earliestCaseDate)
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||||
.addComponent(tableStatusPanelLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
|
||||||
.addContainerGap())
|
|
||||||
);
|
);
|
||||||
tableContainerPanelLayout.setVerticalGroup(
|
tableContainerPanelLayout.setVerticalGroup(
|
||||||
tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, tableContainerPanelLayout.createSequentialGroup()
|
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, tableContainerPanelLayout.createSequentialGroup()
|
||||||
.addComponent(tableScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 176, Short.MAX_VALUE)
|
.addComponent(tableScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 27, Short.MAX_VALUE)
|
||||||
.addGap(0, 0, 0)
|
.addGap(2, 2, 2)
|
||||||
.addGroup(tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
.addGroup(tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||||
.addGroup(tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
.addComponent(earliestCaseLabel)
|
||||||
.addComponent(earliestCaseLabel)
|
.addComponent(earliestCaseDate))
|
||||||
.addComponent(earliestCaseDate))
|
|
||||||
.addComponent(tableStatusPanelLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE))
|
|
||||||
.addGap(0, 0, 0)
|
.addGap(0, 0, 0)
|
||||||
.addComponent(tableStatusPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
.addComponent(tableStatusPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
.addGap(0, 0, 0))
|
.addGap(0, 0, 0))
|
||||||
@ -873,7 +884,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
.addGap(0, 483, Short.MAX_VALUE)
|
.addGap(0, 483, Short.MAX_VALUE)
|
||||||
.addGroup(otherCasesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
.addGroup(otherCasesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addGroup(otherCasesPanelLayout.createSequentialGroup()
|
.addGroup(otherCasesPanelLayout.createSequentialGroup()
|
||||||
.addComponent(tableContainerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 483, Short.MAX_VALUE)
|
.addComponent(tableContainerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 59, Short.MAX_VALUE)
|
||||||
.addGap(0, 0, 0)))
|
.addGap(0, 0, 0)))
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -885,7 +896,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
);
|
);
|
||||||
layout.setVerticalGroup(
|
layout.setVerticalGroup(
|
||||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addComponent(otherCasesPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 483, Short.MAX_VALUE)
|
.addComponent(otherCasesPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 59, Short.MAX_VALUE)
|
||||||
);
|
);
|
||||||
}// </editor-fold>//GEN-END:initComponents
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
|
|
||||||
@ -895,8 +906,9 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
if (EamDbUtil.useCentralRepo() && otherCasesTable.getSelectedRowCount() == 1) {
|
if (EamDbUtil.useCentralRepo() && otherCasesTable.getSelectedRowCount() == 1) {
|
||||||
int rowIndex = otherCasesTable.getSelectedRow();
|
int rowIndex = otherCasesTable.getSelectedRow();
|
||||||
OtherOccurrenceNodeData selectedNode = (OtherOccurrenceNodeData) tableModel.getRow(rowIndex);
|
OtherOccurrenceNodeData selectedNode = (OtherOccurrenceNodeData) tableModel.getRow(rowIndex);
|
||||||
if (selectedNode.isCentralRepoNode()) {
|
if (selectedNode instanceof OtherOccurrenceNodeInstanceData) {
|
||||||
enableCentralRepoActions = true;
|
OtherOccurrenceNodeInstanceData instanceData = (OtherOccurrenceNodeInstanceData) selectedNode;
|
||||||
|
enableCentralRepoActions = instanceData.isCentralRepoNode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -920,7 +932,6 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
private javax.swing.JPanel tableContainerPanel;
|
private javax.swing.JPanel tableContainerPanel;
|
||||||
private javax.swing.JScrollPane tableScrollPane;
|
private javax.swing.JScrollPane tableScrollPane;
|
||||||
private javax.swing.JPanel tableStatusPanel;
|
private javax.swing.JPanel tableStatusPanel;
|
||||||
private javax.swing.JLabel tableStatusPanelLabel;
|
|
||||||
// End of variables declaration//GEN-END:variables
|
// End of variables declaration//GEN-END:variables
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -933,7 +944,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
private final String filePath;
|
private final String filePath;
|
||||||
private final String type;
|
private final String type;
|
||||||
|
|
||||||
UniquePathKey(OtherOccurrenceNodeData nodeData) {
|
UniquePathKey(OtherOccurrenceNodeInstanceData nodeData) {
|
||||||
super();
|
super();
|
||||||
dataSourceID = nodeData.getDeviceID();
|
dataSourceID = nodeData.getDeviceID();
|
||||||
if (nodeData.getFilePath() != null) {
|
if (nodeData.getFilePath() != null) {
|
||||||
@ -947,9 +958,9 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
|
|||||||
@Override
|
@Override
|
||||||
public boolean equals(Object other) {
|
public boolean equals(Object other) {
|
||||||
if (other instanceof UniquePathKey) {
|
if (other instanceof UniquePathKey) {
|
||||||
UniquePathKey otherKey = (UniquePathKey)(other);
|
UniquePathKey otherKey = (UniquePathKey) (other);
|
||||||
return ( Objects.equals(otherKey.dataSourceID, this.dataSourceID)
|
return (Objects.equals(otherKey.dataSourceID, this.dataSourceID)
|
||||||
&& Objects.equals(otherKey.filePath, this.filePath)
|
&& Objects.equals(otherKey.filePath, this.filePath)
|
||||||
&& Objects.equals(otherKey.type, this.type));
|
&& Objects.equals(otherKey.type, this.type));
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Central Repository
|
* Central Repository
|
||||||
*
|
*
|
||||||
* Copyright 2015-2017 Basis Technology Corp.
|
* Copyright 2015-2018 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -22,8 +22,6 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.swing.table.AbstractTableModel;
|
import javax.swing.table.AbstractTableModel;
|
||||||
import org.openide.util.NbBundle.Messages;
|
import org.openide.util.NbBundle.Messages;
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttribute;
|
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Model for cells in data content viewer table
|
* Model for cells in data content viewer table
|
||||||
@ -34,8 +32,8 @@ public class DataContentViewerOtherCasesTableModel extends AbstractTableModel {
|
|||||||
"DataContentViewerOtherCasesTableModel.device=Device",
|
"DataContentViewerOtherCasesTableModel.device=Device",
|
||||||
"DataContentViewerOtherCasesTableModel.dataSource=Data Source",
|
"DataContentViewerOtherCasesTableModel.dataSource=Data Source",
|
||||||
"DataContentViewerOtherCasesTableModel.path=Path",
|
"DataContentViewerOtherCasesTableModel.path=Path",
|
||||||
"DataContentViewerOtherCasesTableModel.type=Correlation Type",
|
"DataContentViewerOtherCasesTableModel.attribute=Matched Attribute",
|
||||||
"DataContentViewerOtherCasesTableModel.value=Correlation Value",
|
"DataContentViewerOtherCasesTableModel.value=Attribute Value",
|
||||||
"DataContentViewerOtherCasesTableModel.known=Known",
|
"DataContentViewerOtherCasesTableModel.known=Known",
|
||||||
"DataContentViewerOtherCasesTableModel.comment=Comment",
|
"DataContentViewerOtherCasesTableModel.comment=Comment",
|
||||||
"DataContentViewerOtherCasesTableModel.noData=No Data.",})
|
"DataContentViewerOtherCasesTableModel.noData=No Data.",})
|
||||||
@ -44,7 +42,7 @@ public class DataContentViewerOtherCasesTableModel extends AbstractTableModel {
|
|||||||
// If order is changed, update the CellRenderer to ensure correct row coloring.
|
// If order is changed, update the CellRenderer to ensure correct row coloring.
|
||||||
CASE_NAME(Bundle.DataContentViewerOtherCasesTableModel_case(), 100),
|
CASE_NAME(Bundle.DataContentViewerOtherCasesTableModel_case(), 100),
|
||||||
DATA_SOURCE(Bundle.DataContentViewerOtherCasesTableModel_dataSource(), 100),
|
DATA_SOURCE(Bundle.DataContentViewerOtherCasesTableModel_dataSource(), 100),
|
||||||
TYPE(Bundle.DataContentViewerOtherCasesTableModel_type(), 100),
|
ATTRIBUTE(Bundle.DataContentViewerOtherCasesTableModel_attribute(), 125),
|
||||||
VALUE(Bundle.DataContentViewerOtherCasesTableModel_value(), 200),
|
VALUE(Bundle.DataContentViewerOtherCasesTableModel_value(), 200),
|
||||||
KNOWN(Bundle.DataContentViewerOtherCasesTableModel_known(), 50),
|
KNOWN(Bundle.DataContentViewerOtherCasesTableModel_known(), 50),
|
||||||
FILE_PATH(Bundle.DataContentViewerOtherCasesTableModel_path(), 450),
|
FILE_PATH(Bundle.DataContentViewerOtherCasesTableModel_path(), 450),
|
||||||
@ -109,26 +107,41 @@ public class DataContentViewerOtherCasesTableModel extends AbstractTableModel {
|
|||||||
return Bundle.DataContentViewerOtherCasesTableModel_noData();
|
return Bundle.DataContentViewerOtherCasesTableModel_noData();
|
||||||
}
|
}
|
||||||
|
|
||||||
return mapValueById(rowIdx, TableColumns.values()[colIdx]);
|
OtherOccurrenceNodeData nodeData = nodeDataList.get(rowIdx);
|
||||||
}
|
TableColumns columnId = TableColumns.values()[colIdx];
|
||||||
|
if (nodeData instanceof OtherOccurrenceNodeMessageData) {
|
||||||
Object getRow(int rowIdx) {
|
return mapNodeMessageData((OtherOccurrenceNodeMessageData) nodeData, columnId);
|
||||||
return nodeDataList.get(rowIdx);
|
}
|
||||||
|
return mapNodeInstanceData((OtherOccurrenceNodeInstanceData) nodeData, columnId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map a rowIdx and colId to the value in that cell.
|
* Map a column ID to the value in that cell for node message data.
|
||||||
*
|
*
|
||||||
* @param rowIdx Index of row to search
|
* @param nodeData The node message data.
|
||||||
* @param colId ID of column to search
|
* @param columnId The ID of the cell column.
|
||||||
*
|
*
|
||||||
* @return value in the cell
|
* @return The value in the cell.
|
||||||
*/
|
*/
|
||||||
private Object mapValueById(int rowIdx, TableColumns colId) {
|
private Object mapNodeMessageData(OtherOccurrenceNodeMessageData nodeData, TableColumns columnId) {
|
||||||
OtherOccurrenceNodeData nodeData = nodeDataList.get(rowIdx);
|
if (columnId == TableColumns.CASE_NAME) {
|
||||||
|
return nodeData.getDisplayMessage();
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map a column ID to the value in that cell for node instance data.
|
||||||
|
*
|
||||||
|
* @param nodeData The node instance data.
|
||||||
|
* @param columnId The ID of the cell column.
|
||||||
|
*
|
||||||
|
* @return The value in the cell.
|
||||||
|
*/
|
||||||
|
private Object mapNodeInstanceData(OtherOccurrenceNodeInstanceData nodeData, TableColumns columnId) {
|
||||||
String value = Bundle.DataContentViewerOtherCasesTableModel_noData();
|
String value = Bundle.DataContentViewerOtherCasesTableModel_noData();
|
||||||
|
|
||||||
switch (colId) {
|
switch (columnId) {
|
||||||
case CASE_NAME:
|
case CASE_NAME:
|
||||||
if (null != nodeData.getCaseName()) {
|
if (null != nodeData.getCaseName()) {
|
||||||
value = nodeData.getCaseName();
|
value = nodeData.getCaseName();
|
||||||
@ -147,7 +160,7 @@ public class DataContentViewerOtherCasesTableModel extends AbstractTableModel {
|
|||||||
case FILE_PATH:
|
case FILE_PATH:
|
||||||
value = nodeData.getFilePath();
|
value = nodeData.getFilePath();
|
||||||
break;
|
break;
|
||||||
case TYPE:
|
case ATTRIBUTE:
|
||||||
value = nodeData.getType();
|
value = nodeData.getType();
|
||||||
break;
|
break;
|
||||||
case VALUE:
|
case VALUE:
|
||||||
@ -159,10 +172,16 @@ public class DataContentViewerOtherCasesTableModel extends AbstractTableModel {
|
|||||||
case COMMENT:
|
case COMMENT:
|
||||||
value = nodeData.getComment();
|
value = nodeData.getComment();
|
||||||
break;
|
break;
|
||||||
|
default: // This shouldn't occur! Use default "No data" value.
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Object getRow(int rowIdx) {
|
||||||
|
return nodeDataList.get(rowIdx);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class<String> getColumnClass(int colIdx) {
|
public Class<String> getColumnClass(int colIdx) {
|
||||||
return String.class;
|
return String.class;
|
||||||
@ -178,6 +197,9 @@ public class DataContentViewerOtherCasesTableModel extends AbstractTableModel {
|
|||||||
fireTableDataChanged();
|
fireTableDataChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the node data table.
|
||||||
|
*/
|
||||||
void clearTable() {
|
void clearTable() {
|
||||||
nodeDataList.clear();
|
nodeDataList.clear();
|
||||||
fireTableDataChanged();
|
fireTableDataChanged();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Central Repository
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2018 Basis Technology Corp.
|
* Copyright 2018 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
@ -18,217 +18,9 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.centralrepository.contentviewer;
|
package org.sleuthkit.autopsy.centralrepository.contentviewer;
|
||||||
|
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
|
||||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoValidationException;
|
|
||||||
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
|
* Marker interface for Other Occurrences nodes.
|
||||||
*/
|
*/
|
||||||
class OtherOccurrenceNodeData {
|
interface 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 CentralRepoValidationException {
|
|
||||||
if (! isCentralRepoNode() ) {
|
|
||||||
throw new CentralRepoValidationException("Can not create CorrelationAttribute for non central repo node"); //NON-NLS
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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 OtherOccurrenceNodeInstanceData implements 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
|
||||||
|
*/
|
||||||
|
OtherOccurrenceNodeInstanceData(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
|
||||||
|
*/
|
||||||
|
OtherOccurrenceNodeInstanceData(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;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* 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.contentviewer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class for populating the Other Occurrences tab with a single message.
|
||||||
|
*/
|
||||||
|
final class OtherOccurrenceNodeMessageData implements OtherOccurrenceNodeData {
|
||||||
|
private final String displayMessage;
|
||||||
|
|
||||||
|
OtherOccurrenceNodeMessageData(String displayMessage) {
|
||||||
|
this.displayMessage = displayMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getDisplayMessage() {
|
||||||
|
return displayMessage;
|
||||||
|
}
|
||||||
|
}
|
@ -70,7 +70,8 @@ public final class UserPreferences {
|
|||||||
private static final String MAX_NUM_OF_LOG_FILE = "MaximumNumberOfLogFiles";
|
private static final String MAX_NUM_OF_LOG_FILE = "MaximumNumberOfLogFiles";
|
||||||
private static final int LOG_FILE_NUM_INT = 10;
|
private static final int LOG_FILE_NUM_INT = 10;
|
||||||
public static final String GROUP_ITEMS_IN_TREE_BY_DATASOURCE = "GroupItemsInTreeByDataSource"; //NON-NLS
|
public static final String GROUP_ITEMS_IN_TREE_BY_DATASOURCE = "GroupItemsInTreeByDataSource"; //NON-NLS
|
||||||
|
public static final String SHOW_ONLY_CURRENT_USER_TAGS = "ShowOnlyCurrentUserTags";
|
||||||
|
|
||||||
// Prevent instantiation.
|
// Prevent instantiation.
|
||||||
private UserPreferences() {
|
private UserPreferences() {
|
||||||
}
|
}
|
||||||
@ -196,6 +197,27 @@ public final class UserPreferences {
|
|||||||
preferences.putBoolean(GROUP_ITEMS_IN_TREE_BY_DATASOURCE, value);
|
preferences.putBoolean(GROUP_ITEMS_IN_TREE_BY_DATASOURCE, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the user preference which identifies whether tags should be shown for
|
||||||
|
* only the current user or all users.
|
||||||
|
*
|
||||||
|
* @return true for just the current user, false for all users
|
||||||
|
*/
|
||||||
|
public static boolean showOnlyCurrentUserTags() {
|
||||||
|
return preferences.getBoolean(SHOW_ONLY_CURRENT_USER_TAGS, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the user preference which identifies whether tags should be shown for
|
||||||
|
* only the current user or all users.
|
||||||
|
*
|
||||||
|
* @param value - true for just the current user, false for all users
|
||||||
|
*/
|
||||||
|
public static void setShowOnlyCurrentUserTags(boolean value) {
|
||||||
|
preferences.putBoolean(SHOW_ONLY_CURRENT_USER_TAGS, value);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads persisted case database connection info.
|
* Reads persisted case database connection info.
|
||||||
*
|
*
|
||||||
@ -379,21 +401,25 @@ public final class UserPreferences {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* get the maximum number of log files to save
|
* get the maximum number of log files to save
|
||||||
|
*
|
||||||
* @return Number of log files
|
* @return Number of log files
|
||||||
*/
|
*/
|
||||||
public static int getLogFileCount() {
|
public static int getLogFileCount() {
|
||||||
return preferences.getInt(MAX_NUM_OF_LOG_FILE, LOG_FILE_NUM_INT);
|
return preferences.getInt(MAX_NUM_OF_LOG_FILE, LOG_FILE_NUM_INT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get the default number of log files to save
|
* get the default number of log files to save
|
||||||
|
*
|
||||||
* @return LOG_FILE_COUNT
|
* @return LOG_FILE_COUNT
|
||||||
*/
|
*/
|
||||||
public static int getDefaultLogFileCount() {
|
public static int getDefaultLogFileCount() {
|
||||||
return LOG_FILE_NUM_INT;
|
return LOG_FILE_NUM_INT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the maximum number of log files to save
|
* Set the maximum number of log files to save
|
||||||
|
*
|
||||||
* @param count number of log files
|
* @param count number of log files
|
||||||
*/
|
*/
|
||||||
public static void setLogFileCount(int count) {
|
public static void setLogFileCount(int count) {
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011-2018 Basis Technology Corp.
|
* Copyright 2011-2018 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@ -55,23 +55,33 @@ public class Tags implements AutopsyVisitableItem {
|
|||||||
// override of Children.Keys<T>.createNodes().
|
// override of Children.Keys<T>.createNodes().
|
||||||
|
|
||||||
private final TagResults tagResults = new TagResults();
|
private final TagResults tagResults = new TagResults();
|
||||||
private final String DISPLAY_NAME = NbBundle.getMessage(RootNode.class, "TagsNode.displayName.text");
|
private final static String DISPLAY_NAME = NbBundle.getMessage(RootNode.class, "TagsNode.displayName.text");
|
||||||
|
private static final String USER_NAME_PROPERTY = "user.name"; //NON-NLS
|
||||||
private final String ICON_PATH = "org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png"; //NON-NLS
|
private final String ICON_PATH = "org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png"; //NON-NLS
|
||||||
|
|
||||||
private final long datasourceObjId;
|
private final long datasourceObjId;
|
||||||
|
|
||||||
Tags() {
|
Tags() {
|
||||||
this(0);
|
this(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Tags(long dsObjId) {
|
Tags(long dsObjId) {
|
||||||
this.datasourceObjId = dsObjId;
|
this.datasourceObjId = dsObjId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the display name used by the tags node in the tree.
|
||||||
|
*
|
||||||
|
* @return - DISPLAY_NAME
|
||||||
|
*/
|
||||||
|
public static String getTagsDisplayName() {
|
||||||
|
return DISPLAY_NAME;
|
||||||
|
}
|
||||||
|
|
||||||
long filteringDataSourceObjId() {
|
long filteringDataSourceObjId() {
|
||||||
return this.datasourceObjId;
|
return this.datasourceObjId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> T accept(AutopsyItemVisitor<T> visitor) {
|
public <T> T accept(AutopsyItemVisitor<T> visitor) {
|
||||||
return visitor.visit(this);
|
return visitor.visit(this);
|
||||||
@ -98,13 +108,11 @@ public class Tags implements AutopsyVisitableItem {
|
|||||||
*/
|
*/
|
||||||
public class RootNode extends DisplayableItemNode {
|
public class RootNode extends DisplayableItemNode {
|
||||||
|
|
||||||
|
|
||||||
public RootNode(long objId) {
|
public RootNode(long objId) {
|
||||||
super(Children.create(new TagNameNodeFactory(objId), true), Lookups.singleton(DISPLAY_NAME));
|
super(Children.create(new TagNameNodeFactory(objId), true), Lookups.singleton(DISPLAY_NAME));
|
||||||
super.setName(DISPLAY_NAME);
|
super.setName(DISPLAY_NAME);
|
||||||
super.setDisplayName(DISPLAY_NAME);
|
super.setDisplayName(DISPLAY_NAME);
|
||||||
this.setIconBaseWithExtension(ICON_PATH);
|
this.setIconBaseWithExtension(ICON_PATH);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -134,12 +142,20 @@ public class Tags implements AutopsyVisitableItem {
|
|||||||
public String getItemType() {
|
public String getItemType() {
|
||||||
return getClass().getName();
|
return getClass().getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cause the contents of the RootNode and its children to be updated.
|
||||||
|
*/
|
||||||
|
public void refresh() {
|
||||||
|
tagResults.update();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TagNameNodeFactory extends ChildFactory.Detachable<TagName> implements Observer {
|
private class TagNameNodeFactory extends ChildFactory.Detachable<TagName> implements Observer {
|
||||||
|
|
||||||
private final long datasourceObjId;
|
private final long datasourceObjId;
|
||||||
|
|
||||||
private final Set<Case.Events> CASE_EVENTS_OF_INTEREST = EnumSet.of(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED,
|
private final Set<Case.Events> CASE_EVENTS_OF_INTEREST = EnumSet.of(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED,
|
||||||
Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED,
|
Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED,
|
||||||
Case.Events.CONTENT_TAG_ADDED,
|
Case.Events.CONTENT_TAG_ADDED,
|
||||||
@ -197,13 +213,14 @@ public class Tags implements AutopsyVisitableItem {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
|
*
|
||||||
* @param objId data source object id
|
* @param objId data source object id
|
||||||
*/
|
*/
|
||||||
TagNameNodeFactory(long objId) {
|
TagNameNodeFactory(long objId) {
|
||||||
this.datasourceObjId = objId;
|
this.datasourceObjId = objId;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void addNotify() {
|
protected void addNotify() {
|
||||||
IngestManager.getInstance().addIngestJobEventListener(pcl);
|
IngestManager.getInstance().addIngestJobEventListener(pcl);
|
||||||
@ -224,11 +241,17 @@ public class Tags implements AutopsyVisitableItem {
|
|||||||
@Override
|
@Override
|
||||||
protected boolean createKeys(List<TagName> keys) {
|
protected boolean createKeys(List<TagName> keys) {
|
||||||
try {
|
try {
|
||||||
|
List<TagName> tagNamesInUse;
|
||||||
List<TagName> tagNamesInUse = UserPreferences.groupItemsInTreeByDatasource() ?
|
if (UserPreferences.showOnlyCurrentUserTags()) {
|
||||||
Case.getCurrentCaseThrows().getServices().getTagsManager().getTagNamesInUse(datasourceObjId) :
|
String userName = System.getProperty(USER_NAME_PROPERTY);
|
||||||
Case.getCurrentCaseThrows().getServices().getTagsManager().getTagNamesInUse()
|
tagNamesInUse = UserPreferences.groupItemsInTreeByDatasource()
|
||||||
;
|
? Case.getCurrentCaseThrows().getServices().getTagsManager().getTagNamesInUseForUser(datasourceObjId, userName)
|
||||||
|
: Case.getCurrentCaseThrows().getServices().getTagsManager().getTagNamesInUseForUser(userName);
|
||||||
|
} else {
|
||||||
|
tagNamesInUse = UserPreferences.groupItemsInTreeByDatasource()
|
||||||
|
? Case.getCurrentCaseThrows().getServices().getTagsManager().getTagNamesInUse(datasourceObjId)
|
||||||
|
: Case.getCurrentCaseThrows().getServices().getTagsManager().getTagNamesInUse();
|
||||||
|
}
|
||||||
Collections.sort(tagNamesInUse);
|
Collections.sort(tagNamesInUse);
|
||||||
keys.addAll(tagNamesInUse);
|
keys.addAll(tagNamesInUse);
|
||||||
} catch (TskCoreException | NoCurrentCaseException ex) {
|
} catch (TskCoreException | NoCurrentCaseException ex) {
|
||||||
@ -276,15 +299,24 @@ public class Tags implements AutopsyVisitableItem {
|
|||||||
long tagsCount = 0;
|
long tagsCount = 0;
|
||||||
try {
|
try {
|
||||||
TagsManager tm = Case.getCurrentCaseThrows().getServices().getTagsManager();
|
TagsManager tm = Case.getCurrentCaseThrows().getServices().getTagsManager();
|
||||||
if (UserPreferences.groupItemsInTreeByDatasource()) {
|
if (UserPreferences.showOnlyCurrentUserTags()) {
|
||||||
tagsCount = tm.getContentTagsCountByTagName(tagName, datasourceObjId);
|
String userName = System.getProperty(USER_NAME_PROPERTY);
|
||||||
tagsCount += tm.getBlackboardArtifactTagsCountByTagName(tagName, datasourceObjId);
|
if (UserPreferences.groupItemsInTreeByDatasource()) {
|
||||||
|
tagsCount = tm.getContentTagsCountByTagNameForUser(tagName, datasourceObjId, userName);
|
||||||
|
tagsCount += tm.getBlackboardArtifactTagsCountByTagNameForUser(tagName, datasourceObjId, userName);
|
||||||
|
} else {
|
||||||
|
tagsCount = tm.getContentTagsCountByTagNameForUser(tagName, userName);
|
||||||
|
tagsCount += tm.getBlackboardArtifactTagsCountByTagNameForUser(tagName, userName);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (UserPreferences.groupItemsInTreeByDatasource()) {
|
||||||
|
tagsCount = tm.getContentTagsCountByTagName(tagName, datasourceObjId);
|
||||||
|
tagsCount += tm.getBlackboardArtifactTagsCountByTagName(tagName, datasourceObjId);
|
||||||
|
} else {
|
||||||
|
tagsCount = tm.getContentTagsCountByTagName(tagName);
|
||||||
|
tagsCount += tm.getBlackboardArtifactTagsCountByTagName(tagName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
tagsCount = tm.getContentTagsCountByTagName(tagName);
|
|
||||||
tagsCount += tm.getBlackboardArtifactTagsCountByTagName(tagName);
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (TskCoreException | NoCurrentCaseException ex) {
|
} catch (TskCoreException | NoCurrentCaseException ex) {
|
||||||
Logger.getLogger(TagNameNode.class.getName()).log(Level.SEVERE, "Failed to get tags count for " + tagName.getDisplayName() + " tag name", ex); //NON-NLS
|
Logger.getLogger(TagNameNode.class.getName()).log(Level.SEVERE, "Failed to get tags count for " + tagName.getDisplayName() + " tag name", ex); //NON-NLS
|
||||||
}
|
}
|
||||||
@ -387,9 +419,17 @@ public class Tags implements AutopsyVisitableItem {
|
|||||||
private void updateDisplayName() {
|
private void updateDisplayName() {
|
||||||
long tagsCount = 0;
|
long tagsCount = 0;
|
||||||
try {
|
try {
|
||||||
tagsCount = UserPreferences.groupItemsInTreeByDatasource() ?
|
|
||||||
Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsCountByTagName(tagName, datasourceObjId) :
|
if (UserPreferences.showOnlyCurrentUserTags()) {
|
||||||
Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsCountByTagName(tagName);
|
String userName = System.getProperty(USER_NAME_PROPERTY);
|
||||||
|
tagsCount = UserPreferences.groupItemsInTreeByDatasource()
|
||||||
|
? Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsCountByTagNameForUser(tagName, datasourceObjId, userName)
|
||||||
|
: Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsCountByTagNameForUser(tagName, userName);
|
||||||
|
} else {
|
||||||
|
tagsCount = UserPreferences.groupItemsInTreeByDatasource()
|
||||||
|
? Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsCountByTagName(tagName, datasourceObjId)
|
||||||
|
: Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsCountByTagName(tagName);
|
||||||
|
}
|
||||||
} catch (TskCoreException | NoCurrentCaseException ex) {
|
} catch (TskCoreException | NoCurrentCaseException ex) {
|
||||||
Logger.getLogger(ContentTagTypeNode.class.getName()).log(Level.SEVERE, "Failed to get content tags count for " + tagName.getDisplayName() + " tag name", ex); //NON-NLS
|
Logger.getLogger(ContentTagTypeNode.class.getName()).log(Level.SEVERE, "Failed to get content tags count for " + tagName.getDisplayName() + " tag name", ex); //NON-NLS
|
||||||
}
|
}
|
||||||
@ -444,11 +484,19 @@ public class Tags implements AutopsyVisitableItem {
|
|||||||
protected boolean createKeys(List<ContentTag> keys) {
|
protected boolean createKeys(List<ContentTag> keys) {
|
||||||
// Use the content tags bearing the specified tag name as the keys.
|
// Use the content tags bearing the specified tag name as the keys.
|
||||||
try {
|
try {
|
||||||
List<ContentTag> contentTags = UserPreferences.groupItemsInTreeByDatasource() ?
|
List<ContentTag> contentTags = UserPreferences.groupItemsInTreeByDatasource()
|
||||||
Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsByTagName(tagName, datasourceObjId) :
|
? Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsByTagName(tagName, datasourceObjId)
|
||||||
Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsByTagName(tagName);
|
: Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsByTagName(tagName);
|
||||||
|
if (UserPreferences.showOnlyCurrentUserTags()) {
|
||||||
keys.addAll(contentTags);
|
String userName = System.getProperty(USER_NAME_PROPERTY);
|
||||||
|
for (ContentTag tag : contentTags) {
|
||||||
|
if (userName.equals(tag.getUserName())) {
|
||||||
|
keys.add(tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
keys.addAll(contentTags);
|
||||||
|
}
|
||||||
} catch (TskCoreException | NoCurrentCaseException ex) {
|
} catch (TskCoreException | NoCurrentCaseException ex) {
|
||||||
Logger.getLogger(ContentTagNodeFactory.class.getName()).log(Level.SEVERE, "Failed to get tag names", ex); //NON-NLS
|
Logger.getLogger(ContentTagNodeFactory.class.getName()).log(Level.SEVERE, "Failed to get tag names", ex); //NON-NLS
|
||||||
}
|
}
|
||||||
@ -492,9 +540,16 @@ public class Tags implements AutopsyVisitableItem {
|
|||||||
private void updateDisplayName() {
|
private void updateDisplayName() {
|
||||||
long tagsCount = 0;
|
long tagsCount = 0;
|
||||||
try {
|
try {
|
||||||
tagsCount = UserPreferences.groupItemsInTreeByDatasource() ?
|
if (UserPreferences.showOnlyCurrentUserTags()) {
|
||||||
Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsCountByTagName(tagName, datasourceObjId) :
|
String userName = System.getProperty(USER_NAME_PROPERTY);
|
||||||
Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsCountByTagName(tagName);
|
tagsCount = UserPreferences.groupItemsInTreeByDatasource()
|
||||||
|
? Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsCountByTagNameForUser(tagName, datasourceObjId, userName)
|
||||||
|
: Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsCountByTagNameForUser(tagName, userName);
|
||||||
|
} else {
|
||||||
|
tagsCount = UserPreferences.groupItemsInTreeByDatasource()
|
||||||
|
? Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsCountByTagName(tagName, datasourceObjId)
|
||||||
|
: Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsCountByTagName(tagName);
|
||||||
|
}
|
||||||
} catch (TskCoreException | NoCurrentCaseException ex) {
|
} catch (TskCoreException | NoCurrentCaseException ex) {
|
||||||
Logger.getLogger(BlackboardArtifactTagTypeNode.class.getName()).log(Level.SEVERE, "Failed to get blackboard artifact tags count for " + tagName.getDisplayName() + " tag name", ex); //NON-NLS
|
Logger.getLogger(BlackboardArtifactTagTypeNode.class.getName()).log(Level.SEVERE, "Failed to get blackboard artifact tags count for " + tagName.getDisplayName() + " tag name", ex); //NON-NLS
|
||||||
}
|
}
|
||||||
@ -549,10 +604,19 @@ public class Tags implements AutopsyVisitableItem {
|
|||||||
protected boolean createKeys(List<BlackboardArtifactTag> keys) {
|
protected boolean createKeys(List<BlackboardArtifactTag> keys) {
|
||||||
try {
|
try {
|
||||||
// Use the blackboard artifact tags bearing the specified tag name as the keys.
|
// Use the blackboard artifact tags bearing the specified tag name as the keys.
|
||||||
List<BlackboardArtifactTag> artifactTags = UserPreferences.groupItemsInTreeByDatasource() ?
|
List<BlackboardArtifactTag> artifactTags = UserPreferences.groupItemsInTreeByDatasource()
|
||||||
Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsByTagName(tagName, datasourceObjId) :
|
? Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsByTagName(tagName, datasourceObjId)
|
||||||
Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsByTagName(tagName);
|
: Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsByTagName(tagName);
|
||||||
keys.addAll(artifactTags);
|
if (UserPreferences.showOnlyCurrentUserTags()) {
|
||||||
|
String userName = System.getProperty(USER_NAME_PROPERTY);
|
||||||
|
for (BlackboardArtifactTag tag : artifactTags) {
|
||||||
|
if (userName.equals(tag.getUserName())) {
|
||||||
|
keys.add(tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
keys.addAll(artifactTags);
|
||||||
|
}
|
||||||
} catch (TskCoreException | NoCurrentCaseException ex) {
|
} catch (TskCoreException | NoCurrentCaseException ex) {
|
||||||
Logger.getLogger(BlackboardArtifactTagNodeFactory.class.getName()).log(Level.SEVERE, "Failed to get tag names", ex); //NON-NLS
|
Logger.getLogger(BlackboardArtifactTagNodeFactory.class.getName()).log(Level.SEVERE, "Failed to get tag names", ex); //NON-NLS
|
||||||
}
|
}
|
||||||
|
@ -124,4 +124,5 @@ GroupDataSourcesDialog.dataSourceCountLabel.text=jLabel1
|
|||||||
GroupDataSourcesDialog.queryLabel.text=Would you like to group by data source for faster loading?
|
GroupDataSourcesDialog.queryLabel.text=Would you like to group by data source for faster loading?
|
||||||
GroupDataSourcesDialog.yesButton.text=Yes
|
GroupDataSourcesDialog.yesButton.text=Yes
|
||||||
GroupDataSourcesDialog.noButton.text=No
|
GroupDataSourcesDialog.noButton.text=No
|
||||||
GroupDataSourcesDialog.title=Group by Data Source?
|
GroupDataSourcesDialog.title=Group by Data Source?
|
||||||
|
DirectoryTreeTopComponent.showOnlyCurrentUserTagsCheckbox.text=Hide Other User's Tags
|
||||||
|
@ -21,7 +21,9 @@
|
|||||||
<Component id="backButton" min="-2" max="-2" attributes="0"/>
|
<Component id="backButton" min="-2" max="-2" attributes="0"/>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Component id="forwardButton" min="-2" max="-2" attributes="0"/>
|
<Component id="forwardButton" min="-2" max="-2" attributes="0"/>
|
||||||
<EmptySpace pref="51" max="32767" attributes="0"/>
|
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||||
|
<Component id="showOnlyCurrentUserTagsCheckbox" max="32767" attributes="0"/>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Component id="showRejectedCheckBox" min="-2" max="-2" attributes="0"/>
|
<Component id="showRejectedCheckBox" min="-2" max="-2" attributes="0"/>
|
||||||
<Component id="groupByDatasourceCheckBox" min="-2" max="-2" attributes="0"/>
|
<Component id="groupByDatasourceCheckBox" min="-2" max="-2" attributes="0"/>
|
||||||
@ -36,7 +38,10 @@
|
|||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Group type="102" attributes="0">
|
<Group type="102" attributes="0">
|
||||||
<EmptySpace min="-2" pref="5" max="-2" attributes="0"/>
|
<EmptySpace min="-2" pref="5" max="-2" attributes="0"/>
|
||||||
<Component id="showRejectedCheckBox" min="-2" max="-2" attributes="0"/>
|
<Group type="103" groupAlignment="3" attributes="0">
|
||||||
|
<Component id="showRejectedCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
|
<Component id="showOnlyCurrentUserTagsCheckbox" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Component id="groupByDatasourceCheckBox" min="-2" max="-2" attributes="0"/>
|
<Component id="groupByDatasourceCheckBox" min="-2" max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
@ -151,5 +156,15 @@
|
|||||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="groupByDatasourceCheckBoxActionPerformed"/>
|
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="groupByDatasourceCheckBoxActionPerformed"/>
|
||||||
</Events>
|
</Events>
|
||||||
</Component>
|
</Component>
|
||||||
|
<Component class="javax.swing.JCheckBox" name="showOnlyCurrentUserTagsCheckbox">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="DirectoryTreeTopComponent.showOnlyCurrentUserTagsCheckbox.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="showOnlyCurrentUserTagsCheckboxActionPerformed"/>
|
||||||
|
</Events>
|
||||||
|
</Component>
|
||||||
</SubComponents>
|
</SubComponents>
|
||||||
</Form>
|
</Form>
|
||||||
|
@ -81,6 +81,7 @@ import org.sleuthkit.autopsy.datamodel.InterestingHits;
|
|||||||
import org.sleuthkit.autopsy.datamodel.KeywordHits;
|
import org.sleuthkit.autopsy.datamodel.KeywordHits;
|
||||||
import org.sleuthkit.autopsy.datamodel.ResultsNode;
|
import org.sleuthkit.autopsy.datamodel.ResultsNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.AutopsyTreeChildFactory;
|
import org.sleuthkit.autopsy.datamodel.AutopsyTreeChildFactory;
|
||||||
|
import org.sleuthkit.autopsy.datamodel.Tags;
|
||||||
import org.sleuthkit.autopsy.datamodel.ViewsNode;
|
import org.sleuthkit.autopsy.datamodel.ViewsNode;
|
||||||
import org.sleuthkit.autopsy.datamodel.accounts.Accounts;
|
import org.sleuthkit.autopsy.datamodel.accounts.Accounts;
|
||||||
import org.sleuthkit.autopsy.datamodel.accounts.BINRange;
|
import org.sleuthkit.autopsy.datamodel.accounts.BINRange;
|
||||||
@ -137,6 +138,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
forwardButton.setEnabled(false);
|
forwardButton.setEnabled(false);
|
||||||
|
|
||||||
groupByDatasourceCheckBox.setSelected(UserPreferences.groupItemsInTreeByDatasource());
|
groupByDatasourceCheckBox.setSelected(UserPreferences.groupItemsInTreeByDatasource());
|
||||||
|
showOnlyCurrentUserTagsCheckbox.setSelected(UserPreferences.showOnlyCurrentUserTags());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -152,6 +154,9 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
case UserPreferences.GROUP_ITEMS_IN_TREE_BY_DATASOURCE:
|
case UserPreferences.GROUP_ITEMS_IN_TREE_BY_DATASOURCE:
|
||||||
refreshContentTreeSafe();
|
refreshContentTreeSafe();
|
||||||
break;
|
break;
|
||||||
|
case UserPreferences.SHOW_ONLY_CURRENT_USER_TAGS:
|
||||||
|
refreshTagsTree();
|
||||||
|
break;
|
||||||
case UserPreferences.HIDE_KNOWN_FILES_IN_VIEWS_TREE:
|
case UserPreferences.HIDE_KNOWN_FILES_IN_VIEWS_TREE:
|
||||||
case UserPreferences.HIDE_SLACK_FILES_IN_VIEWS_TREE:
|
case UserPreferences.HIDE_SLACK_FILES_IN_VIEWS_TREE:
|
||||||
// TODO: Need a way to refresh the Views subtree
|
// TODO: Need a way to refresh the Views subtree
|
||||||
@ -191,6 +196,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
forwardButton = new javax.swing.JButton();
|
forwardButton = new javax.swing.JButton();
|
||||||
showRejectedCheckBox = new javax.swing.JCheckBox();
|
showRejectedCheckBox = new javax.swing.JCheckBox();
|
||||||
groupByDatasourceCheckBox = new javax.swing.JCheckBox();
|
groupByDatasourceCheckBox = new javax.swing.JCheckBox();
|
||||||
|
showOnlyCurrentUserTagsCheckbox = new javax.swing.JCheckBox();
|
||||||
|
|
||||||
treeView.setBorder(null);
|
treeView.setBorder(null);
|
||||||
|
|
||||||
@ -235,6 +241,13 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(showOnlyCurrentUserTagsCheckbox, org.openide.util.NbBundle.getMessage(DirectoryTreeTopComponent.class, "DirectoryTreeTopComponent.showOnlyCurrentUserTagsCheckbox.text")); // NOI18N
|
||||||
|
showOnlyCurrentUserTagsCheckbox.addActionListener(new java.awt.event.ActionListener() {
|
||||||
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
|
showOnlyCurrentUserTagsCheckboxActionPerformed(evt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||||
this.setLayout(layout);
|
this.setLayout(layout);
|
||||||
layout.setHorizontalGroup(
|
layout.setHorizontalGroup(
|
||||||
@ -244,7 +257,9 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
.addComponent(backButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
.addComponent(backButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addComponent(forwardButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
.addComponent(forwardButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 51, Short.MAX_VALUE)
|
.addGap(18, 18, 18)
|
||||||
|
.addComponent(showOnlyCurrentUserTagsCheckbox, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||||
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addComponent(showRejectedCheckBox)
|
.addComponent(showRejectedCheckBox)
|
||||||
.addComponent(groupByDatasourceCheckBox))
|
.addComponent(groupByDatasourceCheckBox))
|
||||||
@ -256,7 +271,9 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addGroup(layout.createSequentialGroup()
|
.addGroup(layout.createSequentialGroup()
|
||||||
.addGap(5, 5, 5)
|
.addGap(5, 5, 5)
|
||||||
.addComponent(showRejectedCheckBox)
|
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||||
|
.addComponent(showRejectedCheckBox)
|
||||||
|
.addComponent(showOnlyCurrentUserTagsCheckbox))
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addComponent(groupByDatasourceCheckBox))
|
.addComponent(groupByDatasourceCheckBox))
|
||||||
.addGroup(layout.createSequentialGroup()
|
.addGroup(layout.createSequentialGroup()
|
||||||
@ -323,10 +340,15 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
UserPreferences.setGroupItemsInTreeByDatasource(this.groupByDatasourceCheckBox.isSelected());
|
UserPreferences.setGroupItemsInTreeByDatasource(this.groupByDatasourceCheckBox.isSelected());
|
||||||
}//GEN-LAST:event_groupByDatasourceCheckBoxActionPerformed
|
}//GEN-LAST:event_groupByDatasourceCheckBoxActionPerformed
|
||||||
|
|
||||||
|
private void showOnlyCurrentUserTagsCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_showOnlyCurrentUserTagsCheckboxActionPerformed
|
||||||
|
UserPreferences.setShowOnlyCurrentUserTags(this.showOnlyCurrentUserTagsCheckbox.isSelected());
|
||||||
|
}//GEN-LAST:event_showOnlyCurrentUserTagsCheckboxActionPerformed
|
||||||
|
|
||||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
private javax.swing.JButton backButton;
|
private javax.swing.JButton backButton;
|
||||||
private javax.swing.JButton forwardButton;
|
private javax.swing.JButton forwardButton;
|
||||||
private javax.swing.JCheckBox groupByDatasourceCheckBox;
|
private javax.swing.JCheckBox groupByDatasourceCheckBox;
|
||||||
|
private javax.swing.JCheckBox showOnlyCurrentUserTagsCheckbox;
|
||||||
private javax.swing.JCheckBox showRejectedCheckBox;
|
private javax.swing.JCheckBox showRejectedCheckBox;
|
||||||
private javax.swing.JScrollPane treeView;
|
private javax.swing.JScrollPane treeView;
|
||||||
// End of variables declaration//GEN-END:variables
|
// End of variables declaration//GEN-END:variables
|
||||||
@ -890,6 +912,29 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
SwingUtilities.invokeLater(this::rebuildTree);
|
SwingUtilities.invokeLater(this::rebuildTree);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refresh only the tags subtree(s) of the tree view.
|
||||||
|
*/
|
||||||
|
private void refreshTagsTree() {
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
// if no open case or has no data then there is no tree to rebuild
|
||||||
|
if (UserPreferences.groupItemsInTreeByDatasource()) {
|
||||||
|
for (Node dataSource : autopsyTreeChildren.getNodes()) {
|
||||||
|
Node tagsNode = dataSource.getChildren().findChild(Tags.getTagsDisplayName());
|
||||||
|
if (tagsNode != null) {
|
||||||
|
//Reports is at the same level as the data sources so we want to ignore it
|
||||||
|
((Tags.RootNode)tagsNode).refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Node tagsNode = autopsyTreeChildren.findChild(Tags.getTagsDisplayName());
|
||||||
|
if (tagsNode != null) {
|
||||||
|
((Tags.RootNode)tagsNode).refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rebuilds the autopsy tree.
|
* Rebuilds the autopsy tree.
|
||||||
*
|
*
|
||||||
|
@ -53,6 +53,8 @@ public final class ExtractAction extends AbstractAction {
|
|||||||
|
|
||||||
private Logger logger = Logger.getLogger(ExtractAction.class.getName());
|
private Logger logger = Logger.getLogger(ExtractAction.class.getName());
|
||||||
|
|
||||||
|
private String userDefinedExportPath;
|
||||||
|
|
||||||
// This class is a singleton to support multi-selection of nodes, since
|
// 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
|
// 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).
|
// node in the array returns a reference to the same action object from Node.getActions(boolean).
|
||||||
@ -110,10 +112,12 @@ public final class ExtractAction extends AbstractAction {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
JFileChooser fileChooser = new JFileChooser();
|
JFileChooser fileChooser = new JFileChooser();
|
||||||
fileChooser.setCurrentDirectory(new File(openCase.getExportDirectory()));
|
fileChooser.setCurrentDirectory(new File(getExportDirectory(openCase)));
|
||||||
// If there is an attribute name, change the ":". Otherwise the extracted file will be hidden
|
// If there is an attribute name, change the ":". Otherwise the extracted file will be hidden
|
||||||
fileChooser.setSelectedFile(new File(FileUtil.escapeFileName(selectedFile.getName())));
|
fileChooser.setSelectedFile(new File(FileUtil.escapeFileName(selectedFile.getName())));
|
||||||
if (fileChooser.showSaveDialog((Component) event.getSource()) == JFileChooser.APPROVE_OPTION) {
|
if (fileChooser.showSaveDialog((Component) event.getSource()) == JFileChooser.APPROVE_OPTION) {
|
||||||
|
updateExportDirectory(fileChooser.getSelectedFile().getParent(), openCase);
|
||||||
|
|
||||||
ArrayList<FileExtractionTask> fileExtractionTasks = new ArrayList<>();
|
ArrayList<FileExtractionTask> fileExtractionTasks = new ArrayList<>();
|
||||||
fileExtractionTasks.add(new FileExtractionTask(selectedFile, fileChooser.getSelectedFile()));
|
fileExtractionTasks.add(new FileExtractionTask(selectedFile, fileChooser.getSelectedFile()));
|
||||||
runExtractionTasks(event, fileExtractionTasks);
|
runExtractionTasks(event, fileExtractionTasks);
|
||||||
@ -137,7 +141,7 @@ public final class ExtractAction extends AbstractAction {
|
|||||||
}
|
}
|
||||||
JFileChooser folderChooser = new JFileChooser();
|
JFileChooser folderChooser = new JFileChooser();
|
||||||
folderChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
|
folderChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
|
||||||
folderChooser.setCurrentDirectory(new File(openCase.getExportDirectory()));
|
folderChooser.setCurrentDirectory(new File(getExportDirectory(openCase)));
|
||||||
if (folderChooser.showSaveDialog((Component) event.getSource()) == JFileChooser.APPROVE_OPTION) {
|
if (folderChooser.showSaveDialog((Component) event.getSource()) == JFileChooser.APPROVE_OPTION) {
|
||||||
File destinationFolder = folderChooser.getSelectedFile();
|
File destinationFolder = folderChooser.getSelectedFile();
|
||||||
if (!destinationFolder.exists()) {
|
if (!destinationFolder.exists()) {
|
||||||
@ -150,6 +154,7 @@ public final class ExtractAction extends AbstractAction {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
updateExportDirectory(destinationFolder.getPath(), openCase);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* get the unique set of files from the list. A user once reported
|
* get the unique set of files from the list. A user once reported
|
||||||
@ -169,6 +174,45 @@ public final class ExtractAction extends AbstractAction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the export directory path.
|
||||||
|
*
|
||||||
|
* @param openCase The current case.
|
||||||
|
*
|
||||||
|
* @return The export directory path.
|
||||||
|
*/
|
||||||
|
private String getExportDirectory(Case openCase) {
|
||||||
|
String caseExportPath = openCase.getExportDirectory();
|
||||||
|
|
||||||
|
if (userDefinedExportPath == null) {
|
||||||
|
return caseExportPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
File file = new File(userDefinedExportPath);
|
||||||
|
if (file.exists() == false || file.isDirectory() == false) {
|
||||||
|
return caseExportPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
return userDefinedExportPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the default export directory. If the directory path matches the
|
||||||
|
* case export directory, then the directory used will always match the
|
||||||
|
* export directory of any given case. Otherwise, the path last used will be
|
||||||
|
* saved.
|
||||||
|
*
|
||||||
|
* @param exportPath The export path.
|
||||||
|
* @param openCase The current case.
|
||||||
|
*/
|
||||||
|
private void updateExportDirectory(String exportPath, Case openCase) {
|
||||||
|
if (exportPath.equalsIgnoreCase(openCase.getExportDirectory())) {
|
||||||
|
userDefinedExportPath = null;
|
||||||
|
} else {
|
||||||
|
userDefinedExportPath = exportPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute a series of file extraction tasks.
|
* Execute a series of file extraction tasks.
|
||||||
*
|
*
|
||||||
|
@ -67,6 +67,7 @@ final class ExtractUnallocAction extends AbstractAction {
|
|||||||
private final List<OutputFileData> filesToExtract = new ArrayList<>();
|
private final List<OutputFileData> filesToExtract = new ArrayList<>();
|
||||||
private static final Set<String> volumesInProgress = new HashSet<>();
|
private static final Set<String> volumesInProgress = new HashSet<>();
|
||||||
private static final Set<Long> imagesInProgress = new HashSet<>();
|
private static final Set<Long> imagesInProgress = new HashSet<>();
|
||||||
|
private static String userDefinedExportPath;
|
||||||
private long currentImage = 0L;
|
private long currentImage = 0L;
|
||||||
private final boolean isImage;
|
private final boolean isImage;
|
||||||
|
|
||||||
@ -159,7 +160,7 @@ final class ExtractUnallocAction extends AbstractAction {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
fileChooser.setCurrentDirectory(new File(openCase.getExportDirectory()));
|
fileChooser.setCurrentDirectory(new File(getExportDirectory(openCase)));
|
||||||
fileChooser.setDialogTitle(
|
fileChooser.setDialogTitle(
|
||||||
NbBundle.getMessage(this.getClass(), "ExtractUnallocAction.dlgTitle.selectDirToSaveTo.msg"));
|
NbBundle.getMessage(this.getClass(), "ExtractUnallocAction.dlgTitle.selectDirToSaveTo.msg"));
|
||||||
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
|
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
|
||||||
@ -167,6 +168,9 @@ final class ExtractUnallocAction extends AbstractAction {
|
|||||||
int returnValue = fileChooser.showSaveDialog((Component) event.getSource());
|
int returnValue = fileChooser.showSaveDialog((Component) event.getSource());
|
||||||
if (returnValue == JFileChooser.APPROVE_OPTION) {
|
if (returnValue == JFileChooser.APPROVE_OPTION) {
|
||||||
String destination = fileChooser.getSelectedFile().getPath();
|
String destination = fileChooser.getSelectedFile().getPath();
|
||||||
|
|
||||||
|
updateExportDirectory(destination, openCase);
|
||||||
|
|
||||||
for (OutputFileData outputFileData : filesToExtract) {
|
for (OutputFileData outputFileData : filesToExtract) {
|
||||||
outputFileData.setPath(destination);
|
outputFileData.setPath(destination);
|
||||||
|
|
||||||
@ -228,7 +232,45 @@ final class ExtractUnallocAction extends AbstractAction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the export directory path.
|
||||||
|
*
|
||||||
|
* @param openCase The current case.
|
||||||
|
*
|
||||||
|
* @return The export directory path.
|
||||||
|
*/
|
||||||
|
private String getExportDirectory(Case openCase) {
|
||||||
|
String caseExportPath = openCase.getExportDirectory();
|
||||||
|
|
||||||
|
if (userDefinedExportPath == null) {
|
||||||
|
return caseExportPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
File file = new File(userDefinedExportPath);
|
||||||
|
if (file.exists() == false || file.isDirectory() == false) {
|
||||||
|
return caseExportPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
return userDefinedExportPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the default export directory. If the directory path matches the
|
||||||
|
* case export directory, then the directory used will always match the
|
||||||
|
* export directory of any given case. Otherwise, the path last used will be
|
||||||
|
* saved.
|
||||||
|
*
|
||||||
|
* @param exportPath The export path.
|
||||||
|
* @param openCase The current case.
|
||||||
|
*/
|
||||||
|
private void updateExportDirectory(String exportPath, Case openCase) {
|
||||||
|
if (exportPath.equalsIgnoreCase(openCase.getExportDirectory())) {
|
||||||
|
userDefinedExportPath = null;
|
||||||
|
} else {
|
||||||
|
userDefinedExportPath = exportPath;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2015-2017 Basis Technology Corp.
|
* Copyright 2015-2018 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -19,16 +19,19 @@
|
|||||||
package org.sleuthkit.autopsy.guiutils;
|
package org.sleuthkit.autopsy.guiutils;
|
||||||
|
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import javax.swing.ImageIcon;
|
import javax.swing.ImageIcon;
|
||||||
import javax.swing.JTable;
|
import javax.swing.JTable;
|
||||||
import static javax.swing.SwingConstants.CENTER;
|
import static javax.swing.SwingConstants.CENTER;
|
||||||
|
import org.openide.nodes.Node;
|
||||||
import org.openide.util.ImageUtilities;
|
import org.openide.util.ImageUtilities;
|
||||||
import org.openide.util.NbBundle.Messages;
|
import org.openide.util.NbBundle.Messages;
|
||||||
|
import org.sleuthkit.autopsy.datamodel.NodeProperty;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A JTable cell renderer that represents a status as a center-aligned icon, and
|
* A JTable and outline view cell renderer that represents a status as a
|
||||||
* grays out the cell if the table is disabled. The statuses represented are OK,
|
* center-aligned icon, and grays out the cell if the table is disabled. The
|
||||||
* WARNING, and ERROR.
|
* statuses represented are OK, WARNING, and ERROR.
|
||||||
*/
|
*/
|
||||||
public class StatusIconCellRenderer extends GrayableCellRenderer {
|
public class StatusIconCellRenderer extends GrayableCellRenderer {
|
||||||
|
|
||||||
@ -45,8 +48,20 @@ public class StatusIconCellRenderer extends GrayableCellRenderer {
|
|||||||
@Override
|
@Override
|
||||||
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
||||||
setHorizontalAlignment(CENTER);
|
setHorizontalAlignment(CENTER);
|
||||||
if ((value instanceof Status)) {
|
Object switchValue = null;
|
||||||
switch((Status) value) {
|
if ((value instanceof NodeProperty)) {
|
||||||
|
//The Outline view has properties in the cell, the value contained in the property is what we want
|
||||||
|
try {
|
||||||
|
switchValue = ((Node.Property) value).getValue();
|
||||||
|
} catch (IllegalAccessException | InvocationTargetException ex) {
|
||||||
|
//Unable to get the value from the NodeProperty no Icon will be displayed
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//JTables contain the value we want directly in the cell
|
||||||
|
switchValue = value;
|
||||||
|
}
|
||||||
|
if ((switchValue instanceof Status)) {
|
||||||
|
switch ((Status) switchValue) {
|
||||||
case OK:
|
case OK:
|
||||||
setIcon(OK_ICON);
|
setIcon(OK_ICON);
|
||||||
setToolTipText(org.openide.util.NbBundle.getMessage(StatusIconCellRenderer.class, "StatusIconCellRenderer.tooltiptext.ok"));
|
setToolTipText(org.openide.util.NbBundle.getMessage(StatusIconCellRenderer.class, "StatusIconCellRenderer.tooltiptext.ok"));
|
||||||
@ -60,8 +75,7 @@ public class StatusIconCellRenderer extends GrayableCellRenderer {
|
|||||||
setToolTipText(org.openide.util.NbBundle.getMessage(StatusIconCellRenderer.class, "StatusIconCellRenderer.tooltiptext.error"));
|
setToolTipText(org.openide.util.NbBundle.getMessage(StatusIconCellRenderer.class, "StatusIconCellRenderer.tooltiptext.error"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
setIcon(null);
|
setIcon(null);
|
||||||
setText("");
|
setText("");
|
||||||
}
|
}
|
||||||
@ -69,7 +83,7 @@ public class StatusIconCellRenderer extends GrayableCellRenderer {
|
|||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum Status {
|
public enum Status {
|
||||||
OK,
|
OK,
|
||||||
WARNING,
|
WARNING,
|
||||||
|
@ -784,8 +784,14 @@ class ReportHTML implements TableReportModule {
|
|||||||
localFileFolder.mkdirs();
|
localFileFolder.mkdirs();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construct a file tagName for the local file that incorporates the file id to ensure uniqueness.
|
/*
|
||||||
String fileName = file.getName();
|
* Construct a file tagName for the local file that incorporates the
|
||||||
|
* file ID to ensure uniqueness.
|
||||||
|
*
|
||||||
|
* Note: File name is normalized to account for possible attribute name
|
||||||
|
* which will be separated by a ':' character.
|
||||||
|
*/
|
||||||
|
String fileName = org.sleuthkit.autopsy.coreutils.FileUtil.escapeFileName(file.getName());
|
||||||
String objectIdSuffix = "_" + file.getId();
|
String objectIdSuffix = "_" + file.getId();
|
||||||
int lastDotIndex = fileName.lastIndexOf(".");
|
int lastDotIndex = fileName.lastIndexOf(".");
|
||||||
if (lastDotIndex != -1 && lastDotIndex != 0) {
|
if (lastDotIndex != -1 && lastDotIndex != 0) {
|
||||||
@ -1294,9 +1300,24 @@ class ReportHTML implements TableReportModule {
|
|||||||
return summary;
|
return summary;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a thumbnail of a given file.
|
||||||
|
*
|
||||||
|
* @param file The file from which to create the thumbnail.
|
||||||
|
*
|
||||||
|
* @return The path to the thumbnail file, or null if a thumbnail couldn't
|
||||||
|
* be created.
|
||||||
|
*/
|
||||||
private String prepareThumbnail(AbstractFile file) {
|
private String prepareThumbnail(AbstractFile file) {
|
||||||
BufferedImage bufferedThumb = ImageUtils.getThumbnail(file, ImageUtils.ICON_SIZE_MEDIUM);
|
BufferedImage bufferedThumb = ImageUtils.getThumbnail(file, ImageUtils.ICON_SIZE_MEDIUM);
|
||||||
File thumbFile = Paths.get(thumbsPath, file.getName() + ".png").toFile();
|
|
||||||
|
/*
|
||||||
|
* File name is normalized to account for possible attribute name which
|
||||||
|
* will be separated by a ':' character.
|
||||||
|
*/
|
||||||
|
String fileName = org.sleuthkit.autopsy.coreutils.FileUtil.escapeFileName(file.getName());
|
||||||
|
|
||||||
|
File thumbFile = Paths.get(thumbsPath, fileName + ".png").toFile();
|
||||||
if (bufferedThumb == null) {
|
if (bufferedThumb == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ import org.sleuthkit.datamodel.TskCoreException;
|
|||||||
public class EmbeddedFileTest extends NbTestCase {
|
public class EmbeddedFileTest extends NbTestCase {
|
||||||
|
|
||||||
private static final String CASE_NAME = "EmbeddedFileTest";
|
private static final String CASE_NAME = "EmbeddedFileTest";
|
||||||
private final Path IMAGE_PATH = Paths.get(this.getDataDir().toString(), "EmbeddedIM_img2_v1.vhd");
|
private final Path IMAGE_PATH = Paths.get(this.getDataDir().toString(), "EmbeddedIM_img1_v2.vhd");
|
||||||
public static final String HASH_VALUE = "098f6bcd4621d373cade4e832627b4f6";
|
public static final String HASH_VALUE = "098f6bcd4621d373cade4e832627b4f6";
|
||||||
private static final int DEEP_FOLDER_COUNT = 25;
|
private static final int DEEP_FOLDER_COUNT = 25;
|
||||||
private Case openCase;
|
private Case openCase;
|
||||||
@ -96,43 +96,45 @@ public class EmbeddedFileTest extends NbTestCase {
|
|||||||
|
|
||||||
public void testEncryptionAndZipBomb() {
|
public void testEncryptionAndZipBomb() {
|
||||||
try {
|
try {
|
||||||
List<AbstractFile> results = openCase.getSleuthkitCase().findAllFilesWhere("name LIKE '%%'");
|
List<AbstractFile> results = openCase.getSleuthkitCase().findAllFilesWhere("name LIKE '%%'");
|
||||||
String protectedName1 = "password_protected.zip";
|
final String zipBombSetName = "Possible Zip Bomb";
|
||||||
String protectedName2 = "level1_protected.zip";
|
final String protectedName1 = "password_protected.zip";
|
||||||
String protectedName3 = "42.zip";
|
final String protectedName2 = "level1_protected.zip";
|
||||||
String depthZipBomb = "DepthTriggerZipBomb.zip";
|
final String protectedName3 = "42.zip";
|
||||||
String ratioZipBomb = "RatioTriggerZipBomb.zip";
|
final String depthZipBomb = "DepthTriggerZipBomb.zip";
|
||||||
|
final String ratioZipBomb = "RatioTriggerZipBomb.zip";
|
||||||
int zipBombs = 0;
|
int zipBombs = 0;
|
||||||
assertEquals(2221, results.size());
|
assertEquals("The number of files in the test image has changed", 2221, results.size());
|
||||||
int passwdProtectedZips = 0;
|
int passwdProtectedZips = 0;
|
||||||
for (AbstractFile file : results) {
|
for (AbstractFile file : results) {
|
||||||
//.zip file has artifact TSK_ENCRYPTION_DETECTED
|
//.zip file has artifact TSK_ENCRYPTION_DETECTED
|
||||||
if (file.getName().equalsIgnoreCase(protectedName1) || file.getName().equalsIgnoreCase(protectedName2) || file.getName().equalsIgnoreCase(protectedName3)){
|
if (file.getName().equalsIgnoreCase(protectedName1) || file.getName().equalsIgnoreCase(protectedName2) || file.getName().equalsIgnoreCase(protectedName3)){
|
||||||
ArrayList<BlackboardArtifact> artifacts = file.getAllArtifacts();
|
ArrayList<BlackboardArtifact> artifacts = file.getAllArtifacts();
|
||||||
assertEquals(1, artifacts.size());
|
assertEquals("Password protected zip file " + file.getName() + " has incorrect number of artifacts", 1, artifacts.size());
|
||||||
for (BlackboardArtifact artifact : artifacts) {
|
for (BlackboardArtifact artifact : artifacts) {
|
||||||
assertEquals(artifact.getArtifactTypeID(), BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_DETECTED.getTypeID());
|
assertEquals("Artifact for password protected zip file " + file.getName() + " has incorrect type ID", artifact.getArtifactTypeID(), BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_DETECTED.getTypeID());
|
||||||
passwdProtectedZips++;
|
passwdProtectedZips++;
|
||||||
}
|
}
|
||||||
} else if (file.getName().equalsIgnoreCase(depthZipBomb) || file.getName().equalsIgnoreCase(ratioZipBomb)){
|
} else if (file.getName().equalsIgnoreCase(depthZipBomb) || file.getName().equalsIgnoreCase(ratioZipBomb)){
|
||||||
ArrayList<BlackboardArtifact> artifacts = file.getAllArtifacts();
|
ArrayList<BlackboardArtifact> artifacts = file.getAllArtifacts();
|
||||||
assertEquals(1, artifacts.size());
|
assertEquals("Zip bomb " + file.getName() + " has incorrect number of artifacts", 1, artifacts.size());
|
||||||
for (BlackboardArtifact artifact : artifacts) {
|
for (BlackboardArtifact artifact : artifacts) {
|
||||||
assertEquals(artifact.getArtifactTypeID(), BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID());
|
assertEquals("Artifact for Zip bomb " + file.getName() + " has incorrect type ID", artifact.getArtifactTypeID(), BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID());
|
||||||
BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME));
|
BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME));
|
||||||
assertNotNull("Possible Zip Bomb", attribute);
|
assertNotNull("No attribute found for artifact on zip bomb " + file.getName(), attribute);
|
||||||
|
assertEquals("Interesting artifact on file, " + file.getName() + ", does not reflect it being a zip bomb", zipBombSetName, attribute.getDisplayString());
|
||||||
zipBombs++;
|
zipBombs++;
|
||||||
}
|
}
|
||||||
} else {//No other files have artifact defined
|
} else {//No other files have artifact defined
|
||||||
assertEquals(0, file.getAllArtifacts().size());
|
assertEquals("Unexpected file, " + file.getName() + ", has artifacts", 0, file.getAllArtifacts().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
//Make sure 3 password protected zip files have been tested: password_protected.zip, level1_protected.zip and 42.zip that we download for bomb testing.
|
//Make sure 3 password protected zip files have been tested: password_protected.zip, level1_protected.zip and 42.zip that we download for bomb testing.
|
||||||
assertEquals(3, passwdProtectedZips);
|
assertEquals("Unexpected number of artifacts reflecting password protected zip files found", 3, passwdProtectedZips);
|
||||||
//Make sure 2 zip bomb files have been tested: DepthTriggerZipBomb.zip and RatioTriggerZipBomb.zip.
|
//Make sure 2 zip bomb files have been tested: DepthTriggerZipBomb.zip and RatioTriggerZipBomb.zip.
|
||||||
assertEquals(2, zipBombs);
|
assertEquals("Unexpected number of artifacts reflecting zip bombs found", 2, zipBombs);
|
||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
Exceptions.printStackTrace(ex);
|
Exceptions.printStackTrace(ex);
|
||||||
Assert.fail(ex);
|
Assert.fail(ex);
|
||||||
|
@ -326,7 +326,7 @@ final class AutoIngestJobsNode extends AbstractNode {
|
|||||||
ss.put(new NodeProperty<>(Bundle.AutoIngestJobsNode_jobCreated_text(), Bundle.AutoIngestJobsNode_jobCreated_text(), Bundle.AutoIngestJobsNode_jobCreated_text(),
|
ss.put(new NodeProperty<>(Bundle.AutoIngestJobsNode_jobCreated_text(), Bundle.AutoIngestJobsNode_jobCreated_text(), Bundle.AutoIngestJobsNode_jobCreated_text(),
|
||||||
jobWrapper.getManifest().getDateFileCreated()));
|
jobWrapper.getManifest().getDateFileCreated()));
|
||||||
ss.put(new NodeProperty<>(Bundle.AutoIngestJobsNode_priority_text(), Bundle.AutoIngestJobsNode_priority_text(), Bundle.AutoIngestJobsNode_priority_text(),
|
ss.put(new NodeProperty<>(Bundle.AutoIngestJobsNode_priority_text(), Bundle.AutoIngestJobsNode_priority_text(), Bundle.AutoIngestJobsNode_priority_text(),
|
||||||
jobWrapper.getPriority() > 0 ? Bundle.AutoIngestJobsNode_prioritized_true() : Bundle.AutoIngestJobsNode_prioritized_false()));
|
jobWrapper.getPriority()));
|
||||||
break;
|
break;
|
||||||
case RUNNING_JOB:
|
case RUNNING_JOB:
|
||||||
AutoIngestJob.StageDetails status = jobWrapper.getProcessingStageDetails();
|
AutoIngestJob.StageDetails status = jobWrapper.getProcessingStageDetails();
|
||||||
|
@ -31,6 +31,7 @@ import org.sleuthkit.autopsy.datamodel.EmptyNode;
|
|||||||
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestJobsNode.AutoIngestJobStatus;
|
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestJobsNode.AutoIngestJobStatus;
|
||||||
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestJobsNode.JobNode;
|
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestJobsNode.JobNode;
|
||||||
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestNodeRefreshEvents.AutoIngestRefreshEvent;
|
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestNodeRefreshEvents.AutoIngestRefreshEvent;
|
||||||
|
import org.sleuthkit.autopsy.guiutils.StatusIconCellRenderer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A panel which displays an outline view with all jobs for a specified status.
|
* A panel which displays an outline view with all jobs for a specified status.
|
||||||
@ -84,6 +85,7 @@ final class AutoIngestJobsPanel extends javax.swing.JPanel implements ExplorerMa
|
|||||||
indexOfColumn = getColumnIndexByName(Bundle.AutoIngestJobsNode_priority_text());
|
indexOfColumn = getColumnIndexByName(Bundle.AutoIngestJobsNode_priority_text());
|
||||||
if (indexOfColumn != INVALID_INDEX) {
|
if (indexOfColumn != INVALID_INDEX) {
|
||||||
outline.getColumnModel().getColumn(indexOfColumn).setPreferredWidth(INITIAL_PRIORITIZED_WIDTH);
|
outline.getColumnModel().getColumn(indexOfColumn).setPreferredWidth(INITIAL_PRIORITIZED_WIDTH);
|
||||||
|
outline.getColumnModel().getColumn(indexOfColumn).setCellRenderer(new PrioritizedIconCellRenderer());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case RUNNING_JOB:
|
case RUNNING_JOB:
|
||||||
@ -108,6 +110,7 @@ final class AutoIngestJobsPanel extends javax.swing.JPanel implements ExplorerMa
|
|||||||
indexOfColumn = getColumnIndexByName(Bundle.AutoIngestJobsNode_status_text());
|
indexOfColumn = getColumnIndexByName(Bundle.AutoIngestJobsNode_status_text());
|
||||||
if (indexOfColumn != INVALID_INDEX) {
|
if (indexOfColumn != INVALID_INDEX) {
|
||||||
outline.getColumnModel().getColumn(indexOfColumn).setPreferredWidth(INITIAL_STATUS_WIDTH);
|
outline.getColumnModel().getColumn(indexOfColumn).setPreferredWidth(INITIAL_STATUS_WIDTH);
|
||||||
|
outline.getColumnModel().getColumn(indexOfColumn).setCellRenderer(new StatusIconCellRenderer());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2017 Basis Technology Corp.
|
* Copyright 2017-2018 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -19,21 +19,22 @@
|
|||||||
package org.sleuthkit.autopsy.experimental.autoingest;
|
package org.sleuthkit.autopsy.experimental.autoingest;
|
||||||
|
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import javax.swing.ImageIcon;
|
import javax.swing.ImageIcon;
|
||||||
import javax.swing.JTable;
|
import javax.swing.JTable;
|
||||||
import static javax.swing.SwingConstants.CENTER;
|
import static javax.swing.SwingConstants.CENTER;
|
||||||
|
import org.openide.nodes.Node;
|
||||||
import org.openide.util.ImageUtilities;
|
import org.openide.util.ImageUtilities;
|
||||||
import org.openide.util.NbBundle.Messages;
|
import org.openide.util.NbBundle.Messages;
|
||||||
import org.sleuthkit.autopsy.guiutils.GrayableCellRenderer;
|
import org.sleuthkit.autopsy.guiutils.GrayableCellRenderer;
|
||||||
import org.sleuthkit.autopsy.guiutils.StatusIconCellRenderer;
|
import org.sleuthkit.autopsy.datamodel.NodeProperty;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A JTable cell renderer that represents whether the priority value of a job
|
* A JTable and Outline view cell renderer that represents whether the priority
|
||||||
* has ever been increased, tick if prioritized nothing if not.
|
* value of a job has ever been increased, tick if prioritized nothing if not.
|
||||||
*/
|
*/
|
||||||
class PrioritizedIconCellRenderer extends GrayableCellRenderer {
|
class PrioritizedIconCellRenderer extends GrayableCellRenderer {
|
||||||
|
|
||||||
|
|
||||||
@Messages({
|
@Messages({
|
||||||
"PrioritizedIconCellRenderer.prioritized.tooltiptext=This job has been prioritized. The most recently prioritized job should be processed next.",
|
"PrioritizedIconCellRenderer.prioritized.tooltiptext=This job has been prioritized. The most recently prioritized job should be processed next.",
|
||||||
"PrioritizedIconCellRenderer.notPrioritized.tooltiptext=This job has not been prioritized."
|
"PrioritizedIconCellRenderer.notPrioritized.tooltiptext=This job has not been prioritized."
|
||||||
@ -44,13 +45,25 @@ class PrioritizedIconCellRenderer extends GrayableCellRenderer {
|
|||||||
@Override
|
@Override
|
||||||
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
||||||
setHorizontalAlignment(CENTER);
|
setHorizontalAlignment(CENTER);
|
||||||
if ((value instanceof Integer)) {
|
Object switchValue = null;
|
||||||
if ((int) value == 0) {
|
if ((value instanceof NodeProperty)) {
|
||||||
setIcon(null);
|
//The Outline view has properties in the cell, the value contained in the property is what we want
|
||||||
|
try {
|
||||||
|
switchValue = ((Node.Property) value).getValue();
|
||||||
|
} catch (IllegalAccessException | InvocationTargetException ignored) {
|
||||||
|
//Unable to get the value from the NodeProperty no Icon will be displayed
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//JTables contain the value we want directly in the cell
|
||||||
|
switchValue = value;
|
||||||
|
}
|
||||||
|
if (switchValue instanceof Integer && (int) switchValue != 0) {
|
||||||
|
setIcon(checkedIcon);
|
||||||
|
setToolTipText(org.openide.util.NbBundle.getMessage(PrioritizedIconCellRenderer.class, "PrioritizedIconCellRenderer.prioritized.tooltiptext"));
|
||||||
|
} else {
|
||||||
|
setIcon(null);
|
||||||
|
if (switchValue instanceof Integer) {
|
||||||
setToolTipText(org.openide.util.NbBundle.getMessage(PrioritizedIconCellRenderer.class, "PrioritizedIconCellRenderer.notPrioritized.tooltiptext"));
|
setToolTipText(org.openide.util.NbBundle.getMessage(PrioritizedIconCellRenderer.class, "PrioritizedIconCellRenderer.notPrioritized.tooltiptext"));
|
||||||
} else {
|
|
||||||
setIcon(checkedIcon);
|
|
||||||
setToolTipText(org.openide.util.NbBundle.getMessage(PrioritizedIconCellRenderer.class, "PrioritizedIconCellRenderer.prioritized.tooltiptext"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
grayCellIfTableNotEnabled(table, isSelected);
|
grayCellIfTableNotEnabled(table, isSelected);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user