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

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