19 package org.sleuthkit.autopsy.filequery;
23 import java.util.ArrayList;
24 import java.util.Collections;
25 import java.util.List;
26 import java.util.logging.Level;
27 import org.openide.util.NbBundle;
44 private final static Logger logger = Logger.getLogger(ResultFile.class.getName());
45 private FileSearchData.Frequency frequency;
46 private final List<String> keywordListNames;
47 private final List<String> hashSetNames;
48 private final List<String> tagNames;
49 private final List<String> interestingSetNames;
50 private final List<String> objectDetectedNames;
51 private final List<AbstractFile> instances =
new ArrayList<>();
52 private DataResultViewerTable.Score currentScore = DataResultViewerTable.Score.NO_SCORE;
53 private String scoreDescription = null;
54 private boolean deleted =
false;
55 private FileType fileType;
62 ResultFile(AbstractFile abstractFile) {
64 instances.add(abstractFile);
65 if (abstractFile.isDirNameFlagSet(TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC)) {
68 updateScoreAndDescription(abstractFile);
69 this.frequency = FileSearchData.Frequency.UNKNOWN;
70 keywordListNames =
new ArrayList<>();
71 hashSetNames =
new ArrayList<>();
72 tagNames =
new ArrayList<>();
73 interestingSetNames =
new ArrayList<>();
74 objectDetectedNames =
new ArrayList<>();
75 fileType = FileType.fromMIMEtype(abstractFile.getMIMEType());
83 FileSearchData.Frequency getFrequency() {
92 void setFrequency(FileSearchData.Frequency frequency) {
93 this.frequency = frequency;
102 void addDuplicate(AbstractFile duplicate) {
103 if (deleted && !duplicate.isDirNameFlagSet(TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC)) {
106 if (fileType == FileType.OTHER) {
107 fileType = FileType.fromMIMEtype(duplicate.getMIMEType());
109 updateScoreAndDescription(duplicate);
110 instances.add(duplicate);
119 DataResultViewerTable.Score getScore() {
128 String getScoreDescription() {
129 return scoreDescription;
138 boolean isDeleted() {
149 List<AbstractFile> getAllInstances() {
150 return Collections.unmodifiableList(instances);
158 FileType getFileType() {
167 void addKeywordListName(String keywordListName) {
168 if (!keywordListNames.contains(keywordListName)) {
169 keywordListNames.add(keywordListName);
173 Collections.sort(keywordListNames);
181 List<String> getKeywordListNames() {
182 return Collections.unmodifiableList(keywordListNames);
190 void addHashSetName(String hashSetName) {
191 if (!hashSetNames.contains(hashSetName)) {
192 hashSetNames.add(hashSetName);
196 Collections.sort(hashSetNames);
204 List<String> getHashSetNames() {
205 return Collections.unmodifiableList(hashSetNames);
213 void addTagName(String tagName) {
214 if (!tagNames.contains(tagName)) {
215 tagNames.add(tagName);
219 Collections.sort(tagNames);
227 List<String> getTagNames() {
228 return Collections.unmodifiableList(tagNames);
236 void addInterestingSetName(String interestingSetName) {
237 if (!interestingSetNames.contains(interestingSetName)) {
238 interestingSetNames.add(interestingSetName);
242 Collections.sort(interestingSetNames);
250 List<String> getInterestingSetNames() {
251 return Collections.unmodifiableList(interestingSetNames);
259 void addObjectDetectedName(String objectDetectedName) {
260 if (!objectDetectedNames.contains(objectDetectedName)) {
261 objectDetectedNames.add(objectDetectedName);
265 Collections.sort(objectDetectedNames);
273 List<String> getObjectDetectedNames() {
274 return Collections.unmodifiableList(objectDetectedNames);
282 AbstractFile getFirstInstance() {
283 return instances.get(0);
287 public String toString() {
288 return getFirstInstance().getName() +
"(" + getFirstInstance().getId() +
") - "
289 + getFirstInstance().getSize() +
", " + getFirstInstance().getParentPath() +
", "
290 + getFirstInstance().getDataSourceObjectId() +
", " + frequency.toString() +
", "
291 + String.join(
",", keywordListNames) +
", " + getFirstInstance().getMIMEType();
295 public int hashCode() {
296 if (this.getFirstInstance().getMd5Hash() == null
297 || HashUtility.isNoDataMd5(
this.getFirstInstance().getMd5Hash())
298 || !HashUtility.isValidMd5Hash(
this.getFirstInstance().getMd5Hash())) {
299 return super.hashCode();
302 return this.getFirstInstance().getMd5Hash().hashCode();
308 public boolean equals(Object obj) {
309 if (!(obj instanceof ResultFile)
310 || this.getFirstInstance().getMd5Hash() == null
311 || HashUtility.isNoDataMd5(
this.getFirstInstance().getMd5Hash())
312 || !HashUtility.isValidMd5Hash(
this.getFirstInstance().getMd5Hash())) {
313 return super.equals(obj);
316 return this.getFirstInstance().getMd5Hash().equals(((ResultFile) obj).getFirstInstance().getMd5Hash());
325 private List<ContentTag> getContentTagsFromDatabase(AbstractFile file) {
326 List<ContentTag> tags =
new ArrayList<>();
328 tags.addAll(Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsByContent(file));
329 }
catch (TskCoreException | NoCurrentCaseException ex) {
330 logger.log(Level.SEVERE,
"Failed to get tags for file " + file.getName(), ex);
336 "ResultFile.score.notableFile.description=At least one instance of the file was recognized as notable.",
337 "ResultFile.score.interestingResult.description=At least one instance of the file has an interesting result associated with it.",
338 "ResultFile.score.taggedFile.description=At least one instance of the file has been tagged.",
339 "ResultFile.score.notableTaggedFile.description=At least one instance of the file is tagged with a notable tag."})
340 private void updateScoreAndDescription(AbstractFile file) {
341 if (currentScore == DataResultViewerTable.Score.NOTABLE_SCORE) {
345 if (file.getKnown() == TskData.FileKnown.BAD) {
346 currentScore = DataResultViewerTable.Score.NOTABLE_SCORE;
347 scoreDescription = Bundle.ResultFile_score_notableFile_description();
351 if (currentScore == DataResultViewerTable.Score.NO_SCORE && !file.getArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT).isEmpty()) {
352 currentScore = DataResultViewerTable.Score.INTERESTING_SCORE;
353 scoreDescription = Bundle.ResultFile_score_interestingResult_description();
355 }
catch (TskCoreException ex) {
356 logger.log(Level.WARNING,
"Error getting artifacts for file: " + file.getName(), ex);
358 List<ContentTag> tags = getContentTagsFromDatabase(file);
359 if (!tags.isEmpty()) {
360 currentScore = DataResultViewerTable.Score.INTERESTING_SCORE;
361 scoreDescription = Bundle.ResultFile_score_taggedFile_description();
362 for (Tag tag : tags) {
363 if (tag.getName().getKnownStatus() == TskData.FileKnown.BAD) {
364 currentScore = DataResultViewerTable.Score.NOTABLE_SCORE;
365 scoreDescription = Bundle.ResultFile_score_notableTaggedFile_description();