Autopsy  4.13.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
ContextViewer.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 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.contextviewer;
20 
21 import java.awt.Component;
22 import java.util.ArrayList;
23 import java.util.HashMap;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.logging.Level;
27 import org.apache.commons.lang.StringUtils;
28 import org.openide.nodes.Node;
29 import org.openide.util.NbBundle;
30 import org.openide.util.lookup.ServiceProvider;
36 import org.sleuthkit.datamodel.AbstractFile;
37 import org.sleuthkit.datamodel.BlackboardArtifact;
38 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT;
39 import org.sleuthkit.datamodel.BlackboardAttribute;
40 import org.sleuthkit.datamodel.SleuthkitCase;
41 import org.sleuthkit.datamodel.TskCoreException;
42 
48 @ServiceProvider(service = DataContentViewer.class, position = 7)
49 public final class ContextViewer extends javax.swing.JPanel implements DataContentViewer {
50 
51  private static final long serialVersionUID = 1L;
52  private static final Logger logger = Logger.getLogger(ContextViewer.class.getName());
53  private static final int ARTIFACT_STR_MAX_LEN = 1024;
54  private static final int ATTRIBUTE_STR_MAX_LEN = 200;
55 
56  // defines a list of artifacts that provide context for a file
57  private static final List<BlackboardArtifact.ARTIFACT_TYPE> SOURCE_CONTEXT_ARTIFACTS = new ArrayList<>();
58 
59  static {
60  SOURCE_CONTEXT_ARTIFACTS.add(TSK_ASSOCIATED_OBJECT);
61  }
62 
63  private BlackboardArtifact sourceContextArtifact;
64 
68  public ContextViewer() {
69 
70  initComponents();
71  }
72 
78  @SuppressWarnings("unchecked")
79  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
80  private void initComponents() {
81 
82  jSourceGoToResultButton = new javax.swing.JButton();
83  jSourceLabel = new javax.swing.JLabel();
84  jSourceNameLabel = new javax.swing.JLabel();
85  jSourceTextLabel = new javax.swing.JLabel();
86 
87  setBackground(new java.awt.Color(255, 255, 255));
88 
89  org.openide.awt.Mnemonics.setLocalizedText(jSourceGoToResultButton, org.openide.util.NbBundle.getMessage(ContextViewer.class, "ContextViewer.jSourceGoToResultButton.text")); // NOI18N
90  jSourceGoToResultButton.addActionListener(new java.awt.event.ActionListener() {
91  public void actionPerformed(java.awt.event.ActionEvent evt) {
92  jSourceGoToResultButtonActionPerformed(evt);
93  }
94  });
95 
96  jSourceLabel.setFont(new java.awt.Font("Dialog", 1, 14)); // NOI18N
97  org.openide.awt.Mnemonics.setLocalizedText(jSourceLabel, org.openide.util.NbBundle.getMessage(ContextViewer.class, "ContextViewer.jSourceLabel.text")); // NOI18N
98 
99  org.openide.awt.Mnemonics.setLocalizedText(jSourceNameLabel, org.openide.util.NbBundle.getMessage(ContextViewer.class, "ContextViewer.jSourceNameLabel.text")); // NOI18N
100 
101  org.openide.awt.Mnemonics.setLocalizedText(jSourceTextLabel, org.openide.util.NbBundle.getMessage(ContextViewer.class, "ContextViewer.jSourceTextLabel.text")); // NOI18N
102 
103  javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
104  this.setLayout(layout);
105  layout.setHorizontalGroup(
106  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
107  .addGroup(layout.createSequentialGroup()
108  .addContainerGap()
109  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
110  .addGroup(layout.createSequentialGroup()
111  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
112  .addComponent(jSourceLabel)
113  .addGroup(layout.createSequentialGroup()
114  .addGap(6, 6, 6)
115  .addComponent(jSourceNameLabel)
116  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
117  .addComponent(jSourceTextLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 192, Short.MAX_VALUE)))
118  .addGap(36, 36, 36))
119  .addGroup(layout.createSequentialGroup()
120  .addComponent(jSourceGoToResultButton)
121  .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
122  );
123  layout.setVerticalGroup(
124  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
125  .addGroup(layout.createSequentialGroup()
126  .addContainerGap()
127  .addComponent(jSourceLabel)
128  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
129  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
130  .addComponent(jSourceNameLabel)
131  .addComponent(jSourceTextLabel))
132  .addGap(18, 18, 18)
133  .addComponent(jSourceGoToResultButton)
134  .addGap(0, 203, Short.MAX_VALUE))
135  );
136  }// </editor-fold>//GEN-END:initComponents
137 
138  private void jSourceGoToResultButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jSourceGoToResultButtonActionPerformed
139 
141 
142  // Navigate to the source context artifact.
143  if (sourceContextArtifact != null) {
144  dtc.viewArtifact(sourceContextArtifact);
145  }
146 
147  }//GEN-LAST:event_jSourceGoToResultButtonActionPerformed
148 
149  @Override
150  public void setNode(Node selectedNode) {
151  if ((selectedNode == null) || (!isSupported(selectedNode))) {
152  resetComponent();
153  return;
154  }
155 
156  AbstractFile file = selectedNode.getLookup().lookup(AbstractFile.class);
157  try {
158  populateSourceContextData(file);
159  } catch (NoCurrentCaseException | TskCoreException ex) {
160  logger.log(Level.SEVERE, String.format("Exception displaying context for file %s", file.getName()), ex); //NON-NLS
161  }
162  }
163 
164  @NbBundle.Messages({
165  "ContextViewer.title=Context",
166  "ContextViewer.toolTip=Displays context for selected file."
167  })
168 
169  @Override
170  public String getTitle() {
171  return Bundle.ContextViewer_title();
172  }
173 
174  @Override
175  public String getToolTip() {
176  return Bundle.ContextViewer_toolTip();
177  }
178 
179  @Override
180  public DataContentViewer createInstance() {
181  return new ContextViewer();
182  }
183 
184  @Override
185  public Component getComponent() {
186  return this;
187  }
188 
189  @Override
190  public void resetComponent() {
191  jSourceGoToResultButton.setVisible(false);
192  setSourceName("");
193  setSourceText("");
194  }
195 
196  @Override
197  public boolean isSupported(Node node) {
198 
199  // check if the node has an abstract file and the file has any context defining artifacts.
200  if (node.getLookup().lookup(AbstractFile.class) != null) {
201  AbstractFile abstractFile = node.getLookup().lookup(AbstractFile.class);
202  for (BlackboardArtifact.ARTIFACT_TYPE artifactType : SOURCE_CONTEXT_ARTIFACTS) {
203  List<BlackboardArtifact> artifactsList;
204  try {
205  artifactsList = abstractFile.getArtifacts(artifactType);
206  if (!artifactsList.isEmpty()) {
207  return true;
208  }
209  } catch (TskCoreException ex) {
210  logger.log(Level.SEVERE, String.format("Exception while looking up context artifacts for file %s", abstractFile), ex); //NON-NLS
211  }
212  }
213 
214  }
215 
216  return false;
217  }
218 
219  @Override
220  public int isPreferred(Node node) {
221  // this is a low preference viewer.
222  return 1;
223  }
224 
234  private void populateSourceContextData(AbstractFile sourceFile) throws NoCurrentCaseException, TskCoreException {
235 
236  SleuthkitCase tskCase = Case.getCurrentCaseThrows().getSleuthkitCase();
237 
238  // Check for all context artifacts
239  boolean foundASource = false;
240  for (BlackboardArtifact.ARTIFACT_TYPE artifactType : SOURCE_CONTEXT_ARTIFACTS) {
241  List<BlackboardArtifact> artifactsList = tskCase.getBlackboardArtifacts(artifactType, sourceFile.getId());
242 
243  foundASource = !artifactsList.isEmpty();
244  for (BlackboardArtifact contextArtifact : artifactsList) {
245  addSourceEntry(contextArtifact);
246  }
247  }
248  jSourceGoToResultButton.setVisible(true);
249  if (foundASource == false) {
250  setSourceName("Unknown");
251  showSourceText(false);
252  }
253 
254  }
255 
265  private void addSourceEntry(BlackboardArtifact artifact) throws TskCoreException {
266  if (BlackboardArtifact.ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT.getTypeID() == artifact.getArtifactTypeID()) {
267  BlackboardAttribute associatedArtifactAttribute = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT));
268  if (associatedArtifactAttribute != null) {
269  long artifactId = associatedArtifactAttribute.getValueLong();
270  BlackboardArtifact associatedArtifact = artifact.getSleuthkitCase().getBlackboardArtifact(artifactId);
271 
272  //save the artifact for "Go to Result" button
273  sourceContextArtifact = associatedArtifact;
274 
275  setSourceFields(associatedArtifact);
276  }
277  }
278  }
279 
288  @NbBundle.Messages({
289  "ContextViewer.attachmentSource=Attached to: ",
290  "ContextViewer.downloadSource=Downloaded from: "
291  })
292  private void setSourceFields(BlackboardArtifact associatedArtifact) throws TskCoreException {
293  if (BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE.getTypeID() == associatedArtifact.getArtifactTypeID()
294  || BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID() == associatedArtifact.getArtifactTypeID()) {
295 
296  setSourceName(Bundle.ContextViewer_attachmentSource());
297  setSourceText(msgArtifactToAbbreviatedString(associatedArtifact));
298 
299  } else if (BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID() == associatedArtifact.getArtifactTypeID()
300  || BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE.getTypeID() == associatedArtifact.getArtifactTypeID()) {
301 
302  setSourceName(Bundle.ContextViewer_downloadSource());
303  setSourceText(webDownloadArtifactToString(associatedArtifact));
304  }
305  }
306 
312  private void setSourceName(String nameLabel) {
313  jSourceNameLabel.setText(nameLabel);
314  }
315 
321  private void setSourceText(String text) {
322  jSourceTextLabel.setText(text);
323  showSourceText(!text.isEmpty());
324  }
325 
326  private void showSourceText(boolean show) {
327  jSourceTextLabel.setVisible(show);
328  jSourceGoToResultButton.setEnabled(show);
329  jSourceLabel.setVisible(show);
330  }
331 
342  @NbBundle.Messages({
343  "ContextViewer.downloadURL=URL",
344  "ContextViewer.downloadedOn=On"
345  })
346  private String webDownloadArtifactToString(BlackboardArtifact artifact) throws TskCoreException {
347  StringBuilder sb = new StringBuilder(ARTIFACT_STR_MAX_LEN);
348  Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> attributesMap = getAttributesMap(artifact);
349 
350  if (BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID() == artifact.getArtifactTypeID()
351  || BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE.getTypeID() == artifact.getArtifactTypeID()) {
352  appendAttributeString(sb, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL, attributesMap, Bundle.ContextViewer_downloadURL());
353  appendAttributeString(sb, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED, attributesMap, Bundle.ContextViewer_downloadedOn());
354  }
355  return sb.toString();
356  }
357 
367  @NbBundle.Messages({
368  "ContextViewer.message=Message",
369  "ContextViewer.email=Email",
370  "ContextViewer.messageFrom=From",
371  "ContextViewer.messageTo=To",
372  "ContextViewer.messageOn=On",})
373  private String msgArtifactToAbbreviatedString(BlackboardArtifact artifact) throws TskCoreException {
374 
375  StringBuilder sb = new StringBuilder(ARTIFACT_STR_MAX_LEN);
376  Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> attributesMap = getAttributesMap(artifact);
377 
378  if (BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE.getTypeID() == artifact.getArtifactTypeID()) {
379  sb.append(Bundle.ContextViewer_message()).append(' ');
380  appendAttributeString(sb, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM, attributesMap, Bundle.ContextViewer_messageFrom());
381  appendAttributeString(sb, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO, attributesMap, Bundle.ContextViewer_messageTo());
382  appendAttributeString(sb, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, attributesMap, Bundle.ContextViewer_messageOn());
383  } else if (BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID() == artifact.getArtifactTypeID()) {
384  sb.append(Bundle.ContextViewer_email()).append(' ');
385  appendAttributeString(sb, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL_FROM, attributesMap, Bundle.ContextViewer_messageFrom());
386  appendAttributeString(sb, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL_TO, attributesMap, Bundle.ContextViewer_messageTo());
387  appendAttributeString(sb, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_SENT, attributesMap, Bundle.ContextViewer_messageOn());
388  }
389  return sb.toString();
390  }
391 
402  private void appendAttributeString(StringBuilder sb, BlackboardAttribute.ATTRIBUTE_TYPE attribType,
403  Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> attributesMap, String prependStr) {
404 
405  BlackboardAttribute attribute = attributesMap.get(attribType);
406  if (attribute != null) {
407  String attrVal = attribute.getDisplayString();
408  if (!StringUtils.isEmpty(attrVal)) {
409  if (!StringUtils.isEmpty(prependStr)) {
410  sb.append(prependStr).append(' ');
411  }
412  sb.append(StringUtils.abbreviate(attrVal, ATTRIBUTE_STR_MAX_LEN)).append(' ');
413  }
414  }
415  }
416 
427  private Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> getAttributesMap(BlackboardArtifact artifact) throws TskCoreException {
428  Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> attributeMap = new HashMap<>();
429 
430  List<BlackboardAttribute> attributeList = artifact.getAttributes();
431  for (BlackboardAttribute attribute : attributeList) {
432  BlackboardAttribute.ATTRIBUTE_TYPE type = BlackboardAttribute.ATTRIBUTE_TYPE.fromID(attribute.getAttributeType().getTypeID());
433  attributeMap.put(type, attribute);
434  }
435 
436  return attributeMap;
437  }
438 
439 
440  // Variables declaration - do not modify//GEN-BEGIN:variables
441  private javax.swing.JButton jSourceGoToResultButton;
442  private javax.swing.JLabel jSourceLabel;
443  private javax.swing.JLabel jSourceNameLabel;
444  private javax.swing.JLabel jSourceTextLabel;
445  // End of variables declaration//GEN-END:variables
446 }
Map< BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute > getAttributesMap(BlackboardArtifact artifact)
void appendAttributeString(StringBuilder sb, BlackboardAttribute.ATTRIBUTE_TYPE attribType, Map< BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute > attributesMap, String prependStr)
void jSourceGoToResultButtonActionPerformed(java.awt.event.ActionEvent evt)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
String msgArtifactToAbbreviatedString(BlackboardArtifact artifact)
static synchronized DirectoryTreeTopComponent findInstance()
void setSourceFields(BlackboardArtifact associatedArtifact)

Copyright © 2012-2019 Basis Technology. Generated on: Tue Jan 7 2020
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.