Autopsy  4.5.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 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;
47 import org.sleuthkit.datamodel.AbstractFile;
48 import org.sleuthkit.datamodel.BlackboardArtifact;
49 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG;
50 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT;
51 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE;
52 import org.sleuthkit.datamodel.BlackboardAttribute;
53 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT;
54 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME;
55 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_RCVD;
56 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION;
57 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL_CC;
58 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL_CONTENT_HTML;
59 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL_CONTENT_PLAIN;
60 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL_CONTENT_RTF;
61 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL_FROM;
62 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL_TO;
63 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_HEADERS;
64 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM;
65 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO;
66 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SUBJECT;
67 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT;
68 import org.sleuthkit.datamodel.TskCoreException;
69 
73 @ServiceProvider(service = DataContentViewer.class, position = 4)
74 public class MessageContentViewer extends javax.swing.JPanel implements DataContentViewer {
75 
76  private static final long serialVersionUID = 1L;
77  private static final Logger LOGGER = Logger.getLogger(MessageContentViewer.class.getName());
78  private static final BlackboardAttribute.Type TSK_ASSOCIATED_TYPE = new BlackboardAttribute.Type(TSK_ASSOCIATED_ARTIFACT);
79 
80  private static final int HDR_TAB_INDEX = 0;
81  private static final int TEXT_TAB_INDEX = 1;
82  private static final int HTML_TAB_INDEX = 2;
83  private static final int RTF_TAB_INDEX = 3;
84  private static final int ATTM_TAB_INDEX = 4;
85 
86  private final List<JTextComponent> textAreas;
87 
91  private BlackboardArtifact artifact;
92  private final DataResultPanel drp;
93  private final ExplorerManager drpExplorerManager;
94 
98  @NbBundle.Messages("MessageContentViewer.AtrachmentsPanel.title=Attachments")
100  initComponents();
101  drp = DataResultPanel.createInstanceUninitialized(Bundle.MessageContentViewer_AtrachmentsPanel_title(), "", Node.EMPTY, 0, null);
102  attachmentsScrollPane.setViewportView(drp);
103  msgbodyTabbedPane.setEnabledAt(ATTM_TAB_INDEX, true);
104 
105  textAreas = Arrays.asList(headersTextArea, textbodyTextArea, htmlbodyTextPane, rtfbodyTextPane);
106 
107  Utilities.configureTextPaneAsHtml(htmlbodyTextPane);
108  Utilities.configureTextPaneAsRtf(rtfbodyTextPane);
109  resetComponent();
110 
111  drp.open();
112  drpExplorerManager = drp.getExplorerManager();
113  drpExplorerManager.addPropertyChangeListener(evt ->
114  viewInNewWindowButton.setEnabled(drpExplorerManager.getSelectedNodes().length == 1));
115  }
116 
122  @SuppressWarnings("unchecked")
123  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
124  private void initComponents() {
125 
126  envelopePanel = new javax.swing.JPanel();
127  fromLabel = new javax.swing.JLabel();
128  datetimeText = new javax.swing.JLabel();
129  fromText = new javax.swing.JLabel();
130  toLabel = new javax.swing.JLabel();
131  toText = new javax.swing.JLabel();
132  ccLabel = new javax.swing.JLabel();
133  ccText = new javax.swing.JLabel();
134  subjectLabel = new javax.swing.JLabel();
135  subjectText = new javax.swing.JLabel();
136  directionText = new javax.swing.JLabel();
137  msgbodyTabbedPane = new javax.swing.JTabbedPane();
138  headersScrollPane = new javax.swing.JScrollPane();
139  headersTextArea = new javax.swing.JTextArea();
140  textbodyScrollPane = new javax.swing.JScrollPane();
141  textbodyTextArea = new javax.swing.JTextArea();
142  htmlPane = new javax.swing.JPanel();
143  htmlScrollPane = new javax.swing.JScrollPane();
144  htmlbodyTextPane = new javax.swing.JTextPane();
145  showImagesToggleButton = new javax.swing.JToggleButton();
146  rtfbodyScrollPane = new javax.swing.JScrollPane();
147  rtfbodyTextPane = new javax.swing.JTextPane();
148  attachmentsPanel = new javax.swing.JPanel();
149  viewInNewWindowButton = new javax.swing.JButton();
150  attachmentsScrollPane = new javax.swing.JScrollPane();
151 
152  envelopePanel.setBackground(new java.awt.Color(204, 204, 204));
153 
154  org.openide.awt.Mnemonics.setLocalizedText(fromLabel, org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.fromLabel.text")); // NOI18N
155 
156  datetimeText.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
157  org.openide.awt.Mnemonics.setLocalizedText(datetimeText, org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.datetimeText.text")); // NOI18N
158 
159  org.openide.awt.Mnemonics.setLocalizedText(fromText, org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.fromText.text")); // NOI18N
160 
161  org.openide.awt.Mnemonics.setLocalizedText(toLabel, org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.toLabel.text")); // NOI18N
162 
163  org.openide.awt.Mnemonics.setLocalizedText(toText, org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.toText.text")); // NOI18N
164  toText.setAutoscrolls(true);
165  toText.setMinimumSize(new java.awt.Dimension(27, 14));
166 
167  org.openide.awt.Mnemonics.setLocalizedText(ccLabel, org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.ccLabel.text")); // NOI18N
168 
169  org.openide.awt.Mnemonics.setLocalizedText(ccText, org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.ccText.text")); // NOI18N
170  ccText.setMinimumSize(new java.awt.Dimension(27, 14));
171 
172  org.openide.awt.Mnemonics.setLocalizedText(subjectLabel, org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.subjectLabel.text")); // NOI18N
173 
174  org.openide.awt.Mnemonics.setLocalizedText(subjectText, org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.subjectText.text")); // NOI18N
175  subjectText.setMinimumSize(new java.awt.Dimension(26, 14));
176 
177  directionText.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
178  org.openide.awt.Mnemonics.setLocalizedText(directionText, org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.directionText.text")); // NOI18N
179 
180  javax.swing.GroupLayout envelopePanelLayout = new javax.swing.GroupLayout(envelopePanel);
181  envelopePanel.setLayout(envelopePanelLayout);
182  envelopePanelLayout.setHorizontalGroup(
183  envelopePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
184  .addGroup(envelopePanelLayout.createSequentialGroup()
185  .addGap(5, 5, 5)
186  .addGroup(envelopePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
187  .addGroup(envelopePanelLayout.createSequentialGroup()
188  .addGroup(envelopePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
189  .addComponent(fromLabel)
190  .addComponent(toLabel))
191  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
192  .addGroup(envelopePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
193  .addGroup(envelopePanelLayout.createSequentialGroup()
194  .addComponent(toText, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
195  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
196  .addComponent(directionText, javax.swing.GroupLayout.PREFERRED_SIZE, 66, javax.swing.GroupLayout.PREFERRED_SIZE))
197  .addGroup(envelopePanelLayout.createSequentialGroup()
198  .addComponent(fromText, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
199  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
200  .addComponent(datetimeText, javax.swing.GroupLayout.PREFERRED_SIZE, 140, javax.swing.GroupLayout.PREFERRED_SIZE))))
201  .addGroup(envelopePanelLayout.createSequentialGroup()
202  .addComponent(ccLabel)
203  .addGap(26, 26, 26)
204  .addComponent(ccText, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
205  .addGroup(envelopePanelLayout.createSequentialGroup()
206  .addComponent(subjectLabel)
207  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
208  .addComponent(subjectText, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
209  .addGap(5, 5, 5))
210  );
211  envelopePanelLayout.setVerticalGroup(
212  envelopePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
213  .addGroup(envelopePanelLayout.createSequentialGroup()
214  .addGap(5, 5, 5)
215  .addGroup(envelopePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
216  .addComponent(fromLabel)
217  .addComponent(datetimeText)
218  .addComponent(fromText))
219  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
220  .addGroup(envelopePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
221  .addComponent(toLabel)
222  .addComponent(toText, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
223  .addComponent(directionText))
224  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
225  .addGroup(envelopePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
226  .addComponent(ccLabel)
227  .addComponent(ccText, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
228  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
229  .addGroup(envelopePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
230  .addComponent(subjectLabel)
231  .addComponent(subjectText, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
232  .addGap(5, 5, 5))
233  );
234 
235  headersScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
236  headersScrollPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
237 
238  headersTextArea.setEditable(false);
239  headersTextArea.setColumns(20);
240  headersTextArea.setLineWrap(true);
241  headersTextArea.setRows(5);
242  headersTextArea.setWrapStyleWord(true);
243  headersScrollPane.setViewportView(headersTextArea);
244 
245  msgbodyTabbedPane.addTab(org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.headersScrollPane.TabConstraints.tabTitle"), headersScrollPane); // NOI18N
246 
247  textbodyScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
248  textbodyScrollPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
249 
250  textbodyTextArea.setEditable(false);
251  textbodyTextArea.setLineWrap(true);
252  textbodyTextArea.setRows(5);
253  textbodyTextArea.setWrapStyleWord(true);
254  textbodyScrollPane.setViewportView(textbodyTextArea);
255 
256  msgbodyTabbedPane.addTab(org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.textbodyScrollPane.TabConstraints.tabTitle"), textbodyScrollPane); // NOI18N
257 
258  htmlScrollPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
259 
260  htmlbodyTextPane.setEditable(false);
261  htmlScrollPane.setViewportView(htmlbodyTextPane);
262 
263  org.openide.awt.Mnemonics.setLocalizedText(showImagesToggleButton, "Show Images");
264  showImagesToggleButton.addActionListener(new java.awt.event.ActionListener() {
265  public void actionPerformed(java.awt.event.ActionEvent evt) {
266  showImagesToggleButtonActionPerformed(evt);
267  }
268  });
269 
270  javax.swing.GroupLayout htmlPaneLayout = new javax.swing.GroupLayout(htmlPane);
271  htmlPane.setLayout(htmlPaneLayout);
272  htmlPaneLayout.setHorizontalGroup(
273  htmlPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
274  .addComponent(htmlScrollPane)
275  .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, htmlPaneLayout.createSequentialGroup()
276  .addContainerGap(533, Short.MAX_VALUE)
277  .addComponent(showImagesToggleButton)
278  .addGap(3, 3, 3))
279  );
280  htmlPaneLayout.setVerticalGroup(
281  htmlPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
282  .addGroup(htmlPaneLayout.createSequentialGroup()
283  .addComponent(showImagesToggleButton)
284  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
285  .addComponent(htmlScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 333, Short.MAX_VALUE)
286  .addGap(0, 0, 0))
287  );
288 
289  msgbodyTabbedPane.addTab(org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.htmlPane.TabConstraints.tabTitle"), htmlPane); // NOI18N
290 
291  rtfbodyScrollPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
292 
293  rtfbodyTextPane.setEditable(false);
294  rtfbodyScrollPane.setViewportView(rtfbodyTextPane);
295 
296  msgbodyTabbedPane.addTab(org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.rtfbodyScrollPane.TabConstraints.tabTitle"), rtfbodyScrollPane); // NOI18N
297 
298  org.openide.awt.Mnemonics.setLocalizedText(viewInNewWindowButton, org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.viewInNewWindowButton.text")); // NOI18N
299  viewInNewWindowButton.addActionListener(new java.awt.event.ActionListener() {
300  public void actionPerformed(java.awt.event.ActionEvent evt) {
301  viewInNewWindowButtonActionPerformed(evt);
302  }
303  });
304 
305  javax.swing.GroupLayout attachmentsPanelLayout = new javax.swing.GroupLayout(attachmentsPanel);
306  attachmentsPanel.setLayout(attachmentsPanelLayout);
307  attachmentsPanelLayout.setHorizontalGroup(
308  attachmentsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
309  .addGroup(attachmentsPanelLayout.createSequentialGroup()
310  .addGap(0, 0, 0)
311  .addGroup(attachmentsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
312  .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, attachmentsPanelLayout.createSequentialGroup()
313  .addComponent(viewInNewWindowButton)
314  .addGap(3, 3, 3))
315  .addComponent(attachmentsScrollPane, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 647, Short.MAX_VALUE)))
316  );
317  attachmentsPanelLayout.setVerticalGroup(
318  attachmentsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
319  .addGroup(attachmentsPanelLayout.createSequentialGroup()
320  .addGap(0, 0, 0)
321  .addComponent(viewInNewWindowButton)
322  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
323  .addComponent(attachmentsScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 333, Short.MAX_VALUE)
324  .addGap(0, 0, 0))
325  );
326 
327  msgbodyTabbedPane.addTab(org.openide.util.NbBundle.getMessage(MessageContentViewer.class, "MessageContentViewer.attachmentsPanel.TabConstraints.tabTitle"), attachmentsPanel); // NOI18N
328 
329  javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
330  this.setLayout(layout);
331  layout.setHorizontalGroup(
332  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
333  .addGroup(layout.createSequentialGroup()
334  .addGap(5, 5, 5)
335  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
336  .addComponent(msgbodyTabbedPane)
337  .addComponent(envelopePanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
338  .addGap(5, 5, 5))
339  );
340  layout.setVerticalGroup(
341  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
342  .addGroup(layout.createSequentialGroup()
343  .addGap(5, 5, 5)
344  .addComponent(envelopePanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
345  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
346  .addComponent(msgbodyTabbedPane)
347  .addGap(5, 5, 5))
348  );
349  }// </editor-fold>//GEN-END:initComponents
350 
351  @NbBundle.Messages({
352  "MessageContentViewer.showImagesToggleButton.hide.text=Hide Images",
353  "MessageContentViewer.showImagesToggleButton.text=Show Images"})
354  private void showImagesToggleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_showImagesToggleButtonActionPerformed
355  try {
356  String htmlText = getAttributeValueSafe(artifact, TSK_EMAIL_CONTENT_HTML);
357  if (false == htmlText.isEmpty()) {
358  if (showImagesToggleButton.isSelected()) {
359  showImagesToggleButton.setText(Bundle.MessageContentViewer_showImagesToggleButton_hide_text());
360  this.htmlbodyTextPane.setText(wrapInHtmlBody(htmlText));
361  } else {
362  showImagesToggleButton.setText(Bundle.MessageContentViewer_showImagesToggleButton_text());
363  this.htmlbodyTextPane.setText(wrapInHtmlBody(cleanseHTML(htmlText)));
364  }
365  }
366  } catch (TskCoreException ex) {
367  LOGGER.log(Level.WARNING, "Failed to get attributes for email message.", ex); //NON-NLS
368  }
369  }//GEN-LAST:event_showImagesToggleButtonActionPerformed
370 
371  private void viewInNewWindowButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_viewInNewWindowButtonActionPerformed
372  new NewWindowViewAction("View in new window", drpExplorerManager.getSelectedNodes()[0]).actionPerformed(evt);
373  }//GEN-LAST:event_viewInNewWindowButtonActionPerformed
374 
375 
376  // Variables declaration - do not modify//GEN-BEGIN:variables
377  private javax.swing.JPanel attachmentsPanel;
378  private javax.swing.JScrollPane attachmentsScrollPane;
379  private javax.swing.JLabel ccLabel;
380  private javax.swing.JLabel ccText;
381  private javax.swing.JLabel datetimeText;
382  private javax.swing.JLabel directionText;
383  private javax.swing.JPanel envelopePanel;
384  private javax.swing.JLabel fromLabel;
385  private javax.swing.JLabel fromText;
386  private javax.swing.JScrollPane headersScrollPane;
387  private javax.swing.JTextArea headersTextArea;
388  private javax.swing.JPanel htmlPane;
389  private javax.swing.JScrollPane htmlScrollPane;
390  private javax.swing.JTextPane htmlbodyTextPane;
391  private javax.swing.JTabbedPane msgbodyTabbedPane;
392  private javax.swing.JScrollPane rtfbodyScrollPane;
393  private javax.swing.JTextPane rtfbodyTextPane;
394  private javax.swing.JToggleButton showImagesToggleButton;
395  private javax.swing.JLabel subjectLabel;
396  private javax.swing.JLabel subjectText;
397  private javax.swing.JScrollPane textbodyScrollPane;
398  private javax.swing.JTextArea textbodyTextArea;
399  private javax.swing.JLabel toLabel;
400  private javax.swing.JLabel toText;
401  private javax.swing.JButton viewInNewWindowButton;
402  // End of variables declaration//GEN-END:variables
403 
404  @Override
405  public void setNode(Node node) {
406  if (node == null) {
407  resetComponent();
408  return;
409  }
410 
411  artifact = node.getLookup().lookup(BlackboardArtifact.class);
412  if (artifact == null) {
413  resetComponent();
414  return;
415  }
416 
417  /*
418  * If the artifact is a keyword hit, use the associated artifact as the
419  * one to show in this viewer
420  */
421  if (artifact.getArtifactTypeID() == TSK_KEYWORD_HIT.getTypeID()) {
422  try {
423  getAssociatedArtifact(artifact).ifPresent(associatedArtifact -> {
424  artifact = associatedArtifact;
425  });
426  } catch (TskCoreException ex) {
427  LOGGER.log(Level.SEVERE, "error getting associated artifact", ex);
428  }
429  }
430 
431  if (artifact.getArtifactTypeID() == TSK_MESSAGE.getTypeID()) {
432  displayMsg();
433  } else if (artifact.getArtifactTypeID() == TSK_EMAIL_MSG.getTypeID()) {
434  displayEmailMsg();
435  } else {
436  resetComponent();
437  }
438  }
439 
450  private static Optional<BlackboardArtifact> getAssociatedArtifact(final BlackboardArtifact artifact) throws TskCoreException {
451  BlackboardAttribute attribute = artifact.getAttribute(TSK_ASSOCIATED_TYPE);
452  if (attribute != null) {
453  return Optional.of(artifact.getSleuthkitCase().getArtifactByArtifactId(attribute.getValueLong()));
454  }
455  return Optional.empty();
456  }
457 
458  @Override
459  @NbBundle.Messages("MessageContentViewer.title=Message")
460  public String getTitle() {
461  return Bundle.MessageContentViewer_title();
462  }
463 
464  @Override
465  @NbBundle.Messages("MessageContentViewer.toolTip=Displays messages.")
466  public String getToolTip() {
467  return Bundle.MessageContentViewer_toolTip();
468  }
469 
470  @Override
471  public DataContentViewer createInstance() {
472  return new MessageContentViewer();
473  }
474 
475  @Override
476  public Component getComponent() {
477  return this;
478  }
479 
480  @Override
481  final public void resetComponent() {
482  // reset all fields
483  fromText.setText("");
484  fromLabel.setEnabled(false);
485  toText.setText("");
486  toLabel.setEnabled(false);
487  ccText.setText("");
488  ccLabel.setEnabled(false);
489  subjectText.setText("");
490  subjectLabel.setEnabled(false);
491  datetimeText.setText("");
492  datetimeText.setEnabled(false);
493  directionText.setText("");
494  directionText.setEnabled(false);
495 
496  headersTextArea.setText("");
497  rtfbodyTextPane.setText("");
498  htmlbodyTextPane.setText("");
499  textbodyTextArea.setText("");
500  drp.setNode(null);
501  showImagesToggleButton.setEnabled(false);
502  msgbodyTabbedPane.setEnabled(false);
503  }
504 
505  @Override
506  public boolean isSupported(Node node) {
507  BlackboardArtifact nodeArtifact = node.getLookup().lookup(BlackboardArtifact.class);
508 
509  if (nodeArtifact == null) {
510  return false;
511  }
512  //if the artifact is a keyword hit, check if its associated artifact is a message or email.
513  if (nodeArtifact.getArtifactTypeID() == TSK_KEYWORD_HIT.getTypeID()) {
514  try {
515  if (getAssociatedArtifact(nodeArtifact).map(MessageContentViewer::isMessageArtifact).orElse(false)) {
516  return true;
517  }
518  } catch (TskCoreException ex) {
519  LOGGER.log(Level.SEVERE, "error getting associated artifact", ex);
520  }
521  }
522  return isMessageArtifact(nodeArtifact);
523  }
524 
534  private static boolean isMessageArtifact(BlackboardArtifact nodeArtifact) {
535  final int artifactTypeID = nodeArtifact.getArtifactTypeID();
536  return artifactTypeID == TSK_EMAIL_MSG.getTypeID()
537  || artifactTypeID == TSK_MESSAGE.getTypeID();
538  }
539 
540  @Override
541  public int isPreferred(Node node) {
542  if (isSupported(node)) {
543  return 6;
544  }
545  return 0;
546  }
547 
557  private void configureTextArea(BlackboardAttribute.ATTRIBUTE_TYPE type, int index) throws TskCoreException {
558  String attributeText = getAttributeValueSafe(artifact, type);
559 
560  if (index == HTML_TAB_INDEX && StringUtils.isNotBlank(attributeText)) {
561  //special case for HTML, we need to 'cleanse' it
562  attributeText = wrapInHtmlBody(cleanseHTML(attributeText));
563  }
564  JTextComponent textComponent = textAreas.get(index);
565  textComponent.setText(attributeText);
566  textComponent.setCaretPosition(0); //make sure we start at the top
567  final boolean hasText = attributeText.length() > 0;
568 
569  msgbodyTabbedPane.setEnabledAt(index, hasText);
570  if (hasText) {
571  msgbodyTabbedPane.setSelectedIndex(index);
572  }
573  }
574 
575  private void enableCommonFields() {
576  msgbodyTabbedPane.setEnabled(true);
577  fromLabel.setEnabled(true);
578  toLabel.setEnabled(true);
579  subjectLabel.setEnabled(true);
580  datetimeText.setEnabled(true);
581  }
582 
583  private void configureAttachments() throws TskCoreException {
584  //TODO: Replace this with code to get the actual attachements!
585  final Set<AbstractFile> attachments = artifact.getChildren().stream()
586  .filter(AbstractFile.class::isInstance)
587  .map(AbstractFile.class::cast)
588  .collect(Collectors.toSet());
589  final int numberOfAttachments = attachments.size();
590 
591  msgbodyTabbedPane.setEnabledAt(ATTM_TAB_INDEX, numberOfAttachments > 0);
592  msgbodyTabbedPane.setTitleAt(ATTM_TAB_INDEX, "Attachments (" + numberOfAttachments + ")");
593  drp.setNode(new TableFilterNode(new DataResultFilterNode(new AbstractNode(
594  new AttachmentsChildren(attachments)), null), true));
595  }
596 
597  private static String wrapInHtmlBody(String htmlText) {
598  return "<html><body>" + htmlText + "</body></html>";
599  }
600 
601  private void displayEmailMsg() {
602  enableCommonFields();
603 
604  directionText.setEnabled(false);
605  ccLabel.setEnabled(true);
606 
607  showImagesToggleButton.setEnabled(true);
608  showImagesToggleButton.setText("Show Images");
609  showImagesToggleButton.setSelected(false);
610 
611  try {
612  this.fromText.setText(getAttributeValueSafe(artifact, TSK_EMAIL_FROM));
613  this.fromText.setToolTipText(getAttributeValueSafe(artifact, TSK_EMAIL_FROM));
614  this.toText.setText(getAttributeValueSafe(artifact, TSK_EMAIL_TO));
615  this.toText.setToolTipText(getAttributeValueSafe(artifact, TSK_EMAIL_TO));
616  this.directionText.setText("");
617  this.ccText.setText(getAttributeValueSafe(artifact, TSK_EMAIL_CC));
618  this.ccText.setToolTipText(getAttributeValueSafe(artifact, TSK_EMAIL_CC));
619  this.subjectText.setText(getAttributeValueSafe(artifact, TSK_SUBJECT));
620  this.datetimeText.setText(getAttributeValueSafe(artifact, TSK_DATETIME_RCVD));
621 
622  configureTextArea(TSK_HEADERS, HDR_TAB_INDEX);
623  configureTextArea(TSK_EMAIL_CONTENT_PLAIN, TEXT_TAB_INDEX);
624  configureTextArea(TSK_EMAIL_CONTENT_HTML, HTML_TAB_INDEX);
625  configureTextArea(TSK_EMAIL_CONTENT_RTF, RTF_TAB_INDEX);
626  configureAttachments();
627  } catch (TskCoreException ex) {
628  LOGGER.log(Level.WARNING, "Failed to get attributes for email message.", ex); //NON-NLS
629  }
630  }
631 
632  private void displayMsg() {
633  enableCommonFields();
634 
635  directionText.setEnabled(true);
636  ccLabel.setEnabled(false);
637 
638  try {
639  this.fromText.setText(getAttributeValueSafe(artifact, TSK_PHONE_NUMBER_FROM));
640  this.toText.setText(getAttributeValueSafe(artifact, TSK_PHONE_NUMBER_TO));
641  this.directionText.setText(getAttributeValueSafe(artifact, TSK_DIRECTION));
642  this.ccText.setText("");
643  this.subjectText.setText(getAttributeValueSafe(artifact, TSK_SUBJECT));
644  this.datetimeText.setText(getAttributeValueSafe(artifact, TSK_DATETIME));
645 
646  msgbodyTabbedPane.setEnabledAt(HTML_TAB_INDEX, false);
647  msgbodyTabbedPane.setEnabledAt(RTF_TAB_INDEX, false);
648  msgbodyTabbedPane.setEnabledAt(HDR_TAB_INDEX, false);
649  msgbodyTabbedPane.setEnabledAt(HDR_TAB_INDEX, false);
650  configureTextArea(TSK_TEXT, TEXT_TAB_INDEX);
651  configureAttachments();
652  } catch (TskCoreException ex) {
653  LOGGER.log(Level.WARNING, "Failed to get attributes for message.", ex); //NON-NLS
654  }
655  }
656 
657  private static String getAttributeValueSafe(BlackboardArtifact artifact, BlackboardAttribute.ATTRIBUTE_TYPE type) throws TskCoreException {
658  return Optional.ofNullable(artifact.getAttribute(new BlackboardAttribute.Type(type)))
659  .map(BlackboardAttribute::getDisplayString)
660  .orElse("");
661  }
662 
670  static private String cleanseHTML(String htmlInString) {
671 
672  Document doc = Jsoup.parse(htmlInString);
673 
674  //fix all img tags
675  doc.select("img[src]").forEach(img -> img.attr("src", ""));
676 
677  return doc.html();
678  }
679 
680  private static class AttachmentsChildren extends Children.Keys<AbstractFile> {
681 
682  private final Set<AbstractFile> attachments;
683 
684  AttachmentsChildren(Set<AbstractFile> attachments) {
685  this.attachments = attachments;
686  }
687 
688  @Override
689  protected Node[] createNodes(AbstractFile t) {
690  return new Node[]{new AttachmentNode(t)};
691  }
692 
693  @Override
694  protected void addNotify() {
695  super.addNotify();
696  setKeys(attachments);
697  }
698  }
699 
706  private static class AttachmentNode extends FileNode {
707 
708  AttachmentNode(AbstractFile file) {
709  super(file, true);
710  }
711 
712  @Override
713  protected Sheet createSheet() {
714  Sheet s = new Sheet();
715  Sheet.Set ss = s.get(Sheet.PROPERTIES);
716  if (ss == null) {
717  ss = Sheet.createPropertiesSet();
718  s.put(ss);
719  }
720  AbstractFile file = getContent();
721  ss.put(new NodeProperty<>("Name", "Name", "Name", file.getName()));
722  ss.put(new NodeProperty<>("Size", "Size", "Size", file.getSize()));
723  ss.put(new NodeProperty<>("Mime Type", "Mime Type", "Mime Type", StringUtils.defaultString(file.getMIMEType())));
724  ss.put(new NodeProperty<>("Known", "Known", "Known", file.getKnown().getName()));
725 
726  addTagProperty(ss);
727  return s;
728  }
729  }
730 }
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 Optional< BlackboardArtifact > getAssociatedArtifact(final BlackboardArtifact artifact)
void showImagesToggleButtonActionPerformed(java.awt.event.ActionEvent evt)
static void configureTextPaneAsHtml(JTextPane pane)
Definition: Utilities.java:32
static DataResultPanel createInstanceUninitialized(String title, String pathText, Node rootNode, int totalMatches, DataContent customContentView)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
void viewInNewWindowButtonActionPerformed(java.awt.event.ActionEvent evt)

Copyright © 2012-2016 Basis Technology. Generated on: Tue Feb 20 2018
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.