Autopsy  4.14.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
AnnotationsContentViewer.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2018-2020 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.ArrayList;
23 import java.util.List;
24 import java.util.logging.Level;
25 import org.apache.commons.lang3.StringEscapeUtils;
26 
27 import org.openide.util.NbBundle;
29 import org.openide.nodes.Node;
30 import org.openide.util.lookup.ServiceProvider;
40 import org.sleuthkit.datamodel.AbstractFile;
41 import org.sleuthkit.datamodel.BlackboardArtifact;
42 import org.sleuthkit.datamodel.BlackboardArtifactTag;
43 import org.sleuthkit.datamodel.Content;
44 import org.sleuthkit.datamodel.ContentTag;
45 import org.sleuthkit.datamodel.SleuthkitCase;
46 import org.sleuthkit.datamodel.Tag;
47 import org.sleuthkit.datamodel.TskCoreException;
49 
53 @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
54 @ServiceProvider(service = DataContentViewer.class, position = 8)
55 @NbBundle.Messages({
56  "AnnotationsContentViewer.title=Annotations",
57  "AnnotationsContentViewer.toolTip=Displays tags and comments associated with the selected content."
58 })
59 public class AnnotationsContentViewer extends javax.swing.JPanel implements DataContentViewer {
60 
61  private static final Logger logger = Logger.getLogger(AnnotationsContentViewer.class.getName());
62 
67  initComponents();
69  }
70 
71  @Override
72  public void setNode(Node node) {
73  if ((node == null) || (!isSupported(node))) {
74  resetComponent();
75  return;
76  }
77 
78  StringBuilder html = new StringBuilder();
79 
80  BlackboardArtifact artifact = node.getLookup().lookup(BlackboardArtifact.class);
81  Content sourceFile = null;
82 
83  try {
84  if (artifact != null) {
85  /*
86  * Get the source content based on the artifact to ensure we
87  * display the correct data instead of whatever was in the node.
88  */
89  sourceFile = artifact.getSleuthkitCase().getAbstractFileById(artifact.getObjectID());
90  } else {
91  /*
92  * No artifact is present, so get the content based on what's
93  * present in the node. In this case, the selected item IS the
94  * source file.
95  */
96  sourceFile = node.getLookup().lookup(AbstractFile.class);
97  }
98  } catch (TskCoreException ex) {
99  logger.log(Level.SEVERE, String.format(
100  "Exception while trying to retrieve a Content instance from the BlackboardArtifact '%s' (id=%d).",
101  artifact.getDisplayName(), artifact.getArtifactID()), ex);
102  }
103 
104  if (artifact != null) {
105  populateTagData(html, artifact, sourceFile);
106  } else {
107  populateTagData(html, sourceFile);
108  }
109 
110  if (sourceFile instanceof AbstractFile) {
111  populateCentralRepositoryData(html, artifact, (AbstractFile) sourceFile);
112  }
113 
114  setText(html.toString());
115  jTextPane1.setCaretPosition(0);
116  }
117 
125  private void populateTagData(StringBuilder html, Content content) {
126  try {
127  SleuthkitCase tskCase = Case.getCurrentCaseThrows().getSleuthkitCase();
128 
129  startSection(html, "Selected Item");
130  List<ContentTag> fileTagsList = tskCase.getContentTagsByContent(content);
131  if (fileTagsList.isEmpty()) {
132  addMessage(html, "There are no tags for the selected content.");
133  } else {
134  for (ContentTag tag : fileTagsList) {
135  addTagEntry(html, tag);
136  }
137  }
138  endSection(html);
139  } catch (NoCurrentCaseException ex) {
140  logger.log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS
141  } catch (TskCoreException ex) {
142  logger.log(Level.SEVERE, "Exception while getting tags from the case database.", ex); //NON-NLS
143  }
144  }
145 
154  private void populateTagData(StringBuilder html, BlackboardArtifact artifact, Content sourceFile) {
155  try {
156  SleuthkitCase tskCase = Case.getCurrentCaseThrows().getSleuthkitCase();
157 
158  startSection(html, "Selected Item");
159  List<BlackboardArtifactTag> artifactTagsList = tskCase.getBlackboardArtifactTagsByArtifact(artifact);
160  if (artifactTagsList.isEmpty()) {
161  addMessage(html, "There are no tags for the selected artifact.");
162  } else {
163  for (BlackboardArtifactTag tag : artifactTagsList) {
164  addTagEntry(html, tag);
165  }
166  }
167  endSection(html);
168 
169  if (sourceFile != null) {
170  startSection(html, "Source File");
171  List<ContentTag> fileTagsList = tskCase.getContentTagsByContent(sourceFile);
172  if (fileTagsList.isEmpty()) {
173  addMessage(html, "There are no tags for the source content.");
174  } else {
175  for (ContentTag tag : fileTagsList) {
176  addTagEntry(html, tag);
177  }
178  }
179  endSection(html);
180  }
181  } catch (NoCurrentCaseException ex) {
182  logger.log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS
183  } catch (TskCoreException ex) {
184  logger.log(Level.SEVERE, "Exception while getting tags from the case database.", ex); //NON-NLS
185  }
186  }
187 
196  private void populateCentralRepositoryData(StringBuilder html, BlackboardArtifact artifact, AbstractFile sourceFile) {
198  startSection(html, "Central Repository Comments");
199  List<CorrelationAttributeInstance> instancesList = new ArrayList<>();
200  if (artifact != null) {
201  instancesList.addAll(CorrelationAttributeUtil.makeCorrAttrsForCorrelation(artifact));
202  }
203  try {
205  String md5 = sourceFile.getMd5Hash();
206  if (md5 != null && !md5.isEmpty() && null != artifactTypes && !artifactTypes.isEmpty()) {
207  for (CorrelationAttributeInstance.Type attributeType : artifactTypes) {
208  if (attributeType.getId() == CorrelationAttributeInstance.FILES_TYPE_ID) {
210  instancesList.add(new CorrelationAttributeInstance(
211  attributeType,
212  md5,
213  correlationCase,
214  CorrelationDataSource.fromTSKDataSource(correlationCase, sourceFile.getDataSource()),
215  sourceFile.getParentPath() + sourceFile.getName(),
216  "",
217  sourceFile.getKnown(),
218  sourceFile.getId()));
219  break;
220  }
221  }
222  }
223 
224  boolean commentDataFound = false;
225 
226  for (CorrelationAttributeInstance instance : instancesList) {
227  List<CorrelationAttributeInstance> correlatedInstancesList
228  = CentralRepository.getInstance().getArtifactInstancesByTypeValue(instance.getCorrelationType(), instance.getCorrelationValue());
229  for (CorrelationAttributeInstance correlatedInstance : correlatedInstancesList) {
230  if (correlatedInstance.getComment() != null && correlatedInstance.getComment().isEmpty() == false) {
231  commentDataFound = true;
232  addCentralRepositoryEntry(html, correlatedInstance);
233  }
234  }
235  }
236 
237  if (commentDataFound == false) {
238  addMessage(html, "There is no comment data for the selected content in the Central Repository.");
239  }
240  } catch (CentralRepoException | TskCoreException ex) {
241  logger.log(Level.SEVERE, "Error connecting to the Central Repository database.", ex); // NON-NLS
243  logger.log(Level.SEVERE, "Error normalizing instance from Central Repository database.", ex); // NON-NLS
244  }
245  endSection(html);
246  }
247  }
248 
254  private void setText(String text) {
255  jTextPane1.setText("<html><body>" + text + "</body></html>"); //NON-NLS
256  }
257 
264  private void startSection(StringBuilder html, String sectionName) {
265  html.append("<p style=\"font-size:14px;font-weight:bold;\">")
266  .append(sectionName)
267  .append("</p><br>"); //NON-NLS
268  }
269 
276  private void addMessage(StringBuilder html, String message) {
277  html.append("<p style=\"font-size:11px;font-style:italic;\">")
278  .append(message)
279  .append("</p><br>"); //NON-NLS
280  }
281 
288  @NbBundle.Messages({
289  "AnnotationsContentViewer.tagEntryDataLabel.tag=Tag:",
290  "AnnotationsContentViewer.tagEntryDataLabel.tagUser=Tag User:",
291  "AnnotationsContentViewer.tagEntryDataLabel.comment=Comment:"
292  })
293  private void addTagEntry(StringBuilder html, Tag tag) {
294  startTable(html);
295  addRow(html, Bundle.AnnotationsContentViewer_tagEntryDataLabel_tag(), tag.getName().getDisplayName());
296  addRow(html, Bundle.AnnotationsContentViewer_tagEntryDataLabel_tagUser(), tag.getUserName());
297  addRow(html, Bundle.AnnotationsContentViewer_tagEntryDataLabel_comment(), formatHtmlString(tag.getComment()));
298  endTable(html);
299  }
300 
309  @NbBundle.Messages({
310  "AnnotationsContentViewer.centralRepositoryEntryDataLabel.case=Case:",
311  "AnnotationsContentViewer.centralRepositoryEntryDataLabel.type=Type:",
312  "AnnotationsContentViewer.centralRepositoryEntryDataLabel.comment=Comment:",
313  "AnnotationsContentViewer.centralRepositoryEntryDataLabel.path=Path:"
314  })
315  private void addCentralRepositoryEntry(StringBuilder html, CorrelationAttributeInstance attributeInstance) {
316  startTable(html);
317  addRow(html, Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_case(), attributeInstance.getCorrelationCase().getDisplayName());
318  addRow(html, Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_type(), attributeInstance.getCorrelationType().getDisplayName());
319  addRow(html, Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_comment(), formatHtmlString(attributeInstance.getComment()));
320  addRow(html, Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_path(), attributeInstance.getFilePath());
321  endTable(html);
322  }
323 
329  private void startTable(StringBuilder html) {
330  html.append("<table>"); //NON-NLS
331  }
332 
340  private void addRow(StringBuilder html, String key, String value) {
341  html.append("<tr><td valign=\"top\">"); //NON-NLS
342  html.append(key);
343  html.append("</td><td>"); //NON-NLS
344  html.append(value);
345  html.append("</td></tr>"); //NON-NLS
346  }
347 
353  private void endTable(StringBuilder html) {
354  html.append("</table><br><br>"); //NON-NLS
355  }
356 
362  private void endSection(StringBuilder html) {
363  html.append("<br>"); //NON-NLS
364  }
365 
374  private String formatHtmlString(String text) {
375  String formattedString = StringEscapeUtils.escapeHtml4(text);
376  return formattedString.replaceAll("(\r\n|\r|\n|\n\r)", "<br>");
377  }
378 
384  @SuppressWarnings("unchecked")
385  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
386  private void initComponents() {
387 
388  jScrollPane5 = new javax.swing.JScrollPane();
389  jTextPane1 = new javax.swing.JTextPane();
390 
391  setPreferredSize(new java.awt.Dimension(100, 58));
392 
393  jTextPane1.setEditable(false);
394  jTextPane1.setName(""); // NOI18N
395  jTextPane1.setPreferredSize(new java.awt.Dimension(600, 52));
396  jScrollPane5.setViewportView(jTextPane1);
397 
398  javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
399  this.setLayout(layout);
400  layout.setHorizontalGroup(
401  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
402  .addComponent(jScrollPane5, javax.swing.GroupLayout.DEFAULT_SIZE, 907, Short.MAX_VALUE)
403  );
404  layout.setVerticalGroup(
405  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
406  .addComponent(jScrollPane5, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 435, Short.MAX_VALUE)
407  );
408  }// </editor-fold>//GEN-END:initComponents
409 
410  // Variables declaration - do not modify//GEN-BEGIN:variables
411  private javax.swing.JScrollPane jScrollPane5;
412  private javax.swing.JTextPane jTextPane1;
413  // End of variables declaration//GEN-END:variables
414 
415  @Override
416  public String getTitle() {
417  return Bundle.AnnotationsContentViewer_title();
418  }
419 
420  @Override
421  public String getToolTip() {
422  return Bundle.AnnotationsContentViewer_toolTip();
423  }
424 
425  @Override
427  return new AnnotationsContentViewer();
428  }
429 
430  @Override
431  public boolean isSupported(Node node) {
432  BlackboardArtifact artifact = node.getLookup().lookup(BlackboardArtifact.class);
433 
434  try {
435  if (artifact != null) {
436  if (artifact.getSleuthkitCase().getAbstractFileById(artifact.getObjectID()) != null) {
437  return true;
438  }
439  } else {
440  if (node.getLookup().lookup(AbstractFile.class) != null) {
441  return true;
442  }
443  }
444  } catch (TskCoreException ex) {
445  logger.log(Level.SEVERE, String.format(
446  "Exception while trying to retrieve a Content instance from the BlackboardArtifact '%s' (id=%d).",
447  artifact.getDisplayName(), artifact.getArtifactID()), ex);
448  }
449 
450  return false;
451  }
452 
453  @Override
454  public int isPreferred(Node node) {
455  return 1;
456  }
457 
458  @Override
459  public Component getComponent() {
460  return this;
461  }
462 
463  @Override
464  public void resetComponent() {
465  setText("");
466  }
467 }
List< CorrelationAttributeInstance > getArtifactInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String value)
static CorrelationDataSource fromTSKDataSource(CorrelationCase correlationCase, Content dataSource)
void addCentralRepositoryEntry(StringBuilder html, CorrelationAttributeInstance attributeInstance)
List< CorrelationAttributeInstance.Type > getDefinedCorrelationTypes()
static List< CorrelationAttributeInstance > makeCorrAttrsForCorrelation(BlackboardArtifact artifact)
static void configureTextPaneAsHtml(JTextPane pane)
Definition: Utilities.java:32
void populateCentralRepositoryData(StringBuilder html, BlackboardArtifact artifact, AbstractFile sourceFile)
void addRow(StringBuilder html, String key, String value)
void populateTagData(StringBuilder html, BlackboardArtifact artifact, Content sourceFile)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124

Copyright © 2012-2020 Basis Technology. Generated on: Wed Apr 8 2020
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.