Autopsy 4.22.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
ExcelReport.java
Go to the documentation of this file.
1/*
2 * Autopsy Forensic Browser
3 *
4 * Copyright 2013-2020 Basis Technology Corp.
5 * Contact: carrier <at> sleuthkit <dot> org
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19package org.sleuthkit.autopsy.report.modules.excel;
20
21import java.io.FileOutputStream;
22import java.io.IOException;
23import java.text.SimpleDateFormat;
24import java.util.List;
25import java.util.logging.Level;
26import org.apache.poi.ss.usermodel.*;
27import org.apache.poi.xssf.usermodel.XSSFWorkbook;
28import org.openide.util.NbBundle;
29import org.openide.util.NbBundle.Messages;
30import org.sleuthkit.autopsy.casemodule.Case;
31import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
32import org.sleuthkit.autopsy.coreutils.Logger;
33import org.sleuthkit.autopsy.report.infrastructure.TableReportModule;
34import org.sleuthkit.datamodel.TskCoreException;
35
36class ExcelReport implements TableReportModule {
37
38 private static final Logger logger = Logger.getLogger(ExcelReport.class.getName());
39 private static ExcelReport instance;
40 private static final int EXCEL_CELL_MAXIMUM_SIZE = 36767; //Specified at:https://poi.apache.org/apidocs/org/apache/poi/ss/SpreadsheetVersion.html
41
42 private Workbook wb;
43 private Sheet sheet;
44 private CellStyle titleStyle;
45 private CellStyle setStyle;
46 private CellStyle elementStyle;
47 private int rowIndex = 0;
48 private int sheetColCount = 0;
49 private String reportPath;
50
51 // Get the default instance of this report
52 public static synchronized ExcelReport getDefault() {
53 if (instance == null) {
54 instance = new ExcelReport();
55 }
56 return instance;
57 }
58
59 // Hidden constructor
60 private ExcelReport() {
61 }
62
69 @Override
70 public void startReport(String baseReportDir) {
71 // Set the path and save it for when the report is written to disk.
72 this.reportPath = baseReportDir + getRelativeFilePath();
73
74 // Make a workbook.
75 wb = new XSSFWorkbook();
76
77 // Create some cell styles.
78 // TODO: The commented out cell style settings below do not work as desired when
79 // the output file is loaded by MS Excel or OfficeLibre. The font height and weight
80 // settings only work as expected when the output file is loaded by OfficeLibre.
81 // The alignment and text wrap settings appear to have no effect.
82 titleStyle = wb.createCellStyle();
83// titleStyle.setBorderBottom((short) 1);
84 Font titleFont = wb.createFont();
85 titleFont.setFontHeightInPoints((short) 12);
86 titleStyle.setFont(titleFont);
87 titleStyle.setAlignment(HorizontalAlignment.LEFT);
88 titleStyle.setWrapText(true);
89
90 setStyle = wb.createCellStyle();
91 Font setFont = wb.createFont();
92 setFont.setFontHeightInPoints((short) 14);
93 setFont.setBold(true);
94 setStyle.setFont(setFont);
95 setStyle.setAlignment(HorizontalAlignment.LEFT);
96 setStyle.setWrapText(true);
97
98 elementStyle = wb.createCellStyle();
99// elementStyle.setF illBackgroundColor(HSSFColor.LIGHT_YELLOW.index);
100 Font elementFont = wb.createFont();
101 elementFont.setFontHeightInPoints((short) 14);
102 elementStyle.setFont(elementFont);
103 elementStyle.setAlignment(HorizontalAlignment.LEFT);
104 elementStyle.setWrapText(true);
105
106 writeSummaryWorksheet();
107 }
108
112 @Override
113 public void endReport() {
114 FileOutputStream out = null;
115 try {
116 out = new FileOutputStream(reportPath);
117 wb.write(out);
118 Case.getCurrentCaseThrows().addReport(reportPath, NbBundle.getMessage(this.getClass(),
119 "ReportExcel.endReport.srcModuleName.text"), "");
120 } catch (IOException ex) {
121 logger.log(Level.SEVERE, "Failed to write Excel report.", ex); //NON-NLS
122 } catch (TskCoreException ex) {
123 String errorMessage = String.format("Error adding %s to case as a report", reportPath); //NON-NLS
124 logger.log(Level.SEVERE, errorMessage, ex);
125 } catch (NoCurrentCaseException ex) {
126 logger.log(Level.SEVERE, "Exception while getting open case.", ex); //NON-NLS
127 } finally {
128 if (out != null) {
129 try {
130 out.close();
131 } catch (IOException ex) {
132 }
133 }
134 }
135 }
136
144 @Override
145 public void startDataType(String name, String description) {
146 // Create a worksheet for the data type (assumed to be an artifact type).
147 name = escapeForExcel(name);
148 sheet = wb.createSheet(name);
149 sheet.setAutobreaks(true);
150 rowIndex = 0;
151
152 // There will be at least two columns, one each for the artifacts count and its label.
153 sheetColCount = 2;
154 }
155
159 @Override
160 public void endDataType() {
161 // Now that the sheet is complete, size the columns to the content.
162 for (int i = 0; i < sheetColCount; ++i) {
163 sheet.autoSizeColumn(i);
164 }
165 }
166
172 @Override
173 public void startSet(String setName) {
174 setName = escapeForExcel(setName);
175 Row row = sheet.createRow(rowIndex);
176 row.setRowStyle(setStyle);
177 row.createCell(0).setCellValue(setName);
178 ++rowIndex;
179 }
180
184 @Override
185 public void endSet() {
186 // Add an empty row as a separator.
187 sheet.createRow(rowIndex);
188 ++rowIndex;
189 }
190
191 @Override
192 public void addSetIndex(List<String> sets) {
193 // Ignored in Excel Report
194 }
195
201 @Override
202 public void addSetElement(String elementName) {
203 elementName = escapeForExcel(elementName);
204 Row row = sheet.createRow(rowIndex);
205 row.setRowStyle(elementStyle);
206 row.createCell(0).setCellValue(elementName);
207 ++rowIndex;
208 }
209
215 @Override
216 public void startTable(List<String> titles) {
217 int tableColCount = 0;
218 Row row = sheet.createRow(rowIndex);
219 row.setRowStyle(titleStyle);
220 for (int i = 0; i < titles.size(); i++) {
221 row.createCell(i).setCellValue(titles.get(i));
222 ++tableColCount;
223 }
224 ++rowIndex;
225
226 // Keep track of the number of columns with data in them for later column auto-sizing.
227 if (tableColCount > sheetColCount) {
228 sheetColCount = tableColCount;
229 }
230 }
231
232 @Override
233 public void endTable() {
234 // Add an empty row as a separator.
235 sheet.createRow(rowIndex);
236 ++rowIndex;
237 }
238
244 @Override
245 @NbBundle.Messages({
246 "ReportExcel.exceptionMessage.dataTooLarge=Value is too long to fit into an Excel cell. ",
247 "ReportExcel.exceptionMessage.errorText=Error showing data into an Excel cell."
248 })
249 public void addRow(List<String> rowData) {
250 Row row = sheet.createRow(rowIndex);
251 for (int i = 0; i < rowData.size(); ++i) {
252 Cell excelCell = row.createCell(i);
253 try {
254 excelCell.setCellValue(rowData.get(i));
255 } catch (Exception e) {
256 if (e instanceof java.lang.IllegalArgumentException && rowData.get(i).length() > EXCEL_CELL_MAXIMUM_SIZE) {
257 excelCell.setCellValue(Bundle.ReportExcel_exceptionMessage_dataTooLarge() + e.getMessage());
258 } else {
259 excelCell.setCellValue(Bundle.ReportExcel_exceptionMessage_errorText());
260 }
261 }
262 }
263 ++rowIndex;
264 }
265
273 @Override
274 public String dateToString(long date) {
275 SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
276 return sdf.format(new java.util.Date(date * 1000));
277 }
278
279 @Override
280 public String getName() {
281 return NbBundle.getMessage(this.getClass(), "ReportExcel.getName.text");
282 }
283
284 @Override
285 public String getDescription() {
286 return NbBundle.getMessage(this.getClass(), "ReportExcel.getDesc.text");
287 }
288
289 @Override
290 public String getRelativeFilePath() {
291 return "Excel.xlsx"; //NON-NLS
292 }
293
302 private static String escapeForExcel(String text) {
303 return text.replaceAll("[\\/\\:\\?\\*\\\\]", "_");
304 }
305
306 @Messages({
307 "ReportExcel.writeSummary.sheetName=Summary",
308 "ReportExcel.writeSummary.summary=Summary",
309 "ReportExcel.writeSummary.caseName=Case Name:",
310 "ReportExcel.writeSummary.numImages=Number of data sources in case:",
311 "ReportExcel.writeSummary.caseNum=Case Number:",
312 "ReportExcel.writeSummary.caseNotes=Case Notes:",
313 "ReportExcel.writeSummary.examiner=Examiner:"
314 })
315 private void writeSummaryWorksheet() {
316 Case currentCase;
317 try {
318 currentCase = Case.getCurrentCaseThrows();
319 } catch (NoCurrentCaseException ex) {
320 logger.log(Level.SEVERE, "Exception while getting open case.", ex); //NON-NLS
321 return;
322 }
323 sheet = wb.createSheet(Bundle.ReportExcel_writeSummary_sheetName());
324 rowIndex = 0;
325
326 Row row = sheet.createRow(rowIndex);
327 row.setRowStyle(setStyle);
328 row.createCell(0).setCellValue(Bundle.ReportExcel_writeSummary_summary());
329 ++rowIndex;
330
331 sheet.createRow(rowIndex);
332 ++rowIndex;
333
334 row = sheet.createRow(rowIndex);
335 row.setRowStyle(setStyle);
336 row.createCell(0).setCellValue(Bundle.ReportExcel_writeSummary_caseName());
337 row.createCell(1).setCellValue(currentCase.getDisplayName());
338 ++rowIndex;
339
340 if (!currentCase.getNumber().isEmpty()) {
341 row = sheet.createRow(rowIndex);
342 row.setRowStyle(setStyle);
343 row.createCell(0).setCellValue(Bundle.ReportExcel_writeSummary_caseNum());
344 row.createCell(1).setCellValue(currentCase.getNumber());
345 ++rowIndex;
346 }
347
348 row = sheet.createRow(rowIndex);
349 row.setRowStyle(setStyle);
350 row.createCell(0).setCellValue(Bundle.ReportExcel_writeSummary_numImages());
351 int numImages;
352 try {
353 numImages = currentCase.getDataSources().size();
354 } catch (TskCoreException ex) {
355 numImages = 0;
356 }
357 row.createCell(1).setCellValue(numImages);
358 ++rowIndex;
359
360 if (!currentCase.getCaseNotes().isEmpty()) {
361 row = sheet.createRow(rowIndex);
362 row.setRowStyle(setStyle);
363 row.createCell(0).setCellValue(Bundle.ReportExcel_writeSummary_caseNotes());
364 row.createCell(1).setCellValue(currentCase.getCaseNotes());
365 ++rowIndex;
366 }
367
368 if (!currentCase.getExaminer().isEmpty()) {
369 row = sheet.createRow(rowIndex);
370 row.setRowStyle(setStyle);
371 row.createCell(0).setCellValue(Bundle.ReportExcel_writeSummary_examiner());
372 row.createCell(1).setCellValue(currentCase.getExaminer());
373 ++rowIndex;
374 }
375
376 sheet.autoSizeColumn(0);
377 sheet.autoSizeColumn(1);
378 }
379}
void addReport(String localPath, String srcModuleName, String reportName)
Definition Case.java:1929
synchronized static Logger getLogger(String name)
Definition Logger.java:124

Copyright © 2012-2024 Sleuth Kit Labs. Generated on:
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.