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

Copyright © 2012-2019 Basis Technology. Generated on: Tue Jan 7 2020
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.