Autopsy  4.17.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 DATETIME_ATT = new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME);
55  private final static BlackboardAttribute.Type ASSOCATED_ATT = new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT);
56  private final static BlackboardAttribute.Type EMAIL_FROM_ATT = new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL_FROM);
57  private final static BlackboardAttribute.Type MSG_DATEIME_SENT_ATT = new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_SENT);
58  private final static BlackboardArtifact.Type ASSOCATED_OBJ_ART = new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT);
59 
60  private static final DateFormat DATETIME_FORMAT = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss", Locale.getDefault());
61 
62  private static final Set<Integer> ARTIFACT_UPDATE_TYPE_IDS = new HashSet<>(Arrays.asList(
63  ARTIFACT_TYPE.TSK_RECENT_OBJECT.getTypeID(),
64  ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID(),
65  ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT.getTypeID(),
66  ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID(),
67  ARTIFACT_TYPE.TSK_MESSAGE.getTypeID()
68  ));
69 
71 
75  public RecentFilesSummary() {
77  }
78 
85  if (provider == null) {
86  throw new IllegalArgumentException("Unable to construct RecentFileSummary object. SleuthkitCaseProvider cannot be null");
87  }
88 
89  this.provider = provider;
90  }
91 
92  @Override
93  public Set<Integer> getArtifactTypeIdsForRefresh() {
95  }
96 
105  private <T extends RecentFileDetails> List<T> getSortedLimited(List<T> fileDetails, int limit) {
106  Map<String, T> fileDetailsMap = fileDetails.stream()
107  .filter(details -> details != null)
108  .collect(Collectors.toMap(
109  d -> d.getPath().toUpperCase(),
110  d -> d,
111  (d1, d2) -> Long.compare(d1.getDateAsLong(), d2.getDateAsLong()) > 0 ? d1 : d2));
112 
113  return fileDetailsMap.values().stream()
114  .sorted((a, b) -> -Long.compare(a.getDateAsLong(), b.getDateAsLong()))
115  .limit(limit)
116  .collect(Collectors.toList());
117  }
118 
126  private RecentFileDetails getRecentlyOpenedDocument(BlackboardArtifact artifact) {
127  String path = DataSourceInfoUtilities.getStringOrNull(artifact, PATH_ATT);
128  Long lastOpened = DataSourceInfoUtilities.getLongOrNull(artifact, DATETIME_ATT);
129 
130  if (StringUtils.isBlank(path) || lastOpened == null || lastOpened == 0) {
131  return null;
132  } else {
133  return new RecentFileDetails(artifact, path, lastOpened);
134  }
135  }
136 
151  public List<RecentFileDetails> getRecentlyOpenedDocuments(DataSource dataSource, int maxCount) throws SleuthkitCaseProviderException, TskCoreException {
152  if (dataSource == null) {
153  return Collections.emptyList();
154  }
155 
156  throwOnNonPositiveCount(maxCount);
157 
158  List<RecentFileDetails> details = provider.get().getBlackboard()
159  .getArtifacts(ARTIFACT_TYPE.TSK_RECENT_OBJECT.getTypeID(), dataSource.getId()).stream()
160  .map(art -> getRecentlyOpenedDocument(art))
161  .filter(d -> d != null)
162  .collect(Collectors.toList());
163 
164  return getSortedLimited(details, maxCount);
165  }
166 
174  private RecentDownloadDetails getRecentDownload(BlackboardArtifact artifact) {
175  Long accessedTime = DataSourceInfoUtilities.getLongOrNull(artifact, DATETIME_ACCESSED_ATT);
176  String domain = DataSourceInfoUtilities.getStringOrNull(artifact, DOMAIN_ATT);
177  String path = DataSourceInfoUtilities.getStringOrNull(artifact, PATH_ATT);
178 
179  if (StringUtils.isBlank(path) || accessedTime == null || accessedTime == 0) {
180  return null;
181  } else {
182  return new RecentDownloadDetails(artifact, path, accessedTime, domain);
183  }
184  }
185 
191  private void throwOnNonPositiveCount(int count) {
192  if (count < 1) {
193  throw new IllegalArgumentException("Invalid count: value must be greater than 0.");
194  }
195  }
196 
211  public List<RecentDownloadDetails> getRecentDownloads(DataSource dataSource, int maxCount) throws TskCoreException, SleuthkitCaseProviderException {
212  if (dataSource == null) {
213  return Collections.emptyList();
214  }
215 
216  throwOnNonPositiveCount(maxCount);
217 
218  List<RecentDownloadDetails> details = provider.get().getBlackboard()
219  .getArtifacts(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID(), dataSource.getId()).stream()
220  .map(art -> getRecentDownload(art))
221  .filter(d -> d != null)
222  .collect(Collectors.toList());
223 
224  return getSortedLimited(details, maxCount);
225  }
226 
239  public List<RecentAttachmentDetails> getRecentAttachments(DataSource dataSource, int maxCount) throws SleuthkitCaseProviderException, TskCoreException {
240  if (dataSource == null) {
241  return Collections.emptyList();
242  }
243 
244  throwOnNonPositiveCount(maxCount);
245 
246  SleuthkitCase skCase = provider.get();
247 
248  List<BlackboardArtifact> associatedArtifacts = skCase.getBlackboard()
249  .getArtifacts(ASSOCATED_OBJ_ART.getTypeID(), dataSource.getId());
250 
251  List<RecentAttachmentDetails> details = new ArrayList<>();
252  for (BlackboardArtifact artifact : associatedArtifacts) {
253  RecentAttachmentDetails thisDetails = getRecentAttachment(artifact, skCase);
254 
255  if (thisDetails != null) {
256  details.add(thisDetails);
257  }
258  }
259 
260  return getSortedLimited(details, maxCount);
261  }
262 
272  private RecentAttachmentDetails getRecentAttachment(BlackboardArtifact artifact, SleuthkitCase skCase) throws TskCoreException {
273  // get associated artifact or return no result
274  BlackboardAttribute attribute = artifact.getAttribute(ASSOCATED_ATT);
275  if (attribute == null) {
276  return null;
277  }
278 
279  // get associated message artifact if exists or return no result
280  BlackboardArtifact messageArtifact = skCase.getBlackboardArtifact(attribute.getValueLong());
281  if (messageArtifact == null || !isMessageArtifact(messageArtifact)) {
282  return null;
283  }
284 
285  // get abstract file if exists or return no result
286  Content content = artifact.getParent();
287  if (!(content instanceof AbstractFile)) {
288  return null;
289  }
290 
291  AbstractFile abstractFile = (AbstractFile) content;
292 
293  // get the path, sender, and date
294  String path = Paths.get(abstractFile.getParentPath(), abstractFile.getName()).toString();
295  String sender = DataSourceInfoUtilities.getStringOrNull(messageArtifact, EMAIL_FROM_ATT);
296  Long date = DataSourceInfoUtilities.getLongOrNull(messageArtifact, MSG_DATEIME_SENT_ATT);
297 
298  if (date == null || date == 0 || StringUtils.isBlank(path)) {
299  return null;
300  } else {
301  return new RecentAttachmentDetails(messageArtifact, path, date, sender);
302  }
303  }
304 
313  private boolean isMessageArtifact(BlackboardArtifact nodeArtifact) {
314  final int artifactTypeID = nodeArtifact.getArtifactTypeID();
315  return artifactTypeID == ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID()
316  || artifactTypeID == ARTIFACT_TYPE.TSK_MESSAGE.getTypeID();
317 
318  }
319 
323  public static class RecentFileDetails {
324 
325  private final String path;
326  private final long date;
327  private final BlackboardArtifact artifact;
328 
336  RecentFileDetails(BlackboardArtifact artifact, String path, long date) {
337  this.artifact = artifact;
338  this.path = path;
339  this.date = date;
340  }
341 
348  public String getDateAsString() {
349  return DATETIME_FORMAT.format(date * 1000);
350  }
351 
357  Long getDateAsLong() {
358  return date;
359  }
360 
366  public String getPath() {
367  return path;
368  }
369 
373  public BlackboardArtifact getArtifact() {
374  return artifact;
375  }
376  }
377 
381  public static class RecentDownloadDetails extends RecentFileDetails {
382 
383  private final String webDomain;
384 
393  RecentDownloadDetails(BlackboardArtifact artifact, String path, long date, String webDomain) {
394  super(artifact, path, date);
395  this.webDomain = webDomain;
396  }
397 
404  public String getWebDomain() {
405  return webDomain;
406  }
407  }
408 
412  public static class RecentAttachmentDetails extends RecentFileDetails {
413 
414  private final String sender;
415 
426  RecentAttachmentDetails(BlackboardArtifact artifact, String path, long date, String sender) {
427  super(artifact, path, date);
428  this.sender = sender;
429  }
430 
437  public String getSender() {
438  return sender;
439  }
440 
441  @Override
442  public boolean equals(Object obj) {
443  if (!(obj instanceof RecentAttachmentDetails)) {
444  return false;
445  }
446  RecentAttachmentDetails compareObj = (RecentAttachmentDetails) obj;
447 
448  return compareObj.getSender().equals(this.sender)
449  && compareObj.getPath().equals(this.getPath())
450  && compareObj.getDateAsLong().equals(this.getDateAsLong());
451  }
452 
453  @Override
454  public int hashCode() {
455  int hash = 5;
456  hash = 73 * hash + Objects.hashCode(this.sender);
457  return hash;
458  }
459  }
460 }
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: Tue Jan 19 2021
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.