This commit is contained in:
Jeff Wallace 2013-08-06 09:52:30 -04:00
commit 96c1f20147
3 changed files with 294 additions and 106 deletions

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2012 Basis Technology Corp.
* Copyright 2013 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -22,8 +22,6 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.logging.Level;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.*;
@ -34,17 +32,15 @@ import org.sleuthkit.autopsy.coreutils.Logger;
public class ReportExcel implements TableReportModule {
private static final Logger logger = Logger.getLogger(ReportExcel.class.getName());
private static ReportExcel instance;
private Case currentCase;
private Workbook wb;
private Sheet sheet;
private CellStyle titleStyle;
private CellStyle setStyle;
private CellStyle elementStyle;
private int rowCount = 2;
private Map<String, Integer> dataTypes;
private String currentDataType;
private int rowIndex = 0;
private int sheetColCount = 0;
private int artifactsCount = 0;
private String reportPath;
// Get the default instance of this report
@ -65,42 +61,43 @@ public class ReportExcel implements TableReportModule {
* @param path path to save the report
*/
@Override
public void startReport(String path) {
currentCase = Case.getCurrentCase();
public void startReport(String path) {
// Set the path and save it for when the report is written to disk.
this.reportPath = path + getFilePath();
// Make a workbook.
wb = new XSSFWorkbook();
// Create some cell styles.
// TODO: The commented out cell style settings below do not work as desired when
// the output file is loaded by MS Excel or OfficeLibre. The font height and weight
// settings only work as expected when the output file is loaded by OfficeLibre.
// The alignment and text wrap settings appear to have no effect.
titleStyle = wb.createCellStyle();
titleStyle.setBorderBottom((short) 1);
// titleStyle.setBorderBottom((short) 1);
Font titleFont = wb.createFont();
titleFont.setFontHeightInPoints((short) 12);
titleStyle.setFont(titleFont);
titleStyle.setAlignment(CellStyle.ALIGN_LEFT);
titleStyle.setWrapText(true);
setStyle = wb.createCellStyle();
Font setFont = wb.createFont();
setFont.setFontHeightInPoints((short) 14);
setFont.setBoldweight((short) 10);
setStyle.setFont(setFont);
setStyle.setAlignment(CellStyle.ALIGN_LEFT);
setStyle.setWrapText(true);
elementStyle = wb.createCellStyle();
elementStyle.setFillBackgroundColor(HSSFColor.LIGHT_YELLOW.index);
// elementStyle.setF illBackgroundColor(HSSFColor.LIGHT_YELLOW.index);
Font elementFont = wb.createFont();
elementFont.setFontHeightInPoints((short) 14);
elementStyle.setFont(elementFont);
dataTypes = new TreeMap<String, Integer>();
this.reportPath = path + getFilePath();
// Write the summary
sheet = wb.createSheet("Summary");
sheet.createRow(0).createCell(0).setCellValue("Case Name:");
sheet.getRow(0).createCell(1).setCellValue(currentCase.getName());
sheet.createRow(1).createCell(0).setCellValue("Case Number:");
sheet.getRow(1).createCell(1).setCellValue(currentCase.getNumber());
sheet.createRow(2).createCell(0).setCellValue("Examiner:");
sheet.getRow(2).createCell(1).setCellValue(currentCase.getExaminer());
sheet.createRow(3).createCell(0).setCellValue("# of Images:");
sheet.getRow(3).createCell(1).setCellValue(currentCase.getImageIDs().length);
elementStyle.setAlignment(CellStyle.ALIGN_LEFT);
elementStyle.setWrapText(true);
writeSummaryWorksheet();
}
/**
@ -126,28 +123,95 @@ public class ReportExcel implements TableReportModule {
/**
* Start a new sheet for the given data type.
* @param title data type name
* Start a new worksheet for the given data type.
* @param name data type name
*/
@Override
public void startDataType(String title) {
title = escapeForExcel(title);
sheet = wb.createSheet(title);
public void startDataType(String name) {
// Create a worksheet for the data type (assumed to be an artifact type).
name = escapeForExcel(name);
sheet = wb.createSheet(name);
sheet.setAutobreaks(true);
currentDataType = title;
rowIndex = 0;
artifactsCount = 0;
// Add a title row to the worksheet.
Row row = sheet.createRow(rowIndex);
row.setRowStyle(setStyle);
row.createCell(0).setCellValue(name);
++rowIndex;
// Add an artifacts count row. The actual count will be filled in later.
row = sheet.createRow(rowIndex);
row.setRowStyle(setStyle);
row.createCell(0).setCellValue("Number of artifacts:");
++rowIndex;
// Add an empty row as a separator.
sheet.createRow(rowIndex);
++rowIndex;
// There will be at least two columns, one each for the artifacts count and its label.
sheetColCount = 2;
}
/**
* Start a new worksheet for the given data type.
* Note: This method is a temporary workaround to avoid modifying the TableReportModule interface.
*
* @param name Name of the data type
* @param comment Comment on the data type, may be the empty string
*/
public void startDataType(String name, String comment) {
// Create a worksheet for the data type (assumed to be an artifact type).
name = escapeForExcel(name);
sheet = wb.createSheet(name);
sheet.setAutobreaks(true);
rowIndex = 0;
artifactsCount = 0;
// Add a title row to the worksheet.
Row row = sheet.createRow(rowIndex);
row.setRowStyle(setStyle);
row.createCell(0).setCellValue(name);
++rowIndex;
// Add an artifacts count row. The actual count will be filled in later.
row = sheet.createRow(rowIndex);
row.setRowStyle(setStyle);
row.createCell(0).setCellValue("Number of artifacts:");
++rowIndex;
// Add a comment row, if a comment was supplied.
if (!comment.isEmpty()) {
row = sheet.createRow(rowIndex);
row.setRowStyle(setStyle);
row.createCell(0).setCellValue(comment);
++rowIndex;
}
// Add an empty row as a separator.
sheet.createRow(rowIndex);
++rowIndex;
// There will be at least two columns, one each for the artifacts count and its label.
sheetColCount = 2;
}
/**
* End the current data type and sheet.
*/
@Override
public void endDataType() {
Row temp = sheet.createRow(0);
temp.createCell(0).setCellValue("Number of " + currentDataType + " artifacts:");
temp.createCell(1).setCellValue(rowCount);
dataTypes.put(currentDataType, rowCount);
rowCount = 2;
// Fill in the artifact count cell in row 0.
Row row = sheet.getRow(1);
row.setRowStyle(setStyle);
row.createCell(1).setCellValue(artifactsCount);
// Now that the sheet is complete, size the columns to the content.
for (int i = 0; i < sheetColCount; ++i) {
sheet.autoSizeColumn(i);
}
}
/**
@ -157,10 +221,10 @@ public class ReportExcel implements TableReportModule {
@Override
public void startSet(String setName) {
setName = escapeForExcel(setName);
Row temp = sheet.createRow(rowCount);
temp.setRowStyle(setStyle);
temp.createCell(0).setCellValue(setName);
rowCount++;
Row row = sheet.createRow(rowIndex);
row.setRowStyle(setStyle);
row.createCell(0).setCellValue(setName);
++rowIndex;
}
/**
@ -168,12 +232,14 @@ public class ReportExcel implements TableReportModule {
*/
@Override
public void endSet() {
rowCount++; // Put a space between the sets
// Add an empty row as a separator.
sheet.createRow(rowIndex);
++rowIndex;
}
// Ignored in Excel Report
@Override
public void addSetIndex(List<String> sets) {
// Ignored in Excel Report
}
/**
@ -183,10 +249,10 @@ public class ReportExcel implements TableReportModule {
@Override
public void addSetElement(String elementName) {
elementName = escapeForExcel(elementName);
Row temp = sheet.createRow(rowCount);
temp.setRowStyle(elementStyle);
temp.createCell(0).setCellValue(elementName);
rowCount++;
Row row = sheet.createRow(rowIndex);
row.setRowStyle(elementStyle);
row.createCell(0).setCellValue(elementName);
++rowIndex;
}
/**
@ -195,17 +261,26 @@ public class ReportExcel implements TableReportModule {
*/
@Override
public void startTable(List<String> titles) {
Row temp = sheet.createRow(rowCount);
temp.setRowStyle(titleStyle);
int tableColCount = 0;
Row row = sheet.createRow(rowIndex);
row.setRowStyle(titleStyle);
for (int i=0; i<titles.size(); i++) {
temp.createCell(i).setCellValue(titles.get(i));
row.createCell(i).setCellValue(titles.get(i));
++tableColCount;
}
++rowIndex;
// Keep track of the number of columns with data in them for later column auto-sizing.
if (tableColCount > sheetColCount) {
sheetColCount = tableColCount;
}
rowCount++;
}
// Do nothing on end table
@Override
public void endTable() {
// Add an empty row as a separator.
sheet.createRow(rowIndex);
++rowIndex;
}
/**
@ -213,12 +288,13 @@ public class ReportExcel implements TableReportModule {
* @param row cells to add
*/
@Override
public void addRow(List<String> row) {
Row temp = sheet.createRow(rowCount);
for (int i=0; i<row.size(); i++) {
temp.createCell(i).setCellValue(row.get(i));
public void addRow(List<String> rowData) {
Row row = sheet.createRow(rowIndex);
for (int i = 0; i < rowData.size(); ++i) {
row.createCell(i).setCellValue(rowData.get(i));
}
rowCount++;
++rowIndex;
++artifactsCount;
}
/**
@ -261,4 +337,46 @@ public class ReportExcel implements TableReportModule {
private static String escapeForExcel(String text) {
return text.replaceAll("[\\/\\:\\?\\*\\\\]", "_");
}
private void writeSummaryWorksheet() {
sheet = wb.createSheet("Summary");
rowIndex = 0;
Row row = sheet.createRow(rowIndex);
row.setRowStyle(setStyle);
row.createCell(0).setCellValue("Summary");
++rowIndex;
sheet.createRow(rowIndex);
++rowIndex;
Case currentCase = Case.getCurrentCase();
row = sheet.createRow(rowIndex);
row.setRowStyle(setStyle);
row.createCell(0).setCellValue("Case Name:");
row.createCell(1).setCellValue(currentCase.getName());
++rowIndex;
row = sheet.createRow(rowIndex);
row.setRowStyle(setStyle);
row.createCell(0).setCellValue("Case Number:");
row.createCell(1).setCellValue(currentCase.getNumber());
++rowIndex;
row = sheet.createRow(rowIndex);
row.setRowStyle(setStyle);
row.createCell(0).setCellValue("Examiner:");
row.createCell(1).setCellValue(currentCase.getExaminer());
++rowIndex;
row = sheet.createRow(rowIndex);
row.setRowStyle(setStyle);
row.createCell(0).setCellValue("Number of Images:");
row.createCell(1).setCellValue(currentCase.getImageIDs().length);
++rowIndex;
sheet.autoSizeColumn(0);
sheet.autoSizeColumn(1);
}
}

View File

@ -60,7 +60,6 @@ import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
/**
* Generates all TableReportModules and GeneralReportModules, given whether each module for both
* types is enabled or disabled, and the base report path to save them at.
@ -197,26 +196,26 @@ public class ReportGenerator {
* SwingWorker to generate reports on blackboard artifacts.
*/
private class ArtifactsReportsWorker extends SwingWorker<Integer, Integer> {
List<TableReportModule> tableModules;
List<ARTIFACT_TYPE> artifactTypes;
HashSet<String> tagNamesFilter;
private List<TableReportModule> tableModules = new ArrayList<>();
private List<ARTIFACT_TYPE> artifactTypes = new ArrayList<>();
private HashSet<String> tagNamesFilter = new HashSet<>();
// Create an ArtifactWorker with the enabled/disabled state of all Artifacts
ArtifactsReportsWorker(Map<ARTIFACT_TYPE, Boolean> artifactTypeSelections, Map<String, Boolean> tagSelections) {
tableModules = new ArrayList<>();
// Get the report modules selected by the user.
for (Entry<TableReportModule, ReportProgressPanel> entry : tableProgress.entrySet()) {
tableModules.add(entry.getKey());
}
artifactTypes = new ArrayList<>();
// Get the artifact types selected by the user.
for (Entry<ARTIFACT_TYPE, Boolean> entry : artifactTypeSelections.entrySet()) {
if (entry.getValue()) {
artifactTypes.add(entry.getKey());
}
}
// Get the tags selected by the user.
if (tagSelections != null) {
tagNamesFilter = new HashSet<>();
for (Entry<String, Boolean> entry : tagSelections.entrySet()) {
if (entry.getValue() == true) {
tagNamesFilter.add(entry.getKey());
@ -238,6 +237,13 @@ public class ReportGenerator {
}
}
// Make a comment on the tags filter.
StringBuilder comment = new StringBuilder();
if (!tagNamesFilter.isEmpty()) {
comment.append("This report only includes files and artifacts tagged with: ");
comment.append(makeCommaSeparatedList(tagNamesFilter));
}
// For every enabled artifact type
for (ARTIFACT_TYPE type : artifactTypes) {
// Check to see if all the TableReportModules have been canceled
@ -254,16 +260,16 @@ public class ReportGenerator {
// If the type is keyword hit or hashset hit, use the helper
if (type.equals(ARTIFACT_TYPE.TSK_KEYWORD_HIT)) {
writeKeywordHits(tableModules, tagNamesFilter);
writeKeywordHits(tableModules, comment.toString(), tagNamesFilter);
continue;
} else if (type.equals(ARTIFACT_TYPE.TSK_HASHSET_HIT)) {
writeHashsetHits(tableModules, tagNamesFilter);
writeHashsetHits(tableModules, comment.toString(), tagNamesFilter);
continue;
}
// Otherwise setup the unsorted list of artifacts, to later be sorted
ArtifactComparator c = new ArtifactComparator();
List<Entry<BlackboardArtifact, List<BlackboardAttribute>>> unsortedArtifacts = new ArrayList<Entry<BlackboardArtifact, List<BlackboardAttribute>>>();
List<Entry<BlackboardArtifact, List<BlackboardAttribute>>> unsortedArtifacts = new ArrayList<>();
try {
// For every artifact of the current type, add it and it's attributes to a list
for (BlackboardArtifact artifact : skCase.getBlackboardArtifacts(type)) {
@ -289,14 +295,20 @@ public class ReportGenerator {
// For every module start a new data type and table for the current artifact type.
for (TableReportModule module : tableModules) {
tableProgress.get(module).updateStatusLabel("Now processing " + type.getDisplayName() + "...");
module.startDataType(type.getDisplayName());
// This is a temporary workaround to avoid modifying the TableReportModule interface.
if (module instanceof ReportHTML) {
ReportHTML htmlReportModule = (ReportHTML)module;
htmlReportModule.startDataType(type.getDisplayName(), comment.toString());
htmlReportModule.startTable(columnHeaders, type);
}
else if (module instanceof ReportExcel) {
ReportExcel excelReportModule = (ReportExcel)module;
excelReportModule.startDataType(type.getDisplayName(), comment.toString());
excelReportModule.startTable(columnHeaders);
}
else {
module.startDataType(type.getDisplayName());
module.startTable(columnHeaders);
}
}
@ -323,6 +335,7 @@ public class ReportGenerator {
rowData.add(tagsList);
}
// This is a temporary workaround to avoid modifying the TableReportModule interface.
if (module instanceof ReportHTML) {
ReportHTML htmlReportModule = (ReportHTML)module;
htmlReportModule.addRow(rowData, artifactEntry.getKey());
@ -353,7 +366,7 @@ public class ReportGenerator {
private Boolean failsTagFilter(HashSet<String> tags, HashSet<String> tagsFilter)
{
if (tagsFilter == null) {
if (null == tagsFilter || tagsFilter.isEmpty()) {
return false;
}
@ -367,7 +380,7 @@ public class ReportGenerator {
* @param tableModules modules to report on
*/
@SuppressWarnings("deprecation")
private void writeKeywordHits(List<TableReportModule> tableModules, HashSet<String> tagNamesFilter) {
private void writeKeywordHits(List<TableReportModule> tableModules, String comment, HashSet<String> tagNamesFilter) {
ResultSet listsRs = null;
try {
// Query for keyword lists
@ -377,7 +390,7 @@ public class ReportGenerator {
"AND art.artifact_type_id = " + ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID() + " " +
"AND att.artifact_id = art.artifact_id " +
"GROUP BY list");
List<String> lists = new ArrayList<String>();
List<String> lists = new ArrayList<>();
while(listsRs.next()) {
String list = listsRs.getString("list");
if(list.isEmpty()) {
@ -388,7 +401,18 @@ public class ReportGenerator {
// Make keyword data type and give them set index
for (TableReportModule module : tableModules) {
module.startDataType(ARTIFACT_TYPE.TSK_KEYWORD_HIT.getDisplayName());
// This is a temporary workaround to avoid modifying the TableReportModule interface.
if (module instanceof ReportHTML) {
ReportHTML htmlReportModule = (ReportHTML)module;
htmlReportModule.startDataType(ARTIFACT_TYPE.TSK_KEYWORD_HIT.getDisplayName(), comment);
}
else if (module instanceof ReportExcel) {
ReportExcel excelReportModule = (ReportExcel)module;
excelReportModule.startDataType(ARTIFACT_TYPE.TSK_KEYWORD_HIT.getDisplayName(), comment);
}
else {
module.startDataType(ARTIFACT_TYPE.TSK_KEYWORD_HIT.getDisplayName());
}
module.addSetIndex(lists);
tableProgress.get(module).updateStatusLabel("Now processing "
+ ARTIFACT_TYPE.TSK_KEYWORD_HIT.getDisplayName() + "...");
@ -507,11 +531,11 @@ public class ReportGenerator {
}
/**
* Write the hashset hits to the provided TableReportModules.
* Write the hash set hits to the provided TableReportModules.
* @param tableModules modules to report on
*/
@SuppressWarnings("deprecation")
private void writeHashsetHits(List<TableReportModule> tableModules, HashSet<String> tagNamesFilter) {
private void writeHashsetHits(List<TableReportModule> tableModules, String comment, HashSet<String> tagNamesFilter) {
ResultSet listsRs = null;
try {
// Query for hashsets
@ -521,14 +545,24 @@ public class ReportGenerator {
"AND art.artifact_type_id = " + ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID() + " " +
"AND att.artifact_id = art.artifact_id " +
"GROUP BY list");
List<String> lists = new ArrayList<String>();
List<String> lists = new ArrayList<>();
while(listsRs.next()) {
lists.add(listsRs.getString("list"));
}
// Make hashset data type and give them set index
for (TableReportModule module : tableModules) {
module.startDataType(ARTIFACT_TYPE.TSK_HASHSET_HIT.getDisplayName());
// This is a temporary workaround to avoid modifying the TableReportModule interface.
if (module instanceof ReportHTML) {
ReportHTML htmlReportModule = (ReportHTML)module;
htmlReportModule.startDataType(ARTIFACT_TYPE.TSK_HASHSET_HIT.getDisplayName(), comment);
}
else if (module instanceof ReportExcel) {
ReportExcel excelReportModule = (ReportExcel)module;
excelReportModule.startDataType(ARTIFACT_TYPE.TSK_HASHSET_HIT.getDisplayName(), comment);
}
else {
module.startDataType(ARTIFACT_TYPE.TSK_HASHSET_HIT.getDisplayName());
}
module.addSetIndex(lists);
tableProgress.get(module).updateStatusLabel("Now processing "
+ ARTIFACT_TYPE.TSK_HASHSET_HIT.getDisplayName() + "...");
@ -640,55 +674,55 @@ public class ReportGenerator {
switch (type) {
case TSK_WEB_BOOKMARK:
columnHeaders = new ArrayList<String>(Arrays.asList(new String[] {"URL", "Title", "Date Accessed", "Program", "Source File"}));
columnHeaders = new ArrayList<>(Arrays.asList(new String[] {"URL", "Title", "Date Accessed", "Program", "Source File"}));
break;
case TSK_WEB_COOKIE:
columnHeaders = new ArrayList<String>(Arrays.asList(new String[] {"URL", "Date/Time", "Name", "Value", "Program", "Source File"}));
columnHeaders = new ArrayList<>(Arrays.asList(new String[] {"URL", "Date/Time", "Name", "Value", "Program", "Source File"}));
break;
case TSK_WEB_HISTORY:
columnHeaders = new ArrayList<String>(Arrays.asList(new String[] {"URL", "Date Accessed", "Referrer", "Name", "Program", "Source File"}));
columnHeaders = new ArrayList<>(Arrays.asList(new String[] {"URL", "Date Accessed", "Referrer", "Name", "Program", "Source File"}));
break;
case TSK_WEB_DOWNLOAD:
columnHeaders = new ArrayList<String>(Arrays.asList(new String[] {"Destination", "Source URL", "Date Accessed", "Program", "Source File"}));
columnHeaders = new ArrayList<>(Arrays.asList(new String[] {"Destination", "Source URL", "Date Accessed", "Program", "Source File"}));
break;
case TSK_RECENT_OBJECT:
columnHeaders = new ArrayList<String>(Arrays.asList(new String[] {"Path", "Source File"}));
columnHeaders = new ArrayList<>(Arrays.asList(new String[] {"Path", "Source File"}));
break;
case TSK_INSTALLED_PROG:
columnHeaders = new ArrayList<String>(Arrays.asList(new String[] {"Program Name", "Install Date/Time", "Source File"}));
columnHeaders = new ArrayList<>(Arrays.asList(new String[] {"Program Name", "Install Date/Time", "Source File"}));
break;
case TSK_KEYWORD_HIT:
columnHeaders = new ArrayList<String>(Arrays.asList(new String[] {"Preview", "Source File"}));
columnHeaders = new ArrayList<>(Arrays.asList(new String[] {"Preview", "Source File"}));
break;
case TSK_HASHSET_HIT:
columnHeaders = new ArrayList<String>(Arrays.asList(new String[] {"File", "Size"}));
columnHeaders = new ArrayList<>(Arrays.asList(new String[] {"File", "Size"}));
break;
case TSK_DEVICE_ATTACHED:
columnHeaders = new ArrayList<String>(Arrays.asList(new String[] {"Name", "Device ID", "Date/Time", "Source File"}));
columnHeaders = new ArrayList<>(Arrays.asList(new String[] {"Name", "Device ID", "Date/Time", "Source File"}));
break;
case TSK_WEB_SEARCH_QUERY:
columnHeaders = new ArrayList<String>(Arrays.asList(new String[] {"Text", "Domain", "Date Accessed", "Program Name", "Source File"}));
columnHeaders = new ArrayList<>(Arrays.asList(new String[] {"Text", "Domain", "Date Accessed", "Program Name", "Source File"}));
break;
case TSK_METADATA_EXIF:
columnHeaders = new ArrayList<String>(Arrays.asList(new String[] {"Date Taken", "Device Manufacturer", "Device Model", "Latitude", "Longitude", "Source File"}));
columnHeaders = new ArrayList<>(Arrays.asList(new String[] {"Date Taken", "Device Manufacturer", "Device Model", "Latitude", "Longitude", "Source File"}));
break;
case TSK_TAG_FILE:
columnHeaders = new ArrayList<String>(Arrays.asList(new String[] {"File", "Tag", "Comment"}));
columnHeaders = new ArrayList<>(Arrays.asList(new String[] {"File", "Tag", "Comment"}));
break;
case TSK_TAG_ARTIFACT:
columnHeaders = new ArrayList<String>(Arrays.asList(new String[] {"Result Type", "Tag", "Comment", "Source File"}));
columnHeaders = new ArrayList<>(Arrays.asList(new String[] {"Result Type", "Tag", "Comment", "Source File"}));
break;
case TSK_CONTACT:
columnHeaders = new ArrayList<String>(Arrays.asList(new String[] {"Person Name", "Phone Number", "Phone Number (Home)", "Phone Number (Office)", "Phone Number (Mobile)", "Email", "Source File" }));
columnHeaders = new ArrayList<>(Arrays.asList(new String[] {"Person Name", "Phone Number", "Phone Number (Home)", "Phone Number (Office)", "Phone Number (Mobile)", "Email", "Source File" }));
break;
case TSK_MESSAGE:
columnHeaders = new ArrayList<String>(Arrays.asList(new String[] {"Message Type", "Direction", "Date/Time", "From Phone Number", "From Email", "To Phone Number", "To Email", "Subject", "Text", "Source File" }));
columnHeaders = new ArrayList<>(Arrays.asList(new String[] {"Message Type", "Direction", "Date/Time", "From Phone Number", "From Email", "To Phone Number", "To Email", "Subject", "Text", "Source File" }));
break;
case TSK_CALLLOG:
columnHeaders = new ArrayList<String>(Arrays.asList(new String[] {"Person Name", "Phone Number", "Date/Time", "Direction", "Source File" }));
columnHeaders = new ArrayList<>(Arrays.asList(new String[] {"Person Name", "Phone Number", "Date/Time", "Direction", "Source File" }));
break;
case TSK_CALENDAR_ENTRY:
columnHeaders = new ArrayList<String>(Arrays.asList(new String[] {"Calendar Entry Type", "Description", "Start Date/Time", "End Date/Time", "Location", "Source File" }));
columnHeaders = new ArrayList<>(Arrays.asList(new String[] {"Calendar Entry Type", "Description", "Start Date/Time", "End Date/Time", "Location", "Source File" }));
break;
default:
return null;
@ -711,7 +745,7 @@ public class ReportGenerator {
* @return Map<Integer, String> of the BlackboardAttributes mapped to their attribute type ID
*/
public Map<Integer, String> getMappedAttributes(List<BlackboardAttribute> attList, TableReportModule... module) {
Map<Integer, String> attributes = new HashMap<Integer, String>();
Map<Integer, String> attributes = new HashMap<>();
int size = ATTRIBUTE_TYPE.values().length;
for (int n = 0; n <= size; n++) {
attributes.put(n, "");
@ -759,11 +793,11 @@ public class ReportGenerator {
private String makeCommaSeparatedList(Collection<String> items) {
String list = "";
for (Iterator<String> iterator = items.iterator(); iterator.hasNext(); ) {
list += iterator.next() + (iterator.hasNext() ? "," : "");
list += iterator.next() + (iterator.hasNext() ? ", " : "");
}
return list;
}
/**
* Get a list of Strings with all the row values for a given BlackboardArtifact and
* list of BlackboardAttributes Entry, basing the date/time field on the given TableReportModule.
@ -882,7 +916,7 @@ public class ReportGenerator {
}
return taggedArtifactRow;
case TSK_CONTACT:
List<String> contact = new ArrayList<String>();
List<String> contact = new ArrayList<>();
contact.add(attributes.get(ATTRIBUTE_TYPE.TSK_NAME_PERSON.getTypeID()));
contact.add(attributes.get(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER.getTypeID()));
contact.add(attributes.get(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_HOME.getTypeID()));
@ -892,7 +926,7 @@ public class ReportGenerator {
contact.add(getFileUniquePath(entry.getKey().getObjectID()));
return contact;
case TSK_MESSAGE:
List<String> message = new ArrayList<String>();
List<String> message = new ArrayList<>();
message.add(attributes.get(ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE.getTypeID()));
message.add(attributes.get(ATTRIBUTE_TYPE.TSK_DIRECTION.getTypeID()));
message.add(attributes.get(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID()));
@ -905,7 +939,7 @@ public class ReportGenerator {
message.add(getFileUniquePath(entry.getKey().getObjectID()));
return message;
case TSK_CALLLOG:
List<String> call_log = new ArrayList<String>();
List<String> call_log = new ArrayList<>();
call_log.add(attributes.get(ATTRIBUTE_TYPE.TSK_NAME_PERSON.getTypeID()));
call_log.add(attributes.get(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER.getTypeID()));
call_log.add(attributes.get(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID()));
@ -913,7 +947,7 @@ public class ReportGenerator {
call_log.add(getFileUniquePath(entry.getKey().getObjectID()));
return call_log;
case TSK_CALENDAR_ENTRY:
List<String> calEntry = new ArrayList<String>();
List<String> calEntry = new ArrayList<>();
calEntry.add(attributes.get(ATTRIBUTE_TYPE.TSK_CALENDAR_ENTRY_TYPE.getTypeID()));
calEntry.add(attributes.get(ATTRIBUTE_TYPE.TSK_DESCRIPTION.getTypeID()));
calEntry.add(attributes.get(ATTRIBUTE_TYPE.TSK_DATETIME_START.getTypeID()));

View File

@ -177,6 +177,41 @@ public class ReportHTML implements TableReportModule {
}
}
/**
* Start a new HTML page for the given data type. Update the output stream to this page,
* and setup the web page header.
* Note: This method is a temporary workaround to avoid modifying the TableReportModule interface.
*
* @param name Name of the data type
* @param comment Comment on the data type, may be the empty string
*/
public void startDataType(String name, String comment) {
String title = org.sleuthkit.autopsy.coreutils.FileUtil.escapeFileName(name);
try {
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path + title + getExtension()), "UTF-8"));
} catch (FileNotFoundException ex) {
logger.log(Level.SEVERE, "File not found: {0}", ex);
} catch (UnsupportedEncodingException ex) {
logger.log(Level.SEVERE, "Unrecognized encoding");
}
try {
StringBuilder page = new StringBuilder();
page.append("<html>\n<head>\n\t<title>").append(name).append("</title>\n\t<link rel=\"stylesheet\" type=\"text/css\" href=\"index.css\" />\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n</head>\n<body>\n");
page.append("<div id=\"header\">").append(name).append("</div>\n<div id=\"content\">\n");
if (!comment.isEmpty()) {
page.append("<p><strong>");
page.append(comment);
page.append("</string></p>\n");
}
out.write(page.toString());
currentDataType = name;
rowCount = 0;
} catch (IOException ex) {
logger.log(Level.SEVERE, "Failed to write page head: {0}", ex);
}
}
/**
* End the current data type. Write the end of the web page and close the
* output stream.
@ -284,6 +319,7 @@ public class ReportHTML implements TableReportModule {
/**
* Start a new table with the given column headers.
* Note: This method is a temporary workaround to avoid modifying the TableReportModule interface.
*
* @param columnHeaders column headers
* @param sourceArtifact source blackboard artifact for the table data
@ -816,7 +852,7 @@ public class ReportHTML implements TableReportModule {
summary.append("<tr><td>Case:</td><td>").append(caseName).append("</td></tr>\n");
summary.append("<tr><td>Case Number:</td><td>").append(!caseNumber.isEmpty() ? caseNumber : "<i>No case number</i>").append("</td></tr>\n");
summary.append("<tr><td>Examiner:</td><td>").append(!examiner.isEmpty() ? examiner : "<i>No examiner</i>").append("</td></tr>\n");
summary.append("<tr><td># of Images:</td><td>").append(imagecount).append("</td></tr>\n");
summary.append("<tr><td>Number of Images:</td><td>").append(imagecount).append("</td></tr>\n");
summary.append("</table>\n");
summary.append("</div>\n");
summary.append("<div class=\"clear\"></div>\n");