19 package org.sleuthkit.autopsy.datasourcesummary.datamodel;
23 import java.util.ArrayList;
24 import java.util.Arrays;
25 import java.util.Collection;
26 import java.util.Collections;
27 import java.util.Comparator;
28 import java.util.Date;
29 import java.util.HashMap;
30 import java.util.HashSet;
31 import java.util.List;
34 import java.util.function.Function;
35 import java.util.logging.Level;
36 import java.util.stream.Collectors;
37 import java.util.stream.Stream;
38 import org.apache.commons.lang3.StringUtils;
39 import org.apache.commons.lang3.tuple.Pair;
40 import org.openide.util.NbBundle.Messages;
49 import static org.
sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
50 import static org.
sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
66 if (pathList.size() < 2) {
70 String rootParent = pathList.get(0).toUpperCase();
71 if (
"PROGRAM FILES".equals(rootParent) ||
"PROGRAM FILES (X86)".equals(rootParent)) {
72 return pathList.get(1);
79 for (String pathEl : pathList) {
80 String uppered = pathEl.toUpperCase();
81 if (
"APPLICATION DATA".equals(uppered) ||
"APPDATA".equals(uppered)) {
89 private static final BlackboardArtifact.Type
TYPE_DEVICE_ATTACHED =
new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_DEVICE_ATTACHED);
90 private static final BlackboardArtifact.Type
TYPE_WEB_HISTORY =
new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_WEB_HISTORY);
92 private static final BlackboardAttribute.Type
TYPE_DATETIME =
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME);
93 private static final BlackboardAttribute.Type
TYPE_DATETIME_ACCESSED =
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED);
94 private static final BlackboardAttribute.Type
TYPE_DEVICE_ID =
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_ID);
95 private static final BlackboardAttribute.Type
TYPE_DEVICE_MAKE =
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE);
96 private static final BlackboardAttribute.Type
TYPE_DEVICE_MODEL =
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL);
97 private static final BlackboardAttribute.Type
TYPE_MESSAGE_TYPE =
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE);
98 private static final BlackboardAttribute.Type
TYPE_TEXT =
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_TEXT);
99 private static final BlackboardAttribute.Type
TYPE_DATETIME_RCVD =
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_RCVD);
100 private static final BlackboardAttribute.Type
TYPE_DATETIME_SENT =
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_SENT);
101 private static final BlackboardAttribute.Type
TYPE_DATETIME_START =
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_START);
102 private static final BlackboardAttribute.Type
TYPE_DATETIME_END =
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_END);
103 private static final BlackboardAttribute.Type
TYPE_DOMAIN =
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DOMAIN);
104 private static final BlackboardAttribute.Type
TYPE_PROG_NAME =
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME);
105 private static final BlackboardAttribute.Type
TYPE_PATH =
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH);
106 private static final BlackboardAttribute.Type
TYPE_COUNT =
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_COUNT);
121 int runTimesCompare =
nullableCompare(a.getRunTimes(), b.getRunTimes());
122 if (runTimesCompare != 0) {
123 return -runTimesCompare;
129 a.getLastAccessed() == null ? null : a.getLastAccessed().getTime(),
130 b.getLastAccessed() == null ? null : b.getLastAccessed().getTime());
132 if (lastRunCompare != 0) {
133 return -lastRunCompare;
137 return (a.getProgramName() == null ?
"" : a.getProgramName())
138 .compareToIgnoreCase((b.getProgramName() == null ?
"" : b.getProgramName()));
142 ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY.getTypeID(),
143 ARTIFACT_TYPE.TSK_MESSAGE.getTypeID(),
144 ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID(),
145 ARTIFACT_TYPE.TSK_CALLLOG.getTypeID(),
146 ARTIFACT_TYPE.TSK_DEVICE_ATTACHED.getTypeID(),
147 ARTIFACT_TYPE.TSK_WEB_HISTORY.getTypeID(),
148 ARTIFACT_TYPE.TSK_PROG_RUN.getTypeID()
151 private static final Set<String>
DEVICE_EXCLUDE_LIST =
new HashSet<>(Arrays.asList(
"ROOT_HUB",
"ROOT_HUB20"));
152 private static final Set<String>
DOMAIN_EXCLUDE_LIST =
new HashSet<>(Arrays.asList(
"127.0.0.1",
"LOCALHOST"));
160 private final java.util.logging.Logger
logger;
182 java.util.logging.Logger
logger) {
184 this.caseProvider = provider;
201 throw new IllegalArgumentException(
"Count must be greater than 0");
218 if (dataSource == null) {
219 return Collections.emptyList();
224 if (mostRecentAndGroups.getKey() == null || mostRecentAndGroups.getValue().size() == 0) {
225 return Collections.emptyList();
228 final long mostRecentMs = mostRecentAndGroups.getLeft();
229 Map<String, List<Pair<BlackboardArtifact, Long>>> groups = mostRecentAndGroups.getRight();
231 return groups.entrySet().stream()
232 .map(entry ->
getDomainsResult(entry.getKey(), entry.getValue(), mostRecentMs))
233 .filter(result -> result != null)
235 .sorted((a, b) -> -Long.compare(a.getVisitTimes(), b.getVisitTimes()))
238 .collect(Collectors.toList());
255 Long thisMostRecentMs = null;
256 BlackboardArtifact thisMostRecentArtifact = null;
258 for (Pair<BlackboardArtifact, Long> visitInstance : visits) {
259 BlackboardArtifact artifact = visitInstance.getLeft();
260 Long visitMs = visitInstance.getRight();
262 if (visitMs == null || visitMs + DOMAIN_WINDOW_MS < mostRecentMs) {
268 if (thisMostRecentMs == null || visitMs > thisMostRecentMs) {
269 thisMostRecentMs = visitMs;
270 thisMostRecentArtifact = artifact;
272 thisMostRecentMs =
getMax(thisMostRecentMs, visitMs);
276 if (visitCount <= 0 || thisMostRecentMs == null) {
280 return new TopDomainsResult(domain, visitCount,
new Date(thisMostRecentMs), thisMostRecentArtifact);
299 List<BlackboardArtifact> artifacts = DataSourceInfoUtilities.getArtifacts(caseProvider.
get(),
TYPE_WEB_HISTORY,
302 Long mostRecentMs = null;
303 Map<String, List<Pair<BlackboardArtifact, Long>>> domainVisits =
new HashMap<>();
305 for (BlackboardArtifact art : artifacts) {
306 Long artifactDateSecs = DataSourceInfoUtilities.getLongOrNull(art, TYPE_DATETIME_ACCESSED);
307 String domain = DataSourceInfoUtilities.getStringOrNull(art,
TYPE_DOMAIN);
311 if (artifactDateSecs == null || StringUtils.isBlank(domain) || DOMAIN_EXCLUDE_LIST.contains(domain.toUpperCase().trim())) {
315 Long artifactDateMs = artifactDateSecs * 1000;
318 mostRecentMs =
getMax(mostRecentMs, artifactDateMs);
321 domain = domain.toLowerCase().trim();
324 List<Pair<BlackboardArtifact, Long>> domainVisitList = domainVisits.get(domain);
325 if (domainVisitList == null) {
326 domainVisitList =
new ArrayList<>();
327 domainVisits.put(domain, domainVisitList);
330 domainVisitList.add(Pair.of(art, artifactDateMs));
333 return Pair.of(mostRecentMs, domainVisits);
344 private static Long
getMax(Long num1, Long num2) {
347 }
else if (num2 == null) {
350 return num2 > num1 ? num2 : num1;
363 String searchString = DataSourceInfoUtilities.getStringOrNull(artifact,
TYPE_TEXT);
365 return (StringUtils.isNotBlank(searchString) && dateAccessed != null)
387 if (dataSource == null) {
388 return Collections.emptyList();
392 List<BlackboardArtifact> webSearchArtifacts = caseProvider.
get().getBlackboard()
393 .getArtifacts(ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY.getTypeID(), dataSource.getId());
396 Collection<TopWebSearchResult> resultGroups = webSearchArtifacts
401 .filter(result -> result != null)
403 .collect(Collectors.toMap(
404 (result) -> result.getSearchString().toUpperCase(),
406 (result1, result2) -> TOP_WEBSEARCH_RESULT_DATE_COMPARE.compare(result1, result2) >= 0 ? result1 : result2))
410 List<TopWebSearchResult> results = resultGroups
413 .sorted(TOP_WEBSEARCH_RESULT_DATE_COMPARE.reversed())
416 .collect(Collectors.toList());
438 if (!translationService.
hasProvider() || StringUtils.isBlank(original)) {
442 String translated = null;
444 translated = translationService.
translate(original);
446 logger.log(Level.WARNING, String.format(
"There was an error translating text: '%s'", original), ex);
450 if (StringUtils.isBlank(translated)
451 || translated.toUpperCase().trim().equals(original.toUpperCase().trim())) {
492 public List<TopDeviceAttachedResult>
getRecentDevices(DataSource dataSource,
int count)
throws SleuthkitCaseProviderException, TskCoreException {
495 if (dataSource == null) {
496 return Collections.emptyList();
499 Collection<TopDeviceAttachedResult> results = DataSourceInfoUtilities.getArtifacts(caseProvider.
get(),
TYPE_DEVICE_ATTACHED,
500 dataSource,
TYPE_DATETIME, DataSourceInfoUtilities.SortOrder.DESCENDING, 0)
504 DataSourceInfoUtilities.getStringOrNull(artifact,
TYPE_DEVICE_ID),
505 DataSourceInfoUtilities.getDateOrNull(artifact, TYPE_DATETIME),
513 return result.getDeviceId() == null
514 || result.getDeviceModel() == null
515 || !DEVICE_EXCLUDE_LIST.contains(result.getDeviceModel().trim().toUpperCase());
517 .collect(Collectors.toMap(result -> result.getDeviceId(), result -> result, (r1, r2) ->
getMostRecentDevice(r1, r2)))
520 return results.stream()
522 .collect(Collectors.toList());
534 String type = DataSourceInfoUtilities.getStringOrNull(artifact,
TYPE_MESSAGE_TYPE);
535 Date date = DataSourceInfoUtilities.getDateOrNull(artifact,
TYPE_DATETIME);
536 return (StringUtils.isNotBlank(type) && date != null)
553 String type = messageType;
555 Date latestDate = null;
556 if (dateAttrs != null) {
557 latestDate = Stream.of(dateAttrs)
558 .map((attr) -> DataSourceInfoUtilities.getDateOrNull(artifact, attr))
559 .filter((date) -> date != null)
560 .max((a, b) -> a.compareTo(b))
564 return (StringUtils.isNotBlank(type) && latestDate != null)
584 "DataSourceUserActivitySummary_getRecentAccounts_emailMessage=Email Message",
585 "DataSourceUserActivitySummary_getRecentAccounts_calllogMessage=Call Log",})
586 public List<TopAccountResult>
getRecentAccounts(DataSource dataSource,
int count)
throws SleuthkitCaseProviderException, TskCoreException {
589 if (dataSource == null) {
590 return Collections.emptyList();
593 Stream<TopAccountResult> messageResults = caseProvider.
get().getBlackboard().getArtifacts(ARTIFACT_TYPE.TSK_MESSAGE.getTypeID(), dataSource.getId())
597 Stream<TopAccountResult> emailResults = caseProvider.
get().getBlackboard().getArtifacts(ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID(), dataSource.getId())
602 Bundle.DataSourceUserActivitySummary_getRecentAccounts_emailMessage(),
607 Stream<TopAccountResult> calllogResults = caseProvider.
get().getBlackboard().getArtifacts(ARTIFACT_TYPE.TSK_CALLLOG.getTypeID(), dataSource.getId())
612 Bundle.DataSourceUserActivitySummary_getRecentAccounts_calllogMessage(),
617 Stream<TopAccountResult> allResults = Stream.concat(messageResults, Stream.concat(emailResults, calllogResults));
620 Collection<TopAccountResult> groupedResults = allResults
622 .filter(result -> result != null)
624 .collect(Collectors.toMap(
625 result -> result.getAccountType(),
627 (result1, result2) -> TOP_ACCOUNT_RESULT_DATE_COMPARE.compare(result1, result2) >= 0 ? result1 : result2))
631 return groupedResults
634 .sorted(TOP_ACCOUNT_RESULT_DATE_COMPARE.reversed())
638 .collect(Collectors.toList());
650 if (strPath == null) {
654 List<String> pathEls =
new ArrayList<>(Arrays.asList(applicationName));
656 File file =
new File(strPath);
657 while (file != null &&
org.apache.commons.lang.StringUtils.isNotBlank(file.getName())) {
658 pathEls.add(file.getName());
659 file = file.getParentFile();
662 Collections.reverse(pathEls);
664 for (Function<List<String>, String> matchEntry : SHORT_FOLDER_MATCHERS) {
665 String result = matchEntry.apply(pathEls);
666 if (
org.apache.commons.lang.StringUtils.isNotBlank(result)) {
682 String programName = DataSourceInfoUtilities.getStringOrNull(artifact,
TYPE_PROG_NAME);
685 if (StringUtils.isBlank(programName) || NTOS_BOOT_IDENTIFIER.equalsIgnoreCase(programName)) {
689 String path = DataSourceInfoUtilities.getStringOrNull(artifact,
TYPE_PATH);
692 if (StringUtils.startsWithIgnoreCase(path, WINDOWS_PREFIX)) {
696 Integer count = DataSourceInfoUtilities.getIntOrNull(artifact,
TYPE_COUNT);
697 Long longCount = (count == null) ? null : (
long) count;
703 DataSourceInfoUtilities.getDateOrNull(artifact,
TYPE_DATETIME),
716 private static Date
getMax(Date date1, Date date2) {
719 }
else if (date2 == null) {
722 return date1.compareTo(date2) > 0 ? date1 : date2;
736 if (long1 == null && long2 == null) {
738 }
else if (long1 != null && long2 == null) {
740 }
else if (long1 == null && long2 != null) {
744 return Long.compare(long1, long2);
755 return longNum != null && longNum > 0;
777 public List<TopProgramsResult>
getTopPrograms(DataSource dataSource,
int count)
throws SleuthkitCaseProviderException, TskCoreException {
780 if (dataSource == null) {
781 return Collections.emptyList();
785 Collection<TopProgramsResult> results = caseProvider.
get().getBlackboard().getArtifacts(ARTIFACT_TYPE.TSK_PROG_RUN.getTypeID(), dataSource.getId())
790 .filter((res) -> res != null)
794 .collect(Collectors.toMap(
796 res.getProgramName() == null ? null : res.getProgramName().toUpperCase(),
797 res.getProgramPath() == null ? null : res.getProgramPath().toUpperCase()),
800 Long maxRunTimes =
getMax(res1.getRunTimes(), res2.getRunTimes());
801 Date maxDate =
getMax(res1.getLastAccessed(), res2.getLastAccessed());
802 TopProgramsResult maxResult = TOP_PROGRAMS_RESULT_COMPARE.compare(res1, res2) >= 0 ? res1 : res2;
804 maxResult.getProgramName(),
805 maxResult.getProgramPath(),
808 maxResult.getArtifact());
811 List<TopProgramsResult> orderedResults = results.stream()
812 .sorted(TOP_PROGRAMS_RESULT_COMPARE)
813 .collect(Collectors.toList());
816 if (!orderedResults.isEmpty()) {
822 return orderedResults.stream().limit(count).collect(Collectors.toList());
827 return orderedResults;
881 super(dateAccessed, artifact);
928 super(dateAccessed, artifact);
972 super(lastAccess, artifact);
1001 super(lastVisit, artifact);
1039 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)
void assertValidCount(int count)
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 TopAccountResult getMessageAccountResult(BlackboardArtifact artifact)
static final Set< String > DOMAIN_EXCLUDE_LIST
static final Set< Integer > ARTIFACT_UPDATE_TYPE_IDS
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
String getShortFolderName(String strPath, String applicationName)
static final long DOMAIN_WINDOW_DAYS
final TextTranslationService translationService
static final BlackboardAttribute.Type TYPE_DATETIME_SENT
static final long MS_PER_DAY
Set< Integer > getArtifactTypeIdsForRefresh()
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)
Pair< Long, Map< String, List< Pair< BlackboardArtifact, Long > > > > getDomainGroupsAndMostRecent(DataSource dataSource)
synchronized boolean hasProvider()
static boolean isPositiveNum(Long longNum)
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 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 final BlackboardAttribute.Type TYPE_DATETIME_RCVD
static final BlackboardArtifact.Type TYPE_WEB_HISTORY
BlackboardArtifact getArtifact()
static final List< Function< List< String >, String > > SHORT_FOLDER_MATCHERS
static TopAccountResult getAccountResult(BlackboardArtifact artifact, String messageType, BlackboardAttribute.Type...dateAttrs)