diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java index e3c750826d2dff1b2ebec83a66576c61b73f40f2..28402861dffe2a36997e9691752b59b0eafa5f85 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2016 Basis Technology Corp. + * Copyright 2011-2017 Basis Technology Corp. * Contact: carrier <at> sleuthkit <dot> org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,11 +22,11 @@ import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.List; -import org.openide.nodes.Children; import java.util.Map; import java.util.logging.Level; import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; +import org.openide.nodes.Children; import org.openide.nodes.Sheet; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; @@ -47,25 +47,23 @@ */ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends AbstractContentNode<T> { - private static final Logger LOGGER = Logger.getLogger(AbstractAbstractFileNode.class.getName()); + private static final Logger logger = Logger.getLogger(AbstractAbstractFileNode.class.getName()); + + @NbBundle.Messages("AbstractAbstractFileNode.addFileProperty.desc=no description") + private static final String NO_DESCR = Bundle.AbstractAbstractFileNode_addFileProperty_desc(); /** - * @param <T> type of the AbstractFile data to encapsulate - * @param abstractFile file to encapsulate + * @param abstractFile file to wrap */ AbstractAbstractFileNode(T abstractFile) { super(abstractFile); - String name = abstractFile.getName(); - int dotIndex = name.lastIndexOf("."); - if (dotIndex > 0) { - String ext = name.substring(dotIndex).toLowerCase(); - + String ext = abstractFile.getNameExtension(); + if (StringUtils.isNotBlank(ext)) { + ext = "." + ext; // If this is an archive file we will listen for ingest events // that will notify us when new content has been identified. - for (String s : FileTypeExtensions.getArchiveExtensions()) { - if (ext.equals(s)) { - IngestManager.getInstance().addIngestModuleEventListener(pcl); - } + if (FileTypeExtensions.getArchiveExtensions().contains(ext)) { + IngestManager.getInstance().addIngestModuleEventListener(pcl); } } // Listen for case events so that we can detect when case is closed @@ -127,144 +125,149 @@ private void updateSheet() { this.setSheet(createSheet()); } - // Note: this order matters for the search result, changed it if the order of property headers on the "KeywordSearchNode"changed public static enum AbstractFilePropertyType { NAME { - @Override - public String toString() { - return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.nameColLbl"); - } - }, + @Override + public String toString() { + return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.nameColLbl"); + } + }, + EXTENSION { + @Override + public String toString() { + return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.extensionColLbl"); + } + }, LOCATION { - @Override - public String toString() { - return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.locationColLbl"); - } - }, + @Override + public String toString() { + return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.locationColLbl"); + } + }, MOD_TIME { - @Override - public String toString() { - return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.modifiedTimeColLbl"); - } - }, + @Override + public String toString() { + return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.modifiedTimeColLbl"); + } + }, CHANGED_TIME { - @Override - public String toString() { - return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.changeTimeColLbl"); - } - }, + @Override + public String toString() { + return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.changeTimeColLbl"); + } + }, ACCESS_TIME { - @Override - public String toString() { - return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.accessTimeColLbl"); - } - }, + @Override + public String toString() { + return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.accessTimeColLbl"); + } + }, CREATED_TIME { - @Override - public String toString() { - return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.createdTimeColLbl"); - } - }, + @Override + public String toString() { + return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.createdTimeColLbl"); + } + }, SIZE { - @Override - public String toString() { - return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.sizeColLbl"); - } - }, + @Override + public String toString() { + return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.sizeColLbl"); + } + }, FLAGS_DIR { - @Override - public String toString() { - return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.flagsDirColLbl"); - } - }, + @Override + public String toString() { + return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.flagsDirColLbl"); + } + }, FLAGS_META { - @Override - public String toString() { - return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.flagsMetaColLbl"); - } - }, + @Override + public String toString() { + return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.flagsMetaColLbl"); + } + }, MODE { - @Override - public String toString() { - return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.modeColLbl"); - } - }, + @Override + public String toString() { + return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.modeColLbl"); + } + }, USER_ID { - @Override - public String toString() { - return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.useridColLbl"); - } - }, + @Override + public String toString() { + return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.useridColLbl"); + } + }, GROUP_ID { - @Override - public String toString() { - return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.groupidColLbl"); - } - }, + @Override + public String toString() { + return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.groupidColLbl"); + } + }, META_ADDR { - @Override - public String toString() { - return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.metaAddrColLbl"); - } - }, + @Override + public String toString() { + return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.metaAddrColLbl"); + } + }, ATTR_ADDR { - @Override - public String toString() { - return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.attrAddrColLbl"); - } - }, + @Override + public String toString() { + return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.attrAddrColLbl"); + } + }, TYPE_DIR { - @Override - public String toString() { - return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.typeDirColLbl"); - } - }, + @Override + public String toString() { + return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.typeDirColLbl"); + } + }, TYPE_META { - @Override - public String toString() { - return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.typeMetaColLbl"); - } - }, + @Override + public String toString() { + return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.typeMetaColLbl"); + } + }, KNOWN { - @Override - public String toString() { - return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.knownColLbl"); - } - }, + @Override + public String toString() { + return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.knownColLbl"); + } + }, HASHSETS { - @Override - public String toString() { - return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.inHashsetsColLbl"); - } - }, + @Override + public String toString() { + return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.inHashsetsColLbl"); + } + }, MD5HASH { - @Override - public String toString() { - return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.md5HashColLbl"); - } - }, + @Override + public String toString() { + return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.md5HashColLbl"); + } + }, ObjectID { - @Override - public String toString() { - return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.objectId"); + @Override + public String toString() { + return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.objectId"); - } - }, + } + }, MIMETYPE { - @Override - public String toString() { - return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.mimeType"); + @Override + public String toString() { + return NbBundle.getMessage(this.getClass(), "AbstractAbstractFileNode.mimeType"); - } - }, + } + }, } /** * Fill map with AbstractFile properties * - * @param map map with preserved ordering, where property names/values are - * put + * @param map map with preserved ordering, where property names/values + * are put * @param content to extract properties from */ public static void fillPropertyMap(Map<String, Object> map, AbstractFile content) { @@ -273,10 +276,10 @@ public static void fillPropertyMap(Map<String, Object> map, AbstractFile content try { path = content.getUniquePath(); } catch (TskCoreException ex) { - LOGGER.log(Level.SEVERE, "Except while calling Content.getUniquePath() on {0}", content); //NON-NLS + logger.log(Level.SEVERE, "Except while calling Content.getUniquePath() on {0}", content); //NON-NLS } - map.put(AbstractFilePropertyType.NAME.toString(), AbstractAbstractFileNode.getContentDisplayName(content)); + map.put(AbstractFilePropertyType.NAME.toString(), getContentDisplayName(content)); map.put(AbstractFilePropertyType.LOCATION.toString(), path); map.put(AbstractFilePropertyType.MOD_TIME.toString(), ContentUtils.getStringTime(content.getMtime(), content)); map.put(AbstractFilePropertyType.CHANGED_TIME.toString(), ContentUtils.getStringTime(content.getCtime(), content)); @@ -289,32 +292,34 @@ public static void fillPropertyMap(Map<String, Object> map, AbstractFile content map.put(AbstractFilePropertyType.USER_ID.toString(), content.getUid()); map.put(AbstractFilePropertyType.GROUP_ID.toString(), content.getGid()); map.put(AbstractFilePropertyType.META_ADDR.toString(), content.getMetaAddr()); - map.put(AbstractFilePropertyType.ATTR_ADDR.toString(), Long.toString(content.getAttrType().getValue()) + "-" + content.getAttributeId()); + map.put(AbstractFilePropertyType.ATTR_ADDR.toString(), content.getAttrType().getValue() + "-" + content.getAttributeId()); map.put(AbstractFilePropertyType.TYPE_DIR.toString(), content.getDirType().getLabel()); map.put(AbstractFilePropertyType.TYPE_META.toString(), content.getMetaType().toString()); map.put(AbstractFilePropertyType.KNOWN.toString(), content.getKnown().getName()); map.put(AbstractFilePropertyType.HASHSETS.toString(), getHashSetHitsForFile(content)); - map.put(AbstractFilePropertyType.MD5HASH.toString(), content.getMd5Hash() == null ? "" : content.getMd5Hash()); + map.put(AbstractFilePropertyType.MD5HASH.toString(), StringUtils.defaultString(content.getMd5Hash())); map.put(AbstractFilePropertyType.ObjectID.toString(), content.getId()); - map.put(AbstractFilePropertyType.MIMETYPE.toString(), content.getMIMEType() == null ? "" : content.getMIMEType()); + map.put(AbstractFilePropertyType.MIMETYPE.toString(), StringUtils.defaultString(content.getMIMEType())); + map.put(AbstractFilePropertyType.EXTENSION.toString(), content.getNameExtension()); } /** * Used by subclasses of AbstractAbstractFileNode to add the tags property * to their sheets. - * @param ss the modifiable Sheet.Set returned by Sheet.get(Sheet.PROPERTIES) + * + * @param ss the modifiable Sheet.Set returned by + * Sheet.get(Sheet.PROPERTIES) */ protected void addTagProperty(Sheet.Set ss) { - final String NO_DESCR = NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.addFileProperty.desc"); List<ContentTag> tags; try { tags = Case.getCurrentCase().getServices().getTagsManager().getContentTagsByContent(content); } catch (TskCoreException ex) { tags = new ArrayList<>(); - LOGGER.log(Level.SEVERE, "Failed to get tags for content " + content.getName(), ex); + logger.log(Level.SEVERE, "Failed to get tags for content " + content.getName(), ex); } ss.put(new NodeProperty<>("Tags", NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.addFileProperty.tags.displayName"), - NO_DESCR, tags.stream().map(t -> t.getName().getDisplayName()).collect(Collectors.joining(", ")))); + NO_DESCR, tags.stream().map(t -> t.getName().getDisplayName()).distinct().collect(Collectors.joining(", ")))); } static String getContentDisplayName(AbstractFile file) { @@ -330,12 +335,11 @@ static String getContentDisplayName(AbstractFile file) { } } - @SuppressWarnings("deprecation") private static String getHashSetHitsForFile(AbstractFile content) { try { return StringUtils.join(content.getHashSetNames(), ", "); } catch (TskCoreException tskCoreException) { - LOGGER.log(Level.WARNING, "Error getting hashset hits: ", tskCoreException); //NON-NLS + logger.log(Level.WARNING, "Error getting hashset hits: ", tskCoreException); //NON-NLS return ""; } } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Bundle.properties b/Core/src/org/sleuthkit/autopsy/datamodel/Bundle.properties index 964b2df827f4010d4c78f2c5ddc905408e06926e..13b2cd63bf5f6b748dda764142480d35d1d62ea4 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Bundle.properties @@ -18,6 +18,7 @@ AbstractAbstractFileNode.typeMetaColLbl=Type(Meta) AbstractAbstractFileNode.knownColLbl=Known AbstractAbstractFileNode.inHashsetsColLbl=In Hashsets AbstractAbstractFileNode.md5HashColLbl=MD5 Hash +AbstractAbstractFileNode.extensionColLbl=Extension AbstractAbstractFileNode.mimeType = MIME Type AbstractContentChildren.CreateTSKNodeVisitor.exception.noNodeMsg=No Node defined for the given SleuthkitItem AbstractContentChildren.createAutopsyNodeVisitor.exception.noNodeMsg=No Node defined for the given DisplayableItem @@ -229,7 +230,6 @@ DeleteReportAction.actionDisplayName.multipleReports=Delete Reports DeleteReportAction.actionPerformed.showConfirmDialog.title=Confirm Deletion DeleteReportAction.actionPerformed.showConfirmDialog.single.msg=Do you want to delete 1 report from the case? DeleteReportAction.actionPerformed.showConfirmDialog.multiple.msg=Do you want to delete {0} reports from the case? -AbstractAbstractFileNode.addFileProperty.desc=no description AbstractAbstractFileNode.addFileProperty.tags.name=Tags AbstractAbstractFileNode.addFileProperty.tags.displayName=Tags BlackboardArtifactNode.createSheet.tags.name=Tags @@ -244,4 +244,4 @@ FileTypeExtensionFilters.autDocHtmlFilter.text=HTML FileTypeExtensionFilters.autDocOfficeFilter.text=Office FileTypeExtensionFilters.autoDocPdfFilter.text=PDF FileTypeExtensionFilters.autDocTxtFilter.text=Plain Text -FileTypeExtensionFilters.autDocRtfFilter.text=Rich Text \ No newline at end of file +FileTypeExtensionFilters.autDocRtfFilter.text=Rich Text