19 package org.sleuthkit.autopsy.contentviewers.artifactviewers;
21 import java.awt.Component;
22 import java.awt.Dimension;
23 import java.awt.GridBagConstraints;
24 import java.awt.GridBagLayout;
25 import java.awt.Insets;
26 import java.awt.Toolkit;
27 import java.awt.datatransfer.StringSelection;
28 import java.awt.event.ActionEvent;
29 import java.awt.event.ActionListener;
30 import java.util.ArrayList;
31 import java.util.Arrays;
32 import java.util.HashMap;
33 import java.util.List;
35 import java.util.Optional;
36 import java.util.logging.Level;
37 import javax.swing.JLabel;
38 import javax.swing.JMenuItem;
39 import javax.swing.JPopupMenu;
40 import javax.swing.JTextPane;
41 import javax.swing.SwingUtilities;
42 import javax.swing.border.EmptyBorder;
43 import org.apache.commons.lang.StringUtils;
44 import org.openide.util.NbBundle;
45 import org.openide.util.lookup.ServiceProvider;
61 @ServiceProvider(service = ArtifactContentViewer.class)
64 private static final long serialVersionUID = 1L;
67 private final static int MAX_COLS = 4;
68 private final static Insets ZERO_INSETS =
new java.awt.Insets(0, 0, 0, 0);
70 private final static Insets FIRST_HEADER_INSETS = ZERO_INSETS;
75 private final static double GLUE_WEIGHT_X = 1.0;
76 private final static double TEXT_WEIGHT_X = 0.0;
77 private final static int LABEL_COLUMN = 0;
78 private final static int VALUE_COLUMN = 1;
79 private final static int VALUE_WIDTH = 2;
80 private final static int LABEL_WIDTH = 1;
90 private final GridBagLayout gridBagLayout =
new GridBagLayout();
91 private final GridBagConstraints gridBagConstraints =
new GridBagConstraints();
92 private final Map<Integer, Integer[]> orderingMap =
new HashMap<>();
93 private final javax.swing.JPanel detailsPanel =
new javax.swing.JPanel();
102 gridBagConstraints.anchor = GridBagConstraints.FIRST_LINE_START;
103 detailsPanel.setLayout(gridBagLayout);
150 @NbBundle.Messages({
"GeneralPurposeArtifactViewer.unknown.text=Unknown"})
154 if (artifact != null) {
155 String dataSourceName = Bundle.GeneralPurposeArtifactViewer_unknown_text();
156 String hostName = Bundle.GeneralPurposeArtifactViewer_unknown_text();
157 String sourceFileName = Bundle.GeneralPurposeArtifactViewer_unknown_text();
158 Map<Integer, List<BlackboardAttribute>> attributeMap =
new HashMap<>();
162 List<BlackboardAttribute> attrList = attributeMap.get(bba.getAttributeType().getTypeID());
163 if (attrList == null) {
164 attrList =
new ArrayList<>();
167 attributeMap.put(bba.getAttributeType().getTypeID(), attrList);
172 .map(h -> h.getName())
177 logger.log(Level.WARNING,
"Unable to get attributes for artifact " + artifact.
getArtifactID(), ex);
179 updateView(artifact, attributeMap, dataSourceName, hostName, sourceFileName);
181 detailsScrollPane.setViewportView(detailsPanel);
182 detailsScrollPane.revalidate();
190 private
void resetComponent() {
192 detailsPanel.removeAll();
193 detailsPanel.setLayout(gridBagLayout);
194 detailsPanel.revalidate();
195 gridBagConstraints.gridy = 0;
196 gridBagConstraints.gridx = LABEL_COLUMN;
197 gridBagConstraints.weighty = 0.0;
198 gridBagConstraints.weightx = TEXT_WEIGHT_X;
199 gridBagConstraints.fill = GridBagConstraints.NONE;
200 gridBagConstraints.insets = ZERO_INSETS;
206 return (artifact != null)
218 @NbBundle.Messages({
"GeneralPurposeArtifactViewer.details.attrHeader=Details",
219 "GeneralPurposeArtifactViewer.details.sourceHeader=Source",
220 "GeneralPurposeArtifactViewer.details.dataSource=Data Source",
221 "GeneralPurposeArtifactViewer_details_host=Host",
222 "GeneralPurposeArtifactViewer.details.file=File",
223 "GeneralPurposeArtifactViewer.details.datesHeader=Dates"})
229 @SuppressWarnings(
"unchecked")
233 detailsScrollPane =
new javax.swing.JScrollPane();
235 detailsScrollPane.setPreferredSize(
new java.awt.Dimension(300, 0));
237 javax.swing.GroupLayout layout =
new javax.swing.GroupLayout(
this);
238 this.setLayout(layout);
239 layout.setHorizontalGroup(
240 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
241 .addComponent(detailsScrollPane, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
243 layout.setVerticalGroup(
244 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
245 .addGroup(layout.createSequentialGroup()
246 .addComponent(detailsScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
262 @NbBundle.Messages({
"GeneralPurposeArtifactViewer.dates.created=Created",
263 "GeneralPurposeArtifactViewer.dates.start=Start",
264 "GeneralPurposeArtifactViewer.dates.end=End",
265 "GeneralPurposeArtifactViewer.dates.time=Time",
266 "GeneralPurposeArtifactViewer.term.label=Term",
267 "GeneralPurposeArtifactViewer.details.otherHeader=Other",
268 "GeneralPurposeArtifactViewer.noFile.text= (no longer exists)"})
270 private void updateView(
BlackboardArtifact artifact, Map<Integer, List<BlackboardAttribute>> attributeMap, String dataSourceName, String hostName, String sourceFilePath) {
272 if (!(artifactTypeId < 1 || artifactTypeId >= Integer.MAX_VALUE)) {
273 JTextPane firstTextPane = addDetailsHeader(artifactTypeId);
274 Integer[] orderingArray = orderingMap.get(artifactTypeId);
275 if (orderingArray == null) {
276 orderingArray = DEFAULT_ORDERING;
278 for (Integer attrId : orderingArray) {
279 List<BlackboardAttribute> attrList = attributeMap.remove(attrId);
280 if (attrList != null) {
282 if (bba.getAttributeType().getTypeName().startsWith(
"TSK_DATETIME")) {
289 addNameValueRow(Bundle.GeneralPurposeArtifactViewer_term_label(), bba.getDisplayString());
291 String displayString = bba.getDisplayString();
293 displayString += Bundle.GeneralPurposeArtifactViewer_noFile_text();
295 addNameValueRow(bba.getAttributeType().getDisplayName(), displayString);
297 addNameValueRow(bba.getAttributeType().getDisplayName(), bba.getDisplayString());
303 boolean headerAdded =
false;
309 if (!attributeMap.keySet().isEmpty()) {
310 addHeader(Bundle.GeneralPurposeArtifactViewer_details_otherHeader());
311 for (
int key : attributeMap.keySet()) {
313 if (bba.getAttributeType().getTypeName().startsWith(
"TSK_DATETIME")) {
316 addNameValueRow(bba.getAttributeType().getDisplayName(), bba.getDisplayString());
321 addHeader(Bundle.GeneralPurposeArtifactViewer_details_sourceHeader());
322 addNameValueRow(Bundle.GeneralPurposeArtifactViewer_details_host(), StringUtils.defaultString(hostName));
323 addNameValueRow(Bundle.GeneralPurposeArtifactViewer_details_dataSource(), dataSourceName);
324 addNameValueRow(Bundle.GeneralPurposeArtifactViewer_details_file(), sourceFilePath);
327 if (firstTextPane != null) {
328 firstTextPane.setCaretPosition(0);
331 detailsPanel.revalidate();
344 private boolean addDates(String label, List<BlackboardAttribute> attrList,
boolean headerExists) {
345 boolean headerAdded = headerExists;
346 if (attrList != null) {
348 addHeader(Bundle.GeneralPurposeArtifactViewer_details_datesHeader());
351 String labelToUse = label;
353 if (StringUtils.isBlank(label)) {
354 labelToUse = bba.getAttributeType().getDisplayName();
356 addNameValueRow(labelToUse, bba.getDisplayString());
367 @NbBundle.Messages({
"GeneralPurposeArtifactViewer.details.bookmarkHeader=Bookmark Details",
368 "GeneralPurposeArtifactViewer.details.historyHeader=Visit Details",
369 "GeneralPurposeArtifactViewer.details.downloadHeader=Downloaded File",
370 "GeneralPurposeArtifactViewer.details.searchHeader=Web Search",
371 "GeneralPurposeArtifactViewer.details.cachedHeader=Cached File",
372 "GeneralPurposeArtifactViewer.details.cookieHeader=Cookie Details",})
376 header = Bundle.GeneralPurposeArtifactViewer_details_historyHeader();
378 header = Bundle.GeneralPurposeArtifactViewer_details_bookmarkHeader();
380 header = Bundle.GeneralPurposeArtifactViewer_details_cachedHeader();
382 header = Bundle.GeneralPurposeArtifactViewer_details_cookieHeader();
384 header = Bundle.GeneralPurposeArtifactViewer_details_downloadHeader();
386 header = Bundle.GeneralPurposeArtifactViewer_details_searchHeader();
388 header = Bundle.GeneralPurposeArtifactViewer_details_attrHeader();
390 return addHeader(header);
401 private JTextPane addHeader(String headerString) {
403 javax.swing.JTextPane headingLabel =
new javax.swing.JTextPane();
404 headingLabel.setOpaque(
false);
405 headingLabel.setFocusable(
false);
406 headingLabel.setEditable(
false);
409 gridBagConstraints.insets = (gridBagConstraints.gridy == 0)
410 ? FIRST_HEADER_INSETS
413 gridBagConstraints.gridy++;
414 gridBagConstraints.gridx = LABEL_COLUMN;;
416 gridBagConstraints.gridwidth = MAX_COLS;
418 headingLabel.setText(headerString);
421 headingLabel.setMargin(ZERO_INSETS);
423 addToPanel(headingLabel);
425 gridBagConstraints.gridwidth = LABEL_WIDTH;
428 gridBagConstraints.insets = ZERO_INSETS;
440 addKeyAtCol(keyString);
441 return addValueAtCol(valueString);
450 gridBagConstraints.gridx = MAX_COLS;
451 gridBagConstraints.weightx = GLUE_WEIGHT_X;
452 gridBagConstraints.fill = GridBagConstraints.BOTH;
453 javax.swing.Box.Filler horizontalFiller =
new javax.swing.Box.Filler(
new Dimension(0, 0),
new Dimension(0, 0),
new Dimension(32767, 0));
455 addToPanel(horizontalFiller);
457 gridBagConstraints.fill = GridBagConstraints.NONE;
458 gridBagConstraints.weightx = TEXT_WEIGHT_X;
466 gridBagConstraints.weighty = 1.0;
467 gridBagConstraints.fill = GridBagConstraints.VERTICAL;
468 javax.swing.Box.Filler vertFiller =
new javax.swing.Box.Filler(
new Dimension(0, 0),
new Dimension(0, 0),
new Dimension(0, 32767));
470 addToPanel(vertFiller);
482 javax.swing.JLabel keyLabel =
new javax.swing.JLabel();
483 keyLabel.setFocusable(
false);
484 gridBagConstraints.gridy++;
485 gridBagConstraints.insets = KEY_COLUMN_INSETS;
486 gridBagConstraints.gridx = LABEL_COLUMN;
487 gridBagConstraints.gridwidth = LABEL_WIDTH;
489 keyLabel.setText(keyString +
": ");
491 addToPanel(keyLabel);
496 detailsPanel.add(comp, gridBagConstraints);
497 detailsPanel.revalidate();
509 JTextPane valueField =
new JTextPane();
510 valueField.setFocusable(
false);
511 valueField.setEditable(
false);
512 valueField.setOpaque(
false);
513 valueField.setMargin(ZERO_INSETS);
514 gridBagConstraints.gridx = VALUE_COLUMN;
515 gridBagConstraints.insets = VALUE_COLUMN_INSETS;
516 GridBagConstraints cloneConstraints = (GridBagConstraints) gridBagConstraints.clone();
518 cloneConstraints.gridwidth = VALUE_WIDTH;
519 cloneConstraints.fill = GridBagConstraints.BOTH;
521 valueField.setText(valueString);
523 valueField.addMouseListener(
new java.awt.event.MouseAdapter() {
525 public void mouseClicked(java.awt.event.MouseEvent evt) {
526 valueLabelMouseClicked(evt, valueField);
530 detailsPanel.add(valueField, cloneConstraints);
545 "GeneralPurposeArtifactViewer_menuitem_copy=Copy"
548 if (SwingUtilities.isRightMouseButton(evt)) {
549 JPopupMenu popup =
new JPopupMenu();
550 JMenuItem copyMenu =
new JMenuItem(Bundle.CommunicationArtifactViewerHelper_menuitem_copy());
551 copyMenu.addActionListener(
new ActionListener() {
553 public void actionPerformed(ActionEvent e) {
554 Toolkit.getDefaultToolkit().getSystemClipboard().setContents(
new StringSelection(valueLabel.getText()), null);
558 popup.show(valueLabel, evt.getX(), evt.getY());
void setArtifact(BlackboardArtifact artifact)
Host getHostByDataSource(DataSource dataSource)
void updateView(BlackboardArtifact artifact, Map< Integer, List< BlackboardAttribute >> attributeMap, String dataSourceName, String hostName, String sourceFilePath)
static Integer getLineSpacing()
JTextPane addNameValueRow(String keyString, String valueString)
static String getFormattedTime(long epochTime)
void addToPanel(Component comp)
static Insets getPanelInsets()
void valueLabelMouseClicked(java.awt.event.MouseEvent evt, JTextPane valueLabel)
static Integer getSectionIndent()
boolean addDates(String label, List< BlackboardAttribute > attrList, boolean headerExists)
JTextPane addValueAtCol(String valueString)
boolean isSupported(BlackboardArtifact artifact)
static Font getHeaderFont()
HostManager getHostManager()
javax.swing.JScrollPane detailsScrollPane
SleuthkitCase getSleuthkitCase()
JTextPane addDetailsHeader(int artifactTypeId)
List< BlackboardAttribute > getAttributes()
static int getColumnSpacing()
static Integer getSectionSpacing()
synchronized static Logger getLogger(String name)
JLabel addKeyAtCol(String keyString)
static Case getCurrentCaseThrows()