Autopsy 4.22.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
Reports.java
Go to the documentation of this file.
1/*
2 * Autopsy Forensic Browser
3 *
4 * Copyright 2011-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.datamodel;
20
21import java.awt.event.ActionEvent;
22import java.beans.PropertyChangeEvent;
23import java.io.File;
24import java.text.SimpleDateFormat;
25import java.util.ArrayList;
26import java.util.Arrays;
27import java.util.Collection;
28import java.util.EnumSet;
29import java.util.List;
30import java.util.Set;
31import java.util.logging.Level;
32import javax.swing.AbstractAction;
33import javax.swing.Action;
34import javax.swing.JOptionPane;
35import org.openide.nodes.ChildFactory;
36import org.openide.nodes.Children;
37import org.openide.nodes.Node;
38import org.openide.nodes.Sheet;
39import org.openide.util.NbBundle;
40import org.openide.util.Utilities;
41import org.openide.util.lookup.Lookups;
42import org.sleuthkit.autopsy.casemodule.Case;
43import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
44import org.sleuthkit.autopsy.coreutils.Logger;
45import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
46import org.sleuthkit.autopsy.directorytree.ExternalViewerAction;
47import org.sleuthkit.datamodel.Report;
48import org.sleuthkit.datamodel.TskCoreException;
49
53public final class Reports implements AutopsyVisitableItem {
54
55 private static final SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
56
57 @Override
58 public <T> T accept(AutopsyItemVisitor<T> visitor) {
59 // CreateAutopsyNodeVisitor.visit() constructs a ReportsListNode.
60 return visitor.visit(this);
61 }
62
66 public static final class ReportsListNode extends DisplayableItemNode {
67
68 private static final long serialVersionUID = 1L;
69 private static final String DISPLAY_NAME = NbBundle.getMessage(ReportsListNode.class, "ReportsListNode.displayName");
70 private static final String ICON_PATH = "org/sleuthkit/autopsy/images/report_16.png"; //NON-NLS
71
72 public ReportsListNode() {
73 super(Children.create(new ReportNodeFactory(), true));
74 setName(DISPLAY_NAME);
75 setDisplayName(DISPLAY_NAME);
76 this.setIconBaseWithExtension(ICON_PATH);
77 }
78
79 @Override
80 public boolean isLeafTypeNode() {
81 return true;
82 }
83
84 @Override
85 public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
86 // - GetPopupActionsDisplayableItemNodeVisitor.visit() returns null.
87 // - GetPreferredActionsDisplayableItemNodeVisitor.visit() returns null.
88 // - IsLeafItemVisitor.visit() returns false.
89 // - ShowItemVisitor.visit() returns true.
90 return visitor.visit(this);
91 }
92
93 @Override
94 public String getItemType() {
95 return getClass().getName();
96 }
97 }
98
103 private static final class ReportNodeFactory extends ChildFactory<Report> {
104
106
107 ReportNodeFactory() {
108 Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, (PropertyChangeEvent evt) -> {
109 String eventType = evt.getPropertyName();
110 if (eventType.equals(Case.Events.REPORT_ADDED.toString()) || eventType.equals(Case.Events.REPORT_DELETED.toString())) {
117 try {
119 ReportNodeFactory.this.refresh(true);
120 } catch (NoCurrentCaseException notUsed) {
124 }
125 }
126 });
127 }
128
129 @Override
130 protected boolean createKeys(List<Report> keys) {
131 try {
132 keys.addAll(Case.getCurrentCaseThrows().getAllReports());
133 } catch (TskCoreException | NoCurrentCaseException ex) {
134 Logger.getLogger(Reports.ReportNodeFactory.class.getName()).log(Level.SEVERE, "Failed to get reports", ex); //NON-NLS
135 }
136 return true;
137 }
138
139 @Override
140 protected Node createNodeForKey(Report key) {
141 return new ReportNode(key);
142 }
143 }
144
149 public static final class ReportNode extends DisplayableItemNode {
150
151 private static final long serialVersionUID = 1L;
152 private static final String ICON_PATH = "org/sleuthkit/autopsy/images/report_16.png"; //NON-NLS
153 private final Report report;
154
155 ReportNode(Report report) {
156 super(Children.LEAF, Lookups.fixed(report));
157 this.report = report;
158 super.setName(this.report.getSourceModuleName());
159 super.setDisplayName(this.report.getSourceModuleName());
160 this.setIconBaseWithExtension(ICON_PATH);
161 }
162
163 @Override
164 public boolean isLeafTypeNode() {
165 return true;
166 }
167
168 @Override
169 public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
170 // - GetPopupActionsDisplayableItemNodeVisitor.visit() calls getActions().
171 // - GetPreferredActionsDisplayableItemNodeVisitor.visit() calls getPreferredAction().
172 // - IsLeafItemVisitor.visit() returns true.
173 // - ShowItemVisitor.visit() returns true.
174 return visitor.visit(this);
175 }
176
177 @Override
178 protected Sheet createSheet() {
179 Sheet sheet = super.createSheet();
180 Sheet.Set propertiesSet = sheet.get(Sheet.PROPERTIES);
181 if (propertiesSet == null) {
182 propertiesSet = Sheet.createPropertiesSet();
183 sheet.put(propertiesSet);
184 }
185 propertiesSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ReportNode.sourceModuleNameProperty.name"),
186 NbBundle.getMessage(this.getClass(), "ReportNode.sourceModuleNameProperty.displayName"),
187 NbBundle.getMessage(this.getClass(), "ReportNode.sourceModuleNameProperty.desc"),
188 this.report.getSourceModuleName()));
189 propertiesSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ReportNode.reportNameProperty.name"),
190 NbBundle.getMessage(this.getClass(), "ReportNode.reportNameProperty.displayName"),
191 NbBundle.getMessage(this.getClass(), "ReportNode.reportNameProperty.desc"),
192 this.report.getReportName()));
193 propertiesSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ReportNode.createdTimeProperty.name"),
194 NbBundle.getMessage(this.getClass(), "ReportNode.createdTimeProperty.displayName"),
195 NbBundle.getMessage(this.getClass(), "ReportNode.createdTimeProperty.desc"),
196 dateFormatter.format(new java.util.Date(this.report.getCreatedTime() * 1000))));
197 propertiesSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ReportNode.pathProperty.name"),
198 NbBundle.getMessage(this.getClass(), "ReportNode.pathProperty.displayName"),
199 NbBundle.getMessage(this.getClass(), "ReportNode.pathProperty.desc"),
200 this.report.getPath()));
201 return sheet;
202 }
203
204 @Override
205 public Action[] getActions(boolean popup) {
206 List<Action> actions = new ArrayList<>();
207 actions.add(new OpenReportAction());
209 actions.add(null);
210 actions.addAll(Arrays.asList(super.getActions(true)));
211 return actions.toArray(new Action[actions.size()]);
212 }
213
214 @Override
215 public AbstractAction getPreferredAction() {
216 return new OpenReportAction();
217 }
218
219 @Override
220 public String getItemType() {
221 return getClass().getName();
222 }
223
224 private static class DeleteReportAction extends AbstractAction {
225
226 private static final long serialVersionUID = 1L;
228
229 // This class is a singleton to support multi-selection of nodes,
230 // since org.openide.nodes.NodeOp.findActions(Node[] nodes) will
231 // only pick up an Action if every node in the array returns a
232 // reference to the same action object from Node.getActions(boolean).
234 if (instance == null) {
236 }
237 if (Utilities.actionsGlobalContext().lookupAll(Report.class).size() == 1) {
238 instance.putValue(Action.NAME, NbBundle.getMessage(Reports.class, "DeleteReportAction.actionDisplayName.singleReport"));
239 } else {
240 instance.putValue(Action.NAME, NbBundle.getMessage(Reports.class, "DeleteReportAction.actionDisplayName.multipleReports"));
241 }
242 return instance;
243 }
244
250 }
251
252 @NbBundle.Messages({
253 "DeleteReportAction.showConfirmDialog.single.explanation=The report will remain on disk.",
254 "DeleteReportAction.showConfirmDialog.multiple.explanation=The reports will remain on disk.",
255 "DeleteReportAction.showConfirmDialog.errorMsg=An error occurred while deleting the reports."})
256 @Override
257 public void actionPerformed(ActionEvent e) {
258 Collection<? extends Report> selectedReportsCollection = Utilities.actionsGlobalContext().lookupAll(Report.class);
259 String message = selectedReportsCollection.size() > 1
260 ? NbBundle.getMessage(Reports.class, "DeleteReportAction.actionPerformed.showConfirmDialog.multiple.msg", selectedReportsCollection.size())
261 : NbBundle.getMessage(Reports.class, "DeleteReportAction.actionPerformed.showConfirmDialog.single.msg");
262 String explanation = selectedReportsCollection.size() > 1
263 ? Bundle.DeleteReportAction_showConfirmDialog_multiple_explanation()
264 : Bundle.DeleteReportAction_showConfirmDialog_single_explanation();
265 Object[] jOptionPaneContent = {message, explanation};
266 if (JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(null, jOptionPaneContent,
267 NbBundle.getMessage(Reports.class, "DeleteReportAction.actionPerformed.showConfirmDialog.title"),
268 JOptionPane.YES_NO_OPTION)) {
269 try {
270 Case.getCurrentCaseThrows().deleteReports(selectedReportsCollection);
271 } catch (TskCoreException | NoCurrentCaseException ex) {
272 Logger.getLogger(DeleteReportAction.class.getName()).log(Level.SEVERE, "Error deleting reports", ex); // NON-NLS
273 MessageNotifyUtil.Message.error(Bundle.DeleteReportAction_showConfirmDialog_errorMsg());
274 }
275 }
276 }
277 }
278
279 private final class OpenReportAction extends AbstractAction {
280
281 private static final long serialVersionUID = 1L;
282
284 super(NbBundle.getMessage(OpenReportAction.class, "OpenReportAction.actionDisplayName"));
285 }
286
287 @Override
288 public void actionPerformed(ActionEvent e) {
289 String reportPath = ReportNode.this.report.getPath();
290
291 if (reportPath.toLowerCase().startsWith("http")) {
292 ExternalViewerAction.openURL(reportPath);
293 }
294 else {
295 String extension = "";
296 int extPosition = reportPath.lastIndexOf('.');
297 if (extPosition != -1) {
298 extension = reportPath.substring(extPosition, reportPath.length()).toLowerCase();
299 }
300
301 ExternalViewerAction.openFile("", extension, new File(reportPath));
302 }
303 }
304 }
305 }
306}
void deleteReports(Collection<? extends Report > reports)
Definition Case.java:1986
static void addEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
Definition Case.java:712
synchronized static Logger getLogger(String name)
Definition Logger.java:124
static final Set< Case.Events > CASE_EVENTS_OF_INTEREST
Definition Reports.java:105
static final SimpleDateFormat dateFormatter
Definition Reports.java:55
static void openFile(String mimeType, String ext, File file)

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