Autopsy  4.14.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
FileSearchFiltering.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2019-2020 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.autopsy.filequery;
20 
28 import org.sleuthkit.datamodel.AbstractFile;
29 import org.sleuthkit.datamodel.DataSource;
30 import org.sleuthkit.datamodel.SleuthkitCase;
31 import org.sleuthkit.datamodel.TagName;
32 import org.sleuthkit.datamodel.TskCoreException;
33 import java.util.ArrayList;
34 import java.util.List;
35 import java.util.stream.Collectors;
36 import org.openide.util.NbBundle;
37 import org.sleuthkit.datamodel.BlackboardArtifact;
38 import org.sleuthkit.datamodel.BlackboardAttribute;
39 import org.sleuthkit.datamodel.TskData;
41 
45 class FileSearchFiltering {
46 
57  static List<ResultFile> runQueries(List<FileFilter> filters, SleuthkitCase caseDb, CentralRepository centralRepoDb) throws FileSearchException {
58  if (caseDb == null) {
59  throw new FileSearchException("Case DB parameter is null"); // NON-NLS
60  }
61  // Combine all the SQL queries from the filters into one query
62  String combinedQuery = "";
63  for (FileFilter filter : filters) {
64  if (!filter.getWhereClause().isEmpty()) {
65  if (!combinedQuery.isEmpty()) {
66  combinedQuery += " AND "; // NON-NLS
67  }
68  combinedQuery += "(" + filter.getWhereClause() + ")"; // NON-NLS
69  }
70  }
71 
72  if (combinedQuery.isEmpty()) {
73  // The file search filter is required, so this should never be empty.
74  throw new FileSearchException("Selected filters do not include a case database query");
75  }
76  try {
77  return getResultList(filters, combinedQuery, caseDb, centralRepoDb);
78  } catch (TskCoreException ex) {
79  throw new FileSearchException("Error querying case database", ex); // NON-NLS
80  }
81  }
82 
97  private static List<ResultFile> getResultList(List<FileFilter> filters, String combinedQuery, SleuthkitCase caseDb, CentralRepository centralRepoDb) throws TskCoreException, FileSearchException {
98  // Get all matching abstract files
99  List<ResultFile> resultList = new ArrayList<>();
100  List<AbstractFile> sqlResults = caseDb.findAllFilesWhere(combinedQuery);
101 
102  // If there are no results, return now
103  if (sqlResults.isEmpty()) {
104  return resultList;
105  }
106 
107  // Wrap each result in a ResultFile
108  for (AbstractFile abstractFile : sqlResults) {
109  resultList.add(new ResultFile(abstractFile));
110  }
111 
112  // Now run any non-SQL filters.
113  for (FileFilter filter : filters) {
114  if (filter.useAlternateFilter()) {
115  resultList = filter.applyAlternateFilter(resultList, caseDb, centralRepoDb);
116  }
117  // There are no matches for the filters run so far, so return
118  if (resultList.isEmpty()) {
119  return resultList;
120  }
121  }
122  return resultList;
123  }
124 
128  static abstract class FileFilter {
129 
137  abstract String getWhereClause();
138 
145  boolean useAlternateFilter() {
146  return false;
147  }
148 
163  List<ResultFile> applyAlternateFilter(List<ResultFile> currentResults, SleuthkitCase caseDb,
164  CentralRepository centralRepoDb) throws FileSearchException {
165  return new ArrayList<>();
166  }
167 
173  abstract String getDesc();
174  }
175 
179  static class SizeFilter extends FileFilter {
180 
181  private final List<FileSize> fileSizes;
182 
188  SizeFilter(List<FileSize> fileSizes) {
189  this.fileSizes = fileSizes;
190  }
191 
192  @Override
193  String getWhereClause() {
194  String queryStr = ""; // NON-NLS
195  for (FileSize size : fileSizes) {
196  if (!queryStr.isEmpty()) {
197  queryStr += " OR "; // NON-NLS
198  }
199  if (size.getMaxBytes() != FileSize.NO_MAXIMUM) {
200  queryStr += "(size > \'" + size.getMinBytes() + "\' AND size <= \'" + size.getMaxBytes() + "\')"; // NON-NLS
201  } else {
202  queryStr += "(size >= \'" + size.getMinBytes() + "\')"; // NON-NLS
203  }
204  }
205  return queryStr;
206  }
207 
208  @NbBundle.Messages({
209  "# {0} - filters",
210  "FileSearchFiltering.SizeFilter.desc=Files with size in range(s): {0}",
211  "FileSearchFiltering.SizeFilter.or= or ",
212  "# {0} - Minimum bytes",
213  "# {1} - Maximum bytes",
214  "FileSearchFiltering.SizeFilter.range=({0} to {1})",})
215  @Override
216  String getDesc() {
217  String desc = ""; // NON-NLS
218  for (FileSize size : fileSizes) {
219  if (!desc.isEmpty()) {
220  desc += Bundle.FileSearchFiltering_SizeFilter_or();
221  }
222  desc += Bundle.FileSearchFiltering_SizeFilter_range(size.getMinBytes(), size.getMaxBytes());
223  }
224  desc = Bundle.FileSearchFiltering_SizeFilter_desc(desc);
225  return desc;
226  }
227  }
228 
233  static class ParentSearchTerm {
234 
235  private final String searchStr;
236  private final boolean fullPath;
237  private final boolean included;
238 
248  ParentSearchTerm(String searchStr, boolean isFullPath, boolean isIncluded) {
249  this.searchStr = searchStr;
250  this.fullPath = isFullPath;
251  this.included = isIncluded;
252  }
253 
259  String getSQLForTerm() {
260  // TODO - these should really be prepared statements
261  if (isIncluded()) {
262  if (isFullPath()) {
263  return "parent_path=\'" + getSearchStr() + "\'"; // NON-NLS
264  } else {
265  return "parent_path LIKE \'%" + getSearchStr() + "%\'"; // NON-NLS
266  }
267  } else {
268  if (isFullPath()) {
269  return "parent_path!=\'" + getSearchStr() + "\'"; // NON-NLS
270  } else {
271  return "parent_path NOT LIKE \'%" + getSearchStr() + "%\'"; // NON-NLS
272  }
273  }
274  }
275 
276  @NbBundle.Messages({
277  "FileSearchFiltering.ParentSearchTerm.fullString= (exact)",
278  "FileSearchFiltering.ParentSearchTerm.subString= (substring)",
279  "FileSearchFiltering.ParentSearchTerm.includeString= (include)",
280  "FileSearchFiltering.ParentSearchTerm.excludeString= (exclude)",})
281  @Override
282  public String toString() {
283  String returnString = getSearchStr();
284  if (isFullPath()) {
285  returnString += Bundle.FileSearchFiltering_ParentSearchTerm_fullString();
286  } else {
287  returnString += Bundle.FileSearchFiltering_ParentSearchTerm_subString();
288  }
289  if (isIncluded()) {
290  returnString += Bundle.FileSearchFiltering_ParentSearchTerm_includeString();
291  } else {
292  returnString += Bundle.FileSearchFiltering_ParentSearchTerm_excludeString();
293  }
294  return returnString;
295  }
296 
300  boolean isFullPath() {
301  return fullPath;
302  }
303 
307  boolean isIncluded() {
308  return included;
309  }
310 
314  String getSearchStr() {
315  return searchStr;
316  }
317  }
318 
322  static class ParentFilter extends FileFilter {
323 
324  private final List<ParentSearchTerm> parentSearchTerms;
325 
331  ParentFilter(List<ParentSearchTerm> parentSearchTerms) {
332  this.parentSearchTerms = parentSearchTerms;
333  }
334 
335  @Override
336  String getWhereClause() {
337  String includeQueryStr = ""; // NON-NLS
338  String excludeQueryStr = "";
339  for (ParentSearchTerm searchTerm : parentSearchTerms) {
340  if (searchTerm.isIncluded()) {
341  if (!includeQueryStr.isEmpty()) {
342  includeQueryStr += " OR "; // NON-NLS
343  }
344  includeQueryStr += searchTerm.getSQLForTerm();
345  } else {
346  if (!excludeQueryStr.isEmpty()) {
347  excludeQueryStr += " AND "; // NON-NLS
348  }
349  excludeQueryStr += searchTerm.getSQLForTerm();
350  }
351  }
352  if (!includeQueryStr.isEmpty()) {
353  includeQueryStr = "(" + includeQueryStr + ")";
354  }
355  if (!excludeQueryStr.isEmpty()) {
356  excludeQueryStr = "(" + excludeQueryStr + ")";
357  }
358  if (includeQueryStr.isEmpty() || excludeQueryStr.isEmpty()) {
359  return includeQueryStr + excludeQueryStr;
360  } else {
361  return includeQueryStr + " AND " + excludeQueryStr;
362  }
363  }
364 
365  @NbBundle.Messages({
366  "# {0} - filters",
367  "FileSearchFiltering.ParentFilter.desc=Files with paths matching: {0}",
368  "FileSearchFiltering.ParentFilter.or= or ",
369  "FileSearchFiltering.ParentFilter.exact=(exact match)",
370  "FileSearchFiltering.ParentFilter.substring=(substring)",})
371  @Override
372  String getDesc() {
373  String desc = ""; // NON-NLS
374  for (ParentSearchTerm searchTerm : parentSearchTerms) {
375  if (!desc.isEmpty()) {
376  desc += Bundle.FileSearchFiltering_ParentFilter_or();
377  }
378  if (searchTerm.isFullPath()) {
379  desc += searchTerm.getSearchStr() + Bundle.FileSearchFiltering_ParentFilter_exact();
380  } else {
381  desc += searchTerm.getSearchStr() + Bundle.FileSearchFiltering_ParentFilter_substring();
382  }
383  }
384  desc = Bundle.FileSearchFiltering_ParentFilter_desc(desc);
385  return desc;
386  }
387  }
388 
392  static class DataSourceFilter extends FileFilter {
393 
394  private final List<DataSource> dataSources;
395 
401  DataSourceFilter(List<DataSource> dataSources) {
402  this.dataSources = dataSources;
403  }
404 
405  @Override
406  String getWhereClause() {
407  String queryStr = ""; // NON-NLS
408  for (DataSource ds : dataSources) {
409  if (!queryStr.isEmpty()) {
410  queryStr += ","; // NON-NLS
411  }
412  queryStr += "\'" + ds.getId() + "\'"; // NON-NLS
413  }
414  queryStr = "data_source_obj_id IN (" + queryStr + ")"; // NON-NLS
415  return queryStr;
416  }
417 
418  @NbBundle.Messages({
419  "# {0} - filters",
420  "FileSearchFiltering.DataSourceFilter.desc=Files in data source(s): {0}",
421  "FileSearchFiltering.DataSourceFilter.or= or ",
422  "# {0} - Data source name",
423  "# {1} - Data source ID",
424  "FileSearchFiltering.DataSourceFilter.datasource={0}({1})",})
425  @Override
426  String getDesc() {
427  String desc = ""; // NON-NLS
428  for (DataSource ds : dataSources) {
429  if (!desc.isEmpty()) {
430  desc += Bundle.FileSearchFiltering_DataSourceFilter_or();
431  }
432  desc += Bundle.FileSearchFiltering_DataSourceFilter_datasource(ds.getName(), ds.getId());
433  }
434  desc = Bundle.FileSearchFiltering_DataSourceFilter_desc(desc);
435  return desc;
436  }
437  }
438 
443  static class KeywordListFilter extends FileFilter {
444 
445  private final List<String> listNames;
446 
452  KeywordListFilter(List<String> listNames) {
453  this.listNames = listNames;
454  }
455 
456  @Override
457  String getWhereClause() {
458  String keywordListPart = concatenateNamesForSQL(listNames);
459 
460  String queryStr = "(obj_id IN (SELECT obj_id from blackboard_artifacts WHERE artifact_id IN "
461  + "(SELECT artifact_id FROM blackboard_attributes WHERE artifact_type_id = 9 AND attribute_type_ID = 37 "
462  + "AND (" + keywordListPart + "))))"; // NON-NLS
463 
464  return queryStr;
465  }
466 
467  @NbBundle.Messages({
468  "# {0} - filters",
469  "FileSearchFiltering.KeywordListFilter.desc=Files with keywords in list(s): {0}",})
470  @Override
471  String getDesc() {
472  return Bundle.FileSearchFiltering_KeywordListFilter_desc(concatenateSetNamesForDisplay(listNames));
473  }
474  }
475 
479  static class FileTypeFilter extends FileFilter {
480 
481  private final List<FileType> categories;
482 
488  FileTypeFilter(List<FileType> categories) {
489  this.categories = categories;
490  }
491 
497  FileTypeFilter(FileType category) {
498  this.categories = new ArrayList<>();
499  this.categories.add(category);
500  }
501 
502  @Override
503  String getWhereClause() {
504  String queryStr = ""; // NON-NLS
505  for (FileType cat : categories) {
506  for (String type : cat.getMediaTypes()) {
507  if (!queryStr.isEmpty()) {
508  queryStr += ","; // NON-NLS
509  }
510  queryStr += "\'" + type + "\'"; // NON-NLS
511  }
512  }
513  queryStr = "mime_type IN (" + queryStr + ")"; // NON-NLS
514  return queryStr;
515  }
516 
517  @NbBundle.Messages({
518  "# {0} - filters",
519  "FileSearchFiltering.FileTypeFilter.desc=Files with type: {0}",
520  "FileSearchFiltering.FileTypeFilter.or= or ",})
521  @Override
522  String getDesc() {
523  String desc = "";
524  for (FileType cat : categories) {
525  if (!desc.isEmpty()) {
526  desc += Bundle.FileSearchFiltering_FileTypeFilter_or();
527  }
528  desc += cat.toString();
529  }
530  desc = Bundle.FileSearchFiltering_FileTypeFilter_desc(desc);
531  return desc;
532  }
533  }
534 
538  static class FrequencyFilter extends FileFilter {
539 
540  private final List<Frequency> frequencies;
541 
547  FrequencyFilter(List<Frequency> frequencies) {
548  this.frequencies = frequencies;
549  }
550 
551  @Override
552  String getWhereClause() {
553  // Since this relies on the central repository database, there is no
554  // query on the case database.
555  return ""; // NON-NLS
556  }
557 
558  @Override
559  boolean useAlternateFilter() {
560  return true;
561  }
562 
563  @Override
564  List<ResultFile> applyAlternateFilter(List<ResultFile> currentResults, SleuthkitCase caseDb,
565  CentralRepository centralRepoDb) throws FileSearchException {
566 
567  // We have to have run some kind of SQL filter before getting to this point,
568  // and should have checked afterward to see if the results were empty.
569  if (currentResults.isEmpty()) {
570  throw new FileSearchException("Can not run on empty list"); // NON-NLS
571  }
572 
573  // Set the frequency for each file
574  FileSearch.FrequencyAttribute freqAttr = new FileSearch.FrequencyAttribute();
575  freqAttr.addAttributeToResultFiles(currentResults, caseDb, centralRepoDb);
576 
577  // If the frequency matches the filter, add the file to the results
578  List<ResultFile> frequencyResults = new ArrayList<>();
579  for (ResultFile file : currentResults) {
580  if (frequencies.contains(file.getFrequency())) {
581  frequencyResults.add(file);
582  }
583  }
584  return frequencyResults;
585  }
586 
587  @NbBundle.Messages({
588  "# {0} - filters",
589  "FileSearchFiltering.FrequencyFilter.desc=Files with frequency: {0}",
590  "FileSearchFiltering.FrequencyFilter.or= or ",})
591  @Override
592  String getDesc() {
593  String desc = ""; // NON-NLS
594  for (Frequency freq : frequencies) {
595  if (!desc.isEmpty()) {
596  desc += Bundle.FileSearchFiltering_FrequencyFilter_or();
597  }
598  desc += freq.name();
599  }
600  return Bundle.FileSearchFiltering_FrequencyFilter_desc(desc);
601  }
602  }
603 
608  static class HashSetFilter extends FileFilter {
609 
610  private final List<String> setNames;
611 
617  HashSetFilter(List<String> setNames) {
618  this.setNames = setNames;
619  }
620 
621  @Override
622  String getWhereClause() {
623  String hashSetPart = concatenateNamesForSQL(setNames);
624 
625  String queryStr = "(obj_id IN (SELECT obj_id from blackboard_artifacts WHERE artifact_id IN "
626  + "(SELECT artifact_id FROM blackboard_attributes WHERE artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID()
627  + " AND attribute_type_ID = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID() + " "
628  + "AND (" + hashSetPart + "))))"; // NON-NLS
629 
630  return queryStr;
631  }
632 
633  @NbBundle.Messages({
634  "# {0} - filters",
635  "FileSearchFiltering.HashSetFilter.desc=Files with hash set hits in set(s): {0}",})
636  @Override
637  String getDesc() {
638  return Bundle.FileSearchFiltering_HashSetFilter_desc(concatenateSetNamesForDisplay(setNames));
639  }
640  }
641 
646  static class InterestingFileSetFilter extends FileFilter {
647 
648  private final List<String> setNames;
649 
655  InterestingFileSetFilter(List<String> setNames) {
656  this.setNames = setNames;
657  }
658 
659  @Override
660  String getWhereClause() {
661  String intItemSetPart = concatenateNamesForSQL(setNames);
662 
663  String queryStr = "(obj_id IN (SELECT obj_id from blackboard_artifacts WHERE artifact_id IN "
664  + "(SELECT artifact_id FROM blackboard_attributes WHERE artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID()
665  + " AND attribute_type_ID = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID() + " "
666  + "AND (" + intItemSetPart + "))))"; // NON-NLS
667 
668  return queryStr;
669  }
670 
671  @NbBundle.Messages({
672  "# {0} - filters",
673  "FileSearchFiltering.InterestingItemSetFilter.desc=Files with interesting item hits in set(s): {0}",})
674  @Override
675  String getDesc() {
676  return Bundle.FileSearchFiltering_InterestingItemSetFilter_desc(concatenateSetNamesForDisplay(setNames));
677  }
678  }
679 
684  static class ObjectDetectionFilter extends FileFilter {
685 
686  private final List<String> typeNames;
687 
693  ObjectDetectionFilter(List<String> typeNames) {
694  this.typeNames = typeNames;
695  }
696 
697  @Override
698  String getWhereClause() {
699  String objTypePart = concatenateNamesForSQL(typeNames);
700 
701  String queryStr = "(obj_id IN (SELECT obj_id from blackboard_artifacts WHERE artifact_id IN "
702  + "(SELECT artifact_id FROM blackboard_attributes WHERE artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_OBJECT_DETECTED.getTypeID()
703  + " AND attribute_type_ID = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DESCRIPTION.getTypeID() + " "
704  + "AND (" + objTypePart + "))))"; // NON-NLS
705 
706  return queryStr;
707  }
708 
709  @NbBundle.Messages({
710  "# {0} - filters",
711  "FileSearchFiltering.ObjectDetectionFilter.desc=Files with objects detected in set(s): {0}",})
712  @Override
713  String getDesc() {
714  return Bundle.FileSearchFiltering_ObjectDetectionFilter_desc(concatenateSetNamesForDisplay(typeNames));
715  }
716  }
717 
722  static class ScoreFilter extends FileFilter {
723 
724  private final List<Score> scores;
725 
731  ScoreFilter(List<Score> scores) {
732  this.scores = scores;
733  }
734 
735  @Override
736  String getWhereClause() {
737 
738  // Current algorithm:
739  // "Notable" if the file is a match for a notable hashset or has been tagged with a notable tag.
740  // "Interesting" if the file has an interesting item match or has been tagged with a non-notable tag.
741  String hashsetQueryPart = "";
742  String tagQueryPart = "";
743  String intItemQueryPart = "";
744 
745  if (scores.contains(Score.NOTABLE)) {
746  // do hashset
747  hashsetQueryPart = " (known = " + TskData.FileKnown.BAD.getFileKnownValue() + ") ";
748  }
749 
750  if (scores.contains(Score.INTERESTING)) {
751  // Matches interesting item artifact
752  intItemQueryPart = " (obj_id IN (SELECT obj_id from blackboard_artifacts WHERE artifact_type_id = "
753  + BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID() + ")) ";
754  }
755 
756  if (scores.contains(Score.NOTABLE) && scores.contains(Score.INTERESTING)) {
757  // Any tag will work
758  tagQueryPart = "(obj_id IN (SELECT obj_id FROM content_tags))";
759  } else if (scores.contains(Score.NOTABLE)) {
760  // Notable tags
761  tagQueryPart = "(obj_id IN (SELECT obj_id FROM content_tags WHERE tag_name_id IN (SELECT tag_name_id FROM tag_names WHERE knownStatus = "
762  + TskData.FileKnown.BAD.getFileKnownValue() + ")))";
763  } else if (scores.contains(Score.INTERESTING)) {
764  // Non-notable tags
765  tagQueryPart = "(obj_id IN (SELECT obj_id FROM content_tags WHERE tag_name_id IN (SELECT tag_name_id FROM tag_names WHERE knownStatus != "
766  + TskData.FileKnown.BAD.getFileKnownValue() + ")))";
767  }
768 
769  String queryStr = hashsetQueryPart;
770  if (!intItemQueryPart.isEmpty()) {
771  if (!queryStr.isEmpty()) {
772  queryStr += " OR ";
773  }
774  queryStr += intItemQueryPart;
775  }
776  if (!tagQueryPart.isEmpty()) {
777  if (!queryStr.isEmpty()) {
778  queryStr += " OR ";
779  }
780  queryStr += tagQueryPart;
781  }
782  return queryStr;
783  }
784 
785  @NbBundle.Messages({
786  "# {0} - filters",
787  "FileSearchFiltering.ScoreFilter.desc=Files with score(s) of : {0}",})
788  @Override
789  String getDesc() {
790  return Bundle.FileSearchFiltering_ScoreFilter_desc(
791  concatenateSetNamesForDisplay(scores.stream().map(p -> p.toString()).collect(Collectors.toList())));
792  }
793  }
794 
799  static class TagsFilter extends FileFilter {
800 
801  private final List<TagName> tagNames;
802 
808  TagsFilter(List<TagName> tagNames) {
809  this.tagNames = tagNames;
810  }
811 
812  @Override
813  String getWhereClause() {
814  String tagIDs = ""; // NON-NLS
815  for (TagName tagName : tagNames) {
816  if (!tagIDs.isEmpty()) {
817  tagIDs += ",";
818  }
819  tagIDs += tagName.getId();
820  }
821 
822  String queryStr = "(obj_id IN (SELECT obj_id FROM content_tags WHERE tag_name_id IN (" + tagIDs + ")))";
823 
824  return queryStr;
825  }
826 
827  @NbBundle.Messages({
828  "# {0} - tag names",
829  "FileSearchFiltering.TagsFilter.desc=Files that have been tagged {0}",
830  "FileSearchFiltering.TagsFilter.or= or ",})
831  @Override
832  String getDesc() {
833  String desc = ""; // NON-NLS
834  for (TagName name : tagNames) {
835  if (!desc.isEmpty()) {
836  desc += Bundle.FileSearchFiltering_TagsFilter_or();
837  }
838  desc += name.getDisplayName();
839  }
840  return Bundle.FileSearchFiltering_TagsFilter_desc(desc);
841  }
842  }
843 
847  static class UserCreatedFilter extends FileFilter {
848 
852  UserCreatedFilter() {
853  // Nothing to save
854  }
855 
856  @Override
857  String getWhereClause() {
858  return "(obj_id IN (SELECT obj_id from blackboard_artifacts WHERE artifact_id IN "
859  + "(SELECT artifact_id FROM blackboard_attributes WHERE artifact_type_id = "
860  + BlackboardArtifact.ARTIFACT_TYPE.TSK_USER_CONTENT_SUSPECTED.getTypeID() + ")))";
861  }
862 
863  @NbBundle.Messages({
864  "FileSearchFiltering.UserCreatedFilter.desc=Files that contain EXIF data",})
865  @Override
866  String getDesc() {
867  return Bundle.FileSearchFiltering_UserCreatedFilter_desc();
868  }
869  }
870 
875  static class NotableFilter extends FileFilter {
876 
880  NotableFilter() {
881  // Nothing to save
882  }
883 
884  @Override
885  String getWhereClause() {
886  // Since this relies on the central repository database, there is no
887  // query on the case database.
888  return ""; // NON-NLS
889  }
890 
891  @Override
892  boolean useAlternateFilter() {
893  return true;
894  }
895 
896  @Override
897  List<ResultFile> applyAlternateFilter(List<ResultFile> currentResults, SleuthkitCase caseDb,
898  CentralRepository centralRepoDb) throws FileSearchException {
899 
900  if (centralRepoDb == null) {
901  throw new FileSearchException("Can not run Previously Notable filter with null Central Repository DB"); // NON-NLS
902  }
903 
904  // We have to have run some kind of SQL filter before getting to this point,
905  // and should have checked afterward to see if the results were empty.
906  if (currentResults.isEmpty()) {
907  throw new FileSearchException("Can not run on empty list"); // NON-NLS
908  }
909 
910  // The matching files
911  List<ResultFile> notableResults = new ArrayList<>();
912 
913  try {
914  CorrelationAttributeInstance.Type type = CorrelationAttributeInstance.getDefaultCorrelationTypes().get(CorrelationAttributeInstance.FILES_TYPE_ID);
915 
916  for (ResultFile file : currentResults) {
917  if (file.getFirstInstance().getMd5Hash() != null && !file.getFirstInstance().getMd5Hash().isEmpty()) {
918 
919  // Check if this file hash is marked as notable in the CR
920  String value = file.getFirstInstance().getMd5Hash();
921  if (centralRepoDb.getCountArtifactInstancesKnownBad(type, value) > 0) {
922  notableResults.add(file);
923  }
924  }
925  }
926  return notableResults;
927  } catch (CentralRepoException | CorrelationAttributeNormalizationException ex) {
928  throw new FileSearchException("Error querying central repository", ex); // NON-NLS
929  }
930  }
931 
932  @NbBundle.Messages({
933  "FileSearchFiltering.PreviouslyNotableFilter.desc=Files that were previously marked as notable",})
934  @Override
935  String getDesc() {
936  return Bundle.FileSearchFiltering_PreviouslyNotableFilter_desc();
937  }
938  }
939 
943  static class KnownFilter extends FileFilter {
944 
945  @Override
946  String getWhereClause() {
947  return "known!=" + TskData.FileKnown.KNOWN.getFileKnownValue(); // NON-NLS
948  }
949 
950  @NbBundle.Messages({
951  "FileSearchFiltering.KnownFilter.desc=Files which are not known"})
952  @Override
953  String getDesc() {
954  return Bundle.FileSearchFiltering_KnownFilter_desc();
955  }
956  }
957 
958  @NbBundle.Messages({
959  "FileSearchFiltering.concatenateSetNamesForDisplay.comma=, ",})
960  private static String concatenateSetNamesForDisplay(List<String> setNames) {
961  String desc = ""; // NON-NLS
962  for (String setName : setNames) {
963  if (!desc.isEmpty()) {
964  desc += Bundle.FileSearchFiltering_concatenateSetNamesForDisplay_comma();
965  }
966  desc += setName;
967  }
968  return desc;
969  }
970 
979  private static String concatenateNamesForSQL(List<String> setNames) {
980  String result = ""; // NON-NLS
981  for (String setName : setNames) {
982  if (!result.isEmpty()) {
983  result += " OR "; // NON-NLS
984  }
985  result += "value_text = \'" + setName + "\'"; // NON-NLS
986  }
987  return result;
988  }
989 
990  private FileSearchFiltering() {
991  // Class should not be instantiated
992  }
993 }

Copyright © 2012-2020 Basis Technology. Generated on: Wed Apr 8 2020
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.