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.function.Function;
34 import java.util.logging.Level;
35 import java.util.stream.Collectors;
36 import java.util.stream.Stream;
37 import org.apache.commons.lang3.StringUtils;
38 import org.apache.commons.lang3.tuple.Pair;
39 import org.openide.util.NbBundle.Messages;
48 import static org.
sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
49 import static org.
sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
65 if (pathList.size() < 2) {
69 String rootParent = pathList.get(0).toUpperCase();
70 if (
"PROGRAM FILES".equals(rootParent) ||
"PROGRAM FILES (X86)".equals(rootParent)) {
71 return pathList.get(1);
78 for (String pathEl : pathList) {
79 String uppered = pathEl.toUpperCase();
80 if (
"APPLICATION DATA".equals(uppered) ||
"APPDATA".equals(uppered)) {
88 private static final BlackboardArtifact.Type
TYPE_DEVICE_ATTACHED =
new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_DEVICE_ATTACHED);
89 private static final BlackboardArtifact.Type
TYPE_WEB_HISTORY =
new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_WEB_HISTORY);
91 private static final BlackboardAttribute.Type
TYPE_DATETIME =
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME);
92 private static final BlackboardAttribute.Type
TYPE_DATETIME_ACCESSED =
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED);
93 private static final BlackboardAttribute.Type
TYPE_DEVICE_ID =
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_ID);
94 private static final BlackboardAttribute.Type
TYPE_DEVICE_MAKE =
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE);
95 private static final BlackboardAttribute.Type
TYPE_DEVICE_MODEL =
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL);
96 private static final BlackboardAttribute.Type
TYPE_MESSAGE_TYPE =
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE);
97 private static final BlackboardAttribute.Type
TYPE_TEXT =
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_TEXT);
98 private static final BlackboardAttribute.Type
TYPE_DATETIME_RCVD =
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_RCVD);
99 private static final BlackboardAttribute.Type
TYPE_DATETIME_SENT =
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_SENT);
100 private static final BlackboardAttribute.Type
TYPE_DATETIME_START =
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_START);
101 private static final BlackboardAttribute.Type
TYPE_DATETIME_END =
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_END);
102 private static final BlackboardAttribute.Type
TYPE_DOMAIN =
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DOMAIN);
103 private static final BlackboardAttribute.Type
TYPE_PROG_NAME =
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME);
104 private static final BlackboardAttribute.Type
TYPE_PATH =
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH);
105 private static final BlackboardAttribute.Type
TYPE_COUNT =
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_COUNT);
120 int runTimesCompare =
nullableCompare(a.getRunTimes(), b.getRunTimes());
121 if (runTimesCompare != 0) {
122 return -runTimesCompare;
128 a.getLastAccessed() == null ? null : a.getLastAccessed().getTime(),
129 b.getLastAccessed() == null ? null : b.getLastAccessed().getTime());
131 if (lastRunCompare != 0) {
132 return -lastRunCompare;
136 return (a.getProgramName() == null ?
"" : a.getProgramName())
137 .compareToIgnoreCase((b.getProgramName() == null ?
"" : b.getProgramName()));
140 private static final Set<String>
DEVICE_EXCLUDE_LIST =
new HashSet<>(Arrays.asList(
"ROOT_HUB",
"ROOT_HUB20"));
141 private static final Set<String>
DOMAIN_EXCLUDE_LIST =
new HashSet<>(Arrays.asList(
"127.0.0.1",
"LOCALHOST"));
149 private final java.util.logging.Logger
logger;
171 java.util.logging.Logger
logger) {
173 this.caseProvider = provider;
185 throw new IllegalArgumentException(
"Count must be greater than 0");
198 if (strPath == null) {
202 List<String> pathEls =
new ArrayList<>(Arrays.asList(applicationName));
204 File file =
new File(strPath);
205 while (file != null &&
org.apache.commons.lang.StringUtils.isNotBlank(file.getName())) {
206 pathEls.add(file.getName());
207 file = file.getParentFile();
210 Collections.reverse(pathEls);
212 for (Function<List<String>, String> matchEntry : SHORT_FOLDER_MATCHERS) {
213 String result = matchEntry.apply(pathEls);
214 if (
org.apache.commons.lang.StringUtils.isNotBlank(result)) {
235 if (dataSource == null) {
236 return Collections.emptyList();
241 if (mostRecentAndGroups.getKey() == null || mostRecentAndGroups.getValue().size() == 0) {
242 return Collections.emptyList();
245 final long mostRecentMs = mostRecentAndGroups.getLeft();
246 Map<String, List<Pair<BlackboardArtifact, Long>>> groups = mostRecentAndGroups.getRight();
248 return groups.entrySet().stream()
249 .map(entry ->
getDomainsResult(entry.getKey(), entry.getValue(), mostRecentMs))
250 .filter(result -> result != null)
252 .sorted((a, b) -> -Long.compare(a.getVisitTimes(), b.getVisitTimes()))
255 .collect(Collectors.toList());
272 Long thisMostRecentMs = null;
273 BlackboardArtifact thisMostRecentArtifact = null;
275 for (Pair<BlackboardArtifact, Long> visitInstance : visits) {
276 BlackboardArtifact artifact = visitInstance.getLeft();
277 Long visitMs = visitInstance.getRight();
279 if (visitMs == null || visitMs + DOMAIN_WINDOW_MS < mostRecentMs) {
285 if (thisMostRecentMs == null || visitMs > thisMostRecentMs) {
286 thisMostRecentMs = visitMs;
287 thisMostRecentArtifact = artifact;
289 thisMostRecentMs =
getMax(thisMostRecentMs, visitMs);
293 if (visitCount <= 0 || thisMostRecentMs == null) {
297 return new TopDomainsResult(domain, visitCount,
new Date(thisMostRecentMs), thisMostRecentArtifact);
319 Long mostRecentMs = null;
320 Map<String, List<Pair<BlackboardArtifact, Long>>> domainVisits =
new HashMap<>();
322 for (BlackboardArtifact art : artifacts) {
328 if (artifactDateSecs == null || StringUtils.isBlank(domain) || DOMAIN_EXCLUDE_LIST.contains(domain.toUpperCase().trim())) {
332 Long artifactDateMs = artifactDateSecs * 1000;
335 mostRecentMs =
getMax(mostRecentMs, artifactDateMs);
338 domain = domain.toLowerCase().trim();
341 List<Pair<BlackboardArtifact, Long>> domainVisitList = domainVisits.get(domain);
342 if (domainVisitList == null) {
343 domainVisitList =
new ArrayList<>();
344 domainVisits.put(domain, domainVisitList);
347 domainVisitList.add(Pair.of(art, artifactDateMs));
350 return Pair.of(mostRecentMs, domainVisits);
361 private static Long
getMax(Long num1, Long num2) {
364 }
else if (num2 == null) {
367 return num2 > num1 ? num2 : num1;
382 return (StringUtils.isNotBlank(searchString) && dateAccessed != null)
405 if (dataSource == null) {
406 return Collections.emptyList();
410 List<BlackboardArtifact> webSearchArtifacts = caseProvider.
get().getBlackboard()
411 .getArtifacts(ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY.getTypeID(), dataSource.getId());
414 Collection<TopWebSearchResult> resultGroups = webSearchArtifacts
419 .filter(result -> result != null)
421 .collect(Collectors.toMap(
422 (result) -> result.getSearchString().toUpperCase(),
424 (result1, result2) -> TOP_WEBSEARCH_RESULT_DATE_COMPARE.compare(result1, result2) >= 0 ? result1 : result2))
428 List<TopWebSearchResult> results = resultGroups
431 .sorted(TOP_WEBSEARCH_RESULT_DATE_COMPARE.reversed())
434 .collect(Collectors.toList());
456 if (!translationService.
hasProvider() || StringUtils.isBlank(original)) {
460 String translated = null;
462 translated = translationService.
translate(original);
464 logger.log(Level.WARNING, String.format(
"There was an error translating text: '%s'", original), ex);
468 if (StringUtils.isBlank(translated)
469 || translated.toUpperCase().trim().equals(original.toUpperCase().trim())) {
512 public List<TopDeviceAttachedResult>
getRecentDevices(DataSource dataSource,
int count)
throws SleuthkitCaseProviderException, TskCoreException {
515 if (dataSource == null) {
516 return Collections.emptyList();
533 return result.getDeviceId() == null
534 || result.getDeviceModel() == null
535 || !DEVICE_EXCLUDE_LIST.contains(result.getDeviceModel().trim().toUpperCase());
537 .collect(Collectors.toMap(result -> result.getDeviceId(), result -> result, (r1, r2) ->
getMostRecentDevice(r1, r2)))
540 return results.stream()
542 .collect(Collectors.toList());
556 return (StringUtils.isNotBlank(type) && date != null)
573 String type = messageType;
575 Date latestDate = null;
576 if (dateAttrs != null) {
577 latestDate = Stream.of(dateAttrs)
579 .filter((date) -> date != null)
580 .max((a, b) -> a.compareTo(b))
584 return (StringUtils.isNotBlank(type) && latestDate != null)
604 "DataSourceUserActivitySummary_getRecentAccounts_emailMessage=Email Message",
605 "DataSourceUserActivitySummary_getRecentAccounts_calllogMessage=Call Log",})
606 public List<TopAccountResult>
getRecentAccounts(DataSource dataSource,
int count)
throws SleuthkitCaseProviderException, TskCoreException {
609 if (dataSource == null) {
610 return Collections.emptyList();
613 Stream<TopAccountResult> messageResults = caseProvider.
get().getBlackboard().getArtifacts(ARTIFACT_TYPE.TSK_MESSAGE.getTypeID(), dataSource.getId())
617 Stream<TopAccountResult> emailResults = caseProvider.
get().getBlackboard().getArtifacts(ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID(), dataSource.getId())
622 Bundle.DataSourceUserActivitySummary_getRecentAccounts_emailMessage(),
627 Stream<TopAccountResult> calllogResults = caseProvider.
get().getBlackboard().getArtifacts(ARTIFACT_TYPE.TSK_CALLLOG.getTypeID(), dataSource.getId())
632 Bundle.DataSourceUserActivitySummary_getRecentAccounts_calllogMessage(),
637 Stream<TopAccountResult> allResults = Stream.concat(messageResults, Stream.concat(emailResults, calllogResults));
640 Collection<TopAccountResult> groupedResults = allResults
642 .filter(result -> result != null)
644 .collect(Collectors.toMap(
645 result -> result.getAccountType(),
647 (result1, result2) -> TOP_ACCOUNT_RESULT_DATE_COMPARE.compare(result1, result2) >= 0 ? result1 : result2))
651 return groupedResults
654 .sorted(TOP_ACCOUNT_RESULT_DATE_COMPARE.reversed())
658 .collect(Collectors.toList());
672 if (StringUtils.isBlank(programName) || NTOS_BOOT_IDENTIFIER.equalsIgnoreCase(programName)) {
679 if (StringUtils.startsWithIgnoreCase(path, WINDOWS_PREFIX)) {
684 Long longCount = (count == null) ? null : (
long) count;
703 private static Date
getMax(Date date1, Date date2) {
706 }
else if (date2 == null) {
709 return date1.compareTo(date2) > 0 ? date1 : date2;
723 if (long1 == null && long2 == null) {
725 }
else if (long1 != null && long2 == null) {
727 }
else if (long1 == null && long2 != null) {
731 return Long.compare(long1, long2);
742 return longNum != null && longNum > 0;
764 public List<TopProgramsResult>
getTopPrograms(DataSource dataSource,
int count)
throws SleuthkitCaseProviderException, TskCoreException {
767 if (dataSource == null) {
768 return Collections.emptyList();
772 Collection<TopProgramsResult> results = caseProvider.
get().getBlackboard().getArtifacts(ARTIFACT_TYPE.TSK_PROG_RUN.getTypeID(), dataSource.getId())
777 .filter((res) -> res != null)
781 .collect(Collectors.toMap(
783 res.getProgramName() == null ? null : res.getProgramName().toUpperCase(),
784 res.getProgramPath() == null ? null : res.getProgramPath().toUpperCase()),
787 Long maxRunTimes =
getMax(res1.getRunTimes(), res2.getRunTimes());
788 Date maxDate =
getMax(res1.getLastAccessed(), res2.getLastAccessed());
789 TopProgramsResult maxResult = TOP_PROGRAMS_RESULT_COMPARE.compare(res1, res2) >= 0 ? res1 : res2;
791 maxResult.getProgramName(),
792 maxResult.getProgramPath(),
795 maxResult.getArtifact());
798 List<TopProgramsResult> orderedResults = results.stream()
799 .sorted(TOP_PROGRAMS_RESULT_COMPARE)
800 .collect(Collectors.toList());
803 if (!orderedResults.isEmpty()) {
809 return orderedResults.stream().limit(count).collect(Collectors.toList());
814 return orderedResults;
868 super(dateAccessed, artifact);
915 super(dateAccessed, artifact);
959 super(lastAccess, artifact);
988 super(lastVisit, artifact);
1026 super(lastRun, artifact);
static final BlackboardAttribute.Type TYPE_DATETIME
static final Comparator< TopWebSearchResult > TOP_WEBSEARCH_RESULT_DATE_COMPARE
TopDomainsResult(String domain, Long visitTimes, Date lastVisit, BlackboardArtifact artifact)
LastAccessedArtifact(Date lastAccessed, BlackboardArtifact artifact)
final java.util.logging.Logger logger
static final BlackboardAttribute.Type TYPE_DEVICE_MODEL
SleuthkitCaseProvider DEFAULT
static Date getMax(Date date1, Date date2)
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)
TopDomainsResult getDomainsResult(String domain, List< Pair< BlackboardArtifact, Long >> visits, long mostRecentMs)
static final long DOMAIN_WINDOW_MS
static final String WINDOWS_PREFIX
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
static final BlackboardAttribute.Type TYPE_PATH
UserActivitySummary(SleuthkitCaseProvider provider, TextTranslationService translationService, java.util.logging.Logger logger)
static int nullableCompare(Long long1, Long long2)
List< TopWebSearchResult > getMostRecentWebSearches(DataSource dataSource, int count)
static void assertValidCount(int count)
static TopAccountResult getMessageAccountResult(BlackboardArtifact artifact)
static final Set< String > DOMAIN_EXCLUDE_LIST
static final String NTOS_BOOT_IDENTIFIER
static final BlackboardAttribute.Type TYPE_COUNT
List< TopDeviceAttachedResult > getRecentDevices(DataSource dataSource, int count)
TopAccountResult(String accountType, Date lastAccess, BlackboardArtifact artifact)
TopProgramsResult getTopProgramsResult(BlackboardArtifact artifact)
TopDeviceAttachedResult getMostRecentDevice(TopDeviceAttachedResult r1, TopDeviceAttachedResult r2)
static TextTranslationService getInstance()
String getTranslationOrNull(String original)
final BlackboardArtifact artifact
static final long DOMAIN_WINDOW_DAYS
final TextTranslationService translationService
static List< BlackboardArtifact > getArtifacts(SleuthkitCase skCase, BlackboardArtifact.Type artifactType, DataSource dataSource, BlackboardAttribute.Type attributeType, SortOrder sortOrder)
static final BlackboardAttribute.Type TYPE_DATETIME_SENT
static final long MS_PER_DAY
static final BlackboardAttribute.Type TYPE_DATETIME_ACCESSED
static final Comparator< TopAccountResult > TOP_ACCOUNT_RESULT_DATE_COMPARE
TopWebSearchResult(String searchString, Date dateAccessed, BlackboardArtifact artifact)
List< TopProgramsResult > getTopPrograms(DataSource dataSource, int count)
static Long getLongOrNull(BlackboardArtifact artifact, Type attributeType)
Pair< Long, Map< String, List< Pair< BlackboardArtifact, Long > > > > getDomainGroupsAndMostRecent(DataSource dataSource)
synchronized boolean hasProvider()
static boolean isPositiveNum(Long longNum)
final SleuthkitCaseProvider caseProvider
static Integer getIntOrNull(BlackboardArtifact artifact, Type attributeType)
final String searchString
List< TopDomainsResult > getRecentDomains(DataSource dataSource, int count)
void setTranslatedResult(String translatedResult)
static final BlackboardAttribute.Type TYPE_DATETIME_END
static final Comparator< TopProgramsResult > TOP_PROGRAMS_RESULT_COMPARE
static final BlackboardAttribute.Type TYPE_MESSAGE_TYPE
synchronized static Logger getLogger(String name)
static final BlackboardAttribute.Type TYPE_TEXT
String getTranslatedResult()
static final BlackboardAttribute.Type TYPE_PROG_NAME
TopDeviceAttachedResult(String deviceId, Date dateAccessed, String deviceMake, String deviceModel, BlackboardArtifact artifact)
static final BlackboardArtifact.Type TYPE_DEVICE_ATTACHED
static Date getDateOrNull(BlackboardArtifact artifact, Type attributeType)
static final BlackboardAttribute.Type TYPE_DATETIME_RCVD
static final BlackboardArtifact.Type TYPE_WEB_HISTORY
static String getShortFolderName(String strPath, String applicationName)
static String getStringOrNull(BlackboardArtifact artifact, Type attributeType)
BlackboardArtifact getArtifact()
static final List< Function< List< String >, String > > SHORT_FOLDER_MATCHERS
static TopAccountResult getAccountResult(BlackboardArtifact artifact, String messageType, BlackboardAttribute.Type...dateAttrs)