Autopsy  4.19.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
RecentFilesSummary.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 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.datasourcesummary.datamodel;
20 
22 import java.nio.file.Paths;
23 import java.text.DateFormat;
24 import java.text.SimpleDateFormat;
25 import java.util.ArrayList;
26 import java.util.Arrays;
27 import java.util.Collections;
28 import java.util.HashSet;
29 import java.util.List;
30 import java.util.Locale;
31 import java.util.Map;
32 import java.util.Objects;
33 import java.util.Set;
34 import java.util.stream.Collectors;
35 import org.apache.commons.lang.StringUtils;
36 import org.sleuthkit.datamodel.AbstractFile;
37 import org.sleuthkit.datamodel.BlackboardArtifact;
38 import org.sleuthkit.datamodel.BlackboardAttribute;
39 import org.sleuthkit.datamodel.Content;
40 import org.sleuthkit.datamodel.DataSource;
41 import org.sleuthkit.datamodel.SleuthkitCase;
42 import org.sleuthkit.datamodel.TskCoreException;
44 import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
45 
50 
51  private final static BlackboardAttribute.Type DATETIME_ACCESSED_ATT = new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED);
52  private final static BlackboardAttribute.Type DOMAIN_ATT = new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN);
53  private final static BlackboardAttribute.Type PATH_ATT = new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH);
54  private final static BlackboardAttribute.Type ASSOCATED_ATT = new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT);
55  private final static BlackboardAttribute.Type EMAIL_FROM_ATT = new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL_FROM);
56  private final static BlackboardAttribute.Type MSG_DATEIME_SENT_ATT = new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_SENT);
57  private final static BlackboardArtifact.Type ASSOCATED_OBJ_ART = new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT);
58 
59  private static final DateFormat DATETIME_FORMAT = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss", Locale.getDefault());
60 
61  private static final Set<Integer> ARTIFACT_UPDATE_TYPE_IDS = new HashSet<>(Arrays.asList(
62  ARTIFACT_TYPE.TSK_RECENT_OBJECT.getTypeID(),
63  ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID(),
64  ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT.getTypeID(),
65  ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID(),
66  ARTIFACT_TYPE.TSK_MESSAGE.getTypeID()
67  ));
68 
70 
74  public RecentFilesSummary() {
76  }
77 
84  if (provider == null) {
85  throw new IllegalArgumentException("Unable to construct RecentFileSummary object. SleuthkitCaseProvider cannot be null");
86  }
87 
88  this.provider = provider;
89  }
90 
91  @Override
92  public Set<Integer> getArtifactTypeIdsForRefresh() {
94  }
95 
104  private <T extends RecentFileDetails> List<T> getSortedLimited(List<T> fileDetails, int limit) {
105  Map<String, T> fileDetailsMap = fileDetails.stream()
106  .filter(details -> details != null)
107  .collect(Collectors.toMap(
108  d -> d.getPath().toUpperCase(),
109  d -> d,
110  (d1, d2) -> Long.compare(d1.getDateAsLong(), d2.getDateAsLong()) > 0 ? d1 : d2));
111 
112  return fileDetailsMap.values().stream()
113  .sorted((a, b) -> -Long.compare(a.getDateAsLong(), b.getDateAsLong()))
114  .limit(limit)
115  .collect(Collectors.toList());
116  }
117 
125  private RecentFileDetails getRecentlyOpenedDocument(BlackboardArtifact artifact) {
126  String path = DataSourceInfoUtilities.getStringOrNull(artifact, PATH_ATT);
127  Long lastOpened = DataSourceInfoUtilities.getLongOrNull(artifact, DATETIME_ACCESSED_ATT);
128 
129  if (StringUtils.isBlank(path) || lastOpened == null || lastOpened == 0) {
130  return null;
131  } else {
132  return new RecentFileDetails(artifact, path, lastOpened);
133  }
134  }
135 
150  public List<RecentFileDetails> getRecentlyOpenedDocuments(DataSource dataSource, int maxCount) throws SleuthkitCaseProviderException, TskCoreException {
151  if (dataSource == null) {
152  return Collections.emptyList();
153  }
154 
155  throwOnNonPositiveCount(maxCount);
156 
157  List<RecentFileDetails> details = provider.get().getBlackboard()
158  .getArtifacts(ARTIFACT_TYPE.TSK_RECENT_OBJECT.getTypeID(), dataSource.getId()).stream()
159  .map(art -> getRecentlyOpenedDocument(art))
160  .filter(d -> d != null)
161  .collect(Collectors.toList());
162 
163  return getSortedLimited(details, maxCount);
164  }
165 
173  private RecentDownloadDetails getRecentDownload(BlackboardArtifact artifact) {
174  Long accessedTime = DataSourceInfoUtilities.getLongOrNull(artifact, DATETIME_ACCESSED_ATT);
175  String domain = DataSourceInfoUtilities.getStringOrNull(artifact, DOMAIN_ATT);
176  String path = DataSourceInfoUtilities.getStringOrNull(artifact, PATH_ATT);
177 
178  if (StringUtils.isBlank(path) || accessedTime == null || accessedTime == 0) {
179  return null;
180  } else {
181  return new RecentDownloadDetails(artifact, path, accessedTime, domain);
182  }
183  }
184 
190  private void throwOnNonPositiveCount(int count) {
191  if (count < 1) {
192  throw new IllegalArgumentException("Invalid count: value must be greater than 0.");
193  }
194  }
195 
210  public List<RecentDownloadDetails> getRecentDownloads(DataSource dataSource, int maxCount) throws TskCoreException, SleuthkitCaseProviderException {
211  if (dataSource == null) {
212  return Collections.emptyList();
213  }
214 
215  throwOnNonPositiveCount(maxCount);
216 
217  List<RecentDownloadDetails> details = provider.get().getBlackboard()
218  .getArtifacts(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID(), dataSource.getId()).stream()
219  .map(art -> getRecentDownload(art))
220  .filter(d -> d != null)
221  .collect(Collectors.toList());
222 
223  return getSortedLimited(details, maxCount);
224  }
225 
238  public List<RecentAttachmentDetails> getRecentAttachments(DataSource dataSource, int maxCount) throws SleuthkitCaseProviderException, TskCoreException {
239  if (dataSource == null) {
240  return Collections.emptyList();
241  }
242 
243  throwOnNonPositiveCount(maxCount);
244 
245  SleuthkitCase skCase = provider.get();
246 
247  List<BlackboardArtifact> associatedArtifacts = skCase.getBlackboard()
248  .getArtifacts(ASSOCATED_OBJ_ART.getTypeID(), dataSource.getId());
249 
250  List<RecentAttachmentDetails> details = new ArrayList<>();
251  for (BlackboardArtifact artifact : associatedArtifacts) {
252  RecentAttachmentDetails thisDetails = getRecentAttachment(artifact, skCase);
253 
254  if (thisDetails != null) {
255  details.add(thisDetails);
256  }
257  }
258 
259  return getSortedLimited(details, maxCount);
260  }
261 
271  private RecentAttachmentDetails getRecentAttachment(BlackboardArtifact artifact, SleuthkitCase skCase) throws TskCoreException {
272  // get associated artifact or return no result
273  BlackboardAttribute attribute = artifact.getAttribute(ASSOCATED_ATT);
274  if (attribute == null) {
275  return null;
276  }
277 
278  // get associated message artifact if exists or return no result
279  BlackboardArtifact messageArtifact = skCase.getBlackboardArtifact(attribute.getValueLong());
280  if (messageArtifact == null || !isMessageArtifact(messageArtifact)) {
281  return null;
282  }
283 
284  // get abstract file if exists or return no result
285  Content content = artifact.getParent();
286  if (!(content instanceof AbstractFile)) {
287  return null;
288  }
289 
290  AbstractFile abstractFile = (AbstractFile) content;
291 
292  // get the path, sender, and date
293  String path = Paths.get(abstractFile.getParentPath(), abstractFile.getName()).toString();
294  String sender = DataSourceInfoUtilities.getStringOrNull(messageArtifact, EMAIL_FROM_ATT);
295  Long date = DataSourceInfoUtilities.getLongOrNull(messageArtifact, MSG_DATEIME_SENT_ATT);
296 
297  if (date == null || date == 0 || StringUtils.isBlank(path)) {
298  return null;
299  } else {
300  return new RecentAttachmentDetails(messageArtifact, path, date, sender);
301  }
302  }
303 
312  private boolean isMessageArtifact(BlackboardArtifact nodeArtifact) {
313  final int artifactTypeID = nodeArtifact.getArtifactTypeID();
314  return artifactTypeID == ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID()
315  || artifactTypeID == ARTIFACT_TYPE.TSK_MESSAGE.getTypeID();
316 
317  }
318 
322  public static class RecentFileDetails {
323 
324  private final String path;
325  private final long date;
326  private final BlackboardArtifact artifact;
327 
335  RecentFileDetails(BlackboardArtifact artifact, String path, long date) {
336  this.artifact = artifact;
337  this.path = path;
338  this.date = date;
339  }
340 
347  public String getDateAsString() {
348  return DATETIME_FORMAT.format(date * 1000);
349  }
350 
356  public Long getDateAsLong() {
357  return date;
358  }
359 
365  public String getPath() {
366  return path;
367  }
368 
372  public BlackboardArtifact getArtifact() {
373  return artifact;
374  }
375  }
376 
380  public static class RecentDownloadDetails extends RecentFileDetails {
381 
382  private final String webDomain;
383 
392  RecentDownloadDetails(BlackboardArtifact artifact, String path, long date, String webDomain) {
393  super(artifact, path, date);
394  this.webDomain = webDomain;
395  }
396 
403  public String getWebDomain() {
404  return webDomain;
405  }
406  }
407 
411  public static class RecentAttachmentDetails extends RecentFileDetails {
412 
413  private final String sender;
414 
425  RecentAttachmentDetails(BlackboardArtifact artifact, String path, long date, String sender) {
426  super(artifact, path, date);
427  this.sender = sender;
428  }
429 
436  public String getSender() {
437  return sender;
438  }
439 
440  @Override
441  public boolean equals(Object obj) {
442  if (!(obj instanceof RecentAttachmentDetails)) {
443  return false;
444  }
445  RecentAttachmentDetails compareObj = (RecentAttachmentDetails) obj;
446 
447  return compareObj.getSender().equals(this.sender)
448  && compareObj.getPath().equals(this.getPath())
449  && compareObj.getDateAsLong().equals(this.getDateAsLong());
450  }
451 
452  @Override
453  public int hashCode() {
454  int hash = 5;
455  hash = 73 * hash + Objects.hashCode(this.sender);
456  return hash;
457  }
458  }
459 }
List< RecentFileDetails > getRecentlyOpenedDocuments(DataSource dataSource, int maxCount)
RecentDownloadDetails getRecentDownload(BlackboardArtifact artifact)
List< RecentDownloadDetails > getRecentDownloads(DataSource dataSource, int maxCount)
RecentAttachmentDetails getRecentAttachment(BlackboardArtifact artifact, SleuthkitCase skCase)
List< RecentAttachmentDetails > getRecentAttachments(DataSource dataSource, int maxCount)
RecentFileDetails getRecentlyOpenedDocument(BlackboardArtifact artifact)

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