Autopsy  4.20.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  // if reportName is null then cancel was selected, if reportName is empty then ok was selected and no report name specified
113  if (reportName != null) {
114  reportName = StringUtils.defaultIfBlank(reportName, defaultReportName);
115 
116  createReport(controller, reportName, generationDate, snapshot);
117  }
118  });
119  });
120  }
121 
122 
123  private void createReport(TimeLineController controller, String reportName, Date generationDate, BufferedImage snapshot) {
124  Path reportFolderPath;
125  try {
126  reportFolderPath = Paths.get(currentCase.getReportDirectory(), reportName, "Timeline Snapshot");
127  } catch (InvalidPathException ex) {
128  //notify user of report location
129  final Alert alert = new Alert(Alert.AlertType.ERROR, null, OK);
130  alert.setTitle(Bundle.SaveSnapShotAsReport_Report_Failed());
131  alert.setHeaderText(Bundle.SaveSnapShotAsReport_Path_Failure_Report(reportName));
132  alert.show();
133  return;
134  }
135  Path reportMainFilePath;
136 
137  try {
138  //generate and write report
139  reportMainFilePath = new SnapShotReportWriter(currentCase,
140  reportFolderPath,
141  reportName,
142  controller.getEventsModel().getModelParams(),
143  generationDate, snapshot).writeReport();
144  } catch (IOException ex) {
145  LOGGER.log(Level.SEVERE, "Error writing report to disk at " + reportFolderPath, ex); //NON_NLS
146  MessageNotifyUtil.Message.error( Bundle.SaveSnapShotAsReport_ErrorWritingReport(reportFolderPath));
147  return;
148  }
149 
150  try {
151  //add main file as report to case
152  Case.getCurrentCaseThrows().addReport(reportMainFilePath.toString(), Bundle.Timeline_ModuleName(), reportName);
153  } catch (TskCoreException | NoCurrentCaseException ex) {
154  LOGGER.log(Level.WARNING, "Failed to add " + reportMainFilePath.toString() + " to case as a report", ex); //NON_NLS
155  MessageNotifyUtil.Message.error(Bundle.SaveSnapShotAsReport_FailedToAddReport());
156  return;
157  }
158 
159  Object[] options = { Bundle.SaveSnapShotAsReport_Open_Button(),
160  Bundle.SaveSnapShotAsReport_OK_Button()};
161 
162  int result = JOptionPane.showOptionDialog(SwingUtilities.windowForComponent(controller.getTopComponent()),
163  Bundle.SaveSnapShotAsReport_success_message(reportMainFilePath),
164  Bundle.SaveSnapShotAsReport_action_dialogs_title(),
165  JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE, null,
166  options, options[0]);
167 
168  if(result == 0) {
169  final OpenReportAction openReportAction = new OpenReportAction(reportMainFilePath);
170  openReportAction.handle(null);
171  }
172  }
173 
177  @NbBundle.Messages({
178  "OpenReportAction.DisplayName=Open Report",
179  "OpenReportAction.NoAssociatedEditorMessage=There is no associated editor for reports of this type or the associated application failed to launch.",
180  "OpenReportAction.MessageBoxTitle=Open Report Failure",
181  "OpenReportAction.NoOpenInEditorSupportMessage=This platform (operating system) does not support opening a file in an editor this way.",
182  "OpenReportAction.MissingReportFileMessage=The report file no longer exists.",
183  "OpenReportAction.ReportFileOpenPermissionDeniedMessage=Permission to open the report file was denied."})
184  private class OpenReportAction extends Action {
185 
186  OpenReportAction(Path reportHTMLFIle) {
187  super(Bundle.OpenReportAction_DisplayName());
188  setEventHandler(actionEvent -> {
189  try {
190  Desktop.getDesktop().open(reportHTMLFIle.toFile());
191  } catch (IOException ex) {
192  JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
193  Bundle.OpenReportAction_NoAssociatedEditorMessage(),
194  Bundle.OpenReportAction_MessageBoxTitle(),
195  JOptionPane.ERROR_MESSAGE);
196  } catch (UnsupportedOperationException ex) {
197  JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
198  Bundle.OpenReportAction_NoOpenInEditorSupportMessage(),
199  Bundle.OpenReportAction_MessageBoxTitle(),
200  JOptionPane.ERROR_MESSAGE);
201  } catch (IllegalArgumentException ex) {
202  JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
203  Bundle.OpenReportAction_MissingReportFileMessage(),
204  Bundle.OpenReportAction_MessageBoxTitle(),
205  JOptionPane.ERROR_MESSAGE);
206  } catch (SecurityException ex) {
207  JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
208  Bundle.OpenReportAction_ReportFileOpenPermissionDeniedMessage(),
209  Bundle.OpenReportAction_MessageBoxTitle(),
210  JOptionPane.ERROR_MESSAGE);
211  }
212  });
213  }
214  }
215 }
void createReport(TimeLineController controller, String reportName, Date generationDate, BufferedImage snapshot)
synchronized EventsModelParams getModelParams()
void addReport(String localPath, String srcModuleName, String reportName)
Definition: Case.java:1919
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-2022 Basis Technology. Generated on: Tue Aug 1 2023
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.