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

Copyright © 2012-2021 Basis Technology. Generated on: Thu Sep 30 2021
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.