Autopsy  4.10.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
MessageContentViewer.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2017-2019 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.contentviewers;
20 
21 import java.awt.Color;
22 import java.awt.Component;
23 import java.util.Arrays;
24 import java.util.HashSet;
25 import java.util.List;
26 import java.util.Optional;
27 import java.util.Set;
28 import java.util.logging.Level;
29 import java.util.stream.Collectors;
30 import javax.swing.text.JTextComponent;
31 import org.apache.commons.lang3.StringUtils;
32 import org.jsoup.Jsoup;
33 import org.jsoup.nodes.Document;
34 import org.openide.explorer.ExplorerManager;
35 import org.openide.nodes.AbstractNode;
36 import org.openide.nodes.Children;
37 import org.openide.nodes.Node;
38 import org.openide.nodes.Sheet;
39 import org.openide.util.NbBundle;
40 import org.openide.util.lookup.ServiceProvider;
49 import org.sleuthkit.datamodel.AbstractFile;
50 import org.sleuthkit.datamodel.BlackboardArtifact;
51 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG;
52 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT;
53 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE;
54 import org.sleuthkit.datamodel.BlackboardAttribute;
55 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT;
56 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME;
57 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_RCVD;
58 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION;
59 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL_CC;
60 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL_CONTENT_HTML;
61 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL_CONTENT_PLAIN;
62 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL_CONTENT_RTF;
63 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL_FROM;
64 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL_TO;
65 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_HEADERS;
66 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM;
67 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO;
68 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SUBJECT;
69 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT;
70 import org.sleuthkit.datamodel.TskCoreException;
71 
75 @ServiceProvider(service = DataContentViewer.class, position = 5)
76 @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
77 public class MessageContentViewer extends javax.swing.JPanel implements DataContentViewer {
78 
79  private static final long serialVersionUID = 1L;
80  private static final Logger LOGGER = Logger.getLogger(MessageContentViewer.class.getName());
81  private static final BlackboardAttribute.Type TSK_ASSOCIATED_TYPE = new BlackboardAttribute.Type(TSK_ASSOCIATED_ARTIFACT);
82 
83  private static final int HDR_TAB_INDEX = 0;
84  private static final int TEXT_TAB_INDEX = 1;
85  private static final int HTML_TAB_INDEX = 2;
86  private static final int RTF_TAB_INDEX = 3;
87  private static final int ATTM_TAB_INDEX = 4;
88 
89  private final List<JTextComponent> textAreas;
90 
94  private BlackboardArtifact artifact;
95  private final DataResultPanel drp;
96  private ExplorerManager drpExplorerManager;
97 
101  @NbBundle.Messages("MessageContentViewer.AtrachmentsPanel.title=Attachments")
103  initComponents();
104  envelopePanel.setBackground(new Color(0, 0, 0, 38));
105  drp = DataResultPanel.createInstanceUninitialized(Bundle.MessageContentViewer_AtrachmentsPanel_title(), "", new TableFilterNode(Node.EMPTY, false), 0, null);
106  attachmentsScrollPane.setViewportView(drp);
107  msgbodyTabbedPane.setEnabledAt(ATTM_TAB_INDEX, true);
108 
109  /*
110  * HTML tab uses the HtmlPanel instead of an internal text pane, so we
111  * use 'null' for that index.
112  */
113  textAreas = Arrays.asList(headersTextArea, textbodyTextArea, null, rtfbodyTextPane);
114 
115  Utilities.configureTextPaneAsRtf(rtfbodyTextPane);
116  resetComponent();
117 
118  }
119 
120  @Override
121  public void addNotify() {
122  super.addNotify(); //To change body of generated methods, choose Tools | Templates.
123 
124  drp.open();
125  drpExplorerManager = drp.getExplorerManager();
126  drpExplorerManager.addPropertyChangeListener(evt
127  -> viewInNewWindowButton.setEnabled(drpExplorerManager.getSelectedNodes().length == 1));
128  }
129 
135  @SuppressWarnings("unchecked")
136  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
137  private void initComponents() {
138 
139  envelopePanel = new javax.swing.JPanel();
140  fromLabel = new javax.swing.JLabel();
141  datetimeText = new javax.swing.JLabel();
142  fromText = new javax.swing.JLabel();
143  toLabel = new javax.swing.JLabel();
144  toText = new javax.swing.JLabel();
145  ccLabel = new javax.swing.JLabel();
146  ccText = new javax.swing.JLabel();
147  subjectLabel = new javax.swing.JLabel();
148  subjectText = new javax.swing.JLabel();
149  directionText = new javax.swing.JLabel();
150  msgbodyTabbedPane = new javax.swing.JTabbedPane();
151  headersScrollPane = new javax.swing.JScrollPane();
152  headersTextArea = new javax.swing.JTextArea();
153  textbodyScrollPane = new javax.swing.JScrollPane();
154  textbodyTextArea = new javax.swing.JTextArea();
155  htmlPane = new javax.swing.JPanel();
156  htmlPanel = new org.sleuthkit.autopsy.contentviewers.HtmlPanel();
157  rtfbodyScrollPane = new javax.swing.JScrollPane();
158  rtfbodyTextPane = new javax.swing.JTextPane();
159  attachmentsPanel = new javax.swing.JPanel();
160  viewInNewWindowButton = new javax.swing.JButton();
161  attachmentsScrollPane = new javax.swing.JScrollPane();
162 
163  envelopePanel.setBackground(new java.awt.Color(204, 204, 204));
164 
165  org.openide.awt.Mnemonics.setLocalizedText(fromLabel, org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.fromLabel.text")); // NOI18N
166 
167  datetimeText.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
168  org.openide.awt.Mnemonics.setLocalizedText(datetimeText, org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.datetimeText.text")); // NOI18N
169 
170  org.openide.awt.Mnemonics.setLocalizedText(fromText, org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.fromText.text")); // NOI18N
171 
172  org.openide.awt.Mnemonics.setLocalizedText(toLabel, org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.toLabel.text")); // NOI18N
173 
174  org.openide.awt.Mnemonics.setLocalizedText(toText, org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.toText.text")); // NOI18N
175  toText.setAutoscrolls(true);
176  toText.setMinimumSize(new java.awt.Dimension(27, 14));
177 
178  org.openide.awt.Mnemonics.setLocalizedText(ccLabel, org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.ccLabel.text")); // NOI18N
179 
180  org.openide.awt.Mnemonics.setLocalizedText(ccText, org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.ccText.text")); // NOI18N
181  ccText.setMinimumSize(new java.awt.Dimension(27, 14));
182 
183  org.openide.awt.Mnemonics.setLocalizedText(subjectLabel, org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.subjectLabel.text")); // NOI18N
184 
185  org.openide.awt.Mnemonics.setLocalizedText(subjectText, org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.subjectText.text")); // NOI18N
186  subjectText.setMinimumSize(new java.awt.Dimension(26, 14));
187 
188  directionText.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
189  org.openide.awt.Mnemonics.setLocalizedText(directionText, org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.directionText.text")); // NOI18N
190 
191  javax.swing.GroupLayout envelopePanelLayout = new javax.swing.GroupLayout(envelopePanel);
192  envelopePanel.setLayout(envelopePanelLayout);
193  envelopePanelLayout.setHorizontalGroup(
194  envelopePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
195  .addGroup(envelopePanelLayout.createSequentialGroup()
196  .addGap(5, 5, 5)
197  .addGroup(envelopePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
198  .addGroup(envelopePanelLayout.createSequentialGroup()
199  .addGroup(envelopePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
200  .addComponent(fromLabel)
201  .addComponent(toLabel))
202  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
203  .addGroup(envelopePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
204  .addGroup(envelopePanelLayout.createSequentialGroup()
205  .addComponent(toText, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
206  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
207  .addComponent(directionText, javax.swing.GroupLayout.PREFERRED_SIZE, 66, javax.swing.GroupLayout.PREFERRED_SIZE))
208  .addGroup(envelopePanelLayout.createSequentialGroup()
209  .addComponent(fromText, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
210  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
211  .addComponent(datetimeText, javax.swing.GroupLayout.PREFERRED_SIZE, 140, javax.swing.GroupLayout.PREFERRED_SIZE))))
212  .addGroup(envelopePanelLayout.createSequentialGroup()
213  .addComponent(ccLabel)
214  .addGap(26, 26, 26)
215  .addComponent(ccText, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
216  .addGroup(envelopePanelLayout.createSequentialGroup()
217  .addComponent(subjectLabel)
218  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
219  .addComponent(subjectText, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
220  .addGap(5, 5, 5))
221  );
222  envelopePanelLayout.setVerticalGroup(
223  envelopePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
224  .addGroup(envelopePanelLayout.createSequentialGroup()
225  .addGap(5, 5, 5)
226  .addGroup(envelopePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
227  .addComponent(fromLabel)
228  .addComponent(datetimeText)
229  .addComponent(fromText))
230  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
231  .addGroup(envelopePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
232  .addComponent(toLabel)
233  .addComponent(toText, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
234  .addComponent(directionText))
235  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
236  .addGroup(envelopePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
237  .addComponent(ccLabel)
238  .addComponent(ccText, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
239  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
240  .addGroup(envelopePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
241  .addComponent(subjectLabel)
242  .addComponent(subjectText, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
243  .addGap(5, 5, 5))
244  );
245 
246  headersScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
247  headersScrollPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
248 
249  headersTextArea.setEditable(false);
250  headersTextArea.setColumns(20);
251  headersTextArea.setLineWrap(true);
252  headersTextArea.setRows(5);
253  headersTextArea.setWrapStyleWord(true);
254  headersScrollPane.setViewportView(headersTextArea);
255 
256  msgbodyTabbedPane.addTab(org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.headersScrollPane.TabConstraints.tabTitle"), headersScrollPane); // NOI18N
257 
258  textbodyScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
259  textbodyScrollPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
260 
261  textbodyTextArea.setEditable(false);
262  textbodyTextArea.setLineWrap(true);
263  textbodyTextArea.setRows(5);
264  textbodyTextArea.setWrapStyleWord(true);
265  textbodyScrollPane.setViewportView(textbodyTextArea);
266 
267  msgbodyTabbedPane.addTab(org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.textbodyScrollPane.TabConstraints.tabTitle"), textbodyScrollPane); // NOI18N
268 
269  javax.swing.GroupLayout htmlPaneLayout = new javax.swing.GroupLayout(htmlPane);
270  htmlPane.setLayout(htmlPaneLayout);
271  htmlPaneLayout.setHorizontalGroup(
272  htmlPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
273  .addComponent(htmlPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 647, Short.MAX_VALUE)
274  );
275  htmlPaneLayout.setVerticalGroup(
276  htmlPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
277  .addComponent(htmlPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 362, Short.MAX_VALUE)
278  );
279 
280  msgbodyTabbedPane.addTab(org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.htmlPane.TabConstraints.tabTitle"), htmlPane); // NOI18N
281 
282  rtfbodyScrollPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
283 
284  rtfbodyTextPane.setEditable(false);
285  rtfbodyScrollPane.setViewportView(rtfbodyTextPane);
286 
287  msgbodyTabbedPane.addTab(org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.rtfbodyScrollPane.TabConstraints.tabTitle"), rtfbodyScrollPane); // NOI18N
288 
289  org.openide.awt.Mnemonics.setLocalizedText(viewInNewWindowButton, org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.viewInNewWindowButton.text")); // NOI18N
290  viewInNewWindowButton.addActionListener(new java.awt.event.ActionListener() {
291  public void actionPerformed(java.awt.event.ActionEvent evt) {
292  viewInNewWindowButtonActionPerformed(evt);
293  }
294  });
295 
296  javax.swing.GroupLayout attachmentsPanelLayout = new javax.swing.GroupLayout(attachmentsPanel);
297  attachmentsPanel.setLayout(attachmentsPanelLayout);
298  attachmentsPanelLayout.setHorizontalGroup(
299  attachmentsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
300  .addGroup(attachmentsPanelLayout.createSequentialGroup()
301  .addGap(0, 0, 0)
302  .addGroup(attachmentsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
303  .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, attachmentsPanelLayout.createSequentialGroup()
304  .addComponent(viewInNewWindowButton)
305  .addGap(3, 3, 3))
306  .addComponent(attachmentsScrollPane, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 647, Short.MAX_VALUE)))
307  );
308  attachmentsPanelLayout.setVerticalGroup(
309  attachmentsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
310  .addGroup(attachmentsPanelLayout.createSequentialGroup()
311  .addGap(0, 0, 0)
312  .addComponent(viewInNewWindowButton)
313  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
314  .addComponent(attachmentsScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 333, Short.MAX_VALUE)
315  .addGap(0, 0, 0))
316  );
317 
318  msgbodyTabbedPane.addTab(org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.attachmentsPanel.TabConstraints.tabTitle"), attachmentsPanel); // NOI18N
319 
320  javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
321  this.setLayout(layout);
322  layout.setHorizontalGroup(
323  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
324  .addGroup(layout.createSequentialGroup()
325  .addGap(5, 5, 5)
326  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
327  .addComponent(msgbodyTabbedPane)
328  .addComponent(envelopePanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
329  .addGap(5, 5, 5))
330  );
331  layout.setVerticalGroup(
332  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
333  .addGroup(layout.createSequentialGroup()
334  .addGap(5, 5, 5)
335  .addComponent(envelopePanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
336  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
337  .addComponent(msgbodyTabbedPane)
338  .addGap(5, 5, 5))
339  );
340  }// </editor-fold>//GEN-END:initComponents
341 
342  private void viewInNewWindowButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_viewInNewWindowButtonActionPerformed
343  new NewWindowViewAction("View in new window", drpExplorerManager.getSelectedNodes()[0]).actionPerformed(evt);
344  }//GEN-LAST:event_viewInNewWindowButtonActionPerformed
345 
346 
347  // Variables declaration - do not modify//GEN-BEGIN:variables
348  private javax.swing.JPanel attachmentsPanel;
349  private javax.swing.JScrollPane attachmentsScrollPane;
350  private javax.swing.JLabel ccLabel;
351  private javax.swing.JLabel ccText;
352  private javax.swing.JLabel datetimeText;
353  private javax.swing.JLabel directionText;
354  private javax.swing.JPanel envelopePanel;
355  private javax.swing.JLabel fromLabel;
356  private javax.swing.JLabel fromText;
357  private javax.swing.JScrollPane headersScrollPane;
358  private javax.swing.JTextArea headersTextArea;
359  private javax.swing.JPanel htmlPane;
361  private javax.swing.JTabbedPane msgbodyTabbedPane;
362  private javax.swing.JScrollPane rtfbodyScrollPane;
363  private javax.swing.JTextPane rtfbodyTextPane;
364  private javax.swing.JLabel subjectLabel;
365  private javax.swing.JLabel subjectText;
366  private javax.swing.JScrollPane textbodyScrollPane;
367  private javax.swing.JTextArea textbodyTextArea;
368  private javax.swing.JLabel toLabel;
369  private javax.swing.JLabel toText;
370  private javax.swing.JButton viewInNewWindowButton;
371  // End of variables declaration//GEN-END:variables
372 
373  @Override
374  public void setNode(Node node) {
375  if (node == null) {
376  resetComponent();
377  return;
378  }
379 
380  artifact = node.getLookup().lookup(BlackboardArtifact.class);
381  if (artifact == null) {
382  resetComponent();
383  return;
384  }
385 
386  /*
387  * If the artifact is a keyword hit, use the associated artifact as the
388  * one to show in this viewer
389  */
390  if (artifact.getArtifactTypeID() == TSK_KEYWORD_HIT.getTypeID()) {
391  try {
392  getAssociatedArtifact(artifact).ifPresent(associatedArtifact -> {
393  artifact = associatedArtifact;
394  });
395  } catch (TskCoreException ex) {
396  LOGGER.log(Level.SEVERE, "error getting associated artifact", ex);
397  }
398  }
399 
400  if (artifact.getArtifactTypeID() == TSK_MESSAGE.getTypeID()) {
401  displayMsg();
402  } else if (artifact.getArtifactTypeID() == TSK_EMAIL_MSG.getTypeID()) {
403  displayEmailMsg();
404  } else {
405  resetComponent();
406  }
407  }
408 
419  private static Optional<BlackboardArtifact> getAssociatedArtifact(final BlackboardArtifact artifact) throws TskCoreException {
420  BlackboardAttribute attribute = artifact.getAttribute(TSK_ASSOCIATED_TYPE);
421  if (attribute != null) {
422  return Optional.of(artifact.getSleuthkitCase().getArtifactByArtifactId(attribute.getValueLong()));
423  }
424  return Optional.empty();
425  }
426 
427  @Override
428  @NbBundle.Messages("MessageContentViewer.title=Message")
429  public String getTitle() {
430  return Bundle.MessageContentViewer_title();
431  }
432 
433  @Override
434  @NbBundle.Messages("MessageContentViewer.toolTip=Displays messages.")
435  public String getToolTip() {
436  return Bundle.MessageContentViewer_toolTip();
437  }
438 
439  @Override
440  public DataContentViewer createInstance() {
441  return new MessageContentViewer();
442  }
443 
444  @Override
445  public Component getComponent() {
446  return this;
447  }
448 
449  @Override
450  final public void resetComponent() {
451  // reset all fields
452  fromText.setText("");
453  fromLabel.setEnabled(false);
454  toText.setText("");
455  toLabel.setEnabled(false);
456  ccText.setText("");
457  ccLabel.setEnabled(false);
458  subjectText.setText("");
459  subjectLabel.setEnabled(false);
460  datetimeText.setText("");
461  datetimeText.setEnabled(false);
462  directionText.setText("");
463  directionText.setEnabled(false);
464 
465  headersTextArea.setText("");
466  rtfbodyTextPane.setText("");
467  htmlPanel.reset();
468  textbodyTextArea.setText("");
469  msgbodyTabbedPane.setEnabled(false);
470  }
471 
472  @Override
473  public boolean isSupported(Node node) {
474  BlackboardArtifact nodeArtifact = node.getLookup().lookup(BlackboardArtifact.class);
475 
476  if (nodeArtifact == null) {
477  return false;
478  }
479  //if the artifact is a keyword hit, check if its associated artifact is a message or email.
480  if (nodeArtifact.getArtifactTypeID() == TSK_KEYWORD_HIT.getTypeID()) {
481  try {
482  if (getAssociatedArtifact(nodeArtifact).map(MessageContentViewer::isMessageArtifact).orElse(false)) {
483  return true;
484  }
485  } catch (TskCoreException ex) {
486  LOGGER.log(Level.SEVERE, "error getting associated artifact", ex);
487  }
488  }
489  return isMessageArtifact(nodeArtifact);
490  }
491 
501  private static boolean isMessageArtifact(BlackboardArtifact nodeArtifact) {
502  final int artifactTypeID = nodeArtifact.getArtifactTypeID();
503  return artifactTypeID == TSK_EMAIL_MSG.getTypeID()
504  || artifactTypeID == TSK_MESSAGE.getTypeID();
505  }
506 
507  @Override
508  public int isPreferred(Node node) {
509  if (isSupported(node)) {
510  return 7;
511  }
512  return 0;
513  }
514 
524  private void configureTextArea(BlackboardAttribute.ATTRIBUTE_TYPE type, int index) throws TskCoreException {
525  String attributeText = getAttributeValueSafe(artifact, type);
526 
527  if (index == HTML_TAB_INDEX && StringUtils.isNotBlank(attributeText)) {
528  htmlPanel.setHtmlText(attributeText);
529  } else {
530  JTextComponent textComponent = textAreas.get(index);
531  if (textComponent != null) {
532  textComponent.setText(attributeText);
533  textComponent.setCaretPosition(0); //make sure we start at the top
534  }
535  }
536 
537  final boolean hasText = attributeText.length() > 0;
538 
539  msgbodyTabbedPane.setEnabledAt(index, hasText);
540  if (hasText) {
541  msgbodyTabbedPane.setSelectedIndex(index);
542  }
543  }
544 
545  private void enableCommonFields() {
546  msgbodyTabbedPane.setEnabled(true);
547  fromLabel.setEnabled(true);
548  toLabel.setEnabled(true);
549  subjectLabel.setEnabled(true);
550  datetimeText.setEnabled(true);
551  }
552 
553  private void configureAttachments() throws TskCoreException {
554  //TODO: Replace this with code to get the actual attachements!
555  final Set<AbstractFile> attachments = artifact.getChildren().stream()
556  .filter(AbstractFile.class::isInstance)
557  .map(AbstractFile.class::cast)
558  .collect(Collectors.toSet());
559  final int numberOfAttachments = attachments.size();
560 
561  msgbodyTabbedPane.setEnabledAt(ATTM_TAB_INDEX, numberOfAttachments > 0);
562  msgbodyTabbedPane.setTitleAt(ATTM_TAB_INDEX, "Attachments (" + numberOfAttachments + ")");
563  drp.setNode(new TableFilterNode(new DataResultFilterNode(new AbstractNode(
564  new AttachmentsChildren(attachments)), null), true));
565  }
566 
567  private static String wrapInHtmlBody(String htmlText) {
568  return "<html><body>" + htmlText + "</body></html>";
569  }
570 
571  private void displayEmailMsg() {
572  enableCommonFields();
573 
574  directionText.setEnabled(false);
575  ccLabel.setEnabled(true);
576 
577  try {
578  this.fromText.setText(getAttributeValueSafe(artifact, TSK_EMAIL_FROM));
579  this.fromText.setToolTipText(getAttributeValueSafe(artifact, TSK_EMAIL_FROM));
580  this.toText.setText(getAttributeValueSafe(artifact, TSK_EMAIL_TO));
581  this.toText.setToolTipText(getAttributeValueSafe(artifact, TSK_EMAIL_TO));
582  this.directionText.setText("");
583  this.ccText.setText(getAttributeValueSafe(artifact, TSK_EMAIL_CC));
584  this.ccText.setToolTipText(getAttributeValueSafe(artifact, TSK_EMAIL_CC));
585  this.subjectText.setText(getAttributeValueSafe(artifact, TSK_SUBJECT));
586  this.datetimeText.setText(getAttributeValueSafe(artifact, TSK_DATETIME_RCVD));
587 
588  configureTextArea(TSK_HEADERS, HDR_TAB_INDEX);
589  configureTextArea(TSK_EMAIL_CONTENT_PLAIN, TEXT_TAB_INDEX);
590  configureTextArea(TSK_EMAIL_CONTENT_HTML, HTML_TAB_INDEX);
591  configureTextArea(TSK_EMAIL_CONTENT_RTF, RTF_TAB_INDEX);
592  configureAttachments();
593  } catch (TskCoreException ex) {
594  LOGGER.log(Level.WARNING, "Failed to get attributes for email message.", ex); //NON-NLS
595  }
596  }
597 
598  private void displayMsg() {
599  enableCommonFields();
600 
601  directionText.setEnabled(true);
602  ccLabel.setEnabled(false);
603 
604  try {
605  this.fromText.setText(getAttributeValueSafe(artifact, TSK_PHONE_NUMBER_FROM));
606  this.toText.setText(getAttributeValueSafe(artifact, TSK_PHONE_NUMBER_TO));
607  this.directionText.setText(getAttributeValueSafe(artifact, TSK_DIRECTION));
608  this.ccText.setText("");
609  this.subjectText.setText(getAttributeValueSafe(artifact, TSK_SUBJECT));
610  this.datetimeText.setText(getAttributeValueSafe(artifact, TSK_DATETIME));
611 
612  msgbodyTabbedPane.setEnabledAt(HTML_TAB_INDEX, false);
613  msgbodyTabbedPane.setEnabledAt(RTF_TAB_INDEX, false);
614  msgbodyTabbedPane.setEnabledAt(HDR_TAB_INDEX, false);
615  msgbodyTabbedPane.setEnabledAt(HDR_TAB_INDEX, false);
616  configureTextArea(TSK_TEXT, TEXT_TAB_INDEX);
617  configureAttachments();
618  } catch (TskCoreException ex) {
619  LOGGER.log(Level.WARNING, "Failed to get attributes for message.", ex); //NON-NLS
620  }
621  }
622 
623  private static String getAttributeValueSafe(BlackboardArtifact artifact, BlackboardAttribute.ATTRIBUTE_TYPE type) throws TskCoreException {
624  return Optional.ofNullable(artifact.getAttribute(new BlackboardAttribute.Type(type)))
625  .map(BlackboardAttribute::getDisplayString)
626  .orElse("");
627  }
628 
636  static private String cleanseHTML(String htmlInString) {
637 
638  Document doc = Jsoup.parse(htmlInString);
639 
640  //fix all img tags
641  doc.select("img[src]").forEach(img -> img.attr("src", ""));
642 
643  return doc.html();
644  }
645 
646  private static class AttachmentsChildren extends Children.Keys<AbstractFile> {
647 
648  private final Set<AbstractFile> attachments;
649 
650  AttachmentsChildren(Set<AbstractFile> attachments) {
651  this.attachments = attachments;
652  }
653 
654  @Override
655  protected Node[] createNodes(AbstractFile t) {
656  return new Node[]{new AttachmentNode(t)};
657  }
658 
659  @Override
660  protected void addNotify() {
661  super.addNotify();
662  setKeys(attachments);
663  }
664  }
665 
672  private static class AttachmentNode extends FileNode {
673 
674  AttachmentNode(AbstractFile file) {
675  super(file, false);
676  }
677 
678  @Override
679  protected Sheet createSheet() {
680  Sheet sheet = super.createSheet();
681  Set<String> keepProps = new HashSet<>(Arrays.asList(
682  NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.nameColLbl"),
683  NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.createSheet.score.name"),
684  NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.createSheet.comment.name"),
685  NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.createSheet.count.name"),
686  NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.sizeColLbl"),
687  NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.mimeType"),
688  NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.knownColLbl")));
689 
690  //Remove all other props except for the ones above
691  Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
692  for(Property<?> p : sheetSet.getProperties()) {
693  if(!keepProps.contains(p.getName())){
694  sheetSet.remove(p.getName());
695  }
696  }
697 
698  return sheet;
699  }
700  }
701 }
static void configureTextPaneAsRtf(JTextPane pane)
Definition: Utilities.java:52
static String getAttributeValueSafe(BlackboardArtifact artifact, BlackboardAttribute.ATTRIBUTE_TYPE type)
void configureTextArea(BlackboardAttribute.ATTRIBUTE_TYPE type, int index)
static boolean isMessageArtifact(BlackboardArtifact nodeArtifact)
static DataResultPanel createInstanceUninitialized(String title, String description, Node currentRootNode, int childNodeCount, DataContent customContentView)
static Optional< BlackboardArtifact > getAssociatedArtifact(final BlackboardArtifact artifact)
org.sleuthkit.autopsy.contentviewers.HtmlPanel htmlPanel
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
void viewInNewWindowButtonActionPerformed(java.awt.event.ActionEvent evt)

Copyright © 2012-2018 Basis Technology. Generated on: Fri Mar 22 2019
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.