Autopsy  4.11.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;
94  private BlackboardArtifact artifact;
95  private final DataResultPanel drp;
96  private ExplorerManager drpExplorerManager;
97 
101  @NbBundle.Messages("MessageContentViewer.AtrachmentsPanel.title=Attachments")
103  initComponents();
104  htmlPane.add(htmlPanel);
105  envelopePanel.setBackground(new Color(0, 0, 0, 38));
106  drp = DataResultPanel.createInstanceUninitialized(Bundle.MessageContentViewer_AtrachmentsPanel_title(), "", new TableFilterNode(Node.EMPTY, false), 0, null);
107  attachmentsScrollPane.setViewportView(drp);
108  msgbodyTabbedPane.setEnabledAt(ATTM_TAB_INDEX, true);
109 
110  /*
111  * HTML tab uses the HtmlPanel instead of an internal text pane, so we
112  * use 'null' for that index.
113  */
114  textAreas = Arrays.asList(headersTextArea, textbodyTextArea, null, rtfbodyTextPane);
115 
116  Utilities.configureTextPaneAsRtf(rtfbodyTextPane);
117  resetComponent();
118 
119  }
120 
121  @Override
122  public void addNotify() {
123  super.addNotify(); //To change body of generated methods, choose Tools | Templates.
124 
125  drp.open();
126  drpExplorerManager = drp.getExplorerManager();
127  drpExplorerManager.addPropertyChangeListener(evt
128  -> viewInNewWindowButton.setEnabled(drpExplorerManager.getSelectedNodes().length == 1));
129  }
130 
136  @SuppressWarnings("unchecked")
137  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
138  private void initComponents() {
139 
140  envelopePanel = new javax.swing.JPanel();
141  fromLabel = new javax.swing.JLabel();
142  datetimeText = new javax.swing.JLabel();
143  fromText = new javax.swing.JLabel();
144  toLabel = new javax.swing.JLabel();
145  toText = new javax.swing.JLabel();
146  ccLabel = new javax.swing.JLabel();
147  ccText = new javax.swing.JLabel();
148  subjectLabel = new javax.swing.JLabel();
149  subjectText = new javax.swing.JLabel();
150  directionText = new javax.swing.JLabel();
151  msgbodyTabbedPane = new javax.swing.JTabbedPane();
152  headersScrollPane = new javax.swing.JScrollPane();
153  headersTextArea = new javax.swing.JTextArea();
154  textbodyScrollPane = new javax.swing.JScrollPane();
155  textbodyTextArea = new javax.swing.JTextArea();
156  htmlPane = new javax.swing.JPanel();
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  htmlPane.setLayout(new java.awt.BorderLayout());
270  msgbodyTabbedPane.addTab(org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.htmlPane.TabConstraints.tabTitle"), htmlPane); // NOI18N
271 
272  rtfbodyScrollPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
273 
274  rtfbodyTextPane.setEditable(false);
275  rtfbodyScrollPane.setViewportView(rtfbodyTextPane);
276 
277  msgbodyTabbedPane.addTab(org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.rtfbodyScrollPane.TabConstraints.tabTitle"), rtfbodyScrollPane); // NOI18N
278 
279  org.openide.awt.Mnemonics.setLocalizedText(viewInNewWindowButton, org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.viewInNewWindowButton.text")); // NOI18N
280  viewInNewWindowButton.addActionListener(new java.awt.event.ActionListener() {
281  public void actionPerformed(java.awt.event.ActionEvent evt) {
282  viewInNewWindowButtonActionPerformed(evt);
283  }
284  });
285 
286  javax.swing.GroupLayout attachmentsPanelLayout = new javax.swing.GroupLayout(attachmentsPanel);
287  attachmentsPanel.setLayout(attachmentsPanelLayout);
288  attachmentsPanelLayout.setHorizontalGroup(
289  attachmentsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
290  .addGroup(attachmentsPanelLayout.createSequentialGroup()
291  .addGap(0, 0, 0)
292  .addGroup(attachmentsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
293  .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, attachmentsPanelLayout.createSequentialGroup()
294  .addComponent(viewInNewWindowButton)
295  .addGap(3, 3, 3))
296  .addComponent(attachmentsScrollPane, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 647, Short.MAX_VALUE)))
297  );
298  attachmentsPanelLayout.setVerticalGroup(
299  attachmentsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
300  .addGroup(attachmentsPanelLayout.createSequentialGroup()
301  .addGap(0, 0, 0)
302  .addComponent(viewInNewWindowButton)
303  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
304  .addComponent(attachmentsScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 333, Short.MAX_VALUE)
305  .addGap(0, 0, 0))
306  );
307 
308  msgbodyTabbedPane.addTab(org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.attachmentsPanel.TabConstraints.tabTitle"), attachmentsPanel); // NOI18N
309 
310  javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
311  this.setLayout(layout);
312  layout.setHorizontalGroup(
313  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
314  .addGroup(layout.createSequentialGroup()
315  .addGap(5, 5, 5)
316  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
317  .addComponent(msgbodyTabbedPane)
318  .addComponent(envelopePanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
319  .addGap(5, 5, 5))
320  );
321  layout.setVerticalGroup(
322  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
323  .addGroup(layout.createSequentialGroup()
324  .addGap(5, 5, 5)
325  .addComponent(envelopePanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
326  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
327  .addComponent(msgbodyTabbedPane)
328  .addGap(5, 5, 5))
329  );
330  }// </editor-fold>//GEN-END:initComponents
331 
332  private void viewInNewWindowButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_viewInNewWindowButtonActionPerformed
333  new NewWindowViewAction("View in new window", drpExplorerManager.getSelectedNodes()[0]).actionPerformed(evt);
334  }//GEN-LAST:event_viewInNewWindowButtonActionPerformed
335 
336 
337  // Variables declaration - do not modify//GEN-BEGIN:variables
338  private javax.swing.JPanel attachmentsPanel;
339  private javax.swing.JScrollPane attachmentsScrollPane;
340  private javax.swing.JLabel ccLabel;
341  private javax.swing.JLabel ccText;
342  private javax.swing.JLabel datetimeText;
343  private javax.swing.JLabel directionText;
344  private javax.swing.JPanel envelopePanel;
345  private javax.swing.JLabel fromLabel;
346  private javax.swing.JLabel fromText;
347  private javax.swing.JScrollPane headersScrollPane;
348  private javax.swing.JTextArea headersTextArea;
349  private javax.swing.JPanel htmlPane;
350  private javax.swing.JTabbedPane msgbodyTabbedPane;
351  private javax.swing.JScrollPane rtfbodyScrollPane;
352  private javax.swing.JTextPane rtfbodyTextPane;
353  private javax.swing.JLabel subjectLabel;
354  private javax.swing.JLabel subjectText;
355  private javax.swing.JScrollPane textbodyScrollPane;
356  private javax.swing.JTextArea textbodyTextArea;
357  private javax.swing.JLabel toLabel;
358  private javax.swing.JLabel toText;
359  private javax.swing.JButton viewInNewWindowButton;
360  // End of variables declaration//GEN-END:variables
361 
362  @Override
363  public void setNode(Node node) {
364  if (node == null) {
365  resetComponent();
366  return;
367  }
368 
369  artifact = node.getLookup().lookup(BlackboardArtifact.class);
370  if (artifact == null) {
371  resetComponent();
372  return;
373  }
374 
375  /*
376  * If the artifact is a keyword hit, use the associated artifact as the
377  * one to show in this viewer
378  */
379  if (artifact.getArtifactTypeID() == TSK_KEYWORD_HIT.getTypeID()) {
380  try {
381  getAssociatedArtifact(artifact).ifPresent(associatedArtifact -> {
382  artifact = associatedArtifact;
383  });
384  } catch (TskCoreException ex) {
385  LOGGER.log(Level.SEVERE, "error getting associated artifact", ex);
386  }
387  }
388 
389  if (artifact.getArtifactTypeID() == TSK_MESSAGE.getTypeID()) {
390  displayMsg();
391  } else if (artifact.getArtifactTypeID() == TSK_EMAIL_MSG.getTypeID()) {
392  displayEmailMsg();
393  } else {
394  resetComponent();
395  }
396  }
397 
408  private static Optional<BlackboardArtifact> getAssociatedArtifact(final BlackboardArtifact artifact) throws TskCoreException {
409  BlackboardAttribute attribute = artifact.getAttribute(TSK_ASSOCIATED_TYPE);
410  if (attribute != null) {
411  return Optional.of(artifact.getSleuthkitCase().getArtifactByArtifactId(attribute.getValueLong()));
412  }
413  return Optional.empty();
414  }
415 
416  @Override
417  @NbBundle.Messages("MessageContentViewer.title=Message")
418  public String getTitle() {
419  return Bundle.MessageContentViewer_title();
420  }
421 
422  @Override
423  @NbBundle.Messages("MessageContentViewer.toolTip=Displays messages.")
424  public String getToolTip() {
425  return Bundle.MessageContentViewer_toolTip();
426  }
427 
428  @Override
429  public DataContentViewer createInstance() {
430  return new MessageContentViewer();
431  }
432 
433  @Override
434  public Component getComponent() {
435  return this;
436  }
437 
438  @Override
439  final public void resetComponent() {
440  // reset all fields
441  fromText.setText("");
442  fromLabel.setEnabled(false);
443  toText.setText("");
444  toLabel.setEnabled(false);
445  ccText.setText("");
446  ccLabel.setEnabled(false);
447  subjectText.setText("");
448  subjectLabel.setEnabled(false);
449  datetimeText.setText("");
450  datetimeText.setEnabled(false);
451  directionText.setText("");
452  directionText.setEnabled(false);
453 
454  headersTextArea.setText("");
455  rtfbodyTextPane.setText("");
456  htmlPanel.reset();
457  textbodyTextArea.setText("");
458  msgbodyTabbedPane.setEnabled(false);
459  drp.setNode(null);
460  }
461 
462  @Override
463  public boolean isSupported(Node node) {
464  BlackboardArtifact nodeArtifact = node.getLookup().lookup(BlackboardArtifact.class);
465 
466  if (nodeArtifact == null) {
467  return false;
468  }
469  //if the artifact is a keyword hit, check if its associated artifact is a message or email.
470  if (nodeArtifact.getArtifactTypeID() == TSK_KEYWORD_HIT.getTypeID()) {
471  try {
472  if (getAssociatedArtifact(nodeArtifact).map(MessageContentViewer::isMessageArtifact).orElse(false)) {
473  return true;
474  }
475  } catch (TskCoreException ex) {
476  LOGGER.log(Level.SEVERE, "error getting associated artifact", ex);
477  }
478  }
479  return isMessageArtifact(nodeArtifact);
480  }
481 
491  private static boolean isMessageArtifact(BlackboardArtifact nodeArtifact) {
492  final int artifactTypeID = nodeArtifact.getArtifactTypeID();
493  return artifactTypeID == TSK_EMAIL_MSG.getTypeID()
494  || artifactTypeID == TSK_MESSAGE.getTypeID();
495  }
496 
497  @Override
498  public int isPreferred(Node node) {
499  if (isSupported(node)) {
500  return 7;
501  }
502  return 0;
503  }
504 
514  private void configureTextArea(BlackboardAttribute.ATTRIBUTE_TYPE type, int index) throws TskCoreException {
515  String attributeText = getAttributeValueSafe(artifact, type);
516 
517  if (index == HTML_TAB_INDEX && StringUtils.isNotBlank(attributeText)) {
518  htmlPanel.setHtmlText(attributeText);
519  } else {
520  JTextComponent textComponent = textAreas.get(index);
521  if (textComponent != null) {
522  textComponent.setText(attributeText);
523  textComponent.setCaretPosition(0); //make sure we start at the top
524  }
525  }
526 
527  final boolean hasText = attributeText.length() > 0;
528 
529  msgbodyTabbedPane.setEnabledAt(index, hasText);
530  if (hasText) {
531  msgbodyTabbedPane.setSelectedIndex(index);
532  }
533  }
534 
535  private void enableCommonFields() {
536  msgbodyTabbedPane.setEnabled(true);
537  fromLabel.setEnabled(true);
538  toLabel.setEnabled(true);
539  subjectLabel.setEnabled(true);
540  datetimeText.setEnabled(true);
541  }
542 
543  private void configureAttachments() throws TskCoreException {
544  //TODO: Replace this with code to get the actual attachements!
545  final Set<AbstractFile> attachments = artifact.getChildren().stream()
546  .filter(AbstractFile.class::isInstance)
547  .map(AbstractFile.class::cast)
548  .collect(Collectors.toSet());
549  final int numberOfAttachments = attachments.size();
550 
551  msgbodyTabbedPane.setEnabledAt(ATTM_TAB_INDEX, numberOfAttachments > 0);
552  msgbodyTabbedPane.setTitleAt(ATTM_TAB_INDEX, "Attachments (" + numberOfAttachments + ")");
553  drp.setNode(new TableFilterNode(new DataResultFilterNode(new AbstractNode(
554  new AttachmentsChildren(attachments))), true));
555  }
556 
557  private static String wrapInHtmlBody(String htmlText) {
558  return "<html><body>" + htmlText + "</body></html>";
559  }
560 
561  private void displayEmailMsg() {
562  enableCommonFields();
563 
564  directionText.setEnabled(false);
565  ccLabel.setEnabled(true);
566 
567  try {
568  this.fromText.setText(getAttributeValueSafe(artifact, TSK_EMAIL_FROM));
569  this.fromText.setToolTipText(getAttributeValueSafe(artifact, TSK_EMAIL_FROM));
570  this.toText.setText(getAttributeValueSafe(artifact, TSK_EMAIL_TO));
571  this.toText.setToolTipText(getAttributeValueSafe(artifact, TSK_EMAIL_TO));
572  this.directionText.setText("");
573  this.ccText.setText(getAttributeValueSafe(artifact, TSK_EMAIL_CC));
574  this.ccText.setToolTipText(getAttributeValueSafe(artifact, TSK_EMAIL_CC));
575  this.subjectText.setText(getAttributeValueSafe(artifact, TSK_SUBJECT));
576  this.datetimeText.setText(getAttributeValueSafe(artifact, TSK_DATETIME_RCVD));
577 
578  configureTextArea(TSK_HEADERS, HDR_TAB_INDEX);
579  configureTextArea(TSK_EMAIL_CONTENT_PLAIN, TEXT_TAB_INDEX);
580  configureTextArea(TSK_EMAIL_CONTENT_HTML, HTML_TAB_INDEX);
581  configureTextArea(TSK_EMAIL_CONTENT_RTF, RTF_TAB_INDEX);
582  configureAttachments();
583  } catch (TskCoreException ex) {
584  LOGGER.log(Level.WARNING, "Failed to get attributes for email message.", ex); //NON-NLS
585  }
586  }
587 
588  private void displayMsg() {
589  enableCommonFields();
590 
591  directionText.setEnabled(true);
592  ccLabel.setEnabled(false);
593 
594  try {
595  this.fromText.setText(getAttributeValueSafe(artifact, TSK_PHONE_NUMBER_FROM));
596  this.toText.setText(getAttributeValueSafe(artifact, TSK_PHONE_NUMBER_TO));
597  this.directionText.setText(getAttributeValueSafe(artifact, TSK_DIRECTION));
598  this.ccText.setText("");
599  this.subjectText.setText(getAttributeValueSafe(artifact, TSK_SUBJECT));
600  this.datetimeText.setText(getAttributeValueSafe(artifact, TSK_DATETIME));
601 
602  msgbodyTabbedPane.setEnabledAt(HTML_TAB_INDEX, false);
603  msgbodyTabbedPane.setEnabledAt(RTF_TAB_INDEX, false);
604  msgbodyTabbedPane.setEnabledAt(HDR_TAB_INDEX, false);
605  msgbodyTabbedPane.setEnabledAt(HDR_TAB_INDEX, false);
606  configureTextArea(TSK_TEXT, TEXT_TAB_INDEX);
607  configureAttachments();
608  } catch (TskCoreException ex) {
609  LOGGER.log(Level.WARNING, "Failed to get attributes for message.", ex); //NON-NLS
610  }
611  }
612 
613  private static String getAttributeValueSafe(BlackboardArtifact artifact, BlackboardAttribute.ATTRIBUTE_TYPE type) throws TskCoreException {
614  return Optional.ofNullable(artifact.getAttribute(new BlackboardAttribute.Type(type)))
615  .map(BlackboardAttribute::getDisplayString)
616  .orElse("");
617  }
618 
626  static private String cleanseHTML(String htmlInString) {
627 
628  Document doc = Jsoup.parse(htmlInString);
629 
630  //fix all img tags
631  doc.select("img[src]").forEach(img -> img.attr("src", ""));
632 
633  return doc.html();
634  }
635 
636  private static class AttachmentsChildren extends Children.Keys<AbstractFile> {
637 
638  private final Set<AbstractFile> attachments;
639 
640  AttachmentsChildren(Set<AbstractFile> attachments) {
641  this.attachments = attachments;
642  }
643 
644  @Override
645  protected Node[] createNodes(AbstractFile t) {
646  return new Node[]{new AttachmentNode(t)};
647  }
648 
649  @Override
650  protected void addNotify() {
651  super.addNotify();
652  setKeys(attachments);
653  }
654  }
655 
662  private static class AttachmentNode extends FileNode {
663 
664  AttachmentNode(AbstractFile file) {
665  super(file, false);
666  }
667 
668  @Override
669  protected Sheet createSheet() {
670  Sheet sheet = super.createSheet();
671  Set<String> keepProps = new HashSet<>(Arrays.asList(
672  NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.nameColLbl"),
673  NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.createSheet.score.name"),
674  NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.createSheet.comment.name"),
675  NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.createSheet.count.name"),
676  NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.sizeColLbl"),
677  NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.mimeType"),
678  NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.knownColLbl")));
679 
680  //Remove all other props except for the ones above
681  Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
682  for (Property<?> p : sheetSet.getProperties()) {
683  if (!keepProps.contains(p.getName())) {
684  sheetSet.remove(p.getName());
685  }
686  }
687 
688  return sheet;
689  }
690  }
691 }
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)
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 Jun 21 2019
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.