Autopsy  4.13.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 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 
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  //store the file the ResultFile was created for as the first value in the instances list
64  instances.add(abstractFile);
65  if (abstractFile.isDirNameFlagSet(TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC)) {
66  deleted = true;
67  }
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());
76  }
77 
83  FileSearchData.Frequency getFrequency() {
84  return frequency;
85  }
86 
92  void setFrequency(FileSearchData.Frequency frequency) {
93  this.frequency = frequency;
94  }
95 
102  void addDuplicate(AbstractFile duplicate) {
103  if (deleted && !duplicate.isDirNameFlagSet(TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC)) {
104  deleted = false;
105  }
106  if (fileType == FileType.OTHER) {
107  fileType = FileType.fromMIMEtype(duplicate.getMIMEType());
108  }
109  updateScoreAndDescription(duplicate);
110  instances.add(duplicate);
111  }
112 
119  DataResultViewerTable.Score getScore() {
120  return currentScore;
121  }
122 
128  String getScoreDescription() {
129  return scoreDescription;
130  }
131 
138  boolean isDeleted() {
139  return deleted;
140  }
141 
149  List<AbstractFile> getAllInstances() {
150  return Collections.unmodifiableList(instances);
151  }
152 
158  FileType getFileType() {
159  return fileType;
160  }
161 
167  void addKeywordListName(String keywordListName) {
168  if (!keywordListNames.contains(keywordListName)) {
169  keywordListNames.add(keywordListName);
170  }
171 
172  // Sort the list so the getKeywordListNames() will be consistent regardless of the order added
173  Collections.sort(keywordListNames);
174  }
175 
181  List<String> getKeywordListNames() {
182  return Collections.unmodifiableList(keywordListNames);
183  }
184 
190  void addHashSetName(String hashSetName) {
191  if (!hashSetNames.contains(hashSetName)) {
192  hashSetNames.add(hashSetName);
193  }
194 
195  // Sort the list so the getHashHitNames() will be consistent regardless of the order added
196  Collections.sort(hashSetNames);
197  }
198 
204  List<String> getHashSetNames() {
205  return Collections.unmodifiableList(hashSetNames);
206  }
207 
213  void addTagName(String tagName) {
214  if (!tagNames.contains(tagName)) {
215  tagNames.add(tagName);
216  }
217 
218  // Sort the list so the getTagNames() will be consistent regardless of the order added
219  Collections.sort(tagNames);
220  }
221 
227  List<String> getTagNames() {
228  return Collections.unmodifiableList(tagNames);
229  }
230 
236  void addInterestingSetName(String interestingSetName) {
237  if (!interestingSetNames.contains(interestingSetName)) {
238  interestingSetNames.add(interestingSetName);
239  }
240 
241  // Sort the list so the getInterestingSetNames() will be consistent regardless of the order added
242  Collections.sort(interestingSetNames);
243  }
244 
250  List<String> getInterestingSetNames() {
251  return Collections.unmodifiableList(interestingSetNames);
252  }
253 
259  void addObjectDetectedName(String objectDetectedName) {
260  if (!objectDetectedNames.contains(objectDetectedName)) {
261  objectDetectedNames.add(objectDetectedName);
262  }
263 
264  // Sort the list so the getObjectDetectedNames() will be consistent regardless of the order added
265  Collections.sort(objectDetectedNames);
266  }
267 
273  List<String> getObjectDetectedNames() {
274  return Collections.unmodifiableList(objectDetectedNames);
275  }
276 
282  AbstractFile getFirstInstance() {
283  return instances.get(0);
284  }
285 
286  @Override
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();
292  }
293 
294  @Override
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();
300  } else {
301  //if the file has a valid MD5 use the hashcode of the MD5 for deduping files with the same MD5
302  return this.getFirstInstance().getMd5Hash().hashCode();
303  }
304 
305  }
306 
307  @Override
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);
314  } else {
315  //if the file has a valid MD5 compare use the MD5 for equality check
316  return this.getFirstInstance().getMd5Hash().equals(((ResultFile) obj).getFirstInstance().getMd5Hash());
317  }
318  }
319 
325  private List<ContentTag> getContentTagsFromDatabase(AbstractFile file) {
326  List<ContentTag> tags = new ArrayList<>();
327  try {
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);
331  }
332  return tags;
333  }
334 
335  @NbBundle.Messages({
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) {
342  //already notable can return
343  return;
344  }
345  if (file.getKnown() == TskData.FileKnown.BAD) {
346  currentScore = DataResultViewerTable.Score.NOTABLE_SCORE;
347  scoreDescription = Bundle.ResultFile_score_notableFile_description();
348  return;
349  }
350  try {
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();
354  }
355  } catch (TskCoreException ex) {
356  logger.log(Level.WARNING, "Error getting artifacts for file: " + file.getName(), ex);
357  }
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();
366  return;
367  }
368  }
369  }
370  }
371 }

Copyright © 2012-2019 Basis Technology. Generated on: Tue Jan 7 2020
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.