Autopsy  4.10.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
AbstractAbstractFileNode.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2011-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.datamodel;
20 
21 import com.google.common.util.concurrent.ThreadFactoryBuilder;
22 import java.beans.PropertyChangeEvent;
23 import java.beans.PropertyChangeListener;
24 import java.lang.ref.WeakReference;
25 import java.util.ArrayList;
26 import java.util.EnumSet;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.Set;
30 import java.util.concurrent.ExecutorService;
31 import java.util.concurrent.Executors;
32 import java.util.logging.Level;
33 import java.util.stream.Collectors;
34 import org.apache.commons.io.FilenameUtils;
35 import org.apache.commons.lang3.StringUtils;
36 import org.apache.commons.lang3.tuple.Pair;
37 import org.openide.nodes.Children;
38 import org.openide.nodes.Sheet;
39 import org.openide.util.NbBundle;
40 import org.openide.util.WeakListeners;
56 import static org.sleuthkit.autopsy.datamodel.Bundle.*;
63 import org.sleuthkit.datamodel.AbstractFile;
64 import org.sleuthkit.datamodel.BlackboardArtifact;
65 import org.sleuthkit.datamodel.Content;
66 import org.sleuthkit.datamodel.ContentTag;
67 import org.sleuthkit.datamodel.TskCoreException;
68 import org.sleuthkit.datamodel.TskData;
69 
75 public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends AbstractContentNode<T> {
76 
77  private static final Logger logger = Logger.getLogger(AbstractAbstractFileNode.class.getName());
78  @NbBundle.Messages("AbstractAbstractFileNode.addFileProperty.desc=no description")
79  private static final String NO_DESCR = AbstractAbstractFileNode_addFileProperty_desc();
80 
81  private static final Set<Case.Events> CASE_EVENTS_OF_INTEREST = EnumSet.of(Case.Events.CURRENT_CASE,
83 
84  private static final ExecutorService translationPool;
85  private static final Integer MAX_POOL_SIZE = 10;
86 
90  AbstractAbstractFileNode(T abstractFile) {
91  super(abstractFile);
92  String ext = abstractFile.getNameExtension();
93  if (StringUtils.isNotBlank(ext)) {
94  ext = "." + ext;
95  // If this is an archive file we will listen for ingest events
96  // that will notify us when new content has been identified.
97  if (FileTypeExtensions.getArchiveExtensions().contains(ext)) {
99  }
100  }
101 
103  AbstractAbstractFileNode.translationPool.submit(new TranslationTask(
104  new WeakReference<>(this), weakPcl));
105  }
106 
107  // Listen for case events so that we can detect when the case is closed
108  // or when tags are added.
110  }
111 
112  static {
113  //Initialize this pool only once! This will be used by every instance of AAFN
114  //to do their heavy duty SCO column and translation updates.
115  translationPool = Executors.newFixedThreadPool(MAX_POOL_SIZE,
116  new ThreadFactoryBuilder().setNameFormat("translation-task-thread-%d").build());
117  }
118 
128  @Override
129  protected void finalize() throws Throwable {
130  super.finalize();
131  removeListeners();
132  }
133 
134  private void removeListeners() {
137  }
138 
145  enum NodeSpecificEvents {
146  TRANSLATION_AVAILABLE,
147  }
148 
149  private final PropertyChangeListener pcl = (PropertyChangeEvent evt) -> {
150  String eventType = evt.getPropertyName();
151 
152  // Is this a content changed event?
153  if (eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())) {
154  if ((evt.getOldValue() instanceof ModuleContentEvent) == false) {
155  return;
156  }
157  ModuleContentEvent moduleContentEvent = (ModuleContentEvent) evt.getOldValue();
158  if ((moduleContentEvent.getSource() instanceof Content) == false) {
159  return;
160  }
161  Content newContent = (Content) moduleContentEvent.getSource();
162 
163  // Does the event indicate that content has been added to *this* file?
164  if (getContent().getId() == newContent.getId()) {
165  // If so, refresh our children.
166  try {
167  Children parentsChildren = getParentNode().getChildren();
168  // We only want to refresh our parents children if we are in the
169  // data sources branch of the tree. The parent nodes in other
170  // branches of the tree (e.g. File Types and Deleted Files) do
171  // not need to be refreshed.
172  if (parentsChildren instanceof ContentChildren) {
173  ((ContentChildren) parentsChildren).refreshChildren();
174  parentsChildren.getNodesCount();
175  }
176  } catch (NullPointerException ex) {
177  // Skip
178  }
179  }
180  } else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
181  if (evt.getNewValue() == null) {
182  // case was closed. Remove listeners so that we don't get called with a stale case handle
183  removeListeners();
184  }
185  /*
186  * No need to do any asynchrony around tag added, deleted or CR
187  * change events, they are so infrequent and user driven that we can
188  * just keep a simple blocking approach, where we go out to the
189  * database ourselves.
190  */
191  } else if (eventType.equals(Case.Events.CONTENT_TAG_ADDED.toString())) {
193  if (event.getAddedTag().getContent().equals(content)) {
194  List<ContentTag> tags = getContentTagsFromDatabase();
195  Pair<Score, String> scorePropAndDescr = getScorePropertyAndDescription(tags);
196  Score value = scorePropAndDescr.getLeft();
197  String descr = scorePropAndDescr.getRight();
198  CorrelationAttributeInstance attribute = getCorrelationAttributeInstance();
199  updateSheet(new NodeProperty<>(SCORE.toString(), SCORE.toString(), descr, value),
200  new NodeProperty<>(COMMENT.toString(), COMMENT.toString(), NO_DESCR, getCommentProperty(tags, attribute))
201  );
202  }
203  } else if (eventType.equals(Case.Events.CONTENT_TAG_DELETED.toString())) {
205  if (event.getDeletedTagInfo().getContentID() == content.getId()) {
206  List<ContentTag> tags = getContentTagsFromDatabase();
207  Pair<Score, String> scorePropAndDescr = getScorePropertyAndDescription(tags);
208  Score value = scorePropAndDescr.getLeft();
209  String descr = scorePropAndDescr.getRight();
210  CorrelationAttributeInstance attribute = getCorrelationAttributeInstance();
211  updateSheet(new NodeProperty<>(SCORE.toString(), SCORE.toString(), descr, value),
212  new NodeProperty<>(COMMENT.toString(), COMMENT.toString(), NO_DESCR, getCommentProperty(tags, attribute))
213  );
214  }
215  } else if (eventType.equals(Case.Events.CR_COMMENT_CHANGED.toString())) {
217  if (event.getContentID() == content.getId()) {
218  List<ContentTag> tags = getContentTagsFromDatabase();
219  CorrelationAttributeInstance attribute = getCorrelationAttributeInstance();
220  updateSheet(new NodeProperty<>(COMMENT.toString(), COMMENT.toString(), NO_DESCR, getCommentProperty(tags, attribute)));
221  }
222  } else if (eventType.equals(NodeSpecificEvents.TRANSLATION_AVAILABLE.toString())) {
223  this.setDisplayName(evt.getNewValue().toString());
224  //Set the tooltip
225  this.setShortDescription(content.getName());
226  updateSheet(new NodeProperty<>(ORIGINAL_NAME.toString(), ORIGINAL_NAME.toString(), NO_DESCR, content.getName()));
227  }
228  };
237  private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
238 
252  private synchronized void updateSheet(NodeProperty<?>... newProps) {
253  //Refresh ONLY those properties in the sheet currently. Subclasses may have
254  //only added a subset of our properties or their own props.s
255  Sheet visibleSheet = this.getSheet();
256  Sheet.Set visibleSheetSet = visibleSheet.get(Sheet.PROPERTIES);
257  Property<?>[] visibleProps = visibleSheetSet.getProperties();
258  for (NodeProperty<?> newProp : newProps) {
259  for (int i = 0; i < visibleProps.length; i++) {
260  if (visibleProps[i].getName().equals(newProp.getName())) {
261  visibleProps[i] = newProp;
262  }
263  }
264  }
265  visibleSheetSet.put(visibleProps);
266  visibleSheet.put(visibleSheetSet);
267  //setSheet() will notify Netbeans to update this node in the UI.
268  this.setSheet(visibleSheet);
269  }
270 
271  /*
272  * This is called when the node is first initialized. Any new updates or
273  * changes happen by directly manipulating the sheet. That means we can fire
274  * off background events everytime this method is called and not worry about
275  * duplicated jobs.
276  */
277  @Override
278  protected synchronized Sheet createSheet() {
279  Sheet sheet = new Sheet();
280  Sheet.Set sheetSet = Sheet.createPropertiesSet();
281  sheet.put(sheetSet);
282 
283  //This will fire off fresh background tasks.
284  List<NodeProperty<?>> newProperties = getProperties();
285  newProperties.forEach((property) -> {
286  sheetSet.put(property);
287  });
288 
289  return sheet;
290  }
291 
292  @NbBundle.Messages({"AbstractAbstractFileNode.nameColLbl=Name",
293  "AbstractAbstractFileNode.originalName=Original Name",
294  "AbstractAbstractFileNode.createSheet.score.name=S",
295  "AbstractAbstractFileNode.createSheet.comment.name=C",
296  "AbstractAbstractFileNode.createSheet.count.name=O",
297  "AbstractAbstractFileNode.locationColLbl=Location",
298  "AbstractAbstractFileNode.modifiedTimeColLbl=Modified Time",
299  "AbstractAbstractFileNode.changeTimeColLbl=Change Time",
300  "AbstractAbstractFileNode.accessTimeColLbl=Access Time",
301  "AbstractAbstractFileNode.createdTimeColLbl=Created Time",
302  "AbstractAbstractFileNode.sizeColLbl=Size",
303  "AbstractAbstractFileNode.flagsDirColLbl=Flags(Dir)",
304  "AbstractAbstractFileNode.flagsMetaColLbl=Flags(Meta)",
305  "AbstractAbstractFileNode.modeColLbl=Mode",
306  "AbstractAbstractFileNode.useridColLbl=UserID",
307  "AbstractAbstractFileNode.groupidColLbl=GroupID",
308  "AbstractAbstractFileNode.metaAddrColLbl=Meta Addr.",
309  "AbstractAbstractFileNode.attrAddrColLbl=Attr. Addr.",
310  "AbstractAbstractFileNode.typeDirColLbl=Type(Dir)",
311  "AbstractAbstractFileNode.typeMetaColLbl=Type(Meta)",
312  "AbstractAbstractFileNode.knownColLbl=Known",
313  "AbstractAbstractFileNode.md5HashColLbl=MD5 Hash",
314  "AbstractAbstractFileNode.objectId=Object ID",
315  "AbstractAbstractFileNode.mimeType=MIME Type",
316  "AbstractAbstractFileNode.extensionColLbl=Extension"})
318 
319  NAME(AbstractAbstractFileNode_nameColLbl()),
320  ORIGINAL_NAME(AbstractAbstractFileNode_originalName()),
321  SCORE(AbstractAbstractFileNode_createSheet_score_name()),
322  COMMENT(AbstractAbstractFileNode_createSheet_comment_name()),
323  OCCURRENCES(AbstractAbstractFileNode_createSheet_count_name()),
324  LOCATION(AbstractAbstractFileNode_locationColLbl()),
325  MOD_TIME(AbstractAbstractFileNode_modifiedTimeColLbl()),
326  CHANGED_TIME(AbstractAbstractFileNode_changeTimeColLbl()),
327  ACCESS_TIME(AbstractAbstractFileNode_accessTimeColLbl()),
328  CREATED_TIME(AbstractAbstractFileNode_createdTimeColLbl()),
329  SIZE(AbstractAbstractFileNode_sizeColLbl()),
330  FLAGS_DIR(AbstractAbstractFileNode_flagsDirColLbl()),
331  FLAGS_META(AbstractAbstractFileNode_flagsMetaColLbl()),
332  MODE(AbstractAbstractFileNode_modeColLbl()),
333  USER_ID(AbstractAbstractFileNode_useridColLbl()),
334  GROUP_ID(AbstractAbstractFileNode_groupidColLbl()),
335  META_ADDR(AbstractAbstractFileNode_metaAddrColLbl()),
336  ATTR_ADDR(AbstractAbstractFileNode_attrAddrColLbl()),
337  TYPE_DIR(AbstractAbstractFileNode_typeDirColLbl()),
338  TYPE_META(AbstractAbstractFileNode_typeMetaColLbl()),
339  KNOWN(AbstractAbstractFileNode_knownColLbl()),
340  MD5HASH(AbstractAbstractFileNode_md5HashColLbl()),
341  ObjectID(AbstractAbstractFileNode_objectId()),
342  MIMETYPE(AbstractAbstractFileNode_mimeType()),
343  EXTENSION(AbstractAbstractFileNode_extensionColLbl());
344 
345  final private String displayString;
346 
347  private AbstractFilePropertyType(String displayString) {
348  this.displayString = displayString;
349  }
350 
351  @Override
352  public String toString() {
353  return displayString;
354  }
355  }
356 
360  private List<NodeProperty<?>> getProperties() {
361  List<NodeProperty<?>> properties = new ArrayList<>();
362  properties.add(new NodeProperty<>(NAME.toString(), NAME.toString(), NO_DESCR, getContentDisplayName(content)));
363  /*
364  * Initialize an empty place holder value. At the bottom, we kick off a
365  * background task that promises to update these values.
366  */
367 
369  properties.add(new NodeProperty<>(ORIGINAL_NAME.toString(), ORIGINAL_NAME.toString(), NO_DESCR, ""));
370  }
371 
372  //SCO column prereq info..
373  List<ContentTag> tags = getContentTagsFromDatabase();
374  CorrelationAttributeInstance attribute = getCorrelationAttributeInstance();
375 
376  Pair<DataResultViewerTable.Score, String> scoreAndDescription = getScorePropertyAndDescription(tags);
377  properties.add(new NodeProperty<>(SCORE.toString(), SCORE.toString(), scoreAndDescription.getRight(), scoreAndDescription.getLeft()));
378  DataResultViewerTable.HasCommentStatus comment = getCommentProperty(tags, attribute);
379  properties.add(new NodeProperty<>(COMMENT.toString(), COMMENT.toString(), NO_DESCR, comment));
381  Pair<Long, String> countAndDescription = getCountPropertyAndDescription(attribute);
382  properties.add(new NodeProperty<>(OCCURRENCES.toString(), OCCURRENCES.toString(), countAndDescription.getRight(), countAndDescription.getLeft()));
383  }
384  properties.add(new NodeProperty<>(LOCATION.toString(), LOCATION.toString(), NO_DESCR, getContentPath(content)));
385  properties.add(new NodeProperty<>(MOD_TIME.toString(), MOD_TIME.toString(), NO_DESCR, ContentUtils.getStringTime(content.getMtime(), content)));
386  properties.add(new NodeProperty<>(CHANGED_TIME.toString(), CHANGED_TIME.toString(), NO_DESCR, ContentUtils.getStringTime(content.getCtime(), content)));
387  properties.add(new NodeProperty<>(ACCESS_TIME.toString(), ACCESS_TIME.toString(), NO_DESCR, ContentUtils.getStringTime(content.getAtime(), content)));
388  properties.add(new NodeProperty<>(CREATED_TIME.toString(), CREATED_TIME.toString(), NO_DESCR, ContentUtils.getStringTime(content.getCrtime(), content)));
389  properties.add(new NodeProperty<>(SIZE.toString(), SIZE.toString(), NO_DESCR, content.getSize()));
390  properties.add(new NodeProperty<>(FLAGS_DIR.toString(), FLAGS_DIR.toString(), NO_DESCR, content.getDirFlagAsString()));
391  properties.add(new NodeProperty<>(FLAGS_META.toString(), FLAGS_META.toString(), NO_DESCR, content.getMetaFlagsAsString()));
392  properties.add(new NodeProperty<>(KNOWN.toString(), KNOWN.toString(), NO_DESCR, content.getKnown().getName()));
393  properties.add(new NodeProperty<>(MD5HASH.toString(), MD5HASH.toString(), NO_DESCR, StringUtils.defaultString(content.getMd5Hash())));
394  properties.add(new NodeProperty<>(MIMETYPE.toString(), MIMETYPE.toString(), NO_DESCR, StringUtils.defaultString(content.getMIMEType())));
395  properties.add(new NodeProperty<>(EXTENSION.toString(), EXTENSION.toString(), NO_DESCR, content.getNameExtension()));
396 
397  return properties;
398  }
399 
409  @NbBundle.Messages("AbstractAbstractFileNode.tagsProperty.displayName=Tags")
410  @Deprecated
411  protected void addTagProperty(Sheet.Set sheetSet) {
412  List<ContentTag> tags = getContentTagsFromDatabase();
413  sheetSet.put(new NodeProperty<>("Tags", AbstractAbstractFileNode_tagsProperty_displayName(),
414  NO_DESCR, tags.stream().map(t -> t.getName().getDisplayName())
415  .distinct()
416  .collect(Collectors.joining(", "))));
417  }
418 
429  @Deprecated
430  protected static String getHashSetHitsCsvList(AbstractFile file) {
431  try {
432  return StringUtils.join(file.getHashSetNames(), ", ");
433  } catch (TskCoreException tskCoreException) {
434  logger.log(Level.WARNING, "Error getting hashset hits: ", tskCoreException); //NON-NLS
435  return "";
436  }
437  }
438 
439  @NbBundle.Messages({
440  "AbstractAbstractFileNode.createSheet.count.displayName=O",
441  "AbstractAbstractFileNode.createSheet.count.noCentralRepo.description=Central repository was not enabled when this column was populated",
442  "AbstractAbstractFileNode.createSheet.count.hashLookupNotRun.description=Hash lookup had not been run on this file when the column was populated",
443  "# {0} - occuranceCount",
444  "AbstractAbstractFileNode.createSheet.count.description=There were {0} datasource(s) found with occurances of the correlation value"})
445  Pair<Long, String> getCountPropertyAndDescription(CorrelationAttributeInstance attribute) {
446  Long count = -1L; //The column renderer will not display negative values, negative value used when count unavailble to preserve sorting
447  String description = Bundle.AbstractAbstractFileNode_createSheet_count_noCentralRepo_description();
448  try {
449  //don't perform the query if there is no correlation value
450  if (attribute != null && StringUtils.isNotBlank(attribute.getCorrelationValue())) {
451  count = EamDb.getInstance().getCountUniqueCaseDataSourceTuplesHavingTypeValue(attribute.getCorrelationType(), attribute.getCorrelationValue());
452  description = Bundle.AbstractAbstractFileNode_createSheet_count_description(count);
453  } else if (attribute != null) {
454  description = Bundle.AbstractAbstractFileNode_createSheet_count_hashLookupNotRun_description();
455  }
456  } catch (EamDbException ex) {
457  logger.log(Level.WARNING, "Error getting count of datasources with correlation attribute", ex);
458  } catch (CorrelationAttributeNormalizationException ex) {
459  logger.log(Level.WARNING, "Unable to normalize data to get count of datasources with correlation attribute", ex);
460  }
461 
462  return Pair.of(count, description);
463  }
464 
465  @NbBundle.Messages({
466  "AbstractAbstractFileNode.createSheet.score.displayName=S",
467  "AbstractAbstractFileNode.createSheet.notableFile.description=File recognized as notable.",
468  "AbstractAbstractFileNode.createSheet.interestingResult.description=File has interesting result associated with it.",
469  "AbstractAbstractFileNode.createSheet.taggedFile.description=File has been tagged.",
470  "AbstractAbstractFileNode.createSheet.notableTaggedFile.description=File tagged with notable tag.",
471  "AbstractAbstractFileNode.createSheet.noScore.description=No score"})
472  Pair<DataResultViewerTable.Score, String> getScorePropertyAndDescription(List<ContentTag> tags) {
473  DataResultViewerTable.Score score = DataResultViewerTable.Score.NO_SCORE;
474  String description = Bundle.AbstractAbstractFileNode_createSheet_noScore_description();
475  if (content.getKnown() == TskData.FileKnown.BAD) {
476  score = DataResultViewerTable.Score.NOTABLE_SCORE;
477  description = Bundle.AbstractAbstractFileNode_createSheet_notableFile_description();
478  }
479  try {
480  if (score == DataResultViewerTable.Score.NO_SCORE && !content.getArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT).isEmpty()) {
481  score = DataResultViewerTable.Score.INTERESTING_SCORE;
482  description = Bundle.AbstractAbstractFileNode_createSheet_interestingResult_description();
483  }
484  } catch (TskCoreException ex) {
485  logger.log(Level.WARNING, "Error getting artifacts for file: " + content.getName(), ex);
486  }
487  if (!tags.isEmpty() && (score == DataResultViewerTable.Score.NO_SCORE || score == DataResultViewerTable.Score.INTERESTING_SCORE)) {
488  score = DataResultViewerTable.Score.INTERESTING_SCORE;
489  description = Bundle.AbstractAbstractFileNode_createSheet_taggedFile_description();
490  for (ContentTag tag : tags) {
491  if (tag.getName().getKnownStatus() == TskData.FileKnown.BAD) {
492  score = DataResultViewerTable.Score.NOTABLE_SCORE;
493  description = Bundle.AbstractAbstractFileNode_createSheet_notableTaggedFile_description();
494  break;
495  }
496  }
497  }
498  return Pair.of(score, description);
499  }
500 
501  @NbBundle.Messages({
502  "AbstractAbstractFileNode.createSheet.comment.displayName=C"})
503  HasCommentStatus getCommentProperty(List<ContentTag> tags, CorrelationAttributeInstance attribute) {
504 
505  DataResultViewerTable.HasCommentStatus status = !tags.isEmpty() ? DataResultViewerTable.HasCommentStatus.TAG_NO_COMMENT : DataResultViewerTable.HasCommentStatus.NO_COMMENT;
506 
507  for (ContentTag tag : tags) {
508  if (!StringUtils.isBlank(tag.getComment())) {
509  //if the tag is null or empty or contains just white space it will indicate there is not a comment
510  status = DataResultViewerTable.HasCommentStatus.TAG_COMMENT;
511  break;
512  }
513  }
514  if (attribute != null && !StringUtils.isBlank(attribute.getComment())) {
515  if (status == DataResultViewerTable.HasCommentStatus.TAG_COMMENT) {
516  status = DataResultViewerTable.HasCommentStatus.CR_AND_TAG_COMMENTS;
517  } else {
518  status = DataResultViewerTable.HasCommentStatus.CR_COMMENT;
519  }
520  }
521  return status;
522  }
523 
528  String getTranslatedFileName() {
529  //If already in complete English, don't translate.
530  if (content.getName().matches("^\\p{ASCII}+$")) {
531  return "";
532  }
533  TextTranslationService tts = TextTranslationService.getInstance();
534  if (tts.hasProvider()) {
535  //Seperate out the base and ext from the contents file name.
536  String base = FilenameUtils.getBaseName(content.getName());
537  try {
538  String translation = tts.translate(base);
539  String ext = FilenameUtils.getExtension(content.getName());
540 
541  //If we have no extension, then we shouldn't add the .
542  String extensionDelimiter = (ext.isEmpty()) ? "" : ".";
543 
544  //Talk directly to this nodes pcl, fire an update when the translation
545  //is complete.
546  if (!translation.isEmpty()) {
547  return translation + extensionDelimiter + ext;
548  }
549  } catch (NoServiceProviderException noServiceEx) {
550  logger.log(Level.WARNING, "Translate unsuccessful because no TextTranslator "
551  + "implementation was provided.", noServiceEx.getMessage());
552  } catch (TranslationException noTranslationEx) {
553  logger.log(Level.WARNING, "Could not successfully translate file name "
554  + content.getName(), noTranslationEx.getMessage());
555  }
556  }
557  return "";
558  }
559 
565  List<ContentTag> getContentTagsFromDatabase() {
566  List<ContentTag> tags = new ArrayList<>();
567  try {
568  tags.addAll(Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsByContent(content));
569  } catch (TskCoreException | NoCurrentCaseException ex) {
570  logger.log(Level.SEVERE, "Failed to get tags for content " + content.getName(), ex);
571  }
572  return tags;
573  }
574 
575  CorrelationAttributeInstance getCorrelationAttributeInstance() {
576  CorrelationAttributeInstance attribute = null;
577  if (EamDb.isEnabled() && !UserPreferences.hideCentralRepoCommentsAndOccurrences()) {
578  attribute = EamArtifactUtil.getInstanceFromContent(content);
579  }
580  return attribute;
581  }
582 
583  static String getContentPath(AbstractFile file) {
584  try {
585  return file.getUniquePath();
586  } catch (TskCoreException ex) {
587  logger.log(Level.SEVERE, "Except while calling Content.getUniquePath() on " + file.getName(), ex); //NON-NLS
588  return ""; //NON-NLS
589  }
590  }
591 
592  static String getContentDisplayName(AbstractFile file) {
593  String name = file.getName();
594  switch (name) {
595  case "..":
596  return DirectoryNode.DOTDOTDIR;
597  case ".":
598  return DirectoryNode.DOTDIR;
599  default:
600  return name;
601  }
602  }
603 
614  static public void fillPropertyMap(Map<String, Object> map, AbstractFile content) {
615  map.put(NAME.toString(), getContentDisplayName(content));
616  map.put(LOCATION.toString(), getContentPath(content));
617  map.put(MOD_TIME.toString(), ContentUtils.getStringTime(content.getMtime(), content));
618  map.put(CHANGED_TIME.toString(), ContentUtils.getStringTime(content.getCtime(), content));
619  map.put(ACCESS_TIME.toString(), ContentUtils.getStringTime(content.getAtime(), content));
620  map.put(CREATED_TIME.toString(), ContentUtils.getStringTime(content.getCrtime(), content));
621  map.put(SIZE.toString(), content.getSize());
622  map.put(FLAGS_DIR.toString(), content.getDirFlagAsString());
623  map.put(FLAGS_META.toString(), content.getMetaFlagsAsString());
624  map.put(KNOWN.toString(), content.getKnown().getName());
625  map.put(MD5HASH.toString(), StringUtils.defaultString(content.getMd5Hash()));
626  map.put(MIMETYPE.toString(), StringUtils.defaultString(content.getMIMEType()));
627  map.put(EXTENSION.toString(), content.getNameExtension());
628  }
629 }
void removeIngestModuleEventListener(final PropertyChangeListener listener)
static String getStringTime(long epochSeconds, TimeZone tzone)
static synchronized IngestManager getInstance()
static void fillPropertyMap(Map< String, Object > map, AbstractFile content)
synchronized void updateSheet(NodeProperty<?>...newProps)
void addIngestModuleEventListener(final PropertyChangeListener listener)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
static void addEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
Definition: Case.java:437
static void removeEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
Definition: Case.java:482

Copyright © 2012-2018 Basis Technology. Generated on: Fri Mar 22 2019
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.