19 package org.sleuthkit.autopsy.datasourcesummary.datamodel;
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.Collection;
25 import java.util.Collections;
26 import java.util.Comparator;
27 import java.util.Date;
28 import java.util.HashMap;
29 import java.util.HashSet;
30 import java.util.List;
33 import java.util.logging.Level;
34 import java.util.stream.Collectors;
35 import java.util.stream.Stream;
36 import org.apache.commons.lang3.StringUtils;
37 import org.apache.commons.lang3.tuple.Pair;
38 import org.openide.util.NbBundle.Messages;
47 import static org.
sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
48 import static org.
sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
57 private static final BlackboardArtifact.Type
TYPE_DEVICE_ATTACHED =
new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_DEVICE_ATTACHED);
58 private static final BlackboardArtifact.Type
TYPE_WEB_HISTORY =
new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_WEB_HISTORY);
60 private static final BlackboardAttribute.Type
TYPE_DATETIME =
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME);
61 private static final BlackboardAttribute.Type
TYPE_DATETIME_ACCESSED =
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED);
62 private static final BlackboardAttribute.Type
TYPE_DEVICE_ID =
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_ID);
63 private static final BlackboardAttribute.Type
TYPE_DEVICE_MAKE =
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE);
64 private static final BlackboardAttribute.Type
TYPE_DEVICE_MODEL =
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL);
65 private static final BlackboardAttribute.Type
TYPE_MESSAGE_TYPE =
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE);
66 private static final BlackboardAttribute.Type
TYPE_TEXT =
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_TEXT);
67 private static final BlackboardAttribute.Type
TYPE_DATETIME_RCVD =
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_RCVD);
68 private static final BlackboardAttribute.Type
TYPE_DATETIME_SENT =
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_SENT);
69 private static final BlackboardAttribute.Type
TYPE_DATETIME_START =
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_START);
70 private static final BlackboardAttribute.Type
TYPE_DATETIME_END =
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_END);
71 private static final BlackboardAttribute.Type
TYPE_DOMAIN =
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DOMAIN);
77 ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY.getTypeID(),
78 ARTIFACT_TYPE.TSK_MESSAGE.getTypeID(),
79 ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID(),
80 ARTIFACT_TYPE.TSK_CALLLOG.getTypeID(),
81 ARTIFACT_TYPE.TSK_DEVICE_ATTACHED.getTypeID(),
82 ARTIFACT_TYPE.TSK_WEB_HISTORY.getTypeID()
85 private static final Set<String>
DEVICE_EXCLUDE_LIST =
new HashSet<>(Arrays.asList(
"ROOT_HUB",
"ROOT_HUB20"));
86 private static final Set<String>
DOMAIN_EXCLUDE_LIST =
new HashSet<>(Arrays.asList(
"127.0.0.1",
"LOCALHOST"));
88 private static final long MS_PER_DAY = 1000 * 60 * 60 * 24;
94 private final java.util.logging.Logger
logger;
116 java.util.logging.Logger
logger) {
118 this.caseProvider = provider;
135 throw new IllegalArgumentException(
"Count must be greater than 0");
152 if (dataSource == null) {
153 return Collections.emptyList();
158 if (mostRecentAndGroups.getKey() == null || mostRecentAndGroups.getValue().size() == 0) {
159 return Collections.emptyList();
162 final long mostRecentMs = mostRecentAndGroups.getLeft();
163 Map<String, List<Long>> groups = mostRecentAndGroups.getRight();
165 return groups.entrySet().stream()
166 .map(entry ->
getDomainsResult(entry.getKey(), entry.getValue(), mostRecentMs))
167 .filter(result -> result != null)
169 .sorted((a, b) -> -Long.compare(a.getVisitTimes(), b.getVisitTimes()))
172 .collect(Collectors.toList());
188 Long thisMostRecentMs = null;
190 for (Long visitMs : visits) {
192 if (visitMs + DOMAIN_WINDOW_MS < mostRecentMs) {
198 thisMostRecentMs =
getMax(thisMostRecentMs, visitMs);
202 if (visitCount <= 0 || thisMostRecentMs == null) {
206 return new TopDomainsResult(domain, visitCount,
new Date(thisMostRecentMs));
225 List<BlackboardArtifact> artifacts = DataSourceInfoUtilities.getArtifacts(caseProvider.
get(),
TYPE_WEB_HISTORY,
228 Long mostRecentMs = null;
229 Map<String, List<Long>> domainVisits =
new HashMap<>();
231 for (BlackboardArtifact art : artifacts) {
232 Long artifactDateSecs = DataSourceInfoUtilities.getLongOrNull(art, TYPE_DATETIME_ACCESSED);
233 String domain = DataSourceInfoUtilities.getStringOrNull(art,
TYPE_DOMAIN);
237 if (artifactDateSecs == null || StringUtils.isBlank(domain) || DOMAIN_EXCLUDE_LIST.contains(domain.toUpperCase().trim())) {
241 Long artifactDateMs = artifactDateSecs * 1000;
244 mostRecentMs =
getMax(mostRecentMs, artifactDateMs);
247 domain = domain.toLowerCase().trim();
250 List<Long> domainVisitList = domainVisits.get(domain);
251 if (domainVisitList == null) {
252 domainVisitList =
new ArrayList<>();
253 domainVisits.put(domain, domainVisitList);
256 domainVisitList.add(artifactDateMs);
259 return Pair.of(mostRecentMs, domainVisits);
270 private static Long
getMax(Long num1, Long num2) {
273 }
else if (num2 == null) {
276 return num2 > num1 ? num2 : num1;
289 String searchString = DataSourceInfoUtilities.getStringOrNull(artifact,
TYPE_TEXT);
291 return (StringUtils.isNotBlank(searchString) && dateAccessed != null)
314 if (dataSource == null) {
315 return Collections.emptyList();
319 List<BlackboardArtifact> webSearchArtifacts = caseProvider.
get().getBlackboard()
320 .getArtifacts(ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY.getTypeID(), dataSource.getId());
323 Collection<List<TopWebSearchResult>> resultGroups = webSearchArtifacts
328 .filter(result -> result != null)
330 .collect(Collectors.groupingBy((result) -> result.getSearchString().toUpperCase()))
334 List<TopWebSearchResult> results = resultGroups
337 .map((list) -> list.stream().max(TOP_WEBSEARCH_RESULT_DATE_COMPARE).get())
339 .sorted(TOP_WEBSEARCH_RESULT_DATE_COMPARE.reversed())
342 .collect(Collectors.toList());
364 if (!translationService.
hasProvider() || StringUtils.isBlank(original)) {
368 String translated = null;
370 translated = translationService.
translate(original);
372 logger.log(Level.WARNING, String.format(
"There was an error translating text: '%s'", original), ex);
376 if (StringUtils.isBlank(translated)
377 || translated.toUpperCase().trim().equals(original.toUpperCase().trim())) {
399 public List<TopDeviceAttachedResult>
getRecentDevices(DataSource dataSource,
int count)
throws SleuthkitCaseProviderException, TskCoreException {
402 if (dataSource == null) {
403 return Collections.emptyList();
407 dataSource,
TYPE_DATETIME, DataSourceInfoUtilities.SortOrder.DESCENDING, 0)
411 DataSourceInfoUtilities.getStringOrNull(artifact,
TYPE_DEVICE_ID),
412 DataSourceInfoUtilities.getDateOrNull(artifact, TYPE_DATETIME),
419 return result.getDeviceModel() == null
420 || !DEVICE_EXCLUDE_LIST.contains(result.getDeviceModel().trim().toUpperCase());
423 .collect(Collectors.toList());
435 String type = DataSourceInfoUtilities.getStringOrNull(artifact,
TYPE_MESSAGE_TYPE);
436 Date date = DataSourceInfoUtilities.getDateOrNull(artifact,
TYPE_DATETIME);
437 return (StringUtils.isNotBlank(type) && date != null)
454 String type = messageType;
456 Date latestDate = null;
457 if (dateAttrs != null) {
458 latestDate = Stream.of(dateAttrs)
459 .map((attr) -> DataSourceInfoUtilities.getDateOrNull(artifact, attr))
460 .filter((date) -> date != null)
461 .max((a, b) -> a.compareTo(b))
465 return (StringUtils.isNotBlank(type) && latestDate != null)
486 "DataSourceUserActivitySummary_getRecentAccounts_emailMessage=Email Message",
487 "DataSourceUserActivitySummary_getRecentAccounts_calllogMessage=Call Log",})
488 public List<TopAccountResult>
getRecentAccounts(DataSource dataSource,
int count)
throws SleuthkitCaseProviderException, TskCoreException {
491 if (dataSource == null) {
492 return Collections.emptyList();
495 Stream<TopAccountResult> messageResults = caseProvider.
get().getBlackboard().getArtifacts(ARTIFACT_TYPE.TSK_MESSAGE.getTypeID(), dataSource.getId())
499 Stream<TopAccountResult> emailResults = caseProvider.
get().getBlackboard().getArtifacts(ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID(), dataSource.getId())
504 Bundle.DataSourceUserActivitySummary_getRecentAccounts_emailMessage(),
509 Stream<TopAccountResult> calllogResults = caseProvider.
get().getBlackboard().getArtifacts(ARTIFACT_TYPE.TSK_CALLLOG.getTypeID(), dataSource.getId())
514 Bundle.DataSourceUserActivitySummary_getRecentAccounts_calllogMessage(),
519 Stream<TopAccountResult> allResults = Stream.concat(messageResults, Stream.concat(emailResults, calllogResults));
522 Collection<List<TopAccountResult>> groupedResults = allResults
524 .filter(result -> result != null)
530 return groupedResults
533 .map((accountGroup) -> accountGroup.stream().max(TOP_ACCOUNT_RESULT_DATE_COMPARE).get())
535 .sorted(TOP_ACCOUNT_RESULT_DATE_COMPARE.reversed())
539 .collect(Collectors.toList());
static final BlackboardAttribute.Type TYPE_DATETIME
TopDeviceAttachedResult(String deviceId, Date dateAccessed, String deviceMake, String deviceModel)
static final Comparator< TopWebSearchResult > TOP_WEBSEARCH_RESULT_DATE_COMPARE
final java.util.logging.Logger logger
static final BlackboardAttribute.Type TYPE_DEVICE_MODEL
SleuthkitCaseProvider DEFAULT
static final BlackboardAttribute.Type TYPE_DOMAIN
static final BlackboardAttribute.Type TYPE_DEVICE_ID
static TopWebSearchResult getWebSearchResult(BlackboardArtifact artifact)
static final BlackboardAttribute.Type TYPE_DATETIME_START
synchronized String translate(String input)
void assertValidCount(int count)
static final long DOMAIN_WINDOW_MS
static Long getMax(Long num1, Long num2)
static final Set< String > DEVICE_EXCLUDE_LIST
List< TopAccountResult > getRecentAccounts(DataSource dataSource, int count)
static final BlackboardAttribute.Type TYPE_DEVICE_MAKE
Pair< Long, Map< String, List< Long > > > getDomainGroupsAndMostRecent(DataSource dataSource)
UserActivitySummary(SleuthkitCaseProvider provider, TextTranslationService translationService, java.util.logging.Logger logger)
List< TopWebSearchResult > getMostRecentWebSearches(DataSource dataSource, int count)
TopAccountResult(String accountType, Date lastAccess)
static TopAccountResult getMessageAccountResult(BlackboardArtifact artifact)
static final Set< String > DOMAIN_EXCLUDE_LIST
static final Set< Integer > ARTIFACT_UPDATE_TYPE_IDS
List< TopDeviceAttachedResult > getRecentDevices(DataSource dataSource, int count)
static TextTranslationService getInstance()
String getTranslationOrNull(String original)
TopDomainsResult getDomainsResult(String domain, List< Long > visits, long mostRecentMs)
static final long DOMAIN_WINDOW_DAYS
final TextTranslationService translationService
static final BlackboardAttribute.Type TYPE_DATETIME_SENT
static final long MS_PER_DAY
TopDomainsResult(String domain, Long visitTimes, Date lastVisit)
Set< Integer > getArtifactTypeIdsForRefresh()
static final BlackboardAttribute.Type TYPE_DATETIME_ACCESSED
static final Comparator< TopAccountResult > TOP_ACCOUNT_RESULT_DATE_COMPARE
synchronized boolean hasProvider()
final SleuthkitCaseProvider caseProvider
final String searchString
List< TopDomainsResult > getRecentDomains(DataSource dataSource, int count)
void setTranslatedResult(String translatedResult)
static final BlackboardAttribute.Type TYPE_DATETIME_END
static final BlackboardAttribute.Type TYPE_MESSAGE_TYPE
synchronized static Logger getLogger(String name)
static final BlackboardAttribute.Type TYPE_TEXT
TopWebSearchResult(String searchString, Date dateAccessed)
String getTranslatedResult()
static final BlackboardArtifact.Type TYPE_DEVICE_ATTACHED
static final BlackboardAttribute.Type TYPE_DATETIME_RCVD
static final BlackboardArtifact.Type TYPE_WEB_HISTORY
static TopAccountResult getAccountResult(BlackboardArtifact artifact, String messageType, BlackboardAttribute.Type...dateAttrs)