Autopsy  4.9.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-2018 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;
20 
21 import java.awt.event.ActionEvent;
22 import java.awt.event.ActionListener;
23 import java.awt.event.WindowAdapter;
24 import java.awt.event.WindowEvent;
25 import java.io.File;
26 import java.io.IOException;
27 import java.text.DateFormat;
28 import java.text.SimpleDateFormat;
29 import java.util.ArrayList;
30 import java.util.Collections;
31 import java.util.Date;
32 import java.util.List;
33 import java.util.Map;
34 import java.util.Map.Entry;
35 import java.util.concurrent.ExecutionException;
36 import java.util.logging.Level;
37 import javax.swing.JDialog;
38 import javax.swing.JFrame;
39 import javax.swing.SwingWorker;
40 import org.openide.filesystems.FileUtil;
41 import org.openide.util.NbBundle;
42 import org.openide.windows.WindowManager;
48 import org.sleuthkit.datamodel.AbstractFile;
49 import org.sleuthkit.datamodel.BlackboardArtifact;
50 import org.sleuthkit.datamodel.SleuthkitCase;
51 import org.sleuthkit.datamodel.TskCoreException;
52 import org.sleuthkit.datamodel.TskData;
53 
54 class ReportGenerator {
55 
56  private static final Logger logger = Logger.getLogger(ReportGenerator.class.getName());
57 
61  private ReportProgressPanel progressPanel;
62 
63  private static final String REPORT_PATH_FMT_STR = "%s" + File.separator + "%s %s %s" + File.separator;
64  private final ReportGenerationPanel reportGenerationPanel = new ReportGenerationPanel();
65 
66  static final String REPORTS_DIR = "Reports"; //NON-NLS
67 
68  private List<String> errorList;
69 
74  private void displayReportErrors() {
75  if (!errorList.isEmpty()) {
76  String errorString = "";
77  for (String error : errorList) {
78  errorString += error + "\n";
79  }
80  MessageNotifyUtil.Notify.error(
81  NbBundle.getMessage(this.getClass(), "ReportGenerator.notifyErr.errsDuringRptGen"), errorString);
82  }
83  }
84 
88  ReportGenerator() {
89  this.errorList = new ArrayList<>();
90  }
91 
92 
97  private void displayProgressPanel() {
98  final JDialog dialog = new JDialog((JFrame) WindowManager.getDefault().getMainWindow(), true);
99  dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
100  dialog.setTitle(NbBundle.getMessage(this.getClass(), "ReportGenerator.displayProgress.title.text"));
101  dialog.add(this.reportGenerationPanel);
102  dialog.pack();
103 
104  reportGenerationPanel.addCloseAction(new ActionListener() {
105  @Override
106  public void actionPerformed(ActionEvent e) {
107  dialog.dispose();
108  }
109  });
110 
111  dialog.addWindowListener(new WindowAdapter() {
112  @Override
113  public void windowClosing(WindowEvent e) {
114  reportGenerationPanel.close();
115  }
116  });
117 
118  dialog.setLocationRelativeTo(WindowManager.getDefault().getMainWindow());
119  dialog.setVisible(true);
120  }
121 
125  void generateGeneralReport(GeneralReportModule generalReportModule) throws IOException {
126  if (generalReportModule != null) {
127  String reportDir = createReportDirectory(generalReportModule);
128  setupProgressPanel(generalReportModule, reportDir);
129  ReportWorker worker = new ReportWorker(() -> {
130  generalReportModule.generateReport(reportDir, progressPanel);
131  });
132  worker.execute();
133  displayProgressPanel();
134  }
135  }
136 
145  void generateTableReport(TableReportModule tableReport, Map<BlackboardArtifact.Type, Boolean> artifactTypeSelections, Map<String, Boolean> tagNameSelections) throws IOException {
146  if (tableReport != null && null != artifactTypeSelections) {
147  String reportDir = createReportDirectory(tableReport);
148  setupProgressPanel(tableReport, reportDir);
149  ReportWorker worker = new ReportWorker(() -> {
150  tableReport.startReport(reportDir);
151  TableReportGenerator generator = new TableReportGenerator(artifactTypeSelections, tagNameSelections, progressPanel, tableReport);
152  generator.execute();
153  tableReport.endReport();
154  // finish progress, wrap up
155  progressPanel.complete(ReportProgressPanel.ReportStatus.COMPLETE);
156  errorList = generator.getErrorList();
157  });
158  worker.execute();
159  displayProgressPanel();
160  }
161  }
162 
169  void generateFileListReport(FileReportModule fileReportModule, Map<FileReportDataTypes, Boolean> enabledInfo) throws IOException {
170  if (fileReportModule != null && null != enabledInfo) {
171  String reportDir = createReportDirectory(fileReportModule);
172  List<FileReportDataTypes> enabled = new ArrayList<>();
173  for (Entry<FileReportDataTypes, Boolean> e : enabledInfo.entrySet()) {
174  if (e.getValue()) {
175  enabled.add(e.getKey());
176  }
177  }
178  setupProgressPanel(fileReportModule, reportDir);
179  ReportWorker worker = new ReportWorker(() -> {
180  if (progressPanel.getStatus() != ReportStatus.CANCELED) {
181  progressPanel.start();
182  progressPanel.updateStatusLabel(
183  NbBundle.getMessage(this.getClass(), "ReportGenerator.progress.queryingDb.text"));
184  }
185 
186  List<AbstractFile> files = getFiles();
187  int numFiles = files.size();
188  if (progressPanel.getStatus() != ReportStatus.CANCELED) {
189  fileReportModule.startReport(reportDir);
190  fileReportModule.startTable(enabled);
191  }
192  progressPanel.setIndeterminate(false);
193  progressPanel.setMaximumProgress(numFiles);
194 
195  int i = 0;
196  // Add files to report.
197  for (AbstractFile file : files) {
198  // Check to see if any reports have been cancelled.
199  if (progressPanel.getStatus() == ReportStatus.CANCELED) {
200  return;
201  } else {
202  fileReportModule.addRow(file, enabled);
203  progressPanel.increment();
204  }
205 
206  if ((i % 100) == 0) {
207  progressPanel.updateStatusLabel(
208  NbBundle.getMessage(this.getClass(), "ReportGenerator.progress.processingFile.text",
209  file.getName()));
210  }
211  i++;
212  }
213 
214  fileReportModule.endTable();
215  fileReportModule.endReport();
216  progressPanel.complete(ReportStatus.COMPLETE);
217  });
218  worker.execute();
219  displayProgressPanel();
220  }
221  }
222 
228  private List<AbstractFile> getFiles() {
229  List<AbstractFile> absFiles;
230  try {
231  SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
232  absFiles = skCase.findAllFilesWhere("meta_type != " + TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR.getValue()); //NON-NLS
233  return absFiles;
234  } catch (TskCoreException | NoCurrentCaseException ex) {
235  MessageNotifyUtil.Notify.show(
236  NbBundle.getMessage(this.getClass(), "ReportGenerator.errors.reportErrorTitle"),
237  NbBundle.getMessage(this.getClass(), "ReportGenerator.errors.reportErrorText") + ex.getLocalizedMessage(),
238  MessageNotifyUtil.MessageType.ERROR);
239  logger.log(Level.SEVERE, "failed to generate reports. Unable to get all files in the image.", ex); //NON-NLS
240  return Collections.<AbstractFile>emptyList();
241  }
242  }
243 
244  private void setupProgressPanel(ReportModule module, String reportDir) {
245  String reportFilePath = module.getRelativeFilePath();
246  if (!reportFilePath.isEmpty()) {
247  this.progressPanel = reportGenerationPanel.addReport(module.getName(), reportDir + reportFilePath);
248  } else {
249  this.progressPanel = reportGenerationPanel.addReport(module.getName(), null);
250  }
251  }
252 
253  private static String createReportDirectory(ReportModule module) throws IOException {
254  Case currentCase;
255  try {
256  currentCase = Case.getCurrentCaseThrows();
257  } catch (NoCurrentCaseException ex) {
258  throw new IOException("Exception while getting open case.", ex);
259  }
260  // Create the root reports directory path of the form: <CASE DIRECTORY>/Reports/<Case fileName> <Timestamp>/
261  DateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy-HH-mm-ss");
262  Date date = new Date();
263  String dateNoTime = dateFormat.format(date);
264  String reportPath = String.format(REPORT_PATH_FMT_STR, currentCase.getReportDirectory(), currentCase.getDisplayName(), module.getName(), dateNoTime);
265  // Create the root reports directory.
266  try {
267  FileUtil.createFolder(new File(reportPath));
268  } catch (IOException ex) {
269  throw new IOException("Failed to make report folder, unable to generate reports.", ex);
270  }
271  return reportPath;
272  }
273 
274  private class ReportWorker extends SwingWorker<Void, Void> {
275 
276  private final Runnable doInBackground;
277 
278  private ReportWorker(Runnable doInBackground) {
279  this.doInBackground = doInBackground;
280  }
281 
282  @Override
283  protected Void doInBackground() throws Exception {
284  doInBackground.run();
285  return null;
286  }
287 
288  @Override
289  protected void done() {
290  try {
291  get();
292  } catch (InterruptedException | ExecutionException ex) {
294  NbBundle.getMessage(this.getClass(), "ReportGenerator.errors.reportErrorTitle"),
295  NbBundle.getMessage(this.getClass(), "ReportGenerator.errors.reportErrorText") + ex.getLocalizedMessage(),
297  logger.log(Level.SEVERE, "failed to generate reports", ex); //NON-NLS
298  } // catch and ignore if we were cancelled
299  catch (java.util.concurrent.CancellationException ex) {
300  } finally {
301  displayReportErrors();
302  errorList.clear();
303  }
304  }
305 
306  }
307 }
static void show(String title, String message, MessageType type, ActionListener actionListener)

Copyright © 2012-2018 Basis Technology. Generated on: Tue Dec 18 2018
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.