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.text.MessageFormat;
 
   25 import java.util.ArrayList;
 
   26 import java.util.EnumSet;
 
   27 import java.util.List;
 
   30 import java.util.logging.Level;
 
   31 import java.util.stream.Collectors;
 
   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;
 
   88         String ext = abstractFile.getNameExtension();
 
   89         if (StringUtils.isNotBlank(ext)) {
 
  102         } 
catch (TskCoreException ex) {
 
  103             logger.log(Level.SEVERE, String.format(
"Failed attempt to cache the " 
  104                     + 
"unique path of the abstract file instance. Name: %s (objID=%d)",
 
  105                     this.content.getName(), this.
content.getId()), ex);
 
  109             backgroundTasksPool.submit(
new TranslationTask(
 
  110                     new WeakReference<>(
this), 
weakPcl));
 
  138     private final PropertyChangeListener 
pcl = (PropertyChangeEvent evt) -> {
 
  139         String eventType = evt.getPropertyName();
 
  147             if ((moduleContentEvent.getSource() instanceof Content) == 
false) {
 
  150             Content newContent = (Content) moduleContentEvent.getSource();
 
  153             if (
getContent().getId() == newContent.getId()) {
 
  161                 } 
catch (NullPointerException ex) {
 
  164                     logger.log(Level.WARNING, 
"Failed to post key refresh event", ex); 
 
  168             if (evt.getNewValue() == null) {
 
  180             if (event.getAddedTag().getContent().equals(
content)) {
 
  183                 Score value = scorePropAndDescr.getLeft();
 
  184                 String descr = scorePropAndDescr.getRight();
 
  185                 List<CorrelationAttributeInstance> listWithJustFileAttr = 
new ArrayList<>();
 
  187                 if (corrInstance != null) {
 
  188                     listWithJustFileAttr.add(corrInstance);
 
  196             if (event.getDeletedTagInfo().getContentID() == 
content.getId()) {
 
  199                 Score value = scorePropAndDescr.getLeft();
 
  200                 String descr = scorePropAndDescr.getRight();
 
  201                 List<CorrelationAttributeInstance> listWithJustFileAttr = 
new ArrayList<>();
 
  203                 if (corrInstance != null) {
 
  204                     listWithJustFileAttr.add(corrInstance);
 
  212             if (event.getContentID() == 
content.getId()) {
 
  214                 List<CorrelationAttributeInstance> listWithJustFileAttr = 
new ArrayList<>();
 
  216                 if (corrInstance != null) {
 
  217                     listWithJustFileAttr.add(corrInstance);
 
  221         } 
else if (eventType.equals(NodeSpecificEvents.TRANSLATION_AVAILABLE.toString())) {
 
  222             this.setDisplayName(evt.getNewValue().toString());
 
  224             this.setShortDescription(
content.getName());
 
  227             SCOData scoData = (SCOData) evt.getNewValue();
 
  228             if (scoData.getScoreAndDescription() != null) {
 
  229                 updateSheet(
new NodeProperty<>(SCORE.toString(), SCORE.toString(), scoData.getScoreAndDescription().getRight(), scoData.getScoreAndDescription().getLeft()));
 
  231             if (scoData.getComment() != null) {
 
  234             if (scoData.getCountAndDescription() != null) {
 
  235                 updateSheet(
new NodeProperty<>(OCCURRENCES.toString(), OCCURRENCES.toString(), scoData.getCountAndDescription().getRight(), scoData.getCountAndDescription().getLeft()));
 
  247     private final PropertyChangeListener 
weakPcl = WeakListeners.propertyChange(pcl, null);
 
  257         Sheet sheet = 
new Sheet();
 
  258         Sheet.Set sheetSet = Sheet.createPropertiesSet();
 
  263         newProperties.forEach((property) -> {
 
  264             sheetSet.put(property);
 
  270     @NbBundle.Messages({
"AbstractAbstractFileNode.nameColLbl=Name",
 
  271         "AbstractAbstractFileNode.originalName=Original Name",
 
  272         "AbstractAbstractFileNode.createSheet.score.name=S",
 
  273         "AbstractAbstractFileNode.createSheet.comment.name=C",
 
  274         "AbstractAbstractFileNode.createSheet.count.name=O",
 
  275         "AbstractAbstractFileNode.locationColLbl=Location",
 
  276         "AbstractAbstractFileNode.modifiedTimeColLbl=Modified Time",
 
  277         "AbstractAbstractFileNode.changeTimeColLbl=Change Time",
 
  278         "AbstractAbstractFileNode.accessTimeColLbl=Access Time",
 
  279         "AbstractAbstractFileNode.createdTimeColLbl=Created Time",
 
  280         "AbstractAbstractFileNode.sizeColLbl=Size",
 
  281         "AbstractAbstractFileNode.flagsDirColLbl=Flags(Dir)",
 
  282         "AbstractAbstractFileNode.flagsMetaColLbl=Flags(Meta)",
 
  283         "AbstractAbstractFileNode.modeColLbl=Mode",
 
  284         "AbstractAbstractFileNode.useridColLbl=UserID",
 
  285         "AbstractAbstractFileNode.groupidColLbl=GroupID",
 
  286         "AbstractAbstractFileNode.metaAddrColLbl=Meta Addr.",
 
  287         "AbstractAbstractFileNode.attrAddrColLbl=Attr. Addr.",
 
  288         "AbstractAbstractFileNode.typeDirColLbl=Type(Dir)",
 
  289         "AbstractAbstractFileNode.typeMetaColLbl=Type(Meta)",
 
  290         "AbstractAbstractFileNode.knownColLbl=Known",
 
  291         "AbstractAbstractFileNode.md5HashColLbl=MD5 Hash",
 
  292         "AbstractAbstractFileNode.sha256HashColLbl=SHA-256 Hash",
 
  293         "AbstractAbstractFileNode.objectId=Object ID",
 
  294         "AbstractAbstractFileNode.mimeType=MIME Type",
 
  295         "AbstractAbstractFileNode.extensionColLbl=Extension"})
 
  298         NAME(AbstractAbstractFileNode_nameColLbl()),
 
  300         SCORE(AbstractAbstractFileNode_createSheet_score_name()),
 
  301         COMMENT(AbstractAbstractFileNode_createSheet_comment_name()),
 
  303         LOCATION(AbstractAbstractFileNode_locationColLbl()),
 
  304         MOD_TIME(AbstractAbstractFileNode_modifiedTimeColLbl()),
 
  308         SIZE(AbstractAbstractFileNode_sizeColLbl()),
 
  311         MODE(AbstractAbstractFileNode_modeColLbl()),
 
  312         USER_ID(AbstractAbstractFileNode_useridColLbl()),
 
  313         GROUP_ID(AbstractAbstractFileNode_groupidColLbl()),
 
  316         TYPE_DIR(AbstractAbstractFileNode_typeDirColLbl()),
 
  318         KNOWN(AbstractAbstractFileNode_knownColLbl()),
 
  319         MD5HASH(AbstractAbstractFileNode_md5HashColLbl()),
 
  328             this.displayString = displayString;
 
  333             return displayString;
 
  341         List<NodeProperty<?>> properties = 
new ArrayList<>();
 
  360             backgroundTasksPool.submit(
new GetSCOTask(
 
  361                     new WeakReference<>(
this), weakPcl));
 
  374         properties.add(
new NodeProperty<>(SHA256HASH.toString(), SHA256HASH.toString(), 
NO_DESCR, StringUtils.defaultString(
content.getSha256Hash())));
 
  390     @NbBundle.Messages(
"AbstractAbstractFileNode.tagsProperty.displayName=Tags")
 
  393         List<ContentTag> tags = getContentTagsFromDatabase();
 
  394         sheetSet.put(
new NodeProperty<>(
"Tags", AbstractAbstractFileNode_tagsProperty_displayName(),
 
  395                 NO_DESCR, tags.stream().map(t -> t.getName().getDisplayName())
 
  397                         .collect(Collectors.joining(
", "))));
 
  413             return StringUtils.join(file.getHashSetNames(), 
", ");
 
  414         } 
catch (TskCoreException tskCoreException) {
 
  415             logger.log(Level.WARNING, 
"Error getting hashset hits: ", tskCoreException); 
 
  421         "AbstractAbstractFileNode.createSheet.count.displayName=O",
 
  422         "AbstractAbstractFileNode.createSheet.count.hashLookupNotRun.description=Hash lookup had not been run on this file when the column was populated",
 
  423         "# {0} - occurrenceCount",
 
  424         "AbstractAbstractFileNode.createSheet.count.description=There were {0} datasource(s) found with occurrences of the MD5 correlation value"})
 
  428         String description = defaultDescription;
 
  431             if (attributeInstance != null && StringUtils.isNotBlank(attributeInstance.
getCorrelationValue())) {
 
  433                 description = Bundle.AbstractAbstractFileNode_createSheet_count_description(count);
 
  434             } 
else if (attributeInstance != null) {
 
  435                 description = Bundle.AbstractAbstractFileNode_createSheet_count_hashLookupNotRun_description();
 
  438             logger.log(Level.WARNING, 
"Error getting count of datasources with correlation attribute", ex);
 
  440             logger.log(Level.WARNING, 
"Unable to normalize data to get count of datasources with correlation attribute", ex);
 
  442         return Pair.of(count, description);
 
  446         "AbstractAbstractFileNode.createSheet.comment.displayName=C"})
 
  452         for (Tag tag : tags) {
 
  453             if (!StringUtils.isBlank(tag.getComment())) {
 
  459         if (attributes != null && !attributes.isEmpty()) {
 
  461                 if (attribute != null && !StringUtils.isBlank(attribute.getComment())) {
 
  480     String getTranslatedFileName() {
 
  483         } 
catch (NoServiceProviderException | TranslationException ex) {
 
  484             logger.log(Level.WARNING, MessageFormat.format(
"Error translating file name (objID={0}))", 
content.getId()), ex);
 
  494     List<ContentTag> getContentTagsFromDatabase() {
 
  495         List<ContentTag> tags = 
new ArrayList<>();
 
  497             tags.addAll(Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsByContent(
content));
 
  498         } 
catch (TskCoreException | NoCurrentCaseException ex) {
 
  499             logger.log(Level.SEVERE, 
"Failed to get tags for content " + 
content.getName(), ex);
 
  506         return new ArrayList<>(getContentTagsFromDatabase());
 
  509     static String getContentPath(AbstractFile file) {
 
  511             return file.getUniquePath();
 
  512         } 
catch (TskCoreException ex) {
 
  513             logger.log(Level.SEVERE, 
"Except while calling Content.getUniquePath() on " + file.getName(), ex); 
 
  518     static String getContentDisplayName(AbstractFile file) {
 
  519         String name = file.getName();
 
  522                 return DirectoryNode.DOTDOTDIR;
 
  524                 return DirectoryNode.DOTDIR;
 
  541         map.put(NAME.toString(), getContentDisplayName(content));
 
  542         map.put(LOCATION.toString(), getContentPath(content));
 
  547         map.put(SIZE.toString(), content.getSize());
 
  548         map.put(FLAGS_DIR.toString(), content.getDirFlagAsString());
 
  549         map.put(FLAGS_META.toString(), content.getMetaFlagsAsString());
 
  550         map.put(KNOWN.toString(), content.getKnown().getName());
 
  551         map.put(MD5HASH.toString(), StringUtils.defaultString(content.getMd5Hash()));
 
  552         map.put(SHA256HASH.toString(), StringUtils.defaultString(content.getSha256Hash()));
 
  553         map.put(MIMETYPE.toString(), StringUtils.defaultString(content.getMIMEType()));
 
  554         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 List< String > getArchiveExtensions()
 
final String displayString
 
static synchronized IngestManager getInstance()
 
synchronized Sheet createSheet()
 
static String getFormattedTime(long epochTime)
 
HasCommentStatus getCommentProperty(List< Tag > tags, List< CorrelationAttributeInstance > attributes)
 
static final Set< IngestManager.IngestModuleEvent > INGEST_MODULE_EVENTS_OF_INTEREST
 
List< Tag > getAllTagsFromDatabase()
 
String getCorrelationValue()
 
static void fillPropertyMap(Map< String, Object > map, AbstractFile content)
 
static String translate(String fileName)
 
Pair< Long, String > getCountPropertyAndDescription(CorrelationAttributeInstance attributeInstance, String defaultDescription)
 
static final Set< Case.Events > CASE_EVENTS_OF_INTEREST
 
static TextTranslationService getInstance()
 
static boolean displayTranslatedFileNames()
 
static CorrelationAttributeInstance getCorrAttrForFile(AbstractFile file)
 
static boolean getHideSCOColumns()
 
Pair< Score, String > getScorePropertyAndDescription(List< Tag > tags)
 
AbstractFilePropertyType(String displayString)
 
synchronized boolean hasProvider()
 
static void post(String nodeName, Object event)
 
Long getCountCasesWithOtherInstances(CorrelationAttributeInstance instance)
 
void addIngestModuleEventListener(final PropertyChangeListener listener)
 
synchronized static Logger getLogger(String name)
 
static void addEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
 
final PropertyChangeListener pcl
 
List< NodeProperty<?> > getProperties()
 
static void removeEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
 
static CentralRepository getInstance()
 
static String getHashSetHitsCsvList(AbstractFile file)
 
void addTagProperty(Sheet.Set sheetSet)
 
static boolean isEnabled()
 
final PropertyChangeListener weakPcl
 
static final String NO_DESCR