19 package org.sleuthkit.autopsy.datamodel;
21 import java.beans.PropertyChangeEvent;
22 import java.beans.PropertyChangeListener;
23 import java.lang.ref.WeakReference;
24 import java.util.ArrayList;
25 import java.util.EnumSet;
26 import java.util.List;
29 import java.util.logging.Level;
30 import java.util.stream.Collectors;
31 import org.apache.commons.io.FilenameUtils;
32 import org.apache.commons.lang3.StringUtils;
33 import org.apache.commons.lang3.tuple.Pair;
34 import org.openide.nodes.Sheet;
35 import org.openide.util.NbBundle;
36 import org.openide.util.WeakListeners;
86 String ext = abstractFile.getNameExtension();
87 if (StringUtils.isNotBlank(ext)) {
97 backgroundTasksPool.submit(
new TranslationTask(
98 new WeakReference<>(
this),
weakPcl));
126 private final PropertyChangeListener
pcl = (PropertyChangeEvent evt) -> {
127 String eventType = evt.getPropertyName();
135 if ((moduleContentEvent.getSource() instanceof Content) ==
false) {
138 Content newContent = (Content) moduleContentEvent.getSource();
141 if (
getContent().getId() == newContent.getId()) {
149 }
catch (NullPointerException ex) {
152 logger.log(Level.WARNING,
"Failed to post key refresh event", ex);
156 if (evt.getNewValue() == null) {
168 if (event.getAddedTag().getContent().equals(content)) {
171 Score value = scorePropAndDescr.getLeft();
172 String descr = scorePropAndDescr.getRight();
180 if (event.getDeletedTagInfo().getContentID() == content.getId()) {
183 Score value = scorePropAndDescr.getLeft();
184 String descr = scorePropAndDescr.getRight();
192 if (event.getContentID() == content.getId()) {
197 }
else if (eventType.equals(NodeSpecificEvents.TRANSLATION_AVAILABLE.toString())) {
198 this.setDisplayName(evt.getNewValue().toString());
200 this.setShortDescription(content.getName());
202 }
else if (eventType.equals(NodeSpecificEvents.SCO_AVAILABLE.toString())) {
203 SCOData scoData = (SCOData) evt.getNewValue();
204 if (scoData.getScoreAndDescription() != null) {
205 updateSheet(
new NodeProperty<>(SCORE.toString(), SCORE.toString(), scoData.getScoreAndDescription().getRight(), scoData.getScoreAndDescription().getLeft()));
207 if (scoData.getComment() != null) {
210 if (scoData.getCountAndDescription() != null
212 updateSheet(
new NodeProperty<>(OCCURRENCES.toString(), OCCURRENCES.toString(), scoData.getCountAndDescription().getRight(), scoData.getCountAndDescription().getLeft()));
224 private final PropertyChangeListener
weakPcl = WeakListeners.propertyChange(pcl, null);
234 Sheet sheet =
new Sheet();
235 Sheet.Set sheetSet = Sheet.createPropertiesSet();
240 newProperties.forEach((property) -> {
241 sheetSet.put(property);
247 @NbBundle.Messages({
"AbstractAbstractFileNode.nameColLbl=Name",
248 "AbstractAbstractFileNode.originalName=Original Name",
249 "AbstractAbstractFileNode.createSheet.score.name=S",
250 "AbstractAbstractFileNode.createSheet.comment.name=C",
251 "AbstractAbstractFileNode.createSheet.count.name=O",
252 "AbstractAbstractFileNode.locationColLbl=Location",
253 "AbstractAbstractFileNode.modifiedTimeColLbl=Modified Time",
254 "AbstractAbstractFileNode.changeTimeColLbl=Change Time",
255 "AbstractAbstractFileNode.accessTimeColLbl=Access Time",
256 "AbstractAbstractFileNode.createdTimeColLbl=Created Time",
257 "AbstractAbstractFileNode.sizeColLbl=Size",
258 "AbstractAbstractFileNode.flagsDirColLbl=Flags(Dir)",
259 "AbstractAbstractFileNode.flagsMetaColLbl=Flags(Meta)",
260 "AbstractAbstractFileNode.modeColLbl=Mode",
261 "AbstractAbstractFileNode.useridColLbl=UserID",
262 "AbstractAbstractFileNode.groupidColLbl=GroupID",
263 "AbstractAbstractFileNode.metaAddrColLbl=Meta Addr.",
264 "AbstractAbstractFileNode.attrAddrColLbl=Attr. Addr.",
265 "AbstractAbstractFileNode.typeDirColLbl=Type(Dir)",
266 "AbstractAbstractFileNode.typeMetaColLbl=Type(Meta)",
267 "AbstractAbstractFileNode.knownColLbl=Known",
268 "AbstractAbstractFileNode.md5HashColLbl=MD5 Hash",
269 "AbstractAbstractFileNode.objectId=Object ID",
270 "AbstractAbstractFileNode.mimeType=MIME Type",
271 "AbstractAbstractFileNode.extensionColLbl=Extension"})
274 NAME(AbstractAbstractFileNode_nameColLbl()),
276 SCORE(AbstractAbstractFileNode_createSheet_score_name()),
277 COMMENT(AbstractAbstractFileNode_createSheet_comment_name()),
279 LOCATION(AbstractAbstractFileNode_locationColLbl()),
280 MOD_TIME(AbstractAbstractFileNode_modifiedTimeColLbl()),
284 SIZE(AbstractAbstractFileNode_sizeColLbl()),
287 MODE(AbstractAbstractFileNode_modeColLbl()),
288 USER_ID(AbstractAbstractFileNode_useridColLbl()),
289 GROUP_ID(AbstractAbstractFileNode_groupidColLbl()),
292 TYPE_DIR(AbstractAbstractFileNode_typeDirColLbl()),
294 KNOWN(AbstractAbstractFileNode_knownColLbl()),
295 MD5HASH(AbstractAbstractFileNode_md5HashColLbl()),
303 this.displayString = displayString;
308 return displayString;
316 List<NodeProperty<?>> properties =
new ArrayList<>();
317 properties.add(
new NodeProperty<>(NAME.toString(), NAME.toString(),
NO_DESCR, getContentDisplayName(content)));
335 backgroundTasksPool.submit(
new GetSCOTask(
336 new WeakReference<>(
this), weakPcl));
338 properties.add(
new NodeProperty<>(LOCATION.toString(), LOCATION.toString(),
NO_DESCR, getContentPath(content)));
344 properties.add(
new NodeProperty<>(FLAGS_DIR.toString(), FLAGS_DIR.toString(),
NO_DESCR, content.getDirFlagAsString()));
345 properties.add(
new NodeProperty<>(FLAGS_META.toString(), FLAGS_META.toString(),
NO_DESCR, content.getMetaFlagsAsString()));
346 properties.add(
new NodeProperty<>(KNOWN.toString(), KNOWN.toString(),
NO_DESCR, content.getKnown().getName()));
347 properties.add(
new NodeProperty<>(MD5HASH.toString(), MD5HASH.toString(),
NO_DESCR, StringUtils.defaultString(content.getMd5Hash())));
348 properties.add(
new NodeProperty<>(MIMETYPE.toString(), MIMETYPE.toString(),
NO_DESCR, StringUtils.defaultString(content.getMIMEType())));
349 properties.add(
new NodeProperty<>(EXTENSION.toString(), EXTENSION.toString(),
NO_DESCR, content.getNameExtension()));
363 @NbBundle.Messages(
"AbstractAbstractFileNode.tagsProperty.displayName=Tags")
366 List<ContentTag> tags = getContentTagsFromDatabase();
367 sheetSet.put(
new NodeProperty<>(
"Tags", AbstractAbstractFileNode_tagsProperty_displayName(),
368 NO_DESCR, tags.stream().map(t -> t.getName().getDisplayName())
370 .collect(Collectors.joining(
", "))));
386 return StringUtils.join(file.getHashSetNames(),
", ");
387 }
catch (TskCoreException tskCoreException) {
388 logger.log(Level.WARNING,
"Error getting hashset hits: ", tskCoreException);
394 "AbstractAbstractFileNode.createSheet.count.displayName=O",
395 "AbstractAbstractFileNode.createSheet.count.hashLookupNotRun.description=Hash lookup had not been run on this file when the column was populated",
396 "# {0} - occurenceCount",
397 "AbstractAbstractFileNode.createSheet.count.description=There were {0} datasource(s) found with occurences of the MD5 correlation value"})
401 String description = defaultDescription;
404 if (attributeType != null && StringUtils.isNotBlank(attributeValue)) {
406 description = Bundle.AbstractAbstractFileNode_createSheet_count_description(count);
407 }
else if (attributeType != null) {
408 description = Bundle.AbstractAbstractFileNode_createSheet_count_hashLookupNotRun_description();
411 logger.log(Level.WARNING,
"Error getting count of datasources with correlation attribute", ex);
413 logger.log(Level.WARNING,
"Unable to normalize data to get count of datasources with correlation attribute", ex);
415 return Pair.of(count, description);
419 "AbstractAbstractFileNode.createSheet.score.displayName=S",
420 "AbstractAbstractFileNode.createSheet.notableFile.description=File recognized as notable.",
421 "AbstractAbstractFileNode.createSheet.interestingResult.description=File has interesting result associated with it.",
422 "AbstractAbstractFileNode.createSheet.taggedFile.description=File has been tagged.",
423 "AbstractAbstractFileNode.createSheet.notableTaggedFile.description=File tagged with notable tag.",
424 "AbstractAbstractFileNode.createSheet.noScore.description=No score"})
428 String description = Bundle.AbstractAbstractFileNode_createSheet_noScore_description();
429 if (content.getKnown() == TskData.FileKnown.BAD) {
431 description = Bundle.AbstractAbstractFileNode_createSheet_notableFile_description();
436 description = Bundle.AbstractAbstractFileNode_createSheet_interestingResult_description();
438 }
catch (TskCoreException ex) {
439 logger.log(Level.WARNING,
"Error getting artifacts for file: " + content.getName(), ex);
443 description = Bundle.AbstractAbstractFileNode_createSheet_taggedFile_description();
444 for (Tag tag : tags) {
445 if (tag.getName().getKnownStatus() == TskData.FileKnown.BAD) {
447 description = Bundle.AbstractAbstractFileNode_createSheet_notableTaggedFile_description();
452 return Pair.of(score, description);
456 "AbstractAbstractFileNode.createSheet.comment.displayName=C"})
462 for (Tag tag : tags) {
463 if (!StringUtils.isBlank(tag.getComment())) {
469 if (attribute != null && !StringUtils.isBlank(attribute.
getComment())) {
483 String getTranslatedFileName() {
485 if (content.getName().matches(
"^\\p{ASCII}+$")) {
488 TextTranslationService tts = TextTranslationService.getInstance();
489 if (tts.hasProvider()) {
491 String base = FilenameUtils.getBaseName(content.getName());
493 String translation = tts.translate(base);
494 String ext = FilenameUtils.getExtension(content.getName());
497 String extensionDelimiter = (ext.isEmpty()) ?
"" :
".";
501 if (!translation.isEmpty()) {
502 return translation + extensionDelimiter + ext;
504 }
catch (NoServiceProviderException noServiceEx) {
505 logger.log(Level.WARNING,
"Translate unsuccessful because no TextTranslator "
506 +
"implementation was provided.", noServiceEx.getMessage());
507 }
catch (TranslationException noTranslationEx) {
508 logger.log(Level.WARNING,
"Could not successfully translate file name "
509 + content.getName(), noTranslationEx.getMessage());
520 List<ContentTag> getContentTagsFromDatabase() {
521 List<ContentTag> tags =
new ArrayList<>();
523 tags.addAll(Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsByContent(content));
524 }
catch (TskCoreException | NoCurrentCaseException ex) {
525 logger.log(Level.SEVERE,
"Failed to get tags for content " + content.getName(), ex);
532 return new ArrayList<>(getContentTagsFromDatabase());
544 static String getContentPath(AbstractFile file) {
546 return file.getUniquePath();
547 }
catch (TskCoreException ex) {
548 logger.log(Level.SEVERE,
"Except while calling Content.getUniquePath() on " + file.getName(), ex);
553 static String getContentDisplayName(AbstractFile file) {
554 String name = file.getName();
557 return DirectoryNode.DOTDOTDIR;
559 return DirectoryNode.DOTDIR;
576 map.put(NAME.toString(), getContentDisplayName(content));
577 map.put(LOCATION.toString(), getContentPath(content));
582 map.put(SIZE.toString(), content.getSize());
583 map.put(FLAGS_DIR.toString(), content.getDirFlagAsString());
584 map.put(FLAGS_META.toString(), content.getMetaFlagsAsString());
585 map.put(KNOWN.toString(), content.getKnown().getName());
586 map.put(MD5HASH.toString(), StringUtils.defaultString(content.getMd5Hash()));
587 map.put(MIMETYPE.toString(), StringUtils.defaultString(content.getMIMEType()));
588 map.put(EXTENSION.toString(), content.getNameExtension());
synchronized void updateSheet(NodeProperty<?>...newProps)
static final Logger logger
static final String VALUE_LOADING
void removeIngestModuleEventListener(final PropertyChangeListener listener)
static String getStringTime(long epochSeconds, TimeZone tzone)
static List< String > getArchiveExtensions()
final String displayString
static synchronized IngestManager getInstance()
CorrelationAttributeInstance getCorrelationAttributeInstance()
synchronized Sheet createSheet()
Pair< DataResultViewerTable.Score, String > getScorePropertyAndDescription(List< Tag > tags)
List< Tag > getAllTagsFromDatabase()
static void fillPropertyMap(Map< String, Object > map, AbstractFile content)
Long getCountUniqueCaseDataSourceTuplesHavingTypeValue(CorrelationAttributeInstance.Type aType, String value)
static final Set< Case.Events > CASE_EVENTS_OF_INTEREST
static EamDb getInstance()
static boolean displayTranslatedFileNames()
static CorrelationAttributeInstance getInstanceFromContent(Content content)
Pair< Long, String > getCountPropertyAndDescription(CorrelationAttributeInstance.Type attributeType, String attributeValue, String defaultDescription)
static boolean isEnabled()
AbstractFilePropertyType(String displayString)
static void post(String nodeName, Object event)
void addIngestModuleEventListener(final PropertyChangeListener listener)
synchronized static Logger getLogger(String name)
HasCommentStatus getCommentProperty(List< Tag > tags, CorrelationAttributeInstance attribute)
static void addEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
static boolean hideCentralRepoCommentsAndOccurrences()
final PropertyChangeListener pcl
List< NodeProperty<?> > getProperties()
static void removeEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
static String getHashSetHitsCsvList(AbstractFile file)
void addTagProperty(Sheet.Set sheetSet)
final PropertyChangeListener weakPcl
static final String NO_DESCR