Autopsy  4.8.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-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  */
19 package org.sleuthkit.autopsy.contentviewers;
20 
21 import java.awt.Component;
22 import java.util.Arrays;
23 import java.util.List;
24 import java.util.Optional;
25 import java.util.Set;
26 import java.util.logging.Level;
27 import java.util.stream.Collectors;
28 import javax.swing.text.JTextComponent;
29 import org.apache.commons.lang3.StringUtils;
30 import org.jsoup.Jsoup;
31 import org.jsoup.nodes.Document;
32 import org.openide.explorer.ExplorerManager;
33 import org.openide.nodes.AbstractNode;
34 import org.openide.nodes.Children;
35 import org.openide.nodes.Node;
36 import org.openide.nodes.Sheet;
37 import org.openide.util.NbBundle;
38 import org.openide.util.lookup.ServiceProvider;
50 import org.sleuthkit.datamodel.AbstractFile;
51 import org.sleuthkit.datamodel.BlackboardArtifact;
52 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG;
53 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT;
54 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE;
55 import org.sleuthkit.datamodel.BlackboardAttribute;
56 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT;
57 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME;
58 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_RCVD;
59 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION;
60 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL_CC;
61 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL_CONTENT_HTML;
62 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL_CONTENT_PLAIN;
63 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL_CONTENT_RTF;
64 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL_FROM;
65 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL_TO;
66 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_HEADERS;
67 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM;
68 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO;
69 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SUBJECT;
70 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT;
71 import org.sleuthkit.datamodel.ContentTag;
72 import org.sleuthkit.datamodel.TskCoreException;
73 
77 @ServiceProvider(service = DataContentViewer.class, position = 5)
78 @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
79 public class MessageContentViewer extends javax.swing.JPanel implements DataContentViewer {
80 
81  private static final long serialVersionUID = 1L;
82  private static final Logger LOGGER = Logger.getLogger(MessageContentViewer.class.getName());
83  private static final BlackboardAttribute.Type TSK_ASSOCIATED_TYPE = new BlackboardAttribute.Type(TSK_ASSOCIATED_ARTIFACT);
84 
85  private static final int HDR_TAB_INDEX = 0;
86  private static final int TEXT_TAB_INDEX = 1;
87  private static final int HTML_TAB_INDEX = 2;
88  private static final int RTF_TAB_INDEX = 3;
89  private static final int ATTM_TAB_INDEX = 4;
90 
91  private final List<JTextComponent> textAreas;
92 
96  private BlackboardArtifact artifact;
97  private final DataResultPanel drp;
98  private ExplorerManager drpExplorerManager;
99 
103  @NbBundle.Messages("MessageContentViewer.AtrachmentsPanel.title=Attachments")
105  initComponents();
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  textAreas = Arrays.asList(headersTextArea, textbodyTextArea, htmlbodyTextPane, rtfbodyTextPane);
111 
112  Utilities.configureTextPaneAsHtml(htmlbodyTextPane);
113  Utilities.configureTextPaneAsRtf(rtfbodyTextPane);
114  resetComponent();
115 
116  }
117 
118  @Override
119  public void addNotify() {
120  super.addNotify(); //To change body of generated methods, choose Tools | Templates.
121 
122  drp.open();
123  drpExplorerManager = drp.getExplorerManager();
124  drpExplorerManager.addPropertyChangeListener(evt
125  -> viewInNewWindowButton.setEnabled(drpExplorerManager.getSelectedNodes().length == 1));
126  }
127 
133  @SuppressWarnings("unchecked")
134  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
135  private void initComponents() {
136 
137  envelopePanel = new javax.swing.JPanel();
138  fromLabel = new javax.swing.JLabel();
139  datetimeText = new javax.swing.JLabel();
140  fromText = new javax.swing.JLabel();
141  toLabel = new javax.swing.JLabel();
142  toText = new javax.swing.JLabel();
143  ccLabel = new javax.swing.JLabel();
144  ccText = new javax.swing.JLabel();
145  subjectLabel = new javax.swing.JLabel();
146  subjectText = new javax.swing.JLabel();
147  directionText = new javax.swing.JLabel();
148  msgbodyTabbedPane = new javax.swing.JTabbedPane();
149  headersScrollPane = new javax.swing.JScrollPane();
150  headersTextArea = new javax.swing.JTextArea();
151  textbodyScrollPane = new javax.swing.JScrollPane();
152  textbodyTextArea = new javax.swing.JTextArea();
153  htmlPane = new javax.swing.JPanel();
154  htmlScrollPane = new javax.swing.JScrollPane();
155  htmlbodyTextPane = new javax.swing.JTextPane();
156  showImagesToggleButton = new javax.swing.JToggleButton();
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  htmlScrollPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
270 
271  htmlbodyTextPane.setEditable(false);
272  htmlScrollPane.setViewportView(htmlbodyTextPane);
273 
274  org.openide.awt.Mnemonics.setLocalizedText(showImagesToggleButton, "Show Images");
275  showImagesToggleButton.addActionListener(new java.awt.event.ActionListener() {
276  public void actionPerformed(java.awt.event.ActionEvent evt) {
277  showImagesToggleButtonActionPerformed(evt);
278  }
279  });
280 
281  javax.swing.GroupLayout htmlPaneLayout = new javax.swing.GroupLayout(htmlPane);
282  htmlPane.setLayout(htmlPaneLayout);
283  htmlPaneLayout.setHorizontalGroup(
284  htmlPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
285  .addComponent(htmlScrollPane)
286  .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, htmlPaneLayout.createSequentialGroup()
287  .addContainerGap(533, Short.MAX_VALUE)
288  .addComponent(showImagesToggleButton)
289  .addGap(3, 3, 3))
290  );
291  htmlPaneLayout.setVerticalGroup(
292  htmlPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
293  .addGroup(htmlPaneLayout.createSequentialGroup()
294  .addComponent(showImagesToggleButton)
295  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
296  .addComponent(htmlScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 333, Short.MAX_VALUE)
297  .addGap(0, 0, 0))
298  );
299 
300  msgbodyTabbedPane.addTab(org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.htmlPane.TabConstraints.tabTitle"), htmlPane); // NOI18N
301 
302  rtfbodyScrollPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
303 
304  rtfbodyTextPane.setEditable(false);
305  rtfbodyScrollPane.setViewportView(rtfbodyTextPane);
306 
307  msgbodyTabbedPane.addTab(org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.rtfbodyScrollPane.TabConstraints.tabTitle"), rtfbodyScrollPane); // NOI18N
308 
309  org.openide.awt.Mnemonics.setLocalizedText(viewInNewWindowButton, org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.viewInNewWindowButton.text")); // NOI18N
310  viewInNewWindowButton.addActionListener(new java.awt.event.ActionListener() {
311  public void actionPerformed(java.awt.event.ActionEvent evt) {
312  viewInNewWindowButtonActionPerformed(evt);
313  }
314  });
315 
316  javax.swing.GroupLayout attachmentsPanelLayout = new javax.swing.GroupLayout(attachmentsPanel);
317  attachmentsPanel.setLayout(attachmentsPanelLayout);
318  attachmentsPanelLayout.setHorizontalGroup(
319  attachmentsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
320  .addGroup(attachmentsPanelLayout.createSequentialGroup()
321  .addGap(0, 0, 0)
322  .addGroup(attachmentsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
323  .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, attachmentsPanelLayout.createSequentialGroup()
324  .addComponent(viewInNewWindowButton)
325  .addGap(3, 3, 3))
326  .addComponent(attachmentsScrollPane, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 647, Short.MAX_VALUE)))
327  );
328  attachmentsPanelLayout.setVerticalGroup(
329  attachmentsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
330  .addGroup(attachmentsPanelLayout.createSequentialGroup()
331  .addGap(0, 0, 0)
332  .addComponent(viewInNewWindowButton)
333  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
334  .addComponent(attachmentsScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 333, Short.MAX_VALUE)
335  .addGap(0, 0, 0))
336  );
337 
338  msgbodyTabbedPane.addTab(org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.attachmentsPanel.TabConstraints.tabTitle"), attachmentsPanel); // NOI18N
339 
340  javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
341  this.setLayout(layout);
342  layout.setHorizontalGroup(
343  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
344  .addGroup(layout.createSequentialGroup()
345  .addGap(5, 5, 5)
346  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
347  .addComponent(msgbodyTabbedPane)
348  .addComponent(envelopePanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
349  .addGap(5, 5, 5))
350  );
351  layout.setVerticalGroup(
352  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
353  .addGroup(layout.createSequentialGroup()
354  .addGap(5, 5, 5)
355  .addComponent(envelopePanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
356  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
357  .addComponent(msgbodyTabbedPane)
358  .addGap(5, 5, 5))
359  );
360  }// </editor-fold>//GEN-END:initComponents
361 
362  @NbBundle.Messages({
363  "MessageContentViewer.showImagesToggleButton.hide.text=Hide Images",
364  "MessageContentViewer.showImagesToggleButton.text=Show Images"})
365  private void showImagesToggleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_showImagesToggleButtonActionPerformed
366  try {
367  String htmlText = getAttributeValueSafe(artifact, TSK_EMAIL_CONTENT_HTML);
368  if (false == htmlText.isEmpty()) {
369  if (showImagesToggleButton.isSelected()) {
370  showImagesToggleButton.setText(Bundle.MessageContentViewer_showImagesToggleButton_hide_text());
371  this.htmlbodyTextPane.setText(wrapInHtmlBody(htmlText));
372  } else {
373  showImagesToggleButton.setText(Bundle.MessageContentViewer_showImagesToggleButton_text());
374  this.htmlbodyTextPane.setText(wrapInHtmlBody(cleanseHTML(htmlText)));
375  }
376  }
377  } catch (TskCoreException ex) {
378  LOGGER.log(Level.WARNING, "Failed to get attributes for email message.", ex); //NON-NLS
379  }
380  }//GEN-LAST:event_showImagesToggleButtonActionPerformed
381 
382  private void viewInNewWindowButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_viewInNewWindowButtonActionPerformed
383  new NewWindowViewAction("View in new window", drpExplorerManager.getSelectedNodes()[0]).actionPerformed(evt);
384  }//GEN-LAST:event_viewInNewWindowButtonActionPerformed
385 
386 
387  // Variables declaration - do not modify//GEN-BEGIN:variables
388  private javax.swing.JPanel attachmentsPanel;
389  private javax.swing.JScrollPane attachmentsScrollPane;
390  private javax.swing.JLabel ccLabel;
391  private javax.swing.JLabel ccText;
392  private javax.swing.JLabel datetimeText;
393  private javax.swing.JLabel directionText;
394  private javax.swing.JPanel envelopePanel;
395  private javax.swing.JLabel fromLabel;
396  private javax.swing.JLabel fromText;
397  private javax.swing.JScrollPane headersScrollPane;
398  private javax.swing.JTextArea headersTextArea;
399  private javax.swing.JPanel htmlPane;
400  private javax.swing.JScrollPane htmlScrollPane;
401  private javax.swing.JTextPane htmlbodyTextPane;
402  private javax.swing.JTabbedPane msgbodyTabbedPane;
403  private javax.swing.JScrollPane rtfbodyScrollPane;
404  private javax.swing.JTextPane rtfbodyTextPane;
405  private javax.swing.JToggleButton showImagesToggleButton;
406  private javax.swing.JLabel subjectLabel;
407  private javax.swing.JLabel subjectText;
408  private javax.swing.JScrollPane textbodyScrollPane;
409  private javax.swing.JTextArea textbodyTextArea;
410  private javax.swing.JLabel toLabel;
411  private javax.swing.JLabel toText;
412  private javax.swing.JButton viewInNewWindowButton;
413  // End of variables declaration//GEN-END:variables
414 
415  @Override
416  public void setNode(Node node) {
417  if (node == null) {
418  resetComponent();
419  return;
420  }
421 
422  artifact = node.getLookup().lookup(BlackboardArtifact.class);
423  if (artifact == null) {
424  resetComponent();
425  return;
426  }
427 
428  /*
429  * If the artifact is a keyword hit, use the associated artifact as the
430  * one to show in this viewer
431  */
432  if (artifact.getArtifactTypeID() == TSK_KEYWORD_HIT.getTypeID()) {
433  try {
434  getAssociatedArtifact(artifact).ifPresent(associatedArtifact -> {
435  artifact = associatedArtifact;
436  });
437  } catch (TskCoreException ex) {
438  LOGGER.log(Level.SEVERE, "error getting associated artifact", ex);
439  }
440  }
441 
442  if (artifact.getArtifactTypeID() == TSK_MESSAGE.getTypeID()) {
443  displayMsg();
444  } else if (artifact.getArtifactTypeID() == TSK_EMAIL_MSG.getTypeID()) {
445  displayEmailMsg();
446  } else {
447  resetComponent();
448  }
449  }
450 
461  private static Optional<BlackboardArtifact> getAssociatedArtifact(final BlackboardArtifact artifact) throws TskCoreException {
462  BlackboardAttribute attribute = artifact.getAttribute(TSK_ASSOCIATED_TYPE);
463  if (attribute != null) {
464  return Optional.of(artifact.getSleuthkitCase().getArtifactByArtifactId(attribute.getValueLong()));
465  }
466  return Optional.empty();
467  }
468 
469  @Override
470  @NbBundle.Messages("MessageContentViewer.title=Message")
471  public String getTitle() {
472  return Bundle.MessageContentViewer_title();
473  }
474 
475  @Override
476  @NbBundle.Messages("MessageContentViewer.toolTip=Displays messages.")
477  public String getToolTip() {
478  return Bundle.MessageContentViewer_toolTip();
479  }
480 
481  @Override
482  public DataContentViewer createInstance() {
483  return new MessageContentViewer();
484  }
485 
486  @Override
487  public Component getComponent() {
488  return this;
489  }
490 
491  @Override
492  final public void resetComponent() {
493  // reset all fields
494  fromText.setText("");
495  fromLabel.setEnabled(false);
496  toText.setText("");
497  toLabel.setEnabled(false);
498  ccText.setText("");
499  ccLabel.setEnabled(false);
500  subjectText.setText("");
501  subjectLabel.setEnabled(false);
502  datetimeText.setText("");
503  datetimeText.setEnabled(false);
504  directionText.setText("");
505  directionText.setEnabled(false);
506 
507  headersTextArea.setText("");
508  rtfbodyTextPane.setText("");
509  htmlbodyTextPane.setText("");
510  textbodyTextArea.setText("");
511  showImagesToggleButton.setEnabled(false);
512  msgbodyTabbedPane.setEnabled(false);
513  }
514 
515  @Override
516  public boolean isSupported(Node node) {
517  BlackboardArtifact nodeArtifact = node.getLookup().lookup(BlackboardArtifact.class);
518 
519  if (nodeArtifact == null) {
520  return false;
521  }
522  //if the artifact is a keyword hit, check if its associated artifact is a message or email.
523  if (nodeArtifact.getArtifactTypeID() == TSK_KEYWORD_HIT.getTypeID()) {
524  try {
525  if (getAssociatedArtifact(nodeArtifact).map(MessageContentViewer::isMessageArtifact).orElse(false)) {
526  return true;
527  }
528  } catch (TskCoreException ex) {
529  LOGGER.log(Level.SEVERE, "error getting associated artifact", ex);
530  }
531  }
532  return isMessageArtifact(nodeArtifact);
533  }
534 
544  private static boolean isMessageArtifact(BlackboardArtifact nodeArtifact) {
545  final int artifactTypeID = nodeArtifact.getArtifactTypeID();
546  return artifactTypeID == TSK_EMAIL_MSG.getTypeID()
547  || artifactTypeID == TSK_MESSAGE.getTypeID();
548  }
549 
550  @Override
551  public int isPreferred(Node node) {
552  if (isSupported(node)) {
553  return 7;
554  }
555  return 0;
556  }
557 
567  private void configureTextArea(BlackboardAttribute.ATTRIBUTE_TYPE type, int index) throws TskCoreException {
568  String attributeText = getAttributeValueSafe(artifact, type);
569 
570  if (index == HTML_TAB_INDEX && StringUtils.isNotBlank(attributeText)) {
571  //special case for HTML, we need to 'cleanse' it
572  attributeText = wrapInHtmlBody(cleanseHTML(attributeText));
573  }
574  JTextComponent textComponent = textAreas.get(index);
575  textComponent.setText(attributeText);
576  textComponent.setCaretPosition(0); //make sure we start at the top
577  final boolean hasText = attributeText.length() > 0;
578 
579  msgbodyTabbedPane.setEnabledAt(index, hasText);
580  if (hasText) {
581  msgbodyTabbedPane.setSelectedIndex(index);
582  }
583  }
584 
585  private void enableCommonFields() {
586  msgbodyTabbedPane.setEnabled(true);
587  fromLabel.setEnabled(true);
588  toLabel.setEnabled(true);
589  subjectLabel.setEnabled(true);
590  datetimeText.setEnabled(true);
591  }
592 
593  private void configureAttachments() throws TskCoreException {
594  //TODO: Replace this with code to get the actual attachements!
595  final Set<AbstractFile> attachments = artifact.getChildren().stream()
596  .filter(AbstractFile.class::isInstance)
597  .map(AbstractFile.class::cast)
598  .collect(Collectors.toSet());
599  final int numberOfAttachments = attachments.size();
600 
601  msgbodyTabbedPane.setEnabledAt(ATTM_TAB_INDEX, numberOfAttachments > 0);
602  msgbodyTabbedPane.setTitleAt(ATTM_TAB_INDEX, "Attachments (" + numberOfAttachments + ")");
603  drp.setNode(new TableFilterNode(new DataResultFilterNode(new AbstractNode(
604  new AttachmentsChildren(attachments)), null), true));
605  }
606 
607  private static String wrapInHtmlBody(String htmlText) {
608  return "<html><body>" + htmlText + "</body></html>";
609  }
610 
611  private void displayEmailMsg() {
612  enableCommonFields();
613 
614  directionText.setEnabled(false);
615  ccLabel.setEnabled(true);
616 
617  showImagesToggleButton.setEnabled(true);
618  showImagesToggleButton.setText("Show Images");
619  showImagesToggleButton.setSelected(false);
620 
621  try {
622  this.fromText.setText(getAttributeValueSafe(artifact, TSK_EMAIL_FROM));
623  this.fromText.setToolTipText(getAttributeValueSafe(artifact, TSK_EMAIL_FROM));
624  this.toText.setText(getAttributeValueSafe(artifact, TSK_EMAIL_TO));
625  this.toText.setToolTipText(getAttributeValueSafe(artifact, TSK_EMAIL_TO));
626  this.directionText.setText("");
627  this.ccText.setText(getAttributeValueSafe(artifact, TSK_EMAIL_CC));
628  this.ccText.setToolTipText(getAttributeValueSafe(artifact, TSK_EMAIL_CC));
629  this.subjectText.setText(getAttributeValueSafe(artifact, TSK_SUBJECT));
630  this.datetimeText.setText(getAttributeValueSafe(artifact, TSK_DATETIME_RCVD));
631 
632  configureTextArea(TSK_HEADERS, HDR_TAB_INDEX);
633  configureTextArea(TSK_EMAIL_CONTENT_PLAIN, TEXT_TAB_INDEX);
634  configureTextArea(TSK_EMAIL_CONTENT_HTML, HTML_TAB_INDEX);
635  configureTextArea(TSK_EMAIL_CONTENT_RTF, RTF_TAB_INDEX);
636  configureAttachments();
637  } catch (TskCoreException ex) {
638  LOGGER.log(Level.WARNING, "Failed to get attributes for email message.", ex); //NON-NLS
639  }
640  }
641 
642  private void displayMsg() {
643  enableCommonFields();
644 
645  directionText.setEnabled(true);
646  ccLabel.setEnabled(false);
647 
648  try {
649  this.fromText.setText(getAttributeValueSafe(artifact, TSK_PHONE_NUMBER_FROM));
650  this.toText.setText(getAttributeValueSafe(artifact, TSK_PHONE_NUMBER_TO));
651  this.directionText.setText(getAttributeValueSafe(artifact, TSK_DIRECTION));
652  this.ccText.setText("");
653  this.subjectText.setText(getAttributeValueSafe(artifact, TSK_SUBJECT));
654  this.datetimeText.setText(getAttributeValueSafe(artifact, TSK_DATETIME));
655 
656  msgbodyTabbedPane.setEnabledAt(HTML_TAB_INDEX, false);
657  msgbodyTabbedPane.setEnabledAt(RTF_TAB_INDEX, false);
658  msgbodyTabbedPane.setEnabledAt(HDR_TAB_INDEX, false);
659  msgbodyTabbedPane.setEnabledAt(HDR_TAB_INDEX, false);
660  configureTextArea(TSK_TEXT, TEXT_TAB_INDEX);
661  configureAttachments();
662  } catch (TskCoreException ex) {
663  LOGGER.log(Level.WARNING, "Failed to get attributes for message.", ex); //NON-NLS
664  }
665  }
666 
667  private static String getAttributeValueSafe(BlackboardArtifact artifact, BlackboardAttribute.ATTRIBUTE_TYPE type) throws TskCoreException {
668  return Optional.ofNullable(artifact.getAttribute(new BlackboardAttribute.Type(type)))
669  .map(BlackboardAttribute::getDisplayString)
670  .orElse("");
671  }
672 
680  static private String cleanseHTML(String htmlInString) {
681 
682  Document doc = Jsoup.parse(htmlInString);
683 
684  //fix all img tags
685  doc.select("img[src]").forEach(img -> img.attr("src", ""));
686 
687  return doc.html();
688  }
689 
690  private static class AttachmentsChildren extends Children.Keys<AbstractFile> {
691 
692  private final Set<AbstractFile> attachments;
693 
694  AttachmentsChildren(Set<AbstractFile> attachments) {
695  this.attachments = attachments;
696  }
697 
698  @Override
699  protected Node[] createNodes(AbstractFile t) {
700  return new Node[]{new AttachmentNode(t)};
701  }
702 
703  @Override
704  protected void addNotify() {
705  super.addNotify();
706  setKeys(attachments);
707  }
708  }
709 
716  private static class AttachmentNode extends FileNode {
717 
718  AttachmentNode(AbstractFile file) {
719  super(file, false);
720  }
721 
722  @Override
723  protected Sheet createSheet() {
724  Sheet sheet = new Sheet();
725  Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
726  if (sheetSet == null) {
727  sheetSet = Sheet.createPropertiesSet();
728  sheet.put(sheetSet);
729  }
730  List<ContentTag> tags = getContentTagsFromDatabase();
731 
732  AbstractFile file = getContent();
733  sheetSet.put(new NodeProperty<>("Name", "Name", "Name", file.getName()));
734 
735  addScoreProperty(sheetSet, tags);
736 
737  CorrelationAttributeInstance correlationAttribute = null;
739  correlationAttribute = getCorrelationAttributeInstance();
740  }
741  addCommentProperty(sheetSet, tags, correlationAttribute);
742 
744  addCountProperty(sheetSet, correlationAttribute);
745  }
746  sheetSet.put(new NodeProperty<>("Size", "Size", "Size", file.getSize()));
747  sheetSet.put(new NodeProperty<>("Mime Type", "Mime Type", "Mime Type", StringUtils.defaultString(file.getMIMEType())));
748  sheetSet.put(new NodeProperty<>("Known", "Known", "Known", file.getKnown().getName()));
749 
750  return sheet;
751  }
752  }
753 }
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)
void showImagesToggleButtonActionPerformed(java.awt.event.ActionEvent evt)
static void configureTextPaneAsHtml(JTextPane pane)
Definition: Utilities.java:32
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
void viewInNewWindowButtonActionPerformed(java.awt.event.ActionEvent evt)

Copyright © 2012-2018 Basis Technology. Generated on: Thu Oct 4 2018
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.