mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-14 17:06:16 +00:00
Merge pull request #6252 from wschaeferB/6714-displayDomainGroups-with6713
6714 display domain groups with6713
This commit is contained in:
commit
80b78b8736
@ -1,9 +1,11 @@
|
||||
DiscoveryAttributes.GroupingAttributeType.datasource.displayName=Data Source
|
||||
DiscoveryAttributes.GroupingAttributeType.fileType.displayName=File Type
|
||||
DiscoveryAttributes.GroupingAttributeType.firstDate.displayName=First Activity Date
|
||||
DiscoveryAttributes.GroupingAttributeType.frequency.displayName=Past Occurrences
|
||||
DiscoveryAttributes.GroupingAttributeType.hash.displayName=Hash Set
|
||||
DiscoveryAttributes.GroupingAttributeType.interestingItem.displayName=Interesting Item
|
||||
DiscoveryAttributes.GroupingAttributeType.keywordList.displayName=Keyword
|
||||
DiscoveryAttributes.GroupingAttributeType.mostRecentDate.displayName=Most Recent Activity Date
|
||||
DiscoveryAttributes.GroupingAttributeType.none.displayName=None
|
||||
DiscoveryAttributes.GroupingAttributeType.object.displayName=Object Detected
|
||||
DiscoveryAttributes.GroupingAttributeType.parent.displayName=Parent Folder
|
||||
@ -15,15 +17,17 @@ DiscoveryKeyUtils.DataSourceGroupKey.datasourceAndID={0}(ID: {1})
|
||||
# {0} - Data source ID
|
||||
DiscoveryKeyUtils.DataSourceGroupKey.idOnly=Data source (ID: {0})
|
||||
DiscoveryKeyUtils.FileTagGroupKey.noSets=None
|
||||
DiscoveryKeyUtils.FirstActivityDateGroupKey.noDate=No Date Available
|
||||
DiscoveryKeyUtils.HashHitsGroupKey.noHashHits=None
|
||||
DiscoveryKeyUtils.InterestingItemGroupKey.noSets=None
|
||||
DiscoveryKeyUtils.KeywordListGroupKey.noKeywords=None
|
||||
DiscoveryKeyUtils.MostRecentActivityDateGroupKey.noDate=No Date Available
|
||||
DiscoveryKeyUtils.NoGroupingGroupKey.allFiles=All Files
|
||||
DiscoveryKeyUtils.ObjectDetectedGroupKey.noSets=None
|
||||
FileGroup.groupSortingAlgorithm.groupName.text=Group Name
|
||||
FileGroup.groupSortingAlgorithm.groupSize.text=Group Size
|
||||
FileSearch.documentSummary.noBytes=No bytes read for document, unable to display preview.
|
||||
FileSearch.documentSummary.noPreview=No preview available.
|
||||
FileSearch.HashHitsGroupKey.noHashHits=None
|
||||
FileSearch.InterestingItemGroupKey.noSets=None
|
||||
FileSearch.KeywordListGroupKey.noKeywords=None
|
||||
FileSearch.ObjectDetectedGroupKey.noSets=None
|
||||
FileSearchFiltering.concatenateSetNamesForDisplay.comma=,
|
||||
# {0} - filters
|
||||
FileSearchFiltering.HashSetFilter.desc=Hash set hits in set(s): {0}
|
||||
|
@ -256,9 +256,7 @@ public class DiscoveryAttributes {
|
||||
CentralRepository centralRepoDb) throws DiscoveryException {
|
||||
List<ResultFile> currentFiles = new ArrayList<>();
|
||||
Set<String> hashesToLookUp = new HashSet<>();
|
||||
|
||||
List<ResultDomain> domainsToQuery = new ArrayList<>();
|
||||
|
||||
for (Result result : results) {
|
||||
if (result.getKnown() == TskData.FileKnown.KNOWN) {
|
||||
result.setFrequency(SearchData.Frequency.KNOWN);
|
||||
@ -274,10 +272,10 @@ public class DiscoveryAttributes {
|
||||
}
|
||||
|
||||
if (hashesToLookUp.size() >= BATCH_SIZE) {
|
||||
computeFrequency(hashesToLookUp, currentFiles, centralRepoDb);
|
||||
computeFrequency(hashesToLookUp, currentFiles, centralRepoDb);
|
||||
|
||||
hashesToLookUp.clear();
|
||||
currentFiles.clear();
|
||||
hashesToLookUp.clear();
|
||||
currentFiles.clear();
|
||||
}
|
||||
} else {
|
||||
ResultDomain domainInstance = (ResultDomain) result;
|
||||
@ -306,7 +304,7 @@ public class DiscoveryAttributes {
|
||||
final StringJoiner joiner = new StringJoiner(", ");
|
||||
|
||||
final CorrelationAttributeInstance.Type attributeType = centralRepository.getCorrelationTypeById(CorrelationAttributeInstance.DOMAIN_TYPE_ID);
|
||||
for(ResultDomain domainInstance : domainsToQuery) {
|
||||
for (ResultDomain domainInstance : domainsToQuery) {
|
||||
try {
|
||||
final String domainValue = domainInstance.getDomain();
|
||||
final String normalizedDomain = CorrelationAttributeNormalizer.normalize(attributeType, domainValue);
|
||||
@ -320,10 +318,10 @@ public class DiscoveryAttributes {
|
||||
}
|
||||
|
||||
final String tableName = CentralRepoDbUtil.correlationTypeToInstanceTableName(attributeType);
|
||||
final String domainFrequencyQuery = " value AS domain_name, COUNT(*) AS frequency " +
|
||||
"FROM " + tableName + " " +
|
||||
"WHERE value IN (" + joiner + ") " +
|
||||
"GROUP BY value";
|
||||
final String domainFrequencyQuery = " value AS domain_name, COUNT(*) AS frequency "
|
||||
+ "FROM " + tableName + " "
|
||||
+ "WHERE value IN (" + joiner + ") "
|
||||
+ "GROUP BY value";
|
||||
|
||||
final DomainFrequencyCallback frequencyCallback = new DomainFrequencyCallback(resultDomainTable);
|
||||
centralRepository.processSelectClause(domainFrequencyQuery, frequencyCallback);
|
||||
@ -353,7 +351,7 @@ public class DiscoveryAttributes {
|
||||
Long frequency = resultSet.getLong("frequency");
|
||||
|
||||
List<ResultDomain> domainInstances = domainLookup.get(domain);
|
||||
for(ResultDomain domainInstance : domainInstances) {
|
||||
for (ResultDomain domainInstance : domainInstances) {
|
||||
domainInstance.setFrequency(SearchData.Frequency.fromCount(frequency));
|
||||
}
|
||||
}
|
||||
@ -560,6 +558,30 @@ public class DiscoveryAttributes {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attribute for grouping/sorting by date of most recent activity.
|
||||
*/
|
||||
static class MostRecentActivityDateAttribute extends AttributeType {
|
||||
|
||||
@Override
|
||||
public DiscoveryKeyUtils.GroupKey getGroupKey(Result result) {
|
||||
return new DiscoveryKeyUtils.MostRecentActivityDateGroupKey(result);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Attribute for grouping/sorting by date of first activity.
|
||||
*/
|
||||
static class FirstActivityDateAttribute extends AttributeType {
|
||||
|
||||
@Override
|
||||
public DiscoveryKeyUtils.GroupKey getGroupKey(Result result) {
|
||||
return new DiscoveryKeyUtils.FirstActivityDateGroupKey(result);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Attribute for grouping/sorting by objects detected
|
||||
*/
|
||||
@ -682,6 +704,8 @@ public class DiscoveryAttributes {
|
||||
"DiscoveryAttributes.GroupingAttributeType.interestingItem.displayName=Interesting Item",
|
||||
"DiscoveryAttributes.GroupingAttributeType.tag.displayName=Tag",
|
||||
"DiscoveryAttributes.GroupingAttributeType.object.displayName=Object Detected",
|
||||
"DiscoveryAttributes.GroupingAttributeType.mostRecentDate.displayName=Most Recent Activity Date",
|
||||
"DiscoveryAttributes.GroupingAttributeType.firstDate.displayName=First Activity Date",
|
||||
"DiscoveryAttributes.GroupingAttributeType.none.displayName=None"})
|
||||
public enum GroupingAttributeType {
|
||||
FILE_SIZE(new FileSizeAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_size_displayName()),
|
||||
@ -693,6 +717,8 @@ public class DiscoveryAttributes {
|
||||
INTERESTING_ITEM_SET(new InterestingItemAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_interestingItem_displayName()),
|
||||
FILE_TAG(new FileTagAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_tag_displayName()),
|
||||
OBJECT_DETECTED(new ObjectDetectedAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_object_displayName()),
|
||||
MOST_RECENT_DATE(new MostRecentActivityDateAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_mostRecentDate_displayName()),
|
||||
FIRST_DATE(new FirstActivityDateAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_firstDate_displayName()),
|
||||
NO_GROUPING(new NoGroupingAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_none_displayName());
|
||||
|
||||
private final AttributeType attributeType;
|
||||
@ -713,13 +739,22 @@ public class DiscoveryAttributes {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of enums that are valid for grouping images.
|
||||
* Get the list of enums that are valid for grouping files.
|
||||
*
|
||||
* @return enums that can be used to group images
|
||||
* @return Enums that can be used to group files.
|
||||
*/
|
||||
public static List<GroupingAttributeType> getOptionsForGrouping() {
|
||||
public static List<GroupingAttributeType> getOptionsForGroupingForFiles() {
|
||||
return Arrays.asList(FILE_SIZE, FREQUENCY, PARENT_PATH, OBJECT_DETECTED, HASH_LIST_NAME, INTERESTING_ITEM_SET);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of enums that are valid for grouping files.
|
||||
*
|
||||
* @return Enums that can be used to group files.
|
||||
*/
|
||||
public static List<GroupingAttributeType> getOptionsForGroupingForDomains() {
|
||||
return Arrays.asList(FREQUENCY, MOST_RECENT_DATE, FIRST_DATE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -18,9 +18,13 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.discovery.search;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
|
||||
@ -83,7 +87,8 @@ public class DiscoveryKeyUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a SearchKey without a SleuthkitCase or CentralRepositry instance.
|
||||
* Construct a SearchKey without a SleuthkitCase or CentralRepositry
|
||||
* instance.
|
||||
*/
|
||||
SearchKey(String userName, List<AbstractFilter> filters,
|
||||
DiscoveryAttributes.AttributeType groupAttributeType,
|
||||
@ -109,8 +114,8 @@ public class DiscoveryKeyUtils {
|
||||
}
|
||||
|
||||
SearchKey otherSearchKey = (SearchKey) otherKey;
|
||||
if (this.sleuthkitCase != otherSearchKey.getSleuthkitCase() ||
|
||||
this.centralRepository != otherSearchKey.getCentralRepository()) {
|
||||
if (this.sleuthkitCase != otherSearchKey.getSleuthkitCase()
|
||||
|| this.centralRepository != otherSearchKey.getCentralRepository()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -125,24 +130,46 @@ public class DiscoveryKeyUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the keyString
|
||||
* Get the String representation of this key.
|
||||
*
|
||||
* @return The String representation of this key.
|
||||
*/
|
||||
String getKeyString() {
|
||||
return keyString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of filters associated with this key.
|
||||
*
|
||||
* @return The list of filters associated with this key.
|
||||
*/
|
||||
List<AbstractFilter> getFilters() {
|
||||
return Collections.unmodifiableList(this.filters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the group sorting type for this key.
|
||||
*
|
||||
* @return The group sorting type for this key.
|
||||
*/
|
||||
Group.GroupSortingAlgorithm getGroupSortingType() {
|
||||
return groupSortingType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the grouping attribute for this key.
|
||||
*
|
||||
* @return The grouping attribute for this key.
|
||||
*/
|
||||
DiscoveryAttributes.AttributeType getGroupAttributeType() {
|
||||
return groupAttributeType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fileSorting
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
ResultsSorter.SortingMethod getFileSortingMethod() {
|
||||
return fileSortingMethod;
|
||||
}
|
||||
@ -326,12 +353,12 @@ public class DiscoveryKeyUtils {
|
||||
private final String keywordListNamesString;
|
||||
|
||||
@NbBundle.Messages({
|
||||
"FileSearch.KeywordListGroupKey.noKeywords=None"})
|
||||
"DiscoveryKeyUtils.KeywordListGroupKey.noKeywords=None"})
|
||||
KeywordListGroupKey(ResultFile file) {
|
||||
keywordListNames = file.getKeywordListNames();
|
||||
|
||||
if (keywordListNames.isEmpty()) {
|
||||
keywordListNamesString = Bundle.FileSearch_KeywordListGroupKey_noKeywords();
|
||||
keywordListNamesString = Bundle.DiscoveryKeyUtils_KeywordListGroupKey_noKeywords();
|
||||
} else {
|
||||
keywordListNamesString = String.join(",", keywordListNames); // NON-NLS
|
||||
}
|
||||
@ -760,12 +787,12 @@ public class DiscoveryKeyUtils {
|
||||
private final String hashSetNamesString;
|
||||
|
||||
@NbBundle.Messages({
|
||||
"FileSearch.HashHitsGroupKey.noHashHits=None"})
|
||||
"DiscoveryKeyUtils.HashHitsGroupKey.noHashHits=None"})
|
||||
HashHitsGroupKey(ResultFile file) {
|
||||
hashSetNames = file.getHashSetNames();
|
||||
|
||||
if (hashSetNames.isEmpty()) {
|
||||
hashSetNamesString = Bundle.FileSearch_HashHitsGroupKey_noHashHits();
|
||||
hashSetNamesString = Bundle.DiscoveryKeyUtils_HashHitsGroupKey_noHashHits();
|
||||
} else {
|
||||
hashSetNamesString = String.join(",", hashSetNames); // NON-NLS
|
||||
}
|
||||
@ -841,12 +868,12 @@ public class DiscoveryKeyUtils {
|
||||
private final String interestingItemSetNamesString;
|
||||
|
||||
@NbBundle.Messages({
|
||||
"FileSearch.InterestingItemGroupKey.noSets=None"})
|
||||
"DiscoveryKeyUtils.InterestingItemGroupKey.noSets=None"})
|
||||
InterestingItemGroupKey(ResultFile file) {
|
||||
interestingItemSetNames = file.getInterestingSetNames();
|
||||
|
||||
if (interestingItemSetNames.isEmpty()) {
|
||||
interestingItemSetNamesString = Bundle.FileSearch_InterestingItemGroupKey_noSets();
|
||||
interestingItemSetNamesString = Bundle.DiscoveryKeyUtils_InterestingItemGroupKey_noSets();
|
||||
} else {
|
||||
interestingItemSetNamesString = String.join(",", interestingItemSetNames); // NON-NLS
|
||||
}
|
||||
@ -913,6 +940,176 @@ public class DiscoveryKeyUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Key representing a date of most recent activity.
|
||||
*/
|
||||
static class MostRecentActivityDateGroupKey extends GroupKey {
|
||||
|
||||
private final Long epochDate;
|
||||
private final String dateNameString;
|
||||
|
||||
@NbBundle.Messages({
|
||||
"DiscoveryKeyUtils.MostRecentActivityDateGroupKey.noDate=No Date Available"})
|
||||
MostRecentActivityDateGroupKey(Result result) {
|
||||
if (result instanceof ResultDomain) {
|
||||
epochDate = ((ResultDomain) result).getActivityEnd();
|
||||
dateNameString = new SimpleDateFormat("yyyy/MM/dd").format(new Date(TimeUnit.SECONDS.toMillis(epochDate)));
|
||||
} else {
|
||||
epochDate = Long.MAX_VALUE;
|
||||
dateNameString = Bundle.DiscoveryKeyUtils_MostRecentActivityDateGroupKey_noDate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
String getDisplayName() {
|
||||
return getDateNameString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object otherKey) {
|
||||
if (otherKey == this) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(otherKey instanceof MostRecentActivityDateGroupKey)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MostRecentActivityDateGroupKey dateGroupKey = (MostRecentActivityDateGroupKey) otherKey;
|
||||
return getDateNameString().equals(dateGroupKey.getDateNameString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(getDateNameString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(GroupKey otherGroupKey) {
|
||||
if (otherGroupKey instanceof MostRecentActivityDateGroupKey) {
|
||||
MostRecentActivityDateGroupKey otherDateGroupKey = (MostRecentActivityDateGroupKey) otherGroupKey;
|
||||
|
||||
// Put the empty list at the end
|
||||
if (this.getEpochDate().equals(Long.MAX_VALUE)) {
|
||||
if (otherDateGroupKey.getEpochDate().equals(Long.MAX_VALUE)) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
} else if (otherDateGroupKey.getEpochDate().equals(Long.MAX_VALUE)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return getDateNameString().compareTo(otherDateGroupKey.getDateNameString());
|
||||
} else {
|
||||
return compareClassNames(otherGroupKey);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the date this group is for as a Long.
|
||||
*
|
||||
* @return The date.
|
||||
*/
|
||||
Long getEpochDate() {
|
||||
return epochDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name which identifies this group.
|
||||
*
|
||||
* @return The dateNameString
|
||||
*/
|
||||
String getDateNameString() {
|
||||
return dateNameString;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Key representing a date of first activity.
|
||||
*/
|
||||
static class FirstActivityDateGroupKey extends GroupKey {
|
||||
|
||||
private final Long epochDate;
|
||||
private final String dateNameString;
|
||||
|
||||
@NbBundle.Messages({
|
||||
"DiscoveryKeyUtils.FirstActivityDateGroupKey.noDate=No Date Available"})
|
||||
FirstActivityDateGroupKey(Result result) {
|
||||
if (result instanceof ResultDomain) {
|
||||
epochDate = ((ResultDomain) result).getActivityStart();
|
||||
dateNameString = new SimpleDateFormat("yyyy/MM/dd", Locale.getDefault()).format(new Date(TimeUnit.SECONDS.toMillis(epochDate)));
|
||||
} else {
|
||||
epochDate = Long.MAX_VALUE;
|
||||
dateNameString = Bundle.DiscoveryKeyUtils_FirstActivityDateGroupKey_noDate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
String getDisplayName() {
|
||||
return getDateNameString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object otherKey) {
|
||||
if (otherKey == this) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(otherKey instanceof FirstActivityDateGroupKey)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FirstActivityDateGroupKey dateGroupKey = (FirstActivityDateGroupKey) otherKey;
|
||||
return getDateNameString().equals(dateGroupKey.getDateNameString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(getDateNameString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(GroupKey otherGroupKey) {
|
||||
if (otherGroupKey instanceof FirstActivityDateGroupKey) {
|
||||
FirstActivityDateGroupKey otherDateGroupKey = (FirstActivityDateGroupKey) otherGroupKey;
|
||||
|
||||
// Put the empty list at the end
|
||||
if (this.getEpochDate().equals(Long.MAX_VALUE)) {
|
||||
if (otherDateGroupKey.getEpochDate().equals(Long.MAX_VALUE)) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
} else if (otherDateGroupKey.getEpochDate().equals(Long.MAX_VALUE)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return getDateNameString().compareTo(otherDateGroupKey.getDateNameString());
|
||||
} else {
|
||||
return compareClassNames(otherGroupKey);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the date this group is for as a Long.
|
||||
*
|
||||
* @return The date.
|
||||
*/
|
||||
Long getEpochDate() {
|
||||
return epochDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name which identifies this group.
|
||||
*
|
||||
* @return The dateNameString
|
||||
*/
|
||||
String getDateNameString() {
|
||||
return dateNameString;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Key representing an object detected group
|
||||
*/
|
||||
@ -922,12 +1119,12 @@ public class DiscoveryKeyUtils {
|
||||
private final String objectDetectedNamesString;
|
||||
|
||||
@NbBundle.Messages({
|
||||
"FileSearch.ObjectDetectedGroupKey.noSets=None"})
|
||||
"DiscoveryKeyUtils.ObjectDetectedGroupKey.noSets=None"})
|
||||
ObjectDetectedGroupKey(ResultFile file) {
|
||||
objectDetectedNames = file.getObjectDetectedNames();
|
||||
|
||||
if (objectDetectedNames.isEmpty()) {
|
||||
objectDetectedNamesString = Bundle.FileSearch_ObjectDetectedGroupKey_noSets();
|
||||
objectDetectedNamesString = Bundle.DiscoveryKeyUtils_ObjectDetectedGroupKey_noSets();
|
||||
} else {
|
||||
objectDetectedNamesString = String.join(",", objectDetectedNames); // NON-NLS
|
||||
}
|
||||
|
@ -36,10 +36,10 @@ import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
class DomainSearchCache {
|
||||
|
||||
private static final int MAXIMUM_CACHE_SIZE = 10;
|
||||
private static final LoadingCache<SearchKey, Map<GroupKey, List<Result>>> cache =
|
||||
CacheBuilder.newBuilder()
|
||||
.maximumSize(MAXIMUM_CACHE_SIZE)
|
||||
.build(new DomainSearchCacheLoader());
|
||||
private static final LoadingCache<SearchKey, Map<GroupKey, List<Result>>> cache
|
||||
= CacheBuilder.newBuilder()
|
||||
.maximumSize(MAXIMUM_CACHE_SIZE)
|
||||
.build(new DomainSearchCacheLoader());
|
||||
|
||||
/**
|
||||
* Get domain search results matching the given parameters. If no results
|
||||
|
@ -235,7 +235,7 @@ public class ResultsSorter implements Comparator<Result> {
|
||||
*/
|
||||
private static Comparator<Result> getDomainNameComparator() {
|
||||
return (Result domain1, Result domain2) -> {
|
||||
if(domain1.getType() != SearchData.Type.DOMAIN) {
|
||||
if (domain1.getType() != SearchData.Type.DOMAIN) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -327,7 +327,7 @@ public class ResultsSorter implements Comparator<Result> {
|
||||
BY_KEYWORD_LIST_NAMES(Arrays.asList(new DiscoveryAttributes.KeywordListAttribute()),
|
||||
Bundle.FileSorter_SortingMethod_keywordlist_displayName()), // Sort alphabetically by list of keyword list names found
|
||||
BY_FULL_PATH(new ArrayList<>(),
|
||||
Bundle.FileSorter_SortingMethod_fullPath_displayName()), // Sort alphabetically by path
|
||||
Bundle.FileSorter_SortingMethod_fullPath_displayName()), // Sort alphabetically by path
|
||||
BY_DOMAIN_NAME(new ArrayList<>(),
|
||||
Bundle.FileSorter_SortingMethod_domain_displayName());
|
||||
|
||||
@ -349,12 +349,22 @@ public class ResultsSorter implements Comparator<Result> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of enums that are valid for ordering images.
|
||||
* Get the list of enums that are valid for ordering files.
|
||||
*
|
||||
* @return enums that can be used to ordering images.
|
||||
* @return Enums that can be used to ordering files.
|
||||
*/
|
||||
public static List<SortingMethod> getOptionsForOrdering() {
|
||||
public static List<SortingMethod> getOptionsForOrderingFiles() {
|
||||
return Arrays.asList(BY_FILE_SIZE, BY_FULL_PATH, BY_FILE_NAME, BY_DATA_SOURCE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of enums that are valid for ordering files.
|
||||
*
|
||||
* @return Enums that can be used to ordering files.
|
||||
*/
|
||||
public static List<SortingMethod> getOptionsForOrderingDomains() {
|
||||
return Arrays.asList(BY_DOMAIN_NAME, BY_DATA_SOURCE);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -32,6 +32,9 @@ import javax.swing.JSplitPane;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.sleuthkit.autopsy.discovery.search.DiscoveryAttributes.GroupingAttributeType;
|
||||
import org.sleuthkit.autopsy.discovery.search.Group;
|
||||
import org.sleuthkit.autopsy.discovery.search.ResultsSorter.SortingMethod;
|
||||
import org.sleuthkit.autopsy.discovery.search.SearchData;
|
||||
import org.sleuthkit.autopsy.discovery.search.SearchFiltering;
|
||||
|
||||
@ -55,6 +58,9 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li
|
||||
private final JPanel secondColumnPanel = new JPanel();
|
||||
private int firstColumnY = 0;
|
||||
private int secondColumnY = 0;
|
||||
private SortingMethod lastSortingMethod = SortingMethod.BY_FILE_NAME;
|
||||
private GroupingAttributeType lastGroupingAttributeType = GroupingAttributeType.PARENT_PATH;
|
||||
private Group.GroupSortingAlgorithm lastGroupSortingAlg = Group.GroupSortingAlgorithm.BY_GROUP_SIZE;
|
||||
|
||||
/**
|
||||
* Setup necessary for implementations of this abstract class.
|
||||
@ -64,6 +70,7 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li
|
||||
secondColumnPanel.setLayout(new GridBagLayout());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the type of results this filters panel is for.
|
||||
*
|
||||
@ -248,12 +255,9 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li
|
||||
synchronized List<AbstractFilter> getFilters() {
|
||||
|
||||
List<AbstractFilter> filtersToUse = new ArrayList<>();
|
||||
if (getType().equals(SearchData.Type.DOMAIN)) {
|
||||
|
||||
} else {
|
||||
if (getType() != SearchData.Type.DOMAIN) { //Domain type does not have a file type
|
||||
filtersToUse.add(new SearchFiltering.FileTypeFilter(getType()));
|
||||
}
|
||||
|
||||
for (AbstractDiscoveryFilterPanel filterPanel : filters) {
|
||||
if (filterPanel.getCheckbox().isSelected()) {
|
||||
AbstractFilter filter = filterPanel.getFilter();
|
||||
@ -274,4 +278,46 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the lastSortingMethod
|
||||
*/
|
||||
SortingMethod getLastSortingMethod() {
|
||||
return lastSortingMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param lastSortingMethod the lastSortingMethod to set
|
||||
*/
|
||||
final void setLastSortingMethod(SortingMethod lastSortingMethod) {
|
||||
this.lastSortingMethod = lastSortingMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the lastGroupingAttributeType
|
||||
*/
|
||||
GroupingAttributeType getLastGroupingAttributeType() {
|
||||
return lastGroupingAttributeType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param lastGroupingAttributeType the lastGroupingAttributeType to set
|
||||
*/
|
||||
final void setLastGroupingAttributeType(GroupingAttributeType lastGroupingAttributeType) {
|
||||
this.lastGroupingAttributeType = lastGroupingAttributeType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the lastGroupSortingAlg
|
||||
*/
|
||||
Group.GroupSortingAlgorithm getLastGroupSortingAlg() {
|
||||
return lastGroupSortingAlg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param lastGroupSortingAlg the lastGroupSortingAlg to set
|
||||
*/
|
||||
final void setLastGroupSortingAlg(Group.GroupSortingAlgorithm lastGroupSortingAlg) {
|
||||
this.lastGroupSortingAlg = lastGroupSortingAlg;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -8,6 +8,9 @@
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/discovery/ui/Bundle.properties" key="ArtifactTypeFilterPanel.artifactTypeCheckbox.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="artifactTypeCheckboxActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
</NonVisualComponents>
|
||||
<Properties>
|
||||
@ -49,7 +52,7 @@
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JList" name="jList1">
|
||||
<Component class="javax.swing.JList" name="artifactList">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||
<Connection code="new DefaultListModel<ArtifactTypeItem>()" type="code"/>
|
||||
|
@ -18,12 +18,16 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.discovery.ui;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.sleuthkit.autopsy.discovery.search.AbstractFilter;
|
||||
import javax.swing.DefaultListModel;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.discovery.search.SearchData;
|
||||
import org.sleuthkit.autopsy.discovery.search.SearchFiltering.ArtifactTypeFilter;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
|
||||
/**
|
||||
@ -47,7 +51,7 @@ class ArtifactTypeFilterPanel extends AbstractDiscoveryFilterPanel {
|
||||
*/
|
||||
private void setUpArtifactTypeFilter() {
|
||||
int count = 0;
|
||||
DefaultListModel<ArtifactTypeItem> artifactTypeModel = (DefaultListModel<ArtifactTypeItem>) jList1.getModel();
|
||||
DefaultListModel<ArtifactTypeItem> artifactTypeModel = (DefaultListModel<ArtifactTypeItem>) artifactList.getModel();
|
||||
artifactTypeModel.removeAllElements();
|
||||
for (BlackboardArtifact.ARTIFACT_TYPE artifactType : SearchData.Type.DOMAIN.getArtifactTypes()) {
|
||||
artifactTypeModel.add(count, new ArtifactTypeItem(artifactType));
|
||||
@ -66,17 +70,22 @@ class ArtifactTypeFilterPanel extends AbstractDiscoveryFilterPanel {
|
||||
|
||||
artifactTypeCheckbox = new javax.swing.JCheckBox();
|
||||
artifactTypeScrollPane = new javax.swing.JScrollPane();
|
||||
jList1 = new javax.swing.JList<>();
|
||||
artifactList = new javax.swing.JList<>();
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(artifactTypeCheckbox, org.openide.util.NbBundle.getMessage(ArtifactTypeFilterPanel.class, "ArtifactTypeFilterPanel.artifactTypeCheckbox.text")); // NOI18N
|
||||
artifactTypeCheckbox.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
artifactTypeCheckboxActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
setPreferredSize(new java.awt.Dimension(27, 27));
|
||||
|
||||
artifactTypeScrollPane.setPreferredSize(new java.awt.Dimension(27, 27));
|
||||
|
||||
jList1.setModel(new DefaultListModel<ArtifactTypeItem>());
|
||||
jList1.setEnabled(false);
|
||||
artifactTypeScrollPane.setViewportView(jList1);
|
||||
artifactList.setModel(new DefaultListModel<ArtifactTypeItem>());
|
||||
artifactList.setEnabled(false);
|
||||
artifactTypeScrollPane.setViewportView(artifactList);
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
@ -90,9 +99,24 @@ class ArtifactTypeFilterPanel extends AbstractDiscoveryFilterPanel {
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
private void artifactTypeCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_artifactTypeCheckboxActionPerformed
|
||||
artifactTypeScrollPane.setEnabled(artifactTypeCheckbox.isSelected());
|
||||
artifactList.setEnabled(artifactTypeCheckbox.isSelected());
|
||||
}//GEN-LAST:event_artifactTypeCheckboxActionPerformed
|
||||
|
||||
@Override
|
||||
void configurePanel(boolean selected, int[] indicesSelected) {
|
||||
artifactTypeCheckbox.setSelected(selected);
|
||||
if (artifactTypeCheckbox.isEnabled() && artifactTypeCheckbox.isSelected()) {
|
||||
artifactTypeScrollPane.setEnabled(true);
|
||||
artifactList.setEnabled(true);
|
||||
if (indicesSelected != null) {
|
||||
artifactList.setSelectedIndices(indicesSelected);
|
||||
}
|
||||
} else {
|
||||
artifactTypeScrollPane.setEnabled(false);
|
||||
artifactList.setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -102,7 +126,7 @@ class ArtifactTypeFilterPanel extends AbstractDiscoveryFilterPanel {
|
||||
|
||||
@Override
|
||||
JList<?> getList() {
|
||||
return null;
|
||||
return artifactList;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -110,13 +134,24 @@ class ArtifactTypeFilterPanel extends AbstractDiscoveryFilterPanel {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NbBundle.Messages({"ArtifactTypeFilterPanel.selectionNeeded.text=At least one Result type must be selected."})
|
||||
@Override
|
||||
String checkForError() {
|
||||
return "Domain search is not implemented.";
|
||||
if (artifactTypeCheckbox.isSelected() && artifactList.getSelectedValuesList().isEmpty()) {
|
||||
return Bundle.ArtifactTypeFilterPanel_selectionNeeded_text();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
AbstractFilter getFilter() {
|
||||
if (artifactTypeCheckbox.isSelected() && !artifactList.getSelectedValuesList().isEmpty()) {
|
||||
List<BlackboardArtifact.ARTIFACT_TYPE> artifactTypeList = new ArrayList<>();
|
||||
for (ArtifactTypeItem item : artifactList.getSelectedValuesList()) {
|
||||
artifactTypeList.add(item.getArtifactType());
|
||||
}
|
||||
return new ArtifactTypeFilter(artifactTypeList);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -153,8 +188,8 @@ class ArtifactTypeFilterPanel extends AbstractDiscoveryFilterPanel {
|
||||
}
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JList<ArtifactTypeItem> artifactList;
|
||||
private javax.swing.JCheckBox artifactTypeCheckbox;
|
||||
private javax.swing.JScrollPane artifactTypeScrollPane;
|
||||
private javax.swing.JList<ArtifactTypeItem> jList1;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
}
|
||||
|
@ -29,17 +29,15 @@ ResultsSplitPaneDivider.showButton.text=
|
||||
ResultsSplitPaneDivider.hideButton.text=
|
||||
ImageFilterPanel.imageFiltersSplitPane.toolTipText=
|
||||
ImageFilterPanel.imageFiltersSplitPane.border.title=Step 2: Filter which images to show
|
||||
ArtifactTypeFilterPanel.artifactTypeCheckbox.text=Artifact Type:
|
||||
ArtifactTypeFilterPanel.artifactTypeCheckbox.text=Result Type:
|
||||
InterestingItemsFilterPanel.interestingItemsCheckbox.text=Interesting Item:
|
||||
DocumentPanel.fileSizeLabel.toolTipText=
|
||||
DocumentPanel.isDeletedLabel.toolTipText=
|
||||
DomainFilterPanel.domainFiltersSplitPane.toolTipText=
|
||||
DomainFilterPanel.domainFiltersSplitPane.border.title=Step 2: Filter which domains to show
|
||||
SizeFilterPanel.sizeCheckbox.text=File Size:
|
||||
DateFilterPanel.dateFilterCheckbox.text=Date Filter:
|
||||
DateFilterPanel.endCheckBox.text=End:
|
||||
DateFilterPanel.startCheckBox.text=Start:
|
||||
DateFilterPanel.mostRecentButton.text=Only last:
|
||||
DateFilterPanel.daysLabel.text=days of activity
|
||||
ImageThumbnailPanel.isDeletedLabel.toolTipText=
|
||||
ResultsPanel.pageControlsLabel.text=Pages:
|
||||
@ -54,3 +52,5 @@ PastOccurrencesFilterPanel.pastOccurrencesCheckbox.text=Past Occurrences:
|
||||
DocumentFilterPanel.documentsFiltersSplitPane.border.title=Step 2: Filter which documents to show
|
||||
ObjectDetectedFilterPanel.text=Object Detected:
|
||||
DetailsPanel.instancesList.border.title=Instances
|
||||
DateFilterPanel.mostRecentRadioButton.text=Only last:
|
||||
DateFilterPanel.dateFilterCheckBox.text=Date Filter:
|
||||
|
@ -83,17 +83,15 @@ ResultsSplitPaneDivider.showButton.text=
|
||||
ResultsSplitPaneDivider.hideButton.text=
|
||||
ImageFilterPanel.imageFiltersSplitPane.toolTipText=
|
||||
ImageFilterPanel.imageFiltersSplitPane.border.title=Step 2: Filter which images to show
|
||||
ArtifactTypeFilterPanel.artifactTypeCheckbox.text=Artifact Type:
|
||||
ArtifactTypeFilterPanel.artifactTypeCheckbox.text=Result Type:
|
||||
InterestingItemsFilterPanel.interestingItemsCheckbox.text=Interesting Item:
|
||||
DocumentPanel.fileSizeLabel.toolTipText=
|
||||
DocumentPanel.isDeletedLabel.toolTipText=
|
||||
DomainFilterPanel.domainFiltersSplitPane.toolTipText=
|
||||
DomainFilterPanel.domainFiltersSplitPane.border.title=Step 2: Filter which domains to show
|
||||
SizeFilterPanel.sizeCheckbox.text=File Size:
|
||||
DateFilterPanel.dateFilterCheckbox.text=Date Filter:
|
||||
DateFilterPanel.endCheckBox.text=End:
|
||||
DateFilterPanel.startCheckBox.text=Start:
|
||||
DateFilterPanel.mostRecentButton.text=Only last:
|
||||
DateFilterPanel.daysLabel.text=days of activity
|
||||
ImageThumbnailPanel.isDeletedLabel.toolTipText=
|
||||
ResultsPanel.pageControlsLabel.text=Pages:
|
||||
@ -108,6 +106,8 @@ PastOccurrencesFilterPanel.pastOccurrencesCheckbox.text=Past Occurrences:
|
||||
DocumentFilterPanel.documentsFiltersSplitPane.border.title=Step 2: Filter which documents to show
|
||||
ObjectDetectedFilterPanel.text=Object Detected:
|
||||
DetailsPanel.instancesList.border.title=Instances
|
||||
DateFilterPanel.mostRecentRadioButton.text=Only last:
|
||||
DateFilterPanel.dateFilterCheckBox.text=Date Filter:
|
||||
VideoThumbnailPanel.bytes.text=bytes
|
||||
VideoThumbnailPanel.deleted.text=All instances of file are deleted.
|
||||
VideoThumbnailPanel.gigaBytes.text=GB
|
||||
|
@ -4,12 +4,15 @@
|
||||
<NonVisualComponents>
|
||||
<Component class="javax.swing.ButtonGroup" name="buttonGroup1">
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="dateFilterCheckbox">
|
||||
<Component class="javax.swing.JCheckBox" name="dateFilterCheckBox">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/discovery/ui/Bundle.properties" key="DateFilterPanel.dateFilterCheckbox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/discovery/ui/Bundle.properties" key="DateFilterPanel.dateFilterCheckBox.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="dateFilterCheckBoxActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
</NonVisualComponents>
|
||||
<AuxValues>
|
||||
@ -51,7 +54,7 @@
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="mostRecentButton" min="-2" pref="90" max="-2" attributes="0"/>
|
||||
<Component id="mostRecentRadioButton" min="-2" pref="90" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="daysSpinner" min="-2" pref="80" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
@ -76,7 +79,7 @@
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="mostRecentButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="mostRecentRadioButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="daysSpinner" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="daysLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
@ -100,10 +103,16 @@
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JSpinner" name="daysSpinner">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.SpinnerModel" editor="org.netbeans.modules.form.editors2.SpinnerModelEditor">
|
||||
<SpinnerModel initial="1" minimum="1" numberType="java.lang.Integer" stepSize="1" type="number"/>
|
||||
</Property>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[75, 26]"/>
|
||||
</Property>
|
||||
<Property name="value" type="java.lang.Object" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||
<Connection code="7" type="code"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new javax.swing.JSpinner(numberModel)"/>
|
||||
@ -117,18 +126,19 @@
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JRadioButton" name="mostRecentButton">
|
||||
<Component class="javax.swing.JRadioButton" name="mostRecentRadioButton">
|
||||
<Properties>
|
||||
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
|
||||
<ComponentRef name="buttonGroup1"/>
|
||||
</Property>
|
||||
<Property name="selected" type="boolean" value="true"/>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/discovery/ui/Bundle.properties" key="DateFilterPanel.mostRecentButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/discovery/ui/Bundle.properties" key="DateFilterPanel.mostRecentRadioButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="mostRecentButtonActionPerformed"/>
|
||||
<EventHandler event="stateChanged" listener="javax.swing.event.ChangeListener" parameters="javax.swing.event.ChangeEvent" handler="mostRecentRadioButtonStateChanged"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="startCheckBox">
|
||||
@ -144,6 +154,9 @@
|
||||
</Component>
|
||||
<Component class="com.github.lgooddatepicker.components.DatePicker" name="startDatePicker">
|
||||
<Properties>
|
||||
<Property name="date" type="java.time.LocalDate" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||
<Connection code="LocalDate.now()" type="code"/>
|
||||
</Property>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[60, 22]"/>
|
||||
@ -155,6 +168,9 @@
|
||||
</Component>
|
||||
<Component class="com.github.lgooddatepicker.components.DatePicker" name="endDatePicker">
|
||||
<Properties>
|
||||
<Property name="date" type="java.time.LocalDate" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||
<Connection code="LocalDate.now()" type="code"/>
|
||||
</Property>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[60, 22]"/>
|
||||
@ -183,7 +199,7 @@
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="rangeRadioButtonActionPerformed"/>
|
||||
<EventHandler event="stateChanged" listener="javax.swing.event.ChangeListener" parameters="javax.swing.event.ChangeEvent" handler="rangeRadioButtonStateChanged"/>
|
||||
</Events>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
|
@ -18,13 +18,19 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.discovery.ui;
|
||||
|
||||
import java.awt.event.ActionListener;
|
||||
import java.time.LocalDate;
|
||||
import java.time.Period;
|
||||
import java.time.ZoneId;
|
||||
import org.sleuthkit.autopsy.discovery.search.AbstractFilter;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.SpinnerNumberModel;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.communications.Utils;
|
||||
import org.sleuthkit.autopsy.discovery.search.SearchFiltering;
|
||||
|
||||
/**
|
||||
* Filter panel for allowing the user to filter on date.
|
||||
@ -33,6 +39,7 @@ class DateFilterPanel extends AbstractDiscoveryFilterPanel {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final SpinnerNumberModel numberModel;
|
||||
private static final long SECS_PER_DAY = 86400;
|
||||
|
||||
/**
|
||||
* Creates new form DateFilterPanel.
|
||||
@ -56,31 +63,39 @@ class DateFilterPanel extends AbstractDiscoveryFilterPanel {
|
||||
private void initComponents() {
|
||||
|
||||
buttonGroup1 = new javax.swing.ButtonGroup();
|
||||
dateFilterCheckbox = new javax.swing.JCheckBox();
|
||||
dateFilterCheckBox = new javax.swing.JCheckBox();
|
||||
jPanel1 = new javax.swing.JPanel();
|
||||
daysSpinner = new javax.swing.JSpinner(numberModel);
|
||||
daysLabel = new javax.swing.JLabel();
|
||||
mostRecentButton = new javax.swing.JRadioButton();
|
||||
mostRecentRadioButton = new javax.swing.JRadioButton();
|
||||
startCheckBox = new javax.swing.JCheckBox();
|
||||
startDatePicker = new com.github.lgooddatepicker.components.DatePicker();
|
||||
endDatePicker = new com.github.lgooddatepicker.components.DatePicker();
|
||||
endCheckBox = new javax.swing.JCheckBox();
|
||||
rangeRadioButton = new javax.swing.JRadioButton();
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(dateFilterCheckbox, org.openide.util.NbBundle.getMessage(DateFilterPanel.class, "DateFilterPanel.dateFilterCheckbox.text")); // NOI18N
|
||||
org.openide.awt.Mnemonics.setLocalizedText(dateFilterCheckBox, org.openide.util.NbBundle.getMessage(DateFilterPanel.class, "DateFilterPanel.dateFilterCheckBox.text")); // NOI18N
|
||||
dateFilterCheckBox.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
dateFilterCheckBoxActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
daysSpinner.setModel(new javax.swing.SpinnerNumberModel(1, 1, null, 1));
|
||||
daysSpinner.setEnabled(false);
|
||||
daysSpinner.setPreferredSize(new java.awt.Dimension(75, 26));
|
||||
daysSpinner.setValue(7);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(daysLabel, org.openide.util.NbBundle.getMessage(DateFilterPanel.class, "DateFilterPanel.daysLabel.text")); // NOI18N
|
||||
daysLabel.setEnabled(false);
|
||||
|
||||
buttonGroup1.add(mostRecentButton);
|
||||
org.openide.awt.Mnemonics.setLocalizedText(mostRecentButton, org.openide.util.NbBundle.getMessage(DateFilterPanel.class, "DateFilterPanel.mostRecentButton.text")); // NOI18N
|
||||
mostRecentButton.setEnabled(false);
|
||||
mostRecentButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
mostRecentButtonActionPerformed(evt);
|
||||
buttonGroup1.add(mostRecentRadioButton);
|
||||
mostRecentRadioButton.setSelected(true);
|
||||
org.openide.awt.Mnemonics.setLocalizedText(mostRecentRadioButton, org.openide.util.NbBundle.getMessage(DateFilterPanel.class, "DateFilterPanel.mostRecentRadioButton.text")); // NOI18N
|
||||
mostRecentRadioButton.setEnabled(false);
|
||||
mostRecentRadioButton.addChangeListener(new javax.swing.event.ChangeListener() {
|
||||
public void stateChanged(javax.swing.event.ChangeEvent evt) {
|
||||
mostRecentRadioButtonStateChanged(evt);
|
||||
}
|
||||
});
|
||||
|
||||
@ -92,10 +107,12 @@ class DateFilterPanel extends AbstractDiscoveryFilterPanel {
|
||||
}
|
||||
});
|
||||
|
||||
startDatePicker.setDate(LocalDate.now());
|
||||
startDatePicker.setEnabled(false);
|
||||
startDatePicker.setMinimumSize(new java.awt.Dimension(60, 22));
|
||||
startDatePicker.setPreferredSize(new java.awt.Dimension(110, 22));
|
||||
|
||||
endDatePicker.setDate(LocalDate.now());
|
||||
endDatePicker.setEnabled(false);
|
||||
endDatePicker.setMinimumSize(new java.awt.Dimension(60, 22));
|
||||
endDatePicker.setPreferredSize(new java.awt.Dimension(110, 22));
|
||||
@ -110,9 +127,9 @@ class DateFilterPanel extends AbstractDiscoveryFilterPanel {
|
||||
|
||||
buttonGroup1.add(rangeRadioButton);
|
||||
rangeRadioButton.setEnabled(false);
|
||||
rangeRadioButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
rangeRadioButtonActionPerformed(evt);
|
||||
rangeRadioButton.addChangeListener(new javax.swing.event.ChangeListener() {
|
||||
public void stateChanged(javax.swing.event.ChangeEvent evt) {
|
||||
rangeRadioButtonStateChanged(evt);
|
||||
}
|
||||
});
|
||||
|
||||
@ -121,7 +138,7 @@ class DateFilterPanel extends AbstractDiscoveryFilterPanel {
|
||||
jPanel1Layout.setHorizontalGroup(
|
||||
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addComponent(mostRecentButton, javax.swing.GroupLayout.PREFERRED_SIZE, 90, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(mostRecentRadioButton, javax.swing.GroupLayout.PREFERRED_SIZE, 90, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(daysSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
@ -141,7 +158,7 @@ class DateFilterPanel extends AbstractDiscoveryFilterPanel {
|
||||
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
|
||||
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(mostRecentButton)
|
||||
.addComponent(mostRecentRadioButton)
|
||||
.addComponent(daysSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(daysLabel))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
@ -176,31 +193,48 @@ class DateFilterPanel extends AbstractDiscoveryFilterPanel {
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
private void startCheckBoxStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_startCheckBoxStateChanged
|
||||
startDatePicker.setEnabled(startCheckBox.isSelected());
|
||||
// validateFilters(); //TODO JIRA-6714 when search will begin doing something
|
||||
startDatePicker.setEnabled(startCheckBox.isEnabled() && startCheckBox.isSelected());
|
||||
}//GEN-LAST:event_startCheckBoxStateChanged
|
||||
|
||||
private void endCheckBoxStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_endCheckBoxStateChanged
|
||||
endDatePicker.setEnabled(endCheckBox.isSelected());
|
||||
// validateFilters(); //TODO JIRA-6714 when search will begin doing something
|
||||
endDatePicker.setEnabled(endCheckBox.isEnabled() && endCheckBox.isSelected());
|
||||
}//GEN-LAST:event_endCheckBoxStateChanged
|
||||
|
||||
private void mostRecentButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mostRecentButtonActionPerformed
|
||||
private void dateFilterCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_dateFilterCheckBoxActionPerformed
|
||||
rangeRadioButton.setEnabled(dateFilterCheckBox.isSelected());
|
||||
mostRecentRadioButton.setEnabled(dateFilterCheckBox.isSelected());
|
||||
rangeRadioButton.firePropertyChange("DateFilterChange", !rangeRadioButton.isEnabled(), rangeRadioButton.isEnabled());
|
||||
mostRecentRadioButton.firePropertyChange("DateFilterChange", !mostRecentRadioButton.isEnabled(), mostRecentRadioButton.isEnabled());
|
||||
}//GEN-LAST:event_dateFilterCheckBoxActionPerformed
|
||||
|
||||
}//GEN-LAST:event_mostRecentButtonActionPerformed
|
||||
private void mostRecentRadioButtonStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_mostRecentRadioButtonStateChanged
|
||||
daysSpinner.setEnabled(mostRecentRadioButton.isSelected());
|
||||
daysLabel.setEnabled(mostRecentRadioButton.isSelected());
|
||||
}//GEN-LAST:event_mostRecentRadioButtonStateChanged
|
||||
|
||||
private void rangeRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_rangeRadioButtonActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_rangeRadioButtonActionPerformed
|
||||
private void rangeRadioButtonStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_rangeRadioButtonStateChanged
|
||||
startCheckBox.setEnabled(rangeRadioButton.isEnabled() && rangeRadioButton.isSelected());
|
||||
endCheckBox.setEnabled(rangeRadioButton.isEnabled() && rangeRadioButton.isSelected());
|
||||
startCheckBox.firePropertyChange("StartButtonChange", true, false);
|
||||
endCheckBox.firePropertyChange("EndButtonChange", true, false);
|
||||
}//GEN-LAST:event_rangeRadioButtonStateChanged
|
||||
|
||||
@Override
|
||||
void configurePanel(boolean selected, int[] indicesSelected) {
|
||||
dateFilterCheckbox.setSelected(selected);
|
||||
dateFilterCheckBox.setSelected(selected);
|
||||
if (dateFilterCheckBox.isEnabled() && dateFilterCheckBox.isSelected()) {
|
||||
mostRecentRadioButton.setEnabled(true);
|
||||
rangeRadioButton.setEnabled(true);
|
||||
mostRecentRadioButton.setSelected(true);
|
||||
} else {
|
||||
mostRecentRadioButton.setEnabled(false);
|
||||
rangeRadioButton.setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
JCheckBox getCheckbox() {
|
||||
return dateFilterCheckbox;
|
||||
return dateFilterCheckBox;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -213,26 +247,81 @@ class DateFilterPanel extends AbstractDiscoveryFilterPanel {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
void addListeners(ActionListener actionListener, ListSelectionListener listListener) {
|
||||
dateFilterCheckBox.addActionListener(actionListener);
|
||||
startCheckBox.addActionListener(actionListener);
|
||||
endCheckBox.addActionListener(actionListener);
|
||||
rangeRadioButton.addActionListener(actionListener);
|
||||
mostRecentRadioButton.addActionListener(actionListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
void removeListeners() {
|
||||
for (ActionListener listener : dateFilterCheckBox.getActionListeners()) {
|
||||
dateFilterCheckBox.removeActionListener(listener);
|
||||
}
|
||||
for (ActionListener listener : rangeRadioButton.getActionListeners()) {
|
||||
rangeRadioButton.removeActionListener(listener);
|
||||
}
|
||||
for (ActionListener listener : mostRecentRadioButton.getActionListeners()) {
|
||||
mostRecentRadioButton.removeActionListener(listener);
|
||||
}
|
||||
for (ActionListener listener : rangeRadioButton.getActionListeners()) {
|
||||
rangeRadioButton.removeActionListener(listener);
|
||||
}
|
||||
for (ActionListener listener : startCheckBox.getActionListeners()) {
|
||||
startCheckBox.removeActionListener(listener);
|
||||
}
|
||||
for (ActionListener listener : endCheckBox.getActionListeners()) {
|
||||
endCheckBox.removeActionListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
@NbBundle.Messages({"DateFilterPanel.invalidRange.text=Range or Only Last must be selected",
|
||||
"DateFilterPanel.startOrEndNeeded.text=A start or end date must be specified to use the range filter"})
|
||||
@Override
|
||||
String checkForError() {
|
||||
return "Domain search is not implemented.";
|
||||
if (dateFilterCheckBox.isSelected()) {
|
||||
if (!(rangeRadioButton.isSelected() || mostRecentRadioButton.isSelected())) {
|
||||
return Bundle.DateFilterPanel_invalidRange_text();
|
||||
} else if (rangeRadioButton.isSelected() && !(startCheckBox.isSelected() || endCheckBox.isSelected())) {
|
||||
return Bundle.DateFilterPanel_startOrEndNeeded_text();
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
AbstractFilter getFilter() {
|
||||
if (dateFilterCheckBox.isSelected()) {
|
||||
LocalDate startDate = LocalDate.MIN;
|
||||
LocalDate endDate = LocalDate.MAX;
|
||||
ZoneId zone = Utils.getUserPreferredZoneId();
|
||||
if (rangeRadioButton.isSelected() && (startCheckBox.isSelected() || endCheckBox.isSelected())) {
|
||||
if (startCheckBox.isSelected() && startDatePicker.getDate() != null) {
|
||||
startDate = startDatePicker.getDate();
|
||||
}
|
||||
if (endCheckBox.isSelected() && endDatePicker.getDate() != null) {
|
||||
endDate = endDatePicker.getDate();
|
||||
}
|
||||
} else if (dateFilterCheckBox.isSelected() && mostRecentRadioButton.isSelected()) {
|
||||
endDate = LocalDate.now();
|
||||
startDate = LocalDate.now().minus(Period.ofDays((Integer) daysSpinner.getValue()));
|
||||
}
|
||||
return new SearchFiltering.ArtifactDateRangeFilter(startDate.atStartOfDay(zone).toEpochSecond(), endDate.atStartOfDay(zone).toEpochSecond() + SECS_PER_DAY);//to insure end date is inclusive
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.ButtonGroup buttonGroup1;
|
||||
private javax.swing.JCheckBox dateFilterCheckbox;
|
||||
private javax.swing.JCheckBox dateFilterCheckBox;
|
||||
private javax.swing.JLabel daysLabel;
|
||||
private javax.swing.JSpinner daysSpinner;
|
||||
private javax.swing.JCheckBox endCheckBox;
|
||||
private com.github.lgooddatepicker.components.DatePicker endDatePicker;
|
||||
private javax.swing.JPanel jPanel1;
|
||||
private javax.swing.JRadioButton mostRecentButton;
|
||||
private javax.swing.JRadioButton mostRecentRadioButton;
|
||||
private javax.swing.JRadioButton rangeRadioButton;
|
||||
private javax.swing.JCheckBox startCheckBox;
|
||||
private com.github.lgooddatepicker.components.DatePicker startDatePicker;
|
||||
|
@ -21,6 +21,8 @@ package org.sleuthkit.autopsy.discovery.ui;
|
||||
import org.sleuthkit.autopsy.discovery.search.AbstractFilter;
|
||||
import static java.awt.BorderLayout.CENTER;
|
||||
import java.awt.Color;
|
||||
import java.awt.event.ItemEvent;
|
||||
import java.awt.event.ItemListener;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.ArrayList;
|
||||
@ -29,6 +31,7 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.SwingUtilities;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.openide.windows.WindowManager;
|
||||
@ -41,12 +44,9 @@ import org.sleuthkit.autopsy.discovery.search.DiscoveryAttributes;
|
||||
import org.sleuthkit.autopsy.discovery.search.DiscoveryEventUtils;
|
||||
import org.sleuthkit.autopsy.discovery.search.Group;
|
||||
import org.sleuthkit.autopsy.discovery.search.Group.GroupSortingAlgorithm;
|
||||
import static org.sleuthkit.autopsy.discovery.search.Group.GroupSortingAlgorithm.BY_GROUP_SIZE;
|
||||
import org.sleuthkit.autopsy.discovery.search.DiscoveryAttributes.GroupingAttributeType;
|
||||
import static org.sleuthkit.autopsy.discovery.search.DiscoveryAttributes.GroupingAttributeType.PARENT_PATH;
|
||||
import org.sleuthkit.autopsy.discovery.search.ResultsSorter;
|
||||
import org.sleuthkit.autopsy.discovery.search.ResultsSorter.SortingMethod;
|
||||
import static org.sleuthkit.autopsy.discovery.search.ResultsSorter.SortingMethod.BY_FILE_NAME;
|
||||
import org.sleuthkit.autopsy.discovery.search.SearchData;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
|
||||
@ -111,12 +111,41 @@ final class DiscoveryDialog extends javax.swing.JDialog {
|
||||
}
|
||||
}
|
||||
};
|
||||
for (GroupSortingAlgorithm groupSortAlgorithm : GroupSortingAlgorithm.values()) {
|
||||
groupSortingComboBox.addItem(groupSortAlgorithm);
|
||||
}
|
||||
updateSearchSettings();
|
||||
groupByCombobox.addItemListener(new ItemListener() {
|
||||
@Override
|
||||
public void itemStateChanged(ItemEvent event) {
|
||||
if (event.getStateChange() == ItemEvent.SELECTED) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
getSelectedFilterPanel().setLastGroupingAttributeType(groupByCombobox.getItemAt(groupByCombobox.getSelectedIndex()));
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
orderByCombobox.addItemListener(new ItemListener() {
|
||||
@Override
|
||||
public void itemStateChanged(ItemEvent event) {
|
||||
if (event.getStateChange() == ItemEvent.SELECTED) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
getSelectedFilterPanel().setLastSortingMethod(orderByCombobox.getItemAt(orderByCombobox.getSelectedIndex()));
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
groupSortingComboBox.addItemListener(new ItemListener() {
|
||||
@Override
|
||||
public void itemStateChanged(ItemEvent event) {
|
||||
if (event.getStateChange() == ItemEvent.SELECTED) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
getSelectedFilterPanel().setLastGroupSortingAlg(groupSortingComboBox.getItemAt(groupSortingComboBox.getSelectedIndex()));
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, this.new CasePropertyChangeListener());
|
||||
IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, this.new ModuleChangeListener());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -140,7 +169,6 @@ final class DiscoveryDialog extends javax.swing.JDialog {
|
||||
add(imageFilterPanel, CENTER);
|
||||
imageFilterPanel.addPropertyChangeListener(listener);
|
||||
updateComboBoxes();
|
||||
groupSortingComboBox.setSelectedItem(BY_GROUP_SIZE);
|
||||
pack();
|
||||
repaint();
|
||||
}
|
||||
@ -167,20 +195,54 @@ final class DiscoveryDialog extends javax.swing.JDialog {
|
||||
* Private helper method to perform update of comboboxes update.
|
||||
*/
|
||||
private void updateComboBoxes() {
|
||||
groupByCombobox.removeAllItems();
|
||||
// Set up the grouping attributes
|
||||
for (DiscoveryAttributes.GroupingAttributeType groupingType : DiscoveryAttributes.GroupingAttributeType.getOptionsForGrouping()) {
|
||||
List<GroupingAttributeType> groupingAttrs = new ArrayList<>();
|
||||
List<SortingMethod> sortingMethods = new ArrayList<>();
|
||||
groupByCombobox.removeAllItems();
|
||||
if (type == SearchData.Type.DOMAIN) {
|
||||
groupingAttrs.addAll(GroupingAttributeType.getOptionsForGroupingForDomains());
|
||||
sortingMethods.addAll(SortingMethod.getOptionsForOrderingDomains());
|
||||
} else {
|
||||
groupingAttrs.addAll(GroupingAttributeType.getOptionsForGroupingForFiles());
|
||||
sortingMethods.addAll(SortingMethod.getOptionsForOrderingFiles());
|
||||
}
|
||||
for (GroupingAttributeType groupingType : groupingAttrs) {
|
||||
addTypeToGroupByComboBox(groupingType);
|
||||
}
|
||||
groupByCombobox.setSelectedItem(PARENT_PATH);
|
||||
groupByCombobox.setSelectedItem(getSelectedFilterPanel().getLastGroupingAttributeType());
|
||||
orderByCombobox.removeAllItems();
|
||||
// Set up the file order list
|
||||
for (ResultsSorter.SortingMethod method : ResultsSorter.SortingMethod.getOptionsForOrdering()) {
|
||||
for (SortingMethod method : sortingMethods) {
|
||||
if (method != SortingMethod.BY_FREQUENCY || CentralRepository.isEnabled()) {
|
||||
orderByCombobox.addItem(method);
|
||||
}
|
||||
}
|
||||
orderByCombobox.setSelectedItem(BY_FILE_NAME);
|
||||
orderByCombobox.setSelectedItem(getSelectedFilterPanel().getLastSortingMethod());
|
||||
groupSortingComboBox.removeAllItems();
|
||||
for (GroupSortingAlgorithm groupSortAlgorithm : GroupSortingAlgorithm.values()) {
|
||||
groupSortingComboBox.addItem(groupSortAlgorithm);
|
||||
}
|
||||
groupSortingComboBox.setSelectedItem(getSelectedFilterPanel().getLastGroupSortingAlg());
|
||||
}
|
||||
|
||||
/**
|
||||
* Private helper method to get the correct panel for the selected type.
|
||||
*
|
||||
* @return The panel that corresponds to the currently selected type.
|
||||
*/
|
||||
private AbstractFiltersPanel getSelectedFilterPanel() {
|
||||
switch (type) {
|
||||
case IMAGE:
|
||||
return imageFilterPanel;
|
||||
case VIDEO:
|
||||
return videoFilterPanel;
|
||||
case DOCUMENT:
|
||||
return documentFilterPanel;
|
||||
case DOMAIN:
|
||||
return domainFilterPanel;
|
||||
default:
|
||||
return imageFilterPanel;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -221,29 +283,9 @@ final class DiscoveryDialog extends javax.swing.JDialog {
|
||||
* Validate the filter settings for File type filters.
|
||||
*/
|
||||
synchronized void validateDialog() {
|
||||
switch (type) {
|
||||
case IMAGE:
|
||||
if (imageFilterPanel != null) {
|
||||
imageFilterPanel.validateFields();
|
||||
}
|
||||
break;
|
||||
case VIDEO:
|
||||
if (videoFilterPanel != null) {
|
||||
videoFilterPanel.validateFields();
|
||||
}
|
||||
break;
|
||||
case DOCUMENT:
|
||||
if (documentFilterPanel != null) {
|
||||
documentFilterPanel.validateFields();
|
||||
}
|
||||
break;
|
||||
case DOMAIN:
|
||||
if (domainFilterPanel != null) {
|
||||
domainFilterPanel.validateFields();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
AbstractFiltersPanel panel = getSelectedFilterPanel();
|
||||
if (panel != null) {
|
||||
panel.validateFields();
|
||||
}
|
||||
}
|
||||
|
||||
@ -469,6 +511,7 @@ final class DiscoveryDialog extends javax.swing.JDialog {
|
||||
imagesButton.setForeground(Color.BLACK);
|
||||
type = SearchData.Type.IMAGE;
|
||||
imageFilterPanel.addPropertyChangeListener(listener);
|
||||
updateComboBoxes();
|
||||
validateDialog();
|
||||
pack();
|
||||
repaint();
|
||||
@ -484,6 +527,7 @@ final class DiscoveryDialog extends javax.swing.JDialog {
|
||||
videosButton.setForeground(Color.BLACK);
|
||||
videoFilterPanel.addPropertyChangeListener(listener);
|
||||
type = SearchData.Type.VIDEO;
|
||||
updateComboBoxes();
|
||||
validateDialog();
|
||||
pack();
|
||||
repaint();
|
||||
@ -499,6 +543,7 @@ final class DiscoveryDialog extends javax.swing.JDialog {
|
||||
documentsButton.setForeground(Color.BLACK);
|
||||
type = SearchData.Type.DOCUMENT;
|
||||
documentFilterPanel.addPropertyChangeListener(listener);
|
||||
updateComboBoxes();
|
||||
validateDialog();
|
||||
pack();
|
||||
repaint();
|
||||
@ -512,6 +557,10 @@ final class DiscoveryDialog extends javax.swing.JDialog {
|
||||
remove(imageFilterPanel);
|
||||
imageFilterPanel.removePropertyChangeListener(listener);
|
||||
}
|
||||
if (domainFilterPanel != null) {
|
||||
remove(domainFilterPanel);
|
||||
domainFilterPanel.removePropertyChangeListener(listener);
|
||||
}
|
||||
if (documentFilterPanel != null) {
|
||||
remove(documentFilterPanel);
|
||||
documentFilterPanel.removePropertyChangeListener(listener);
|
||||
@ -520,10 +569,6 @@ final class DiscoveryDialog extends javax.swing.JDialog {
|
||||
remove(videoFilterPanel);
|
||||
videoFilterPanel.removePropertyChangeListener(listener);
|
||||
}
|
||||
if (domainFilterPanel != null) {
|
||||
remove(domainFilterPanel);
|
||||
domainFilterPanel.removePropertyChangeListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
private void searchButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_searchButtonActionPerformed
|
||||
@ -584,7 +629,8 @@ final class DiscoveryDialog extends javax.swing.JDialog {
|
||||
domainsButton.setBackground(SELECTED_COLOR);
|
||||
domainsButton.setForeground(Color.BLACK);
|
||||
type = SearchData.Type.DOMAIN;
|
||||
documentFilterPanel.addPropertyChangeListener(listener);
|
||||
domainFilterPanel.addPropertyChangeListener(listener);
|
||||
updateComboBoxes();
|
||||
validateDialog();
|
||||
pack();
|
||||
repaint();
|
||||
|
@ -19,6 +19,8 @@
|
||||
package org.sleuthkit.autopsy.discovery.ui;
|
||||
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
|
||||
import org.sleuthkit.autopsy.discovery.search.DiscoveryAttributes;
|
||||
import org.sleuthkit.autopsy.discovery.search.ResultsSorter;
|
||||
import org.sleuthkit.autopsy.discovery.search.SearchData;
|
||||
|
||||
/**
|
||||
@ -44,6 +46,8 @@ public class DomainFilterPanel extends AbstractFiltersPanel {
|
||||
}
|
||||
addFilter(new PastOccurrencesFilterPanel(TYPE), true, pastOccurrencesIndices, 0);
|
||||
addPanelsToScrollPane(domainFiltersSplitPane);
|
||||
setLastGroupingAttributeType(DiscoveryAttributes.GroupingAttributeType.MOST_RECENT_DATE);
|
||||
setLastSortingMethod(ResultsSorter.SortingMethod.BY_DOMAIN_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user