Autopsy 4.22.1
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 */
19package org.sleuthkit.autopsy.timeline.actions;
20
21import org.sleuthkit.autopsy.coreutils.Desktop;
22import java.awt.image.BufferedImage;
23import java.io.IOException;
24import java.nio.file.InvalidPathException;
25import java.nio.file.Path;
26import java.nio.file.Paths;
27import java.text.SimpleDateFormat;
28import java.util.Date;
29import java.util.function.Supplier;
30import java.util.logging.Level;
31import javafx.embed.swing.SwingFXUtils;
32import javafx.scene.Node;
33import javafx.scene.control.Alert;
34import javafx.scene.control.ButtonBar;
35import javafx.scene.control.ButtonType;
36import javafx.scene.image.Image;
37import javafx.scene.image.ImageView;
38import javax.swing.JOptionPane;
39import javax.swing.SwingUtilities;
40import org.apache.commons.lang3.StringUtils;
41import org.controlsfx.control.action.Action;
42import org.openide.util.NbBundle;
43import org.openide.windows.WindowManager;
44import org.sleuthkit.autopsy.casemodule.Case;
45import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
46import org.sleuthkit.autopsy.coreutils.FileUtil;
47import org.sleuthkit.autopsy.coreutils.Logger;
48import org.sleuthkit.autopsy.timeline.TimeLineController;
49import org.sleuthkit.autopsy.timeline.snapshot.SnapShotReportWriter;
50import org.sleuthkit.datamodel.TskCoreException;
51import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
52
57public 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 addReport(String localPath, String srcModuleName, String reportName)
Definition Case.java:1929
static String escapeFileName(String fileName)
synchronized static Logger getLogger(String name)
Definition Logger.java:124
synchronized EventsModelParams getModelParams()
synchronized TimeLineTopComponent getTopComponent()
void createReport(TimeLineController controller, String reportName, Date generationDate, BufferedImage snapshot)
SaveSnapshotAsReport(TimeLineController controller, Supplier< Node > nodeSupplier)

Copyright © 2012-2024 Sleuth Kit Labs. Generated on:
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.