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