Autopsy  4.15.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
ResultFile.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.discovery;
20 
22 import org.sleuthkit.datamodel.AbstractFile;
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;
32 import org.sleuthkit.datamodel.BlackboardArtifact;
33 import org.sleuthkit.datamodel.ContentTag;
34 import org.sleuthkit.datamodel.HashUtility;
35 import org.sleuthkit.datamodel.Tag;
36 import org.sleuthkit.datamodel.TskCoreException;
37 import org.sleuthkit.datamodel.TskData;
38 
42 class ResultFile {
43 
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;
56 
62  ResultFile(AbstractFile abstractFile) {
63  try {
64  //call get uniquePath to cache the path
65  abstractFile.getUniquePath();
66  } catch (TskCoreException ignored) {
67  //path wasnt cached will likely be called on EDT later JIRA-5972
68  }
69  //store the file the ResultFile was created for as the first value in the instances list
70  instances.add(abstractFile);
71  if (abstractFile.isDirNameFlagSet(TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC)) {
72  deleted = true;
73  }
74  updateScoreAndDescription(abstractFile);
75  this.frequency = FileSearchData.Frequency.UNKNOWN;
76  keywordListNames = new ArrayList<>();
77  hashSetNames = new ArrayList<>();
78  tagNames = new ArrayList<>();
79  interestingSetNames = new ArrayList<>();
80  objectDetectedNames = new ArrayList<>();
81  fileType = FileType.fromMIMEtype(abstractFile.getMIMEType());
82  }
83 
89  FileSearchData.Frequency getFrequency() {
90  return frequency;
91  }
92 
98  void setFrequency(FileSearchData.Frequency frequency) {
99  this.frequency = frequency;
100  }
101 
108  void addDuplicate(AbstractFile duplicate) {
109  if (deleted && !duplicate.isDirNameFlagSet(TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC)) {
110  deleted = false;
111  }
112  if (fileType == FileType.OTHER) {
113  fileType = FileType.fromMIMEtype(duplicate.getMIMEType());
114  }
115  updateScoreAndDescription(duplicate);
116  try {
117  //call get uniquePath to cache the path
118  duplicate.getUniquePath();
119  } catch (TskCoreException ignored) {
120  //path wasnt cached will likely be called on EDT later JIRA-5972
121  }
122  instances.add(duplicate);
123  }
124 
131  DataResultViewerTable.Score getScore() {
132  return currentScore;
133  }
134 
140  String getScoreDescription() {
141  return scoreDescription;
142  }
143 
150  boolean isDeleted() {
151  return deleted;
152  }
153 
161  List<AbstractFile> getAllInstances() {
162  return Collections.unmodifiableList(instances);
163  }
164 
170  FileType getFileType() {
171  return fileType;
172  }
173 
179  void addKeywordListName(String keywordListName) {
180  if (!keywordListNames.contains(keywordListName)) {
181  keywordListNames.add(keywordListName);
182  }
183 
184  // Sort the list so the getKeywordListNames() will be consistent regardless of the order added
185  Collections.sort(keywordListNames);
186  }
187 
193  List<String> getKeywordListNames() {
194  return Collections.unmodifiableList(keywordListNames);
195  }
196 
202  void addHashSetName(String hashSetName) {
203  if (!hashSetNames.contains(hashSetName)) {
204  hashSetNames.add(hashSetName);
205  }
206 
207  // Sort the list so the getHashHitNames() will be consistent regardless of the order added
208  Collections.sort(hashSetNames);
209  }
210 
216  List<String> getHashSetNames() {
217  return Collections.unmodifiableList(hashSetNames);
218  }
219 
225  void addTagName(String tagName) {
226  if (!tagNames.contains(tagName)) {
227  tagNames.add(tagName);
228  }
229 
230  // Sort the list so the getTagNames() will be consistent regardless of the order added
231  Collections.sort(tagNames);
232  }
233 
239  List<String> getTagNames() {
240  return Collections.unmodifiableList(tagNames);
241  }
242 
248  void addInterestingSetName(String interestingSetName) {
249  if (!interestingSetNames.contains(interestingSetName)) {
250  interestingSetNames.add(interestingSetName);
251  }
252 
253  // Sort the list so the getInterestingSetNames() will be consistent regardless of the order added
254  Collections.sort(interestingSetNames);
255  }
256 
262  List<String> getInterestingSetNames() {
263  return Collections.unmodifiableList(interestingSetNames);
264  }
265 
271  void addObjectDetectedName(String objectDetectedName) {
272  if (!objectDetectedNames.contains(objectDetectedName)) {
273  objectDetectedNames.add(objectDetectedName);
274  }
275 
276  // Sort the list so the getObjectDetectedNames() will be consistent regardless of the order added
277  Collections.sort(objectDetectedNames);
278  }
279 
285  List<String> getObjectDetectedNames() {
286  return Collections.unmodifiableList(objectDetectedNames);
287  }
288 
294  AbstractFile getFirstInstance() {
295  return instances.get(0);
296  }
297 
298  @Override
299  public String toString() {
300  return getFirstInstance().getName() + "(" + getFirstInstance().getId() + ") - "
301  + getFirstInstance().getSize() + ", " + getFirstInstance().getParentPath() + ", "
302  + getFirstInstance().getDataSourceObjectId() + ", " + frequency.toString() + ", "
303  + String.join(",", keywordListNames) + ", " + getFirstInstance().getMIMEType();
304  }
305 
306  @Override
307  public int hashCode() {
308  if (this.getFirstInstance().getMd5Hash() == null
309  || HashUtility.isNoDataMd5(this.getFirstInstance().getMd5Hash())
310  || !HashUtility.isValidMd5Hash(this.getFirstInstance().getMd5Hash())) {
311  return super.hashCode();
312  } else {
313  //if the file has a valid MD5 use the hashcode of the MD5 for deduping files with the same MD5
314  return this.getFirstInstance().getMd5Hash().hashCode();
315  }
316 
317  }
318 
319  @Override
320  public boolean equals(Object obj) {
321  if (!(obj instanceof ResultFile)
322  || this.getFirstInstance().getMd5Hash() == null
323  || HashUtility.isNoDataMd5(this.getFirstInstance().getMd5Hash())
324  || !HashUtility.isValidMd5Hash(this.getFirstInstance().getMd5Hash())) {
325  return super.equals(obj);
326  } else {
327  //if the file has a valid MD5 compare use the MD5 for equality check
328  return this.getFirstInstance().getMd5Hash().equals(((ResultFile) obj).getFirstInstance().getMd5Hash());
329  }
330  }
331 
337  private List<ContentTag> getContentTagsFromDatabase(AbstractFile file) {
338  List<ContentTag> tags = new ArrayList<>();
339  try {
340  tags.addAll(Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsByContent(file));
341  } catch (TskCoreException | NoCurrentCaseException ex) {
342  logger.log(Level.SEVERE, "Failed to get tags for file " + file.getName(), ex);
343  }
344  return tags;
345  }
346 
347  @NbBundle.Messages({
348  "ResultFile.score.notableFile.description=At least one instance of the file was recognized as notable.",
349  "ResultFile.score.interestingResult.description=At least one instance of the file has an interesting result associated with it.",
350  "ResultFile.score.taggedFile.description=At least one instance of the file has been tagged.",
351  "ResultFile.score.notableTaggedFile.description=At least one instance of the file is tagged with a notable tag."})
352  private void updateScoreAndDescription(AbstractFile file) {
353  if (currentScore == DataResultViewerTable.Score.NOTABLE_SCORE) {
354  //already notable can return
355  return;
356  }
357  if (file.getKnown() == TskData.FileKnown.BAD) {
358  currentScore = DataResultViewerTable.Score.NOTABLE_SCORE;
359  scoreDescription = Bundle.ResultFile_score_notableFile_description();
360  return;
361  }
362  try {
363  if (currentScore == DataResultViewerTable.Score.NO_SCORE && !file.getArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT).isEmpty()) {
364  currentScore = DataResultViewerTable.Score.INTERESTING_SCORE;
365  scoreDescription = Bundle.ResultFile_score_interestingResult_description();
366  }
367  } catch (TskCoreException ex) {
368  logger.log(Level.WARNING, "Error getting artifacts for file: " + file.getName(), ex);
369  }
370  List<ContentTag> tags = getContentTagsFromDatabase(file);
371  if (!tags.isEmpty()) {
372  currentScore = DataResultViewerTable.Score.INTERESTING_SCORE;
373  scoreDescription = Bundle.ResultFile_score_taggedFile_description();
374  for (Tag tag : tags) {
375  if (tag.getName().getKnownStatus() == TskData.FileKnown.BAD) {
376  currentScore = DataResultViewerTable.Score.NOTABLE_SCORE;
377  scoreDescription = Bundle.ResultFile_score_notableTaggedFile_description();
378  return;
379  }
380  }
381  }
382  }
383 }

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