19 package org.sleuthkit.autopsy.discovery.search;
21 import java.text.SimpleDateFormat;
34 import java.util.ArrayList;
35 import java.util.Arrays;
36 import java.util.Collection;
37 import java.util.Collections;
38 import java.util.Date;
39 import java.util.List;
40 import java.util.Locale;
41 import java.util.StringJoiner;
42 import java.util.concurrent.TimeUnit;
43 import java.util.stream.Collectors;
44 import org.openide.util.NbBundle;
49 import org.
sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
74 throw new DiscoveryException(
"Case DB parameter is null");
77 String combinedQuery =
"";
79 if (!filter.getWhereClause().isEmpty()) {
80 if (!combinedQuery.isEmpty()) {
81 combinedQuery +=
" AND ";
83 combinedQuery +=
"(" + filter.getWhereClause() +
")";
87 if (combinedQuery.isEmpty()) {
89 throw new DiscoveryException(
"Selected filters do not include a case database query");
95 return getResultList(filters, combinedQuery, caseDb, centralRepoDb, context);
96 }
catch (TskCoreException ex) {
97 throw new DiscoveryException(
"Error querying case database", ex);
121 List<Result> resultList =
new ArrayList<>();
122 List<AbstractFile> sqlResults = caseDb.findAllFilesWhere(combinedQuery);
127 if (sqlResults.isEmpty()) {
132 for (AbstractFile abstractFile : sqlResults) {
141 if (filter.useAlternateFilter()) {
142 resultList = filter.applyAlternateFilter(resultList, caseDb, centralRepoDb, context);
145 if (resultList.isEmpty()) {
162 private static List<BlackboardAttribute.ATTRIBUTE_TYPE>
dateAttributes
164 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME,
165 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
166 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED
184 static String createAttributeTypeClause() {
185 StringJoiner joiner =
new StringJoiner(
",");
187 joiner.add(
"\'" + type.getTypeID() +
"\'");
189 return "attribute_type_id IN (" + joiner.toString() +
")";
194 return createAttributeTypeClause()
195 +
" AND (value_int64 BETWEEN " + startDate +
" AND " + endDate +
")";
198 @NbBundle.Messages({
"SearchFiltering.dateRangeFilter.lable=Activity date ",
200 "SearchFiltering.dateRangeFilter.after=after: {0}",
202 "SearchFiltering.dateRangeFilter.before=before: {0}",
203 "SearchFiltering.dateRangeFilter.and= and "})
208 desc += Bundle.SearchFiltering_dateRangeFilter_after(
new SimpleDateFormat(
"yyyy/MM/dd", Locale.getDefault()).format(
new Date(TimeUnit.SECONDS.toMillis(startDate))));
210 if (endDate < 10000000000L) {
211 if (!desc.isEmpty()) {
212 desc += Bundle.SearchFiltering_dateRangeFilter_and();
214 desc += Bundle.SearchFiltering_dateRangeFilter_before(
new SimpleDateFormat(
"yyyy/MM/dd", Locale.getDefault()).format(
new Date(TimeUnit.SECONDS.toMillis(endDate))));
216 if (!desc.isEmpty()) {
217 desc = Bundle.SearchFiltering_dateRangeFilter_lable() + desc;
228 private final Collection<ARTIFACT_TYPE>
types;
246 return Collections.unmodifiableCollection(types);
250 StringJoiner joiner =
new StringJoiner(
",");
251 for (ARTIFACT_TYPE type : types) {
252 joiner.add(
"\'" + type.getTypeID() +
"\'");
260 return "artifact_type_id IN (" + joiner +
")";
267 String
getWhereClause(List<ARTIFACT_TYPE> nonVisibleArtifactTypesToInclude) {
269 for (ARTIFACT_TYPE type : nonVisibleArtifactTypesToInclude) {
270 joiner.add(
"\'" + type.getTypeID() +
"\'");
272 return "artifact_type_id IN (" + joiner +
")";
275 @NbBundle.Messages({
"# {0} - artifactTypes",
276 "SearchFiltering.artifactTypeFilter.desc=Result type(s): {0}",
277 "SearchFiltering.artifactTypeFilter.or=, "})
281 for (ARTIFACT_TYPE type : types) {
282 if (!desc.isEmpty()) {
283 desc += Bundle.SearchFiltering_artifactTypeFilter_or();
285 desc += type.getDisplayName();
287 desc = Bundle.SearchFiltering_artifactTypeFilter_desc(desc);
311 String queryStr =
"";
313 if (!queryStr.isEmpty()) {
317 queryStr +=
"(size > \'" + size.getMinBytes() +
"\' AND size <= \'" + size.getMaxBytes() +
"\')";
319 queryStr +=
"(size >= \'" + size.getMinBytes() +
"\')";
327 "SearchFiltering.SizeFilter.desc=Size(s): {0}",
328 "SearchFiltering.SizeFilter.or=, "})
333 if (!desc.isEmpty()) {
334 desc += Bundle.SearchFiltering_SizeFilter_or();
336 desc += size.getSizeGroup();
338 desc = Bundle.SearchFiltering_SizeFilter_desc(desc);
385 return "parent_path NOT LIKE \'%" +
getSearchStr() +
"%\'";
391 "SearchFiltering.ParentSearchTerm.fullString= (exact)",
392 "SearchFiltering.ParentSearchTerm.subString= (substring)",
393 "SearchFiltering.ParentSearchTerm.includeString= (include)",
394 "SearchFiltering.ParentSearchTerm.excludeString= (exclude)",})
399 returnString += Bundle.SearchFiltering_ParentSearchTerm_fullString();
401 returnString += Bundle.SearchFiltering_ParentSearchTerm_subString();
404 returnString += Bundle.SearchFiltering_ParentSearchTerm_includeString();
406 returnString += Bundle.SearchFiltering_ParentSearchTerm_excludeString();
461 String includeQueryStr =
"";
462 String excludeQueryStr =
"";
464 if (searchTerm.isIncluded()) {
465 if (!includeQueryStr.isEmpty()) {
466 includeQueryStr +=
" OR ";
468 includeQueryStr += searchTerm.getSQLForTerm();
470 if (!excludeQueryStr.isEmpty()) {
471 excludeQueryStr +=
" AND ";
473 excludeQueryStr += searchTerm.getSQLForTerm();
476 if (!includeQueryStr.isEmpty()) {
477 includeQueryStr =
"(" + includeQueryStr +
")";
479 if (!excludeQueryStr.isEmpty()) {
480 excludeQueryStr =
"(" + excludeQueryStr +
")";
482 if (includeQueryStr.isEmpty() || excludeQueryStr.isEmpty()) {
483 return includeQueryStr + excludeQueryStr;
485 return includeQueryStr +
" AND " + excludeQueryStr;
491 "SearchFiltering.ParentFilter.desc=Paths matching: {0}",
492 "SearchFiltering.ParentFilter.or=, ",
493 "SearchFiltering.ParentFilter.exact=(exact match)",
494 "SearchFiltering.ParentFilter.substring=(substring)",
495 "SearchFiltering.ParentFilter.included=(included)",
496 "SearchFiltering.ParentFilter.excluded=(excluded)"})
501 if (!desc.isEmpty()) {
502 desc += Bundle.SearchFiltering_ParentFilter_or();
504 if (searchTerm.isFullPath()) {
505 desc += searchTerm.getSearchStr() + Bundle.SearchFiltering_ParentFilter_exact();
507 desc += searchTerm.getSearchStr() + Bundle.SearchFiltering_ParentFilter_substring();
509 if (searchTerm.isIncluded()) {
510 desc += Bundle.SearchFiltering_ParentFilter_included();
512 desc += Bundle.SearchFiltering_ParentFilter_excluded();
515 desc = Bundle.SearchFiltering_ParentFilter_desc(desc);
538 String queryStr =
"";
539 for (DataSource ds : dataSources) {
540 if (!queryStr.isEmpty()) {
543 queryStr +=
"\'" + ds.getId() +
"\'";
545 queryStr =
"data_source_obj_id IN (" + queryStr +
")";
551 "SearchFiltering.DataSourceFilter.desc=Data source(s): {0}",
552 "SearchFiltering.DataSourceFilter.or=, ",
553 "# {0} - Data source name",
554 "# {1} - Data source ID",
555 "SearchFiltering.DataSourceFilter.datasource={0}({1})",})
559 for (DataSource ds : dataSources) {
560 if (!desc.isEmpty()) {
561 desc += Bundle.SearchFiltering_DataSourceFilter_or();
563 desc += Bundle.SearchFiltering_DataSourceFilter_datasource(ds.getName(), ds.getId());
565 desc = Bundle.SearchFiltering_DataSourceFilter_desc(desc);
591 String queryStr =
"(obj_id IN (SELECT obj_id from blackboard_artifacts WHERE artifact_id IN "
592 +
"(SELECT artifact_id FROM blackboard_attributes WHERE artifact_type_id = 9 AND attribute_type_ID = 37 "
593 +
"AND (" + keywordListPart +
"))))";
600 "SearchFiltering.KeywordListFilter.desc=Keywords in list(s): {0}",})
629 this.categories =
new ArrayList<>();
630 this.categories.add(category);
635 String queryStr =
"";
636 for (
Type cat : categories) {
637 for (String type : cat.getMediaTypes()) {
638 if (!queryStr.isEmpty()) {
641 queryStr +=
"\'" + type +
"\'";
644 queryStr =
"mime_type IN (" + queryStr +
")";
650 "SearchFiltering.FileTypeFilter.desc=Type: {0}",
651 "SearchFiltering.FileTypeFilter.or=, ",})
655 for (
Type cat : categories) {
656 if (!desc.isEmpty()) {
657 desc += Bundle.SearchFiltering_FileTypeFilter_or();
659 desc += cat.toString();
661 desc = Bundle.SearchFiltering_FileTypeFilter_desc(desc);
699 freqAttr.addAttributeToResults(currentResults, caseDb, centralRepoDb, context);
702 List<Result> frequencyResults =
new ArrayList<>();
703 for (
Result file : currentResults) {
707 if (frequencies.contains(file.getFrequency())) {
708 frequencyResults.add(file);
711 return frequencyResults;
716 "SearchFiltering.FrequencyFilter.desc=Past occurrences: {0}",
717 "SearchFiltering.FrequencyFilter.or=, ",})
722 if (!desc.isEmpty()) {
723 desc += Bundle.SearchFiltering_FrequencyFilter_or();
725 desc += freq.toString();
727 return Bundle.SearchFiltering_FrequencyFilter_desc(desc);
738 throw new UnsupportedOperationException(
"Not supported, this is an alternative filter.");
749 List<Result> filteredResults =
new ArrayList<>();
750 for (
Result result : currentResults) {
755 ResultDomain domain = (ResultDomain) result;
757 filteredResults.add(domain);
760 filteredResults.add(result);
763 return filteredResults;
767 "SearchFiltering.KnownAccountTypeFilter.desc=Only domains with known account type"
771 return Bundle.SearchFiltering_KnownAccountTypeFilter_desc();
783 throw new UnsupportedOperationException(
"Not supported, this is an alternative filter.");
795 previouslyNotableAttr.addAttributeToResults(currentResults, caseDb, centralRepoDb, context);
796 List<Result> filteredResults =
new ArrayList<>();
797 for (
Result file : currentResults) {
802 filteredResults.add(file);
805 return filteredResults;
809 "SearchFiltering.PreviouslyNotableFilter.desc=Previously marked as notable in central repository"
813 return Bundle.SearchFiltering_PreviouslyNotableFilter_desc();
839 String queryStr =
"(obj_id IN (SELECT obj_id from blackboard_artifacts WHERE artifact_id IN "
840 +
"(SELECT artifact_id FROM blackboard_attributes WHERE artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID()
841 +
" AND attribute_type_ID = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID() +
" "
842 +
"AND (" + hashSetPart +
"))))";
849 "FileSearchFiltering.HashSetFilter.desc=Hash set hits in set(s): {0}",})
877 @SuppressWarnings(
"deprecation")
882 String queryStr =
"(obj_id IN (SELECT obj_id from blackboard_artifacts WHERE artifact_id IN "
883 +
"(SELECT artifact_id FROM blackboard_attributes WHERE (artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID()
884 +
" OR artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ITEM.getTypeID()
885 +
") AND attribute_type_ID = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID() +
" "
886 +
"AND (" + intItemSetPart +
"))))";
893 "SearchFiltering.InterestingItemSetFilter.desc=Interesting item hits in set(s): {0}",})
921 String queryStr =
"(obj_id IN (SELECT obj_id from blackboard_artifacts WHERE artifact_id IN "
922 +
"(SELECT artifact_id FROM blackboard_attributes WHERE artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_OBJECT_DETECTED.getTypeID()
923 +
" AND attribute_type_ID = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DESCRIPTION.getTypeID() +
" "
924 +
"AND (" + objTypePart +
"))))";
931 "SearchFiltering.ObjectDetectionFilter.desc=Objects detected in set(s): {0}",})
959 @SuppressWarnings(
"deprecation")
966 String hashsetQueryPart =
"";
967 String tagQueryPart =
"";
968 String intItemQueryPart =
"";
972 hashsetQueryPart =
" (known = " + TskData.FileKnown.BAD.getFileKnownValue() +
") ";
977 intItemQueryPart =
" (obj_id IN (SELECT obj_id from blackboard_artifacts WHERE artifact_type_id = "
978 + BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ITEM.getTypeID() +
" OR artifact_type_id = "
979 + BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID() +
")) ";
984 tagQueryPart =
"(obj_id IN (SELECT obj_id FROM content_tags))";
987 tagQueryPart =
"(obj_id IN (SELECT obj_id FROM content_tags WHERE tag_name_id IN (SELECT tag_name_id FROM tag_names WHERE knownStatus = "
988 + TskData.FileKnown.BAD.getFileKnownValue() +
")))";
991 tagQueryPart =
"(obj_id IN (SELECT obj_id FROM content_tags WHERE tag_name_id IN (SELECT tag_name_id FROM tag_names WHERE knownStatus != "
992 + TskData.FileKnown.BAD.getFileKnownValue() +
")))";
995 String queryStr = hashsetQueryPart;
996 if (!intItemQueryPart.isEmpty()) {
997 if (!queryStr.isEmpty()) {
1000 queryStr += intItemQueryPart;
1002 if (!tagQueryPart.isEmpty()) {
1003 if (!queryStr.isEmpty()) {
1006 queryStr += tagQueryPart;
1011 @NbBundle.Messages({
1013 "SearchFiltering.ScoreFilter.desc=Score(s) of : {0}",})
1016 return Bundle.SearchFiltering_ScoreFilter_desc(
1041 for (TagName tagName : tagNames) {
1042 if (!tagIDs.isEmpty()) {
1045 tagIDs += tagName.getId();
1048 String queryStr =
"(obj_id IN (SELECT obj_id FROM content_tags WHERE tag_name_id IN (" + tagIDs +
")))";
1053 @NbBundle.Messages({
1054 "# {0} - tag names",
1055 "FileSearchFiltering.TagsFilter.desc=Tagged {0}",
1056 "FileSearchFiltering.TagsFilter.or=, ",})
1060 for (TagName name : tagNames) {
1061 if (!desc.isEmpty()) {
1062 desc += Bundle.FileSearchFiltering_TagsFilter_or();
1064 desc += name.getDisplayName();
1066 return Bundle.FileSearchFiltering_TagsFilter_desc(desc);
1078 return "(obj_id IN (SELECT obj_id from blackboard_artifacts WHERE artifact_id IN "
1079 +
"(SELECT artifact_id FROM blackboard_attributes WHERE artifact_type_id = "
1080 + BlackboardArtifact.ARTIFACT_TYPE.TSK_USER_CONTENT_SUSPECTED.getTypeID() +
")))";
1083 @NbBundle.Messages({
1084 "FileSearchFiltering.UserCreatedFilter.desc=that contain EXIF data",})
1087 return Bundle.FileSearchFiltering_UserCreatedFilter_desc();
1113 if (centralRepoDb == null) {
1114 throw new DiscoveryException(
"Can not run Previously Notable filter with null Central Repository DB");
1119 if (currentResults.isEmpty()) {
1120 throw new DiscoveryException(
"Can not run on empty list");
1124 List<Result> notableResults =
new ArrayList<>();
1129 for (
Result result : currentResults) {
1141 notableResults.add(result);
1145 return notableResults;
1147 throw new DiscoveryException(
"Error querying central repository", ex);
1151 @NbBundle.Messages({
1152 "FileSearchFiltering.PreviouslyNotableFilter.desc=that were previously marked as notable",})
1155 return Bundle.FileSearchFiltering_PreviouslyNotableFilter_desc();
1166 return "known!=" + TskData.FileKnown.KNOWN.getFileKnownValue();
1169 @NbBundle.Messages({
1170 "FileSearchFiltering.KnownFilter.desc=which are not known"})
1173 return Bundle.FileSearchFiltering_KnownFilter_desc();
1184 @NbBundle.Messages({
1185 "FileSearchFiltering.concatenateSetNamesForDisplay.comma=, ",})
1188 for (String setName : setNames) {
1189 if (!desc.isEmpty()) {
1190 desc += Bundle.FileSearchFiltering_concatenateSetNamesForDisplay_comma();
1207 for (String setName : setNames) {
1208 if (!result.isEmpty()) {
1211 result +=
"value_text = \'" + setName +
"\'";
static String concatenateNamesForSQL(List< String > setNames)
static List< BlackboardAttribute.ATTRIBUTE_TYPE > dateAttributes
final List< Score > scores
FrequencyFilter(List< Frequency > frequencies)
staticfinal long NO_MAXIMUM
ParentFilter(List< ParentSearchTerm > parentSearchTerms)
List< Result > applyAlternateFilter(List< Result > currentResults, SleuthkitCase caseDb, CentralRepository centralRepoDb, SearchContext context)
final Collection< ARTIFACT_TYPE > types
final List< String > listNames
HashSetFilter(List< String > setNames)
ArtifactTypeFilter(Collection< ARTIFACT_TYPE > types)
ParentSearchTerm(String searchStr, boolean isFullPath, boolean isIncluded)
Collection< ARTIFACT_TYPE > getTypes()
List< Result > applyAlternateFilter(List< Result > currentResults, SleuthkitCase caseDb, CentralRepository centralRepoDb, SearchContext context)
static List< CorrelationAttributeInstance.Type > getDefaultCorrelationTypes()
List< Result > applyAlternateFilter(List< Result > currentResults, SleuthkitCase caseDb, CentralRepository centralRepoDb, SearchContext context)
ObjectDetectionFilter(List< String > typeNames)
boolean useAlternateFilter()
KeywordListFilter(List< String > listNames)
final List< String > setNames
boolean hasKnownAccountType()
ArtifactDateRangeFilter(Long startDate, Long endDate)
FileTypeFilter(Type category)
Long getCountArtifactInstancesKnownBad(CorrelationAttributeInstance.Type aType, String value)
boolean useAlternateFilter()
AbstractFile getFirstInstance()
static String concatenateSetNamesForDisplay(List< String > setNames)
final List< DataSource > dataSources
static List< Result > getResultList(List< AbstractFilter > filters, String combinedQuery, SleuthkitCase caseDb, CentralRepository centralRepoDb, SearchContext context)
List< Result > applyAlternateFilter(List< Result > currentResults, SleuthkitCase caseDb, CentralRepository centralRepoDb, SearchContext context)
final List< ParentSearchTerm > parentSearchTerms
boolean useAlternateFilter()
SizeFilter(List< FileSize > fileSizes)
StringJoiner joinStandardArtifactTypes()
ScoreFilter(List< Score > scores)
final List< String > typeNames
final List< FileSize > fileSizes
boolean useAlternateFilter()
final List< Frequency > frequencies
DataSourceFilter(List< DataSource > dataSources)
InterestingFileSetFilter(List< String > setNames)
FileTypeFilter(List< Type > categories)
boolean searchIsCancelled()
final List< String > setNames
static final int FILES_TYPE_ID
final List< Type > categories