23 package org.sleuthkit.autopsy.recentactivity;
 
   25 import com.google.gson.JsonArray;
 
   26 import com.google.gson.JsonElement;
 
   27 import com.google.gson.JsonIOException;
 
   28 import com.google.gson.JsonObject;
 
   29 import com.google.gson.JsonParser;
 
   30 import com.google.gson.JsonSyntaxException;
 
   31 import org.openide.util.NbBundle;
 
   33 import java.util.logging.Level;
 
   36 import java.io.FileNotFoundException;
 
   37 import java.io.FileReader;
 
   38 import java.io.IOException;
 
   39 import org.apache.commons.io.FilenameUtils;
 
   40 import org.openide.util.NbBundle.Messages;
 
   51 import org.
sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
 
   53 import org.
sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
 
   55 import org.
sleuthkit.datamodel.ReadContentInputStream.ReadContentInputStreamException;
 
   62 class Chrome 
extends Extract {
 
   64     private static final String HISTORY_QUERY = 
"SELECT urls.url, urls.title, urls.visit_count, urls.typed_count, "  
   65             + 
"last_visit_time, urls.hidden, visits.visit_time, (SELECT urls.url FROM urls WHERE urls.id=visits.url) AS from_visit, visits.transition FROM urls, visits WHERE urls.id = visits.url"; 
 
   66     private static final String COOKIE_QUERY = 
"SELECT name, value, host_key, expires_utc,last_access_utc, creation_utc FROM cookies"; 
 
   67     private static final String DOWNLOAD_QUERY = 
"SELECT full_path, url, start_time, received_bytes FROM downloads"; 
 
   68     private static final String DOWNLOAD_QUERY_V30 = 
"SELECT current_path AS full_path, url, start_time, received_bytes FROM downloads, downloads_url_chains WHERE downloads.id=downloads_url_chains.id"; 
 
   69     private static final String LOGIN_QUERY = 
"SELECT origin_url, username_value, date_created, signon_realm from logins"; 
 
   70     private static final String AUTOFILL_QUERY = 
"SELECT name, value, count, date_created " + 
 
   71                                                     " FROM autofill, autofill_dates " +
 
   72                                                     " WHERE autofill.pair_id = autofill_dates.pair_id" 
   74     private static final String AUTOFILL_QUERY_V8X = 
"SELECT name, value, count, date_created, date_last_used from autofill"; 
 
   75     private static final String WEBFORM_ADDRESS_QUERY = 
"SELECT first_name, middle_name, last_name, address_line_1, address_line_2, city, state, zipcode, country_code, number, email, date_modified " +
 
   76                                                         " FROM autofill_profiles, autofill_profile_names, autofill_profile_emails, autofill_profile_phones" +
 
   77                                                         " WHERE autofill_profiles.guid = autofill_profile_names.guid AND autofill_profiles.guid = autofill_profile_emails.guid AND autofill_profiles.guid = autofill_profile_phones.guid";
 
   79     private static final String WEBFORM_ADDRESS_QUERY_V8X = 
"SELECT first_name, middle_name, last_name, full_name, street_address, city, state, zipcode, country_code, number, email, date_modified, use_date, use_count" +
 
   80                                                             " FROM autofill_profiles, autofill_profile_names, autofill_profile_emails, autofill_profile_phones" +
 
   81                                                             " WHERE autofill_profiles.guid = autofill_profile_names.guid AND autofill_profiles.guid = autofill_profile_emails.guid AND autofill_profiles.guid = autofill_profile_phones.guid";
 
   82     private final Logger logger = Logger.getLogger(this.getClass().getName());
 
   83     private Content dataSource;
 
   84     private IngestJobContext context;
 
   87         "Progress_Message_Chrome_History=Chrome History",
 
   88         "Progress_Message_Chrome_Bookmarks=Chrome Bookmarks",
 
   89         "Progress_Message_Chrome_Cookies=Chrome Cookies",
 
   90         "Progress_Message_Chrome_Downloads=Chrome Downloads",
 
   91         "Progress_Message_Chrome_FormHistory=Chrome Form History",
 
   92         "Progress_Message_Chrome_AutoFill=Chrome Auto Fill",
 
   93         "Progress_Message_Chrome_Logins=Chrome Logins",
 
   94         "Progress_Message_Chrome_Cache=Chrome Cache",
 
   98         moduleName = NbBundle.getMessage(Chrome.class, 
"Chrome.moduleName");
 
  102     public void process(Content dataSource, IngestJobContext context, DataSourceIngestModuleProgress progressBar) {
 
  103         this.dataSource = dataSource;
 
  104         this.context = context;
 
  107         progressBar.progress(Bundle.Progress_Message_Chrome_History());
 
  109         if (context.dataSourceIngestIsCancelled()) {
 
  113         progressBar.progress(Bundle.Progress_Message_Chrome_Bookmarks());
 
  115         if (context.dataSourceIngestIsCancelled()) {
 
  119         progressBar.progress(Bundle.Progress_Message_Chrome_Cookies());
 
  121         if (context.dataSourceIngestIsCancelled()) {
 
  125         progressBar.progress(Bundle.Progress_Message_Chrome_Logins());
 
  127         if (context.dataSourceIngestIsCancelled()) {
 
  131         progressBar.progress(Bundle.Progress_Message_Chrome_AutoFill());
 
  133         if (context.dataSourceIngestIsCancelled()) {
 
  137         progressBar.progress(Bundle.Progress_Message_Chrome_Downloads());
 
  139         if (context.dataSourceIngestIsCancelled()) {
 
  143         progressBar.progress(Bundle.Progress_Message_Chrome_Cache());
 
  144         ChromeCacheExtractor chromeCacheExtractor = 
new ChromeCacheExtractor(dataSource, context, progressBar);
 
  145         chromeCacheExtractor.getCaches();
 
  151     private void getHistory() {
 
  152         FileManager fileManager = currentCase.getServices().getFileManager();
 
  153         List<AbstractFile> historyFiles;
 
  155             historyFiles = fileManager.findFiles(dataSource, 
"History", 
"Chrome"); 
 
  156         } 
catch (TskCoreException ex) {
 
  157             String msg = NbBundle.getMessage(this.getClass(), 
"Chrome.getHistory.errMsg.errGettingFiles");
 
  158             logger.log(Level.SEVERE, msg, ex);
 
  159             this.addErrorMessage(this.getName() + 
": " + msg);
 
  164         List<AbstractFile> allocatedHistoryFiles = 
new ArrayList<>();
 
  165         for (AbstractFile historyFile : historyFiles) {
 
  166             if (historyFile.isMetaFlagSet(TskData.TSK_FS_META_FLAG_ENUM.ALLOC)) {
 
  167                 allocatedHistoryFiles.add(historyFile);
 
  172         if (allocatedHistoryFiles.isEmpty()) {
 
  173             String msg = NbBundle.getMessage(this.getClass(), 
"Chrome.getHistory.errMsg.couldntFindAnyFiles");
 
  174             logger.log(Level.INFO, msg);
 
  179         Collection<BlackboardArtifact> bbartifacts = 
new ArrayList<>();
 
  181         while (j < historyFiles.size()) {
 
  182             String temps = RAImageIngestModule.getRATempPath(currentCase, 
"chrome") + File.separator + historyFiles.get(j).getName() + j + 
".db"; 
 
  183             final AbstractFile historyFile = historyFiles.get(j++);
 
  184             if (historyFile.getSize() == 0) {
 
  188                 ContentUtils.writeToFile(historyFile, 
new File(temps), context::dataSourceIngestIsCancelled);
 
  189             } 
catch (ReadContentInputStreamException ex) {
 
  190                 logger.log(Level.WARNING, String.format(
"Error reading Chrome web history artifacts file '%s' (id=%d).",
 
  191                         historyFile.getName(), historyFile.getId()), ex); 
 
  192                 this.addErrorMessage(NbBundle.getMessage(
this.getClass(), 
"Chrome.getHistory.errMsg.errAnalyzingFile",
 
  193                         this.getName(), historyFile.getName()));
 
  195             } 
catch (IOException ex) {
 
  196                 logger.log(Level.SEVERE, String.format(
"Error writing temp sqlite db file '%s' for Chrome web history artifacts file '%s' (id=%d).",
 
  197                         temps, historyFile.getName(), historyFile.getId()), ex); 
 
  198                 this.addErrorMessage(NbBundle.getMessage(
this.getClass(), 
"Chrome.getHistory.errMsg.errAnalyzingFile",
 
  199                         this.getName(), historyFile.getName()));
 
  202             File dbFile = 
new File(temps);
 
  203             if (context.dataSourceIngestIsCancelled()) {
 
  207             List<HashMap<String, Object>> tempList;
 
  208             tempList = this.dbConnect(temps, HISTORY_QUERY);
 
  209             logger.log(Level.INFO, 
"{0}- Now getting history from {1} with {2}artifacts identified.", 
new Object[]{moduleName, temps, tempList.size()}); 
 
  210             for (HashMap<String, Object> result : tempList) {
 
  211                 Collection<BlackboardAttribute> bbattributes = 
new ArrayList<BlackboardAttribute>();
 
  212                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
 
  213                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  214                         ((result.get(
"url").toString() != null) ? result.get(
"url").toString() : 
""))); 
 
  215                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
 
  216                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  217                         (Long.valueOf(result.get(
"last_visit_time").toString()) / 1000000) - Long.valueOf(
"11644473600"))); 
 
  218                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REFERRER,
 
  219                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  220                         ((result.get(
"from_visit").toString() != null) ? result.get(
"from_visit").toString() : 
""))); 
 
  221                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TITLE,
 
  222                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  223                         ((result.get(
"title").toString() != null) ? result.get(
"title").toString() : 
""))); 
 
  224                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
 
  225                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  226                         NbBundle.getMessage(this.getClass(), 
"Chrome.moduleName")));
 
  227                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
 
  228                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  229                         (NetworkUtils.extractDomain((result.get(
"url").toString() != null) ? result.get(
"url").toString() : 
"")))); 
 
  231                 BlackboardArtifact bbart = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_WEB_HISTORY, historyFile, bbattributes);
 
  233                     bbartifacts.add(bbart);
 
  239         if( !bbartifacts.isEmpty() ){
 
  240             postArtifacts(bbartifacts);
 
  247     private void getBookmark() {
 
  248         FileManager fileManager = currentCase.getServices().getFileManager();
 
  249         List<AbstractFile> bookmarkFiles;
 
  251             bookmarkFiles = fileManager.findFiles(dataSource, 
"Bookmarks", 
"Chrome"); 
 
  252         } 
catch (TskCoreException ex) {
 
  253             String msg = NbBundle.getMessage(this.getClass(), 
"Chrome.getBookmark.errMsg.errGettingFiles");
 
  254             logger.log(Level.SEVERE, msg, ex);
 
  255             this.addErrorMessage(this.getName() + 
": " + msg);
 
  259         if (bookmarkFiles.isEmpty()) {
 
  260             logger.log(Level.INFO, 
"Didn't find any Chrome bookmark files."); 
 
  265         Collection<BlackboardArtifact> bbartifacts = 
new ArrayList<>();
 
  268         while (j < bookmarkFiles.size()) {
 
  269             AbstractFile bookmarkFile = bookmarkFiles.get(j++);
 
  270             if (bookmarkFile.getSize() == 0) {
 
  273             String temps = RAImageIngestModule.getRATempPath(currentCase, 
"chrome") + File.separator + bookmarkFile.getName() + j + 
".db"; 
 
  275                 ContentUtils.writeToFile(bookmarkFile, 
new File(temps), context::dataSourceIngestIsCancelled);
 
  276             } 
catch (ReadContentInputStreamException ex) {
 
  277                 logger.log(Level.WARNING, String.format(
"Error reading Chrome bookmark artifacts file '%s' (id=%d).",
 
  278                         bookmarkFile.getName(), bookmarkFile.getId()), ex); 
 
  279                 this.addErrorMessage(NbBundle.getMessage(
this.getClass(), 
"Chrome.getBookmark.errMsg.errAnalyzingFile",
 
  280                         this.getName(), bookmarkFile.getName()));
 
  282             } 
catch (IOException ex) {
 
  283                 logger.log(Level.SEVERE, String.format(
"Error writing temp sqlite db file '%s' for Chrome bookmark artifacts file '%s' (id=%d).",
 
  284                         temps, bookmarkFile.getName(), bookmarkFile.getId()), ex); 
 
  285                 this.addErrorMessage(NbBundle.getMessage(
this.getClass(), 
"Chrome.getBookmark.errMsg.errAnalyzingFile",
 
  286                         this.getName(), bookmarkFile.getName()));
 
  290             logger.log(Level.INFO, 
"{0}- Now getting Bookmarks from {1}", 
new Object[]{moduleName, temps}); 
 
  291             File dbFile = 
new File(temps);
 
  292             if (context.dataSourceIngestIsCancelled()) {
 
  297             FileReader tempReader;
 
  299                 tempReader = 
new FileReader(temps);
 
  300             } 
catch (FileNotFoundException ex) {
 
  301                 logger.log(Level.WARNING, 
"Error while trying to read into the Bookmarks for Chrome.", ex); 
 
  305             final JsonParser parser = 
new JsonParser();
 
  306             JsonElement jsonElement;
 
  307             JsonObject jElement, jRoot, jBookmark;
 
  308             JsonArray jBookmarkArray;
 
  311                 jsonElement = parser.parse(tempReader);
 
  312                 jElement = jsonElement.getAsJsonObject();
 
  313                 jRoot = jElement.get(
"roots").getAsJsonObject(); 
 
  314                 jBookmark = jRoot.get(
"bookmark_bar").getAsJsonObject(); 
 
  315                 jBookmarkArray = jBookmark.getAsJsonArray(
"children"); 
 
  316             } 
catch (JsonIOException | JsonSyntaxException | IllegalStateException ex) {
 
  317                 logger.log(Level.WARNING, 
"Error parsing Json from Chrome Bookmark.", ex); 
 
  318                 this.addErrorMessage(NbBundle.getMessage(
this.getClass(), 
"Chrome.getBookmark.errMsg.errAnalyzingFile3",
 
  319                         this.getName(), bookmarkFile.getName()));
 
  323             for (JsonElement result : jBookmarkArray) {
 
  324                 JsonObject address = result.getAsJsonObject();
 
  325                 if (address == null) {
 
  328                 JsonElement urlEl = address.get(
"url"); 
 
  331                     url = urlEl.getAsString();
 
  336                 JsonElement nameEl = address.get(
"name"); 
 
  337                 if (nameEl != null) {
 
  338                     name = nameEl.getAsString();
 
  343                 JsonElement dateEl = address.get(
"date_added"); 
 
  344                 if (dateEl != null) {
 
  345                     date = dateEl.getAsLong();
 
  347                     date = Long.valueOf(0);
 
  349                 String domain = NetworkUtils.extractDomain(url);
 
  351                     BlackboardArtifact bbart = bookmarkFile.newArtifact(ARTIFACT_TYPE.TSK_WEB_BOOKMARK);
 
  352                     Collection<BlackboardAttribute> bbattributes = 
new ArrayList<>();
 
  354                     bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
 
  355                             RecentActivityExtracterModuleFactory.getModuleName(), url));
 
  356                     bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TITLE,
 
  357                             RecentActivityExtracterModuleFactory.getModuleName(), name));
 
  358                     bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
 
  359                             RecentActivityExtracterModuleFactory.getModuleName(), (date / 1000000) - Long.valueOf(
"11644473600")));
 
  360                     bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
 
  361                             RecentActivityExtracterModuleFactory.getModuleName(),
 
  362                             NbBundle.getMessage(this.getClass(), 
"Chrome.moduleName")));
 
  363                     bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
 
  364                             RecentActivityExtracterModuleFactory.getModuleName(), domain));
 
  365                     bbart.addAttributes(bbattributes);
 
  367                     bbartifacts.add(bbart);
 
  368                 } 
catch (TskCoreException ex) {
 
  369                     logger.log(Level.SEVERE, 
"Error while trying to insert Chrome bookmark artifact{0}", ex); 
 
  370                     this.addErrorMessage(
 
  371                             NbBundle.getMessage(
this.getClass(), 
"Chrome.getBookmark.errMsg.errAnalyzingFile4",
 
  372                                     this.getName(), bookmarkFile.getName()));
 
  375             postArtifacts(bbartifacts);
 
  383     private void getCookie() {
 
  385         FileManager fileManager = currentCase.getServices().getFileManager();
 
  386         List<AbstractFile> cookiesFiles;
 
  388             cookiesFiles = fileManager.findFiles(dataSource, 
"Cookies", 
"Chrome"); 
 
  389         } 
catch (TskCoreException ex) {
 
  390             String msg = NbBundle.getMessage(this.getClass(), 
"Chrome.getCookie.errMsg.errGettingFiles");
 
  391             logger.log(Level.SEVERE, msg, ex);
 
  392             this.addErrorMessage(this.getName() + 
": " + msg);
 
  396         if (cookiesFiles.isEmpty()) {
 
  397             logger.log(Level.INFO, 
"Didn't find any Chrome cookies files."); 
 
  402         Collection<BlackboardArtifact> bbartifacts = 
new ArrayList<>();
 
  404         while (j < cookiesFiles.size()) {
 
  405             AbstractFile cookiesFile = cookiesFiles.get(j++);
 
  406             if (cookiesFile.getSize() == 0) {
 
  409             String temps = RAImageIngestModule.getRATempPath(currentCase, 
"chrome") + File.separator + cookiesFile.getName() + j + 
".db"; 
 
  411                 ContentUtils.writeToFile(cookiesFile, 
new File(temps), context::dataSourceIngestIsCancelled);
 
  412             } 
catch (ReadContentInputStreamException ex) {
 
  413                 logger.log(Level.WARNING, String.format(
"Error reading Chrome cookie artifacts file '%s' (id=%d).",
 
  414                         cookiesFile.getName(), cookiesFile.getId()), ex); 
 
  415                 this.addErrorMessage(NbBundle.getMessage(
this.getClass(), 
"Chrome.getCookie.errMsg.errAnalyzeFile",
 
  416                         this.getName(), cookiesFile.getName()));
 
  418             } 
catch (IOException ex) {
 
  419                 logger.log(Level.SEVERE, String.format(
"Error writing temp sqlite db file '%s' for Chrome cookie artifacts file '%s' (id=%d).",
 
  420                         temps, cookiesFile.getName(), cookiesFile.getId()), ex); 
 
  421                 this.addErrorMessage(NbBundle.getMessage(
this.getClass(), 
"Chrome.getCookie.errMsg.errAnalyzeFile",
 
  422                         this.getName(), cookiesFile.getName()));
 
  425             File dbFile = 
new File(temps);
 
  426             if (context.dataSourceIngestIsCancelled()) {
 
  431             List<HashMap<String, Object>> tempList = this.dbConnect(temps, COOKIE_QUERY);
 
  432             logger.log(Level.INFO, 
"{0}- Now getting cookies from {1} with {2}artifacts identified.", 
new Object[]{moduleName, temps, tempList.size()}); 
 
  433             for (HashMap<String, Object> result : tempList) {
 
  434                 Collection<BlackboardAttribute> bbattributes = 
new ArrayList<>();
 
  435                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
 
  436                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  437                         ((result.get(
"host_key").toString() != null) ? result.get(
"host_key").toString() : 
""))); 
 
  438                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME,
 
  439                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  440                         (Long.valueOf(result.get(
"last_access_utc").toString()) / 1000000) - Long.valueOf(
"11644473600"))); 
 
  442                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME,
 
  443                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  444                         ((result.get(
"name").toString() != null) ? result.get(
"name").toString() : 
""))); 
 
  445                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE,
 
  446                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  447                         ((result.get(
"value").toString() != null) ? result.get(
"value").toString() : 
""))); 
 
  448                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
 
  449                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  450                         NbBundle.getMessage(this.getClass(), 
"Chrome.moduleName")));
 
  451                 String domain = result.get(
"host_key").toString(); 
 
  452                 domain = domain.replaceFirst(
"^\\.+(?!$)", 
"");
 
  453                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
 
  454                         RecentActivityExtracterModuleFactory.getModuleName(), domain));
 
  456                 BlackboardArtifact bbart = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_WEB_COOKIE, cookiesFile, bbattributes);
 
  458                     bbartifacts.add(bbart);
 
  465         if( !bbartifacts.isEmpty() ) {
 
  466             postArtifacts(bbartifacts);
 
  473     private void getDownload() {
 
  474         FileManager fileManager = currentCase.getServices().getFileManager();
 
  475         List<AbstractFile> downloadFiles;
 
  477             downloadFiles = fileManager.findFiles(dataSource, 
"History", 
"Chrome"); 
 
  478         } 
catch (TskCoreException ex) {
 
  479             String msg = NbBundle.getMessage(this.getClass(), 
"Chrome.getDownload.errMsg.errGettingFiles");
 
  480             logger.log(Level.SEVERE, msg, ex);
 
  481             this.addErrorMessage(this.getName() + 
": " + msg);
 
  485         if (downloadFiles.isEmpty()) {
 
  486             logger.log(Level.INFO, 
"Didn't find any Chrome download files."); 
 
  491         Collection<BlackboardArtifact> bbartifacts = 
new ArrayList<>();
 
  493         while (j < downloadFiles.size()) {
 
  494             AbstractFile downloadFile = downloadFiles.get(j++);
 
  495             if (downloadFile.getSize() == 0) {
 
  498             String temps = RAImageIngestModule.getRATempPath(currentCase, 
"chrome") + File.separator + downloadFile.getName() + j + 
".db"; 
 
  500                 ContentUtils.writeToFile(downloadFile, 
new File(temps), context::dataSourceIngestIsCancelled);
 
  501             } 
catch (ReadContentInputStreamException ex) {
 
  502                 logger.log(Level.WARNING, String.format(
"Error reading Chrome download artifacts file '%s' (id=%d).",
 
  503                         downloadFile.getName(), downloadFile.getId()), ex); 
 
  504                 this.addErrorMessage(NbBundle.getMessage(
this.getClass(), 
"Chrome.getDownload.errMsg.errAnalyzeFiles1",
 
  505                         this.getName(), downloadFile.getName()));
 
  507             } 
catch (IOException ex) {
 
  508                 logger.log(Level.SEVERE, String.format(
"Error writing temp sqlite db file '%s' for Chrome download artifacts file '%s' (id=%d).",
 
  509                         temps, downloadFile.getName(), downloadFile.getId()), ex); 
 
  510                 this.addErrorMessage(NbBundle.getMessage(
this.getClass(), 
"Chrome.getDownload.errMsg.errAnalyzeFiles1",
 
  511                         this.getName(), downloadFile.getName()));
 
  514             File dbFile = 
new File(temps);
 
  515             if (context.dataSourceIngestIsCancelled()) {
 
  520             List<HashMap<String, Object>> tempList;
 
  522             if (isChromePreVersion30(temps)) {
 
  523                 tempList = this.dbConnect(temps, DOWNLOAD_QUERY);
 
  525                 tempList = this.dbConnect(temps, DOWNLOAD_QUERY_V30);
 
  528             logger.log(Level.INFO, 
"{0}- Now getting downloads from {1} with {2} artifacts identified.", 
new Object[]{moduleName, temps, tempList.size()}); 
 
  529             for (HashMap<String, Object> result : tempList) {
 
  530                 Collection<BlackboardAttribute> bbattributes = 
new ArrayList<>();
 
  531                 String fullPath = result.get(
"full_path").toString(); 
 
  532                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
 
  533                         RecentActivityExtracterModuleFactory.getModuleName(), fullPath)); 
 
  534                 long pathID = Util.findID(dataSource, fullPath); 
 
  536                     bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH_ID,
 
  537                             NbBundle.getMessage(
this.getClass(),
 
  538                                     "Chrome.parentModuleName"), pathID));
 
  540                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
 
  541                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  542                         ((result.get(
"url").toString() != null) ? result.get(
"url").toString() : 
""))); 
 
  544                 Long time = (Long.valueOf(result.get(
"start_time").toString()) / 1000000) - Long.valueOf(
"11644473600"); 
 
  548                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
 
  549                         RecentActivityExtracterModuleFactory.getModuleName(), time));
 
  550                 String domain = NetworkUtils.extractDomain((result.get(
"url").toString() != null) ? result.get(
"url").toString() : 
""); 
 
  551                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
 
  552                         RecentActivityExtracterModuleFactory.getModuleName(), domain));
 
  553                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
 
  554                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  555                         NbBundle.getMessage(this.getClass(), 
"Chrome.moduleName")));
 
  557                 BlackboardArtifact bbart = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, downloadFile, bbattributes);
 
  559                     bbartifacts.add(bbart);
 
  564                     for (AbstractFile downloadedFile : fileManager.findFiles(dataSource, FilenameUtils.getName(fullPath), FilenameUtils.getPath(fullPath))) {
 
  565                         BlackboardArtifact downloadSourceArt =  downloadedFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_DOWNLOAD_SOURCE);
 
  566                         downloadSourceArt.addAttributes(createDownloadSourceAttributes(result.get(
"url").toString()));
 
  568                         bbartifacts.add(downloadSourceArt);
 
  571                 } 
catch (TskCoreException ex) {
 
  572                      logger.log(Level.SEVERE, String.format(
"Error creating download source artifact for file  '%s'", fullPath), ex); 
 
  579         if( !bbartifacts.isEmpty() ) {
 
  580             postArtifacts(bbartifacts);
 
  587     private void getLogins() {
 
  589         FileManager fileManager = currentCase.getServices().getFileManager();
 
  590         List<AbstractFile> loginDataFiles;
 
  592             loginDataFiles = fileManager.findFiles(dataSource, 
"Login Data", 
"Chrome"); 
 
  593         } 
catch (TskCoreException ex) {
 
  594             String msg = NbBundle.getMessage(this.getClass(), 
"Chrome.getLogin.errMsg.errGettingFiles");
 
  595             logger.log(Level.SEVERE, msg, ex);
 
  596             this.addErrorMessage(this.getName() + 
": " + msg);
 
  600         if (loginDataFiles.isEmpty()) {
 
  601             logger.log(Level.INFO, 
"Didn't find any Chrome Login Data files."); 
 
  606         Collection<BlackboardArtifact> bbartifacts = 
new ArrayList<>();
 
  608         while (j < loginDataFiles.size()) {
 
  609             AbstractFile loginDataFile = loginDataFiles.get(j++);
 
  610             if (loginDataFile.getSize() == 0) {
 
  613             String temps = RAImageIngestModule.getRATempPath(currentCase, 
"chrome") + File.separator + loginDataFile.getName() + j + 
".db"; 
 
  615                 ContentUtils.writeToFile(loginDataFile, 
new File(temps), context::dataSourceIngestIsCancelled);
 
  616             } 
catch (ReadContentInputStreamException ex) {
 
  617                 logger.log(Level.WARNING, String.format(
"Error reading Chrome login artifacts file '%s' (id=%d).",
 
  618                         loginDataFile.getName(), loginDataFile.getId()), ex); 
 
  619                 this.addErrorMessage(NbBundle.getMessage(
this.getClass(), 
"Chrome.getLogin.errMsg.errAnalyzingFiles",
 
  620                         this.getName(), loginDataFile.getName()));
 
  622             } 
catch (IOException ex) {
 
  623                 logger.log(Level.SEVERE, String.format(
"Error writing temp sqlite db file '%s' for Chrome login artifacts file '%s' (id=%d).",
 
  624                         temps, loginDataFile.getName(), loginDataFile.getId()), ex); 
 
  625                 this.addErrorMessage(NbBundle.getMessage(
this.getClass(), 
"Chrome.getLogin.errMsg.errAnalyzingFiles",
 
  626                         this.getName(), loginDataFile.getName()));
 
  629             File dbFile = 
new File(temps);
 
  630             if (context.dataSourceIngestIsCancelled()) {
 
  634             List<HashMap<String, Object>> tempList = this.dbConnect(temps, LOGIN_QUERY);
 
  635             logger.log(Level.INFO, 
"{0}- Now getting login information from {1} with {2}artifacts identified.", 
new Object[]{moduleName, temps, tempList.size()}); 
 
  636             for (HashMap<String, Object> result : tempList) {
 
  637                 Collection<BlackboardAttribute> bbattributes = 
new ArrayList<>();
 
  639                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
 
  640                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  641                         ((result.get(
"origin_url").toString() != null) ? result.get(
"origin_url").toString() : 
""))); 
 
  644                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
 
  645                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  646                         (Long.valueOf(result.get(
"date_created").toString()) / 1000000) - Long.valueOf(
"11644473600"))); 
 
  648                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED,
 
  649                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  650                         (NetworkUtils.extractDomain((result.get(
"origin_url").toString() != null) ? result.get(
"origin_url").toString() : 
"")))); 
 
  652                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
 
  653                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  654                         ((result.get(
"username_value").toString() != null) ? result.get(
"username_value").toString().replaceAll(
"'", 
"''") : 
""))); 
 
  656                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
 
  657                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  658                         ((result.get(
"signon_realm").toString() != null) ? result.get(
"signon_realm").toString() : 
""))); 
 
  660                 BlackboardArtifact bbart = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_SERVICE_ACCOUNT, loginDataFile, bbattributes);
 
  662                     bbartifacts.add(bbart);
 
  669         if( !bbartifacts.isEmpty() ) {
 
  670             postArtifacts(bbartifacts);
 
  678     private void getAutofill() {
 
  680         FileManager fileManager = currentCase.getServices().getFileManager();
 
  681         List<AbstractFile> webDataFiles;
 
  683             webDataFiles = fileManager.findFiles(dataSource, 
"Web Data", 
"Chrome"); 
 
  684         } 
catch (TskCoreException ex) {
 
  685             String msg = NbBundle.getMessage(this.getClass(), 
"Chrome.getAutofills.errMsg.errGettingFiles");
 
  686             logger.log(Level.SEVERE, msg, ex);
 
  687             this.addErrorMessage(this.getName() + 
": " + msg);
 
  691         if (webDataFiles.isEmpty()) {
 
  692             logger.log(Level.INFO, 
"Didn't find any Chrome Web Data files."); 
 
  697         Collection<BlackboardArtifact> bbartifacts = 
new ArrayList<>();
 
  699         while (j < webDataFiles.size()) {
 
  700             AbstractFile webDataFile = webDataFiles.get(j++);
 
  701             if (webDataFile.getSize() == 0) {
 
  704             String tempFilePath = RAImageIngestModule.getRATempPath(currentCase, 
"chrome") + File.separator + webDataFile.getName() + j + 
".db"; 
 
  706                 ContentUtils.writeToFile(webDataFile, 
new File(tempFilePath), context::dataSourceIngestIsCancelled);
 
  707             } 
catch (ReadContentInputStreamException ex) {
 
  708                 logger.log(Level.WARNING, String.format(
"Error reading Chrome Autofill artifacts file '%s' (id=%d).",
 
  709                         webDataFile.getName(), webDataFile.getId()), ex); 
 
  710                 this.addErrorMessage(NbBundle.getMessage(
this.getClass(), 
"Chrome.getAutofill.errMsg.errAnalyzingFiles",
 
  711                         this.getName(), webDataFile.getName()));
 
  713             } 
catch (IOException ex) {
 
  714                 logger.log(Level.SEVERE, String.format(
"Error writing temp sqlite db file '%s' for Chrome Web data file '%s' (id=%d).",
 
  715                         tempFilePath, webDataFile.getName(), webDataFile.getId()), ex); 
 
  716                 this.addErrorMessage(NbBundle.getMessage(
this.getClass(), 
"Chrome.getLogin.errMsg.errAnalyzingFiles",
 
  717                         this.getName(), webDataFile.getName()));
 
  720             File dbFile = 
new File(tempFilePath);
 
  721             if (context.dataSourceIngestIsCancelled()) {
 
  727             boolean isSchemaV8X = Util.checkColumn(
"date_created", 
"autofill", tempFilePath);
 
  730             bbartifacts.addAll(getFormAutofillArtifacts(webDataFile, tempFilePath, isSchemaV8X));
 
  732             bbartifacts.addAll(getFormAddressArtifacts(webDataFile, tempFilePath, isSchemaV8X));
 
  737         if( !bbartifacts.isEmpty() ){
 
  738             postArtifacts(bbartifacts);
 
  751     private Collection<BlackboardArtifact> getFormAutofillArtifacts (AbstractFile webDataFile, String dbFilePath , 
boolean isSchemaV8X ) {
 
  753         Collection<BlackboardArtifact> bbartifacts = 
new ArrayList<>();
 
  756         String autoFillquery = (isSchemaV8X) ? AUTOFILL_QUERY_V8X  
 
  759         List<HashMap<String, Object>> autofills = this.dbConnect(dbFilePath, autoFillquery);
 
  760         logger.log(Level.INFO, 
"{0}- Now getting Autofill information from {1} with {2}artifacts identified.", 
new Object[]{moduleName, dbFilePath, autofills.size()}); 
 
  761         for (HashMap<String, Object> result : autofills) {
 
  762             Collection<BlackboardAttribute> bbattributes = 
new ArrayList<>();
 
  765             bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME,
 
  766                     NbBundle.getMessage(
this.getClass(), 
"Chrome.parentModuleName"),
 
  767                     ((result.get(
"name").toString() != null) ? result.get(
"name").toString() : 
""))); 
 
  769             bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE,
 
  770                     RecentActivityExtracterModuleFactory.getModuleName(),
 
  771                     ((result.get(
"value").toString() != null) ? result.get(
"value").toString() : 
""))); 
 
  773             bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COUNT,
 
  774                     RecentActivityExtracterModuleFactory.getModuleName(),
 
  775                     (Integer.valueOf(result.get(
"count").toString())))); 
 
  777              bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
 
  778                     RecentActivityExtracterModuleFactory.getModuleName(),
 
  779                     Long.valueOf(result.get(
"date_created").toString()))); 
 
  783                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
 
  784                     RecentActivityExtracterModuleFactory.getModuleName(),
 
  785                     Long.valueOf(result.get(
"date_last_used").toString()))); 
 
  789             BlackboardArtifact bbart = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_WEB_FORM_AUTOFILL, webDataFile, bbattributes);
 
  791                 bbartifacts.add(bbart);
 
  808     private Collection<BlackboardArtifact> getFormAddressArtifacts (AbstractFile webDataFile, String dbFilePath , 
boolean isSchemaV8X ) {
 
  809         Collection<BlackboardArtifact> bbartifacts = 
new ArrayList<>();
 
  811         String webformAddressQuery = (isSchemaV8X) ? WEBFORM_ADDRESS_QUERY_V8X 
 
  812                                                     : WEBFORM_ADDRESS_QUERY;
 
  815         List<HashMap<String, Object>> addresses = this.dbConnect(dbFilePath, webformAddressQuery);
 
  816         logger.log(Level.INFO, 
"{0}- Now getting Web form addresses from {1} with {2}artifacts identified.", 
new Object[]{moduleName, dbFilePath, addresses.size()}); 
 
  817         for (HashMap<String, Object> result : addresses) {
 
  818             Collection<BlackboardAttribute> bbattributes = 
new ArrayList<>();
 
  821             String first_name = result.get(
"first_name").toString() != null ? result.get(
"first_name").toString() : 
"";
 
  822             String middle_name = result.get(
"middle_name").toString() != null ? result.get(
"middle_name").toString() : 
"";
 
  823             String last_name = result.get(
"last_name").toString() != null ? result.get(
"last_name").toString() : 
"";
 
  826             String email_Addr = result.get(
"email").toString() != null ? result.get(
"email").toString() : 
"";
 
  827             String phone_number = result.get(
"number").toString() != null ? result.get(
"number").toString() : 
"";
 
  830             String city = result.get(
"city").toString() != null ? result.get(
"city").toString() : 
"";
 
  831             String state = result.get(
"state").toString() != null ? result.get(
"state").toString() : 
"";
 
  832             String zipcode = result.get(
"zipcode").toString() != null ? result.get(
"zipcode").toString() : 
"";
 
  833             String country_code = result.get(
"country_code").toString() != null ? result.get(
"country_code").toString() : 
"";
 
  836             String full_name = 
"";
 
  837             String street_address = 
"";
 
  838             long date_modified = 0;
 
  843                 full_name = result.get(
"full_name").toString() != null ? result.get(
"full_name").toString() : 
"";
 
  844                 street_address = result.get(
"street_address").toString() != null ? result.get(
"street_address").toString() : 
"";
 
  845                 date_modified = result.get(
"date_modified").toString() != null ? Long.valueOf(result.get(
"date_modified").toString()) : 0;
 
  846                 use_count = result.get(
"use_count").toString() != null ? Integer.valueOf(result.get(
"use_count").toString()) : 0;
 
  847                 use_date = result.get(
"use_date").toString() != null ? Long.valueOf(result.get(
"use_date").toString()) : 0;   
 
  849                 String address_line_1 = result.get(
"address_line_1").toString() != null ? result.get(
"street_address").toString() : 
""; 
 
  850                 String address_line_2 = result.get(
"address_line_2").toString() != null ? result.get(
"address_line_2").toString() : 
"";
 
  851                 street_address = String.join(
" ", address_line_1, address_line_2);
 
  855             if (email_Addr != null && !email_Addr.isEmpty()) {
 
  857                     Case.getCurrentCaseThrows().getSleuthkitCase().getCommunicationsManager().createAccountFileInstance(Account.Type.EMAIL, email_Addr,  NbBundle.getMessage(
this.getClass(), 
"Chrome.parentModuleName"), webDataFile);
 
  858                 } 
catch (NoCurrentCaseException | TskCoreException ex) {
 
  859                     logger.log(Level.SEVERE, String.format(
"Error creating email account instance for '%s' from Chrome WebData file '%s' .",
 
  860                         email_Addr, webDataFile.getName()), ex); 
 
  864             if (phone_number != null && !phone_number.isEmpty()) {
 
  866                     Case.getCurrentCaseThrows().getSleuthkitCase().getCommunicationsManager().createAccountFileInstance(Account.Type.PHONE, phone_number,  NbBundle.getMessage(
this.getClass(), 
"Chrome.parentModuleName"), webDataFile);
 
  867                 } 
catch (NoCurrentCaseException | TskCoreException ex) {
 
  868                     logger.log(Level.SEVERE, String.format(
"Error creating phone account instance for '%s' from Chrome WebData file '%s' .",
 
  869                         phone_number, webDataFile.getName()), ex); 
 
  874             if (full_name == null || full_name.isEmpty()) {
 
  875                 full_name = String.join(
" ", first_name, middle_name, last_name);
 
  877             bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME_PERSON,
 
  878                     RecentActivityExtracterModuleFactory.getModuleName(),
 
  881             bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_EMAIL,
 
  882                     RecentActivityExtracterModuleFactory.getModuleName(),
 
  885             bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER,
 
  886                     RecentActivityExtracterModuleFactory.getModuleName(),
 
  889             String locationAddress = String.join(
", ", street_address, city, state, zipcode, country_code);
 
  890             bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LOCATION,
 
  891                     RecentActivityExtracterModuleFactory.getModuleName(),
 
  894             if (date_modified > 0) {
 
  895                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_MODIFIED,
 
  896                     RecentActivityExtracterModuleFactory.getModuleName(),
 
  901                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COUNT,
 
  902                     RecentActivityExtracterModuleFactory.getModuleName(),
 
  907                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
 
  908                     RecentActivityExtracterModuleFactory.getModuleName(),
 
  913             BlackboardArtifact bbart = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_WEB_FORM_ADDRESS, webDataFile, bbattributes);
 
  915                 bbartifacts.add(bbart);
 
  922     private boolean isChromePreVersion30(String temps) {
 
  923         String query = 
"PRAGMA table_info(downloads)"; 
 
  924         List<HashMap<String, Object>> columns = this.dbConnect(temps, query);
 
  925         for (HashMap<String, Object> col : columns) {
 
  926             if (col.get(
"name").equals(
"url")) {