Autopsy  4.19.1
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.BlackboardArtifact.ARTIFACT_TYPE;
60 import org.sleuthkit.datamodel.BlackboardAttribute;
61 import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
62 import org.sleuthkit.datamodel.Content;
63 import org.sleuthkit.datamodel.ReadContentInputStream.ReadContentInputStreamException;
64 import org.sleuthkit.datamodel.TskCoreException;
65 import org.sleuthkit.datamodel.blackboardutils.WebBrowserArtifactsHelper;
66 
67 @Messages({
68  "Progress_Message_Firefox_History=Firefox History",
69  "Progress_Message_Firefox_Bookmarks=Firefox Bookmarks",
70  "Progress_Message_Firefox_Cookies=Firefox Cookies",
71  "Progress_Message_Firefox_Downloads=Firefox Downloads",
72  "Progress_Message_Firefox_FormHistory=Firefox Form History",
73  "Progress_Message_Firefox_AutoFill=Firefox Auto Fill"
74 })
75 
79 class Firefox extends Extract {
80 
81  private static final Logger logger = Logger.getLogger(Firefox.class.getName());
82  private static final String PLACE_URL_PREFIX = "place:";
83  private static final String HISTORY_QUERY = "SELECT moz_historyvisits.id, url, title, visit_count,(visit_date/1000000) AS visit_date,from_visit,"
84  + "(SELECT url FROM moz_historyvisits history, moz_places places where history.id = moz_historyvisits.from_visit and history.place_id = places.id ) as ref "
85  + "FROM moz_places, moz_historyvisits "
86  + "WHERE moz_places.id = moz_historyvisits.place_id "
87  + "AND hidden = 0"; //NON-NLS
88  private static final String COOKIE_QUERY = "SELECT name,value,host,expiry,(lastAccessed/1000000) AS lastAccessed,(creationTime/1000000) AS creationTime FROM moz_cookies"; //NON-NLS
89  private static final String COOKIE_QUERY_V3 = "SELECT name,value,host,expiry,(lastAccessed/1000000) AS lastAccessed FROM moz_cookies"; //NON-NLS
90  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
91  private static final String DOWNLOAD_QUERY = "SELECT target, source,(startTime/1000000) AS startTime, maxBytes FROM moz_downloads"; //NON-NLS
92  private static final String DOWNLOAD_QUERY_V24 = "SELECT url, content AS target, (lastModified/1000000) AS lastModified "
93  + " FROM moz_places, moz_annos, moz_anno_attributes "
94  + " WHERE moz_places.id = moz_annos.place_id"
95  + " AND moz_annos.anno_attribute_id = moz_anno_attributes.id"
96  + " AND moz_anno_attributes.name='downloads/destinationFileURI'"; //NON-NLS
97  private static final String FORMHISTORY_QUERY = "SELECT fieldname, value FROM moz_formhistory";
98  private static final String FORMHISTORY_QUERY_V64 = "SELECT fieldname, value, timesUsed, firstUsed, lastUsed FROM moz_formhistory";
99  private Content dataSource;
100  private IngestJobContext context;
101 
102  Firefox() {
103  super(NbBundle.getMessage(Firefox.class, "Firefox.moduleName"));
104  }
105 
106  @Override
107  public void process(Content dataSource, IngestJobContext context, DataSourceIngestModuleProgress progressBar) {
108  this.dataSource = dataSource;
109  this.context = context;
110  dataFound = false;
111  long ingestJobId = context.getJobId();
112 
113  progressBar.progress(Bundle.Progress_Message_Firefox_History());
114  this.getHistory(context.getJobId());
115 
116  if (context.dataSourceIngestIsCancelled()) {
117  return;
118  }
119 
120  progressBar.progress(Bundle.Progress_Message_Firefox_Bookmarks());
121  this.getBookmark(ingestJobId);
122 
123  if (context.dataSourceIngestIsCancelled()) {
124  return;
125  }
126 
127  progressBar.progress(Bundle.Progress_Message_Firefox_Downloads());
128  this.getDownload(ingestJobId);
129 
130  if (context.dataSourceIngestIsCancelled()) {
131  return;
132  }
133 
134  progressBar.progress(Bundle.Progress_Message_Firefox_Cookies());
135  this.getCookie(ingestJobId);
136 
137  if (context.dataSourceIngestIsCancelled()) {
138  return;
139  }
140 
141  progressBar.progress(Bundle.Progress_Message_Firefox_FormHistory());
142  this.getFormsHistory(ingestJobId);
143 
144  if (context.dataSourceIngestIsCancelled()) {
145  return;
146  }
147 
148  progressBar.progress(Bundle.Progress_Message_Firefox_AutoFill());
149  this.getAutofillProfiles(ingestJobId);
150  }
151 
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.getName() + ": " + 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.getName(),
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.getName(),
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.dbConnect(temps, HISTORY_QUERY);
212  logger.log(Level.INFO, "{0} - Now getting history from {1} with {2} artifacts identified.", new Object[]{getName(), 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(ARTIFACT_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 
264  private void getBookmark(long ingestJobId) {
265 
266  FileManager fileManager = currentCase.getServices().getFileManager();
267  List<AbstractFile> bookmarkFiles;
268  try {
269  bookmarkFiles = fileManager.findFiles(dataSource, "places.sqlite", "Firefox"); //NON-NLS
270  } catch (TskCoreException ex) {
271  String msg = NbBundle.getMessage(this.getClass(), "Firefox.getBookmark.errMsg.errFetchFiles");
272  logger.log(Level.WARNING, msg);
273  this.addErrorMessage(this.getName() + ": " + msg);
274  return;
275  }
276 
277  if (bookmarkFiles.isEmpty()) {
278  logger.log(Level.INFO, "Didn't find any firefox bookmark files."); //NON-NLS
279  return;
280  }
281 
282  dataFound = true;
283  Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
284  int j = 0;
285  for (AbstractFile bookmarkFile : bookmarkFiles) {
286  if (bookmarkFile.getSize() == 0) {
287  continue;
288  }
289  String fileName = bookmarkFile.getName();
290  String temps = RAImageIngestModule.getRATempPath(currentCase, "firefox", ingestJobId) + File.separator + fileName + j + ".db"; //NON-NLS
291  try {
292  ContentUtils.writeToFile(bookmarkFile, new File(temps), context::dataSourceIngestIsCancelled);
293  } catch (ReadContentInputStreamException ex) {
294  logger.log(Level.WARNING, String.format("Error reading Firefox bookmark artifacts file '%s' (id=%d).",
295  fileName, bookmarkFile.getId()), ex); //NON-NLS
296  this.addErrorMessage(
297  NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errAnalyzeFile", this.getName(),
298  fileName));
299  continue;
300  } catch (IOException ex) {
301  logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Firefox bookmark artifacts file '%s' (id=%d).",
302  temps, fileName, bookmarkFile.getId()), ex); //NON-NLS
303  this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Firefox.getBookmark.errMsg.errAnalyzeFile",
304  this.getName(), fileName));
305  continue;
306  }
307  File dbFile = new File(temps);
308  if (context.dataSourceIngestIsCancelled()) {
309  dbFile.delete();
310  break;
311  }
312  List<HashMap<String, Object>> tempList = this.dbConnect(temps, BOOKMARK_QUERY);
313  logger.log(Level.INFO, "{0} - Now getting bookmarks from {1} with {2} artifacts identified.", new Object[]{getName(), temps, tempList.size()}); //NON-NLS
314  for (HashMap<String, Object> result : tempList) {
315 
316  if (context.dataSourceIngestIsCancelled()) {
317  break;
318  }
319 
320  String url = result.get("url").toString();
321 
322  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
323  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
324  RecentActivityExtracterModuleFactory.getModuleName(),
325  ((url != null) ? url : ""))); //NON-NLS
326  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TITLE,
327  RecentActivityExtracterModuleFactory.getModuleName(),
328  ((result.get("title").toString() != null) ? result.get("title").toString() : ""))); //NON-NLS
329  if (Long.valueOf(result.get("dateAdded").toString()) > 0) { //NON-NLS
330  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
331  RecentActivityExtracterModuleFactory.getModuleName(),
332  (Long.valueOf(result.get("dateAdded").toString())))); //NON-NLS
333  }
334  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
335  RecentActivityExtracterModuleFactory.getModuleName(),
336  NbBundle.getMessage(this.getClass(), "Firefox.moduleName")));
337  String domain = extractDomain(url);
338  if (domain != null && domain.isEmpty() == false) {
339  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
340  RecentActivityExtracterModuleFactory.getModuleName(), domain)); //NON-NLS
341  }
342 
343  try {
344  bbartifacts.add(createArtifactWithAttributes(ARTIFACT_TYPE.TSK_WEB_BOOKMARK, bookmarkFile, bbattributes));
345  } catch (TskCoreException ex) {
346  logger.log(Level.SEVERE, String.format("Failed to create TSK_WEB_BOOKMARK artifact for file %d", bookmarkFile.getId()), ex);
347  }
348  }
349  ++j;
350  dbFile.delete();
351  }
352 
353  if(!context.dataSourceIngestIsCancelled()) {
354  postArtifacts(bbartifacts);
355  }
356  }
357 
362  private void getCookie(long ingestJobId) {
363  FileManager fileManager = currentCase.getServices().getFileManager();
364  List<AbstractFile> cookiesFiles;
365  try {
366  cookiesFiles = fileManager.findFiles(dataSource, "cookies.sqlite", "Firefox"); //NON-NLS
367  } catch (TskCoreException ex) {
368  String msg = NbBundle.getMessage(this.getClass(), "Firefox.getCookie.errMsg.errFetchFile");
369  logger.log(Level.WARNING, msg);
370  this.addErrorMessage(this.getName() + ": " + msg);
371  return;
372  }
373 
374  if (cookiesFiles.isEmpty()) {
375  logger.log(Level.INFO, "Didn't find any Firefox cookie files."); //NON-NLS
376  return;
377  }
378 
379  dataFound = true;
380  Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
381  int j = 0;
382  for (AbstractFile cookiesFile : cookiesFiles) {
383  if (context.dataSourceIngestIsCancelled()) {
384  return;
385  }
386 
387  if (cookiesFile.getSize() == 0) {
388  continue;
389  }
390  String fileName = cookiesFile.getName();
391  String temps = RAImageIngestModule.getRATempPath(currentCase, "firefox", ingestJobId) + File.separator + fileName + j + ".db"; //NON-NLS
392  try {
393  ContentUtils.writeToFile(cookiesFile, new File(temps), context::dataSourceIngestIsCancelled);
394  } catch (ReadContentInputStreamException ex) {
395  logger.log(Level.WARNING, String.format("Error reading Firefox cookie artifacts file '%s' (id=%d).",
396  fileName, cookiesFile.getId()), ex); //NON-NLS
397  this.addErrorMessage(
398  NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errAnalyzeFile", this.getName(),
399  fileName));
400  continue;
401  } catch (IOException ex) {
402  logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Firefox cookie artifacts file '%s' (id=%d).",
403  temps, fileName, cookiesFile.getId()), ex); //NON-NLS
404  this.addErrorMessage(
405  NbBundle.getMessage(this.getClass(), "Firefox.getCookie.errMsg.errAnalyzeFile", this.getName(),
406  fileName));
407  continue;
408  }
409  File dbFile = new File(temps);
410  if (context.dataSourceIngestIsCancelled()) {
411  dbFile.delete();
412  break;
413  }
414  boolean checkColumn = Util.checkColumn("creationTime", "moz_cookies", temps); //NON-NLS
415  String query;
416  if (checkColumn) {
417  query = COOKIE_QUERY;
418  } else {
419  query = COOKIE_QUERY_V3;
420  }
421 
422  List<HashMap<String, Object>> tempList = this.dbConnect(temps, query);
423  logger.log(Level.INFO, "{0} - Now getting cookies from {1} with {2} artifacts identified.", new Object[]{getName(), temps, tempList.size()}); //NON-NLS
424  for (HashMap<String, Object> result : tempList) {
425 
426  if (context.dataSourceIngestIsCancelled()) {
427  break;
428  }
429 
430  String host = result.get("host").toString();
431 
432  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
433  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
434  RecentActivityExtracterModuleFactory.getModuleName(),
435  ((host != null) ? host : ""))); //NON-NLS
436  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
437  RecentActivityExtracterModuleFactory.getModuleName(),
438  (Long.valueOf(result.get("lastAccessed").toString())))); //NON-NLS
439  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME,
440  RecentActivityExtracterModuleFactory.getModuleName(),
441  ((result.get("name").toString() != null) ? result.get("name").toString() : ""))); //NON-NLS
442  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE,
443  RecentActivityExtracterModuleFactory.getModuleName(),
444  ((result.get("value").toString() != null) ? result.get("value").toString() : ""))); //NON-NLS
445  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
446  RecentActivityExtracterModuleFactory.getModuleName(),
447  NbBundle.getMessage(this.getClass(), "Firefox.moduleName")));
448 
449  if (checkColumn == true) {
450  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
451  RecentActivityExtracterModuleFactory.getModuleName(),
452  (Long.valueOf(result.get("creationTime").toString())))); //NON-NLS
453  }
454  String domain = extractDomain(host);
455  if (domain != null && domain.isEmpty() == false) {
456  domain = domain.replaceFirst("^\\.+(?!$)", "");
457  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
458  RecentActivityExtracterModuleFactory.getModuleName(), domain));
459  }
460 
461  try {
462  bbartifacts.add(createArtifactWithAttributes(ARTIFACT_TYPE.TSK_WEB_COOKIE, cookiesFile, bbattributes));
463  } catch (TskCoreException ex) {
464  logger.log(Level.SEVERE, String.format("Failed to create TSK_WEB_COOKIE artifact for file %d", cookiesFile.getId()), ex);
465  }
466  }
467  ++j;
468  dbFile.delete();
469  }
470 
471  if (!context.dataSourceIngestIsCancelled()) {
472  postArtifacts(bbartifacts);
473  }
474  }
475 
480  private void getDownload(long ingestJobId) {
481  getDownloadPreVersion24(ingestJobId);
482  getDownloadVersion24(ingestJobId);
483  }
484 
491  private void getDownloadPreVersion24(long ingestJobId) {
492 
493  FileManager fileManager = currentCase.getServices().getFileManager();
494  List<AbstractFile> downloadsFiles;
495  try {
496  downloadsFiles = fileManager.findFiles(dataSource, "downloads.sqlite", "Firefox"); //NON-NLS
497  } catch (TskCoreException ex) {
498  String msg = NbBundle.getMessage(this.getClass(), "Firefox.getDlPre24.errMsg.errFetchFiles");
499  logger.log(Level.WARNING, msg);
500  this.addErrorMessage(this.getName() + ": " + msg);
501  return;
502  }
503 
504  if (downloadsFiles.isEmpty()) {
505  logger.log(Level.INFO, "Didn't find any pre-version-24.0 Firefox download files."); //NON-NLS
506  return;
507  }
508 
509  dataFound = true;
510  Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
511  int j = 0;
512  for (AbstractFile downloadsFile : downloadsFiles) {
513  if (downloadsFile.getSize() == 0) {
514  continue;
515  }
516  String fileName = downloadsFile.getName();
517  String temps = RAImageIngestModule.getRATempPath(currentCase, "firefox", ingestJobId) + File.separator + fileName + j + ".db"; //NON-NLS
518  int errors = 0;
519  try {
520  ContentUtils.writeToFile(downloadsFile, new File(temps), context::dataSourceIngestIsCancelled);
521  } catch (ReadContentInputStreamException ex) {
522  logger.log(Level.WARNING, String.format("Error reading Firefox download artifacts file '%s' (id=%d).",
523  fileName, downloadsFile.getId()), ex); //NON-NLS
524  this.addErrorMessage(
525  NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errAnalyzeFile", this.getName(),
526  fileName));
527  continue;
528  } catch (IOException ex) {
529  logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Firefox download artifacts file '%s' (id=%d).",
530  temps, fileName, downloadsFile.getId()), ex); //NON-NLS
531  this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Firefox.getDlPre24.errMsg.errAnalyzeFiles",
532  this.getName(), fileName));
533  continue;
534  }
535  File dbFile = new File(temps);
536  if (context.dataSourceIngestIsCancelled()) {
537  dbFile.delete();
538  break;
539  }
540 
541  List<HashMap<String, Object>> tempList = this.dbConnect(temps, DOWNLOAD_QUERY);
542  logger.log(Level.INFO, "{0}- Now getting downloads from {1} with {2} artifacts identified.", new Object[]{getName(), temps, tempList.size()}); //NON-NLS
543  for (HashMap<String, Object> result : tempList) {
544 
545  if (context.dataSourceIngestIsCancelled()) {
546  break;
547  }
548 
549  String source = result.get("source").toString();
550 
551  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
552 
553  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
554  RecentActivityExtracterModuleFactory.getModuleName(),
555  source)); //NON-NLS
556  //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", ((result.get("source").toString() != null) ? EscapeUtil.decodeURL(result.get("source").toString()) : "")));
557  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
558  RecentActivityExtracterModuleFactory.getModuleName(),
559  (Long.valueOf(result.get("startTime").toString())))); //NON-NLS
560 
561  String target = result.get("target").toString(); //NON-NLS
562  String downloadedFilePath = "";
563  if (target != null) {
564  try {
565  downloadedFilePath = URLDecoder.decode(target.replaceAll("file:///", ""), "UTF-8"); //NON-NLS
566  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
567  RecentActivityExtracterModuleFactory.getModuleName(),
568  downloadedFilePath));
569  long pathID = Util.findID(dataSource, downloadedFilePath);
570  if (pathID != -1) {
571  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH_ID,
572  RecentActivityExtracterModuleFactory.getModuleName(),
573  pathID));
574  }
575  } catch (UnsupportedEncodingException ex) {
576  logger.log(Level.SEVERE, "Error decoding Firefox download URL in " + temps, ex); //NON-NLS
577  errors++;
578  }
579  }
580 
581  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
582  RecentActivityExtracterModuleFactory.getModuleName(),
583  NbBundle.getMessage(this.getClass(), "Firefox.moduleName")));
584  String domain = extractDomain(source);
585  if (domain != null && domain.isEmpty() == false) {
586  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
587  RecentActivityExtracterModuleFactory.getModuleName(),
588  domain)); //NON-NLS
589  }
590  try {
591  BlackboardArtifact webDownloadArtifact = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, downloadsFile, bbattributes);
592  bbartifacts.add(webDownloadArtifact);
593 
594  // find the downloaded file and create a TSK_ASSOCIATED_OBJECT for it, associating it with the TSK_WEB_DOWNLOAD artifact.
595  for (AbstractFile downloadedFile : currentCase.getSleuthkitCase().getFileManager().findFilesExactNameExactPath(dataSource,
596  FilenameUtils.getName(downloadedFilePath), FilenameUtils.getPath(downloadedFilePath))) {
597  bbartifacts.add(createAssociatedArtifact(downloadedFile, webDownloadArtifact));
598  break;
599  }
600  } catch (TskCoreException ex) {
601  logger.log(Level.SEVERE, String.format("Error creating TSK_WEB_DOWNLOAD or TSK_ASSOCIATED_ARTIFACT artifact for file '%d'",
602  downloadsFile.getId()), ex); //NON-NLS
603  }
604 
605  }
606  if (errors > 0) {
607  this.addErrorMessage(
608  NbBundle.getMessage(this.getClass(), "Firefox.getDlPre24.errMsg.errParsingArtifacts",
609  this.getName(), errors));
610  }
611  j++;
612  dbFile.delete();
613  }
614 
615  if(!context.dataSourceIngestIsCancelled()) {
616  postArtifacts(bbartifacts);
617  }
618  }
619 
626  private void getDownloadVersion24(long ingestJobId) {
627  FileManager fileManager = currentCase.getServices().getFileManager();
628  List<AbstractFile> downloadsFiles;
629  try {
630  downloadsFiles = fileManager.findFiles(dataSource, "places.sqlite", "Firefox"); //NON-NLS
631  } catch (TskCoreException ex) {
632  String msg = NbBundle.getMessage(this.getClass(), "Firefox.getDlV24.errMsg.errFetchFiles");
633  logger.log(Level.WARNING, msg);
634  this.addErrorMessage(this.getName() + ": " + msg);
635  return;
636  }
637 
638  if (downloadsFiles.isEmpty()) {
639  logger.log(Level.INFO, "Didn't find any version-24.0 Firefox download files."); //NON-NLS
640  return;
641  }
642 
643  dataFound = true;
644  Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
645  int j = 0;
646  for (AbstractFile downloadsFile : downloadsFiles) {
647  if (downloadsFile.getSize() == 0) {
648  continue;
649  }
650  String fileName = downloadsFile.getName();
651  String temps = RAImageIngestModule.getRATempPath(currentCase, "firefox", ingestJobId) + File.separator + fileName + "-downloads" + j + ".db"; //NON-NLS
652  int errors = 0;
653  try {
654  ContentUtils.writeToFile(downloadsFile, new File(temps), context::dataSourceIngestIsCancelled);
655  } catch (ReadContentInputStreamException ex) {
656  logger.log(Level.WARNING, String.format("Error reading Firefox download artifacts file '%s' (id=%d).",
657  fileName, downloadsFile.getId()), ex); //NON-NLS
658  this.addErrorMessage(
659  NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errAnalyzeFile", this.getName(),
660  fileName));
661  continue;
662  } catch (IOException ex) {
663  logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Firefox download artifacts file '%s' (id=%d).",
664  temps, fileName, downloadsFile.getId()), ex); //NON-NLS
665  this.addErrorMessage(
666  NbBundle.getMessage(this.getClass(), "Firefox.getDlV24.errMsg.errAnalyzeFile", this.getName(),
667  fileName));
668  continue;
669  }
670  File dbFile = new File(temps);
671  if (context.dataSourceIngestIsCancelled()) {
672  dbFile.delete();
673  break;
674  }
675 
676  List<HashMap<String, Object>> tempList = this.dbConnect(temps, DOWNLOAD_QUERY_V24);
677 
678  logger.log(Level.INFO, "{0} - Now getting downloads from {1} with {2} artifacts identified.", new Object[]{getName(), temps, tempList.size()}); //NON-NLS
679  for (HashMap<String, Object> result : tempList) {
680 
681  if (context.dataSourceIngestIsCancelled()) {
682  break;
683  }
684 
685  String url = result.get("url").toString();
686 
687  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
688 
689  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
690  RecentActivityExtracterModuleFactory.getModuleName(),
691  url)); //NON-NLS
692  //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", ((result.get("source").toString() != null) ? EscapeUtil.decodeURL(result.get("source").toString()) : "")));
693  //TODO Revisit usage of deprecated constructor as per TSK-583
694  //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LAST_ACCESSED.getTypeID(), "RecentActivity", "Last Visited", (Long.valueOf(result.get("startTime").toString()))));
695 
696  String target = result.get("target").toString(); //NON-NLS
697  String downloadedFilePath = "";
698  if (target != null) {
699  try {
700  downloadedFilePath = URLDecoder.decode(target.replaceAll("file:///", ""), "UTF-8"); //NON-NLS
701  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
702  RecentActivityExtracterModuleFactory.getModuleName(),
703  downloadedFilePath));
704  long pathID = Util.findID(dataSource, downloadedFilePath);
705  if (pathID != -1) {
706  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH_ID,
707  RecentActivityExtracterModuleFactory.getModuleName(),
708  pathID));
709  }
710  } catch (UnsupportedEncodingException ex) {
711  logger.log(Level.SEVERE, "Error decoding Firefox download URL in " + temps, ex); //NON-NLS
712  errors++;
713  }
714  }
715  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
716  RecentActivityExtracterModuleFactory.getModuleName(),
717  Long.valueOf(result.get("lastModified").toString()))); //NON-NLS
718  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
719  RecentActivityExtracterModuleFactory.getModuleName(),
720  NbBundle.getMessage(this.getClass(), "Firefox.moduleName")));
721  String domain = extractDomain(url);
722  if (domain != null && domain.isEmpty() == false) {
723  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
724  RecentActivityExtracterModuleFactory.getModuleName(), domain)); //NON-NLS
725  }
726  try {
727  BlackboardArtifact webDownloadArtifact = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, downloadsFile, bbattributes);
728  bbartifacts.add(webDownloadArtifact);
729 
730  // find the downloaded file and create a TSK_ASSOCIATED_OBJECT for it, associating it with the TSK_WEB_DOWNLOAD artifact.
731  for (AbstractFile downloadedFile : currentCase.getSleuthkitCase().getFileManager().findFilesExactNameExactPath(dataSource,
732  FilenameUtils.getName(downloadedFilePath), FilenameUtils.getPath(downloadedFilePath))) {
733  bbartifacts.add(createAssociatedArtifact(downloadedFile, webDownloadArtifact));
734  break;
735  }
736  } catch (TskCoreException ex) {
737  logger.log(Level.SEVERE, String.format("Error creating associated object artifact for file '%s'",
738  downloadedFilePath), ex); //NON-NLS
739  }
740  }
741  if (errors > 0) {
742  this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Firefox.getDlV24.errMsg.errParsingArtifacts",
743  this.getName(), errors));
744  }
745  j++;
746  dbFile.delete();
747  }
748 
749  if(!context.dataSourceIngestIsCancelled()) {
750  postArtifacts(bbartifacts);
751  }
752  }
753 
759  private void getFormsHistory(long ingestJobId) {
760  FileManager fileManager = currentCase.getServices().getFileManager();
761  List<AbstractFile> formHistoryFiles;
762 
763  // Some fields are just noisy and can me excluded
764  Set<String> excludedFieldNames = new HashSet<>(Arrays.asList(
765  "it", // some kind of timestamp
766  "ts" // some kind of timestamp
767  ));
768 
769  try {
770  formHistoryFiles = fileManager.findFiles(dataSource, "formhistory.sqlite", "Firefox"); //NON-NLS
771  } catch (TskCoreException ex) {
772  String msg = NbBundle.getMessage(this.getClass(), "Firefox.getFormsAutofill.errMsg.errFetchingFiles");
773  logger.log(Level.WARNING, msg);
774  this.addErrorMessage(this.getName() + ": " + msg);
775  return;
776  }
777 
778  if (formHistoryFiles.isEmpty()) {
779  String msg = NbBundle.getMessage(this.getClass(), "Firefox.getFormsAutofill.errMsg.noFilesFound");
780  logger.log(Level.INFO, msg);
781  return;
782  }
783 
784  dataFound = true;
785  Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
786  int j = 0;
787  for (AbstractFile formHistoryFile : formHistoryFiles) {
788  if (formHistoryFile.getSize() == 0) {
789  continue;
790  }
791 
792  String fileName = formHistoryFile.getName();
793  String tempFilePath = RAImageIngestModule.getRATempPath(currentCase, "firefox", ingestJobId) + File.separator + fileName + j + ".db"; //NON-NLS
794  try {
795  ContentUtils.writeToFile(formHistoryFile, new File(tempFilePath), context::dataSourceIngestIsCancelled);
796  } catch (ReadContentInputStreamException ex) {
797  logger.log(Level.WARNING, String.format("Error reading Firefox web history artifacts file '%s' (id=%d).",
798  fileName, formHistoryFile.getId()), ex); //NON-NLS
799  this.addErrorMessage(
800  NbBundle.getMessage(this.getClass(), "Firefox.getFormsAutofill.errMsg.errAnalyzeFile", this.getName(),
801  fileName));
802  continue;
803  } catch (IOException ex) {
804  logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Firefox web history artifacts file '%s' (id=%d).",
805  tempFilePath, fileName, formHistoryFile.getId()), ex); //NON-NLS
806  this.addErrorMessage(
807  NbBundle.getMessage(this.getClass(), "Firefox.getFormsAutofill.errMsg.errAnalyzeFile", this.getName(),
808  fileName));
809  continue;
810  }
811  File dbFile = new File(tempFilePath);
812  if (context.dataSourceIngestIsCancelled()) {
813  dbFile.delete();
814  break;
815  }
816 
817  // The table schema is a little different in newer version of Firefox
818  boolean isFirefoxV64 = Util.checkColumn("timesUsed", "moz_formhistory", tempFilePath);
819  String formHistoryQuery = (isFirefoxV64) ? FORMHISTORY_QUERY_V64 : FORMHISTORY_QUERY;
820 
821  List<HashMap<String, Object>> tempList = this.dbConnect(tempFilePath, formHistoryQuery);
822  logger.log(Level.INFO, "{0} - Now getting history from {1} with {2} artifacts identified.", new Object[]{getName(), tempFilePath, tempList.size()}); //NON-NLS
823  for (HashMap<String, Object> result : tempList) {
824 
825  if (context.dataSourceIngestIsCancelled()) {
826  break;
827  }
828 
829  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
830 
831  String fieldName = ((result.get("fieldname").toString() != null) ? result.get("fieldname").toString() : "");
832  // filter out unuseful values
833  if (excludedFieldNames.contains(fieldName.toLowerCase())) {
834  continue;
835  }
836 
837  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME,
838  RecentActivityExtracterModuleFactory.getModuleName(),
839  fieldName)); //NON-NLS
840 
841  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE,
842  RecentActivityExtracterModuleFactory.getModuleName(),
843  ((result.get("value").toString() != null) ? result.get("value").toString() : ""))); //NON-NLS
844 
845  // Newer versions of firefox have additional columns
846  if (isFirefoxV64) {
847  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
848  RecentActivityExtracterModuleFactory.getModuleName(),
849  (Long.valueOf(result.get("firstUsed").toString()) / 1000000))); //NON-NLS
850 
851  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
852  RecentActivityExtracterModuleFactory.getModuleName(),
853  (Long.valueOf(result.get("lastUsed").toString()) / 1000000))); //NON-NLS
854 
855  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COUNT,
856  RecentActivityExtracterModuleFactory.getModuleName(),
857  (Integer.valueOf(result.get("timesUsed").toString())))); //NON-NLS
858 
859  }
860  try {
861  // Add artifact
862  bbartifacts.add(createArtifactWithAttributes(ARTIFACT_TYPE.TSK_WEB_FORM_AUTOFILL, formHistoryFile, bbattributes));
863  } catch (TskCoreException ex) {
864  logger.log(Level.SEVERE, String.format("Failed to create TSK_WEB_FORM_AUTOFILL artifact for file %d", formHistoryFile.getId()), ex);
865  }
866  }
867  ++j;
868  dbFile.delete();
869  }
870 
871  if(!context.dataSourceIngestIsCancelled()) {
872  postArtifacts(bbartifacts);
873  }
874  }
875 
876 
882  private void getAutofillProfiles(long ingestJobId) {
883  FileManager fileManager = currentCase.getServices().getFileManager();
884  List<AbstractFile> autofillProfilesFiles;
885  try {
886  autofillProfilesFiles = fileManager.findFiles(dataSource, "autofill-profiles.json", "Firefox"); //NON-NLS
887  } catch (TskCoreException ex) {
888  String msg = NbBundle.getMessage(this.getClass(), "Firefox.getAutofillProfiles.errMsg.errGettingFiles");
889  logger.log(Level.SEVERE, msg, ex);
890  this.addErrorMessage(this.getName() + ": " + msg);
891  return;
892  }
893 
894  if (autofillProfilesFiles.isEmpty()) {
895  logger.log(Level.INFO, "Didn't find any Firefox Autofill Profiles files."); //NON-NLS
896  return;
897  }
898 
899  dataFound = true;
900  int j = 0;
901 
902  while (j < autofillProfilesFiles.size()) {
903  AbstractFile profileFile = autofillProfilesFiles.get(j++);
904  if (profileFile.getSize() == 0) {
905  continue;
906  }
907  String temps = RAImageIngestModule.getRATempPath(currentCase, "Firefox", ingestJobId) + File.separator + profileFile.getName() + j + ".json"; //NON-NLS
908  try {
909  ContentUtils.writeToFile(profileFile, new File(temps), context::dataSourceIngestIsCancelled);
910  } catch (ReadContentInputStreamException ex) {
911  logger.log(Level.WARNING, String.format("Error reading Firefox Autofill profiles artifacts file '%s' (id=%d).",
912  profileFile.getName(), profileFile.getId()), ex); //NON-NLS
913  this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Firefox.getAutofillProfiles.errMsg.errAnalyzingFile",
914  this.getName(), profileFile.getName()));
915  continue;
916  } catch (IOException ex) {
917  logger.log(Level.SEVERE, String.format("Error writing temp file '%s' for Firefox Autofill profiles file '%s' (id=%d).",
918  temps, profileFile.getName(), profileFile.getId()), ex); //NON-NLS
919  this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Firefox.getAutofillProfiles.errMsg.errAnalyzingFile",
920  this.getName(), profileFile.getName()));
921  continue;
922  }
923 
924  logger.log(Level.INFO, "{0}- Now getting Bookmarks from {1}", new Object[]{getName(), temps}); //NON-NLS
925  File dbFile = new File(temps);
926  if (context.dataSourceIngestIsCancelled()) {
927  dbFile.delete();
928  break;
929  }
930 
931  FileReader tempReader;
932  try {
933  tempReader = new FileReader(temps);
934  } catch (FileNotFoundException ex) {
935  logger.log(Level.SEVERE, "Error while trying to read the Autofill profiles json file for Firefox.", ex); //NON-NLS
936  this.addErrorMessage(
937  NbBundle.getMessage(this.getClass(), "Firefox.getAutofillProfiles.errMsg.errAnalyzeFile", this.getName(),
938  profileFile.getName()));
939  continue;
940  }
941 
942  final JsonParser parser = new JsonParser();
943 
944  JsonObject jsonRootObject;
945  JsonArray jAddressesArray;
946 
947  try {
948  jsonRootObject = parser.parse(tempReader).getAsJsonObject();
949  jAddressesArray = jsonRootObject.getAsJsonArray("addresses"); //NON-NLS
950  } catch (JsonIOException | JsonSyntaxException | IllegalStateException ex) {
951  logger.log(Level.WARNING, "Error parsing Json for Firefox Autofill profiles.", ex); //NON-NLS
952  this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Firefox.getAutofillProfiles.errMsg.errAnalyzingFile3",
953  this.getName(), profileFile.getName()));
954  continue;
955  }
956 
957  WebBrowserArtifactsHelper helper;
958  try {
959  // Helper to create web form address artifacts.
960  helper = new WebBrowserArtifactsHelper(
961  Case.getCurrentCaseThrows().getSleuthkitCase(),
962  NbBundle.getMessage(this.getClass(), "Firefox.parentModuleName"),
963  profileFile
964  );
965  } catch (NoCurrentCaseException ex) {
966  logger.log(Level.SEVERE, "No case open, bailing.", ex); //NON-NLS
967  return;
968  }
969 
970  for (JsonElement result : jAddressesArray) {
971  JsonObject address = result.getAsJsonObject();
972  if (address == null) {
973  continue;
974  }
975 
976  JsonElement nameEl = address.get("name"); //NON-NLS
977  String name = (nameEl != null) ? nameEl.getAsString() : "";
978 
979  JsonElement emailEl = address.get("email"); //NON-NLS
980  String email = (emailEl != null) ? emailEl.getAsString() : "";
981 
982  JsonElement telEl = address.get("tel"); //NON-NLS
983  String tel = (telEl != null) ? telEl.getAsString() : "";
984  JsonElement telCountryCodeEl = address.get("tel-country-code"); //NON-NLS
985  String telCountryCode = (telCountryCodeEl != null) ? telCountryCodeEl.getAsString() : "";
986  JsonElement telNationalEl = address.get("tel-national"); //NON-NLS
987  String telNational = (telNationalEl != null) ? telNationalEl.getAsString() : "";
988 
989  String phoneNumber = makeTelNumber(tel, telCountryCode, telNational);
990 
991  JsonElement createdEl = address.get("timeCreated"); //NON-NLS
992  Long datetimeCreated = (createdEl != null) ? createdEl.getAsLong()/1000 : Long.valueOf(0);
993  JsonElement lastusedEl = address.get("timeLastUsed"); //NON-NLS
994  Long datetimeLastUsed = (lastusedEl != null) ? lastusedEl.getAsLong()/1000 : Long.valueOf(0);
995  JsonElement timesUsedEl = address.get("timesUsed"); //NON-NLS
996  Integer timesUsed = (timesUsedEl != null) ? timesUsedEl.getAsShort() : Integer.valueOf(0);
997 
998  JsonElement addressLine1El = address.get("address-line1"); //NON-NLS
999  String addressLine1 = (addressLine1El != null) ? addressLine1El.getAsString() : "";
1000  JsonElement addressLine2El = address.get("address-line2"); //NON-NLS
1001  String addressLine2 = (addressLine2El != null) ? addressLine2El.getAsString() : "";
1002  JsonElement addressLine3El = address.get("address-line3"); //NON-NLS
1003  String addressLine3 = (addressLine3El != null) ? addressLine3El.getAsString() : "";
1004 
1005  JsonElement postalCodeEl = address.get("postal-code"); //NON-NLS
1006  String postalCode = (postalCodeEl != null) ? postalCodeEl.getAsString() : "";
1007  JsonElement countryEl = address.get("country"); //NON-NLS
1008  String country = (countryEl != null) ? countryEl.getAsString() : "";
1009 
1010  String mailingAddress = makeFullAddress(addressLine1, addressLine2, addressLine3, postalCode, country );
1011 
1012  try {
1013  helper.addWebFormAddress(name, email, phoneNumber,
1014  mailingAddress, datetimeCreated, datetimeLastUsed, timesUsed);
1015  } catch (TskCoreException | Blackboard.BlackboardException ex) {
1016  logger.log(Level.SEVERE, "Error while trying to insert Firefox Autofill profile artifact{0}", ex); //NON-NLS
1017  this.addErrorMessage(
1018  NbBundle.getMessage(this.getClass(), "Firefox.getAutofillProfiles.errMsg.errAnalyzingFile4",
1019  this.getName(), profileFile.getName()));
1020  }
1021  }
1022  dbFile.delete();
1023  }
1024  }
1025 
1034  private String extractDomain(String url) {
1035  if (url == null || url.isEmpty()) {
1036  return url;
1037  }
1038 
1039  if (url.toLowerCase().startsWith(PLACE_URL_PREFIX)) {
1040  /*
1041  * Ignore URLs that begin with the matched text.
1042  */
1043  return null;
1044  }
1045 
1046  return NetworkUtils.extractDomain(url);
1047  }
1048 
1049 
1059  private String makeTelNumber(String tel, String telCountryCode, String telNational) {
1060 
1061  if (tel != null && !tel.isEmpty()) {
1062  return tel;
1063  }
1064 
1065  if ((telCountryCode != null && !telCountryCode.isEmpty()) &&
1066  (telNational != null && !telNational.isEmpty())) {
1067  return telCountryCode + telNational;
1068  }
1069 
1070  return "";
1071  }
1072 
1084  private String makeFullAddress(String addressLine1, String addressLine2, String addressLine3, String postalCode, String country ) {
1085  String fullAddress = "";
1086  fullAddress = appendAddressField(fullAddress, addressLine1 );
1087  fullAddress = appendAddressField(fullAddress, addressLine2 );
1088  fullAddress = appendAddressField(fullAddress, addressLine3 );
1089  fullAddress = appendAddressField(fullAddress, postalCode );
1090  fullAddress = appendAddressField(fullAddress, country );
1091 
1092  return fullAddress;
1093  }
1094 
1103  private String appendAddressField(String address, String addressfield) {
1104 
1105  String updatedAddress = address;
1106  if (addressfield != null && !addressfield.isEmpty()) {
1107  if (!updatedAddress.isEmpty()) {
1108  updatedAddress += ", ";
1109  }
1110  updatedAddress += addressfield;
1111  }
1112 
1113  return updatedAddress;
1114  }
1115 
1116 }

Copyright © 2012-2021 Basis Technology. Generated on: Thu Sep 30 2021
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.