Autopsy  4.20.0
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  */
19 package org.sleuthkit.autopsy.report.modules.excel;
20 
21 import java.io.FileOutputStream;
22 import java.io.IOException;
23 import java.text.SimpleDateFormat;
24 import java.util.List;
25 import java.util.logging.Level;
26 import org.apache.poi.ss.usermodel.*;
27 import org.apache.poi.xssf.usermodel.XSSFWorkbook;
28 import org.openide.util.NbBundle;
29 import org.openide.util.NbBundle.Messages;
34 import org.sleuthkit.datamodel.TskCoreException;
35 
36 class 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 }
List< Content > getDataSources()
Definition: Case.java:1696
void addReport(String localPath, String srcModuleName, String reportName)
Definition: Case.java:1919
synchronized static Logger getLogger(String name)
Definition: Logger.java:124

Copyright © 2012-2022 Basis Technology. Generated on: Tue Aug 1 2023
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.