Autopsy  4.14.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
ReportGenerator.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2013-2019 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.infrastructure;
20 
27 import java.awt.event.ActionEvent;
28 import java.awt.event.ActionListener;
29 import java.awt.event.WindowAdapter;
30 import java.awt.event.WindowEvent;
31 import java.io.File;
32 import java.io.IOException;
33 import java.text.DateFormat;
34 import java.text.SimpleDateFormat;
35 import java.util.ArrayList;
36 import java.util.Collections;
37 import java.util.Date;
38 import java.util.HashMap;
39 import java.util.List;
40 import java.util.Map;
41 import java.util.Map.Entry;
42 import java.util.logging.Level;
43 import javax.swing.JDialog;
44 import org.openide.filesystems.FileUtil;
45 import org.openide.util.NbBundle;
46 import org.openide.windows.WindowManager;
53 import org.sleuthkit.datamodel.AbstractFile;
54 import org.sleuthkit.datamodel.SleuthkitCase;
55 import org.sleuthkit.datamodel.TskCoreException;
56 import org.sleuthkit.datamodel.TskData;
57 
62 public class ReportGenerator {
63 
64  private static final Logger logger = Logger.getLogger(ReportGenerator.class.getName());
66  private final ReportGenerationPanel reportGenerationPanel;
67  private static final String REPORT_PATH_FMT_STR = "%s" + File.separator + "%s %s %s" + File.separator;
68  private final String configName;
69  private static final String REPORTS_DIR = "Reports"; //NON-NLS
70  private List<String> errorList = new ArrayList<>();
71 
78  public static String getReportsDirectory() {
79  return REPORTS_DIR;
80  }
81 
86  private void displayReportErrors() {
87  if (!errorList.isEmpty()) {
88  String errorString = "";
89  for (String error : errorList) {
90  errorString += error + "\n";
91  }
92  progressIndicator.updateStatusLabel(errorString);
93  }
94  }
95 
104  public ReportGenerator(String configName, ReportProgressIndicator progressIndicator) {
105  this.progressIndicator = progressIndicator;
106  this.reportGenerationPanel = null;
107  this.configName = configName;
108  }
109 
118  ReportGenerator(String configName, ReportGenerationPanel panel) {
119  this.reportGenerationPanel = panel;
120  this.progressIndicator = panel.getProgressPanel();
121  this.configName = configName;
122  }
123 
128  public void generateReports() {
129  // load all report modules
130  Map<String, ReportModule> modules = new HashMap<>();
131  for (TableReportModule module : ReportModuleLoader.getTableReportModules()) {
132  modules.put(FactoryClassNameNormalizer.normalize(module.getClass().getCanonicalName()), module);
133  }
134 
135  for (GeneralReportModule module : ReportModuleLoader.getGeneralReportModules()) {
136  modules.put(FactoryClassNameNormalizer.normalize(module.getClass().getCanonicalName()), module);
137  }
138 
139  for (FileReportModule module : ReportModuleLoader.getFileReportModules()) {
140  modules.put(FactoryClassNameNormalizer.normalize(module.getClass().getCanonicalName()), module);
141  }
142 
143  // special case for PortableCaseReportModule
144  modules.put(FactoryClassNameNormalizer.normalize(PortableCaseReportModule.class.getCanonicalName()), new PortableCaseReportModule());
145 
146  generateReports(modules);
147  }
148 
156  public void generateReports(Map<String, ReportModule> modules) {
157 
158  if (modules == null || modules.isEmpty()) {
159  logger.log(Level.SEVERE, "No report modules found");
160  progressIndicator.updateStatusLabel("No report modules found. Exiting");
161  return;
162  }
163 
164  ReportingConfig config = null;
165  try {
166  config = ReportingConfigLoader.loadConfig(configName);
167  } catch (ReportConfigException ex) {
168  logger.log(Level.SEVERE, "Unable to load reporting configuration " + configName + ". Exiting", ex);
169  progressIndicator.updateStatusLabel("Unable to load reporting configuration " + configName + ". Exiting");
170  return;
171  }
172 
173  if (config == null) {
174  logger.log(Level.SEVERE, "Unable to load reporting configuration {0}. Exiting", configName);
175  progressIndicator.updateStatusLabel("Unable to load reporting configuration " + configName + ". Exiting");
176  return;
177  }
178 
179  try {
180  // generate reports for enabled modules
181  for (Map.Entry<String, ReportModuleConfig> entry : config.getModuleConfigs().entrySet()) {
182  ReportModuleConfig moduleConfig = entry.getValue();
183  if (moduleConfig == null || !moduleConfig.isEnabled()) {
184  continue;
185  }
186 
187  // found enabled module
188  String moduleName = entry.getKey();
189  ReportModule module = modules.get(moduleName);
190  if (module == null) {
191  logger.log(Level.SEVERE, "Report module {0} not found", moduleName);
192  progressIndicator.updateStatusLabel("Report module " + moduleName + " not found");
193  continue;
194  }
195 
196  // get persisted module settings
197  ReportModuleSettings settings = moduleConfig.getModuleSettings();
198  if (settings == null) {
199  // use default configuration for this module
200  settings = module.getDefaultConfiguration();
201  }
202 
203  // set module configuration
204  module.setConfiguration(settings);
205 
206  try {
207  // generate report according to report module type
208  if (module instanceof GeneralReportModule) {
209 
210  // generate report
211  generateGeneralReport((GeneralReportModule) module);
212 
213  } else if (module instanceof TableReportModule) {
214 
215  // get table report settings
216  TableReportSettings tableSettings = config.getTableReportSettings();
217  if (tableSettings == null) {
218  logger.log(Level.SEVERE, "No table report settings for report module {0}", moduleName);
219  progressIndicator.updateStatusLabel("No table report settings for report module " + moduleName);
220  continue;
221  }
222 
223  generateTableReport((TableReportModule) module, tableSettings); //NON-NLS
224 
225  } else if (module instanceof FileReportModule) {
226 
227  // get file report settings
228  FileReportSettings fileSettings = config.getFileReportSettings();
229  if (fileSettings == null) {
230  logger.log(Level.SEVERE, "No file report settings for report module {0}", moduleName);
231  progressIndicator.updateStatusLabel("No file report settings for report module " + moduleName);
232  continue;
233  }
234 
235  generateFileListReport((FileReportModule) module, fileSettings); //NON-NLS
236 
237  } else if (module instanceof PortableCaseReportModule) {
238  // get report settings
239  if (settings instanceof NoReportModuleSettings) {
240  settings = new PortableCaseReportModuleSettings();
241  } else if (!(settings instanceof PortableCaseReportModuleSettings)) {
242  logger.log(Level.SEVERE, "Invalid settings for report module {0}", moduleName);
243  progressIndicator.updateStatusLabel("Invalid settings for report module " + moduleName);
244  continue;
245  }
246 
247  generatePortableCaseReport((PortableCaseReportModule) module, (PortableCaseReportModuleSettings) settings);
248 
249  } else {
250  logger.log(Level.SEVERE, "Report module {0} has unsupported report module type", moduleName);
251  progressIndicator.updateStatusLabel("Report module " + moduleName + " has unsupported report module type");
252  }
253  } catch (IOException e) {
254  logger.log(Level.SEVERE, "Exception while running report module {0}: {1}", new Object[]{moduleName, e.getMessage()});
255  progressIndicator.updateStatusLabel("Exception while running report module " + moduleName);
256  }
257  }
258  } finally {
260  errorList.clear();
261  }
262  }
263 
268  void displayProgressPanel() {
269  if (reportGenerationPanel == null) {
270  return;
271  }
272 
273  final JDialog dialog = new JDialog(WindowManager.getDefault().getMainWindow(), true);
274  dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
275  dialog.setTitle(NbBundle.getMessage(this.getClass(), "ReportGenerator.displayProgress.title.text"));
276  dialog.add(this.reportGenerationPanel);
277  dialog.pack();
278 
279  reportGenerationPanel.addCloseAction(new ActionListener() {
280  @Override
281  public void actionPerformed(ActionEvent e) {
282  dialog.dispose();
283  }
284  });
285 
286  dialog.addWindowListener(new WindowAdapter() {
287  @Override
288  public void windowClosing(WindowEvent e) {
289  reportGenerationPanel.close();
290  }
291  });
292 
293  dialog.setLocationRelativeTo(WindowManager.getDefault().getMainWindow());
294  dialog.setVisible(true);
295  }
296 
300  private void generateGeneralReport(GeneralReportModule generalReportModule) throws IOException {
301  if (generalReportModule != null) {
302  String reportDir = createReportDirectory(generalReportModule);
303  setupProgressPanel(generalReportModule, reportDir);
304  generalReportModule.generateReport(reportDir, progressIndicator);
305  }
306  }
307 
314  private void generateTableReport(TableReportModule tableReport, TableReportSettings tableReportSettings) throws IOException {
315  if (tableReport != null && tableReportSettings != null && null != tableReportSettings.getArtifactSelections()) {
316  String reportDir = createReportDirectory(tableReport);
317  setupProgressPanel(tableReport, reportDir);
318  tableReport.startReport(reportDir);
319  TableReportGenerator generator = new TableReportGenerator(tableReportSettings, progressIndicator, tableReport);
320  generator.execute();
321  tableReport.endReport();
322  // finish progress, wrap up
324  errorList = generator.getErrorList();
325  }
326  }
327 
334  private void generateFileListReport(FileReportModule fileReportModule, FileReportSettings fileReportSettings) throws IOException {
335  if (fileReportModule != null && fileReportSettings != null && null != fileReportSettings.getFileProperties()) {
336  String reportDir = createReportDirectory(fileReportModule);
337  List<FileReportDataTypes> enabled = new ArrayList<>();
338  for (Entry<FileReportDataTypes, Boolean> e : fileReportSettings.getFileProperties().entrySet()) {
339  if (e.getValue()) {
340  enabled.add(e.getKey());
341  }
342  }
343  setupProgressPanel(fileReportModule, reportDir);
344  if (progressIndicator.getStatus() != ReportStatus.CANCELED) {
345  progressIndicator.start();
346  progressIndicator.updateStatusLabel(
347  NbBundle.getMessage(this.getClass(), "ReportGenerator.progress.queryingDb.text"));
348  }
349 
350  List<AbstractFile> files = getFiles();
351  int numFiles = files.size();
352  if (progressIndicator.getStatus() != ReportStatus.CANCELED) {
353  fileReportModule.startReport(reportDir);
354  fileReportModule.startTable(enabled);
355  }
356  progressIndicator.setIndeterminate(false);
357  progressIndicator.setMaximumProgress(numFiles);
358 
359  int i = 0;
360  // Add files to report.
361  for (AbstractFile file : files) {
362  // Check to see if any reports have been cancelled.
363  if (progressIndicator.getStatus() == ReportStatus.CANCELED) {
364  return;
365  } else {
366  fileReportModule.addRow(file, enabled);
367  progressIndicator.increment();
368  }
369 
370  if ((i % 100) == 0) {
371  progressIndicator.updateStatusLabel(
372  NbBundle.getMessage(this.getClass(), "ReportGenerator.progress.processingFile.text",
373  file.getName()));
374  }
375  i++;
376  }
377 
378  fileReportModule.endTable();
379  fileReportModule.endReport();
380  progressIndicator.complete(ReportStatus.COMPLETE);
381  }
382  }
383 
387  private void generatePortableCaseReport(PortableCaseReportModule portableCaseReportModule, PortableCaseReportModuleSettings settings) throws IOException {
388  if (portableCaseReportModule != null) {
389  String reportDir = createReportDirectory(portableCaseReportModule);
390  setupProgressPanel(portableCaseReportModule, reportDir);
391  portableCaseReportModule.generateReport(reportDir, settings, progressIndicator);
392  }
393  }
394 
400  private List<AbstractFile> getFiles() {
401  List<AbstractFile> absFiles;
402  try {
403  SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
404  absFiles = skCase.findAllFilesWhere("meta_type != " + TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR.getValue()); //NON-NLS
405  return absFiles;
406  } catch (TskCoreException | NoCurrentCaseException ex) {
407  progressIndicator.updateStatusLabel(NbBundle.getMessage(this.getClass(), "ReportGenerator.errors.reportErrorText") + ex.getLocalizedMessage());
408  logger.log(Level.SEVERE, "failed to generate reports. Unable to get all files in the image.", ex); //NON-NLS
409  return Collections.<AbstractFile>emptyList();
410  }
411  }
412 
413  private void setupProgressPanel(ReportModule module, String reportDir) {
414  if (reportGenerationPanel != null) {
415  String reportFilePath = module.getRelativeFilePath();
416  if (reportFilePath == null) {
417  reportGenerationPanel.addReport(module.getName(), null);
418  } else if (reportFilePath.isEmpty()) {
419  reportGenerationPanel.addReport(module.getName(), reportDir);
420  } else {
421  reportGenerationPanel.addReport(module.getName(), reportDir + reportFilePath);
422  }
423  }
424  }
425 
426  private static String createReportDirectory(ReportModule module) throws IOException {
427  Case currentCase;
428  try {
429  currentCase = Case.getCurrentCaseThrows();
430  } catch (NoCurrentCaseException ex) {
431  throw new IOException("Exception while getting open case.", ex);
432  }
433  // Create the root reports directory path of the form: <CASE DIRECTORY>/Reports/<Case fileName> <Timestamp>/
434  DateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy-HH-mm-ss");
435  Date date = new Date();
436  String dateNoTime = dateFormat.format(date);
437  String reportPath = String.format(REPORT_PATH_FMT_STR, currentCase.getReportDirectory(), currentCase.getDisplayName(), module.getName(), dateNoTime);
438  // Create the root reports directory.
439  try {
440  FileUtil.createFolder(new File(reportPath));
441  } catch (IOException ex) {
442  throw new IOException("Failed to make report folder, unable to generate reports.", ex);
443  }
444  return reportPath;
445  }
446 }
void generatePortableCaseReport(PortableCaseReportModule portableCaseReportModule, PortableCaseReportModuleSettings settings)
void generateGeneralReport(GeneralReportModule generalReportModule)
void generateTableReport(TableReportModule tableReport, TableReportSettings tableReportSettings)
void generateFileListReport(FileReportModule fileReportModule, FileReportSettings fileReportSettings)
default ReportModuleSettings getDefaultConfiguration()
ReportGenerator(String configName, ReportProgressIndicator progressIndicator)
default void setConfiguration(ReportModuleSettings settings)
void generateReports(Map< String, ReportModule > modules)
void setupProgressPanel(ReportModule module, String reportDir)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124

Copyright © 2012-2020 Basis Technology. Generated on: Wed Apr 8 2020
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.