19 package org.sleuthkit.autopsy.discovery.search;
21 import java.sql.ResultSet;
22 import java.sql.SQLException;
23 import java.util.ArrayList;
24 import java.util.Arrays;
25 import java.util.HashMap;
26 import java.util.HashSet;
27 import java.util.Iterator;
28 import java.util.List;
31 import java.util.logging.Level;
32 import org.openide.util.NbBundle;
47 import java.util.StringJoiner;
49 import static org.
sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CATEGORIZATION;
129 static class DataSourceAttribute
extends AttributeType {
132 public DiscoveryKeyUtils.GroupKey getGroupKey(Result result) {
133 return new DiscoveryKeyUtils.DataSourceGroupKey(result);
140 static class FileTypeAttribute
extends AttributeType {
143 public DiscoveryKeyUtils.GroupKey getGroupKey(Result file) {
144 return new DiscoveryKeyUtils.FileTypeGroupKey(file);
152 static class DomainCategoryAttribute
extends AttributeType {
155 public DiscoveryKeyUtils.GroupKey getGroupKey(Result result) {
156 return new DiscoveryKeyUtils.DomainCategoryGroupKey(result);
160 public void addAttributeToResults(List<Result> results, SleuthkitCase caseDb,
161 CentralRepository centralRepoDb, SearchContext context)
throws DiscoveryException, SearchCancellationException {
163 Map<String, Set<String>> domainsToCategories = getDomainsWithWebCategories(caseDb, context);
164 for (Result result : results) {
165 if (context.searchIsCancelled()) {
166 throw new SearchCancellationException(
"The search was cancelled while Domain Category Attribute was being added.");
168 if (result instanceof ResultDomain) {
169 ResultDomain domain = (ResultDomain) result;
170 domain.addWebCategories(domainsToCategories.get(domain.getDomain()));
173 }
catch (TskCoreException | InterruptedException ex) {
174 throw new DiscoveryException(
"Error fetching TSK_WEB_CATEGORY artifacts from the database", ex);
195 private Map<String, Set<String>> getDomainsWithWebCategories(SleuthkitCase caseDb, SearchContext context)
throws TskCoreException, InterruptedException, SearchCancellationException {
196 Map<String, Set<String>> domainToCategory =
new HashMap<>();
198 for (BlackboardArtifact artifact : caseDb.getBlackboardArtifacts(TSK_WEB_CATEGORIZATION)) {
199 if (Thread.currentThread().isInterrupted()) {
200 throw new InterruptedException();
202 if (context.searchIsCancelled()) {
203 throw new SearchCancellationException(
"Search was cancelled while getting domains for artifact type: " + artifact.getDisplayName());
205 BlackboardAttribute webCategory = artifact.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME));
206 BlackboardAttribute domain = artifact.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN));
207 if (webCategory != null && domain != null) {
208 String domainDisplayName = domain.getValueString().trim().toLowerCase();
209 if (!domainToCategory.containsKey(domainDisplayName)) {
210 domainToCategory.put(domainDisplayName,
new HashSet<>());
212 domainToCategory.get(domainDisplayName).add(webCategory.getValueString());
215 return domainToCategory;
222 static class KeywordListAttribute
extends AttributeType {
225 public DiscoveryKeyUtils.GroupKey getGroupKey(Result file) {
226 return new DiscoveryKeyUtils.KeywordListGroupKey((ResultFile) file);
230 public void addAttributeToResults(List<Result> results, SleuthkitCase caseDb,
231 CentralRepository centralRepoDb, SearchContext context)
throws DiscoveryException, SearchCancellationException {
235 String selectQuery =
createSetNameClause(results, BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID(),
236 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID());
237 SetKeywordListNamesCallback callback =
new SetKeywordListNamesCallback(results);
238 if (context.searchIsCancelled()) {
239 throw new SearchCancellationException(
"The search was cancelled while Keyword List Attribute was being added.");
242 caseDb.getCaseDbAccessManager().select(selectQuery, callback);
243 }
catch (TskCoreException ex) {
244 throw new DiscoveryException(
"Error looking up keyword list attributes", ex);
255 List<Result> resultFiles;
263 this.resultFiles = resultFiles;
270 Map<Long, ResultFile> tempMap =
new HashMap<>();
271 for (
Result result : resultFiles) {
281 Long objId = rs.getLong(
"object_id");
282 String keywordListName = rs.getString(
"set_name");
286 }
catch (SQLException ex) {
287 logger.log(Level.SEVERE,
"Unable to get object_id or set_name from result set", ex);
290 }
catch (SQLException ex) {
291 logger.log(Level.SEVERE,
"Failed to get keyword list names", ex);
319 final Map<String, List<ResultDomain>> resultDomainTable =
new HashMap<>();
322 final String domainValue = domainInstance.getDomain();
324 final List<ResultDomain> bucket = resultDomainTable.getOrDefault(normalizedDomain,
new ArrayList<>());
325 bucket.add(domainInstance);
326 resultDomainTable.put(normalizedDomain, bucket);
327 if (context.searchIsCancelled()) {
331 logger.log(Level.INFO, String.format(
"Domain [%s] failed normalization, skipping...", domainInstance.getDomain()));
334 return resultDomainTable;
343 StringJoiner joiner =
new StringJoiner(
", ");
344 for (String value : values) {
345 joiner.add(
"'" + value +
"'");
347 return joiner.toString();
353 static class PreviouslyNotableAttribute
extends AttributeType {
355 static final int DOMAIN_BATCH_SIZE = 500;
363 public void addAttributeToResults(List<Result> results, SleuthkitCase caseDb,
364 CentralRepository centralRepoDb, SearchContext context)
throws DiscoveryException, SearchCancellationException {
366 if (centralRepoDb != null) {
367 processFilesWithCr(results, centralRepoDb, context);
385 private void processFilesWithCr(List<Result> results, CentralRepository centralRepo, SearchContext context)
throws DiscoveryException, SearchCancellationException {
387 List<ResultDomain> domainsBatch =
new ArrayList<>();
388 for (Result result : results) {
389 if (context.searchIsCancelled()) {
390 throw new SearchCancellationException(
"The search was cancelled while Previously Notable attribute was being calculated with the CR.");
393 domainsBatch.add((ResultDomain) result);
394 if (domainsBatch.size() == DOMAIN_BATCH_SIZE) {
395 queryPreviouslyNotable(domainsBatch, centralRepo, context);
396 domainsBatch.clear();
401 queryPreviouslyNotable(domainsBatch, centralRepo, context);
419 private void queryPreviouslyNotable(List<ResultDomain> domainsBatch, CentralRepository centralRepo, SearchContext context)
throws DiscoveryException, SearchCancellationException {
420 if (domainsBatch.isEmpty()) {
425 final CorrelationAttributeInstance.Type attributeType = centralRepo.getCorrelationTypeById(CorrelationAttributeInstance.DOMAIN_TYPE_ID);
426 final Map<String, List<ResultDomain>> resultDomainTable =
organizeByValue(domainsBatch, attributeType, context);
427 final String values =
createCSV(resultDomainTable.keySet());
428 if (context.searchIsCancelled()) {
429 throw new SearchCancellationException(
"Search was cancelled while checking for previously notable domains.");
431 final String tableName = CentralRepoDbUtil.correlationTypeToInstanceTableName(attributeType);
432 final String domainFrequencyQuery =
" value AS domain_name "
433 +
"FROM " + tableName +
" "
434 +
"WHERE value IN (" + values +
") "
435 +
"AND known_status = " + TskData.FileKnown.BAD.getFileKnownValue();
437 final DomainPreviouslyNotableCallback previouslyNotableCallback =
new DomainPreviouslyNotableCallback(resultDomainTable);
438 centralRepo.processSelectClause(domainFrequencyQuery, previouslyNotableCallback);
440 if (previouslyNotableCallback.getCause() != null) {
441 throw previouslyNotableCallback.getCause();
443 }
catch (CentralRepoException | SQLException ex) {
444 throw new DiscoveryException(
"Fatal exception encountered querying the CR.", ex);
460 while (resultSet.next()) {
461 String domain = resultSet.getString(
"domain_name");
462 List<ResultDomain> domainInstances = domainLookup.get(domain);
464 domainInstance.markAsPreviouslyNotableInCR();
467 }
catch (SQLException ex) {
475 SQLException getCause() {
484 static class FrequencyAttribute
extends AttributeType {
486 static final int BATCH_SIZE = 50;
488 static final int DOMAIN_BATCH_SIZE = 500;
491 public DiscoveryKeyUtils.GroupKey getGroupKey(Result file) {
492 return new DiscoveryKeyUtils.FrequencyGroupKey(file);
496 public void addAttributeToResults(List<Result> results, SleuthkitCase caseDb,
497 CentralRepository centralRepoDb, SearchContext context)
throws DiscoveryException, SearchCancellationException {
498 if (centralRepoDb == null) {
499 for (Result result : results) {
505 processResultFilesForCR(results, centralRepoDb, context);
524 private void processResultFilesForCR(List<Result> results,
525 CentralRepository centralRepoDb, SearchContext context)
throws DiscoveryException, SearchCancellationException {
526 List<ResultFile> currentFiles =
new ArrayList<>();
527 Set<String> hashesToLookUp =
new HashSet<>();
528 List<ResultDomain> domainsToQuery =
new ArrayList<>();
529 for (Result result : results) {
530 if (context.searchIsCancelled()) {
531 throw new SearchCancellationException(
"The search was cancelled while Frequency attribute was being calculated with the CR.");
535 if (result.
getKnown() == TskData.FileKnown.KNOWN) {
540 ResultFile file = (ResultFile) result;
541 if (file.getFirstInstance().getMd5Hash() != null
542 && !file.getFirstInstance().getMd5Hash().isEmpty()) {
543 hashesToLookUp.add(file.getFirstInstance().getMd5Hash());
544 currentFiles.add(file);
547 if (hashesToLookUp.size() >= BATCH_SIZE) {
550 hashesToLookUp.clear();
551 currentFiles.clear();
554 domainsToQuery.add((ResultDomain) result);
555 if (domainsToQuery.size() == DOMAIN_BATCH_SIZE) {
557 domainsToQuery.clear();
582 if (domainsToQuery.isEmpty()) {
587 final Map<String, List<ResultDomain>> resultDomainTable =
organizeByValue(domainsToQuery, attributeType, context);
588 final String values =
createCSV(resultDomainTable.keySet());
590 final String domainFrequencyQuery =
" value AS domain_name, COUNT(value) AS frequency FROM"
591 +
"(SELECT DISTINCT case_id, value FROM "
593 +
" WHERE value IN ("
595 +
")) AS foo GROUP BY value";
599 centralRepository.processSelectClause(domainFrequencyQuery, frequencyCallback);
600 if (context.searchIsCancelled()) {
603 if (frequencyCallback.getCause() != null) {
604 throw frequencyCallback.getCause();
607 throw new DiscoveryException(
"Fatal exception encountered querying the CR.", ex);
631 while (resultSet.next()) {
632 String domain = resultSet.getString(
"domain_name");
633 Long frequency = resultSet.getLong(
"frequency");
635 List<ResultDomain> domainInstances = domainLookup.get(domain);
640 }
catch (SQLException ex) {
650 SQLException getCause() {
661 private final List<ResultFile>
files;
669 this.files =
new ArrayList<>(
files);
676 while (resultSet.next()) {
677 String hash = resultSet.getString(1);
678 int count = resultSet.getInt(2);
679 for (Iterator<ResultFile> iterator = files.iterator(); iterator.hasNext();) {
692 }
catch (SQLException ex) {
693 logger.log(Level.WARNING,
"Error getting frequency counts from Central Repository", ex);
708 return new DiscoveryKeyUtils.HashHitsGroupKey((ResultFile) result);
712 public void addAttributeToResults(List<Result> results, SleuthkitCase caseDb,
713 CentralRepository centralRepoDb, SearchContext context)
throws DiscoveryException, SearchCancellationException {
717 String selectQuery =
createSetNameClause(results, BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID(),
718 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID());
720 HashSetNamesCallback callback =
new HashSetNamesCallback(results);
721 if (context.searchIsCancelled()) {
722 throw new SearchCancellationException(
"The search was cancelled while Hash Hit attribute was being added.");
725 caseDb.getCaseDbAccessManager().select(selectQuery, callback);
726 }
catch (TskCoreException ex) {
727 throw new DiscoveryException(
"Error looking up hash set attributes", ex);
737 List<Result> results;
745 this.results = results;
752 Map<Long, ResultFile> tempMap =
new HashMap<>();
753 for (
Result result : results) {
763 Long objId = rs.getLong(
"object_id");
764 String hashSetName = rs.getString(
"set_name");
766 tempMap.get(objId).addHashSetName(hashSetName);
768 }
catch (SQLException ex) {
769 logger.log(Level.SEVERE,
"Unable to get object_id or set_name from result set", ex);
772 }
catch (SQLException ex) {
773 logger.log(Level.SEVERE,
"Failed to get hash set names", ex);
782 static class InterestingItemAttribute
extends AttributeType {
790 public void addAttributeToResults(List<Result> results, SleuthkitCase caseDb,
791 CentralRepository centralRepoDb, SearchContext context)
throws DiscoveryException, SearchCancellationException {
795 String selectQuery =
createSetNameClause(results, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ITEM.getTypeID(),
796 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID());
798 InterestingFileSetNamesCallback callback =
new InterestingFileSetNamesCallback(results);
799 if (context.searchIsCancelled()) {
800 throw new SearchCancellationException(
"The search was cancelled while Interesting Item attribute was being added.");
803 caseDb.getCaseDbAccessManager().select(selectQuery, callback);
804 }
catch (TskCoreException ex) {
805 throw new DiscoveryException(
"Error looking up interesting file set attributes", ex);
816 List<Result> results;
825 this.results = results;
832 Map<Long, ResultFile> tempMap =
new HashMap<>();
833 for (
Result result : results) {
843 Long objId = rs.getLong(
"object_id");
844 String setName = rs.getString(
"set_name");
846 tempMap.get(objId).addInterestingSetName(setName);
848 }
catch (SQLException ex) {
849 logger.log(Level.SEVERE,
"Unable to get object_id or set_name from result set", ex);
852 }
catch (SQLException ex) {
853 logger.log(Level.SEVERE,
"Failed to get interesting file set names", ex);
862 static class LastActivityDateAttribute
extends AttributeType {
874 static class FirstActivityDateAttribute
extends AttributeType {
877 public DiscoveryKeyUtils.GroupKey getGroupKey(Result result) {
878 return new DiscoveryKeyUtils.FirstActivityDateGroupKey(result);
887 static class PageViewsAttribute
extends AttributeType {
890 public DiscoveryKeyUtils.GroupKey getGroupKey(Result result) {
891 return new DiscoveryKeyUtils.PageViewsGroupKey(result);
898 static class ObjectDetectedAttribute
extends AttributeType {
901 public DiscoveryKeyUtils.GroupKey getGroupKey(Result file) {
902 return new DiscoveryKeyUtils.ObjectDetectedGroupKey((ResultFile) file);
906 public void addAttributeToResults(List<Result> results, SleuthkitCase caseDb,
907 CentralRepository centralRepoDb, SearchContext context)
throws DiscoveryException, SearchCancellationException {
911 String selectQuery =
createSetNameClause(results, BlackboardArtifact.ARTIFACT_TYPE.TSK_OBJECT_DETECTED.getTypeID(),
912 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DESCRIPTION.getTypeID());
914 ObjectDetectedNamesCallback callback =
new ObjectDetectedNamesCallback(results);
915 if (context.searchIsCancelled()) {
916 throw new SearchCancellationException(
"The search was cancelled while Object Detected attribute was being added.");
919 caseDb.getCaseDbAccessManager().select(selectQuery, callback);
920 }
catch (TskCoreException ex) {
921 throw new DiscoveryException(
"Error looking up object detected attributes", ex);
932 List<Result> results;
940 this.results = results;
947 Map<Long, ResultFile> tempMap =
new HashMap<>();
948 for (
Result result : results) {
958 Long objId = rs.getLong(
"object_id");
959 String setName = rs.getString(
"set_name");
961 tempMap.get(objId).addObjectDetectedName(setName);
963 }
catch (SQLException ex) {
964 logger.log(Level.SEVERE,
"Unable to get object_id or set_name from result set", ex);
967 }
catch (SQLException ex) {
968 logger.log(Level.SEVERE,
"Failed to get object detected names", ex);
985 public void addAttributeToResults(List<Result> results, SleuthkitCase caseDb,
986 CentralRepository centralRepoDb, SearchContext context)
throws DiscoveryException, SearchCancellationException {
989 for (Result result : results) {
990 if (context.searchIsCancelled()) {
991 throw new SearchCancellationException(
"The search was cancelled while File Tag attribute was being added.");
996 ResultFile file = (ResultFile) result;
997 List<ContentTag> contentTags = caseDb.getContentTagsByContent(file.getFirstInstance());
999 for (ContentTag tag : contentTags) {
1000 result.
addTagName(tag.getName().getDisplayName());
1003 }
catch (TskCoreException ex) {
1004 throw new DiscoveryException(
"Error looking up file tag attributes", ex);
1012 @NbBundle.Messages({
1013 "DiscoveryAttributes.GroupingAttributeType.fileType.displayName=File Type",
1014 "DiscoveryAttributes.GroupingAttributeType.frequency.displayName=Past Occurrences",
1015 "DiscoveryAttributes.GroupingAttributeType.keywordList.displayName=Keyword",
1016 "DiscoveryAttributes.GroupingAttributeType.size.displayName=File Size",
1017 "DiscoveryAttributes.GroupingAttributeType.datasource.displayName=Data Source",
1018 "DiscoveryAttributes.GroupingAttributeType.parent.displayName=Parent Folder",
1019 "DiscoveryAttributes.GroupingAttributeType.hash.displayName=Hash Set",
1020 "DiscoveryAttributes.GroupingAttributeType.interestingItem.displayName=Interesting Item",
1021 "DiscoveryAttributes.GroupingAttributeType.tag.displayName=Tag",
1022 "DiscoveryAttributes.GroupingAttributeType.object.displayName=Object Detected",
1023 "DiscoveryAttributes.GroupingAttributeType.lastDate.displayName=Final Activity Date",
1024 "DiscoveryAttributes.GroupingAttributeType.firstDate.displayName=First Activity Date",
1025 "DiscoveryAttributes.GroupingAttributeType.pageViews.displayName=Page Views",
1026 "DiscoveryAttributes.GroupingAttributeType.none.displayName=None",
1027 "DiscoveryAttributes.GroupingAttributeType.previouslyNotable.displayName=Previous Notability",
1028 "DiscoveryAttributes.GroupingAttributeType.webCategory.displayName=Domain Category"})
1031 FREQUENCY(
new FrequencyAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_frequency_displayName()),
1032 KEYWORD_LIST_NAME(
new KeywordListAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_keywordList_displayName()),
1033 DATA_SOURCE(
new DataSourceAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_datasource_displayName()),
1035 HASH_LIST_NAME(
new HashHitsAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_hash_displayName()),
1036 INTERESTING_ITEM_SET(
new InterestingItemAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_interestingItem_displayName()),
1037 FILE_TAG(
new FileTagAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_tag_displayName()),
1038 OBJECT_DETECTED(
new ObjectDetectedAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_object_displayName()),
1039 LAST_ACTIVITY_DATE(
new LastActivityDateAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_lastDate_displayName()),
1040 FIRST_ACTIVITY_DATE(
new FirstActivityDateAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_firstDate_displayName()),
1041 PAGE_VIEWS(
new PageViewsAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_pageViews_displayName()),
1042 NO_GROUPING(
new NoGroupingAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_none_displayName()),
1043 PREVIOUSLY_NOTABLE(
new PreviouslyNotableAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_previouslyNotable_displayName()),
1044 DOMAIN_CATEGORY(
new DomainCategoryAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_webCategory_displayName());
1058 this.attributeType = attributeType;
1059 this.displayName = displayName;
1073 return attributeType;
1082 return Arrays.asList(FILE_SIZE, FREQUENCY, PARENT_PATH, OBJECT_DETECTED, HASH_LIST_NAME, INTERESTING_ITEM_SET);
1092 return Arrays.asList(PAGE_VIEWS, FREQUENCY, LAST_ACTIVITY_DATE, FIRST_ACTIVITY_DATE, PREVIOUSLY_NOTABLE, DOMAIN_CATEGORY);
1094 return Arrays.asList(PAGE_VIEWS, LAST_ACTIVITY_DATE, FIRST_ACTIVITY_DATE, DOMAIN_CATEGORY);
1115 if (hashesToLookUp.isEmpty()) {
1119 String hashes = String.join(
"','", hashesToLookUp);
1120 hashes =
"'" + hashes +
"'";
1125 String selectClause =
" value, COUNT(value) FROM "
1126 +
"(SELECT DISTINCT case_id, value FROM " + tableName
1127 +
" WHERE value IN ("
1129 +
")) AS foo GROUP BY value";
1132 centralRepoDb.processSelectClause(selectClause, callback);
1133 if (context.searchIsCancelled()) {
1137 logger.log(Level.WARNING,
"Error getting frequency counts from Central Repository", ex);
1156 int artifactTypeID,
int setNameAttrID)
throws DiscoveryException {
1159 String objIdList =
"";
1160 for (
Result result : results) {
1165 if (!objIdList.isEmpty()) {
1173 return "blackboard_artifacts.obj_id AS object_id, blackboard_attributes.value_text AS set_name "
1174 +
"FROM blackboard_artifacts "
1175 +
"INNER JOIN blackboard_attributes ON blackboard_artifacts.artifact_id=blackboard_attributes.artifact_id "
1176 +
"WHERE blackboard_attributes.artifact_type_id=\'" + artifactTypeID +
"\' "
1177 +
"AND blackboard_attributes.attribute_type_id=\'" + setNameAttrID +
"\' "
1178 +
"AND blackboard_artifacts.obj_id IN (" + objIdList
static String createSetNameClause(List< Result > results, int artifactTypeID, int setNameAttrID)
AttributeType getAttributeType()
DiscoveryKeyUtils.GroupKey getGroupKey(Result file)
DomainPreviouslyNotableCallback(Map< String, List< ResultDomain >> domainLookup)
static List< GroupingAttributeType > getOptionsForGroupingForDomains()
DomainFrequencyCallback(Map< String, List< ResultDomain >> domainLookup)
SearchData.Frequency getFrequency()
void process(ResultSet rs)
abstract TskData.FileKnown getKnown()
static final Logger logger
void process(ResultSet resultSet)
void addTagName(String tagName)
static Frequency fromCount(long count)
abstract SearchData.Type getType()
FrequencyCallback(List< ResultFile > files)
GroupingAttributeType(AttributeType attributeType, String displayName)
static List< GroupingAttributeType > getOptionsForGroupingForFiles()
static void queryDomainFrequency(List< ResultDomain > domainsToQuery, CentralRepository centralRepository, SearchContext context)
final void setFrequency(SearchData.Frequency frequency)
static String correlationTypeToInstanceTableName(CorrelationAttributeInstance.Type type)
static String normalize(CorrelationAttributeInstance.Type attributeType, String data)
void addAttributeToResults(List< Result > results, SleuthkitCase caseDb, CentralRepository centralRepoDb, SearchContext context)
AbstractFile getFirstInstance()
void process(ResultSet resultSet)
DiscoveryKeyUtils.GroupKey getGroupKey(Result result)
static final int DOMAIN_TYPE_ID
void process(ResultSet rs)
abstract DiscoveryKeyUtils.GroupKey getGroupKey(Result result)
final List< ResultFile > files
final Map< String, List< ResultDomain > > domainLookup
void process(ResultSet rs)
void addKeywordListName(String keywordListName)
final Map< String, List< ResultDomain > > domainLookup
void process(ResultSet rs)
static Map< String, List< ResultDomain > > organizeByValue(List< ResultDomain > domainsBatch, CorrelationAttributeInstance.Type attributeType, SearchContext context)
synchronized static Logger getLogger(String name)
void process(ResultSet resultSet)
static String createCSV(Set< String > values)
static void computeFrequency(Set< String > hashesToLookUp, List< ResultFile > currentFiles, CentralRepository centralRepoDb, SearchContext context)
static final int FILES_TYPE_ID
final AttributeType attributeType
static boolean isEnabled()