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)