Autopsy  4.15.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
SaveSnapshotAsReport.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2014-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.timeline.actions;
20 
21 import java.awt.Desktop;
22 import java.awt.image.BufferedImage;
23 import java.io.IOException;
24 import java.nio.file.InvalidPathException;
25 import java.nio.file.Path;
26 import java.nio.file.Paths;
27 import java.text.SimpleDateFormat;
28 import java.util.Date;
29 import java.util.function.Supplier;
30 import java.util.logging.Level;
31 import javafx.embed.swing.SwingFXUtils;
32 import javafx.scene.Node;
33 import javafx.scene.control.Alert;
34 import javafx.scene.control.ButtonBar;
35 import javafx.scene.control.ButtonType;
36 import javafx.scene.image.Image;
37 import javafx.scene.image.ImageView;
38 import javax.swing.JOptionPane;
39 import javax.swing.SwingUtilities;
40 import org.apache.commons.lang3.StringUtils;
41 import org.controlsfx.control.action.Action;
42 import org.openide.util.NbBundle;
43 import org.openide.windows.WindowManager;
50 import org.sleuthkit.datamodel.TskCoreException;
52 
57 public class SaveSnapshotAsReport extends Action {
58 
59  private static final Logger LOGGER = Logger.getLogger(SaveSnapshotAsReport.class.getName());
60  private static final Image SNAP_SHOT = new Image("org/sleuthkit/autopsy/timeline/images/image.png", 16, 16, true, true); //NON_NLS
61  private static final ButtonType OK = new ButtonType(ButtonType.OK.getText(), ButtonBar.ButtonData.CANCEL_CLOSE);
62 
63  private final Case currentCase;
64 
71  @NbBundle.Messages({
72  "Timeline.ModuleName=Timeline",
73  "SaveSnapShotAsReport.action.dialogs.title=Timeline",
74  "SaveSnapShotAsReport.action.name.text=Snapshot Report",
75  "SaveSnapShotAsReport.action.longText=Save a screen capture of the current view of the timeline as a report.",
76  "# {0} - report file path",
77  "SaveSnapShotAsReport.ReportSavedAt=Report saved at [{0}]",
78  "SaveSnapShotAsReport.Success=Success",
79  "SaveSnapShotAsReport.FailedToAddReport=Failed to add snaphot to case as a report.",
80  "# {0} - report path",
81  "SaveSnapShotAsReport.ErrorWritingReport=Error writing report to disk at {0}.",
82  "# {0} - generated default report name",
83  "SaveSnapShotAsReport.reportName.prompt=Leave empty for default report name:\n{0}.",
84  "SaveSnapShotAsReport.reportName.header=Enter a report name for the Timeline Snapshot Report.",
85  "SaveSnapShotAsReport.duplicateReportNameError.text=A report with that name already exists.",
86  "SaveSnapShotAsReport_Report_Failed=Report failed",
87  "# {0} - supplied report name",
88  "SaveSnapShotAsReport_Path_Failure_Report=Failed to create report. Supplied report name has invalid characters: {0}",
89  "# {0} - report location",
90  "SaveSnapShotAsReport_success_message=Snapshot report successfully created at location: \n\n {0}",
91  "SaveSnapShotAsReport_Open_Button=Open Report",
92  "SaveSnapShotAsReport_OK_Button=OK"
93  })
94  public SaveSnapshotAsReport(TimeLineController controller, Supplier<Node> nodeSupplier) {
95  super(Bundle.SaveSnapShotAsReport_action_name_text());
96  setLongText(Bundle.SaveSnapShotAsReport_action_longText());
97  setGraphic(new ImageView(SNAP_SHOT));
98 
99  this.currentCase = controller.getAutopsyCase();
100 
101  setEventHandler(actionEvent -> {
102  //capture generation date and use to make default report name
103  Date generationDate = new Date();
104  final String defaultReportName = FileUtil.escapeFileName(currentCase.getDisplayName() + " " + new SimpleDateFormat("MM-dd-yyyy-HH-mm-ss").format(generationDate)); //NON_NLS
105  BufferedImage snapshot = SwingFXUtils.fromFXImage(nodeSupplier.get().snapshot(null, null), null);
106 
107  SwingUtilities.invokeLater(() ->{
108  String message = String.format("%s\n\n%s", Bundle.SaveSnapShotAsReport_reportName_header(), Bundle.SaveSnapShotAsReport_reportName_prompt(defaultReportName));
109 
110  String reportName = JOptionPane.showInputDialog(SwingUtilities.windowForComponent(controller.getTopComponent()), message,
111  Bundle.SaveSnapShotAsReport_action_dialogs_title(), JOptionPane.QUESTION_MESSAGE);
112 
113  reportName = StringUtils.defaultIfBlank(reportName, defaultReportName);
114 
115  createReport(controller, reportName, generationDate, snapshot);
116  });
117  });
118  }
119 
120 
121  private void createReport(TimeLineController controller, String reportName, Date generationDate, BufferedImage snapshot) {
122  Path reportFolderPath;
123  try {
124  reportFolderPath = Paths.get(currentCase.getReportDirectory(), reportName, "Timeline Snapshot");
125  } catch (InvalidPathException ex) {
126  //notify user of report location
127  final Alert alert = new Alert(Alert.AlertType.ERROR, null, OK);
128  alert.setTitle(Bundle.SaveSnapShotAsReport_Report_Failed());
129  alert.setHeaderText(Bundle.SaveSnapShotAsReport_Path_Failure_Report(reportName));
130  alert.show();
131  return;
132  }
133  Path reportMainFilePath;
134 
135  try {
136  //generate and write report
137  reportMainFilePath = new SnapShotReportWriter(currentCase,
138  reportFolderPath,
139  reportName,
140  controller.getEventsModel().getModelParams(),
141  generationDate, snapshot).writeReport();
142  } catch (IOException ex) {
143  LOGGER.log(Level.SEVERE, "Error writing report to disk at " + reportFolderPath, ex); //NON_NLS
144  MessageNotifyUtil.Message.error( Bundle.SaveSnapShotAsReport_ErrorWritingReport(reportFolderPath));
145  return;
146  }
147 
148  try {
149  //add main file as report to case
150  Case.getCurrentCaseThrows().addReport(reportMainFilePath.toString(), Bundle.Timeline_ModuleName(), reportName);
151  } catch (TskCoreException | NoCurrentCaseException ex) {
152  LOGGER.log(Level.WARNING, "Failed to add " + reportMainFilePath.toString() + " to case as a report", ex); //NON_NLS
153  MessageNotifyUtil.Message.error(Bundle.SaveSnapShotAsReport_FailedToAddReport());
154  return;
155  }
156 
157  Object[] options = { Bundle.SaveSnapShotAsReport_Open_Button(),
158  Bundle.SaveSnapShotAsReport_OK_Button()};
159 
160  int result = JOptionPane.showOptionDialog(SwingUtilities.windowForComponent(controller.getTopComponent()),
161  Bundle.SaveSnapShotAsReport_success_message(reportMainFilePath),
162  Bundle.SaveSnapShotAsReport_action_dialogs_title(),
163  JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE, null,
164  options, options[0]);
165 
166  if(result == 0) {
167  final OpenReportAction openReportAction = new OpenReportAction(reportMainFilePath);
168  openReportAction.handle(null);
169  }
170  }
171 
175  @NbBundle.Messages({
176  "OpenReportAction.DisplayName=Open Report",
177  "OpenReportAction.NoAssociatedEditorMessage=There is no associated editor for reports of this type or the associated application failed to launch.",
178  "OpenReportAction.MessageBoxTitle=Open Report Failure",
179  "OpenReportAction.NoOpenInEditorSupportMessage=This platform (operating system) does not support opening a file in an editor this way.",
180  "OpenReportAction.MissingReportFileMessage=The report file no longer exists.",
181  "OpenReportAction.ReportFileOpenPermissionDeniedMessage=Permission to open the report file was denied."})
182  private class OpenReportAction extends Action {
183 
184  OpenReportAction(Path reportHTMLFIle) {
185  super(Bundle.OpenReportAction_DisplayName());
186  setEventHandler(actionEvent -> {
187  try {
188  Desktop.getDesktop().open(reportHTMLFIle.toFile());
189  } catch (IOException ex) {
190  JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
191  Bundle.OpenReportAction_NoAssociatedEditorMessage(),
192  Bundle.OpenReportAction_MessageBoxTitle(),
193  JOptionPane.ERROR_MESSAGE);
194  } catch (UnsupportedOperationException ex) {
195  JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
196  Bundle.OpenReportAction_NoOpenInEditorSupportMessage(),
197  Bundle.OpenReportAction_MessageBoxTitle(),
198  JOptionPane.ERROR_MESSAGE);
199  } catch (IllegalArgumentException ex) {
200  JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
201  Bundle.OpenReportAction_MissingReportFileMessage(),
202  Bundle.OpenReportAction_MessageBoxTitle(),
203  JOptionPane.ERROR_MESSAGE);
204  } catch (SecurityException ex) {
205  JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
206  Bundle.OpenReportAction_ReportFileOpenPermissionDeniedMessage(),
207  Bundle.OpenReportAction_MessageBoxTitle(),
208  JOptionPane.ERROR_MESSAGE);
209  }
210  });
211  }
212  }
213 }
void createReport(TimeLineController controller, String reportName, Date generationDate, BufferedImage snapshot)
synchronized EventsModelParams getModelParams()
void addReport(String localPath, String srcModuleName, String reportName)
Definition: Case.java:1661
SaveSnapshotAsReport(TimeLineController controller, Supplier< Node > nodeSupplier)
synchronized TimeLineTopComponent getTopComponent()
static String escapeFileName(String fileName)
Definition: FileUtil.java:169
synchronized static Logger getLogger(String name)
Definition: Logger.java:124

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