mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-19 11:07:43 +00:00
Adding more attributes
This commit is contained in:
parent
e41f38ec28
commit
124fd325d5
@ -20,3 +20,7 @@ FileSearchDialog.searchButton.text=Search
|
||||
ResultsDialog.exitButton.text=Exit
|
||||
ResultsDialog.searchButton.text=Run another search
|
||||
FileSearchDialog.errorLabel.text=jLabel6
|
||||
FileSearchDialog.hashCheckBox.text=Hash Set
|
||||
FileSearchDialog.intCheckBox.text=Interesting Items
|
||||
FileSearchDialog.tagsCheckBox.text=Tags
|
||||
FileSearchDialog.objCheckBox.text=Objects
|
||||
|
@ -4,15 +4,23 @@ CTL_FileSearchTestAction=Test file search
|
||||
FileSearch.DataSourceGroupKey.datasourceAndID={0}(ID: {1})
|
||||
# {0} - Data source ID
|
||||
FileSearch.DataSourceGroupKey.idOnly=Data source (ID: {0})
|
||||
FileSearch.FileTagGroupKey.noSets=None
|
||||
FileSearch.GroupingAttributeType.datasource.displayName=Data source
|
||||
FileSearch.GroupingAttributeType.fileType.displayName=File type
|
||||
FileSearch.GroupingAttributeType.frequency.displayName=Past occurrences
|
||||
FileSearch.GroupingAttributeType.hash.displayName=Hash set
|
||||
FileSearch.GroupingAttributeType.interestingItem.displayName=Interesting item set
|
||||
FileSearch.GroupingAttributeType.keywordList.displayName=Keyword list names
|
||||
FileSearch.GroupingAttributeType.none.displayName=None
|
||||
FileSearch.GroupingAttributeType.object.displayName=Object detected
|
||||
FileSearch.GroupingAttributeType.parent.displayName=Parent folder
|
||||
FileSearch.GroupingAttributeType.size.displayName=Size
|
||||
FileSearch.GroupingAttributeType.tag.displayName=File tag
|
||||
FileSearch.HashHitsGroupKey.noHashHits=None
|
||||
FileSearch.InterestingItemGroupKey.noSets=None
|
||||
FileSearch.KeywordListGroupKey.noKeywords=None
|
||||
FileSearch.NoGroupingGroupKey.allFiles=All Files
|
||||
FileSearch.ObjectDetectedGroupKey.noSets=None
|
||||
FileSearchData.FileSize.large.displayName=200MB-1GB
|
||||
FileSearchData.FileSize.medium.displayName=50-200MB
|
||||
FileSearchData.FileSize.small.displayName=1-50MB
|
||||
@ -48,6 +56,7 @@ FileSearchDialog.orderSizeRadioButton.text=Group Size
|
||||
FileSearchDialog.jLabel5.text=Order files by:
|
||||
FileSearchDialog.parentCheckBox.text=Parent
|
||||
FileSearchDialog.searchButton.text=Search
|
||||
FileSearchFiltering.concatenateSetNamesForDisplay.comma=,
|
||||
# {0} - Data source name
|
||||
# {1} - Data source ID
|
||||
FileSearchFiltering.DataSourceFilter.datasource={0}({1})
|
||||
@ -60,10 +69,15 @@ FileSearchFiltering.FileTypeFilter.or=\ or
|
||||
# {0} - filters
|
||||
FileSearchFiltering.FrequencyFilter.desc=Files with frequency: {0}
|
||||
FileSearchFiltering.FrequencyFilter.or=\ or
|
||||
FileSearchFiltering.KeywordListFilter.comma=,
|
||||
# {0} - filters
|
||||
FileSearchFiltering.HashSetFilter.desc=Files with hash set hits in set(s): {0}
|
||||
# {0} - filters
|
||||
FileSearchFiltering.InterestingItemSetFilter.desc=Files with interesting item hits in set(s): {0}
|
||||
# {0} - filters
|
||||
FileSearchFiltering.KeywordListFilter.desc=Files with keywords in list(s): {0}
|
||||
# {0} - filters
|
||||
FileSearchFiltering.ObjectDetectionFilter.desc=Files with objects detected in set(s): {0}
|
||||
# {0} - filters
|
||||
FileSearchFiltering.ParentFilter.desc=Files with paths matching: {0}
|
||||
FileSearchFiltering.ParentFilter.exact=(exact match)
|
||||
FileSearchFiltering.ParentFilter.or=\ or
|
||||
@ -78,6 +92,9 @@ FileSearchFiltering.SizeFilter.or=\ or
|
||||
# {0} - Minimum bytes
|
||||
# {1} - Maximum bytes
|
||||
FileSearchFiltering.SizeFilter.range=({0} to {1})
|
||||
# {0} - tag names
|
||||
FileSearchFiltering.TagsFilter.desc=Files that have been tagged {0}
|
||||
FileSearchFiltering.TagsFilter.or=\ or
|
||||
FileSorter.SortingMethod.datasource.displayName=By data source
|
||||
FileSorter.SortingMethod.filename.displayName=By file name
|
||||
FileSorter.SortingMethod.filesize.displayName=By file size
|
||||
@ -89,3 +106,7 @@ ResultsDialog.dialogTitle.text=File search results
|
||||
ResultsDialog.exitButton.text=Exit
|
||||
ResultsDialog.searchButton.text=Run another search
|
||||
FileSearchDialog.errorLabel.text=jLabel6
|
||||
FileSearchDialog.hashCheckBox.text=Hash Set
|
||||
FileSearchDialog.intCheckBox.text=Interesting Items
|
||||
FileSearchDialog.tagsCheckBox.text=Tags
|
||||
FileSearchDialog.objCheckBox.text=Objects
|
||||
|
@ -42,6 +42,7 @@ import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.CaseDbAccessManager;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.ContentTag;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
@ -157,6 +158,10 @@ class FileSearch {
|
||||
"FileSearch.GroupingAttributeType.size.displayName=Size",
|
||||
"FileSearch.GroupingAttributeType.datasource.displayName=Data source",
|
||||
"FileSearch.GroupingAttributeType.parent.displayName=Parent folder",
|
||||
"FileSearch.GroupingAttributeType.hash.displayName=Hash set",
|
||||
"FileSearch.GroupingAttributeType.interestingItem.displayName=Interesting item set",
|
||||
"FileSearch.GroupingAttributeType.tag.displayName=File tag",
|
||||
"FileSearch.GroupingAttributeType.object.displayName=Object detected",
|
||||
"FileSearch.GroupingAttributeType.none.displayName=None",
|
||||
})
|
||||
enum GroupingAttributeType {
|
||||
@ -166,6 +171,10 @@ class FileSearch {
|
||||
FILE_SIZE(new FileSizeAttribute(), Bundle.FileSearch_GroupingAttributeType_size_displayName()),
|
||||
DATA_SOURCE(new DataSourceAttribute(), Bundle.FileSearch_GroupingAttributeType_datasource_displayName()),
|
||||
PARENT_PATH(new ParentPathAttribute(), Bundle.FileSearch_GroupingAttributeType_parent_displayName()),
|
||||
HASH_LIST_NAME(new HashHitsAttribute(), Bundle.FileSearch_GroupingAttributeType_hash_displayName()),
|
||||
INTERESTING_ITEM_SET(new InterestingItemAttribute(), Bundle.FileSearch_GroupingAttributeType_interestingItem_displayName()),
|
||||
FILE_TAG(new FileTagAttribute(), Bundle.FileSearch_GroupingAttributeType_tag_displayName()),
|
||||
OBJECT_DETECTED(new ObjectDetectedAttribute(), Bundle.FileSearch_GroupingAttributeType_object_displayName()),
|
||||
NO_GROUPING(new NoGroupingAttribute(), Bundle.FileSearch_GroupingAttributeType_none_displayName());
|
||||
|
||||
private final AttributeType attributeType;
|
||||
@ -527,24 +536,11 @@ class FileSearch {
|
||||
@Override
|
||||
void addAttributeToResultFiles(List<ResultFile> files, SleuthkitCase caseDb,
|
||||
EamDb centralRepoDb) throws FileSearchException {
|
||||
|
||||
// Concatenate the object IDs in the list of files
|
||||
String objIdList = ""; // NON-NLS
|
||||
for (ResultFile file : files) {
|
||||
if ( ! objIdList.isEmpty()) {
|
||||
objIdList += ","; // NON-NLS
|
||||
}
|
||||
objIdList += "\'" + file.getAbstractFile().getId() + "\'"; // NON-NLS
|
||||
}
|
||||
|
||||
|
||||
// Get pairs of (object ID, keyword list name) for all files in the list of files that have
|
||||
// keyword list hits.
|
||||
String selectQuery = "blackboard_artifacts.obj_id AS object_id, blackboard_attributes.value_text AS keyword_list_name " +
|
||||
"FROM blackboard_artifacts " +
|
||||
"INNER JOIN blackboard_attributes ON blackboard_artifacts.artifact_id=blackboard_attributes.artifact_id " +
|
||||
"WHERE blackboard_attributes.artifact_type_id=\'" + BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID() + "\' " +
|
||||
"AND blackboard_attributes.attribute_type_id=\'" + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID() + "\' " +
|
||||
"AND blackboard_artifacts.obj_id IN (" + objIdList + ") "; // NON-NLS
|
||||
String selectQuery = createSetNameQuery(files, caseDb, BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID(),
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID());
|
||||
|
||||
SetKeywordListNamesCallback callback = new SetKeywordListNamesCallback(files);
|
||||
try {
|
||||
@ -583,12 +579,12 @@ class FileSearch {
|
||||
while (rs.next()) {
|
||||
try {
|
||||
Long objId = rs.getLong("object_id"); // NON-NLS
|
||||
String keywordListName = rs.getString("keyword_list_name"); // NON-NLS
|
||||
String keywordListName = rs.getString("set_name"); // NON-NLS
|
||||
|
||||
tempMap.get(objId).addKeywordListName(keywordListName);
|
||||
|
||||
} catch (SQLException ex) {
|
||||
logger.log(Level.SEVERE, "Unable to get object_id or keyword_list_name from result set", ex); // NON-NLS
|
||||
logger.log(Level.SEVERE, "Unable to get object_id or set_name from result set", ex); // NON-NLS
|
||||
}
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
@ -760,23 +756,10 @@ class FileSearch {
|
||||
void addAttributeToResultFiles(List<ResultFile> files, SleuthkitCase caseDb,
|
||||
EamDb centralRepoDb) throws FileSearchException {
|
||||
|
||||
// Concatenate the object IDs in the list of files
|
||||
String objIdList = ""; // NON-NLS
|
||||
for (ResultFile file : files) {
|
||||
if ( ! objIdList.isEmpty()) {
|
||||
objIdList += ","; // NON-NLS
|
||||
}
|
||||
objIdList += "\'" + file.getAbstractFile().getId() + "\'"; // NON-NLS
|
||||
}
|
||||
|
||||
// Get pairs of (object ID, keyword list name) for all files in the list of files that have
|
||||
// keyword list hits.
|
||||
String selectQuery = "blackboard_artifacts.obj_id AS object_id, blackboard_attributes.value_text AS hash_set_name " +
|
||||
"FROM blackboard_artifacts " +
|
||||
"INNER JOIN blackboard_attributes ON blackboard_artifacts.artifact_id=blackboard_attributes.artifact_id " +
|
||||
"WHERE blackboard_attributes.artifact_type_id=\'" + BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID() + "\' " +
|
||||
"AND blackboard_attributes.attribute_type_id=\'" + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID() + "\' " +
|
||||
"AND blackboard_artifacts.obj_id IN (" + objIdList + ") "; // NON-NLS
|
||||
// hash set hits.
|
||||
String selectQuery = createSetNameQuery(files, caseDb, BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID(),
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID());
|
||||
|
||||
SetHashSetNamesCallback callback = new SetHashSetNamesCallback(files);
|
||||
try {
|
||||
@ -797,7 +780,7 @@ class FileSearch {
|
||||
/**
|
||||
* Create the callback.
|
||||
*
|
||||
* @param resultFiles List of files to add keyword list names to
|
||||
* @param resultFiles List of files to add hash set names to
|
||||
*/
|
||||
SetHashSetNamesCallback(List<ResultFile> resultFiles) {
|
||||
this.resultFiles = resultFiles;
|
||||
@ -815,12 +798,12 @@ class FileSearch {
|
||||
while (rs.next()) {
|
||||
try {
|
||||
Long objId = rs.getLong("object_id"); // NON-NLS
|
||||
String hashSetName = rs.getString("hash_set_name"); // NON-NLS
|
||||
String hashSetName = rs.getString("set_name"); // NON-NLS
|
||||
|
||||
tempMap.get(objId).addHashSetName(hashSetName);
|
||||
|
||||
} catch (SQLException ex) {
|
||||
logger.log(Level.SEVERE, "Unable to get object_id or hash_set_name from result set", ex); // NON-NLS
|
||||
logger.log(Level.SEVERE, "Unable to get object_id or set_name from result set", ex); // NON-NLS
|
||||
}
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
@ -841,7 +824,7 @@ class FileSearch {
|
||||
"FileSearch.HashHitsGroupKey.noHashHits=None",
|
||||
})
|
||||
HashHitsGroupKey(ResultFile file) {
|
||||
hashSetNames = file.getKeywordListNames();
|
||||
hashSetNames = file.getHashSetNames();
|
||||
|
||||
if (hashSetNames.isEmpty()) {
|
||||
hashSetNamesString = Bundle.FileSearch_HashHitsGroupKey_noHashHits();
|
||||
@ -896,7 +879,378 @@ class FileSearch {
|
||||
return Objects.hash(hashSetNamesString);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attribute for grouping/sorting by interesting item set lists
|
||||
*/
|
||||
static class InterestingItemAttribute extends AttributeType {
|
||||
|
||||
@Override
|
||||
GroupKey getGroupKey(ResultFile file) {
|
||||
return new InterestingItemGroupKey(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
void addAttributeToResultFiles(List<ResultFile> files, SleuthkitCase caseDb,
|
||||
EamDb centralRepoDb) throws FileSearchException {
|
||||
|
||||
// Get pairs of (object ID, keyword list name) for all files in the list of files that have
|
||||
// interesting file set hits.
|
||||
String selectQuery = createSetNameQuery(files, caseDb, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID(),
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID());
|
||||
|
||||
SetInterstingFileSetNamesCallback callback = new SetInterstingFileSetNamesCallback(files);
|
||||
try {
|
||||
caseDb.getCaseDbAccessManager().select(selectQuery, callback);
|
||||
} catch (TskCoreException ex) {
|
||||
throw new FileSearchException("Error looking up interesting file set attributes", ex); // NON-NLS
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to process the results of the CaseDbAccessManager select query. Will add
|
||||
* the interesting file set names to the list of ResultFile objects.
|
||||
*/
|
||||
private static class SetInterstingFileSetNamesCallback implements CaseDbAccessManager.CaseDbAccessQueryCallback {
|
||||
|
||||
List<ResultFile> resultFiles;
|
||||
|
||||
/**
|
||||
* Create the callback.
|
||||
*
|
||||
* @param resultFiles List of files to add interesting file set names to
|
||||
*/
|
||||
SetInterstingFileSetNamesCallback(List<ResultFile> resultFiles) {
|
||||
this.resultFiles = resultFiles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(ResultSet rs) {
|
||||
try {
|
||||
// Create a temporary map of object ID to ResultFile
|
||||
Map<Long, ResultFile> tempMap = new HashMap<>();
|
||||
for (ResultFile file : resultFiles) {
|
||||
tempMap.put(file.getAbstractFile().getId(), file);
|
||||
}
|
||||
|
||||
while (rs.next()) {
|
||||
try {
|
||||
Long objId = rs.getLong("object_id"); // NON-NLS
|
||||
String setName = rs.getString("set_name"); // NON-NLS
|
||||
|
||||
tempMap.get(objId).addInterestingSetName(setName);
|
||||
|
||||
} catch (SQLException ex) {
|
||||
logger.log(Level.SEVERE, "Unable to get object_id or set_name from result set", ex); // NON-NLS
|
||||
}
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
logger.log(Level.SEVERE, "Failed to get interesting file set names", ex); // NON-NLS
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Key representing a interesting item set group
|
||||
*/
|
||||
private static class InterestingItemGroupKey extends GroupKey {
|
||||
private final List<String> interestingItemSetNames;
|
||||
private final String interestingItemSetNamesString;
|
||||
|
||||
@NbBundle.Messages({
|
||||
"FileSearch.InterestingItemGroupKey.noSets=None",
|
||||
})
|
||||
InterestingItemGroupKey(ResultFile file) {
|
||||
interestingItemSetNames = file.getInterestingSetNames();
|
||||
|
||||
if (interestingItemSetNames.isEmpty()) {
|
||||
interestingItemSetNamesString = Bundle.FileSearch_InterestingItemGroupKey_noSets();
|
||||
} else {
|
||||
interestingItemSetNamesString = String.join(",", interestingItemSetNames); // NON-NLS
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
String getDisplayName() {
|
||||
return interestingItemSetNamesString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(GroupKey otherGroupKey) {
|
||||
if (otherGroupKey instanceof InterestingItemGroupKey) {
|
||||
InterestingItemGroupKey otherInterestingItemGroupKey = (InterestingItemGroupKey)otherGroupKey;
|
||||
|
||||
// Put the empty list at the end
|
||||
if (this.interestingItemSetNames.isEmpty()) {
|
||||
if (otherInterestingItemGroupKey.interestingItemSetNames.isEmpty()) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
} else if (otherInterestingItemGroupKey.interestingItemSetNames.isEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return interestingItemSetNamesString.compareTo(otherInterestingItemGroupKey.interestingItemSetNamesString);
|
||||
} else {
|
||||
return compareClassNames(otherGroupKey);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object otherKey) {
|
||||
if (otherKey == this){
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(otherKey instanceof InterestingItemGroupKey)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
InterestingItemGroupKey otherInterestingItemGroupKey = (InterestingItemGroupKey)otherKey;
|
||||
return interestingItemSetNamesString.equals(otherInterestingItemGroupKey.interestingItemSetNamesString);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(interestingItemSetNamesString);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attribute for grouping/sorting by objects detected
|
||||
*/
|
||||
static class ObjectDetectedAttribute extends AttributeType {
|
||||
|
||||
@Override
|
||||
GroupKey getGroupKey(ResultFile file) {
|
||||
return new ObjectDetectedGroupKey(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
void addAttributeToResultFiles(List<ResultFile> files, SleuthkitCase caseDb,
|
||||
EamDb centralRepoDb) throws FileSearchException {
|
||||
|
||||
// Get pairs of (object ID, keyword list name) for all files in the list of files that have
|
||||
// objects detected
|
||||
String selectQuery = createSetNameQuery(files, caseDb, BlackboardArtifact.ARTIFACT_TYPE.TSK_OBJECT_DETECTED.getTypeID(),
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DESCRIPTION.getTypeID());
|
||||
|
||||
SetObjectDetectedNamesCallback callback = new SetObjectDetectedNamesCallback(files);
|
||||
try {
|
||||
caseDb.getCaseDbAccessManager().select(selectQuery, callback);
|
||||
} catch (TskCoreException ex) {
|
||||
throw new FileSearchException("Error looking up object detected attributes", ex); // NON-NLS
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to process the results of the CaseDbAccessManager select query. Will add
|
||||
* the interesting file set names to the list of ResultFile objects.
|
||||
*/
|
||||
private static class SetObjectDetectedNamesCallback implements CaseDbAccessManager.CaseDbAccessQueryCallback {
|
||||
|
||||
List<ResultFile> resultFiles;
|
||||
|
||||
/**
|
||||
* Create the callback.
|
||||
*
|
||||
* @param resultFiles List of files to add object detected names to
|
||||
*/
|
||||
SetObjectDetectedNamesCallback(List<ResultFile> resultFiles) {
|
||||
this.resultFiles = resultFiles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(ResultSet rs) {
|
||||
try {
|
||||
// Create a temporary map of object ID to ResultFile
|
||||
Map<Long, ResultFile> tempMap = new HashMap<>();
|
||||
for (ResultFile file : resultFiles) {
|
||||
tempMap.put(file.getAbstractFile().getId(), file);
|
||||
}
|
||||
|
||||
while (rs.next()) {
|
||||
try {
|
||||
Long objId = rs.getLong("object_id"); // NON-NLS
|
||||
String setName = rs.getString("set_name"); // NON-NLS
|
||||
|
||||
tempMap.get(objId).addObjectDetectedName(setName);
|
||||
|
||||
} catch (SQLException ex) {
|
||||
logger.log(Level.SEVERE, "Unable to get object_id or set_name from result set", ex); // NON-NLS
|
||||
}
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
logger.log(Level.SEVERE, "Failed to get object detected names", ex); // NON-NLS
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Key representing an object detected group
|
||||
*/
|
||||
private static class ObjectDetectedGroupKey extends GroupKey {
|
||||
private final List<String> objectDetectedNames;
|
||||
private final String objectDetectedNamesString;
|
||||
|
||||
@NbBundle.Messages({
|
||||
"FileSearch.ObjectDetectedGroupKey.noSets=None",
|
||||
})
|
||||
ObjectDetectedGroupKey(ResultFile file) {
|
||||
objectDetectedNames = file.getObjectDetectedNames();
|
||||
|
||||
if (objectDetectedNames.isEmpty()) {
|
||||
objectDetectedNamesString = Bundle.FileSearch_ObjectDetectedGroupKey_noSets();
|
||||
} else {
|
||||
objectDetectedNamesString = String.join(",", objectDetectedNames); // NON-NLS
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
String getDisplayName() {
|
||||
return objectDetectedNamesString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(GroupKey otherGroupKey) {
|
||||
if (otherGroupKey instanceof ObjectDetectedGroupKey) {
|
||||
ObjectDetectedGroupKey otherObjectDetectedGroupKey = (ObjectDetectedGroupKey)otherGroupKey;
|
||||
|
||||
// Put the empty list at the end
|
||||
if (this.objectDetectedNames.isEmpty()) {
|
||||
if (otherObjectDetectedGroupKey.objectDetectedNames.isEmpty()) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
} else if (otherObjectDetectedGroupKey.objectDetectedNames.isEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return objectDetectedNamesString.compareTo(otherObjectDetectedGroupKey.objectDetectedNamesString);
|
||||
} else {
|
||||
return compareClassNames(otherGroupKey);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object otherKey) {
|
||||
if (otherKey == this){
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(otherKey instanceof ObjectDetectedGroupKey)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ObjectDetectedGroupKey otherObjectDetectedGroupKey = (ObjectDetectedGroupKey)otherKey;
|
||||
return objectDetectedNamesString.equals(otherObjectDetectedGroupKey.objectDetectedNamesString);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(objectDetectedNamesString);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attribute for grouping/sorting by tag name
|
||||
*/
|
||||
static class FileTagAttribute extends AttributeType {
|
||||
|
||||
@Override
|
||||
GroupKey getGroupKey(ResultFile file) {
|
||||
return new FileTagGroupKey(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
void addAttributeToResultFiles(List<ResultFile> files, SleuthkitCase caseDb,
|
||||
EamDb centralRepoDb) throws FileSearchException {
|
||||
|
||||
|
||||
try {
|
||||
for (ResultFile resultFile : files) {
|
||||
List<ContentTag> contentTags = caseDb.getContentTagsByContent(resultFile.getAbstractFile());
|
||||
|
||||
for (ContentTag tag : contentTags) {
|
||||
resultFile.addTagName(tag.getName().getDisplayName());
|
||||
}
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
throw new FileSearchException("Error looking up file tag attributes", ex); // NON-NLS
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Key representing a interesting item set group
|
||||
*/
|
||||
private static class FileTagGroupKey extends GroupKey {
|
||||
private final List<String> tagNames;
|
||||
private final String tagNamesString;
|
||||
|
||||
@NbBundle.Messages({
|
||||
"FileSearch.FileTagGroupKey.noSets=None",
|
||||
})
|
||||
FileTagGroupKey(ResultFile file) {
|
||||
tagNames = file.getTagNames();
|
||||
|
||||
if (tagNames.isEmpty()) {
|
||||
tagNamesString = Bundle.FileSearch_FileTagGroupKey_noSets();
|
||||
} else {
|
||||
tagNamesString = String.join(",", tagNames); // NON-NLS
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
String getDisplayName() {
|
||||
return tagNamesString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(GroupKey otherGroupKey) {
|
||||
if (otherGroupKey instanceof FileTagGroupKey) {
|
||||
FileTagGroupKey otherFileTagGroupKey = (FileTagGroupKey)otherGroupKey;
|
||||
|
||||
// Put the empty list at the end
|
||||
if (tagNames.isEmpty()) {
|
||||
if (otherFileTagGroupKey.tagNames.isEmpty()) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
} else if (otherFileTagGroupKey.tagNames.isEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return tagNamesString.compareTo(otherFileTagGroupKey.tagNamesString);
|
||||
} else {
|
||||
return compareClassNames(otherGroupKey);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object otherKey) {
|
||||
if (otherKey == this){
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(otherKey instanceof FileTagGroupKey)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FileTagGroupKey otherFileTagGroupKey = (FileTagGroupKey)otherKey;
|
||||
return tagNamesString.equals(otherFileTagGroupKey.tagNamesString);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(tagNamesString);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Default attribute used to make one group
|
||||
@ -956,6 +1310,28 @@ class FileSearch {
|
||||
}
|
||||
}
|
||||
|
||||
private static String createSetNameQuery(List<ResultFile> files, SleuthkitCase caseDb,
|
||||
int artifactTypeID, int setNameAttrID) throws FileSearchException {
|
||||
|
||||
// Concatenate the object IDs in the list of files
|
||||
String objIdList = ""; // NON-NLS
|
||||
for (ResultFile file : files) {
|
||||
if ( ! objIdList.isEmpty()) {
|
||||
objIdList += ","; // NON-NLS
|
||||
}
|
||||
objIdList += "\'" + file.getAbstractFile().getId() + "\'"; // NON-NLS
|
||||
}
|
||||
|
||||
// Get pairs of (object ID, set name) for all files in the list of files that have
|
||||
// the given artifact type.
|
||||
return "blackboard_artifacts.obj_id AS object_id, blackboard_attributes.value_text AS set_name " +
|
||||
"FROM blackboard_artifacts " +
|
||||
"INNER JOIN blackboard_attributes ON blackboard_artifacts.artifact_id=blackboard_attributes.artifact_id " +
|
||||
"WHERE blackboard_attributes.artifact_type_id=\'" + artifactTypeID + "\' " +
|
||||
"AND blackboard_attributes.attribute_type_id=\'" + setNameAttrID + "\' " +
|
||||
"AND blackboard_artifacts.obj_id IN (" + objIdList + ") "; // NON-NLS
|
||||
}
|
||||
|
||||
private FileSearch() {
|
||||
// Class should not be instantiated
|
||||
}
|
||||
|
@ -66,37 +66,62 @@
|
||||
<Component id="jScrollPane6" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="filler1" min="-2" pref="265" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
<Component id="searchButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="cancelButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="errorLabel" alignment="0" max="32767" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="filler2" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="errorLabel" max="32767" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="344" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="jLabel3" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jLabel4" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jLabel5" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="29" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||
<Component id="orderAttrRadioButton" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="groupComboBox" pref="144" max="32767" attributes="0"/>
|
||||
<Component id="orderSizeRadioButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="fileOrderComboBox" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="hashCheckBox" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||
<Component id="jScrollPane7" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="intCheckBox" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jScrollPane8" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="tagsCheckBox" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||
<Component id="jScrollPane9" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="objCheckBox" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||
<Component id="jScrollPane10" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="filler2" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="25" max="32767" attributes="0"/>
|
||||
<EmptySpace min="35" pref="35" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="jLabel3" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jLabel4" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jLabel5" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="29" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||
<Component id="orderAttrRadioButton" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="groupComboBox" max="32767" attributes="0"/>
|
||||
<Component id="orderSizeRadioButton" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="fileOrderComboBox" min="-2" pref="144" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
@ -109,8 +134,29 @@
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jScrollPane1" min="-2" pref="82" max="-2" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jScrollPane1" min="-2" pref="82" max="-2" attributes="0"/>
|
||||
<Component id="jScrollPane7" alignment="0" min="-2" pref="49" max="-2" attributes="0"/>
|
||||
<Component id="hashCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="jScrollPane10" alignment="0" min="-2" pref="49" max="-2" attributes="0"/>
|
||||
<Component id="objCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="jScrollPane9" alignment="0" min="-2" pref="49" max="-2" attributes="0"/>
|
||||
<Component id="tagsCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="dsCheckBox" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jScrollPane2" min="-2" pref="56" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="jLabel3" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
@ -123,16 +169,16 @@
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="orderSizeRadioButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="jLabel5" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="fileOrderComboBox" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="dsCheckBox" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="jLabel5" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="fileOrderComboBox" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" alignment="1" groupAlignment="0" attributes="0">
|
||||
<Component id="jScrollPane8" alignment="0" min="-2" pref="49" max="-2" attributes="0"/>
|
||||
<Component id="intCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="jScrollPane2" min="-2" pref="56" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
@ -172,8 +218,8 @@
|
||||
</Group>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="cancelButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="searchButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="cancelButton" alignment="3" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
@ -534,5 +580,125 @@
|
||||
<AuxValue name="classDetails" type="java.lang.String" value="Box.Filler.RigidArea"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="hashCheckBox">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/filequery/Bundle.properties" key="FileSearchDialog.hashCheckBox.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="hashCheckBoxActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Container class="javax.swing.JScrollPane" name="jScrollPane7">
|
||||
<AuxValues>
|
||||
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JList" name="hashList">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||
<Connection code="new DefaultListModel<String>()" type="code"/>
|
||||
</Property>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<String>"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JCheckBox" name="intCheckBox">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/filequery/Bundle.properties" key="FileSearchDialog.intCheckBox.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="intCheckBoxActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Container class="javax.swing.JScrollPane" name="jScrollPane8">
|
||||
<AuxValues>
|
||||
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JList" name="intList">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||
<Connection code="new DefaultListModel<String>()" type="code"/>
|
||||
</Property>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<String>"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JScrollPane" name="jScrollPane9">
|
||||
<AuxValues>
|
||||
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JList" name="tagsList">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||
<Connection code="new DefaultListModel<TagName>()" type="code"/>
|
||||
</Property>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<TagName>"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JCheckBox" name="tagsCheckBox">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/filequery/Bundle.properties" key="FileSearchDialog.tagsCheckBox.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="tagsCheckBoxActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Container class="javax.swing.JScrollPane" name="jScrollPane10">
|
||||
<AuxValues>
|
||||
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JList" name="objList">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||
<Connection code="new DefaultListModel<String>()" type="code"/>
|
||||
</Property>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<String>"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JCheckBox" name="objCheckBox">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/filequery/Bundle.properties" key="FileSearchDialog.objCheckBox.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="objCheckBoxActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
@ -26,6 +26,7 @@ import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.swing.DefaultListModel;
|
||||
import javax.swing.DefaultListCellRenderer;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JList;
|
||||
@ -46,6 +47,7 @@ import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.DataSource;
|
||||
import org.sleuthkit.datamodel.TagName;
|
||||
|
||||
/**
|
||||
* Dialog to allow the user to choose filtering and grouping options.
|
||||
@ -98,6 +100,11 @@ public class FileSearchDialog extends javax.swing.JDialog implements ActionListe
|
||||
setUpKWFilter();
|
||||
setUpParentPathFilter();
|
||||
|
||||
setUpHashFilter();
|
||||
setUpInterestingItemsFilter();
|
||||
setUpTagsFilter();
|
||||
setUpObjectFilter();
|
||||
|
||||
// Set up the grouping attributes
|
||||
for (GroupingAttributeType type : GroupingAttributeType.values()) {
|
||||
groupComboBox.addItem(type);
|
||||
@ -202,20 +209,8 @@ public class FileSearchDialog extends javax.swing.JDialog implements ActionListe
|
||||
try {
|
||||
DefaultListModel<String> kwListModel = (DefaultListModel<String>)kwList.getModel();
|
||||
|
||||
// TODO - create case DB query
|
||||
List<BlackboardArtifact> arts = caseDb.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT);
|
||||
List<String> setNames = new ArrayList<>();
|
||||
for (BlackboardArtifact art : arts) {
|
||||
for (BlackboardAttribute attr : art.getAttributes()) {
|
||||
if (attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()) {
|
||||
String setName = attr.getValueString();
|
||||
if ( ! setNames.contains(setName)) {
|
||||
setNames.add(setName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Collections.sort(setNames);
|
||||
List<String> setNames = getSetNames(BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT,
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME);
|
||||
for(String name : setNames) {
|
||||
kwListModel.add(count, name);
|
||||
}
|
||||
@ -227,6 +222,116 @@ public class FileSearchDialog extends javax.swing.JDialog implements ActionListe
|
||||
addListeners(kwCheckBox, kwList);
|
||||
}
|
||||
|
||||
private void setUpHashFilter() {
|
||||
int count = 0;
|
||||
try {
|
||||
DefaultListModel<String> hashListModel = (DefaultListModel<String>)hashList.getModel();
|
||||
|
||||
List<String> setNames = getSetNames(BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT,
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME);
|
||||
for(String name : setNames) {
|
||||
hashListModel.add(count, name);
|
||||
count++;
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error loading hash set names", ex);
|
||||
hashCheckBox.setEnabled(false);
|
||||
hashList.setEnabled(false);
|
||||
}
|
||||
addListeners(hashCheckBox, hashList);
|
||||
}
|
||||
|
||||
private void setUpInterestingItemsFilter() {
|
||||
int count = 0;
|
||||
try {
|
||||
DefaultListModel<String> intListModel = (DefaultListModel<String>)intList.getModel();
|
||||
|
||||
List<String> setNames = getSetNames(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT,
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME);
|
||||
for(String name : setNames) {
|
||||
intListModel.add(count, name);
|
||||
count++;
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error loading interesting file set names", ex);
|
||||
intCheckBox.setEnabled(false);
|
||||
intList.setEnabled(false);
|
||||
}
|
||||
addListeners(intCheckBox, intList);
|
||||
}
|
||||
|
||||
private void setUpTagsFilter() {
|
||||
int count = 0;
|
||||
try {
|
||||
DefaultListModel<TagName> tagsListModel = (DefaultListModel<TagName>)tagsList.getModel();
|
||||
|
||||
List<TagName> tagNames = caseDb.getTagNamesInUse();
|
||||
for(TagName name : tagNames) {
|
||||
//tagsListModel.add(count, name.getDisplayName());
|
||||
tagsListModel.add(count, name);
|
||||
count++;
|
||||
}
|
||||
tagsList.setCellRenderer(new TagsListCellRenderer());
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error loading tag names", ex);
|
||||
tagsCheckBox.setEnabled(false);
|
||||
tagsList.setEnabled(false);
|
||||
}
|
||||
addListeners(tagsCheckBox, tagsList);
|
||||
}
|
||||
|
||||
private class TagsListCellRenderer extends DefaultListCellRenderer {
|
||||
|
||||
@Override
|
||||
public java.awt.Component getListCellRendererComponent(
|
||||
JList<?> list,
|
||||
Object value,
|
||||
int index,
|
||||
boolean isSelected,
|
||||
boolean cellHasFocus) {
|
||||
if (value instanceof TagName) {
|
||||
value = ((TagName)value).getDisplayName();
|
||||
}
|
||||
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
private void setUpObjectFilter() {
|
||||
int count = 0;
|
||||
try {
|
||||
DefaultListModel<String> objListModel = (DefaultListModel<String>)objList.getModel();
|
||||
|
||||
List<String> setNames = getSetNames(BlackboardArtifact.ARTIFACT_TYPE.TSK_OBJECT_DETECTED, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DESCRIPTION);
|
||||
for(String name : setNames) {
|
||||
objListModel.add(count, name);
|
||||
count++;
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error loading object detected set names", ex);
|
||||
objCheckBox.setEnabled(false);
|
||||
objList.setEnabled(false);
|
||||
}
|
||||
addListeners(objCheckBox, objList);
|
||||
}
|
||||
|
||||
private List<String> getSetNames(BlackboardArtifact.ARTIFACT_TYPE artifactType, BlackboardAttribute.ATTRIBUTE_TYPE setNameAttribute) throws TskCoreException {
|
||||
List<BlackboardArtifact> arts = caseDb.getBlackboardArtifacts(artifactType);
|
||||
List<String> setNames = new ArrayList<>();
|
||||
for (BlackboardArtifact art : arts) {
|
||||
for (BlackboardAttribute attr : art.getAttributes()) {
|
||||
if (attr.getAttributeType().getTypeID() == setNameAttribute.getTypeID()) {
|
||||
String setName = attr.getValueString();
|
||||
if ( ! setNames.contains(setName)) {
|
||||
setNames.add(setName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Collections.sort(setNames);
|
||||
return setNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the parent path filter
|
||||
*/
|
||||
@ -272,6 +377,22 @@ public class FileSearchDialog extends javax.swing.JDialog implements ActionListe
|
||||
filters.add(new FileSearchFiltering.KeywordListFilter(kwList.getSelectedValuesList()));
|
||||
}
|
||||
|
||||
if (hashCheckBox.isSelected()) {
|
||||
filters.add(new FileSearchFiltering.HashSetFilter(hashList.getSelectedValuesList()));
|
||||
}
|
||||
|
||||
if (intCheckBox.isSelected()) {
|
||||
filters.add(new FileSearchFiltering.InterestingFileSetFilter(intList.getSelectedValuesList()));
|
||||
}
|
||||
|
||||
if (objCheckBox.isSelected()) {
|
||||
filters.add(new FileSearchFiltering.ObjectDetectionFilter(objList.getSelectedValuesList()));
|
||||
}
|
||||
|
||||
if (tagsCheckBox.isSelected()) {
|
||||
filters.add(new FileSearchFiltering.TagsFilter(tagsList.getSelectedValuesList()));
|
||||
}
|
||||
|
||||
return filters;
|
||||
}
|
||||
|
||||
@ -385,6 +506,26 @@ public class FileSearchDialog extends javax.swing.JDialog implements ActionListe
|
||||
return;
|
||||
}
|
||||
|
||||
if (hashCheckBox.isSelected() && hashList.getSelectedValuesList().isEmpty()) {
|
||||
setInvalid("At least one hash set name must be selected");
|
||||
return;
|
||||
}
|
||||
|
||||
if (intCheckBox.isSelected() && intList.getSelectedValuesList().isEmpty()) {
|
||||
setInvalid("At least one interesting file set name must be selected");
|
||||
return;
|
||||
}
|
||||
|
||||
if (objCheckBox.isSelected() && objList.getSelectedValuesList().isEmpty()) {
|
||||
setInvalid("At least one object type name must be selected");
|
||||
return;
|
||||
}
|
||||
|
||||
if (tagsCheckBox.isSelected() && tagsList.getSelectedValuesList().isEmpty()) {
|
||||
setInvalid("At least one tag name must be selected");
|
||||
return;
|
||||
}
|
||||
|
||||
setValid();
|
||||
|
||||
}
|
||||
@ -456,6 +597,18 @@ public class FileSearchDialog extends javax.swing.JDialog implements ActionListe
|
||||
errorLabel = new javax.swing.JLabel();
|
||||
filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(8, 7), new java.awt.Dimension(8, 7), new java.awt.Dimension(8, 7));
|
||||
filler2 = new javax.swing.Box.Filler(new java.awt.Dimension(265, 23), new java.awt.Dimension(265, 23), new java.awt.Dimension(265, 23));
|
||||
hashCheckBox = new javax.swing.JCheckBox();
|
||||
jScrollPane7 = new javax.swing.JScrollPane();
|
||||
hashList = new javax.swing.JList<>();
|
||||
intCheckBox = new javax.swing.JCheckBox();
|
||||
jScrollPane8 = new javax.swing.JScrollPane();
|
||||
intList = new javax.swing.JList<>();
|
||||
jScrollPane9 = new javax.swing.JScrollPane();
|
||||
tagsList = new javax.swing.JList<>();
|
||||
tagsCheckBox = new javax.swing.JCheckBox();
|
||||
jScrollPane10 = new javax.swing.JScrollPane();
|
||||
objList = new javax.swing.JList<>();
|
||||
objCheckBox = new javax.swing.JCheckBox();
|
||||
|
||||
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
|
||||
|
||||
@ -580,6 +733,50 @@ public class FileSearchDialog extends javax.swing.JDialog implements ActionListe
|
||||
errorLabel.setForeground(new java.awt.Color(255, 0, 0));
|
||||
org.openide.awt.Mnemonics.setLocalizedText(errorLabel, org.openide.util.NbBundle.getMessage(FileSearchDialog.class, "FileSearchDialog.errorLabel.text")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(hashCheckBox, org.openide.util.NbBundle.getMessage(FileSearchDialog.class, "FileSearchDialog.hashCheckBox.text")); // NOI18N
|
||||
hashCheckBox.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
hashCheckBoxActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
hashList.setModel(new DefaultListModel<String>());
|
||||
hashList.setEnabled(false);
|
||||
jScrollPane7.setViewportView(hashList);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(intCheckBox, org.openide.util.NbBundle.getMessage(FileSearchDialog.class, "FileSearchDialog.intCheckBox.text")); // NOI18N
|
||||
intCheckBox.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
intCheckBoxActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
intList.setModel(new DefaultListModel<String>());
|
||||
intList.setEnabled(false);
|
||||
jScrollPane8.setViewportView(intList);
|
||||
|
||||
tagsList.setModel(new DefaultListModel<TagName>());
|
||||
tagsList.setEnabled(false);
|
||||
jScrollPane9.setViewportView(tagsList);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(tagsCheckBox, org.openide.util.NbBundle.getMessage(FileSearchDialog.class, "FileSearchDialog.tagsCheckBox.text")); // NOI18N
|
||||
tagsCheckBox.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
tagsCheckBoxActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
objList.setModel(new DefaultListModel<String>());
|
||||
objList.setEnabled(false);
|
||||
jScrollPane10.setViewportView(objList);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(objCheckBox, org.openide.util.NbBundle.getMessage(FileSearchDialog.class, "FileSearchDialog.objCheckBox.text")); // NOI18N
|
||||
objCheckBox.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
objCheckBoxActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
|
||||
getContentPane().setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
@ -615,30 +812,50 @@ public class FileSearchDialog extends javax.swing.JDialog implements ActionListe
|
||||
.addComponent(jScrollPane5)
|
||||
.addComponent(jScrollPane6, javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(filler1, javax.swing.GroupLayout.PREFERRED_SIZE, 265, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addGap(18, 18, 18)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(0, 0, Short.MAX_VALUE)
|
||||
.addComponent(searchButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(cancelButton))
|
||||
.addComponent(errorLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(cancelButton)
|
||||
.addContainerGap())
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(filler2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(errorLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGap(344, 344, 344))
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jLabel3)
|
||||
.addComponent(jLabel4)
|
||||
.addComponent(jLabel5))
|
||||
.addGap(29, 29, 29)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
|
||||
.addComponent(orderAttrRadioButton)
|
||||
.addComponent(groupComboBox, 0, 144, Short.MAX_VALUE)
|
||||
.addComponent(orderSizeRadioButton)
|
||||
.addComponent(fileOrderComboBox, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
|
||||
.addComponent(filler2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addGap(0, 25, Short.MAX_VALUE)))
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addComponent(hashCheckBox)
|
||||
.addGap(18, 18, 18)
|
||||
.addComponent(jScrollPane7))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(intCheckBox)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jScrollPane8))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(tagsCheckBox)
|
||||
.addGap(18, 18, 18)
|
||||
.addComponent(jScrollPane9))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(objCheckBox)
|
||||
.addGap(18, 18, 18)
|
||||
.addComponent(jScrollPane10)))
|
||||
.addGap(35, 35, 35)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jLabel3)
|
||||
.addComponent(jLabel4)
|
||||
.addComponent(jLabel5))
|
||||
.addGap(29, 29, 29)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
|
||||
.addComponent(orderAttrRadioButton)
|
||||
.addComponent(groupComboBox, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(orderSizeRadioButton)
|
||||
.addComponent(fileOrderComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 144, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addContainerGap())))
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
@ -648,8 +865,24 @@ public class FileSearchDialog extends javax.swing.JDialog implements ActionListe
|
||||
.addComponent(filler2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jLabel1)
|
||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 82, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jLabel1)
|
||||
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 82, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(jScrollPane7, javax.swing.GroupLayout.PREFERRED_SIZE, 49, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(hashCheckBox))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jScrollPane10, javax.swing.GroupLayout.PREFERRED_SIZE, 49, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(objCheckBox))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jScrollPane9, javax.swing.GroupLayout.PREFERRED_SIZE, 49, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(tagsCheckBox))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(dsCheckBox)
|
||||
.addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 56, javax.swing.GroupLayout.PREFERRED_SIZE)))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(jLabel3)
|
||||
@ -659,14 +892,14 @@ public class FileSearchDialog extends javax.swing.JDialog implements ActionListe
|
||||
.addComponent(jLabel4)
|
||||
.addComponent(orderAttrRadioButton))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(orderSizeRadioButton)))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(dsCheckBox)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(jLabel5)
|
||||
.addComponent(fileOrderComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 56, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addComponent(orderSizeRadioButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(jLabel5)
|
||||
.addComponent(fileOrderComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jScrollPane8, javax.swing.GroupLayout.PREFERRED_SIZE, 49, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(intCheckBox)))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(freqCheckBox)
|
||||
@ -698,8 +931,8 @@ public class FileSearchDialog extends javax.swing.JDialog implements ActionListe
|
||||
.addComponent(errorLabel))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(cancelButton)
|
||||
.addComponent(searchButton))
|
||||
.addComponent(searchButton)
|
||||
.addComponent(cancelButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
@ -767,6 +1000,22 @@ public class FileSearchDialog extends javax.swing.JDialog implements ActionListe
|
||||
setVisible(false);
|
||||
}//GEN-LAST:event_searchButtonActionPerformed
|
||||
|
||||
private void hashCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_hashCheckBoxActionPerformed
|
||||
hashList.setEnabled(hashCheckBox.isSelected());
|
||||
}//GEN-LAST:event_hashCheckBoxActionPerformed
|
||||
|
||||
private void intCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_intCheckBoxActionPerformed
|
||||
intList.setEnabled(intCheckBox.isSelected());
|
||||
}//GEN-LAST:event_intCheckBoxActionPerformed
|
||||
|
||||
private void tagsCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_tagsCheckBoxActionPerformed
|
||||
tagsList.setEnabled(tagsCheckBox.isSelected());
|
||||
}//GEN-LAST:event_tagsCheckBoxActionPerformed
|
||||
|
||||
private void objCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_objCheckBoxActionPerformed
|
||||
objList.setEnabled(objCheckBox.isSelected());
|
||||
}//GEN-LAST:event_objCheckBoxActionPerformed
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JButton addParentButton;
|
||||
private javax.swing.JButton cancelButton;
|
||||
@ -781,19 +1030,29 @@ public class FileSearchDialog extends javax.swing.JDialog implements ActionListe
|
||||
private javax.swing.JCheckBox freqCheckBox;
|
||||
private javax.swing.JList<Frequency> freqList;
|
||||
private javax.swing.JComboBox<GroupingAttributeType> groupComboBox;
|
||||
private javax.swing.JCheckBox hashCheckBox;
|
||||
private javax.swing.JList<String> hashList;
|
||||
private javax.swing.JCheckBox intCheckBox;
|
||||
private javax.swing.JList<String> intList;
|
||||
private javax.swing.JLabel jLabel1;
|
||||
private javax.swing.JLabel jLabel2;
|
||||
private javax.swing.JLabel jLabel3;
|
||||
private javax.swing.JLabel jLabel4;
|
||||
private javax.swing.JLabel jLabel5;
|
||||
private javax.swing.JScrollPane jScrollPane1;
|
||||
private javax.swing.JScrollPane jScrollPane10;
|
||||
private javax.swing.JScrollPane jScrollPane2;
|
||||
private javax.swing.JScrollPane jScrollPane3;
|
||||
private javax.swing.JScrollPane jScrollPane4;
|
||||
private javax.swing.JScrollPane jScrollPane5;
|
||||
private javax.swing.JScrollPane jScrollPane6;
|
||||
private javax.swing.JScrollPane jScrollPane7;
|
||||
private javax.swing.JScrollPane jScrollPane8;
|
||||
private javax.swing.JScrollPane jScrollPane9;
|
||||
private javax.swing.JCheckBox kwCheckBox;
|
||||
private javax.swing.JList<String> kwList;
|
||||
private javax.swing.JCheckBox objCheckBox;
|
||||
private javax.swing.JList<String> objList;
|
||||
private javax.swing.JRadioButton orderAttrRadioButton;
|
||||
private javax.swing.ButtonGroup orderButtonGroup;
|
||||
private javax.swing.JRadioButton orderSizeRadioButton;
|
||||
@ -806,5 +1065,7 @@ public class FileSearchDialog extends javax.swing.JDialog implements ActionListe
|
||||
private javax.swing.JButton searchButton;
|
||||
private javax.swing.JCheckBox sizeCheckBox;
|
||||
private javax.swing.JList<FileSize> sizeList;
|
||||
private javax.swing.JCheckBox tagsCheckBox;
|
||||
private javax.swing.JList<TagName> tagsList;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
}
|
||||
|
@ -30,12 +30,15 @@ import org.sleuthkit.autopsy.filequery.FileSearchData.Frequency;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.DataSource;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.TagName;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
|
||||
/**
|
||||
* Run various filters to return a subset of files from the current case.
|
||||
@ -381,13 +384,7 @@ class FileSearchFiltering {
|
||||
|
||||
@Override
|
||||
String getWhereClause() {
|
||||
String keywordListPart = ""; // NON-NLS
|
||||
for (String listName : listNames) {
|
||||
if (! keywordListPart.isEmpty()) {
|
||||
keywordListPart += " OR "; // NON-NLS
|
||||
}
|
||||
keywordListPart += "value_text = \'" + listName + "\'"; // TODO - these should really be prepared statements // NON-NLS
|
||||
}
|
||||
String keywordListPart = concatenateNamesForSQL(listNames);
|
||||
|
||||
String queryStr = "(obj_id IN (SELECT obj_id from blackboard_artifacts WHERE artifact_id IN " +
|
||||
"(SELECT artifact_id FROM blackboard_attributes WHERE artifact_type_id = 9 AND attribute_type_ID = 37 " +
|
||||
@ -399,19 +396,10 @@ class FileSearchFiltering {
|
||||
@NbBundle.Messages({
|
||||
"# {0} - filters",
|
||||
"FileSearchFiltering.KeywordListFilter.desc=Files with keywords in list(s): {0}",
|
||||
"FileSearchFiltering.KeywordListFilter.comma=, ",
|
||||
})
|
||||
@Override
|
||||
String getDesc() {
|
||||
String desc = ""; // NON-NLS
|
||||
for (String listName : listNames) {
|
||||
if ( ! desc.isEmpty()) {
|
||||
desc += Bundle.FileSearchFiltering_KeywordListFilter_comma();
|
||||
}
|
||||
desc += listName;
|
||||
}
|
||||
desc = Bundle.FileSearchFiltering_KeywordListFilter_desc(desc);
|
||||
return desc;
|
||||
return Bundle.FileSearchFiltering_KeywordListFilter_desc(concatenateSetNamesForDisplay(listNames));
|
||||
}
|
||||
}
|
||||
|
||||
@ -543,6 +531,198 @@ class FileSearchFiltering {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A filter for specifying hash set names.
|
||||
* A file must match one of the given sets to pass.
|
||||
*/
|
||||
static class HashSetFilter extends FileFilter {
|
||||
private final List<String> setNames;
|
||||
|
||||
/**
|
||||
* Create the HashSetFilter
|
||||
* @param setNames
|
||||
*/
|
||||
HashSetFilter(List<String> setNames) {
|
||||
this.setNames = setNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
String getWhereClause() {
|
||||
String hashSetPart = concatenateNamesForSQL(setNames);
|
||||
|
||||
String queryStr = "(obj_id IN (SELECT obj_id from blackboard_artifacts WHERE artifact_id IN " +
|
||||
"(SELECT artifact_id FROM blackboard_attributes WHERE artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID() +
|
||||
" AND attribute_type_ID = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID() + " " +
|
||||
"AND (" + hashSetPart + "))))"; // NON-NLS
|
||||
|
||||
return queryStr;
|
||||
}
|
||||
|
||||
@NbBundle.Messages({
|
||||
"# {0} - filters",
|
||||
"FileSearchFiltering.HashSetFilter.desc=Files with hash set hits in set(s): {0}",
|
||||
})
|
||||
@Override
|
||||
String getDesc() {
|
||||
return Bundle.FileSearchFiltering_HashSetFilter_desc(concatenateSetNamesForDisplay(setNames));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A filter for specifying interesting file set names.
|
||||
* A file must match one of the given sets to pass.
|
||||
*/
|
||||
static class InterestingFileSetFilter extends FileFilter {
|
||||
private final List<String> setNames;
|
||||
|
||||
/**
|
||||
* Create the InterestingFileSetFilter
|
||||
* @param setNames
|
||||
*/
|
||||
InterestingFileSetFilter(List<String> setNames) {
|
||||
this.setNames = setNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
String getWhereClause() {
|
||||
String intItemSetPart = concatenateNamesForSQL(setNames);
|
||||
|
||||
String queryStr = "(obj_id IN (SELECT obj_id from blackboard_artifacts WHERE artifact_id IN " +
|
||||
"(SELECT artifact_id FROM blackboard_attributes WHERE artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID() +
|
||||
" AND attribute_type_ID = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID() + " " +
|
||||
"AND (" + intItemSetPart + "))))"; // NON-NLS
|
||||
|
||||
return queryStr;
|
||||
}
|
||||
|
||||
@NbBundle.Messages({
|
||||
"# {0} - filters",
|
||||
"FileSearchFiltering.InterestingItemSetFilter.desc=Files with interesting item hits in set(s): {0}",
|
||||
})
|
||||
@Override
|
||||
String getDesc() {
|
||||
return Bundle.FileSearchFiltering_InterestingItemSetFilter_desc(concatenateSetNamesForDisplay(setNames));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A filter for specifying object types detected.
|
||||
* A file must match one of the given types to pass.
|
||||
*/
|
||||
static class ObjectDetectionFilter extends FileFilter {
|
||||
private final List<String> typeNames;
|
||||
|
||||
/**
|
||||
* Create the ObjectDetectionFilter
|
||||
* @param typeNames
|
||||
*/
|
||||
ObjectDetectionFilter(List<String> typeNames) {
|
||||
this.typeNames = typeNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
String getWhereClause() {
|
||||
String objTypePart = concatenateNamesForSQL(typeNames);
|
||||
|
||||
String queryStr = "(obj_id IN (SELECT obj_id from blackboard_artifacts WHERE artifact_id IN " +
|
||||
"(SELECT artifact_id FROM blackboard_attributes WHERE artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_OBJECT_DETECTED.getTypeID() +
|
||||
" AND attribute_type_ID = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DESCRIPTION.getTypeID() + " " +
|
||||
"AND (" + objTypePart + "))))"; // NON-NLS
|
||||
|
||||
return queryStr;
|
||||
}
|
||||
|
||||
@NbBundle.Messages({
|
||||
"# {0} - filters",
|
||||
"FileSearchFiltering.ObjectDetectionFilter.desc=Files with objects detected in set(s): {0}",
|
||||
})
|
||||
@Override
|
||||
String getDesc() {
|
||||
return Bundle.FileSearchFiltering_ObjectDetectionFilter_desc(concatenateSetNamesForDisplay(typeNames));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A filter for specifying tag names.
|
||||
* A file must contain one of the given tags to pass.
|
||||
*/
|
||||
static class TagsFilter extends FileFilter {
|
||||
private final List<TagName> tagNames;
|
||||
|
||||
/**
|
||||
* Create the TagsFilter
|
||||
* @param tagNames
|
||||
*/
|
||||
TagsFilter(List<TagName> tagNames) {
|
||||
this.tagNames = tagNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
String getWhereClause() {
|
||||
String tagIDs = ""; // NON-NLS
|
||||
for (TagName tagName : tagNames) {
|
||||
if (! tagIDs.isEmpty()) {
|
||||
tagIDs += ",";
|
||||
}
|
||||
tagIDs += tagName.getId();
|
||||
}
|
||||
|
||||
String queryStr = "(obj_id IN (SELECT obj_id FROM content_tags WHERE tag_name_id IN (" + tagIDs + ")))";
|
||||
|
||||
return queryStr;
|
||||
}
|
||||
|
||||
@NbBundle.Messages({
|
||||
"# {0} - tag names",
|
||||
"FileSearchFiltering.TagsFilter.desc=Files that have been tagged {0}",
|
||||
"FileSearchFiltering.TagsFilter.or= or ",
|
||||
})
|
||||
@Override
|
||||
String getDesc() {
|
||||
String desc = ""; // NON-NLS
|
||||
for (TagName name : tagNames) {
|
||||
if ( ! desc.isEmpty()) {
|
||||
desc += Bundle.FileSearchFiltering_TagsFilter_or();
|
||||
}
|
||||
desc += name.getDisplayName();
|
||||
}
|
||||
return Bundle.FileSearchFiltering_TagsFilter_desc(desc); // Nope
|
||||
}
|
||||
}
|
||||
|
||||
@NbBundle.Messages({
|
||||
"FileSearchFiltering.concatenateSetNamesForDisplay.comma=, ",
|
||||
})
|
||||
private static String concatenateSetNamesForDisplay(List<String> setNames) {
|
||||
String desc = ""; // NON-NLS
|
||||
for (String setName : setNames) {
|
||||
if ( ! desc.isEmpty()) {
|
||||
desc += Bundle.FileSearchFiltering_concatenateSetNamesForDisplay_comma();
|
||||
}
|
||||
desc += setName;
|
||||
}
|
||||
return desc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenate the set names into an "OR" separated list.
|
||||
* This does not do any SQL-escaping.
|
||||
*
|
||||
* @param setNames
|
||||
*
|
||||
* @return the list to use in the SQL query
|
||||
*/
|
||||
private static String concatenateNamesForSQL(List<String> setNames) {
|
||||
String result = ""; // NON-NLS
|
||||
for (String setName : setNames) {
|
||||
if (! result.isEmpty()) {
|
||||
result += " OR "; // NON-NLS
|
||||
}
|
||||
result += "value_text = \'" + setName + "\'"; // NON-NLS
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private FileSearchFiltering() {
|
||||
// Class should not be instantiated
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ class ResultFile {
|
||||
private final List<String> hashSetNames;
|
||||
private final List<String> tagNames;
|
||||
private final List<String> interestingSetNames;
|
||||
private final List<String> objectDetectedNames;
|
||||
private FileType fileType;
|
||||
|
||||
/**
|
||||
@ -47,9 +48,11 @@ class ResultFile {
|
||||
this.abstractFile = abstractFile;
|
||||
this.frequency = FileSearchData.Frequency.UNKNOWN;
|
||||
keywordListNames = new ArrayList<>();
|
||||
hashSetNames = new ArrayList();
|
||||
tagNames = new ArrayList();
|
||||
interestingSetNames = new ArrayList();
|
||||
hashSetNames = new ArrayList<>();
|
||||
tagNames = new ArrayList<>();
|
||||
interestingSetNames = new ArrayList<>();
|
||||
objectDetectedNames = new ArrayList<>();
|
||||
|
||||
fileType = FileType.OTHER;
|
||||
}
|
||||
|
||||
@ -159,7 +162,7 @@ class ResultFile {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a hash set name that matched this file.
|
||||
* Add an interesting file set name that matched this file.
|
||||
*
|
||||
* @param interestingSetName
|
||||
*/
|
||||
@ -181,6 +184,29 @@ class ResultFile {
|
||||
return interestingSetNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an object detected in this file.
|
||||
*
|
||||
* @param objectDetectedName
|
||||
*/
|
||||
void addObjectDetectedName (String objectDetectedName) {
|
||||
if (! objectDetectedNames.contains(objectDetectedName)) {
|
||||
objectDetectedNames.add(objectDetectedName);
|
||||
}
|
||||
|
||||
// Sort the list so the getObjectDetectedNames() will be consistent regardless of the order added
|
||||
Collections.sort(objectDetectedNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the objects detected for this file
|
||||
*
|
||||
* @return the objects detected in this file.
|
||||
*/
|
||||
List<String> getObjectDetectedNames() {
|
||||
return objectDetectedNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the AbstractFile
|
||||
*
|
||||
|
Loading…
x
Reference in New Issue
Block a user