Autopsy  4.9.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-2018 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 java.io.File;
26 import java.io.IOException;
27 import java.io.UnsupportedEncodingException;
28 import java.net.URLDecoder;
29 import java.util.ArrayList;
30 import java.util.Collection;
31 import java.util.HashMap;
32 import java.util.List;
33 import java.util.logging.Level;
34 
35 import org.openide.util.NbBundle;
43 import org.sleuthkit.datamodel.AbstractFile;
44 import org.sleuthkit.datamodel.BlackboardArtifact;
45 import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
46 import org.sleuthkit.datamodel.BlackboardAttribute;
47 import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
48 import org.sleuthkit.datamodel.Content;
49 import org.sleuthkit.datamodel.ReadContentInputStream.ReadContentInputStreamException;
50 import org.sleuthkit.datamodel.TskCoreException;
51 
55 class Firefox extends Extract {
56 
57  private static final Logger logger = Logger.getLogger(Firefox.class.getName());
58  private static final String PLACE_URL_PREFIX = "place:";
59  private static final String HISTORY_QUERY = "SELECT moz_historyvisits.id,url,title,visit_count,(visit_date/1000000) AS visit_date,from_visit,(SELECT url FROM moz_places WHERE id=moz_historyvisits.from_visit) as ref FROM moz_places, moz_historyvisits WHERE moz_places.id = moz_historyvisits.place_id AND hidden = 0"; //NON-NLS
60  private static final String COOKIE_QUERY = "SELECT name,value,host,expiry,(lastAccessed/1000000) AS lastAccessed,(creationTime/1000000) AS creationTime FROM moz_cookies"; //NON-NLS
61  private static final String COOKIE_QUERY_V3 = "SELECT name,value,host,expiry,(lastAccessed/1000000) AS lastAccessed FROM moz_cookies"; //NON-NLS
62  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
63  private static final String DOWNLOAD_QUERY = "SELECT target, source,(startTime/1000000) AS startTime, maxBytes FROM moz_downloads"; //NON-NLS
64  private static final String DOWNLOAD_QUERY_V24 = "SELECT url, content AS target, (lastModified/1000000) AS lastModified FROM moz_places, moz_annos WHERE moz_places.id = moz_annos.place_id AND moz_annos.anno_attribute_id = 3"; //NON-NLS
65  private final IngestServices services = IngestServices.getInstance();
66  private Content dataSource;
67  private IngestJobContext context;
68 
69  Firefox() {
70  moduleName = NbBundle.getMessage(Firefox.class, "Firefox.moduleName");
71  }
72 
73  @Override
74  public void process(Content dataSource, IngestJobContext context) {
75  this.dataSource = dataSource;
76  this.context = context;
77  dataFound = false;
78  this.getHistory();
79  this.getBookmark();
80  this.getDownload();
81  this.getCookie();
82  }
83 
84  private void getHistory() {
85  FileManager fileManager = currentCase.getServices().getFileManager();
86  List<AbstractFile> historyFiles;
87  try {
88  historyFiles = fileManager.findFiles(dataSource, "places.sqlite", "Firefox"); //NON-NLS
89  } catch (TskCoreException ex) {
90  String msg = NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errFetchingFiles");
91  logger.log(Level.WARNING, msg);
92  this.addErrorMessage(this.getName() + ": " + msg);
93  return;
94  }
95 
96  if (historyFiles.isEmpty()) {
97  String msg = NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.noFilesFound");
98  logger.log(Level.INFO, msg);
99  return;
100  }
101 
102  dataFound = true;
103  Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
104  int j = 0;
105  for (AbstractFile historyFile : historyFiles) {
106  if (historyFile.getSize() == 0) {
107  continue;
108  }
109 
110  String fileName = historyFile.getName();
111  String temps = RAImageIngestModule.getRATempPath(currentCase, "firefox") + File.separator + fileName + j + ".db"; //NON-NLS
112  try {
113  ContentUtils.writeToFile(historyFile, new File(temps), context::dataSourceIngestIsCancelled);
114  } catch (ReadContentInputStreamException ex) {
115  logger.log(Level.WARNING, String.format("Error reading Firefox web history artifacts file '%s' (id=%d).",
116  fileName, historyFile.getId()), ex); //NON-NLS
117  this.addErrorMessage(
118  NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errAnalyzeFile", this.getName(),
119  fileName));
120  continue;
121  } catch (IOException ex) {
122  logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Firefox web history artifacts file '%s' (id=%d).",
123  temps, fileName, historyFile.getId()), ex); //NON-NLS
124  this.addErrorMessage(
125  NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errAnalyzeFile", this.getName(),
126  fileName));
127  continue;
128  }
129  File dbFile = new File(temps);
130  if (context.dataSourceIngestIsCancelled()) {
131  dbFile.delete();
132  break;
133  }
134  List<HashMap<String, Object>> tempList = this.dbConnect(temps, HISTORY_QUERY);
135  logger.log(Level.INFO, "{0} - Now getting history from {1} with {2} artifacts identified.", new Object[]{moduleName, temps, tempList.size()}); //NON-NLS
136  for (HashMap<String, Object> result : tempList) {
137  String url = result.get("url").toString();
138 
139  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
140  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
141  NbBundle.getMessage(this.getClass(),
142  "Firefox.parentModuleName.noSpace"),
143  ((url != null) ? url : ""))); //NON-NLS
144  //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", ((result.get("url").toString() != null) ? EscapeUtil.decodeURL(result.get("url").toString()) : "")));
145  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
146  NbBundle.getMessage(this.getClass(),
147  "Firefox.parentModuleName.noSpace"),
148  (Long.valueOf(result.get("visit_date").toString())))); //NON-NLS
149  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REFERRER,
150  NbBundle.getMessage(this.getClass(),
151  "Firefox.parentModuleName.noSpace"),
152  ((result.get("ref").toString() != null) ? result.get("ref").toString() : ""))); //NON-NLS
153  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TITLE,
154  NbBundle.getMessage(this.getClass(),
155  "Firefox.parentModuleName.noSpace"),
156  ((result.get("title").toString() != null) ? result.get("title").toString() : ""))); //NON-NLS
157  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
158  NbBundle.getMessage(this.getClass(),
159  "Firefox.parentModuleName.noSpace"),
160  NbBundle.getMessage(this.getClass(), "Firefox.moduleName")));
161  String domain = extractDomain(url);
162  if (domain != null && domain.isEmpty() == false) {
163  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
164  NbBundle.getMessage(this.getClass(),
165  "Firefox.parentModuleName.noSpace"), domain)); //NON-NLS
166 
167  }
168  BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY, historyFile, bbattributes);
169  if (bbart != null) {
170  bbartifacts.add(bbart);
171  }
172  }
173  ++j;
174  dbFile.delete();
175  }
176 
177  services.fireModuleDataEvent(new ModuleDataEvent(
178  NbBundle.getMessage(this.getClass(), "Firefox.parentModuleName"),
179  BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY, bbartifacts));
180  }
181 
185  private void getBookmark() {
186 
187  FileManager fileManager = currentCase.getServices().getFileManager();
188  List<AbstractFile> bookmarkFiles;
189  try {
190  bookmarkFiles = fileManager.findFiles(dataSource, "places.sqlite", "Firefox"); //NON-NLS
191  } catch (TskCoreException ex) {
192  String msg = NbBundle.getMessage(this.getClass(), "Firefox.getBookmark.errMsg.errFetchFiles");
193  logger.log(Level.WARNING, msg);
194  this.addErrorMessage(this.getName() + ": " + msg);
195  return;
196  }
197 
198  if (bookmarkFiles.isEmpty()) {
199  logger.log(Level.INFO, "Didn't find any firefox bookmark files."); //NON-NLS
200  return;
201  }
202 
203  dataFound = true;
204  Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
205  int j = 0;
206  for (AbstractFile bookmarkFile : bookmarkFiles) {
207  if (bookmarkFile.getSize() == 0) {
208  continue;
209  }
210  String fileName = bookmarkFile.getName();
211  String temps = RAImageIngestModule.getRATempPath(currentCase, "firefox") + File.separator + fileName + j + ".db"; //NON-NLS
212  try {
213  ContentUtils.writeToFile(bookmarkFile, new File(temps), context::dataSourceIngestIsCancelled);
214  } catch (ReadContentInputStreamException ex) {
215  logger.log(Level.WARNING, String.format("Error reading Firefox bookmark artifacts file '%s' (id=%d).",
216  fileName, bookmarkFile.getId()), ex); //NON-NLS
217  this.addErrorMessage(
218  NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errAnalyzeFile", this.getName(),
219  fileName));
220  continue;
221  } catch (IOException ex) {
222  logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Firefox bookmark artifacts file '%s' (id=%d).",
223  temps, fileName, bookmarkFile.getId()), ex); //NON-NLS
224  this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Firefox.getBookmark.errMsg.errAnalyzeFile",
225  this.getName(), fileName));
226  continue;
227  }
228  File dbFile = new File(temps);
229  if (context.dataSourceIngestIsCancelled()) {
230  dbFile.delete();
231  break;
232  }
233  List<HashMap<String, Object>> tempList = this.dbConnect(temps, BOOKMARK_QUERY);
234  logger.log(Level.INFO, "{0} - Now getting bookmarks from {1} with {2} artifacts identified.", new Object[]{moduleName, temps, tempList.size()}); //NON-NLS
235  for (HashMap<String, Object> result : tempList) {
236  String url = result.get("url").toString();
237 
238  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
239  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
240  NbBundle.getMessage(this.getClass(),
241  "Firefox.parentModuleName.noSpace"),
242  ((url != null) ? url : ""))); //NON-NLS
243  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TITLE,
244  NbBundle.getMessage(this.getClass(),
245  "Firefox.parentModuleName.noSpace"),
246  ((result.get("title").toString() != null) ? result.get("title").toString() : ""))); //NON-NLS
247  if (Long.valueOf(result.get("dateAdded").toString()) > 0) { //NON-NLS
248  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
249  NbBundle.getMessage(this.getClass(),
250  "Firefox.parentModuleName.noSpace"),
251  (Long.valueOf(result.get("dateAdded").toString())))); //NON-NLS
252  }
253  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
254  NbBundle.getMessage(this.getClass(),
255  "Firefox.parentModuleName.noSpace"),
256  NbBundle.getMessage(this.getClass(), "Firefox.moduleName")));
257  String domain = extractDomain(url);
258  if (domain != null && domain.isEmpty() == false) {
259  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
260  NbBundle.getMessage(this.getClass(),
261  "Firefox.parentModuleName.noSpace"),
262  domain)); //NON-NLS
263  }
264 
265  BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_BOOKMARK, bookmarkFile, bbattributes);
266  if (bbart != null) {
267  bbartifacts.add(bbart);
268  }
269  }
270  ++j;
271  dbFile.delete();
272  }
273 
274  services.fireModuleDataEvent(new ModuleDataEvent(
275  NbBundle.getMessage(this.getClass(), "Firefox.parentModuleName"),
276  BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK, bbartifacts));
277  }
278 
282  private void getCookie() {
283  FileManager fileManager = currentCase.getServices().getFileManager();
284  List<AbstractFile> cookiesFiles;
285  try {
286  cookiesFiles = fileManager.findFiles(dataSource, "cookies.sqlite", "Firefox"); //NON-NLS
287  } catch (TskCoreException ex) {
288  String msg = NbBundle.getMessage(this.getClass(), "Firefox.getCookie.errMsg.errFetchFile");
289  logger.log(Level.WARNING, msg);
290  this.addErrorMessage(this.getName() + ": " + msg);
291  return;
292  }
293 
294  if (cookiesFiles.isEmpty()) {
295  logger.log(Level.INFO, "Didn't find any Firefox cookie files."); //NON-NLS
296  return;
297  }
298 
299  dataFound = true;
300  Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
301  int j = 0;
302  for (AbstractFile cookiesFile : cookiesFiles) {
303  if (cookiesFile.getSize() == 0) {
304  continue;
305  }
306  String fileName = cookiesFile.getName();
307  String temps = RAImageIngestModule.getRATempPath(currentCase, "firefox") + File.separator + fileName + j + ".db"; //NON-NLS
308  try {
309  ContentUtils.writeToFile(cookiesFile, new File(temps), context::dataSourceIngestIsCancelled);
310  } catch (ReadContentInputStreamException ex) {
311  logger.log(Level.WARNING, String.format("Error reading Firefox cookie artifacts file '%s' (id=%d).",
312  fileName, cookiesFile.getId()), ex); //NON-NLS
313  this.addErrorMessage(
314  NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errAnalyzeFile", this.getName(),
315  fileName));
316  continue;
317  } catch (IOException ex) {
318  logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Firefox cookie artifacts file '%s' (id=%d).",
319  temps, fileName, cookiesFile.getId()), ex); //NON-NLS
320  this.addErrorMessage(
321  NbBundle.getMessage(this.getClass(), "Firefox.getCookie.errMsg.errAnalyzeFile", this.getName(),
322  fileName));
323  continue;
324  }
325  File dbFile = new File(temps);
326  if (context.dataSourceIngestIsCancelled()) {
327  dbFile.delete();
328  break;
329  }
330  boolean checkColumn = Util.checkColumn("creationTime", "moz_cookies", temps); //NON-NLS
331  String query;
332  if (checkColumn) {
333  query = COOKIE_QUERY;
334  } else {
335  query = COOKIE_QUERY_V3;
336  }
337 
338  List<HashMap<String, Object>> tempList = this.dbConnect(temps, query);
339  logger.log(Level.INFO, "{0} - Now getting cookies from {1} with {2} artifacts identified.", new Object[]{moduleName, temps, tempList.size()}); //NON-NLS
340  for (HashMap<String, Object> result : tempList) {
341  String host = result.get("host").toString();
342 
343  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
344  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
345  NbBundle.getMessage(this.getClass(),
346  "Firefox.parentModuleName.noSpace"),
347  ((host != null) ? host : ""))); //NON-NLS
348  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME,
349  NbBundle.getMessage(this.getClass(),
350  "Firefox.parentModuleName.noSpace"),
351  (Long.valueOf(result.get("lastAccessed").toString())))); //NON-NLS
352  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME,
353  NbBundle.getMessage(this.getClass(),
354  "Firefox.parentModuleName.noSpace"),
355  ((result.get("name").toString() != null) ? result.get("name").toString() : ""))); //NON-NLS
356  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE,
357  NbBundle.getMessage(this.getClass(),
358  "Firefox.parentModuleName.noSpace"),
359  ((result.get("value").toString() != null) ? result.get("value").toString() : ""))); //NON-NLS
360  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
361  NbBundle.getMessage(this.getClass(),
362  "Firefox.parentModuleName.noSpace"),
363  NbBundle.getMessage(this.getClass(), "Firefox.moduleName")));
364 
365  if (checkColumn == true) {
366  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
367  NbBundle.getMessage(this.getClass(),
368  "Firefox.parentModuleName.noSpace"),
369  (Long.valueOf(result.get("creationTime").toString())))); //NON-NLS
370  }
371  String domain = extractDomain(host);
372  if (domain != null && domain.isEmpty() == false) {
373  domain = domain.replaceFirst("^\\.+(?!$)", "");
374  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
375  NbBundle.getMessage(this.getClass(),
376  "Firefox.parentModuleName.noSpace"), domain));
377  }
378 
379  BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_COOKIE, cookiesFile, bbattributes);
380  if (bbart != null) {
381  bbartifacts.add(bbart);
382  }
383  }
384  ++j;
385  dbFile.delete();
386  }
387 
388  services.fireModuleDataEvent(new ModuleDataEvent(
389  NbBundle.getMessage(this.getClass(), "Firefox.parentModuleName"),
390  BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE, bbartifacts));
391  }
392 
396  private void getDownload() {
397  getDownloadPreVersion24();
398  getDownloadVersion24();
399  }
400 
406  private void getDownloadPreVersion24() {
407 
408  FileManager fileManager = currentCase.getServices().getFileManager();
409  List<AbstractFile> downloadsFiles;
410  try {
411  downloadsFiles = fileManager.findFiles(dataSource, "downloads.sqlite", "Firefox"); //NON-NLS
412  } catch (TskCoreException ex) {
413  String msg = NbBundle.getMessage(this.getClass(), "Firefox.getDlPre24.errMsg.errFetchFiles");
414  logger.log(Level.WARNING, msg);
415  this.addErrorMessage(this.getName() + ": " + msg);
416  return;
417  }
418 
419  if (downloadsFiles.isEmpty()) {
420  logger.log(Level.INFO, "Didn't find any pre-version-24.0 Firefox download files."); //NON-NLS
421  return;
422  }
423 
424  dataFound = true;
425  Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
426  int j = 0;
427  for (AbstractFile downloadsFile : downloadsFiles) {
428  if (downloadsFile.getSize() == 0) {
429  continue;
430  }
431  String fileName = downloadsFile.getName();
432  String temps = RAImageIngestModule.getRATempPath(currentCase, "firefox") + File.separator + fileName + j + ".db"; //NON-NLS
433  int errors = 0;
434  try {
435  ContentUtils.writeToFile(downloadsFile, new File(temps), context::dataSourceIngestIsCancelled);
436  } catch (ReadContentInputStreamException ex) {
437  logger.log(Level.WARNING, String.format("Error reading Firefox download artifacts file '%s' (id=%d).",
438  fileName, downloadsFile.getId()), ex); //NON-NLS
439  this.addErrorMessage(
440  NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errAnalyzeFile", this.getName(),
441  fileName));
442  continue;
443  } catch (IOException ex) {
444  logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Firefox download artifacts file '%s' (id=%d).",
445  temps, fileName, downloadsFile.getId()), ex); //NON-NLS
446  this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Firefox.getDlPre24.errMsg.errAnalyzeFiles",
447  this.getName(), fileName));
448  continue;
449  }
450  File dbFile = new File(temps);
451  if (context.dataSourceIngestIsCancelled()) {
452  dbFile.delete();
453  break;
454  }
455 
456  List<HashMap<String, Object>> tempList = this.dbConnect(temps, DOWNLOAD_QUERY);
457  logger.log(Level.INFO, "{0}- Now getting downloads from {1} with {2} artifacts identified.", new Object[]{moduleName, temps, tempList.size()}); //NON-NLS
458  for (HashMap<String, Object> result : tempList) {
459  String source = result.get("source").toString();
460 
461  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
462 
463  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
464  NbBundle.getMessage(this.getClass(),
465  "Firefox.parentModuleName.noSpace"),
466  source)); //NON-NLS
467  //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", ((result.get("source").toString() != null) ? EscapeUtil.decodeURL(result.get("source").toString()) : "")));
468  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
469  NbBundle.getMessage(this.getClass(),
470  "Firefox.parentModuleName.noSpace"),
471  (Long.valueOf(result.get("startTime").toString())))); //NON-NLS
472 
473  String target = result.get("target").toString(); //NON-NLS
474 
475  if (target != null) {
476  try {
477  String decodedTarget = URLDecoder.decode(target.replaceAll("file:///", ""), "UTF-8"); //NON-NLS
478  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
479  NbBundle.getMessage(this.getClass(),
480  "Firefox.parentModuleName.noSpace"),
481  decodedTarget));
482  long pathID = Util.findID(dataSource, decodedTarget);
483  if (pathID != -1) {
484  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH_ID,
485  NbBundle.getMessage(this.getClass(),
486  "Firefox.parentModuleName.noSpace"),
487  pathID));
488  }
489  } catch (UnsupportedEncodingException ex) {
490  logger.log(Level.SEVERE, "Error decoding Firefox download URL in " + temps, ex); //NON-NLS
491  errors++;
492  }
493  }
494 
495  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
496  NbBundle.getMessage(this.getClass(),
497  "Firefox.parentModuleName.noSpace"),
498  NbBundle.getMessage(this.getClass(), "Firefox.moduleName")));
499  String domain = extractDomain(source);
500  if (domain != null && domain.isEmpty() == false) {
501  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
502  NbBundle.getMessage(this.getClass(),
503  "Firefox.parentModuleName.noSpace"),
504  domain)); //NON-NLS
505  }
506 
507  BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, downloadsFile, bbattributes);
508  if (bbart != null) {
509  bbartifacts.add(bbart);
510  }
511  }
512  if (errors > 0) {
513  this.addErrorMessage(
514  NbBundle.getMessage(this.getClass(), "Firefox.getDlPre24.errMsg.errParsingArtifacts",
515  this.getName(), errors));
516  }
517  j++;
518  dbFile.delete();
519  break;
520  }
521 
522  services.fireModuleDataEvent(new ModuleDataEvent(
523  NbBundle.getMessage(this.getClass(), "Firefox.parentModuleName"),
524  BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, bbartifacts));
525  }
526 
532  private void getDownloadVersion24() {
533  FileManager fileManager = currentCase.getServices().getFileManager();
534  List<AbstractFile> downloadsFiles;
535  try {
536  downloadsFiles = fileManager.findFiles(dataSource, "places.sqlite", "Firefox"); //NON-NLS
537  } catch (TskCoreException ex) {
538  String msg = NbBundle.getMessage(this.getClass(), "Firefox.getDlV24.errMsg.errFetchFiles");
539  logger.log(Level.WARNING, msg);
540  this.addErrorMessage(this.getName() + ": " + msg);
541  return;
542  }
543 
544  if (downloadsFiles.isEmpty()) {
545  logger.log(Level.INFO, "Didn't find any version-24.0 Firefox download files."); //NON-NLS
546  return;
547  }
548 
549  dataFound = true;
550  Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
551  int j = 0;
552  for (AbstractFile downloadsFile : downloadsFiles) {
553  if (downloadsFile.getSize() == 0) {
554  continue;
555  }
556  String fileName = downloadsFile.getName();
557  String temps = RAImageIngestModule.getRATempPath(currentCase, "firefox") + File.separator + fileName + "-downloads" + j + ".db"; //NON-NLS
558  int errors = 0;
559  try {
560  ContentUtils.writeToFile(downloadsFile, new File(temps), context::dataSourceIngestIsCancelled);
561  } catch (ReadContentInputStreamException ex) {
562  logger.log(Level.WARNING, String.format("Error reading Firefox download artifacts file '%s' (id=%d).",
563  fileName, downloadsFile.getId()), ex); //NON-NLS
564  this.addErrorMessage(
565  NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errAnalyzeFile", this.getName(),
566  fileName));
567  continue;
568  } catch (IOException ex) {
569  logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Firefox download artifacts file '%s' (id=%d).",
570  temps, fileName, downloadsFile.getId()), ex); //NON-NLS
571  this.addErrorMessage(
572  NbBundle.getMessage(this.getClass(), "Firefox.getDlV24.errMsg.errAnalyzeFile", this.getName(),
573  fileName));
574  continue;
575  }
576  File dbFile = new File(temps);
577  if (context.dataSourceIngestIsCancelled()) {
578  dbFile.delete();
579  break;
580  }
581 
582  List<HashMap<String, Object>> tempList = this.dbConnect(temps, DOWNLOAD_QUERY_V24);
583 
584  logger.log(Level.INFO, "{0} - Now getting downloads from {1} with {2} artifacts identified.", new Object[]{moduleName, temps, tempList.size()}); //NON-NLS
585  for (HashMap<String, Object> result : tempList) {
586  String url = result.get("url").toString();
587 
588  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
589 
590  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
591  NbBundle.getMessage(this.getClass(),
592  "Firefox.parentModuleName.noSpace"),
593  url)); //NON-NLS
594  //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", ((result.get("source").toString() != null) ? EscapeUtil.decodeURL(result.get("source").toString()) : "")));
595  //TODO Revisit usage of deprecated constructor as per TSK-583
596  //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LAST_ACCESSED.getTypeID(), "RecentActivity", "Last Visited", (Long.valueOf(result.get("startTime").toString()))));
597 
598  String target = result.get("target").toString(); //NON-NLS
599  if (target != null) {
600  try {
601  String decodedTarget = URLDecoder.decode(target.replaceAll("file:///", ""), "UTF-8"); //NON-NLS
602  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
603  NbBundle.getMessage(this.getClass(),
604  "Firefox.parentModuleName.noSpace"),
605  decodedTarget));
606  long pathID = Util.findID(dataSource, decodedTarget);
607  if (pathID != -1) {
608  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH_ID,
609  NbBundle.getMessage(this.getClass(),
610  "Firefox.parentModuleName.noSpace"),
611  pathID));
612  }
613  } catch (UnsupportedEncodingException ex) {
614  logger.log(Level.SEVERE, "Error decoding Firefox download URL in " + temps, ex); //NON-NLS
615  errors++;
616  }
617  }
618  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
619  NbBundle.getMessage(this.getClass(),
620  "Firefox.parentModuleName.noSpace"),
621  Long.valueOf(result.get("lastModified").toString()))); //NON-NLS
622  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
623  NbBundle.getMessage(this.getClass(),
624  "Firefox.parentModuleName.noSpace"),
625  NbBundle.getMessage(this.getClass(), "Firefox.moduleName")));
626  String domain = extractDomain(url);
627  if (domain != null && domain.isEmpty() == false) {
628  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
629  NbBundle.getMessage(this.getClass(),
630  "Firefox.parentModuleName.noSpace"),
631  domain)); //NON-NLS
632  }
633 
634  BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, downloadsFile, bbattributes);
635  if (bbart != null) {
636  bbartifacts.add(bbart);
637  }
638  }
639  if (errors > 0) {
640  this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Firefox.getDlV24.errMsg.errParsingArtifacts",
641  this.getName(), errors));
642  }
643  j++;
644  dbFile.delete();
645  break;
646  }
647 
648  services.fireModuleDataEvent(new ModuleDataEvent(
649  NbBundle.getMessage(this.getClass(), "Firefox.parentModuleName"),
650  BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, bbartifacts));
651  }
652 
661  private String extractDomain(String url) {
662  if (url == null || url.isEmpty()) {
663  return url;
664  }
665 
666  if (url.toLowerCase().startsWith(PLACE_URL_PREFIX)) {
667  /*
668  * Ignore URLs that begin with the matched text.
669  */
670  return null;
671  }
672 
673  return NetworkUtils.extractDomain(url);
674  }
675 }

Copyright © 2012-2018 Basis Technology. Generated on: Tue Dec 18 2018
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.