diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java b/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java index f5a0b3ddc4..acc8b0053c 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java @@ -45,18 +45,20 @@ import java.util.TreeMap; import java.util.TreeSet; import java.util.logging.Level; import org.openide.filesystems.FileUtil; +import org.openide.util.Exceptions; import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.coreutils.EscapeUtil; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.PlatformUtil; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.datamodel.*; -import org.sleuthkit.autopsy.coreutils.EscapeUtil; /** * Generates an HTML report for all the Blackboard Artifacts found in the current case. */ public class ReportHTML implements ReportModule { private static final Logger logger = Logger.getLogger(ReportHTML.class.getName()); - private final String INGEST_WARNING = "

Warning, this report was run before ingest services completed!

"; + private final String INGEST_WARNING = "Warning, this report was run before ingest services completed!"; private final String HTML_META = "\n" + "\n"; private final String CSS = "\n"; @@ -74,28 +76,27 @@ public class ReportHTML implements ReportModule { private Set>> history; private Set>> downloads; private Set>> recent; - private Set>> trackpoint; + //private Set>> trackpoint; private Set>> installed; - //private Set>> keywords; //private Set>> hash; private Set>> devices; private Set>> search; private Set>> exif; - private Set>> fileBookmarks; + private Set>> userBookmarks; private int countBookmarks; private int countCookies; private int countHistory; private int countDownloads; private int countRecent; - private int countTrackpoint; + //private int countTrackpoint; private int countInstalled; private int countKeywords; - //private int countHash; + private int countHash; private int countDevices; private int countSearch; private int countExif; - private int countFileBookmarks; + private int countUserBookmarks; ReportHTML() { } @@ -173,7 +174,6 @@ public class ReportHTML implements ReportModule { reportSize = report.size(); // The report output - DateFormat datetimeFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); DateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy-HH-mm-ss"); Date date = new Date(); String datenotime = dateFormat.format(date); @@ -193,14 +193,13 @@ public class ReportHTML implements ReportModule { history = new TreeSet>>(c); downloads = new TreeSet>>(c); recent = new TreeSet>>(c); - trackpoint = new TreeSet>>(c); + //trackpoint = new TreeSet>>(c); installed = new TreeSet>>(c); - //keywords = new TreeSet>>(c); //hash = new TreeSet>>(c); devices = new TreeSet>>(c); search = new TreeSet>>(c); exif = new TreeSet>>(c); - fileBookmarks = new TreeSet>>(c); + userBookmarks = new TreeSet>>(c); for (Entry> entry : report.entrySet()) { if (ReportFilter.cancel == true) { @@ -216,22 +215,23 @@ public class ReportHTML implements ReportModule { downloads.add(entry); } else if (entry.getKey().getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_RECENT_OBJECT.getTypeID()) { recent.add(entry); - } else if (entry.getKey().getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_TRACKPOINT.getTypeID()) { - trackpoint.add(entry); + //} else if (entry.getKey().getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_TRACKPOINT.getTypeID()) { + // trackpoint.add(entry); } else if (entry.getKey().getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_INSTALLED_PROG.getTypeID()) { installed.add(entry); } else if (entry.getKey().getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) { countKeywords++; - //} else if (entry.getKey().getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID()) { - // hash.add(entry); + } else if (entry.getKey().getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID()) { + countHash++; } else if (entry.getKey().getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_DEVICE_ATTACHED.getTypeID()) { devices.add(entry); } else if (entry.getKey().getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY.getTypeID()) { search.add(entry); } else if (entry.getKey().getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_METADATA_EXIF.getTypeID()){ exif.add(entry); - } else if (entry.getKey().getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID()){ - fileBookmarks.add(entry); + } else if (entry.getKey().getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID() || + entry.getKey().getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getTypeID()){ + userBookmarks.add(entry); } } @@ -243,14 +243,13 @@ public class ReportHTML implements ReportModule { countHistory = history.size(); countDownloads = downloads.size(); countRecent = recent.size(); - countTrackpoint = trackpoint.size(); + //countTrackpoint = trackpoint.size(); countInstalled = installed.size(); - //countKeywords = keywords.size(); //countHash = hash.size(); countDevices = devices.size(); countSearch = search.size(); countExif = exif.size(); - countFileBookmarks = fileBookmarks.size(); + countUserBookmarks = userBookmarks.size(); save(htmlFolder); return htmlFolder + "index.html"; @@ -270,7 +269,7 @@ public class ReportHTML implements ReportModule { "h1 {font-size: 20px; font-weight: normal; color: #07A; padding: 0 0 7px 0; border-bottom: 1px solid #D6D6D6;}\n" + "h2 {font-size: 20px; font-weight: bolder; color: #07A;}\n" + "h3 {font-size: 16px; color: #07A;}\n" + - "ul.nav {list-style-type: none; line-height: 35px; padding: 0px;}\n" + + "ul.nav {list-style-type: none; line-height: 35px; padding: 0px; margin-left: 15px;}\n" + "ul li a {font-size: 14px; color: #444; text-decoration: none; padding-left: 25px;}\n" + "ul li a:hover {text-decoration: underline;}\n" + "p {margin: 0 0 20px 0;}\n" + @@ -321,7 +320,11 @@ public class ReportHTML implements ReportModule { Writer out = null; try { out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(folder + "index.html"), "UTF-8")); - out.write("\n" + CSS + "Autopsy Report for case " + currentCase.getName() + "\n" + "\n"); + StringBuilder head = new StringBuilder(); + head.append("\n" + CSS + "Autopsy Report for case ").append(currentCase.getName()).append("\n"); + head.append("\n"); + head.append("\n"); + out.write(head.toString()); StringBuilder index = new StringBuilder(); index.append("\n"); @@ -364,45 +367,45 @@ public class ReportHTML implements ReportModule { StringBuilder nav = new StringBuilder(); nav.append("
\n

Report Navigation

\n"); nav.append("\n"); out.write(nav.toString()); @@ -432,45 +435,83 @@ public class ReportHTML implements ReportModule { Writer out = null; try { out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(folder + "summary.html"), "UTF-8")); - out.write(generateHead("Case Summary")); + StringBuilder head = new StringBuilder(HTML_META); + head.append("\nCase Summary\n"); + head.append("\n"); + head.append("\n\n"); + out.write(head.toString()); DateFormat datetimeFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); Date date = new Date(); String datetime = datetimeFormat.format(date); String caseName = currentCase.getName(); + String caseNumber = currentCase.getNumber(); String examiner = currentCase.getExaminer(); - String number = currentCase.getNumber(); - Integer imagecount = currentCase.getImageIDs().length; + int imagecount = currentCase.getImageIDs().length; StringBuilder summary = new StringBuilder(); + boolean running = false; if (IngestManager.getDefault().isIngestRunning() || IngestManager.getDefault().areModulesRunning()) { - summary.append(INGEST_WARNING); + running = true; } - summary.append("

Report for Case: ").append(caseName).append("

\n"); - summary.append("

HTML Report Generated by Autopsy 3 on ").append(datetime).append("

\n"); - summary.append("

Examiner: ").append(examiner.isEmpty()? "No examiner" : examiner).append("

\n"); - summary.append("

Case Number: ").append(number.isEmpty() ? "No case number" : number).append("

\n"); - summary.append("

# of Images: ").append(imagecount).append("

\n"); + + summary.append("
\n"); + summary.append("

Autopsy Forensic Report").append(running ? INGEST_WARNING : "").append("

\n"); + summary.append("

HTML Report Generated on ").append(datetime).append("

\n"); + summary.append("
\n"); + summary.append("
\n"); + summary.append("\n"); + summary.append("
\n"); + summary.append("
\n"); + summary.append("\n"); + summary.append("\n"); + summary.append("\n"); + summary.append("\n"); + summary.append("\n"); + summary.append("
Case:").append(caseName).append("
Case Number:").append(!caseNumber.isEmpty() ? caseNumber : "No case number").append("
Examiner:").append(!examiner.isEmpty() ? examiner : "No examiner").append("
# of Images:").append(imagecount).append("
\n"); + summary.append("
\n"); + summary.append("
\n"); + summary.append("
\n"); + summary.append("

Image Information:

\n"); + summary.append("
\n"); try { Image[] images = new Image[imagecount]; for(int i=0; i
  • ").append(img.getName()).append(":\n"); - summary.append("
      \n
    • Timezone: ").append(img.getTimeZone()).append("
    • \n"); + summary.append("

      ").append(img.getName()).append("

      \n"); + summary.append("\n"); + summary.append("\n"); for(String path : img.getPaths()) { - summary.append("
    • Image Path: ").append(path).append("
    • \n"); + summary.append("\n"); } - summary.append("\n\n\n"); + summary.append("
      Timezone:").append(img.getTimeZone()).append("
      Path:").append(path).append("
      \n"); } } catch (TskCoreException ex) { logger.log(Level.WARNING, "Unable to get image information for the HTML report."); } + summary.append("
  • \n"); + summary.append("
    \n"); + summary.append(""); out.write(summary.toString()); - out.write(HTML_FOOT); } catch (FileNotFoundException ex) { logger.log(Level.SEVERE, "Could not find summary.html file to write to."); } catch (UnsupportedEncodingException ex) { @@ -508,7 +549,10 @@ public class ReportHTML implements ReportModule { SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); value = sdf.format(new java.util.Date((tempatt.getValueLong() * 1000))); - + } else if(type.equals(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID()) || + type.equals(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE.getTypeID()) || + type.equals(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE.getTypeID())) { + value = Double.toString(tempatt.getValueDouble()); } else { value = tempatt.getValueString(); } @@ -803,7 +847,7 @@ public class ReportHTML implements ReportModule { /** * Write the trackpoint.html file. * @param folder path to output folder - */ + private void writeTrackpoint(String folder) { Writer out = null; try { @@ -848,7 +892,7 @@ public class ReportHTML implements ReportModule { } catch (IOException ex) { } } - } + }*/ /** * Write the installed.html file. @@ -1161,20 +1205,20 @@ public class ReportHTML implements ReportModule { } /** - * Write the filebookmarks.html file. + * Write the userbookmarks.html file. * @param folder path to output folder */ - private void writeFileBookmarks(String folder) { + private void writeUserBookmarks(String folder) { Writer out = null; try { - out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(folder + "filebookmarks.html"), "UTF-8")); - out.write(generateHead("File Bookmarks (" + countFileBookmarks + ")")); - String title = "
    File Bookmarks (" + countFileBookmarks + ")
    \n
    \n"; + out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(folder + "userbookmarks.html"), "UTF-8")); + out.write(generateHead("User Bookmarks (" + countUserBookmarks + ")")); + String title = "
    User Bookmarks (" + countUserBookmarks + ")
    \n
    \n"; String tableHeader = getTableHead("Comment", "File Name", "Source File"); out.write(title); out.write(tableHeader); - for(Entry> entry: fileBookmarks) { + for(Entry> entry: userBookmarks) { if (ReportFilter.cancel == true) { break; } Long objId = entry.getKey().getObjectID(); AbstractFile file = getFile(objId); @@ -1191,13 +1235,13 @@ public class ReportHTML implements ReportModule { out.write(TABLE_FOOT); out.write(HTML_FOOT); } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Unable to get file's path for filebookmarks.html."); + logger.log(Level.SEVERE, "Unable to get file's path for userbookmarks.html."); } catch (FileNotFoundException ex) { - logger.log(Level.SEVERE, "Could not find filebookmarks.html file to write to."); + logger.log(Level.SEVERE, "Could not find userbookmarks.html file to write to."); } catch (UnsupportedEncodingException ex) { - logger.log(Level.SEVERE, "Did not recognize encoding when writing filebookmarks.hmtl."); + logger.log(Level.SEVERE, "Did not recognize encoding when writing userbookmarks.hmtl."); } catch (IOException ex) { - logger.log(Level.SEVERE, "Error creating Writer for filebookmarks.html."); + logger.log(Level.SEVERE, "Error creating Writer for userbookmarks.html."); } finally { try { if(out != null) { @@ -1209,6 +1253,41 @@ public class ReportHTML implements ReportModule { } } + /** + * Write the hashhits.html file + * @param folder path to output folder + */ + private void writeHashHits(String folder) { + Writer out = null; + try { + out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(folder + "hash.html"), "UTF-8")); + out.write(generateHead("Hash Hit Artifacts (" + countHash + ")")); + String title = "
    Hash Hits (" + countHash + ")
    \n
    \n"; + out.write(title); + + Report key = new Report(); + String HashsetTable = key.getGroupedHashsetHit(); + out.write(HashsetTable); + + out.write(TABLE_FOOT); + out.write(HTML_FOOT); + } catch (FileNotFoundException ex) { + logger.log(Level.SEVERE, "Could not find keywords.html file to write to."); + } catch (UnsupportedEncodingException ex) { + logger.log(Level.SEVERE, "Did not recognize encoding when writing keywords.hmtl."); + } catch (IOException ex) { + logger.log(Level.SEVERE, "Error creating Writer for keywords.html."); + } finally { + try { + if (out != null) { + out.flush(); + out.close(); + } + } catch (IOException ex) { + } + } + } + @Override public String getName() { String name = "HTML"; @@ -1231,12 +1310,49 @@ public class ReportHTML implements ReportModule { writeDownload(path); writeSearch(path); writeRecent(path); - writeTrackpoint(path); + //writeTrackpoint(path); writeInstalled(path); writeKeyword(path); writeDevice(path); writeExif(path); - writeFileBookmarks(path); + writeUserBookmarks(path); + writeHashHits(path); + try { + String dir = PlatformUtil.getUserConfigDirectory() + File.separator; + + PlatformUtil.extractResourceToUserConfigDir(ReportHTML.class, "favicon.ico"); + PlatformUtil.extractResourceToUserConfigDir(ReportHTML.class, "logo.png"); + PlatformUtil.extractResourceToUserConfigDir(ReportHTML.class, "summary.png"); + PlatformUtil.extractResourceToUserConfigDir(ReportHTML.class, "bookmarks.png"); + PlatformUtil.extractResourceToUserConfigDir(ReportHTML.class, "cookies.png"); + PlatformUtil.extractResourceToUserConfigDir(ReportHTML.class, "history.png"); + PlatformUtil.extractResourceToUserConfigDir(ReportHTML.class, "downloads.png"); + PlatformUtil.extractResourceToUserConfigDir(ReportHTML.class, "search.png"); + PlatformUtil.extractResourceToUserConfigDir(ReportHTML.class, "recent.png"); + PlatformUtil.extractResourceToUserConfigDir(ReportHTML.class, "installed.png"); + PlatformUtil.extractResourceToUserConfigDir(ReportHTML.class, "keywords.png"); + PlatformUtil.extractResourceToUserConfigDir(ReportHTML.class, "devices.png"); + PlatformUtil.extractResourceToUserConfigDir(ReportHTML.class, "exif.png"); + PlatformUtil.extractResourceToUserConfigDir(ReportHTML.class, "userbookmarks.png"); + PlatformUtil.extractResourceToUserConfigDir(ReportHTML.class, "hash.png"); + org.sleuthkit.autopsy.coreutils.FileUtil.copyFile(dir + "favicon.ico", path, "favicon", ".ico", true); + org.sleuthkit.autopsy.coreutils.FileUtil.copyFile(dir + "logo.png", path, "logo", ".png", true); + org.sleuthkit.autopsy.coreutils.FileUtil.copyFile(dir + "summary.png", path, "summary", ".png", true); + org.sleuthkit.autopsy.coreutils.FileUtil.copyFile(dir + "bookmarks.png", path, "bookmarks", ".png", true); + org.sleuthkit.autopsy.coreutils.FileUtil.copyFile(dir + "cookies.png", path, "cookies", ".png", true); + org.sleuthkit.autopsy.coreutils.FileUtil.copyFile(dir + "history.png", path, "history", ".png", true); + org.sleuthkit.autopsy.coreutils.FileUtil.copyFile(dir + "downloads.png", path, "downloads", ".png", true); + org.sleuthkit.autopsy.coreutils.FileUtil.copyFile(dir + "search.png", path, "search", ".png", true); + org.sleuthkit.autopsy.coreutils.FileUtil.copyFile(dir + "recent.png", path, "recent", ".png", true); + org.sleuthkit.autopsy.coreutils.FileUtil.copyFile(dir + "installed.png", path, "installed", ".png", true); + org.sleuthkit.autopsy.coreutils.FileUtil.copyFile(dir + "keywords.png", path, "keywords", ".png", true); + org.sleuthkit.autopsy.coreutils.FileUtil.copyFile(dir + "devices.png", path, "devices", ".png", true); + org.sleuthkit.autopsy.coreutils.FileUtil.copyFile(dir + "exif.png", path, "exif", ".png", true); + org.sleuthkit.autopsy.coreutils.FileUtil.copyFile(dir + "userbookmarks.png", path, "userbookmarks", ".png", true); + org.sleuthkit.autopsy.coreutils.FileUtil.copyFile(dir + "hash.png", path, "hash", ".png", true); + } catch (IOException ex) { + System.out.println("Failed to extract images for HTML report."); + } } @Override diff --git a/Core/src/org/sleuthkit/autopsy/report/bookmarks.png b/Core/src/org/sleuthkit/autopsy/report/bookmarks.png new file mode 100644 index 0000000000..cbb650ad4c Binary files /dev/null and b/Core/src/org/sleuthkit/autopsy/report/bookmarks.png differ diff --git a/Core/src/org/sleuthkit/autopsy/report/cookies.png b/Core/src/org/sleuthkit/autopsy/report/cookies.png new file mode 100644 index 0000000000..793964127b Binary files /dev/null and b/Core/src/org/sleuthkit/autopsy/report/cookies.png differ diff --git a/Core/src/org/sleuthkit/autopsy/report/devices.png b/Core/src/org/sleuthkit/autopsy/report/devices.png new file mode 100644 index 0000000000..e49540dccc Binary files /dev/null and b/Core/src/org/sleuthkit/autopsy/report/devices.png differ diff --git a/Core/src/org/sleuthkit/autopsy/report/downloads.png b/Core/src/org/sleuthkit/autopsy/report/downloads.png new file mode 100644 index 0000000000..a976964fc5 Binary files /dev/null and b/Core/src/org/sleuthkit/autopsy/report/downloads.png differ diff --git a/Core/src/org/sleuthkit/autopsy/report/exif.png b/Core/src/org/sleuthkit/autopsy/report/exif.png new file mode 100644 index 0000000000..046f049a48 Binary files /dev/null and b/Core/src/org/sleuthkit/autopsy/report/exif.png differ diff --git a/Core/src/org/sleuthkit/autopsy/report/favicon.ico b/Core/src/org/sleuthkit/autopsy/report/favicon.ico new file mode 100644 index 0000000000..efad7a3de4 Binary files /dev/null and b/Core/src/org/sleuthkit/autopsy/report/favicon.ico differ diff --git a/Core/src/org/sleuthkit/autopsy/report/hash.png b/Core/src/org/sleuthkit/autopsy/report/hash.png new file mode 100644 index 0000000000..f1caff1f30 Binary files /dev/null and b/Core/src/org/sleuthkit/autopsy/report/hash.png differ diff --git a/Core/src/org/sleuthkit/autopsy/report/history.png b/Core/src/org/sleuthkit/autopsy/report/history.png new file mode 100644 index 0000000000..48f4d5f324 Binary files /dev/null and b/Core/src/org/sleuthkit/autopsy/report/history.png differ diff --git a/Core/src/org/sleuthkit/autopsy/report/installed.png b/Core/src/org/sleuthkit/autopsy/report/installed.png new file mode 100644 index 0000000000..b8872bbcf9 Binary files /dev/null and b/Core/src/org/sleuthkit/autopsy/report/installed.png differ diff --git a/Core/src/org/sleuthkit/autopsy/report/keywords.png b/Core/src/org/sleuthkit/autopsy/report/keywords.png new file mode 100644 index 0000000000..133ba948b3 Binary files /dev/null and b/Core/src/org/sleuthkit/autopsy/report/keywords.png differ diff --git a/Core/src/org/sleuthkit/autopsy/report/logo.png b/Core/src/org/sleuthkit/autopsy/report/logo.png new file mode 100644 index 0000000000..1561f126a5 Binary files /dev/null and b/Core/src/org/sleuthkit/autopsy/report/logo.png differ diff --git a/Core/src/org/sleuthkit/autopsy/report/recent.png b/Core/src/org/sleuthkit/autopsy/report/recent.png new file mode 100644 index 0000000000..a3250fe168 Binary files /dev/null and b/Core/src/org/sleuthkit/autopsy/report/recent.png differ diff --git a/Core/src/org/sleuthkit/autopsy/report/search.png b/Core/src/org/sleuthkit/autopsy/report/search.png new file mode 100644 index 0000000000..d036553018 Binary files /dev/null and b/Core/src/org/sleuthkit/autopsy/report/search.png differ diff --git a/Core/src/org/sleuthkit/autopsy/report/summary.png b/Core/src/org/sleuthkit/autopsy/report/summary.png new file mode 100644 index 0000000000..cffe6d8b7f Binary files /dev/null and b/Core/src/org/sleuthkit/autopsy/report/summary.png differ diff --git a/Core/src/org/sleuthkit/autopsy/report/userbookmarks.png b/Core/src/org/sleuthkit/autopsy/report/userbookmarks.png new file mode 100644 index 0000000000..a06c596ada Binary files /dev/null and b/Core/src/org/sleuthkit/autopsy/report/userbookmarks.png differ