Autopsy  4.19.2
Graphical digital forensics platform for The Sleuth Kit and other tools.
Firefox.java
Go to the documentation of this file.
1 /*
2  *
3  * Autopsy Forensic Browser
4  *
5  * Copyright 2012-2021 Basis Technology Corp.
6  *
7  * Copyright 2012 42six Solutions.
8  * Contact: aebadirad <at> 42six <dot> com
9  * Project Contact/Architect: carrier <at> sleuthkit <dot> org
10  *
11  * Licensed under the Apache License, Version 2.0 (the "License");
12  * you may not use this file except in compliance with the License.
13  * You may obtain a copy of the License at
14  *
15  * http://www.apache.org/licenses/LICENSE-2.0
16  *
17  * Unless required by applicable law or agreed to in writing, software
18  * distributed under the License is distributed on an "AS IS" BASIS,
19  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20  * See the License for the specific language governing permissions and
21  * limitations under the License.
22  */
23 package org.sleuthkit.autopsy.recentactivity;
24 
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 java.io.File;
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;
43 import java.util.Set;
44 import java.util.logging.Level;
45 import org.apache.commons.io.FilenameUtils;
46 import org.openide.util.NbBundle;
47 import org.openide.util.NbBundle.Messages;
56 import org.sleuthkit.datamodel.AbstractFile;
57 import org.sleuthkit.datamodel.Blackboard;
58 import org.sleuthkit.datamodel.BlackboardArtifact;
59 import org.sleuthkit.datamodel.BlackboardAttribute;
60 import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
61 import org.sleuthkit.datamodel.Content;
62 import org.sleuthkit.datamodel.ReadContentInputStream.ReadContentInputStreamException;
63 import org.sleuthkit.datamodel.TskCoreException;
64 import org.sleuthkit.datamodel.blackboardutils.WebBrowserArtifactsHelper;
65 
66 @Messages({
67  "Progress_Message_Firefox_History=Firefox History",
68  "Progress_Message_Firefox_Bookmarks=Firefox Bookmarks",
69  "Progress_Message_Firefox_Cookies=Firefox Cookies",
70  "Progress_Message_Firefox_Downloads=Firefox Downloads",
71  "Progress_Message_Firefox_FormHistory=Firefox Form History",
72  "Progress_Message_Firefox_AutoFill=Firefox Auto Fill"
73 })
74 
78 class Firefox extends Extract {
79 
80  private static final Logger logger = Logger.getLogger(Firefox.class.getName());
81  private static final String PLACE_URL_PREFIX = "place:";
82  private static final String HISTORY_QUERY = "SELECT moz_historyvisits.id, url, title, visit_count,(visit_date/1000000) AS visit_date,from_visit,"
83  + "(SELECT url FROM moz_historyvisits history, moz_places places where history.id = moz_historyvisits.from_visit and history.place_id = places.id ) as ref "
84  + "FROM moz_places, moz_historyvisits "
85  + "WHERE moz_places.id = moz_historyvisits.place_id "
86  + "AND hidden = 0"; //NON-NLS
87  private static final String COOKIE_QUERY = "SELECT name,value,host,expiry,(lastAccessed/1000000) AS lastAccessed,(creationTime/1000000) AS creationTime FROM moz_cookies"; //NON-NLS
88  private static final String COOKIE_QUERY_V3 = "SELECT name,value,host,expiry,(lastAccessed/1000000) AS lastAccessed FROM moz_cookies"; //NON-NLS
89  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"; //NON-NLS
90  private static final String DOWNLOAD_QUERY = "SELECT target, source,(startTime/1000000) AS startTime, maxBytes FROM moz_downloads"; //NON-NLS
91  private static final String DOWNLOAD_QUERY_V24 = "SELECT url, content AS target, (lastModified/1000000) AS lastModified "
92  + " FROM moz_places, moz_annos, moz_anno_attributes "
93  + " WHERE moz_places.id = moz_annos.place_id"
94  + " AND moz_annos.anno_attribute_id = moz_anno_attributes.id"
95  + " AND moz_anno_attributes.name='downloads/destinationFileURI'"; //NON-NLS
96  private static final String FORMHISTORY_QUERY = "SELECT fieldname, value FROM moz_formhistory";
97  private static final String FORMHISTORY_QUERY_V64 = "SELECT fieldname, value, timesUsed, firstUsed, lastUsed FROM moz_formhistory";
98  private Content dataSource;
99  private final IngestJobContext context;
100 
101  Firefox(IngestJobContext context) {
102  super(NbBundle.getMessage(Firefox.class, "Firefox.moduleName"), context);
103  this.context = context;
104  }
105 
106  @Override
107  public void process(Content dataSource, DataSourceIngestModuleProgress progressBar) {
108  this.dataSource = dataSource;
109  dataFound = false;
110  long ingestJobId = context.getJobId();
111 
112  progressBar.progress(Bundle.Progress_Message_Firefox_History());
113  this.getHistory(context.getJobId());
114 
115  if (context.dataSourceIngestIsCancelled()) {
116  return;
117  }
118 
119  progressBar.progress(Bundle.Progress_Message_Firefox_Bookmarks());
120  this.getBookmark(ingestJobId);
121 
122  if (context.dataSourceIngestIsCancelled()) {
123  return;
124  }
125 
126  progressBar.progress(Bundle.Progress_Message_Firefox_Downloads());
127  this.getDownload(ingestJobId);
128 
129  if (context.dataSourceIngestIsCancelled()) {
130  return;
131  }
132 
133  progressBar.progress(Bundle.Progress_Message_Firefox_Cookies());
134  this.getCookie(ingestJobId);
135 
136  if (context.dataSourceIngestIsCancelled()) {
137  return;
138  }
139 
140  progressBar.progress(Bundle.Progress_Message_Firefox_FormHistory());
141  this.getFormsHistory(ingestJobId);
142 
143  if (context.dataSourceIngestIsCancelled()) {
144  return;
145  }
146 
147  progressBar.progress(Bundle.Progress_Message_Firefox_AutoFill());
148  this.getAutofillProfiles(ingestJobId);
149  }
150 
156  private void getHistory(long ingestJobId) {
157  FileManager fileManager = currentCase.getServices().getFileManager();
158  List<AbstractFile> historyFiles;
159  try {
160  historyFiles = fileManager.findFiles(dataSource, "places.sqlite", "Firefox"); //NON-NLS
161  } catch (TskCoreException ex) {
162  String msg = NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errFetchingFiles");
163  logger.log(Level.WARNING, msg);
164  this.addErrorMessage(this.getDisplayName() + ": " + msg);
165  return;
166  }
167 
168  if (historyFiles.isEmpty()) {
169  String msg = NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.noFilesFound");
170  logger.log(Level.INFO, msg);
171  return;
172  }
173 
174  dataFound = true;
175  Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
176  int j = 0;
177  for (AbstractFile historyFile : historyFiles) {
178 
179  if (context.dataSourceIngestIsCancelled()) {
180  return;
181  }
182 
183  if (historyFile.getSize() == 0) {
184  continue;
185  }
186 
187  String fileName = historyFile.getName();
188  String temps = RAImageIngestModule.getRATempPath(currentCase, "firefox", ingestJobId) + File.separator + fileName + j + ".db"; //NON-NLS
189  try {
190  ContentUtils.writeToFile(historyFile, new File(temps), context::dataSourceIngestIsCancelled);
191  } catch (ReadContentInputStreamException ex) {
192  logger.log(Level.WARNING, String.format("Error reading Firefox web history artifacts file '%s' (id=%d).",
193  fileName, historyFile.getId()), ex); //NON-NLS
194  this.addErrorMessage(
195  NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errAnalyzeFile", this.getDisplayName(),
196  fileName));
197  continue;
198  } catch (IOException ex) {
199  logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Firefox web history artifacts file '%s' (id=%d).",
200  temps, fileName, historyFile.getId()), ex); //NON-NLS
201  this.addErrorMessage(
202  NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errAnalyzeFile", this.getDisplayName(),
203  fileName));
204  continue;
205  }
206  File dbFile = new File(temps);
207  if (context.dataSourceIngestIsCancelled()) {
208  dbFile.delete();
209  break;
210  }
211  List<HashMap<String, Object>> tempList = this.querySQLiteDb(temps, HISTORY_QUERY);
212  logger.log(Level.INFO, "{0} - Now getting history from {1} with {2} artifacts identified.", new Object[]{getDisplayName(), temps, tempList.size()}); //NON-NLS
213  for (HashMap<String, Object> result : tempList) {
214 
215  if (context.dataSourceIngestIsCancelled()) {
216  return;
217  }
218 
219  String url = result.get("url").toString();
220 
221  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
222  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
223  RecentActivityExtracterModuleFactory.getModuleName(),
224  ((url != null) ? url : ""))); //NON-NLS
225  //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", ((result.get("url").toString() != null) ? EscapeUtil.decodeURL(result.get("url").toString()) : "")));
226  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
227  RecentActivityExtracterModuleFactory.getModuleName(),
228  (Long.valueOf(result.get("visit_date").toString())))); //NON-NLS
229  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REFERRER,
230  RecentActivityExtracterModuleFactory.getModuleName(),
231  ((result.get("ref").toString() != null) ? result.get("ref").toString() : ""))); //NON-NLS
232  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TITLE,
233  RecentActivityExtracterModuleFactory.getModuleName(),
234  ((result.get("title").toString() != null) ? result.get("title").toString() : ""))); //NON-NLS
235  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
236  RecentActivityExtracterModuleFactory.getModuleName(),
237  NbBundle.getMessage(this.getClass(), "Firefox.moduleName")));
238  String domain = extractDomain(url);
239  if (domain != null && domain.isEmpty() == false) {
240  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
241  RecentActivityExtracterModuleFactory.getModuleName(), domain)); //NON-NLS
242 
243  }
244 
245  try {
246  bbartifacts.add(createArtifactWithAttributes(BlackboardArtifact.Type.TSK_WEB_HISTORY, historyFile, bbattributes));
247  } catch (TskCoreException ex) {
248  logger.log(Level.SEVERE, String.format("Failed to create TSK_WEB_HISTORY artifact for file %d", historyFile.getId()), ex);
249  }
250  }
251  ++j;
252  dbFile.delete();
253  }
254 
255  if (!context.dataSourceIngestIsCancelled()) {
256  postArtifacts(bbartifacts);
257  }
258  }
259 
265  private void getBookmark(long ingestJobId) {
266 
267  FileManager fileManager = currentCase.getServices().getFileManager();
268  List<AbstractFile> bookmarkFiles;
269  try {
270  bookmarkFiles = fileManager.findFiles(dataSource, "places.sqlite", "Firefox"); //NON-NLS
271  } catch (TskCoreException ex) {
272  String msg = NbBundle.getMessage(this.getClass(), "Firefox.getBookmark.errMsg.errFetchFiles");
273  logger.log(Level.WARNING, msg);
274  this.addErrorMessage(this.getDisplayName() + ": " + msg);
275  return;
276  }
277 
278  if (bookmarkFiles.isEmpty()) {
279  logger.log(Level.INFO, "Didn't find any firefox bookmark files."); //NON-NLS
280  return;
281  }
282 
283  dataFound = true;
284  Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
285  int j = 0;
286  for (AbstractFile bookmarkFile : bookmarkFiles) {
287  if (bookmarkFile.getSize() == 0) {
288  continue;
289  }
290  String fileName = bookmarkFile.getName();
291  String temps = RAImageIngestModule.getRATempPath(currentCase, "firefox", ingestJobId) + File.separator + fileName + j + ".db"; //NON-NLS
292  try {
293  ContentUtils.writeToFile(bookmarkFile, new File(temps), context::dataSourceIngestIsCancelled);
294  } catch (ReadContentInputStreamException ex) {
295  logger.log(Level.WARNING, String.format("Error reading Firefox bookmark artifacts file '%s' (id=%d).",
296  fileName, bookmarkFile.getId()), ex); //NON-NLS
297  this.addErrorMessage(
298  NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errAnalyzeFile", this.getDisplayName(),
299  fileName));
300  continue;
301  } catch (IOException ex) {
302  logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Firefox bookmark artifacts file '%s' (id=%d).",
303  temps, fileName, bookmarkFile.getId()), ex); //NON-NLS
304  this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Firefox.getBookmark.errMsg.errAnalyzeFile",
305  this.getDisplayName(), fileName));
306  continue;
307  }
308  File dbFile = new File(temps);
309  if (context.dataSourceIngestIsCancelled()) {
310  dbFile.delete();
311  break;
312  }
313  List<HashMap<String, Object>> tempList = this.querySQLiteDb(temps, BOOKMARK_QUERY);
314  logger.log(Level.INFO, "{0} - Now getting bookmarks from {1} with {2} artifacts identified.", new Object[]{getDisplayName(), temps, tempList.size()}); //NON-NLS
315  for (HashMap<String, Object> result : tempList) {
316 
317  if (context.dataSourceIngestIsCancelled()) {
318  break;
319  }
320 
321  String url = result.get("url").toString();
322 
323  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
324  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
325  RecentActivityExtracterModuleFactory.getModuleName(),
326  ((url != null) ? url : ""))); //NON-NLS
327  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TITLE,
328  RecentActivityExtracterModuleFactory.getModuleName(),
329  ((result.get("title").toString() != null) ? result.get("title").toString() : ""))); //NON-NLS
330  if (Long.valueOf(result.get("dateAdded").toString()) > 0) { //NON-NLS
331  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
332  RecentActivityExtracterModuleFactory.getModuleName(),
333  (Long.valueOf(result.get("dateAdded").toString())))); //NON-NLS
334  }
335  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
336  RecentActivityExtracterModuleFactory.getModuleName(),
337  NbBundle.getMessage(this.getClass(), "Firefox.moduleName")));
338  String domain = extractDomain(url);
339  if (domain != null && domain.isEmpty() == false) {
340  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
341  RecentActivityExtracterModuleFactory.getModuleName(), domain)); //NON-NLS
342  }
343 
344  try {
345  bbartifacts.add(createArtifactWithAttributes(BlackboardArtifact.Type.TSK_WEB_BOOKMARK, bookmarkFile, bbattributes));
346  } catch (TskCoreException ex) {
347  logger.log(Level.SEVERE, String.format("Failed to create TSK_WEB_BOOKMARK artifact for file %d", bookmarkFile.getId()), ex);
348  }
349  }
350  ++j;
351  dbFile.delete();
352  }
353 
354  if (!context.dataSourceIngestIsCancelled()) {
355  postArtifacts(bbartifacts);
356  }
357  }
358 
364  private void getCookie(long ingestJobId) {
365  FileManager fileManager = currentCase.getServices().getFileManager();
366  List<AbstractFile> cookiesFiles;
367  try {
368  cookiesFiles = fileManager.findFiles(dataSource, "cookies.sqlite", "Firefox"); //NON-NLS
369  } catch (TskCoreException ex) {
370  String msg = NbBundle.getMessage(this.getClass(), "Firefox.getCookie.errMsg.errFetchFile");
371  logger.log(Level.WARNING, msg);
372  this.addErrorMessage(this.getDisplayName() + ": " + msg);
373  return;
374  }
375 
376  if (cookiesFiles.isEmpty()) {
377  logger.log(Level.INFO, "Didn't find any Firefox cookie files."); //NON-NLS
378  return;
379  }
380 
381  dataFound = true;
382  Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
383  int j = 0;
384  for (AbstractFile cookiesFile : cookiesFiles) {
385  if (context.dataSourceIngestIsCancelled()) {
386  return;
387  }
388 
389  if (cookiesFile.getSize() == 0) {
390  continue;
391  }
392  String fileName = cookiesFile.getName();
393  String temps = RAImageIngestModule.getRATempPath(currentCase, "firefox", ingestJobId) + File.separator + fileName + j + ".db"; //NON-NLS
394  try {
395  ContentUtils.writeToFile(cookiesFile, new File(temps), context::dataSourceIngestIsCancelled);
396  } catch (ReadContentInputStreamException ex) {
397  logger.log(Level.WARNING, String.format("Error reading Firefox cookie artifacts file '%s' (id=%d).",
398  fileName, cookiesFile.getId()), ex); //NON-NLS
399  this.addErrorMessage(
400  NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errAnalyzeFile", this.getDisplayName(),
401  fileName));
402  continue;
403  } catch (IOException ex) {
404  logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Firefox cookie artifacts file '%s' (id=%d).",
405  temps, fileName, cookiesFile.getId()), ex); //NON-NLS
406  this.addErrorMessage(
407  NbBundle.getMessage(this.getClass(), "Firefox.getCookie.errMsg.errAnalyzeFile", this.getDisplayName(),
408  fileName));
409  continue;
410  }
411  File dbFile = new File(temps);
412  if (context.dataSourceIngestIsCancelled()) {
413  dbFile.delete();
414  break;
415  }
416  boolean checkColumn = Util.checkColumn("creationTime", "moz_cookies", temps); //NON-NLS
417  String query;
418  if (checkColumn) {
419  query = COOKIE_QUERY;
420  } else {
421  query = COOKIE_QUERY_V3;
422  }
423 
424  List<HashMap<String, Object>> tempList = this.querySQLiteDb(temps, query);
425  logger.log(Level.INFO, "{0} - Now getting cookies from {1} with {2} artifacts identified.", new Object[]{getDisplayName(), temps, tempList.size()}); //NON-NLS
426  for (HashMap<String, Object> result : tempList) {
427 
428  if (context.dataSourceIngestIsCancelled()) {
429  break;
430  }
431 
432  String host = result.get("host").toString();
433 
434  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
435  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
436  RecentActivityExtracterModuleFactory.getModuleName(),
437  ((host != null) ? host : ""))); //NON-NLS
438  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
439  RecentActivityExtracterModuleFactory.getModuleName(),
440  (Long.valueOf(result.get("lastAccessed").toString())))); //NON-NLS
441  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME,
442  RecentActivityExtracterModuleFactory.getModuleName(),
443  ((result.get("name").toString() != null) ? result.get("name").toString() : ""))); //NON-NLS
444  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE,
445  RecentActivityExtracterModuleFactory.getModuleName(),
446  ((result.get("value").toString() != null) ? result.get("value").toString() : ""))); //NON-NLS
447  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
448  RecentActivityExtracterModuleFactory.getModuleName(),
449  NbBundle.getMessage(this.getClass(), "Firefox.moduleName")));
450 
451  if (checkColumn == true) {
452  String value = result.get("creationTime").toString();
453  if(value != null && !value.isEmpty()) {
454  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
455  RecentActivityExtracterModuleFactory.getModuleName(),
456  (Long.valueOf(result.get("creationTime").toString())))); //NON-NLS
457  }
458  }
459  String domain = extractDomain(host);
460  if (domain != null && domain.isEmpty() == false) {
461  domain = domain.replaceFirst("^\\.+(?!$)", "");
462  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
463  RecentActivityExtracterModuleFactory.getModuleName(), domain));
464  }
465 
466  try {
467  bbartifacts.add(createArtifactWithAttributes(BlackboardArtifact.Type.TSK_WEB_COOKIE, cookiesFile, bbattributes));
468  } catch (TskCoreException ex) {
469  logger.log(Level.SEVERE, String.format("Failed to create TSK_WEB_COOKIE artifact for file %d", cookiesFile.getId()), ex);
470  }
471  }
472  ++j;
473  dbFile.delete();
474  }
475 
476  if (!context.dataSourceIngestIsCancelled()) {
477  postArtifacts(bbartifacts);
478  }
479  }
480 
486  private void getDownload(long ingestJobId) {
487  getDownloadPreVersion24(ingestJobId);
488  getDownloadVersion24(ingestJobId);
489  }
490 
498  private void getDownloadPreVersion24(long ingestJobId) {
499 
500  FileManager fileManager = currentCase.getServices().getFileManager();
501  List<AbstractFile> downloadsFiles;
502  try {
503  downloadsFiles = fileManager.findFiles(dataSource, "downloads.sqlite", "Firefox"); //NON-NLS
504  } catch (TskCoreException ex) {
505  String msg = NbBundle.getMessage(this.getClass(), "Firefox.getDlPre24.errMsg.errFetchFiles");
506  logger.log(Level.WARNING, msg);
507  this.addErrorMessage(this.getDisplayName() + ": " + msg);
508  return;
509  }
510 
511  if (downloadsFiles.isEmpty()) {
512  logger.log(Level.INFO, "Didn't find any pre-version-24.0 Firefox download files."); //NON-NLS
513  return;
514  }
515 
516  dataFound = true;
517  Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
518  int j = 0;
519  for (AbstractFile downloadsFile : downloadsFiles) {
520  if (downloadsFile.getSize() == 0) {
521  continue;
522  }
523  String fileName = downloadsFile.getName();
524  String temps = RAImageIngestModule.getRATempPath(currentCase, "firefox", ingestJobId) + File.separator + fileName + j + ".db"; //NON-NLS
525  int errors = 0;
526  try {
527  ContentUtils.writeToFile(downloadsFile, new File(temps), context::dataSourceIngestIsCancelled);
528  } catch (ReadContentInputStreamException ex) {
529  logger.log(Level.WARNING, String.format("Error reading Firefox download artifacts file '%s' (id=%d).",
530  fileName, downloadsFile.getId()), ex); //NON-NLS
531  this.addErrorMessage(
532  NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errAnalyzeFile", this.getDisplayName(),
533  fileName));
534  continue;
535  } catch (IOException ex) {
536  logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Firefox download artifacts file '%s' (id=%d).",
537  temps, fileName, downloadsFile.getId()), ex); //NON-NLS
538  this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Firefox.getDlPre24.errMsg.errAnalyzeFiles",
539  this.getDisplayName(), fileName));
540  continue;
541  }
542  File dbFile = new File(temps);
543  if (context.dataSourceIngestIsCancelled()) {
544  dbFile.delete();
545  break;
546  }
547 
548  List<HashMap<String, Object>> tempList = this.querySQLiteDb(temps, DOWNLOAD_QUERY);
549  logger.log(Level.INFO, "{0}- Now getting downloads from {1} with {2} artifacts identified.", new Object[]{getDisplayName(), temps, tempList.size()}); //NON-NLS
550  for (HashMap<String, Object> result : tempList) {
551 
552  if (context.dataSourceIngestIsCancelled()) {
553  break;
554  }
555 
556  String source = result.get("source").toString();
557 
558  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
559 
560  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
561  RecentActivityExtracterModuleFactory.getModuleName(),
562  source)); //NON-NLS
563  //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", ((result.get("source").toString() != null) ? EscapeUtil.decodeURL(result.get("source").toString()) : "")));
564  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
565  RecentActivityExtracterModuleFactory.getModuleName(),
566  (Long.valueOf(result.get("startTime").toString())))); //NON-NLS
567 
568  String target = result.get("target").toString(); //NON-NLS
569  String downloadedFilePath = "";
570  if (target != null) {
571  try {
572  downloadedFilePath = URLDecoder.decode(target.replaceAll("file:///", ""), "UTF-8"); //NON-NLS
573  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
574  RecentActivityExtracterModuleFactory.getModuleName(),
575  downloadedFilePath));
576  long pathID = Util.findID(dataSource, downloadedFilePath);
577  if (pathID != -1) {
578  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH_ID,
579  RecentActivityExtracterModuleFactory.getModuleName(),
580  pathID));
581  }
582  } catch (UnsupportedEncodingException ex) {
583  logger.log(Level.SEVERE, "Error decoding Firefox download URL in " + temps, ex); //NON-NLS
584  errors++;
585  }
586  }
587 
588  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
589  RecentActivityExtracterModuleFactory.getModuleName(),
590  NbBundle.getMessage(this.getClass(), "Firefox.moduleName")));
591  String domain = extractDomain(source);
592  if (domain != null && domain.isEmpty() == false) {
593  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
594  RecentActivityExtracterModuleFactory.getModuleName(),
595  domain)); //NON-NLS
596  }
597  try {
598  BlackboardArtifact webDownloadArtifact = createArtifactWithAttributes(BlackboardArtifact.Type.TSK_WEB_DOWNLOAD, downloadsFile, bbattributes);
599  bbartifacts.add(webDownloadArtifact);
600 
601  // find the downloaded file and create a TSK_ASSOCIATED_OBJECT for it, associating it with the TSK_WEB_DOWNLOAD artifact.
602  for (AbstractFile downloadedFile : currentCase.getSleuthkitCase().getFileManager().findFilesExactNameExactPath(dataSource,
603  FilenameUtils.getName(downloadedFilePath), FilenameUtils.getPath(downloadedFilePath))) {
604  bbartifacts.add(createAssociatedArtifact(downloadedFile, webDownloadArtifact));
605  break;
606  }
607  } catch (TskCoreException ex) {
608  logger.log(Level.SEVERE, String.format("Error creating TSK_WEB_DOWNLOAD or TSK_ASSOCIATED_ARTIFACT artifact for file '%d'",
609  downloadsFile.getId()), ex); //NON-NLS
610  }
611 
612  }
613  if (errors > 0) {
614  this.addErrorMessage(
615  NbBundle.getMessage(this.getClass(), "Firefox.getDlPre24.errMsg.errParsingArtifacts",
616  this.getDisplayName(), errors));
617  }
618  j++;
619  dbFile.delete();
620  }
621 
622  if (!context.dataSourceIngestIsCancelled()) {
623  postArtifacts(bbartifacts);
624  }
625  }
626 
634  private void getDownloadVersion24(long ingestJobId) {
635  FileManager fileManager = currentCase.getServices().getFileManager();
636  List<AbstractFile> downloadsFiles;
637  try {
638  downloadsFiles = fileManager.findFiles(dataSource, "places.sqlite", "Firefox"); //NON-NLS
639  } catch (TskCoreException ex) {
640  String msg = NbBundle.getMessage(this.getClass(), "Firefox.getDlV24.errMsg.errFetchFiles");
641  logger.log(Level.WARNING, msg);
642  this.addErrorMessage(this.getDisplayName() + ": " + msg);
643  return;
644  }
645 
646  if (downloadsFiles.isEmpty()) {
647  logger.log(Level.INFO, "Didn't find any version-24.0 Firefox download files."); //NON-NLS
648  return;
649  }
650 
651  dataFound = true;
652  Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
653  int j = 0;
654  for (AbstractFile downloadsFile : downloadsFiles) {
655  if (downloadsFile.getSize() == 0) {
656  continue;
657  }
658  String fileName = downloadsFile.getName();
659  String temps = RAImageIngestModule.getRATempPath(currentCase, "firefox", ingestJobId) + File.separator + fileName + "-downloads" + j + ".db"; //NON-NLS
660  int errors = 0;
661  try {
662  ContentUtils.writeToFile(downloadsFile, new File(temps), context::dataSourceIngestIsCancelled);
663  } catch (ReadContentInputStreamException ex) {
664  logger.log(Level.WARNING, String.format("Error reading Firefox download artifacts file '%s' (id=%d).",
665  fileName, downloadsFile.getId()), ex); //NON-NLS
666  this.addErrorMessage(
667  NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errAnalyzeFile", this.getDisplayName(),
668  fileName));
669  continue;
670  } catch (IOException ex) {
671  logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Firefox download artifacts file '%s' (id=%d).",
672  temps, fileName, downloadsFile.getId()), ex); //NON-NLS
673  this.addErrorMessage(
674  NbBundle.getMessage(this.getClass(), "Firefox.getDlV24.errMsg.errAnalyzeFile", this.getDisplayName(),
675  fileName));
676  continue;
677  }
678  File dbFile = new File(temps);
679  if (context.dataSourceIngestIsCancelled()) {
680  dbFile.delete();
681  break;
682  }
683 
684  List<HashMap<String, Object>> tempList = this.querySQLiteDb(temps, DOWNLOAD_QUERY_V24);
685 
686  logger.log(Level.INFO, "{0} - Now getting downloads from {1} with {2} artifacts identified.", new Object[]{getDisplayName(), temps, tempList.size()}); //NON-NLS
687  for (HashMap<String, Object> result : tempList) {
688 
689  if (context.dataSourceIngestIsCancelled()) {
690  break;
691  }
692 
693  String url = result.get("url").toString();
694 
695  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
696 
697  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
698  RecentActivityExtracterModuleFactory.getModuleName(),
699  url)); //NON-NLS
700  //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", ((result.get("source").toString() != null) ? EscapeUtil.decodeURL(result.get("source").toString()) : "")));
701  //TODO Revisit usage of deprecated constructor as per TSK-583
702  //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LAST_ACCESSED.getTypeID(), "RecentActivity", "Last Visited", (Long.valueOf(result.get("startTime").toString()))));
703 
704  String target = result.get("target").toString(); //NON-NLS
705  String downloadedFilePath = "";
706  if (target != null) {
707  try {
708  downloadedFilePath = URLDecoder.decode(target.replaceAll("file:///", ""), "UTF-8"); //NON-NLS
709  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
710  RecentActivityExtracterModuleFactory.getModuleName(),
711  downloadedFilePath));
712  long pathID = Util.findID(dataSource, downloadedFilePath);
713  if (pathID != -1) {
714  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH_ID,
715  RecentActivityExtracterModuleFactory.getModuleName(),
716  pathID));
717  }
718  } catch (UnsupportedEncodingException ex) {
719  logger.log(Level.SEVERE, "Error decoding Firefox download URL in " + temps, ex); //NON-NLS
720  errors++;
721  }
722  }
723  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
724  RecentActivityExtracterModuleFactory.getModuleName(),
725  Long.valueOf(result.get("lastModified").toString()))); //NON-NLS
726  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
727  RecentActivityExtracterModuleFactory.getModuleName(),
728  NbBundle.getMessage(this.getClass(), "Firefox.moduleName")));
729  String domain = extractDomain(url);
730  if (domain != null && domain.isEmpty() == false) {
731  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
732  RecentActivityExtracterModuleFactory.getModuleName(), domain)); //NON-NLS
733  }
734  try {
735  BlackboardArtifact webDownloadArtifact = createArtifactWithAttributes(BlackboardArtifact.Type.TSK_WEB_DOWNLOAD, downloadsFile, bbattributes);
736  bbartifacts.add(webDownloadArtifact);
737 
738  // find the downloaded file and create a TSK_ASSOCIATED_OBJECT for it, associating it with the TSK_WEB_DOWNLOAD artifact.
739  for (AbstractFile downloadedFile : currentCase.getSleuthkitCase().getFileManager().findFilesExactNameExactPath(dataSource,
740  FilenameUtils.getName(downloadedFilePath), FilenameUtils.getPath(downloadedFilePath))) {
741  bbartifacts.add(createAssociatedArtifact(downloadedFile, webDownloadArtifact));
742  break;
743  }
744  } catch (TskCoreException ex) {
745  logger.log(Level.SEVERE, String.format("Error creating associated object artifact for file '%s'",
746  downloadedFilePath), ex); //NON-NLS
747  }
748  }
749  if (errors > 0) {
750  this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Firefox.getDlV24.errMsg.errParsingArtifacts",
751  this.getDisplayName(), errors));
752  }
753  j++;
754  dbFile.delete();
755  }
756 
757  if (!context.dataSourceIngestIsCancelled()) {
758  postArtifacts(bbartifacts);
759  }
760  }
761 
768  private void getFormsHistory(long ingestJobId) {
769  FileManager fileManager = currentCase.getServices().getFileManager();
770  List<AbstractFile> formHistoryFiles;
771 
772  // Some fields are just noisy and can me excluded
773  Set<String> excludedFieldNames = new HashSet<>(Arrays.asList(
774  "it", // some kind of timestamp
775  "ts" // some kind of timestamp
776  ));
777 
778  try {
779  formHistoryFiles = fileManager.findFiles(dataSource, "formhistory.sqlite", "Firefox"); //NON-NLS
780  } catch (TskCoreException ex) {
781  String msg = NbBundle.getMessage(this.getClass(), "Firefox.getFormsAutofill.errMsg.errFetchingFiles");
782  logger.log(Level.WARNING, msg);
783  this.addErrorMessage(this.getDisplayName() + ": " + msg);
784  return;
785  }
786 
787  if (formHistoryFiles.isEmpty()) {
788  String msg = NbBundle.getMessage(this.getClass(), "Firefox.getFormsAutofill.errMsg.noFilesFound");
789  logger.log(Level.INFO, msg);
790  return;
791  }
792 
793  dataFound = true;
794  Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
795  int j = 0;
796  for (AbstractFile formHistoryFile : formHistoryFiles) {
797  if (formHistoryFile.getSize() == 0) {
798  continue;
799  }
800 
801  String fileName = formHistoryFile.getName();
802  String tempFilePath = RAImageIngestModule.getRATempPath(currentCase, "firefox", ingestJobId) + File.separator + fileName + j + ".db"; //NON-NLS
803  try {
804  ContentUtils.writeToFile(formHistoryFile, new File(tempFilePath), context::dataSourceIngestIsCancelled);
805  } catch (ReadContentInputStreamException ex) {
806  logger.log(Level.WARNING, String.format("Error reading Firefox web history artifacts file '%s' (id=%d).",
807  fileName, formHistoryFile.getId()), ex); //NON-NLS
808  this.addErrorMessage(
809  NbBundle.getMessage(this.getClass(), "Firefox.getFormsAutofill.errMsg.errAnalyzeFile", this.getDisplayName(),
810  fileName));
811  continue;
812  } catch (IOException ex) {
813  logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Firefox web history artifacts file '%s' (id=%d).",
814  tempFilePath, fileName, formHistoryFile.getId()), ex); //NON-NLS
815  this.addErrorMessage(
816  NbBundle.getMessage(this.getClass(), "Firefox.getFormsAutofill.errMsg.errAnalyzeFile", this.getDisplayName(),
817  fileName));
818  continue;
819  }
820  File dbFile = new File(tempFilePath);
821  if (context.dataSourceIngestIsCancelled()) {
822  dbFile.delete();
823  break;
824  }
825 
826  // The table schema is a little different in newer version of Firefox
827  boolean isFirefoxV64 = Util.checkColumn("timesUsed", "moz_formhistory", tempFilePath);
828  String formHistoryQuery = (isFirefoxV64) ? FORMHISTORY_QUERY_V64 : FORMHISTORY_QUERY;
829 
830  List<HashMap<String, Object>> tempList = this.querySQLiteDb(tempFilePath, formHistoryQuery);
831  logger.log(Level.INFO, "{0} - Now getting history from {1} with {2} artifacts identified.", new Object[]{getDisplayName(), tempFilePath, tempList.size()}); //NON-NLS
832  for (HashMap<String, Object> result : tempList) {
833 
834  if (context.dataSourceIngestIsCancelled()) {
835  break;
836  }
837 
838  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
839 
840  String fieldName = ((result.get("fieldname").toString() != null) ? result.get("fieldname").toString() : "");
841  // filter out unuseful values
842  if (excludedFieldNames.contains(fieldName.toLowerCase())) {
843  continue;
844  }
845 
846  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME,
847  RecentActivityExtracterModuleFactory.getModuleName(),
848  fieldName)); //NON-NLS
849 
850  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE,
851  RecentActivityExtracterModuleFactory.getModuleName(),
852  ((result.get("value").toString() != null) ? result.get("value").toString() : ""))); //NON-NLS
853 
854  // Newer versions of firefox have additional columns
855  if (isFirefoxV64) {
856  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
857  RecentActivityExtracterModuleFactory.getModuleName(),
858  (Long.valueOf(result.get("firstUsed").toString()) / 1000000))); //NON-NLS
859 
860  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
861  RecentActivityExtracterModuleFactory.getModuleName(),
862  (Long.valueOf(result.get("lastUsed").toString()) / 1000000))); //NON-NLS
863 
864  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COUNT,
865  RecentActivityExtracterModuleFactory.getModuleName(),
866  (Integer.valueOf(result.get("timesUsed").toString())))); //NON-NLS
867 
868  }
869  try {
870  // Add artifact
871  bbartifacts.add(createArtifactWithAttributes(BlackboardArtifact.Type.TSK_WEB_FORM_AUTOFILL, formHistoryFile, bbattributes));
872  } catch (TskCoreException ex) {
873  logger.log(Level.SEVERE, String.format("Failed to create TSK_WEB_FORM_AUTOFILL artifact for file %d", formHistoryFile.getId()), ex);
874  }
875  }
876  ++j;
877  dbFile.delete();
878  }
879 
880  if (!context.dataSourceIngestIsCancelled()) {
881  postArtifacts(bbartifacts);
882  }
883  }
884 
891  private void getAutofillProfiles(long ingestJobId) {
892  FileManager fileManager = currentCase.getServices().getFileManager();
893  List<AbstractFile> autofillProfilesFiles;
894  try {
895  autofillProfilesFiles = fileManager.findFiles(dataSource, "autofill-profiles.json", "Firefox"); //NON-NLS
896  } catch (TskCoreException ex) {
897  String msg = NbBundle.getMessage(this.getClass(), "Firefox.getAutofillProfiles.errMsg.errGettingFiles");
898  logger.log(Level.SEVERE, msg, ex);
899  this.addErrorMessage(this.getDisplayName() + ": " + msg);
900  return;
901  }
902 
903  if (autofillProfilesFiles.isEmpty()) {
904  logger.log(Level.INFO, "Didn't find any Firefox Autofill Profiles files."); //NON-NLS
905  return;
906  }
907 
908  dataFound = true;
909  int j = 0;
910  while (j < autofillProfilesFiles.size()) {
911  AbstractFile profileFile = autofillProfilesFiles.get(j++);
912  if (profileFile.getSize() == 0) {
913  continue;
914  }
915  String temps = RAImageIngestModule.getRATempPath(currentCase, "Firefox", ingestJobId) + File.separator + profileFile.getName() + j + ".json"; //NON-NLS
916  try {
917  ContentUtils.writeToFile(profileFile, new File(temps), context::dataSourceIngestIsCancelled);
918  } catch (ReadContentInputStreamException ex) {
919  logger.log(Level.WARNING, String.format("Error reading Firefox Autofill profiles artifacts file '%s' (id=%d).",
920  profileFile.getName(), profileFile.getId()), ex); //NON-NLS
921  this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Firefox.getAutofillProfiles.errMsg.errAnalyzingFile",
922  this.getDisplayName(), profileFile.getName()));
923  continue;
924  } catch (IOException ex) {
925  logger.log(Level.SEVERE, String.format("Error writing temp file '%s' for Firefox Autofill profiles file '%s' (id=%d).",
926  temps, profileFile.getName(), profileFile.getId()), ex); //NON-NLS
927  this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Firefox.getAutofillProfiles.errMsg.errAnalyzingFile",
928  this.getDisplayName(), profileFile.getName()));
929  continue;
930  }
931 
932  logger.log(Level.INFO, "{0}- Now getting Bookmarks from {1}", new Object[]{getDisplayName(), temps}); //NON-NLS
933  File dbFile = new File(temps);
934  if (context.dataSourceIngestIsCancelled()) {
935  dbFile.delete();
936  break;
937  }
938 
939  FileReader tempReader;
940  try {
941  tempReader = new FileReader(temps);
942  } catch (FileNotFoundException ex) {
943  logger.log(Level.SEVERE, "Error while trying to read the Autofill profiles json file for Firefox.", ex); //NON-NLS
944  this.addErrorMessage(
945  NbBundle.getMessage(this.getClass(), "Firefox.getAutofillProfiles.errMsg.errAnalyzeFile", this.getDisplayName(),
946  profileFile.getName()));
947  continue;
948  }
949 
950  final JsonParser parser = new JsonParser();
951 
952  JsonObject jsonRootObject;
953  JsonArray jAddressesArray;
954 
955  try {
956  jsonRootObject = parser.parse(tempReader).getAsJsonObject();
957  jAddressesArray = jsonRootObject.getAsJsonArray("addresses"); //NON-NLS
958  } catch (JsonIOException | JsonSyntaxException | IllegalStateException ex) {
959  logger.log(Level.WARNING, "Error parsing Json for Firefox Autofill profiles.", ex); //NON-NLS
960  this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Firefox.getAutofillProfiles.errMsg.errAnalyzingFile3",
961  this.getDisplayName(), profileFile.getName()));
962  continue;
963  }
964 
965  WebBrowserArtifactsHelper helper;
966  try {
967  // Helper to create web form address artifacts.
968  helper = new WebBrowserArtifactsHelper(
969  Case.getCurrentCaseThrows().getSleuthkitCase(),
970  NbBundle.getMessage(this.getClass(), "Firefox.parentModuleName"),
971  profileFile
972  );
973  } catch (NoCurrentCaseException ex) {
974  logger.log(Level.SEVERE, "No case open, bailing.", ex); //NON-NLS
975  return;
976  }
977 
978  for (JsonElement result : jAddressesArray) {
979  JsonObject address = result.getAsJsonObject();
980  if (address == null) {
981  continue;
982  }
983 
984  JsonElement nameEl = address.get("name"); //NON-NLS
985  String name = (nameEl != null) ? nameEl.getAsString() : "";
986 
987  JsonElement emailEl = address.get("email"); //NON-NLS
988  String email = (emailEl != null) ? emailEl.getAsString() : "";
989 
990  JsonElement telEl = address.get("tel"); //NON-NLS
991  String tel = (telEl != null) ? telEl.getAsString() : "";
992  JsonElement telCountryCodeEl = address.get("tel-country-code"); //NON-NLS
993  String telCountryCode = (telCountryCodeEl != null) ? telCountryCodeEl.getAsString() : "";
994  JsonElement telNationalEl = address.get("tel-national"); //NON-NLS
995  String telNational = (telNationalEl != null) ? telNationalEl.getAsString() : "";
996 
997  String phoneNumber = makeTelNumber(tel, telCountryCode, telNational);
998 
999  JsonElement createdEl = address.get("timeCreated"); //NON-NLS
1000  Long datetimeCreated = (createdEl != null) ? createdEl.getAsLong() / 1000 : Long.valueOf(0);
1001  JsonElement lastusedEl = address.get("timeLastUsed"); //NON-NLS
1002  Long datetimeLastUsed = (lastusedEl != null) ? lastusedEl.getAsLong() / 1000 : Long.valueOf(0);
1003  JsonElement timesUsedEl = address.get("timesUsed"); //NON-NLS
1004  Integer timesUsed = (timesUsedEl != null) ? timesUsedEl.getAsShort() : Integer.valueOf(0);
1005 
1006  JsonElement addressLine1El = address.get("address-line1"); //NON-NLS
1007  String addressLine1 = (addressLine1El != null) ? addressLine1El.getAsString() : "";
1008  JsonElement addressLine2El = address.get("address-line2"); //NON-NLS
1009  String addressLine2 = (addressLine2El != null) ? addressLine2El.getAsString() : "";
1010  JsonElement addressLine3El = address.get("address-line3"); //NON-NLS
1011  String addressLine3 = (addressLine3El != null) ? addressLine3El.getAsString() : "";
1012 
1013  JsonElement postalCodeEl = address.get("postal-code"); //NON-NLS
1014  String postalCode = (postalCodeEl != null) ? postalCodeEl.getAsString() : "";
1015  JsonElement countryEl = address.get("country"); //NON-NLS
1016  String country = (countryEl != null) ? countryEl.getAsString() : "";
1017 
1018  String mailingAddress = makeFullAddress(addressLine1, addressLine2, addressLine3, postalCode, country);
1019 
1020  try {
1021  helper.addWebFormAddress(name, email, phoneNumber,
1022  mailingAddress, datetimeCreated, datetimeLastUsed, timesUsed);
1023  } catch (TskCoreException | Blackboard.BlackboardException ex) {
1024  logger.log(Level.SEVERE, "Error while trying to insert Firefox Autofill profile artifact{0}", ex); //NON-NLS
1025  this.addErrorMessage(
1026  NbBundle.getMessage(this.getClass(), "Firefox.getAutofillProfiles.errMsg.errAnalyzingFile4",
1027  this.getDisplayName(), profileFile.getName()));
1028  }
1029  }
1030  dbFile.delete();
1031  }
1032  }
1033 
1042  private String extractDomain(String url) {
1043  if (url == null || url.isEmpty()) {
1044  return url;
1045  }
1046 
1047  if (url.toLowerCase().startsWith(PLACE_URL_PREFIX)) {
1048  /*
1049  * Ignore URLs that begin with the matched text.
1050  */
1051  return null;
1052  }
1053 
1054  return NetworkUtils.extractDomain(url);
1055  }
1056 
1068  private String makeTelNumber(String tel, String telCountryCode, String telNational) {
1069 
1070  if (tel != null && !tel.isEmpty()) {
1071  return tel;
1072  }
1073 
1074  if ((telCountryCode != null && !telCountryCode.isEmpty())
1075  && (telNational != null && !telNational.isEmpty())) {
1076  return telCountryCode + telNational;
1077  }
1078 
1079  return "";
1080  }
1081 
1093  private String makeFullAddress(String addressLine1, String addressLine2, String addressLine3, String postalCode, String country) {
1094  String fullAddress = "";
1095  fullAddress = appendAddressField(fullAddress, addressLine1);
1096  fullAddress = appendAddressField(fullAddress, addressLine2);
1097  fullAddress = appendAddressField(fullAddress, addressLine3);
1098  fullAddress = appendAddressField(fullAddress, postalCode);
1099  fullAddress = appendAddressField(fullAddress, country);
1100 
1101  return fullAddress;
1102  }
1103 
1113  private String appendAddressField(String address, String addressfield) {
1114 
1115  String updatedAddress = address;
1116  if (addressfield != null && !addressfield.isEmpty()) {
1117  if (!updatedAddress.isEmpty()) {
1118  updatedAddress += ", ";
1119  }
1120  updatedAddress += addressfield;
1121  }
1122 
1123  return updatedAddress;
1124  }
1125 
1126 }

Copyright © 2012-2021 Basis Technology. Generated on: Tue Feb 22 2022
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.