23 package org.sleuthkit.autopsy.recentactivity;
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;
35 import org.openide.util.NbBundle;
53 class Firefox
extends Extract {
55 private static final Logger logger = Logger.getLogger(Firefox.class.getName());
56 private static final String historyQuery =
"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";
57 private static final String cookieQuery =
"SELECT name,value,host,expiry,(lastAccessed/1000000) as lastAccessed,(creationTime/1000000) as creationTime FROM moz_cookies";
58 private static final String cookieQueryV3 =
"SELECT name,value,host,expiry,(lastAccessed/1000000) as lastAccessed FROM moz_cookies";
59 private static final String bookmarkQuery =
"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";
60 private static final String downloadQuery =
"SELECT target, source,(startTime/1000000) as startTime, maxBytes FROM moz_downloads";
61 private static final String downloadQueryVersion24 =
"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";
62 private final IngestServices services = IngestServices.getInstance();
63 private Content dataSource;
64 private IngestJobContext context;
67 moduleName = NbBundle.getMessage(Firefox.class,
"Firefox.moduleName");
71 public void process(Content dataSource, IngestJobContext context) {
72 this.dataSource = dataSource;
73 this.context = context;
81 private void getHistory() {
82 FileManager fileManager = currentCase.getServices().getFileManager();
83 List<AbstractFile> historyFiles;
85 historyFiles = fileManager.findFiles(dataSource,
"places.sqlite",
"Firefox");
86 }
catch (TskCoreException ex) {
87 String msg = NbBundle.getMessage(this.getClass(),
"Firefox.getHistory.errMsg.errFetchingFiles");
88 logger.log(Level.WARNING, msg);
89 this.addErrorMessage(this.getName() +
": " + msg);
93 if (historyFiles.isEmpty()) {
94 String msg = NbBundle.getMessage(this.getClass(),
"Firefox.getHistory.errMsg.noFilesFound");
95 logger.log(Level.INFO, msg);
102 for (AbstractFile historyFile : historyFiles) {
103 if (historyFile.getSize() == 0) {
107 String fileName = historyFile.getName();
108 String temps = RAImageIngestModule.getRATempPath(currentCase,
"firefox") + File.separator + fileName + j +
".db";
110 ContentUtils.writeToFile(historyFile,
new File(temps));
111 }
catch (IOException ex) {
112 logger.log(Level.SEVERE,
"Error writing the sqlite db for firefox web history artifacts.{0}", ex);
113 this.addErrorMessage(
114 NbBundle.getMessage(
this.getClass(),
"Firefox.getHistory.errMsg.errAnalyzeFile", this.getName(),
118 File dbFile =
new File(temps);
119 if (context.dataSourceIngestIsCancelled()) {
123 List<HashMap<String, Object>> tempList = this.dbConnect(temps, historyQuery);
124 logger.log(Level.INFO,
"{0} - Now getting history from {1} with {2} artifacts identified.",
new Object[]{moduleName, temps, tempList.size()});
125 for (HashMap<String, Object> result : tempList) {
126 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
127 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(),
128 NbBundle.getMessage(this.getClass(),
129 "Firefox.parentModuleName.noSpace"),
130 ((result.get(
"url").toString() != null) ? result.get(
"url").toString() :
"")));
132 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID(),
133 NbBundle.getMessage(this.getClass(),
134 "Firefox.parentModuleName.noSpace"),
135 (Long.valueOf(result.get(
"visit_date").toString()))));
136 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REFERRER.getTypeID(),
137 NbBundle.getMessage(this.getClass(),
138 "Firefox.parentModuleName.noSpace"),
139 ((result.get(
"ref").toString() != null) ? result.get(
"ref").toString() :
"")));
140 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TITLE.getTypeID(),
141 NbBundle.getMessage(this.getClass(),
142 "Firefox.parentModuleName.noSpace"),
143 ((result.get(
"title").toString() != null) ? result.get(
"title").toString() :
"")));
144 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(),
145 NbBundle.getMessage(this.getClass(),
146 "Firefox.parentModuleName.noSpace"),
147 NbBundle.getMessage(this.getClass(),
"Firefox.moduleName")));
148 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID(),
149 NbBundle.getMessage(this.getClass(),
150 "Firefox.parentModuleName.noSpace"), (Util.extractDomain((result.get(
"url").toString() != null) ? result.get(
"url").toString() :
""))));
151 this.addArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY, historyFile, bbattributes);
157 services.fireModuleDataEvent(
new ModuleDataEvent(
158 NbBundle.getMessage(
this.getClass(),
"Firefox.parentModuleName"), BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY));
164 private void getBookmark() {
166 FileManager fileManager = currentCase.getServices().getFileManager();
167 List<AbstractFile> bookmarkFiles;
169 bookmarkFiles = fileManager.findFiles(dataSource,
"places.sqlite",
"Firefox");
170 }
catch (TskCoreException ex) {
171 String msg = NbBundle.getMessage(this.getClass(),
"Firefox.getBookmark.errMsg.errFetchFiles");
172 logger.log(Level.WARNING, msg);
173 this.addErrorMessage(this.getName() +
": " + msg);
177 if (bookmarkFiles.isEmpty()) {
178 logger.log(Level.INFO,
"Didn't find any firefox bookmark files.");
185 for (AbstractFile bookmarkFile : bookmarkFiles) {
186 if (bookmarkFile.getSize() == 0) {
189 String fileName = bookmarkFile.getName();
190 String temps = RAImageIngestModule.getRATempPath(currentCase,
"firefox") + File.separator + fileName + j +
".db";
192 ContentUtils.writeToFile(bookmarkFile,
new File(temps));
193 }
catch (IOException ex) {
194 logger.log(Level.SEVERE,
"Error writing the sqlite db for firefox bookmark artifacts.{0}", ex);
195 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Firefox.getBookmark.errMsg.errAnalyzeFile",
196 this.getName(), fileName));
199 File dbFile =
new File(temps);
200 if (context.dataSourceIngestIsCancelled()) {
204 List<HashMap<String, Object>> tempList = this.dbConnect(temps, bookmarkQuery);
205 logger.log(Level.INFO,
"{0} - Now getting bookmarks from {1} with {2} artifacts identified.",
new Object[]{moduleName, temps, tempList.size()});
206 for (HashMap<String, Object> result : tempList) {
208 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
209 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(),
210 NbBundle.getMessage(this.getClass(),
211 "Firefox.parentModuleName.noSpace"),
212 ((result.get(
"url").toString() != null) ? result.get(
"url").toString() :
"")));
213 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TITLE.getTypeID(),
214 NbBundle.getMessage(this.getClass(),
215 "Firefox.parentModuleName.noSpace"),
216 ((result.get(
"title").toString() != null) ? result.get(
"title").toString() :
"")));
217 if (Long.valueOf(result.get(
"dateAdded").toString()) > 0) {
218 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED.getTypeID(),
219 NbBundle.getMessage(this.getClass(),
220 "Firefox.parentModuleName.noSpace"),
221 (Long.valueOf(result.get(
"dateAdded").toString()))));
223 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(),
224 NbBundle.getMessage(this.getClass(),
225 "Firefox.parentModuleName.noSpace"),
226 NbBundle.getMessage(this.getClass(),
"Firefox.moduleName")));
227 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID(),
228 NbBundle.getMessage(this.getClass(),
229 "Firefox.parentModuleName.noSpace"),
230 (Util.extractDomain((result.get(
"url").toString() != null) ? result.get(
"url").toString() :
""))));
231 this.addArtifact(ARTIFACT_TYPE.TSK_WEB_BOOKMARK, bookmarkFile, bbattributes);
238 services.fireModuleDataEvent(
new ModuleDataEvent(
239 NbBundle.getMessage(
this.getClass(),
"Firefox.parentModuleName"), BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK));
245 private void getCookie() {
246 FileManager fileManager = currentCase.getServices().getFileManager();
247 List<AbstractFile> cookiesFiles;
249 cookiesFiles = fileManager.findFiles(dataSource,
"cookies.sqlite",
"Firefox");
250 }
catch (TskCoreException ex) {
251 String msg = NbBundle.getMessage(this.getClass(),
"Firefox.getCookie.errMsg.errFetchFile");
252 logger.log(Level.WARNING, msg);
253 this.addErrorMessage(this.getName() +
": " + msg);
257 if (cookiesFiles.isEmpty()) {
258 logger.log(Level.INFO,
"Didn't find any Firefox cookie files.");
264 for (AbstractFile cookiesFile : cookiesFiles) {
265 if (cookiesFile.getSize() == 0) {
268 String fileName = cookiesFile.getName();
269 String temps = RAImageIngestModule.getRATempPath(currentCase,
"firefox") + File.separator + fileName + j +
".db";
271 ContentUtils.writeToFile(cookiesFile,
new File(temps));
272 }
catch (IOException ex) {
273 logger.log(Level.SEVERE,
"Error writing the sqlite db for firefox cookie artifacts.{0}", ex);
274 this.addErrorMessage(
275 NbBundle.getMessage(
this.getClass(),
"Firefox.getCookie.errMsg.errAnalyzeFile", this.getName(),
279 File dbFile =
new File(temps);
280 if (context.dataSourceIngestIsCancelled()) {
284 boolean checkColumn = Util.checkColumn(
"creationTime",
"moz_cookies", temps);
289 query = cookieQueryV3;
292 List<HashMap<String, Object>> tempList = this.dbConnect(temps, query);
293 logger.log(Level.INFO,
"{0} - Now getting cookies from {1} with {2} artifacts identified.",
new Object[]{moduleName, temps, tempList.size()});
294 for (HashMap<String, Object> result : tempList) {
296 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
297 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(),
298 NbBundle.getMessage(this.getClass(),
299 "Firefox.parentModuleName.noSpace"),
300 ((result.get(
"host").toString() != null) ? result.get(
"host").toString() :
"")));
301 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(),
302 NbBundle.getMessage(this.getClass(),
303 "Firefox.parentModuleName.noSpace"),
304 (Long.valueOf(result.get(
"lastAccessed").toString()))));
305 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(),
306 NbBundle.getMessage(this.getClass(),
307 "Firefox.parentModuleName.noSpace"),
308 ((result.get(
"name").toString() != null) ? result.get(
"name").toString() :
"")));
309 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE.getTypeID(),
310 NbBundle.getMessage(this.getClass(),
311 "Firefox.parentModuleName.noSpace"),
312 ((result.get(
"value").toString() != null) ? result.get(
"value").toString() :
"")));
313 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(),
314 NbBundle.getMessage(this.getClass(),
315 "Firefox.parentModuleName.noSpace"),
316 NbBundle.getMessage(this.getClass(),
"Firefox.moduleName")));
318 if (checkColumn ==
true) {
319 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED.getTypeID(),
320 NbBundle.getMessage(this.getClass(),
321 "Firefox.parentModuleName.noSpace"),
322 (Long.valueOf(result.get(
"creationTime").toString()))));
324 String domain = Util.extractDomain(result.get(
"host").toString());
325 domain = domain.replaceFirst(
"^\\.+(?!$)",
"");
326 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID(),
327 NbBundle.getMessage(this.getClass(),
328 "Firefox.parentModuleName.noSpace"), domain));
329 this.addArtifact(ARTIFACT_TYPE.TSK_WEB_COOKIE, cookiesFile, bbattributes);
335 services.fireModuleDataEvent(
new ModuleDataEvent(
336 NbBundle.getMessage(
this.getClass(),
"Firefox.parentModuleName"), BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE));
342 private void getDownload() {
343 getDownloadPreVersion24();
344 getDownloadVersion24();
352 private void getDownloadPreVersion24() {
354 FileManager fileManager = currentCase.getServices().getFileManager();
355 List<AbstractFile> downloadsFiles;
357 downloadsFiles = fileManager.findFiles(dataSource,
"downloads.sqlite",
"Firefox");
358 }
catch (TskCoreException ex) {
359 String msg = NbBundle.getMessage(this.getClass(),
"Firefox.getDlPre24.errMsg.errFetchFiles");
360 logger.log(Level.WARNING, msg);
361 this.addErrorMessage(this.getName() +
": " + msg);
365 if (downloadsFiles.isEmpty()) {
366 logger.log(Level.INFO,
"Didn't find any pre-version-24.0 Firefox download files.");
372 for (AbstractFile downloadsFile : downloadsFiles) {
373 if (downloadsFile.getSize() == 0) {
376 String fileName = downloadsFile.getName();
377 String temps = RAImageIngestModule.getRATempPath(currentCase,
"firefox") + File.separator + fileName + j +
".db";
380 ContentUtils.writeToFile(downloadsFile,
new File(temps));
381 }
catch (IOException ex) {
382 logger.log(Level.SEVERE,
"Error writing the sqlite db for firefox download artifacts.{0}", ex);
383 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Firefox.getDlPre24.errMsg.errAnalyzeFiles",
384 this.getName(), fileName));
387 File dbFile =
new File(temps);
388 if (context.dataSourceIngestIsCancelled()) {
393 List<HashMap<String, Object>> tempList = this.dbConnect(temps, downloadQuery);
394 logger.log(Level.INFO,
"{0}- Now getting downloads from {1} with {2} artifacts identified.",
new Object[]{moduleName, temps, tempList.size()});
395 for (HashMap<String, Object> result : tempList) {
397 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
399 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(),
400 NbBundle.getMessage(this.getClass(),
401 "Firefox.parentModuleName.noSpace"),
402 ((result.get(
"source").toString() != null) ? result.get(
"source").toString() :
"")));
404 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID(),
405 NbBundle.getMessage(this.getClass(),
406 "Firefox.parentModuleName.noSpace"),
407 (Long.valueOf(result.get(
"startTime").toString()))));
409 String target = result.get(
"target").toString();
411 if (target != null) {
413 String decodedTarget = URLDecoder.decode(target.toString().replaceAll(
"file:///",
""),
"UTF-8");
414 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH.getTypeID(),
415 NbBundle.getMessage(this.getClass(),
416 "Firefox.parentModuleName.noSpace"),
418 long pathID = Util.findID(dataSource, decodedTarget);
420 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID(),
421 NbBundle.getMessage(this.getClass(),
422 "Firefox.parentModuleName.noSpace"),
425 }
catch (UnsupportedEncodingException ex) {
426 logger.log(Level.SEVERE,
"Error decoding Firefox download URL in " + temps, ex);
431 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(),
432 NbBundle.getMessage(this.getClass(),
433 "Firefox.parentModuleName.noSpace"),
434 NbBundle.getMessage(this.getClass(),
"Firefox.moduleName")));
435 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID(),
436 NbBundle.getMessage(this.getClass(),
437 "Firefox.parentModuleName.noSpace"),
438 (Util.extractDomain((result.get(
"source").toString() != null) ? result.get(
"source").toString() :
""))));
439 this.addArtifact(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, downloadsFile, bbattributes);
443 this.addErrorMessage(
444 NbBundle.getMessage(
this.getClass(),
"Firefox.getDlPre24.errMsg.errParsingArtifacts",
445 this.getName(), errors));
452 services.fireModuleDataEvent(
new ModuleDataEvent(
453 NbBundle.getMessage(
this.getClass(),
"Firefox.parentModuleName"), BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD));
461 private void getDownloadVersion24() {
462 FileManager fileManager = currentCase.getServices().getFileManager();
463 List<AbstractFile> downloadsFiles;
465 downloadsFiles = fileManager.findFiles(dataSource,
"places.sqlite",
"Firefox");
466 }
catch (TskCoreException ex) {
467 String msg = NbBundle.getMessage(this.getClass(),
"Firefox.getDlV24.errMsg.errFetchFiles");
468 logger.log(Level.WARNING, msg);
469 this.addErrorMessage(this.getName() +
": " + msg);
473 if (downloadsFiles.isEmpty()) {
474 logger.log(Level.INFO,
"Didn't find any version-24.0 Firefox download files.");
480 for (AbstractFile downloadsFile : downloadsFiles) {
481 if (downloadsFile.getSize() == 0) {
484 String fileName = downloadsFile.getName();
485 String temps = RAImageIngestModule.getRATempPath(currentCase,
"firefox") + File.separator + fileName +
"-downloads" + j +
".db";
488 ContentUtils.writeToFile(downloadsFile,
new File(temps));
489 }
catch (IOException ex) {
490 logger.log(Level.SEVERE,
"Error writing the sqlite db for firefox download artifacts.{0}", ex);
491 this.addErrorMessage(
492 NbBundle.getMessage(
this.getClass(),
"Firefox.getDlV24.errMsg.errAnalyzeFile", this.getName(),
496 File dbFile =
new File(temps);
497 if (context.dataSourceIngestIsCancelled()) {
502 List<HashMap<String, Object>> tempList = this.dbConnect(temps, downloadQueryVersion24);
504 logger.log(Level.INFO,
"{0} - Now getting downloads from {1} with {2} artifacts identified.",
new Object[]{moduleName, temps, tempList.size()});
505 for (HashMap<String, Object> result : tempList) {
507 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
509 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(),
510 NbBundle.getMessage(this.getClass(),
511 "Firefox.parentModuleName.noSpace"),
512 ((result.get(
"url").toString() != null) ? result.get(
"url").toString() :
"")));
517 String target = result.get(
"target").toString();
518 if (target != null) {
520 String decodedTarget = URLDecoder.decode(target.toString().replaceAll(
"file:///",
""),
"UTF-8");
521 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH.getTypeID(),
522 NbBundle.getMessage(this.getClass(),
523 "Firefox.parentModuleName.noSpace"),
525 long pathID = Util.findID(dataSource, decodedTarget);
527 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID(),
528 NbBundle.getMessage(this.getClass(),
529 "Firefox.parentModuleName.noSpace"),
532 }
catch (UnsupportedEncodingException ex) {
533 logger.log(Level.SEVERE,
"Error decoding Firefox download URL in " + temps, ex);
537 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID(),
538 NbBundle.getMessage(this.getClass(),
539 "Firefox.parentModuleName.noSpace"),
540 Long.valueOf(result.get(
"lastModified").toString())));
541 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(),
542 NbBundle.getMessage(this.getClass(),
543 "Firefox.parentModuleName.noSpace"),
544 NbBundle.getMessage(this.getClass(),
"Firefox.moduleName")));
545 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID(),
546 NbBundle.getMessage(this.getClass(),
547 "Firefox.parentModuleName.noSpace"),
548 (Util.extractDomain((result.get(
"url").toString() != null) ? result.get(
"url").toString() :
""))));
549 this.addArtifact(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, downloadsFile, bbattributes);
553 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Firefox.getDlV24.errMsg.errParsingArtifacts",
554 this.getName(), errors));
561 services.fireModuleDataEvent(
new ModuleDataEvent(
562 NbBundle.getMessage(
this.getClass(),
"Firefox.parentModuleName"), BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD));