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;
 
   32 import java.io.FileNotFoundException;
 
   33 import java.io.FileReader;
 
   34 import java.io.IOException;
 
   35 import java.io.UnsupportedEncodingException;
 
   36 import java.net.URLDecoder;
 
   37 import java.util.ArrayList;
 
   38 import java.util.Arrays;
 
   39 import java.util.Collection;
 
   40 import java.util.HashMap;
 
   41 import java.util.HashSet;
 
   42 import java.util.List;
 
   44 import java.util.logging.Level;
 
   45 import org.apache.commons.io.FilenameUtils;
 
   47 import org.openide.util.NbBundle;
 
   48 import org.openide.util.NbBundle.Messages;
 
   62 import org.
sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
 
   64 import org.
sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
 
   66 import org.
sleuthkit.datamodel.ReadContentInputStream.ReadContentInputStreamException;
 
   70     "Progress_Message_Firefox_History=Firefox History",
 
   71     "Progress_Message_Firefox_Bookmarks=Firefox Bookmarks",
 
   72     "Progress_Message_Firefox_Cookies=Firefox Cookies",
 
   73     "Progress_Message_Firefox_Downloads=Firefox Downloads",
 
   74     "Progress_Message_Firefox_FormHistory=Firefox Form History",
 
   75     "Progress_Message_Firefox_AutoFill=Firefox Auto Fill" 
   81 class Firefox extends Extract {
 
   83     private static final Logger logger = Logger.getLogger(Firefox.class.getName());
 
   84     private static final String PLACE_URL_PREFIX = 
"place:";
 
   85     private static final String HISTORY_QUERY = 
"SELECT moz_historyvisits.id, url, title, visit_count,(visit_date/1000000) AS visit_date,from_visit," 
   86             + 
"(SELECT url FROM moz_historyvisits history, moz_places places where history.id = moz_historyvisits.from_visit and history.place_id = places.id ) as ref " 
   87             + 
"FROM moz_places, moz_historyvisits " 
   88             + 
"WHERE moz_places.id = moz_historyvisits.place_id " 
   90     private static final String COOKIE_QUERY = 
"SELECT name,value,host,expiry,(lastAccessed/1000000) AS lastAccessed,(creationTime/1000000) AS creationTime FROM moz_cookies"; 
 
   91     private static final String COOKIE_QUERY_V3 = 
"SELECT name,value,host,expiry,(lastAccessed/1000000) AS lastAccessed FROM moz_cookies"; 
 
   92     private static final String BOOKMARK_QUERY = 
"SELECT fk, moz_bookmarks.title, url, (moz_bookmarks.dateAdded/1000000) AS dateAdded FROM moz_bookmarks INNER JOIN moz_places ON moz_bookmarks.fk=moz_places.id"; 
 
   93     private static final String DOWNLOAD_QUERY = 
"SELECT target, source,(startTime/1000000) AS startTime, maxBytes FROM moz_downloads"; 
 
   94     private static final String DOWNLOAD_QUERY_V24 = 
"SELECT url, content AS target, (lastModified/1000000) AS lastModified " 
   95                                                         + 
" FROM moz_places, moz_annos, moz_anno_attributes "  
   96                                                         + 
" WHERE moz_places.id = moz_annos.place_id"  
   97                                                         + 
" AND moz_annos.anno_attribute_id = moz_anno_attributes.id" 
   98                                                         + 
" AND moz_anno_attributes.name='downloads/destinationFileURI'"; 
 
   99     private static final String FORMHISTORY_QUERY = 
"SELECT fieldname, value FROM moz_formhistory";
 
  100     private static final String FORMHISTORY_QUERY_V64 = 
"SELECT fieldname, value, timesUsed, firstUsed, lastUsed FROM moz_formhistory";
 
  101     private final IngestServices services = IngestServices.getInstance();
 
  102     private Content dataSource;
 
  103     private IngestJobContext context;
 
  106         moduleName = NbBundle.getMessage(Firefox.class, 
"Firefox.moduleName");
 
  110     public void process(Content dataSource, IngestJobContext context, DataSourceIngestModuleProgress progressBar) {
 
  111         this.dataSource = dataSource;
 
  112         this.context = context;
 
  115         progressBar.progress(Bundle.Progress_Message_Firefox_History());
 
  118         progressBar.progress(Bundle.Progress_Message_Firefox_Bookmarks());
 
  121         progressBar.progress(Bundle.Progress_Message_Firefox_Downloads());
 
  124         progressBar.progress(Bundle.Progress_Message_Firefox_Cookies());
 
  127         progressBar.progress(Bundle.Progress_Message_Firefox_FormHistory());
 
  128         this.getFormsHistory();
 
  130         progressBar.progress(Bundle.Progress_Message_Firefox_AutoFill());
 
  131         this.getAutofillProfiles();
 
  134     private void getHistory() {
 
  135         FileManager fileManager = currentCase.getServices().getFileManager();
 
  136         List<AbstractFile> historyFiles;
 
  138             historyFiles = fileManager.findFiles(dataSource, 
"places.sqlite", 
"Firefox"); 
 
  139         } 
catch (TskCoreException ex) {
 
  140             String msg = NbBundle.getMessage(this.getClass(), 
"Firefox.getHistory.errMsg.errFetchingFiles");
 
  141             logger.log(Level.WARNING, msg);
 
  142             this.addErrorMessage(this.getName() + 
": " + msg);
 
  146         if (historyFiles.isEmpty()) {
 
  147             String msg = NbBundle.getMessage(this.getClass(), 
"Firefox.getHistory.errMsg.noFilesFound");
 
  148             logger.log(Level.INFO, msg);
 
  153         Collection<BlackboardArtifact> bbartifacts = 
new ArrayList<>();
 
  155         for (AbstractFile historyFile : historyFiles) {
 
  156             if (historyFile.getSize() == 0) {
 
  160             String fileName = historyFile.getName();
 
  161             String temps = RAImageIngestModule.getRATempPath(currentCase, 
"firefox") + File.separator + fileName + j + 
".db"; 
 
  163                 ContentUtils.writeToFile(historyFile, 
new File(temps), context::dataSourceIngestIsCancelled);
 
  164             } 
catch (ReadContentInputStreamException ex) {
 
  165                 logger.log(Level.WARNING, String.format(
"Error reading Firefox web history artifacts file '%s' (id=%d).",
 
  166                         fileName, historyFile.getId()), ex); 
 
  167                 this.addErrorMessage(
 
  168                         NbBundle.getMessage(
this.getClass(), 
"Firefox.getHistory.errMsg.errAnalyzeFile", this.getName(),
 
  171             } 
catch (IOException ex) {
 
  172                 logger.log(Level.SEVERE, String.format(
"Error writing temp sqlite db file '%s' for Firefox web history artifacts file '%s' (id=%d).",
 
  173                         temps, fileName, historyFile.getId()), ex); 
 
  174                 this.addErrorMessage(
 
  175                         NbBundle.getMessage(
this.getClass(), 
"Firefox.getHistory.errMsg.errAnalyzeFile", this.getName(),
 
  179             File dbFile = 
new File(temps);
 
  180             if (context.dataSourceIngestIsCancelled()) {
 
  184             List<HashMap<String, Object>> tempList = this.dbConnect(temps, HISTORY_QUERY);
 
  185             logger.log(Level.INFO, 
"{0} - Now getting history from {1} with {2} artifacts identified.", 
new Object[]{moduleName, temps, tempList.size()}); 
 
  186             for (HashMap<String, Object> result : tempList) {
 
  187                 String url = result.get(
"url").toString();
 
  189                 Collection<BlackboardAttribute> bbattributes = 
new ArrayList<>();
 
  190                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
 
  191                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  192                         ((url != null) ? url : 
""))); 
 
  194                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
 
  195                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  196                         (Long.valueOf(result.get(
"visit_date").toString())))); 
 
  197                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REFERRER,
 
  198                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  199                         ((result.get(
"ref").toString() != null) ? result.get(
"ref").toString() : 
""))); 
 
  200                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TITLE,
 
  201                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  202                         ((result.get(
"title").toString() != null) ? result.get(
"title").toString() : 
""))); 
 
  203                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
 
  204                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  205                         NbBundle.getMessage(this.getClass(), 
"Firefox.moduleName")));
 
  206                 String domain = extractDomain(url);
 
  207                 if (domain != null && domain.isEmpty() == 
false) {
 
  208                     bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
 
  209                         RecentActivityExtracterModuleFactory.getModuleName(), domain)); 
 
  212                 BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY, historyFile, bbattributes);
 
  214                     bbartifacts.add(bbart);
 
  221         services.fireModuleDataEvent(
new ModuleDataEvent(
 
  222                 NbBundle.getMessage(
this.getClass(), 
"Firefox.parentModuleName"),
 
  223                 BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY, bbartifacts));
 
  229     private void getBookmark() {
 
  231         FileManager fileManager = currentCase.getServices().getFileManager();
 
  232         List<AbstractFile> bookmarkFiles;
 
  234             bookmarkFiles = fileManager.findFiles(dataSource, 
"places.sqlite", 
"Firefox"); 
 
  235         } 
catch (TskCoreException ex) {
 
  236             String msg = NbBundle.getMessage(this.getClass(), 
"Firefox.getBookmark.errMsg.errFetchFiles");
 
  237             logger.log(Level.WARNING, msg);
 
  238             this.addErrorMessage(this.getName() + 
": " + msg);
 
  242         if (bookmarkFiles.isEmpty()) {
 
  243             logger.log(Level.INFO, 
"Didn't find any firefox bookmark files."); 
 
  248         Collection<BlackboardArtifact> bbartifacts = 
new ArrayList<>();
 
  250         for (AbstractFile bookmarkFile : bookmarkFiles) {
 
  251             if (bookmarkFile.getSize() == 0) {
 
  254             String fileName = bookmarkFile.getName();
 
  255             String temps = RAImageIngestModule.getRATempPath(currentCase, 
"firefox") + File.separator + fileName + j + 
".db"; 
 
  257                 ContentUtils.writeToFile(bookmarkFile, 
new File(temps), context::dataSourceIngestIsCancelled);
 
  258             } 
catch (ReadContentInputStreamException ex) {
 
  259                 logger.log(Level.WARNING, String.format(
"Error reading Firefox bookmark artifacts file '%s' (id=%d).",
 
  260                         fileName, bookmarkFile.getId()), ex); 
 
  261                 this.addErrorMessage(
 
  262                         NbBundle.getMessage(
this.getClass(), 
"Firefox.getHistory.errMsg.errAnalyzeFile", this.getName(),
 
  265             } 
catch (IOException ex) {
 
  266                 logger.log(Level.SEVERE, String.format(
"Error writing temp sqlite db file '%s' for Firefox bookmark artifacts file '%s' (id=%d).",
 
  267                         temps, fileName, bookmarkFile.getId()), ex); 
 
  268                 this.addErrorMessage(NbBundle.getMessage(
this.getClass(), 
"Firefox.getBookmark.errMsg.errAnalyzeFile",
 
  269                         this.getName(), fileName));
 
  272             File dbFile = 
new File(temps);
 
  273             if (context.dataSourceIngestIsCancelled()) {
 
  277             List<HashMap<String, Object>> tempList = this.dbConnect(temps, BOOKMARK_QUERY);
 
  278             logger.log(Level.INFO, 
"{0} - Now getting bookmarks from {1} with {2} artifacts identified.", 
new Object[]{moduleName, temps, tempList.size()}); 
 
  279             for (HashMap<String, Object> result : tempList) {
 
  280                 String url = result.get(
"url").toString();
 
  282                 Collection<BlackboardAttribute> bbattributes = 
new ArrayList<>();
 
  283                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
 
  284                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  285                         ((url != null) ? url : 
""))); 
 
  286                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TITLE,
 
  287                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  288                         ((result.get(
"title").toString() != null) ? result.get(
"title").toString() : 
""))); 
 
  289                 if (Long.valueOf(result.get(
"dateAdded").toString()) > 0) { 
 
  290                     bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
 
  291                             RecentActivityExtracterModuleFactory.getModuleName(),
 
  292                             (Long.valueOf(result.get(
"dateAdded").toString())))); 
 
  294                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
 
  295                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  296                         NbBundle.getMessage(this.getClass(), 
"Firefox.moduleName")));
 
  297                 String domain = extractDomain(url);
 
  298                 if (domain != null && domain.isEmpty() == 
false) {
 
  299                     bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
 
  300                         RecentActivityExtracterModuleFactory.getModuleName(), domain)); 
 
  303                 BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_BOOKMARK, bookmarkFile, bbattributes);
 
  305                     bbartifacts.add(bbart);
 
  312         services.fireModuleDataEvent(
new ModuleDataEvent(
 
  313                 NbBundle.getMessage(
this.getClass(), 
"Firefox.parentModuleName"),
 
  314                 BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK, bbartifacts));
 
  320     private void getCookie() {
 
  321         FileManager fileManager = currentCase.getServices().getFileManager();
 
  322         List<AbstractFile> cookiesFiles;
 
  324             cookiesFiles = fileManager.findFiles(dataSource, 
"cookies.sqlite", 
"Firefox"); 
 
  325         } 
catch (TskCoreException ex) {
 
  326             String msg = NbBundle.getMessage(this.getClass(), 
"Firefox.getCookie.errMsg.errFetchFile");
 
  327             logger.log(Level.WARNING, msg);
 
  328             this.addErrorMessage(this.getName() + 
": " + msg);
 
  332         if (cookiesFiles.isEmpty()) {
 
  333             logger.log(Level.INFO, 
"Didn't find any Firefox cookie files."); 
 
  338         Collection<BlackboardArtifact> bbartifacts = 
new ArrayList<>();
 
  340         for (AbstractFile cookiesFile : cookiesFiles) {
 
  341             if (cookiesFile.getSize() == 0) {
 
  344             String fileName = cookiesFile.getName();
 
  345             String temps = RAImageIngestModule.getRATempPath(currentCase, 
"firefox") + File.separator + fileName + j + 
".db"; 
 
  347                 ContentUtils.writeToFile(cookiesFile, 
new File(temps), context::dataSourceIngestIsCancelled);
 
  348             } 
catch (ReadContentInputStreamException ex) {
 
  349                 logger.log(Level.WARNING, String.format(
"Error reading Firefox cookie artifacts file '%s' (id=%d).",
 
  350                         fileName, cookiesFile.getId()), ex); 
 
  351                 this.addErrorMessage(
 
  352                         NbBundle.getMessage(
this.getClass(), 
"Firefox.getHistory.errMsg.errAnalyzeFile", this.getName(),
 
  355             } 
catch (IOException ex) {
 
  356                 logger.log(Level.SEVERE, String.format(
"Error writing temp sqlite db file '%s' for Firefox cookie artifacts file '%s' (id=%d).",
 
  357                         temps, fileName, cookiesFile.getId()), ex); 
 
  358                 this.addErrorMessage(
 
  359                         NbBundle.getMessage(
this.getClass(), 
"Firefox.getCookie.errMsg.errAnalyzeFile", this.getName(),
 
  363             File dbFile = 
new File(temps);
 
  364             if (context.dataSourceIngestIsCancelled()) {
 
  368             boolean checkColumn = Util.checkColumn(
"creationTime", 
"moz_cookies", temps); 
 
  371                 query = COOKIE_QUERY;
 
  373                 query = COOKIE_QUERY_V3;
 
  376             List<HashMap<String, Object>> tempList = this.dbConnect(temps, query);
 
  377             logger.log(Level.INFO, 
"{0} - Now getting cookies from {1} with {2} artifacts identified.", 
new Object[]{moduleName, temps, tempList.size()}); 
 
  378             for (HashMap<String, Object> result : tempList) {
 
  379                 String host = result.get(
"host").toString();
 
  381                 Collection<BlackboardAttribute> bbattributes = 
new ArrayList<>();
 
  382                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
 
  383                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  384                         ((host != null) ? host : 
""))); 
 
  385                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME,
 
  386                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  387                         (Long.valueOf(result.get(
"lastAccessed").toString())))); 
 
  388                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME,
 
  389                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  390                         ((result.get(
"name").toString() != null) ? result.get(
"name").toString() : 
""))); 
 
  391                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE,
 
  392                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  393                         ((result.get(
"value").toString() != null) ? result.get(
"value").toString() : 
""))); 
 
  394                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
 
  395                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  396                         NbBundle.getMessage(this.getClass(), 
"Firefox.moduleName")));
 
  398                 if (checkColumn == 
true) {
 
  399                     bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
 
  400                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  401                         (Long.valueOf(result.get(
"creationTime").toString())))); 
 
  403                 String domain = extractDomain(host);
 
  404                 if (domain != null && domain.isEmpty() == 
false) {
 
  405                     domain = domain.replaceFirst(
"^\\.+(?!$)", 
"");
 
  406                     bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
 
  407                         RecentActivityExtracterModuleFactory.getModuleName(), domain));
 
  410                 BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_COOKIE, cookiesFile, bbattributes);
 
  412                     bbartifacts.add(bbart);
 
  419         services.fireModuleDataEvent(
new ModuleDataEvent(
 
  420                 NbBundle.getMessage(
this.getClass(), 
"Firefox.parentModuleName"),
 
  421                 BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE, bbartifacts));
 
  427     private void getDownload() {
 
  428         getDownloadPreVersion24();
 
  429         getDownloadVersion24();
 
  437     private void getDownloadPreVersion24() {
 
  439         FileManager fileManager = currentCase.getServices().getFileManager();
 
  440         List<AbstractFile> downloadsFiles;
 
  442             downloadsFiles = fileManager.findFiles(dataSource, 
"downloads.sqlite", 
"Firefox"); 
 
  443         } 
catch (TskCoreException ex) {
 
  444             String msg = NbBundle.getMessage(this.getClass(), 
"Firefox.getDlPre24.errMsg.errFetchFiles");
 
  445             logger.log(Level.WARNING, msg);
 
  446             this.addErrorMessage(this.getName() + 
": " + msg);
 
  450         if (downloadsFiles.isEmpty()) {
 
  451             logger.log(Level.INFO, 
"Didn't find any pre-version-24.0 Firefox download files."); 
 
  456         Collection<BlackboardArtifact> bbartifacts = 
new ArrayList<>();
 
  458         for (AbstractFile downloadsFile : downloadsFiles) {
 
  459             if (downloadsFile.getSize() == 0) {
 
  462             String fileName = downloadsFile.getName();
 
  463             String temps = RAImageIngestModule.getRATempPath(currentCase, 
"firefox") + File.separator + fileName + j + 
".db"; 
 
  466                 ContentUtils.writeToFile(downloadsFile, 
new File(temps), context::dataSourceIngestIsCancelled);
 
  467             } 
catch (ReadContentInputStreamException ex) {
 
  468                 logger.log(Level.WARNING, String.format(
"Error reading Firefox download artifacts file '%s' (id=%d).",
 
  469                         fileName, downloadsFile.getId()), ex); 
 
  470                 this.addErrorMessage(
 
  471                         NbBundle.getMessage(
this.getClass(), 
"Firefox.getHistory.errMsg.errAnalyzeFile", this.getName(),
 
  474             } 
catch (IOException ex) {
 
  475                 logger.log(Level.SEVERE, String.format(
"Error writing temp sqlite db file '%s' for Firefox download artifacts file '%s' (id=%d).",
 
  476                         temps, fileName, downloadsFile.getId()), ex); 
 
  477                 this.addErrorMessage(NbBundle.getMessage(
this.getClass(), 
"Firefox.getDlPre24.errMsg.errAnalyzeFiles",
 
  478                         this.getName(), fileName));
 
  481             File dbFile = 
new File(temps);
 
  482             if (context.dataSourceIngestIsCancelled()) {
 
  487             List<HashMap<String, Object>> tempList = this.dbConnect(temps, DOWNLOAD_QUERY);
 
  488             logger.log(Level.INFO, 
"{0}- Now getting downloads from {1} with {2} artifacts identified.", 
new Object[]{moduleName, temps, tempList.size()}); 
 
  489             for (HashMap<String, Object> result : tempList) {
 
  490                 String source = result.get(
"source").toString();
 
  492                 Collection<BlackboardAttribute> bbattributes = 
new ArrayList<>();
 
  494                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
 
  495                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  498                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
 
  499                        RecentActivityExtracterModuleFactory.getModuleName(),
 
  500                         (Long.valueOf(result.get(
"startTime").toString())))); 
 
  502                 String target = result.get(
"target").toString(); 
 
  503                 String downloadedFilePath = 
"";
 
  504                 if (target != null) {
 
  506                         downloadedFilePath = URLDecoder.decode(target.replaceAll(
"file:///", 
""), 
"UTF-8"); 
 
  507                         bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
 
  508                                 RecentActivityExtracterModuleFactory.getModuleName(),
 
  509                                 downloadedFilePath));
 
  510                         long pathID = Util.findID(dataSource, downloadedFilePath);
 
  512                             bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH_ID,
 
  513                                     RecentActivityExtracterModuleFactory.getModuleName(),
 
  516                     } 
catch (UnsupportedEncodingException ex) {
 
  517                         logger.log(Level.SEVERE, 
"Error decoding Firefox download URL in " + temps, ex); 
 
  522                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
 
  523                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  524                         NbBundle.getMessage(this.getClass(), 
"Firefox.moduleName")));
 
  525                 String domain = extractDomain(source);
 
  526                 if (domain != null && domain.isEmpty() == 
false) {
 
  527                     bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
 
  528                             RecentActivityExtracterModuleFactory.getModuleName(),
 
  532                 BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, downloadsFile, bbattributes);
 
  534                     bbartifacts.add(bbart);
 
  539                     for (AbstractFile downloadedFile : fileManager.findFiles(dataSource, FilenameUtils.getName(downloadedFilePath), FilenameUtils.getPath(downloadedFilePath))) {
 
  540                         BlackboardArtifact downloadSourceArt =  downloadedFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_DOWNLOAD_SOURCE);
 
  541                         downloadSourceArt.addAttributes(createDownloadSourceAttributes(source));
 
  542                         bbartifacts.add(downloadSourceArt);
 
  545                 } 
catch (TskCoreException ex) {
 
  546                     logger.log(Level.SEVERE, String.format(
"Error creating download source artifact for file  '%s'",
 
  547                         downloadedFilePath), ex); 
 
  551                 this.addErrorMessage(
 
  552                         NbBundle.getMessage(
this.getClass(), 
"Firefox.getDlPre24.errMsg.errParsingArtifacts",
 
  553                                 this.getName(), errors));
 
  560         services.fireModuleDataEvent(
new ModuleDataEvent(
 
  561                 NbBundle.getMessage(
this.getClass(), 
"Firefox.parentModuleName"),
 
  562                 BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, bbartifacts));
 
  570     private void getDownloadVersion24() {
 
  571         FileManager fileManager = currentCase.getServices().getFileManager();
 
  572         List<AbstractFile> downloadsFiles;
 
  574             downloadsFiles = fileManager.findFiles(dataSource, 
"places.sqlite", 
"Firefox"); 
 
  575         } 
catch (TskCoreException ex) {
 
  576             String msg = NbBundle.getMessage(this.getClass(), 
"Firefox.getDlV24.errMsg.errFetchFiles");
 
  577             logger.log(Level.WARNING, msg);
 
  578             this.addErrorMessage(this.getName() + 
": " + msg);
 
  582         if (downloadsFiles.isEmpty()) {
 
  583             logger.log(Level.INFO, 
"Didn't find any version-24.0 Firefox download files."); 
 
  588         Collection<BlackboardArtifact> bbartifacts = 
new ArrayList<>();
 
  590         for (AbstractFile downloadsFile : downloadsFiles) {
 
  591             if (downloadsFile.getSize() == 0) {
 
  594             String fileName = downloadsFile.getName();
 
  595             String temps = RAImageIngestModule.getRATempPath(currentCase, 
"firefox") + File.separator + fileName + 
"-downloads" + j + 
".db"; 
 
  598                 ContentUtils.writeToFile(downloadsFile, 
new File(temps), context::dataSourceIngestIsCancelled);
 
  599             } 
catch (ReadContentInputStreamException ex) {
 
  600                 logger.log(Level.WARNING, String.format(
"Error reading Firefox download artifacts file '%s' (id=%d).",
 
  601                         fileName, downloadsFile.getId()), ex); 
 
  602                 this.addErrorMessage(
 
  603                         NbBundle.getMessage(
this.getClass(), 
"Firefox.getHistory.errMsg.errAnalyzeFile", this.getName(),
 
  606             } 
catch (IOException ex) {
 
  607                 logger.log(Level.SEVERE, String.format(
"Error writing temp sqlite db file '%s' for Firefox download artifacts file '%s' (id=%d).",
 
  608                         temps, fileName, downloadsFile.getId()), ex); 
 
  609                 this.addErrorMessage(
 
  610                         NbBundle.getMessage(
this.getClass(), 
"Firefox.getDlV24.errMsg.errAnalyzeFile", this.getName(),
 
  614             File dbFile = 
new File(temps);
 
  615             if (context.dataSourceIngestIsCancelled()) {
 
  620             List<HashMap<String, Object>> tempList = this.dbConnect(temps, DOWNLOAD_QUERY_V24);
 
  622             logger.log(Level.INFO, 
"{0} - Now getting downloads from {1} with {2} artifacts identified.", 
new Object[]{moduleName, temps, tempList.size()}); 
 
  623             for (HashMap<String, Object> result : tempList) {
 
  624                 String url = result.get(
"url").toString();
 
  626                 Collection<BlackboardAttribute> bbattributes = 
new ArrayList<>();
 
  628                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
 
  629                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  635                 String target = result.get(
"target").toString(); 
 
  636                 String downloadedFilePath = 
"";
 
  637                 if (target != null) {
 
  639                         downloadedFilePath = URLDecoder.decode(target.replaceAll(
"file:///", 
""), 
"UTF-8"); 
 
  640                         bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
 
  641                                 RecentActivityExtracterModuleFactory.getModuleName(),
 
  642                                 downloadedFilePath));
 
  643                         long pathID = Util.findID(dataSource, downloadedFilePath);
 
  645                             bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH_ID,
 
  646                                     RecentActivityExtracterModuleFactory.getModuleName(),
 
  649                     } 
catch (UnsupportedEncodingException ex) {
 
  650                         logger.log(Level.SEVERE, 
"Error decoding Firefox download URL in " + temps, ex); 
 
  654                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
 
  655                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  656                         Long.valueOf(result.get(
"lastModified").toString()))); 
 
  657                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
 
  658                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  659                         NbBundle.getMessage(this.getClass(), 
"Firefox.moduleName")));
 
  660                 String domain = extractDomain(url);
 
  661                 if (domain != null && domain.isEmpty() == 
false) {
 
  662                     bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
 
  663                         RecentActivityExtracterModuleFactory.getModuleName(), domain)); 
 
  666                 BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, downloadsFile, bbattributes);
 
  668                     bbartifacts.add(bbart);
 
  673                     for (AbstractFile downloadedFile : fileManager.findFiles(dataSource, FilenameUtils.getName(downloadedFilePath), FilenameUtils.getPath(downloadedFilePath))) {
 
  674                         BlackboardArtifact downloadSourceArt =  downloadedFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_DOWNLOAD_SOURCE);
 
  675                         downloadSourceArt.addAttributes(createDownloadSourceAttributes(url));
 
  676                         bbartifacts.add(downloadSourceArt);
 
  679                 } 
catch (TskCoreException ex) {
 
  680                     logger.log(Level.SEVERE, String.format(
"Error creating download source artifact for file  '%s'",
 
  681                         downloadedFilePath), ex); 
 
  685                 this.addErrorMessage(NbBundle.getMessage(
this.getClass(), 
"Firefox.getDlV24.errMsg.errParsingArtifacts",
 
  686                         this.getName(), errors));
 
  693         services.fireModuleDataEvent(
new ModuleDataEvent(
 
  694                 NbBundle.getMessage(
this.getClass(), 
"Firefox.parentModuleName"),
 
  695                 BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, bbartifacts));
 
  702     private void getFormsHistory() {
 
  703         FileManager fileManager = currentCase.getServices().getFileManager();
 
  704         List<AbstractFile> formHistoryFiles;
 
  707         Set<String> excludedFieldNames = 
new HashSet<>(Arrays.asList(
 
  713             formHistoryFiles = fileManager.findFiles(dataSource, 
"formhistory.sqlite", 
"Firefox"); 
 
  714         } 
catch (TskCoreException ex) {
 
  715             String msg = NbBundle.getMessage(this.getClass(), 
"Firefox.getFormsAutofill.errMsg.errFetchingFiles");
 
  716             logger.log(Level.WARNING, msg);
 
  717             this.addErrorMessage(this.getName() + 
": " + msg);
 
  721         if (formHistoryFiles.isEmpty()) {
 
  722             String msg = NbBundle.getMessage(this.getClass(), 
"Firefox.getFormsAutofill.errMsg.noFilesFound");
 
  723             logger.log(Level.INFO, msg);
 
  728         Collection<BlackboardArtifact> bbartifacts = 
new ArrayList<>();
 
  730         for (AbstractFile formHistoryFile : formHistoryFiles) {
 
  731             if (formHistoryFile.getSize() == 0) {
 
  735             String fileName = formHistoryFile.getName();
 
  736             String tempFilePath = RAImageIngestModule.getRATempPath(currentCase, 
"firefox") + File.separator + fileName + j + 
".db"; 
 
  738                 ContentUtils.writeToFile(formHistoryFile, 
new File(tempFilePath), context::dataSourceIngestIsCancelled);
 
  739             } 
catch (ReadContentInputStreamException ex) {
 
  740                 logger.log(Level.WARNING, String.format(
"Error reading Firefox web history artifacts file '%s' (id=%d).",
 
  741                         fileName, formHistoryFile.getId()), ex); 
 
  742                 this.addErrorMessage(
 
  743                         NbBundle.getMessage(
this.getClass(), 
"Firefox.getFormsAutofill.errMsg.errAnalyzeFile", this.getName(),
 
  746             } 
catch (IOException ex) {
 
  747                 logger.log(Level.SEVERE, String.format(
"Error writing temp sqlite db file '%s' for Firefox web history artifacts file '%s' (id=%d).",
 
  748                         tempFilePath, fileName, formHistoryFile.getId()), ex); 
 
  749                 this.addErrorMessage(
 
  750                         NbBundle.getMessage(
this.getClass(), 
"Firefox.getFormsAutofill.errMsg.errAnalyzeFile", this.getName(),
 
  754             File dbFile = 
new File(tempFilePath);
 
  755             if (context.dataSourceIngestIsCancelled()) {
 
  761             boolean isFirefoxV64 = Util.checkColumn(
"timesUsed", 
"moz_formhistory", tempFilePath);
 
  762             String formHistoryQuery = (isFirefoxV64) ? FORMHISTORY_QUERY_V64 : FORMHISTORY_QUERY;
 
  764             List<HashMap<String, Object>> tempList = this.dbConnect(tempFilePath, formHistoryQuery);
 
  765             logger.log(Level.INFO, 
"{0} - Now getting history from {1} with {2} artifacts identified.", 
new Object[]{moduleName, tempFilePath, tempList.size()}); 
 
  766             for (HashMap<String, Object> result : tempList) {
 
  767                 Collection<BlackboardAttribute> bbattributes = 
new ArrayList<>();
 
  769                 String fieldName = ((result.get(
"fieldname").toString() != null) ? result.get(
"fieldname").toString() : 
"");
 
  771                 if (excludedFieldNames.contains(fieldName.toLowerCase())) {
 
  775                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME,
 
  776                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  779                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE,
 
  780                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  781                         ((result.get(
"value").toString() != null) ? result.get(
"value").toString() : 
""))); 
 
  785                     bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
 
  786                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  787                         (Long.valueOf(result.get(
"firstUsed").toString()) / 1000000))); 
 
  789                     bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
 
  790                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  791                         (Long.valueOf(result.get(
"lastUsed").toString()) / 1000000))); 
 
  793                     bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COUNT,
 
  794                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  795                         (Integer.valueOf(result.get(
"timesUsed").toString())))); 
 
  799                 BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_FORM_AUTOFILL, formHistoryFile, bbattributes);
 
  801                     this.indexArtifact(bbart);
 
  802                     bbartifacts.add(bbart);
 
  809         services.fireModuleDataEvent(
new ModuleDataEvent(
 
  810                 NbBundle.getMessage(
this.getClass(), 
"Firefox.parentModuleName"),
 
  811                 BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_FORM_AUTOFILL, bbartifacts));
 
  820     private void getAutofillProfiles() {
 
  821         FileManager fileManager = currentCase.getServices().getFileManager();
 
  822         List<AbstractFile> autofillProfilesFiles;
 
  824             autofillProfilesFiles = fileManager.findFiles(dataSource, 
"autofill-profiles.json", 
"Firefox"); 
 
  825         } 
catch (TskCoreException ex) {
 
  826             String msg = NbBundle.getMessage(this.getClass(), 
"Firefox.getAutofillProfiles.errMsg.errGettingFiles");
 
  827             logger.log(Level.SEVERE, msg, ex);
 
  828             this.addErrorMessage(this.getName() + 
": " + msg);
 
  832         if (autofillProfilesFiles.isEmpty()) {
 
  833             logger.log(Level.INFO, 
"Didn't find any Firefox Autofill Profiles files."); 
 
  838         Collection<BlackboardArtifact> bbartifacts = 
new ArrayList<>();
 
  841         while (j < autofillProfilesFiles.size()) {
 
  842             AbstractFile profileFile = autofillProfilesFiles.get(j++);
 
  843             if (profileFile.getSize() == 0) {
 
  846             String temps = RAImageIngestModule.getRATempPath(currentCase, 
"Firefox") + File.separator + profileFile.getName() + j + 
".json"; 
 
  848                 ContentUtils.writeToFile(profileFile, 
new File(temps), context::dataSourceIngestIsCancelled);
 
  849             } 
catch (ReadContentInputStreamException ex) {
 
  850                 logger.log(Level.WARNING, String.format(
"Error reading Firefox Autofill profiles artifacts file '%s' (id=%d).",
 
  851                         profileFile.getName(), profileFile.getId()), ex); 
 
  852                 this.addErrorMessage(NbBundle.getMessage(
this.getClass(), 
"Firefox.getAutofillProfiles.errMsg.errAnalyzingFile",
 
  853                         this.getName(), profileFile.getName()));
 
  855             } 
catch (IOException ex) {
 
  856                 logger.log(Level.SEVERE, String.format(
"Error writing temp file '%s' for Firefox Autofill profiles file '%s' (id=%d).",
 
  857                         temps, profileFile.getName(), profileFile.getId()), ex); 
 
  858                 this.addErrorMessage(NbBundle.getMessage(
this.getClass(), 
"Firefox.getAutofillProfiles.errMsg.errAnalyzingFile",
 
  859                         this.getName(), profileFile.getName()));
 
  863             logger.log(Level.INFO, 
"{0}- Now getting Bookmarks from {1}", 
new Object[]{moduleName, temps}); 
 
  864             File dbFile = 
new File(temps);
 
  865             if (context.dataSourceIngestIsCancelled()) {
 
  870             FileReader tempReader;
 
  872                 tempReader = 
new FileReader(temps);
 
  873             } 
catch (FileNotFoundException ex) {
 
  874                 logger.log(Level.SEVERE, 
"Error while trying to read the Autofill profiles json file for Firefox.", ex); 
 
  875                 this.addErrorMessage(
 
  876                         NbBundle.getMessage(
this.getClass(), 
"Firefox.getAutofillProfiles.errMsg.errAnalyzeFile", this.getName(),
 
  877                                 profileFile.getName()));
 
  881             final JsonParser parser = 
new JsonParser();
 
  883             JsonObject jsonRootObject;
 
  884             JsonArray jAddressesArray;
 
  887                 jsonRootObject = parser.parse(tempReader).getAsJsonObject();
 
  888                 jAddressesArray = jsonRootObject.getAsJsonArray(
"addresses"); 
 
  889             } 
catch (JsonIOException | JsonSyntaxException | IllegalStateException ex) {
 
  890                 logger.log(Level.WARNING, 
"Error parsing Json for Firefox Autofill profiles.", ex); 
 
  891                 this.addErrorMessage(NbBundle.getMessage(
this.getClass(), 
"Firefox.getAutofillProfiles.errMsg.errAnalyzingFile3",
 
  892                         this.getName(), profileFile.getName()));
 
  896             for (JsonElement result : jAddressesArray) {
 
  897                 JsonObject address = result.getAsJsonObject();
 
  898                 if (address == null) {
 
  902                 JsonElement nameEl = address.get(
"name"); 
 
  903                 String name = (nameEl != null) ? nameEl.getAsString() : 
"";
 
  905                 JsonElement emailEl = address.get(
"email"); 
 
  906                 String email = (emailEl != null) ? emailEl.getAsString() : 
"";
 
  908                 JsonElement telEl = address.get(
"tel"); 
 
  909                 String tel = (telEl != null) ? telEl.getAsString() : 
"";
 
  910                 JsonElement telCountryCodeEl = address.get(
"tel-country-code"); 
 
  911                 String telCountryCode = (telCountryCodeEl != null) ? telCountryCodeEl.getAsString() : 
"";
 
  912                 JsonElement telNationalEl = address.get(
"tel-national"); 
 
  913                 String telNational = (telNationalEl != null) ? telNationalEl.getAsString() : 
"";
 
  915                 String phoneNumber = makeTelNumber(tel, telCountryCode, telNational);
 
  917                 JsonElement createdEl = address.get(
"timeCreated"); 
 
  918                 Long datetimeCreated = (createdEl != null) ? createdEl.getAsLong()/1000 : Long.valueOf(0);     
 
  919                 JsonElement lastusedEl = address.get(
"timeLastUsed"); 
 
  920                 Long datetimeLastUsed = (lastusedEl != null) ? lastusedEl.getAsLong()/1000 : Long.valueOf(0); 
 
  921                 JsonElement timesUsedEl = address.get(
"timesUsed"); 
 
  922                 Integer timesUsed = (timesUsedEl != null) ? timesUsedEl.getAsShort() : Integer.valueOf(0); 
 
  924                 JsonElement addressLine1El = address.get(
"address-line1"); 
 
  925                 String addressLine1 = (addressLine1El != null) ? addressLine1El.getAsString() : 
"";
 
  926                 JsonElement addressLine2El = address.get(
"address-line2"); 
 
  927                 String addressLine2 = (addressLine2El != null) ? addressLine2El.getAsString() : 
"";
 
  928                 JsonElement addressLine3El = address.get(
"address-line3"); 
 
  929                 String addressLine3 = (addressLine3El != null) ? addressLine3El.getAsString() : 
"";
 
  931                 JsonElement postalCodeEl = address.get(
"postal-code"); 
 
  932                 String postalCode = (postalCodeEl != null) ? postalCodeEl.getAsString() : 
"";
 
  933                 JsonElement countryEl = address.get(
"country"); 
 
  934                 String country = (countryEl != null) ? countryEl.getAsString() : 
"";
 
  936                 String mailingAddress = makeFullAddress(addressLine1, addressLine2, addressLine3, postalCode, country );
 
  939                     Collection<BlackboardAttribute> bbattributes = 
new ArrayList<>();
 
  940                     bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME_PERSON,
 
  941                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  944                     bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_EMAIL,
 
  945                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  948                     bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER,
 
  949                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  952                     bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LOCATION,
 
  953                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  956                     bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
 
  957                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  960                     bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
 
  961                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  964                     bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COUNT,
 
  965                         RecentActivityExtracterModuleFactory.getModuleName(),
 
  968                     BlackboardArtifact bbart = profileFile.newArtifact(ARTIFACT_TYPE.TSK_WEB_FORM_ADDRESS);  
 
  972                         bbart.addAttributes(bbattributes);
 
  973                         this.indexArtifact(bbart);
 
  974                         bbartifacts.add(bbart);
 
  978                     if (email != null && !email.isEmpty()) {
 
  980                             Case.getCurrentCaseThrows().getSleuthkitCase().getCommunicationsManager().createAccountFileInstance(Account.Type.EMAIL, email,  NbBundle.getMessage(
this.getClass(), 
"Firefox.parentModuleName"), profileFile);
 
  981                         } 
catch (NoCurrentCaseException | TskCoreException ex) {
 
  982                             logger.log(Level.SEVERE, String.format(
"Error creating email account instance for '%s' from Firefox profiles file '%s' .",
 
  983                                 email, profileFile.getName()), ex); 
 
  988                     if (phoneNumber != null && !phoneNumber.isEmpty()) {
 
  990                             Case.getCurrentCaseThrows().getSleuthkitCase().getCommunicationsManager().createAccountFileInstance(Account.Type.PHONE, phoneNumber,  NbBundle.getMessage(
this.getClass(), 
"Firefox.parentModuleName"), profileFile);
 
  991                         } 
catch (NoCurrentCaseException | TskCoreException ex) {
 
  992                             logger.log(Level.SEVERE, String.format(
"Error creating phone number account instance for '%s' from Chrome profiles file '%s' .",
 
  993                                 phoneNumber, profileFile.getName()), ex); 
 
  997                 } 
catch (TskCoreException ex) {
 
  998                     logger.log(Level.SEVERE, 
"Error while trying to insert Firefox Autofill profile artifact{0}", ex); 
 
  999                     this.addErrorMessage(
 
 1000                             NbBundle.getMessage(
this.getClass(), 
"Firefox.getAutofillProfiles.errMsg.errAnalyzingFile4",
 
 1001                                     this.getName(), profileFile.getName()));
 
 1007         IngestServices.getInstance().fireModuleDataEvent(
new ModuleDataEvent(
 
 1008                 NbBundle.getMessage(
this.getClass(), 
"Firefox.parentModuleName"),
 
 1009                 BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_FORM_ADDRESS, bbartifacts));
 
 1020     private String extractDomain(String url) {
 
 1021         if (url == null || url.isEmpty()) {
 
 1025         if (url.toLowerCase().startsWith(PLACE_URL_PREFIX)) {
 
 1032         return NetworkUtils.extractDomain(url);
 
 1045     private String makeTelNumber(String tel, String telCountryCode, String telNational) {
 
 1047         if (tel != null && !tel.isEmpty()) {
 
 1051         if ((telCountryCode != null && !telCountryCode.isEmpty()) && 
 
 1052             (telNational != null && !telNational.isEmpty())) {
 
 1053             return telCountryCode + telNational;
 
 1070     private String makeFullAddress(String addressLine1, String addressLine2, String addressLine3, String postalCode, String country ) {
 
 1071         String fullAddress = 
"";
 
 1072         fullAddress = appendAddressField(fullAddress, addressLine1 );
 
 1073         fullAddress = appendAddressField(fullAddress, addressLine2 );
 
 1074         fullAddress = appendAddressField(fullAddress, addressLine3 );
 
 1075         fullAddress = appendAddressField(fullAddress, postalCode );
 
 1076         fullAddress = appendAddressField(fullAddress, country );
 
 1089     private String appendAddressField(String address, String addressfield) {
 
 1091         String updatedAddress = address;
 
 1092         if (addressfield != null && !addressfield.isEmpty()) {
 
 1093             if (!updatedAddress.isEmpty()) {
 
 1094                 updatedAddress += 
", ";
 
 1096             updatedAddress += addressfield;
 
 1099         return updatedAddress;