Autopsy  4.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
BlackboardArtifactNode.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2011-2014 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.datamodel;
20 
21 import java.util.ArrayList;
22 import java.util.Arrays;
23 import java.util.LinkedHashMap;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.logging.Level;
27 import org.openide.nodes.Children;
28 import org.openide.nodes.Sheet;
29 import org.openide.util.Lookup;
30 import org.openide.util.NbBundle;
31 import org.openide.util.lookup.Lookups;
34 import org.sleuthkit.datamodel.AbstractFile;
35 import org.sleuthkit.datamodel.BlackboardArtifact;
36 import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
37 import org.sleuthkit.datamodel.BlackboardAttribute;
38 import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
39 import org.sleuthkit.datamodel.Content;
40 import org.sleuthkit.datamodel.TskCoreException;
41 import org.sleuthkit.datamodel.TskException;
42 
48 
49  private final BlackboardArtifact artifact;
50  private final Content associated;
51  private List<NodeProperty<? extends Object>> customProperties;
52  static final Logger logger = Logger.getLogger(BlackboardArtifactNode.class.getName());
53  /*
54  * Artifact types which should have the full unique path of the associated
55  * content as a property.
56  */
57  private static final Integer[] SHOW_UNIQUE_PATH = new Integer[]{
58  BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID(),
59  BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID(),
60  BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID(),};
61 
62  // TODO (RC): This is an unattractive alternative to subclassing BlackboardArtifactNode,
63  // cut from the same cloth as the equally unattractive SHOW_UNIQUE_PATH array
64  // above. It should be removed when and if the subclassing is implemented.
65  private static final Integer[] SHOW_FILE_METADATA = new Integer[]{
66  BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID(),};
67 
75  public BlackboardArtifactNode(BlackboardArtifact artifact, String iconPath) {
76  super(Children.LEAF, createLookup(artifact));
77 
78  this.artifact = artifact;
79  //this.associated = getAssociatedContent(artifact);
80  this.associated = this.getLookup().lookup(Content.class);
81  this.setName(Long.toString(artifact.getArtifactID()));
82  this.setDisplayName();
83  this.setIconBaseWithExtension(iconPath);
84  }
85 
92  public BlackboardArtifactNode(BlackboardArtifact artifact) {
93  super(Children.LEAF, createLookup(artifact));
94 
95  this.artifact = artifact;
96  //this.associated = getAssociatedContent(artifact);
97  this.associated = this.getLookup().lookup(Content.class);
98  this.setName(Long.toString(artifact.getArtifactID()));
99  this.setDisplayName();
100  this.setIconBaseWithExtension(ExtractedContent.getIconFilePath(artifact.getArtifactTypeID())); //NON-NLS
101  }
102 
108  private void setDisplayName() {
109  String displayName = "";
110  if (associated != null) {
111  displayName = associated.getName();
112  }
113 
114  // If this is a node for a keyword hit on an artifact, we set the
115  // display name to be the artifact type name followed by " Artifact"
116  // e.g. "Messages Artifact".
117  if (artifact != null && artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) {
118  try {
119  for (BlackboardAttribute attribute : artifact.getAttributes()) {
120  if (attribute.getAttributeType().getTypeID() == ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID()) {
121  BlackboardArtifact associatedArtifact = Case.getCurrentCase().getSleuthkitCase().getBlackboardArtifact(attribute.getValueLong());
122  if (associatedArtifact != null) {
123  displayName = associatedArtifact.getDisplayName() + " Artifact"; // NON-NLS
124  }
125  }
126  }
127  } catch (TskCoreException ex) {
128  // Do nothing since the display name will be set to the file name.
129  }
130  }
131  this.setDisplayName(displayName);
132  }
133 
134  protected Sheet createSheet() {
135  Sheet s = super.createSheet();
136  Sheet.Set ss = s.get(Sheet.PROPERTIES);
137  if (ss == null) {
138  ss = Sheet.createPropertiesSet();
139  s.put(ss);
140  }
141  final String NO_DESCR = NbBundle.getMessage(this.getClass(), "BlackboardArtifactNode.noDesc.text");
142 
143  Map<String, Object> map = new LinkedHashMap<>();
144  fillPropertyMap(map, artifact);
145 
146  ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "BlackboardArtifactNode.createSheet.srcFile.name"),
147  NbBundle.getMessage(this.getClass(), "BlackboardArtifactNode.createSheet.srcFile.displayName"),
148  NO_DESCR,
149  this.getDisplayName()));
150 
151  for (Map.Entry<String, Object> entry : map.entrySet()) {
152  ss.put(new NodeProperty<>(entry.getKey(),
153  entry.getKey(),
154  NO_DESCR,
155  entry.getValue()));
156  }
157 
158  //append custom node properties
159  if (customProperties != null) {
160  for (NodeProperty<? extends Object> np : customProperties) {
161  ss.put(np);
162  }
163  }
164  final int artifactTypeId = artifact.getArtifactTypeID();
165 
166  // If mismatch, add props for extension and file type
167  if (artifactTypeId == BlackboardArtifact.ARTIFACT_TYPE.TSK_EXT_MISMATCH_DETECTED.getTypeID()) {
168  String ext = "";
169  String actualMimeType = "";
170  if (associated instanceof AbstractFile) {
171  AbstractFile af = (AbstractFile) associated;
172  ext = af.getNameExtension();
173  actualMimeType = af.getMIMEType();
174  if (actualMimeType == null) {
175  actualMimeType = "";
176  }
177  }
178  ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "BlackboardArtifactNode.createSheet.ext.name"),
179  NbBundle.getMessage(this.getClass(), "BlackboardArtifactNode.createSheet.ext.displayName"),
180  NO_DESCR,
181  ext));
182  ss.put(new NodeProperty<>(
183  NbBundle.getMessage(this.getClass(), "BlackboardArtifactNode.createSheet.mimeType.name"),
184  NbBundle.getMessage(this.getClass(), "BlackboardArtifactNode.createSheet.mimeType.displayName"),
185  NO_DESCR,
186  actualMimeType));
187  }
188 
189  if (Arrays.asList(SHOW_UNIQUE_PATH).contains(artifactTypeId)) {
190  String sourcePath = "";
191  try {
192  sourcePath = associated.getUniquePath();
193  } catch (TskCoreException ex) {
194  logger.log(Level.WARNING, "Failed to get unique path from: {0}", associated.getName()); //NON-NLS
195  }
196 
197  if (sourcePath.isEmpty() == false) {
198  ss.put(new NodeProperty<>(
199  NbBundle.getMessage(this.getClass(), "BlackboardArtifactNode.createSheet.filePath.name"),
200  NbBundle.getMessage(this.getClass(), "BlackboardArtifactNode.createSheet.filePath.displayName"),
201  NO_DESCR,
202  sourcePath));
203  }
204 
205  if (Arrays.asList(SHOW_FILE_METADATA).contains(artifactTypeId)) {
206  AbstractFile file = associated instanceof AbstractFile ? (AbstractFile) associated : null;
207  ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileModifiedTime.name"),
208  NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileModifiedTime.displayName"),
209  "",
210  file != null ? ContentUtils.getStringTime(file.getMtime(), file) : ""));
211  ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileChangedTime.name"),
212  NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileChangedTime.displayName"),
213  "",
214  file != null ? ContentUtils.getStringTime(file.getCtime(), file) : ""));
215  ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileAccessedTime.name"),
216  NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileAccessedTime.displayName"),
217  "",
218  file != null ? ContentUtils.getStringTime(file.getAtime(), file) : ""));
219  ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileCreatedTime.name"),
220  NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileCreatedTime.displayName"),
221  "",
222  file != null ? ContentUtils.getStringTime(file.getCrtime(), file) : ""));
223  ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileSize.name"),
224  NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileSize.displayName"),
225  "",
226  associated.getSize()));
227  }
228  } else {
229  String dataSourceStr = "";
230  try {
231  Content dataSource = associated.getDataSource();
232  if (dataSource != null) {
233  dataSourceStr = dataSource.getName();
234  } else {
235  dataSourceStr = getRootParentName();
236  }
237  } catch (TskCoreException ex) {
238  logger.log(Level.WARNING, "Failed to get image name from {0}", associated.getName()); //NON-NLS
239  }
240 
241  if (dataSourceStr.isEmpty() == false) {
242  ss.put(new NodeProperty<>(
243  NbBundle.getMessage(this.getClass(), "BlackboardArtifactNode.createSheet.dataSrc.name"),
244  NbBundle.getMessage(this.getClass(), "BlackboardArtifactNode.createSheet.dataSrc.displayName"),
245  NO_DESCR,
246  dataSourceStr));
247  }
248  }
249 
250  return s;
251  }
252 
253  private String getRootParentName() {
254  String parentName = associated.getName();
255  Content parent = associated;
256  try {
257  while ((parent = parent.getParent()) != null) {
258  parentName = parent.getName();
259  }
260  } catch (TskCoreException ex) {
261  logger.log(Level.WARNING, "Failed to get parent name from {0}", associated.getName()); //NON-NLS
262  return "";
263  }
264  return parentName;
265  }
266 
273  public <T> void addNodeProperty(NodeProperty<T> np) {
274  if (null == customProperties) {
275  //lazy create the list
276  customProperties = new ArrayList<>();
277  }
278  customProperties.add(np);
279 
280  }
281 
289  @SuppressWarnings("deprecation")
290  private void fillPropertyMap(Map<String, Object> map, BlackboardArtifact artifact) {
291  try {
292  for (BlackboardAttribute attribute : artifact.getAttributes()) {
293  final int attributeTypeID = attribute.getAttributeType().getTypeID();
294  //skip some internal attributes that user shouldn't see
295  if (attributeTypeID == ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID()
296  || attributeTypeID == ATTRIBUTE_TYPE.TSK_TAGGED_ARTIFACT.getTypeID()
297  || attributeTypeID == ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID()
298  || attributeTypeID == ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()) {
299  continue;
300  } else if (attribute.getAttributeType().getValueType() == BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME) {
301  map.put(attribute.getAttributeType().getDisplayName(), ContentUtils.getStringTime(attribute.getValueLong(), associated));
302  } else if (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_TOOL_OUTPUT.getTypeID()
303  && attributeTypeID == ATTRIBUTE_TYPE.TSK_TEXT.getTypeID()) {
304  /*
305  * This was added because the RegRipper output would often
306  * cause the UI to get a black line accross it and hang if
307  * you hovered over large output or selected it. This
308  * reduces the amount of data in the table. Could consider
309  * doing this for all fields in the UI.
310  */
311  String value = attribute.getDisplayString();
312  if (value.length() > 512) {
313  value = value.substring(0, 512);
314  }
315  map.put(attribute.getAttributeType().getDisplayName(), value);
316  } else {
317  map.put(attribute.getAttributeType().getDisplayName(), attribute.getDisplayString());
318  }
319  }
320  } catch (TskException ex) {
321  logger.log(Level.SEVERE, "Getting attributes failed", ex); //NON-NLS
322  }
323  }
324 
325  @Override
326  public <T> T accept(DisplayableItemNodeVisitor<T> v) {
327  return v.visit(this);
328  }
329 
337  private static Lookup createLookup(BlackboardArtifact artifact) {
338  List<Object> forLookup = new ArrayList<>();
339  forLookup.add(artifact);
340 
341  // Add the content the artifact is associated with
342  Content content = getAssociatedContent(artifact);
343  if (content != null) {
344  forLookup.add(content);
345  }
346 
347  // if there is a text highlighted version, of the content, add it too
348  // currently happens from keyword search module
349  TextMarkupLookup highlight = getHighlightLookup(artifact, content);
350  if (highlight != null) {
351  forLookup.add(highlight);
352  }
353 
354  return Lookups.fixed(forLookup.toArray(new Object[forLookup.size()]));
355  }
356 
357  private static Content getAssociatedContent(BlackboardArtifact artifact) {
358  try {
359  return artifact.getSleuthkitCase().getContentById(artifact.getObjectID());
360  } catch (TskException ex) {
361  logger.log(Level.WARNING, "Getting file failed", ex); //NON-NLS
362  }
363  throw new IllegalArgumentException(
364  NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.getAssocCont.exception.msg"));
365  }
366 
367  private static TextMarkupLookup getHighlightLookup(BlackboardArtifact artifact, Content content) {
368  if (artifact.getArtifactTypeID() != BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) {
369  return null;
370  }
371 
372  long objectId = content.getId();
373 
374  Lookup lookup = Lookup.getDefault();
375  TextMarkupLookup highlightFactory = lookup.lookup(TextMarkupLookup.class);
376  try {
377  List<BlackboardAttribute> attributes = artifact.getAttributes();
378  String keyword = null;
379  String regexp = null;
380  for (BlackboardAttribute att : attributes) {
381  final int attributeTypeID = att.getAttributeType().getTypeID();
382  if (attributeTypeID == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID()) {
383  keyword = att.getValueString();
384  } else if (attributeTypeID == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP.getTypeID()) {
385  regexp = att.getValueString();
386  } else if (attributeTypeID == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID()) {
387  objectId = att.getValueLong();
388  }
389  }
390  if (keyword != null) {
391  boolean isRegexp = (regexp != null && !regexp.equals(""));
392  String origQuery;
393  if (isRegexp) {
394  origQuery = regexp;
395  } else {
396  origQuery = keyword;
397  }
398  return highlightFactory.createInstance(objectId, keyword, isRegexp, origQuery);
399  }
400  } catch (TskException ex) {
401  logger.log(Level.WARNING, "Failed to retrieve Blackboard Attributes", ex); //NON-NLS
402  }
403  return null;
404  }
405 
406  @Override
407  public boolean isLeafTypeNode() {
408  return true;
409  }
410 
411  /*
412  * TODO (AUT-1849): Correct or remove peristent column reordering code
413  *
414  * Added to support this feature.
415  */
416 // @Override
417 // public String getItemType() {
418 // return "BlackboardArtifact"; //NON-NLS
419 // }
420 }
void fillPropertyMap(Map< String, Object > map, BlackboardArtifact artifact)
static String getStringTime(long epochSeconds, TimeZone tzone)
BlackboardArtifactNode(BlackboardArtifact artifact, String iconPath)
static Lookup createLookup(BlackboardArtifact artifact)
TextMarkupLookup createInstance(long objectId, String keyword, boolean isRegex, String originalQuery)
static Content getAssociatedContent(BlackboardArtifact artifact)
static TextMarkupLookup getHighlightLookup(BlackboardArtifact artifact, Content content)
synchronized static Logger getLogger(String name)
Definition: Logger.java:166

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