19package org.sleuthkit.autopsy.timeline.actions;
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;
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;
60 private static final Image
SNAP_SHOT =
new Image(
"org/sleuthkit/autopsy/timeline/images/image.png", 16, 16,
true,
true);
61 private static final ButtonType
OK =
new ButtonType(ButtonType.OK.getText(), ButtonBar.ButtonData.CANCEL_CLOSE);
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"
95 super(Bundle.SaveSnapShotAsReport_action_name_text());
96 setLongText(Bundle.SaveSnapShotAsReport_action_longText());
101 setEventHandler(actionEvent -> {
103 Date generationDate =
new Date();
104 final String defaultReportName =
FileUtil.
escapeFileName(
currentCase.getDisplayName() +
" " +
new SimpleDateFormat(
"MM-dd-yyyy-HH-mm-ss").format(generationDate));
105 BufferedImage
snapshot = SwingFXUtils.fromFXImage(nodeSupplier.get().snapshot(
null,
null),
null);
107 SwingUtilities.invokeLater(() ->{
108 String message = String.format(
"%s\n\n%s", Bundle.SaveSnapShotAsReport_reportName_header(), Bundle.SaveSnapShotAsReport_reportName_prompt(defaultReportName));
110 String reportName = JOptionPane.showInputDialog(SwingUtilities.windowForComponent(controller.
getTopComponent()), message,
111 Bundle.SaveSnapShotAsReport_action_dialogs_title(), JOptionPane.QUESTION_MESSAGE);
113 if (reportName !=
null) {
114 reportName = StringUtils.defaultIfBlank(reportName, defaultReportName);
124 Path reportFolderPath;
126 reportFolderPath = Paths.get(
currentCase.getReportDirectory(), reportName,
"Timeline Snapshot");
127 }
catch (InvalidPathException ex) {
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));
135 Path reportMainFilePath;
144 }
catch (IOException ex) {
145 LOGGER.log(Level.SEVERE,
"Error writing report to disk at " + reportFolderPath, ex);
154 LOGGER.log(Level.WARNING,
"Failed to add " + reportMainFilePath.toString() +
" to case as a report", ex);
159 Object[] options = { Bundle.SaveSnapShotAsReport_Open_Button(),
160 Bundle.SaveSnapShotAsReport_OK_Button()};
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]);
170 openReportAction.handle(
null);
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 {
186 OpenReportAction(Path reportHTMLFIle) {
187 super(Bundle.OpenReportAction_DisplayName());
188 setEventHandler(actionEvent -> {
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);
static Case getCurrentCaseThrows()
void addReport(String localPath, String srcModuleName, String reportName)
static Desktop getDesktop()
static String escapeFileName(String fileName)
synchronized static Logger getLogger(String name)
static void error(String message)
synchronized EventsModelParams getModelParams()
synchronized TimeLineTopComponent getTopComponent()
EventsModel getEventsModel()
void createReport(TimeLineController controller, String reportName, Date generationDate, BufferedImage snapshot)
SaveSnapshotAsReport(TimeLineController controller, Supplier< Node > nodeSupplier)
static final ButtonType OK
static final Image SNAP_SHOT
static final Logger LOGGER