From 5242566ea09907245ec9f32b3b5950f88b01874a Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 8 Nov 2016 17:30:48 -0500 Subject: [PATCH 01/10] 1917 Added Node Level between Views and (Files by Ext AND Files by MIME) --- .../datamodel/AbstractContentChildren.java | 5 ++ .../autopsy/datamodel/AutopsyItemVisitor.java | 8 +++ .../datamodel/DisplayableItemNodeVisitor.java | 8 ++- .../autopsy/datamodel/FileTypes.java | 42 ++++++++++++ .../autopsy/datamodel/FileTypesNew.java | 66 +++++++++++++++++++ .../autopsy/datamodel/ResultsNode.java | 2 + .../autopsy/datamodel/ViewsNode.java | 3 +- .../directorytree/DataResultFilterNode.java | 15 ++++- .../DirectoryTreeFilterChildren.java | 11 ++++ 9 files changed, 156 insertions(+), 4 deletions(-) create mode 100644 Core/src/org/sleuthkit/autopsy/datamodel/FileTypes.java create mode 100644 Core/src/org/sleuthkit/autopsy/datamodel/FileTypesNew.java diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentChildren.java b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentChildren.java index f2babbc88e..db85e382f3 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentChildren.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentChildren.java @@ -189,6 +189,11 @@ abstract class AbstractContentChildren extends Keys { return new ResultsNode(r.getSleuthkitCase()); } + @Override + public AbstractNode visit(FileTypes ft) { + return new FileTypesNew(ft.getSleuthkitCase()); + } + @Override public AbstractNode visit(Reports reportsItem) { return new Reports.ReportsListNode(); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyItemVisitor.java b/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyItemVisitor.java index d673acb71e..e06e7c9d08 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyItemVisitor.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyItemVisitor.java @@ -71,6 +71,8 @@ public interface AutopsyItemVisitor { T visit(Accounts accountsItem); + T visit(FileTypes aThis); + static abstract public class Default implements AutopsyItemVisitor { protected abstract T defaultVisit(AutopsyVisitableItem ec); @@ -170,6 +172,12 @@ public interface AutopsyItemVisitor { return defaultVisit(r); } + + @Override + public T visit(FileTypes ft) { + return defaultVisit(ft); + } + @Override public T visit(Reports reportsItem) { return defaultVisit(reportsItem); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java index e300ace134..3af8d3c0f8 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java @@ -140,6 +140,8 @@ public interface DisplayableItemNodeVisitor { T visit(Accounts.DefaultAccountTypeNode node); + T visit(FileTypesNew fileTypes); + /** * Visitor with an implementable default behavior for all types. Override * specific visit types to not use the default behavior. @@ -256,7 +258,11 @@ public interface DisplayableItemNodeVisitor { public T visit(ResultsNode rn) { return defaultVisit(rn); } - + + @Override + public T visit(FileTypesNew ft) { + return defaultVisit(ft); + } @Override public T visit(DataSourcesNode in) { return defaultVisit(in); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypes.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypes.java new file mode 100644 index 0000000000..f977a1e797 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypes.java @@ -0,0 +1,42 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.datamodel; + +import org.sleuthkit.datamodel.SleuthkitCase; + +/** + * Results node support + */ +public class FileTypes implements AutopsyVisitableItem { + + private SleuthkitCase skCase; + + public FileTypes(SleuthkitCase skCase) { + this.skCase = skCase; + } + + @Override + public T accept(AutopsyItemVisitor v) { + return v.visit(this); + } + + public SleuthkitCase getSleuthkitCase() { + return skCase; + } +} diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesNew.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesNew.java new file mode 100644 index 0000000000..b0273b4ae4 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesNew.java @@ -0,0 +1,66 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.sleuthkit.autopsy.datamodel; + +import java.util.Arrays; +import org.openide.nodes.Sheet; +import org.openide.util.NbBundle; +import org.openide.util.lookup.Lookups; +import org.sleuthkit.autopsy.datamodel.accounts.FileTypeExtensionFilters; +import org.sleuthkit.datamodel.SleuthkitCase; + +/** + * + * @author wschaefer + */ +public class FileTypesNew extends DisplayableItemNode { + + @NbBundle.Messages("FileTypesNew.name.text=File Types_New") + public static final String NAME = Bundle.FileTypesNew_name_text(); + + public FileTypesNew(SleuthkitCase sleuthkitCase) { + super(new RootContentChildren(Arrays.asList( + + new FileTypeExtensionFilters(sleuthkitCase) + )), Lookups.singleton(NAME)); + setName(NAME); + setDisplayName(NAME); + this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file_types.png"); + } + + + @Override + public boolean isLeafTypeNode() { + return false; + } + + @Override + public T accept(DisplayableItemNodeVisitor v) { + return v.visit(this); + } + + @Override + @NbBundle.Messages({ + "FileTypesNew.createSheet.name.name=Name", + "FileTypesNew.createSheet.name.displayName=Name", + "FileTypesNew.createSheet.name.desc=no description"}) + protected Sheet createSheet() { + Sheet s = super.createSheet(); + Sheet.Set ss = s.get(Sheet.PROPERTIES); + if (ss == null) { + ss = Sheet.createPropertiesSet(); + s.put(ss); + } + + ss.put(new NodeProperty<>(Bundle.FileTypesNew_createSheet_name_name(), + Bundle.FileTypesNew_createSheet_name_displayName(), + Bundle.FileTypesNew_createSheet_name_desc(), + NAME + )); + return s; + } + +} diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ResultsNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/ResultsNode.java index ebf71a872d..d3b2cf8371 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ResultsNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/ResultsNode.java @@ -33,6 +33,8 @@ public class ResultsNode extends DisplayableItemNode { @NbBundle.Messages("ResultsNode.name.text=Results") public static final String NAME = Bundle.ResultsNode_name_text(); + + public ResultsNode(SleuthkitCase sleuthkitCase) { super(new RootContentChildren(Arrays.asList( new ExtractedContent(sleuthkitCase), diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ViewsNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/ViewsNode.java index 89a6ac170f..06551eab67 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ViewsNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/ViewsNode.java @@ -36,7 +36,8 @@ public class ViewsNode extends DisplayableItemNode { public ViewsNode(SleuthkitCase sleuthkitCase) { super(new RootContentChildren(Arrays.asList( - new FileTypeExtensionFilters(sleuthkitCase), + // new FileTypeExtensionFilters(sleuthkitCase), + new FileTypes(sleuthkitCase), // June '15: Recent Files was removed because it was not useful w/out filtering // add it back in if we can filter the results to a more managable size. // new RecentFiles(sleuthkitCase), diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java index ec66a5d4c7..26a14f34d3 100755 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java @@ -42,6 +42,7 @@ import org.sleuthkit.autopsy.datamodel.DirectoryNode; import org.sleuthkit.autopsy.datamodel.DisplayableItemNode; import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor; import org.sleuthkit.autopsy.datamodel.FileNode; +import org.sleuthkit.autopsy.datamodel.FileTypesNew; import org.sleuthkit.autopsy.datamodel.LayoutFileNode; import org.sleuthkit.autopsy.datamodel.LocalFileNode; import org.sleuthkit.autopsy.datamodel.Reports; @@ -231,7 +232,12 @@ public class DataResultFilterNode extends FilterNode { // The base class Action is "Collapse All", inappropriate. return null; } - + + @Override + public List visit(FileTypesNew fileTypes) { + return defaultVisit(fileTypes); + } + @Override protected List defaultVisit(DisplayableItemNode ditem) { //preserve the default node's actions @@ -271,6 +277,7 @@ public class DataResultFilterNode extends FilterNode { } return c; } + } /* @@ -322,7 +329,11 @@ public class DataResultFilterNode extends FilterNode { protected AbstractAction defaultVisit(DisplayableItemNode c) { return openChild(c); } - + + @Override + public AbstractAction visit(FileTypesNew fileTypes) { + return openChild(fileTypes); + } /** * Tell the originating ExplorerManager to display the given * dataModelNode. diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeFilterChildren.java b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeFilterChildren.java index e6ce27bc0e..728e42c426 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeFilterChildren.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeFilterChildren.java @@ -29,6 +29,7 @@ import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode; import org.sleuthkit.autopsy.datamodel.DisplayableItemNode; import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor; import org.sleuthkit.autopsy.datamodel.FileNode; +import org.sleuthkit.autopsy.datamodel.FileTypesNew; import org.sleuthkit.autopsy.datamodel.LayoutFileNode; import org.sleuthkit.autopsy.datamodel.LocalFileNode; import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode; @@ -236,6 +237,11 @@ class DirectoryTreeFilterChildren extends FilterNode.Children { return visitDeep(vdn); //return ! vdn.hasContentChildren(); } + + @Override + public Boolean visit(FileTypesNew ft) { + return defaultVisit(ft); + } } private static class ShowItemVisitor extends DisplayableItemNodeVisitor.Default { @@ -273,5 +279,10 @@ class DirectoryTreeFilterChildren extends FilterNode.Children { return true; //return vdn.hasContentChildren(); } + + @Override + public Boolean visit(FileTypesNew fileTypes) { + return defaultVisit(fileTypes); + } } } From cfeae3485099cb12a3d09e1970463a037524ef4d Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 11 Nov 2016 13:55:47 -0500 Subject: [PATCH 02/10] 1917 - Mime Type tree added - still needs clean up and null case --- .../datamodel/AbstractContentChildren.java | 10 +- .../autopsy/datamodel/AutopsyItemVisitor.java | 12 +- .../autopsy/datamodel/Bundle.properties | 2 +- .../datamodel/DisplayableItemNodeVisitor.java | 33 +- ...leTypeNode.java => FileTypeByExtNode.java} | 6 +- .../autopsy/datamodel/FileTypes.java | 68 ++- ...TypesNode.java => FileTypesByExtNode.java} | 14 +- .../datamodel/FileTypesByMimeType.java | 407 ++++++++++++++++++ .../autopsy/datamodel/FileTypesNew.java | 66 --- .../directorytree/DataResultFilterNode.java | 10 +- .../DirectoryTreeFilterChildren.java | 8 +- 11 files changed, 539 insertions(+), 97 deletions(-) rename Core/src/org/sleuthkit/autopsy/datamodel/{FileTypeNode.java => FileTypeByExtNode.java} (97%) rename Core/src/org/sleuthkit/autopsy/datamodel/{FileTypesNode.java => FileTypesByExtNode.java} (93%) create mode 100644 Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java delete mode 100644 Core/src/org/sleuthkit/autopsy/datamodel/FileTypesNew.java diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentChildren.java b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentChildren.java index db85e382f3..67cfda93df 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentChildren.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentChildren.java @@ -22,6 +22,7 @@ import org.openide.nodes.AbstractNode; import org.openide.nodes.Children.Keys; import org.openide.nodes.Node; import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.datamodel.FileTypes.FileTypesNode; import org.sleuthkit.autopsy.datamodel.accounts.FileTypeExtensionFilters; import org.sleuthkit.autopsy.datamodel.accounts.RecentFiles; import org.sleuthkit.autopsy.datamodel.accounts.Accounts; @@ -131,7 +132,7 @@ abstract class AbstractContentChildren extends Keys { @Override public AbstractNode visit(FileTypeExtensionFilters sf) { - return new FileTypesNode(sf.getSleuthkitCase(), null); + return new FileTypesByExtNode(sf.getSleuthkitCase(), null); } @Override @@ -191,7 +192,7 @@ abstract class AbstractContentChildren extends Keys { @Override public AbstractNode visit(FileTypes ft) { - return new FileTypesNew(ft.getSleuthkitCase()); + return new FileTypesNode(ft.getSleuthkitCase()); } @Override @@ -210,5 +211,10 @@ abstract class AbstractContentChildren extends Keys { NbBundle.getMessage(this.getClass(), "AbstractContentChildren.createAutopsyNodeVisitor.exception.noNodeMsg")); } + + @Override + public AbstractNode visit(FileTypesByMimeType ftByMimeTypeItem) { + return ftByMimeTypeItem.new FileTypesByMimeTypeNode(ftByMimeTypeItem.getSleuthkitCase()); + } } } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyItemVisitor.java b/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyItemVisitor.java index e06e7c9d08..f0d2bcc253 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyItemVisitor.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyItemVisitor.java @@ -71,7 +71,10 @@ public interface AutopsyItemVisitor { T visit(Accounts accountsItem); - T visit(FileTypes aThis); + T visit(FileTypes fileTypesItem); + + T visit(FileTypesByMimeType aThis); + static abstract public class Default implements AutopsyItemVisitor { @@ -101,7 +104,12 @@ public interface AutopsyItemVisitor { public T visit(FileTypeExtensionFilters.ExecutableFilter ef) { return defaultVisit(ef); } - + + @Override + public T visit(FileTypesByMimeType ftByMimeType) { + return defaultVisit(ftByMimeType); + } + @Override public T visit(DeletedContent dc) { return defaultVisit(dc); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Bundle.properties b/Core/src/org/sleuthkit/autopsy/datamodel/Bundle.properties index 3c24e02283..590f0fa993 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Bundle.properties @@ -124,7 +124,7 @@ FileTypeNode.createSheet.filterType.desc=no description FileTypeNode.createSheet.fileExt.name=File Extensions FileTypeNode.createSheet.fileExt.displayName=File Extensions FileTypeNode.createSheet.fileExt.desc=no description -FileTypesNode.fname.text=File Types +FileTypesNode.fname.text=By Extension FileTypesNode.createSheet.name.name=Name FileTypesNode.createSheet.name.displayName=Name FileTypesNode.createSheet.name.desc=no description diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java index 3af8d3c0f8..51b6b5ce11 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java @@ -22,6 +22,7 @@ import org.sleuthkit.autopsy.datamodel.DeletedContent.DeletedContentsChildren.De import org.sleuthkit.autopsy.datamodel.DeletedContent.DeletedContentsNode; import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootChildren.FileSizeNode; import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootNode; +import org.sleuthkit.autopsy.datamodel.FileTypes.FileTypesNode; import org.sleuthkit.autopsy.datamodel.accounts.Accounts; /** @@ -54,7 +55,7 @@ public interface DisplayableItemNodeVisitor { */ T visit(ViewsNode vn); - T visit(FileTypeNode fsfn); + T visit(FileTypeByExtNode fsfn); T visit(DeletedContentNode dcn); @@ -64,7 +65,7 @@ public interface DisplayableItemNodeVisitor { T visit(FileSizeNode fsn); - T visit(FileTypesNode sfn); + T visit(FileTypesByExtNode sfn); T visit(RecentFilesNode rfn); @@ -140,7 +141,14 @@ public interface DisplayableItemNodeVisitor { T visit(Accounts.DefaultAccountTypeNode node); - T visit(FileTypesNew fileTypes); + T visit(FileTypes.FileTypesNode fileTypes); + + T visit(FileTypesByMimeType.FileTypesByMimeTypeNode aThis); + + T visit(FileTypesByMimeType.MediaTypeNode aThis); + + T visit(FileTypesByMimeType.MediaSubTypeNode aThis); + /** * Visitor with an implementable default behavior for all types. Override @@ -195,10 +203,21 @@ public interface DisplayableItemNodeVisitor { } @Override - public T visit(FileTypeNode fsfn) { + public T visit(FileTypeByExtNode fsfn) { return defaultVisit(fsfn); } - + @Override + public T visit(FileTypesByMimeType.FileTypesByMimeTypeNode ftByMimeTypeNode) { + return defaultVisit(ftByMimeTypeNode); + } + @Override + public T visit(FileTypesByMimeType.MediaTypeNode ftByMimeTypeMediaTypeNode) { + return defaultVisit(ftByMimeTypeMediaTypeNode); + } + @Override + public T visit(FileTypesByMimeType.MediaSubTypeNode ftByMimeTypeMediaTypeNode) { + return defaultVisit(ftByMimeTypeMediaTypeNode); + } @Override public T visit(DeletedContentNode dcn) { return defaultVisit(dcn); @@ -220,7 +239,7 @@ public interface DisplayableItemNodeVisitor { } @Override - public T visit(FileTypesNode sfn) { + public T visit(FileTypesByExtNode sfn) { return defaultVisit(sfn); } @@ -260,7 +279,7 @@ public interface DisplayableItemNodeVisitor { } @Override - public T visit(FileTypesNew ft) { + public T visit(FileTypesNode ft) { return defaultVisit(ft); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypeNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypeByExtNode.java similarity index 97% rename from Core/src/org/sleuthkit/autopsy/datamodel/FileTypeNode.java rename to Core/src/org/sleuthkit/autopsy/datamodel/FileTypeByExtNode.java index ce65c82194..9561c3f2ef 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypeNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypeByExtNode.java @@ -48,14 +48,14 @@ import org.sleuthkit.datamodel.TskData; * Node for a specific file type / extension. Children of it will be the files * of that type. */ -public class FileTypeNode extends DisplayableItemNode { +public class FileTypeByExtNode extends DisplayableItemNode { FileTypeExtensionFilters.SearchFilterInterface filter; SleuthkitCase skCase; // deprecated in favor of the version that takes an observable to provide refresh updates @Deprecated - FileTypeNode(FileTypeExtensionFilters.SearchFilterInterface filter, SleuthkitCase skCase) { + FileTypeByExtNode(FileTypeExtensionFilters.SearchFilterInterface filter, SleuthkitCase skCase) { super(Children.create(new FileTypeChildFactory(filter, skCase), true), Lookups.singleton(filter.getDisplayName())); this.filter = filter; this.skCase = skCase; @@ -69,7 +69,7 @@ public class FileTypeNode extends DisplayableItemNode { * @param o Observable that sends updates when the child factories * should refresh */ - FileTypeNode(FileTypeExtensionFilters.SearchFilterInterface filter, SleuthkitCase skCase, Observable o) { + FileTypeByExtNode(FileTypeExtensionFilters.SearchFilterInterface filter, SleuthkitCase skCase, Observable o) { super(Children.create(new FileTypeChildFactory(filter, skCase, o), true), Lookups.singleton(filter.getDisplayName())); this.filter = filter; this.skCase = skCase; diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypes.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypes.java index f977a1e797..44b357f12f 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypes.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypes.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,6 +18,11 @@ */ package org.sleuthkit.autopsy.datamodel; +import java.util.Arrays; +import org.openide.nodes.Sheet; +import org.openide.util.NbBundle; +import org.openide.util.lookup.Lookups; +import org.sleuthkit.autopsy.datamodel.accounts.FileTypeExtensionFilters; import org.sleuthkit.datamodel.SleuthkitCase; /** @@ -27,7 +32,7 @@ public class FileTypes implements AutopsyVisitableItem { private SleuthkitCase skCase; - public FileTypes(SleuthkitCase skCase) { + FileTypes(SleuthkitCase skCase) { this.skCase = skCase; } @@ -36,7 +41,64 @@ public class FileTypes implements AutopsyVisitableItem { return v.visit(this); } - public SleuthkitCase getSleuthkitCase() { + SleuthkitCase getSleuthkitCase() { return skCase; } + + /** + * + * @author wschaefer + */ + public static class FileTypesNode extends DisplayableItemNode { + + @NbBundle.Messages("FileTypesNew.name.text=File Types") + private static final String NAME = Bundle.FileTypesNew_name_text(); + + public FileTypesNode(SleuthkitCase sleuthkitCase) { + super(new RootContentChildren(Arrays.asList( + new FileTypeExtensionFilters(sleuthkitCase), + new FileTypesByMimeType(sleuthkitCase) + )), Lookups.singleton(NAME)); + setName(NAME); + setDisplayName(NAME); + this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file_types.png"); + } + + @Override + public boolean isLeafTypeNode() { + return false; + } + + @Override + public T accept(DisplayableItemNodeVisitor v) { + return v.visit(this); + } + + @Override + @NbBundle.Messages({ + "FileTypesNew.createSheet.name.name=Name", + "FileTypesNew.createSheet.name.displayName=Name", + "FileTypesNew.createSheet.name.desc=no description"}) + protected Sheet createSheet() { + Sheet s = super.createSheet(); + Sheet.Set ss = s.get(Sheet.PROPERTIES); + if (ss == null) { + ss = Sheet.createPropertiesSet(); + s.put(ss); + } + + ss.put(new NodeProperty<>(Bundle.FileTypesNew_createSheet_name_name(), + Bundle.FileTypesNew_createSheet_name_displayName(), + Bundle.FileTypesNew_createSheet_name_desc(), + NAME + )); + return s; + } + + @Override + public String getItemType() { + return getClass().getName(); + } + + } } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByExtNode.java similarity index 93% rename from Core/src/org/sleuthkit/autopsy/datamodel/FileTypesNode.java rename to Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByExtNode.java index daf1a31780..d9ce314ae7 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByExtNode.java @@ -37,9 +37,9 @@ import org.sleuthkit.datamodel.SleuthkitCase; /** * Node for root of file types view. Children are nodes for specific types. */ -public class FileTypesNode extends DisplayableItemNode { +public class FileTypesByExtNode extends DisplayableItemNode { - private static final String FNAME = NbBundle.getMessage(FileTypesNode.class, "FileTypesNode.fname.text"); + private static final String FNAME = NbBundle.getMessage(FileTypesByExtNode.class, "FileTypesNode.fname.text"); private final FileTypeExtensionFilters.RootFilter filter; /** * @@ -47,7 +47,7 @@ public class FileTypesNode extends DisplayableItemNode { * @param filter null to display root node of file type tree, pass in * something to provide a sub-node. */ - FileTypesNode(SleuthkitCase skCase, FileTypeExtensionFilters.RootFilter filter) { + FileTypesByExtNode(SleuthkitCase skCase, FileTypeExtensionFilters.RootFilter filter) { super(Children.create(new FileTypesChildren(skCase, filter, null), true), Lookups.singleton(filter == null ? FNAME : filter.getName())); this.filter = filter; init(); @@ -60,7 +60,7 @@ public class FileTypesNode extends DisplayableItemNode { * @param o Observable that was created by a higher-level node that * provides updates on events */ - private FileTypesNode(SleuthkitCase skCase, FileTypeExtensionFilters.RootFilter filter, Observable o) { + private FileTypesByExtNode(SleuthkitCase skCase, FileTypeExtensionFilters.RootFilter filter, Observable o) { super(Children.create(new FileTypesChildren(skCase, filter, o), true), Lookups.singleton(filter == null ? FNAME : filter.getName())); this.filter = filter; init(); @@ -220,11 +220,11 @@ public class FileTypesNode extends DisplayableItemNode { protected Node createNodeForKey(FileTypeExtensionFilters.SearchFilterInterface key) { // make new nodes for the sub-nodes if (key.getName().equals(FileTypeExtensionFilters.RootFilter.TSK_DOCUMENT_FILTER.getName())) { - return new FileTypesNode(skCase, FileTypeExtensionFilters.RootFilter.TSK_DOCUMENT_FILTER, notifier); + return new FileTypesByExtNode(skCase, FileTypeExtensionFilters.RootFilter.TSK_DOCUMENT_FILTER, notifier); } else if (key.getName().equals(FileTypeExtensionFilters.RootFilter.TSK_EXECUTABLE_FILTER.getName())) { - return new FileTypesNode(skCase, FileTypeExtensionFilters.RootFilter.TSK_EXECUTABLE_FILTER, notifier); + return new FileTypesByExtNode(skCase, FileTypeExtensionFilters.RootFilter.TSK_EXECUTABLE_FILTER, notifier); } else { - return new FileTypeNode(key, skCase, notifier); + return new FileTypeByExtNode(key, skCase, notifier); } } } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java new file mode 100644 index 0000000000..59711cf1a0 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java @@ -0,0 +1,407 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011-2016 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.datamodel; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Observable; +import java.util.Observer; +import java.util.logging.Level; +import org.openide.nodes.AbstractNode; +import org.openide.nodes.ChildFactory; +import org.openide.nodes.Children; +import org.openide.nodes.Node; +import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.core.UserPreferences; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.ingest.IngestManager; +import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.Content; +import org.sleuthkit.datamodel.ContentVisitor; +import org.sleuthkit.datamodel.DerivedFile; +import org.sleuthkit.datamodel.Directory; +import org.sleuthkit.datamodel.File; +import org.sleuthkit.datamodel.LayoutFile; +import org.sleuthkit.datamodel.LocalFile; +import org.sleuthkit.datamodel.SleuthkitCase; +import org.sleuthkit.datamodel.TskCoreException; +import org.sleuthkit.datamodel.TskData; + +/** + * Node for Root of the 'By Mime Type' view located in the File Types view, + * shows all files with a mime type. Will intially be empty until file type + * identification has been performed. + */ +class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { + + static SleuthkitCase skCase; + static final String EMPTY_MIME_TREE_STRING = "Data not available. Run file type identification module."; + /** + * The nodes of this tree will be determined dynamically by the mimetypes + * which exist in the database. This hashmap will store them with the media + * type as the key and a list of media subtypes as the value. + */ + private final HashMap> existingMimeTypes = new HashMap<>(); + private static final Logger LOGGER = Logger.getLogger(FileTypesByMimeType.class.getName()); + + /* + * The pcl is in the class because it has the easiest mechanisms to add + * and remove itself during its life cycles. + */ + private final PropertyChangeListener pcl = new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + String eventType = evt.getPropertyName(); + if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) + || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString()) + // || eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString()) + || eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())) { + /** + * Checking for a current case is a stop gap measure until a + * different way of handling the closing of cases is worked out. + * Currently, remote events may be received for a case that is + * already closed. + */ + try { + Case.getCurrentCase(); + populateHashMap(); + } catch (IllegalStateException notUsed) { + /** + * Case is closed, do nothing. + */ + } + } + } + }; + + private List getMediaTypeList() { + synchronized (existingMimeTypes) { + List mediaTypes = new ArrayList<>(existingMimeTypes.keySet()); + Collections.sort(mediaTypes); + return mediaTypes; + } + } + + private void populateHashMap() { + StringBuilder allDistinctMimeTypesQuery = new StringBuilder(); + allDistinctMimeTypesQuery.append("SELECT DISTINCT mime_type from tsk_files where mime_type NOT null"); + allDistinctMimeTypesQuery.append(" AND dir_type = ").append(TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue()).append(";"); //NON-NLS + synchronized (existingMimeTypes) { + existingMimeTypes.clear(); + } + + if (skCase == null) { + + return; + } + try (SleuthkitCase.CaseDbQuery dbQuery = skCase.executeQuery(allDistinctMimeTypesQuery.toString())) { + ResultSet resultSet = dbQuery.getResultSet(); + synchronized (existingMimeTypes) { + while (resultSet.next()) { + final String mime_type = resultSet.getString("mime_type"); //NON-NLS + if (!mime_type.isEmpty()) { + String mimeType[] = mime_type.split("/"); + if (!mimeType[0].isEmpty() && !mimeType[1].isEmpty()) { + if (!existingMimeTypes.containsKey(mimeType[0])) { + existingMimeTypes.put(mimeType[0], new ArrayList<>()); + } + existingMimeTypes.get(mimeType[0]).add(mimeType[1]); + } + } + } + } + } catch (TskCoreException | SQLException ex) { + LOGGER.log(Level.WARNING, "Unable to populate File Types by MIME Type tree view from DB: ", ex); //NON-NLS + } + setChanged(); + notifyObservers(); + } + + FileTypesByMimeType(SleuthkitCase skCase) { + IngestManager.getInstance().addIngestJobEventListener(pcl); + IngestManager.getInstance().addIngestModuleEventListener(pcl); +// Case.addPropertyChangeListener(pcl); + + FileTypesByMimeType.skCase = skCase; + } + + SleuthkitCase getSleuthkitCase() { + return skCase; + } + + @Override + public T accept(AutopsyItemVisitor v) { + return v.visit(this); + } + + class FileTypesByMimeTypeNode extends DisplayableItemNode { + + @NbBundle.Messages("FileTypesByMimeType.name.text=By MIME Type") + final String NAME = Bundle.FileTypesByMimeType_name_text(); + + FileTypesByMimeTypeNode(SleuthkitCase sleuthkitCase) { + super(Children.create(new FileTypesByMimeTypeNodeChildren(skCase), true)); + setName(NAME); + setDisplayName(NAME); + this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file_types.png"); + } + + @Override + public boolean isLeafTypeNode() { +// if (!existingMimeTypes.isEmpty()) { + return false; +// } +// else { +// return true; +// } + } + + @Override + public T accept(DisplayableItemNodeVisitor v) { + return v.visit(this); + } + + @Override + public String getItemType() { + return getClass().getName(); + } + + } + + class FileTypesByMimeTypeNodeChildren extends ChildFactory implements Observer { + + private SleuthkitCase skCase; + + /** + * + * @param skCase (or null if one needs to be created) + */ + public FileTypesByMimeTypeNodeChildren(SleuthkitCase skCase) { + super(); + addObserver(this); + this.skCase = skCase; + } + + @Override + protected boolean createKeys(List mediaTypeNodes) { +// if (!existingMimeTypes.isEmpty()) { + mediaTypeNodes.addAll(getMediaTypeList()); +// } else { +// mediaTypeNodes.add(EMPTY_MIME_TREE_STRING); +// } + return true; + } + + @Override + protected Node createNodeForKey(String key) { + return new MediaTypeNode(key); + + } + + @Override + public void update(Observable o, Object arg) { + refresh(true); + } + + } + + class MediaTypeNode extends DisplayableItemNode { + + String mediaType; + + MediaTypeNode(String name) { + super(Children.create(new MediaTypeChildren(name), true)); + setName(name); + setDisplayName(name); + this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file_types.png"); + } + + @Override + public boolean isLeafTypeNode() { + return false; + } + + @Override + public T accept(DisplayableItemNodeVisitor v) { + return v.visit(this); + } + + @Override + public String getItemType() { + return getClass().getName(); + } + + } + + class MediaTypeChildren extends ChildFactory implements Observer { + + String mediaType; + + MediaTypeChildren(String name) { + addObserver(this); + this.mediaType = name; + } + + @Override + protected boolean createKeys(List mediaTypeNodes) { +// if (!existingMimeTypes.isEmpty() && !mediaType.equals(EMPTY_MIME_TREE_STRING)) { +// System.out.println(mediaType); +// System.out.println(existingMimeTypes.size()); + mediaTypeNodes.addAll(existingMimeTypes.get(mediaType)); + return true; +// } else { +// return false; +// } + } + + @Override + protected Node createNodeForKey(String subtype) { + String mimeType = mediaType + "/" + subtype; + return new MediaSubTypeNode(mimeType); + } + + @Override + public void update(Observable o, Object arg) { + refresh(true); + } + + } + + class MediaSubTypeNode extends DisplayableItemNode { + + private MediaSubTypeNode(String mimeType) { + super(Children.create(new MediaSubTypeNodeChildren(mimeType), true)); + init(mimeType); + } + + private void init(String mimeType) { + super.setName(mimeType); + updateDisplayName(mimeType); + this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-filter-icon.png"); //NON-NLS + } + + private void updateDisplayName(String mimeType) { + final long count = MediaSubTypeNodeChildren.calculateItems(skCase, mimeType); + super.setDisplayName(mimeType.split("/")[1] + " (" + count + ")"); + } + + @Override + public boolean isLeafTypeNode() { + return true; + } + + @Override + public T accept(DisplayableItemNodeVisitor v) { + return v.visit(this); + } + + @Override + public String getItemType() { + return getClass().getName(); + } + + } + + private static class MediaSubTypeNodeChildren extends ChildFactory.Detachable { + + private final String mimeType; + + MediaSubTypeNodeChildren(String mimeType) { + super(); + this.mimeType = mimeType; + } + + /** + * Get children count without actually loading all nodes + * + * @return + */ + private static long calculateItems(SleuthkitCase sleuthkitCase, String mimeType) { + try { + return sleuthkitCase.countFilesWhere(createQuery(mimeType)); + } catch (TskCoreException ex) { + LOGGER.log(Level.SEVERE, "Error getting file search view count", ex); //NON-NLS + return 0; + } + } + + @Override + protected boolean createKeys(List list) { + try { + List files = skCase.findAllFilesWhere(createQuery(mimeType)); + list.addAll(files); + } catch (TskCoreException ex) { + LOGGER.log(Level.SEVERE, "Couldn't get search results", ex); //NON-NLS + } + return true; + } + + private static String createQuery(String mimeType) { + StringBuilder query = new StringBuilder(); + query.append("(dir_type = ").append(TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue()).append(")"); //NON-NLS + if (UserPreferences.hideKnownFilesInViewsTree()) { + query.append(" AND (known IS NULL OR known != ").append(TskData.FileKnown.KNOWN.getFileKnownValue()).append(")"); //NON-NLS + } + query.append(" AND mime_type = '").append(mimeType).append("'"); + return query.toString(); + } + + @Override + protected Node createNodeForKey(Content key) { + return key.accept(new ContentVisitor.Default() { + @Override + public FileNode visit(File f) { + return new FileNode(f, false); + } + + @Override + public DirectoryNode visit(Directory d) { + return new DirectoryNode(d); + } + + @Override + public LayoutFileNode visit(LayoutFile lf) { + return new LayoutFileNode(lf); + } + + @Override + public LocalFileNode visit(DerivedFile df) { + return new LocalFileNode(df); + } + + @Override + public LocalFileNode visit(LocalFile lf) { + return new LocalFileNode(lf); + } + + @Override + protected AbstractNode defaultVisit(Content di) { + throw new UnsupportedOperationException(NbBundle.getMessage(this.getClass(), "FileTypeChildren.exception.notSupported.msg", di.toString())); + } + }); + } + } +} diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesNew.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesNew.java deleted file mode 100644 index b0273b4ae4..0000000000 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesNew.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.sleuthkit.autopsy.datamodel; - -import java.util.Arrays; -import org.openide.nodes.Sheet; -import org.openide.util.NbBundle; -import org.openide.util.lookup.Lookups; -import org.sleuthkit.autopsy.datamodel.accounts.FileTypeExtensionFilters; -import org.sleuthkit.datamodel.SleuthkitCase; - -/** - * - * @author wschaefer - */ -public class FileTypesNew extends DisplayableItemNode { - - @NbBundle.Messages("FileTypesNew.name.text=File Types_New") - public static final String NAME = Bundle.FileTypesNew_name_text(); - - public FileTypesNew(SleuthkitCase sleuthkitCase) { - super(new RootContentChildren(Arrays.asList( - - new FileTypeExtensionFilters(sleuthkitCase) - )), Lookups.singleton(NAME)); - setName(NAME); - setDisplayName(NAME); - this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file_types.png"); - } - - - @Override - public boolean isLeafTypeNode() { - return false; - } - - @Override - public T accept(DisplayableItemNodeVisitor v) { - return v.visit(this); - } - - @Override - @NbBundle.Messages({ - "FileTypesNew.createSheet.name.name=Name", - "FileTypesNew.createSheet.name.displayName=Name", - "FileTypesNew.createSheet.name.desc=no description"}) - protected Sheet createSheet() { - Sheet s = super.createSheet(); - Sheet.Set ss = s.get(Sheet.PROPERTIES); - if (ss == null) { - ss = Sheet.createPropertiesSet(); - s.put(ss); - } - - ss.put(new NodeProperty<>(Bundle.FileTypesNew_createSheet_name_name(), - Bundle.FileTypesNew_createSheet_name_displayName(), - Bundle.FileTypesNew_createSheet_name_desc(), - NAME - )); - return s; - } - -} diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java index 26a14f34d3..2d3d26d5b3 100755 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java @@ -42,7 +42,7 @@ import org.sleuthkit.autopsy.datamodel.DirectoryNode; import org.sleuthkit.autopsy.datamodel.DisplayableItemNode; import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor; import org.sleuthkit.autopsy.datamodel.FileNode; -import org.sleuthkit.autopsy.datamodel.FileTypesNew; +import org.sleuthkit.autopsy.datamodel.FileTypes.FileTypesNode; import org.sleuthkit.autopsy.datamodel.LayoutFileNode; import org.sleuthkit.autopsy.datamodel.LocalFileNode; import org.sleuthkit.autopsy.datamodel.Reports; @@ -234,10 +234,11 @@ public class DataResultFilterNode extends FilterNode { } @Override - public List visit(FileTypesNew fileTypes) { + public List visit(FileTypesNode fileTypes) { return defaultVisit(fileTypes); } + @Override protected List defaultVisit(DisplayableItemNode ditem) { //preserve the default node's actions @@ -331,9 +332,12 @@ public class DataResultFilterNode extends FilterNode { } @Override - public AbstractAction visit(FileTypesNew fileTypes) { + public AbstractAction visit(FileTypesNode fileTypes) { return openChild(fileTypes); } + + + /** * Tell the originating ExplorerManager to display the given * dataModelNode. diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeFilterChildren.java b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeFilterChildren.java index 728e42c426..09759c79a8 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeFilterChildren.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeFilterChildren.java @@ -29,7 +29,7 @@ import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode; import org.sleuthkit.autopsy.datamodel.DisplayableItemNode; import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor; import org.sleuthkit.autopsy.datamodel.FileNode; -import org.sleuthkit.autopsy.datamodel.FileTypesNew; +import org.sleuthkit.autopsy.datamodel.FileTypes.FileTypesNode; import org.sleuthkit.autopsy.datamodel.LayoutFileNode; import org.sleuthkit.autopsy.datamodel.LocalFileNode; import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode; @@ -239,9 +239,10 @@ class DirectoryTreeFilterChildren extends FilterNode.Children { } @Override - public Boolean visit(FileTypesNew ft) { + public Boolean visit(FileTypesNode ft) { return defaultVisit(ft); } + } private static class ShowItemVisitor extends DisplayableItemNodeVisitor.Default { @@ -281,8 +282,9 @@ class DirectoryTreeFilterChildren extends FilterNode.Children { } @Override - public Boolean visit(FileTypesNew fileTypes) { + public Boolean visit(FileTypesNode fileTypes) { return defaultVisit(fileTypes); } + } } From f45b0b642b6d1b37a38e591f3a3f9e3cc207b6d1 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 11 Nov 2016 16:13:46 -0500 Subject: [PATCH 03/10] 1917 Mime Tree fixed when updating from empty to contents --- .../datamodel/DisplayableItemNodeVisitor.java | 7 +++ .../datamodel/FileTypesByMimeType.java | 61 +++++++++++++------ 2 files changed, 49 insertions(+), 19 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java index 51b6b5ce11..457d4a8353 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java @@ -149,6 +149,8 @@ public interface DisplayableItemNodeVisitor { T visit(FileTypesByMimeType.MediaSubTypeNode aThis); + T visit(FileTypesByMimeType.EmptyNode aThis); + /** * Visitor with an implementable default behavior for all types. Override @@ -218,6 +220,11 @@ public interface DisplayableItemNodeVisitor { public T visit(FileTypesByMimeType.MediaSubTypeNode ftByMimeTypeMediaTypeNode) { return defaultVisit(ftByMimeTypeMediaTypeNode); } + @Override + public T visit(FileTypesByMimeType.EmptyNode ftByMimeTypeEmptyNode) { + return defaultVisit(ftByMimeTypeEmptyNode); + } + @Override public T visit(DeletedContentNode dcn) { return defaultVisit(dcn); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java index 59711cf1a0..24974d2df7 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java @@ -58,7 +58,6 @@ import org.sleuthkit.datamodel.TskData; class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { static SleuthkitCase skCase; - static final String EMPTY_MIME_TREE_STRING = "Data not available. Run file type identification module."; /** * The nodes of this tree will be determined dynamically by the mimetypes * which exist in the database. This hashmap will store them with the media @@ -77,7 +76,7 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { String eventType = evt.getPropertyName(); if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString()) - // || eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString()) + // || eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString()) || eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())) { /** * Checking for a current case is a stop gap measure until a @@ -144,7 +143,7 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { IngestManager.getInstance().addIngestJobEventListener(pcl); IngestManager.getInstance().addIngestModuleEventListener(pcl); // Case.addPropertyChangeListener(pcl); - + // populateHashMap(); FileTypesByMimeType.skCase = skCase; } @@ -172,7 +171,7 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { @Override public boolean isLeafTypeNode() { // if (!existingMimeTypes.isEmpty()) { - return false; + return false; // } // else { // return true; @@ -194,6 +193,7 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { class FileTypesByMimeTypeNodeChildren extends ChildFactory implements Observer { private SleuthkitCase skCase; + static final String EMPTY_MIME_TREE_STRING = "Data not available. Run file type identification module."; /** * @@ -207,17 +207,21 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { @Override protected boolean createKeys(List mediaTypeNodes) { -// if (!existingMimeTypes.isEmpty()) { - mediaTypeNodes.addAll(getMediaTypeList()); -// } else { -// mediaTypeNodes.add(EMPTY_MIME_TREE_STRING); -// } + if (!existingMimeTypes.isEmpty()) { + mediaTypeNodes.addAll(getMediaTypeList()); + } else { + mediaTypeNodes.add(EMPTY_MIME_TREE_STRING); + } return true; } @Override protected Node createNodeForKey(String key) { + if (!existingMimeTypes.isEmpty()) { return new MediaTypeNode(key); + } else { + return new EmptyNode(EMPTY_MIME_TREE_STRING); + } } @@ -228,6 +232,31 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { } + class EmptyNode extends DisplayableItemNode { + + EmptyNode(String name) { + super(Children.LEAF); + super.setName(name); + setName(name); + setDisplayName(name); + } + + @Override + public boolean isLeafTypeNode() { + return true; + } + + @Override + public T accept(DisplayableItemNodeVisitor v) { + return v.visit(this); + } + + @Override + public String getItemType() { + return getClass().getName(); + } + } + class MediaTypeNode extends DisplayableItemNode { String mediaType; @@ -267,20 +296,14 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { @Override protected boolean createKeys(List mediaTypeNodes) { -// if (!existingMimeTypes.isEmpty() && !mediaType.equals(EMPTY_MIME_TREE_STRING)) { -// System.out.println(mediaType); -// System.out.println(existingMimeTypes.size()); - mediaTypeNodes.addAll(existingMimeTypes.get(mediaType)); - return true; -// } else { -// return false; -// } + mediaTypeNodes.addAll(existingMimeTypes.get(mediaType)); + return true; } @Override protected Node createNodeForKey(String subtype) { - String mimeType = mediaType + "/" + subtype; - return new MediaSubTypeNode(mimeType); + String mimeType = mediaType + "/" + subtype; + return new MediaSubTypeNode(mimeType); } @Override From e8f7029a0f3c4bcd84d705f6cd88d6a4237142f7 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Mon, 14 Nov 2016 13:05:23 -0500 Subject: [PATCH 04/10] 1917-Comments added and other minor clean up, emptyNode removed --- .../datamodel/DisplayableItemNodeVisitor.java | 15 +- .../autopsy/datamodel/FileTypeByExtNode.java | 2 +- .../autopsy/datamodel/FileTypes.java | 5 +- .../datamodel/FileTypesByMimeType.java | 157 +++++++++++------- 4 files changed, 108 insertions(+), 71 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java index 457d4a8353..a203b6054a 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java @@ -143,13 +143,11 @@ public interface DisplayableItemNodeVisitor { T visit(FileTypes.FileTypesNode fileTypes); - T visit(FileTypesByMimeType.FileTypesByMimeTypeNode aThis); + T visit(FileTypesByMimeType.FileTypesByMimeTypeNode ftByMimeTypeNode); - T visit(FileTypesByMimeType.MediaTypeNode aThis); + T visit(FileTypesByMimeType.MediaTypeNode ftByMimeTypeMediaType); - T visit(FileTypesByMimeType.MediaSubTypeNode aThis); - - T visit(FileTypesByMimeType.EmptyNode aThis); + T visit(FileTypesByMimeType.MediaSubTypeNode ftByMimeTypeMediaSubType); /** @@ -208,22 +206,21 @@ public interface DisplayableItemNodeVisitor { public T visit(FileTypeByExtNode fsfn) { return defaultVisit(fsfn); } + @Override public T visit(FileTypesByMimeType.FileTypesByMimeTypeNode ftByMimeTypeNode) { return defaultVisit(ftByMimeTypeNode); } + @Override public T visit(FileTypesByMimeType.MediaTypeNode ftByMimeTypeMediaTypeNode) { return defaultVisit(ftByMimeTypeMediaTypeNode); } + @Override public T visit(FileTypesByMimeType.MediaSubTypeNode ftByMimeTypeMediaTypeNode) { return defaultVisit(ftByMimeTypeMediaTypeNode); } - @Override - public T visit(FileTypesByMimeType.EmptyNode ftByMimeTypeEmptyNode) { - return defaultVisit(ftByMimeTypeEmptyNode); - } @Override public T visit(DeletedContentNode dcn) { diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypeByExtNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypeByExtNode.java index 9561c3f2ef..f708a8d056 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypeByExtNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypeByExtNode.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2014 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypes.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypes.java index 44b357f12f..54a4c792c8 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypes.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypes.java @@ -26,7 +26,7 @@ import org.sleuthkit.autopsy.datamodel.accounts.FileTypeExtensionFilters; import org.sleuthkit.datamodel.SleuthkitCase; /** - * Results node support + * File Types node support */ public class FileTypes implements AutopsyVisitableItem { @@ -46,8 +46,7 @@ public class FileTypes implements AutopsyVisitableItem { } /** - * - * @author wschaefer + * Node which will contain By Mime Type and By Extension nodes. */ public static class FileTypesNode extends DisplayableItemNode { diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java index 24974d2df7..3ec3a41054 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java @@ -51,9 +51,11 @@ import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; /** - * Node for Root of the 'By Mime Type' view located in the File Types view, - * shows all files with a mime type. Will intially be empty until file type - * identification has been performed. + * Class which contains the Nodes for the 'By Mime Type' view located in the + * File Types view, shows all files with a mime type. Will initially be empty + * until file type identification has been performed. Contains a Property Change + * Listener which is checking for changes in IngestJobEvent Completed or + * Cancelled and IngestModuleEvent Content Changed. */ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { @@ -96,6 +98,12 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { } }; + /** + * Retrieve the media types by retrieving the keyset from the hashmap. + * + * @return mediaTypes - a list of strings representing all distinct media + * types of files for this case + */ private List getMediaTypeList() { synchronized (existingMimeTypes) { List mediaTypes = new ArrayList<>(existingMimeTypes.keySet()); @@ -104,6 +112,10 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { } } + /** + * Performs the query on the database to get all distinct MIME types of + * files in it, and populate the hashmap with those results. + */ private void populateHashMap() { StringBuilder allDistinctMimeTypesQuery = new StringBuilder(); allDistinctMimeTypesQuery.append("SELECT DISTINCT mime_type from tsk_files where mime_type NOT null"); @@ -112,11 +124,11 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { existingMimeTypes.clear(); } - if (skCase == null) { + if (getSleuthkitCase() == null) { return; } - try (SleuthkitCase.CaseDbQuery dbQuery = skCase.executeQuery(allDistinctMimeTypesQuery.toString())) { + try (SleuthkitCase.CaseDbQuery dbQuery = getSleuthkitCase().executeQuery(allDistinctMimeTypesQuery.toString())) { ResultSet resultSet = dbQuery.getResultSet(); synchronized (existingMimeTypes) { while (resultSet.next()) { @@ -142,11 +154,12 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { FileTypesByMimeType(SleuthkitCase skCase) { IngestManager.getInstance().addIngestJobEventListener(pcl); IngestManager.getInstance().addIngestModuleEventListener(pcl); -// Case.addPropertyChangeListener(pcl); - // populateHashMap(); FileTypesByMimeType.skCase = skCase; } + /** + * @return skCase - the sluethkit case + */ SleuthkitCase getSleuthkitCase() { return skCase; } @@ -156,13 +169,19 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { return v.visit(this); } + /** + * Class which represents the root node of the "By MIME Type" tree, will + * have children of each media type present in the database or no children + * when the file detection module has not been run and MIME type is + * currently unknown. + */ class FileTypesByMimeTypeNode extends DisplayableItemNode { @NbBundle.Messages("FileTypesByMimeType.name.text=By MIME Type") final String NAME = Bundle.FileTypesByMimeType_name_text(); FileTypesByMimeTypeNode(SleuthkitCase sleuthkitCase) { - super(Children.create(new FileTypesByMimeTypeNodeChildren(skCase), true)); + super(Children.create(new FileTypesByMimeTypeNodeChildren(), true)); setName(NAME); setDisplayName(NAME); this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file_types.png"); @@ -170,12 +189,7 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { @Override public boolean isLeafTypeNode() { -// if (!existingMimeTypes.isEmpty()) { return false; -// } -// else { -// return true; -// } } @Override @@ -190,27 +204,21 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { } + /** + * Creates the children for the "By MIME Type" node these children will each + * represent a distinct media type present in the DB + */ class FileTypesByMimeTypeNodeChildren extends ChildFactory implements Observer { - private SleuthkitCase skCase; - static final String EMPTY_MIME_TREE_STRING = "Data not available. Run file type identification module."; - - /** - * - * @param skCase (or null if one needs to be created) - */ - public FileTypesByMimeTypeNodeChildren(SleuthkitCase skCase) { + public FileTypesByMimeTypeNodeChildren() { super(); addObserver(this); - this.skCase = skCase; } @Override protected boolean createKeys(List mediaTypeNodes) { if (!existingMimeTypes.isEmpty()) { mediaTypeNodes.addAll(getMediaTypeList()); - } else { - mediaTypeNodes.add(EMPTY_MIME_TREE_STRING); } return true; } @@ -220,7 +228,7 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { if (!existingMimeTypes.isEmpty()) { return new MediaTypeNode(key); } else { - return new EmptyNode(EMPTY_MIME_TREE_STRING); + return null; } } @@ -232,35 +240,13 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { } - class EmptyNode extends DisplayableItemNode { - - EmptyNode(String name) { - super(Children.LEAF); - super.setName(name); - setName(name); - setDisplayName(name); - } - - @Override - public boolean isLeafTypeNode() { - return true; - } - - @Override - public T accept(DisplayableItemNodeVisitor v) { - return v.visit(this); - } - - @Override - public String getItemType() { - return getClass().getName(); - } - } - + /** + * The Media type node created by the FileTypesByMimeTypeNodeChildren and + * contains one of the unique media types present in the database for this + * case. + */ class MediaTypeNode extends DisplayableItemNode { - String mediaType; - MediaTypeNode(String name) { super(Children.create(new MediaTypeChildren(name), true)); setName(name); @@ -285,6 +271,11 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { } + /** + * Creates children fro media type nodes, children will be MediaSubTypeNodes + * and represent one of the subtypes which are present in the database of + * their media type. + */ class MediaTypeChildren extends ChildFactory implements Observer { String mediaType; @@ -313,6 +304,10 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { } + /** + * Node which represents the media sub type in the By MIME type tree, the + * media subtype is the portion of the MIME type following the /. + */ class MediaSubTypeNode extends DisplayableItemNode { private MediaSubTypeNode(String mimeType) { @@ -326,11 +321,24 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-filter-icon.png"); //NON-NLS } + /** + * Updates the display name of the mediaSubTypeNode to include the count + * of files which it represents. + * + * @param mimeType - the complete MimeType, needed for accurate query + * results + */ private void updateDisplayName(String mimeType) { - final long count = MediaSubTypeNodeChildren.calculateItems(skCase, mimeType); + final long count = MediaSubTypeNodeChildren.calculateItems(getSleuthkitCase(), mimeType); super.setDisplayName(mimeType.split("/")[1] + " (" + count + ")"); } + /** + * This returns true because any MediaSubTypeNode that exists is going + * to be a bottom level node in the Tree view on the left of Autopsy. + * + * @return true + */ @Override public boolean isLeafTypeNode() { return true; @@ -348,6 +356,11 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { } + /** + * Factory for populating the contents of the Media Sub Type Node with the + * files that match MimeType which is represented by this position in the + * tree. + */ private static class MediaSubTypeNodeChildren extends ChildFactory.Detachable { private final String mimeType; @@ -360,17 +373,27 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { /** * Get children count without actually loading all nodes * - * @return + * @return count(*) - the number of items that will be shown in this + * items Directory Listing */ - private static long calculateItems(SleuthkitCase sleuthkitCase, String mimeType) { + private static long calculateItems(SleuthkitCase sleuthkitCase, String mime_type) { try { - return sleuthkitCase.countFilesWhere(createQuery(mimeType)); + return sleuthkitCase.countFilesWhere(createQuery(mime_type)); } catch (TskCoreException ex) { LOGGER.log(Level.SEVERE, "Error getting file search view count", ex); //NON-NLS return 0; } } + /** + * Uses the createQuery method to complete the query, Select * from + * tsk_files WHERE. The results from the database will contain the files + * which match this mime type and their information. + * + * @param list - will contain all files and their attributes from the + * tsk_files table where mime_type matches the one specified + * @return true + */ @Override protected boolean createKeys(List list) { try { @@ -382,16 +405,33 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { return true; } - private static String createQuery(String mimeType) { + /** + * Create the portion of the query following WHERE for a query of the + * database for each file which matches the complete MIME type + * represented by this node. Matches against the mime_type column in + * tsk_files. + * + * @param mimeType - the complete mimetype of the file mediatype/subtype + * @return query.toString - portion of SQL query which will follow a + * WHERE clause. + */ + private static String createQuery(String mime_type) { StringBuilder query = new StringBuilder(); query.append("(dir_type = ").append(TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue()).append(")"); //NON-NLS if (UserPreferences.hideKnownFilesInViewsTree()) { query.append(" AND (known IS NULL OR known != ").append(TskData.FileKnown.KNOWN.getFileKnownValue()).append(")"); //NON-NLS } - query.append(" AND mime_type = '").append(mimeType).append("'"); + query.append(" AND mime_type = '").append(mime_type).append("'"); return query.toString(); } + /** + * Creates the content to populate the Directory Listing Table view for + * each file + * + * @param key + * @return + */ @Override protected Node createNodeForKey(Content key) { return key.accept(new ContentVisitor.Default() { @@ -426,5 +466,6 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { } }); } + } } From 0a15b431c0c4dd355ef72b9f95dd690cab029977 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Mon, 14 Nov 2016 13:43:22 -0500 Subject: [PATCH 05/10] 1917 minor comment fixes to denote some NON-NLS text --- .../org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java index 3ec3a41054..05a55f9bfb 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java @@ -118,7 +118,7 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { */ private void populateHashMap() { StringBuilder allDistinctMimeTypesQuery = new StringBuilder(); - allDistinctMimeTypesQuery.append("SELECT DISTINCT mime_type from tsk_files where mime_type NOT null"); + allDistinctMimeTypesQuery.append("SELECT DISTINCT mime_type from tsk_files where mime_type NOT null"); //NON-NLS allDistinctMimeTypesQuery.append(" AND dir_type = ").append(TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue()).append(";"); //NON-NLS synchronized (existingMimeTypes) { existingMimeTypes.clear(); @@ -421,7 +421,7 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { if (UserPreferences.hideKnownFilesInViewsTree()) { query.append(" AND (known IS NULL OR known != ").append(TskData.FileKnown.KNOWN.getFileKnownValue()).append(")"); //NON-NLS } - query.append(" AND mime_type = '").append(mime_type).append("'"); + query.append(" AND mime_type = '").append(mime_type).append("'"); //NON-NLS return query.toString(); } From 2bab13a1f2aa55554a3c9998bfc189d4a3ddeeee Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 15 Nov 2016 16:48:58 -0500 Subject: [PATCH 06/10] 1917 Null Case Implemented for MIME tree, and clean up --- .../autopsy/datamodel/FileTypesByExtNode.java | 14 ++-- .../datamodel/FileTypesByMimeType.java | 64 +++++++++++++++---- .../autopsy/datamodel/ViewsNode.java | 1 - .../DirectoryTreeTopComponent.java | 18 ++++-- 4 files changed, 74 insertions(+), 23 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByExtNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByExtNode.java index d9ce314ae7..5afb64fef8 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByExtNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByExtNode.java @@ -48,7 +48,7 @@ public class FileTypesByExtNode extends DisplayableItemNode { * something to provide a sub-node. */ FileTypesByExtNode(SleuthkitCase skCase, FileTypeExtensionFilters.RootFilter filter) { - super(Children.create(new FileTypesChildren(skCase, filter, null), true), Lookups.singleton(filter == null ? FNAME : filter.getName())); + super(Children.create(new FileTypesByExtChildren(skCase, filter, null), true), Lookups.singleton(filter == null ? FNAME : filter.getName())); this.filter = filter; init(); } @@ -61,7 +61,7 @@ public class FileTypesByExtNode extends DisplayableItemNode { * provides updates on events */ private FileTypesByExtNode(SleuthkitCase skCase, FileTypeExtensionFilters.RootFilter filter, Observable o) { - super(Children.create(new FileTypesChildren(skCase, filter, o), true), Lookups.singleton(filter == null ? FNAME : filter.getName())); + super(Children.create(new FileTypesByExtChildren(skCase, filter, o), true), Lookups.singleton(filter == null ? FNAME : filter.getName())); this.filter = filter; init(); } @@ -122,7 +122,7 @@ public class FileTypesByExtNode extends DisplayableItemNode { /** * */ - static class FileTypesChildren extends ChildFactory { + static class FileTypesByExtChildren extends ChildFactory { private SleuthkitCase skCase; private FileTypeExtensionFilters.RootFilter filter; @@ -135,12 +135,12 @@ public class FileTypesByExtNode extends DisplayableItemNode { * @param o Observable that provides updates based on events being * fired (or null if one needs to be created) */ - public FileTypesChildren(SleuthkitCase skCase, FileTypeExtensionFilters.RootFilter filter, Observable o) { + public FileTypesByExtChildren(SleuthkitCase skCase, FileTypeExtensionFilters.RootFilter filter, Observable o) { super(); this.skCase = skCase; this.filter = filter; if (o == null) { - this.notifier = new FileTypesChildrenObservable(); + this.notifier = new FileTypesByExtChildrenObservable(); } else { this.notifier = o; } @@ -150,9 +150,9 @@ public class FileTypesByExtNode extends DisplayableItemNode { * Listens for case and ingest invest. Updates observers when events are * fired. FileType and FileTypes nodes are all listening to this. */ - private final class FileTypesChildrenObservable extends Observable { + private final class FileTypesByExtChildrenObservable extends Observable { - FileTypesChildrenObservable() { + FileTypesByExtChildrenObservable() { IngestManager.getInstance().addIngestJobEventListener(pcl); IngestManager.getInstance().addIngestModuleEventListener(pcl); Case.addPropertyChangeListener(pcl); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java index 05a55f9bfb..892a34b653 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java @@ -57,9 +57,9 @@ import org.sleuthkit.datamodel.TskData; * Listener which is checking for changes in IngestJobEvent Completed or * Cancelled and IngestModuleEvent Content Changed. */ -class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { +public class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { - static SleuthkitCase skCase; + private static SleuthkitCase skCase; /** * The nodes of this tree will be determined dynamically by the mimetypes * which exist in the database. This hashmap will store them with the media @@ -175,15 +175,15 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { * when the file detection module has not been run and MIME type is * currently unknown. */ - class FileTypesByMimeTypeNode extends DisplayableItemNode { + public class FileTypesByMimeTypeNode extends DisplayableItemNode { @NbBundle.Messages("FileTypesByMimeType.name.text=By MIME Type") final String NAME = Bundle.FileTypesByMimeType_name_text(); FileTypesByMimeTypeNode(SleuthkitCase sleuthkitCase) { super(Children.create(new FileTypesByMimeTypeNodeChildren(), true)); - setName(NAME); - setDisplayName(NAME); + super.setName(NAME); + super.setDisplayName(NAME); this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file_types.png"); } @@ -202,6 +202,10 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { return getClass().getName(); } + public boolean isEmpty() { + return existingMimeTypes.isEmpty(); + } + } /** @@ -225,12 +229,7 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { @Override protected Node createNodeForKey(String key) { - if (!existingMimeTypes.isEmpty()) { - return new MediaTypeNode(key); - } else { - return null; - } - + return new MediaTypeNode(key); } @Override @@ -468,4 +467,47 @@ class FileTypesByMimeType extends Observable implements AutopsyVisitableItem { } } + + /** + * EmptyNode Class made for edge case where no mime exist in the database + * yet. Creates a node to display information on why the tree is empty. + * + * Swapped for the FileTypesByMimeType node in + * DirectoryTreeTopComponent.respondSelection + */ + static public class EmptyNode extends AbstractNode { + + public EmptyNode() { + super(Children.create(new EmptyChildFactory(), true)); + + } + + static class EmptyChildFactory extends ChildFactory { + + String FILE_ID_MSG = "Data not available. Run file type identification module."; //NON-NLS + + @Override + protected boolean createKeys(List list) { + list.add(FILE_ID_MSG); + return true; + } + + @Override + protected Node createNodeForKey(String key) { + return new MessageNode(key); + } + + } + + static class MessageNode extends AbstractNode { + + MessageNode(String name) { + super(Children.LEAF); + super.setName(name); + setName(name); + setDisplayName(name); + } + } + } + } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ViewsNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/ViewsNode.java index 7e73f37bec..a2c09299d1 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ViewsNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/ViewsNode.java @@ -36,7 +36,6 @@ public class ViewsNode extends DisplayableItemNode { public ViewsNode(SleuthkitCase sleuthkitCase) { super(new RootContentChildren(Arrays.asList( - // new FileTypeExtensionFilters(sleuthkitCase), new FileTypes(sleuthkitCase), // June '15: Recent Files was removed because it was not useful w/out filtering // add it back in if we can filter the results to a more managable size. diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java index 8f63752a27..c0c5ac3cd4 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java @@ -61,7 +61,9 @@ import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode; import org.sleuthkit.autopsy.datamodel.DataSources; import org.sleuthkit.autopsy.datamodel.DataSourcesNode; import org.sleuthkit.autopsy.datamodel.DisplayableItemNode; +import org.sleuthkit.autopsy.datamodel.FileTypesByMimeType.EmptyNode; import org.sleuthkit.autopsy.datamodel.ExtractedContent; +import org.sleuthkit.autopsy.datamodel.FileTypesByMimeType; import org.sleuthkit.autopsy.datamodel.KeywordHits; import org.sleuthkit.autopsy.datamodel.KnownFileFilterNode; import org.sleuthkit.autopsy.datamodel.Reports; @@ -361,7 +363,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat items.add(new Tags()); items.add(new Reports()); contentChildren = new RootContentChildren(items); - + Node root = new AbstractNode(contentChildren) { /** * to override the right click action in the white blank @@ -632,6 +634,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat if (origin == null) { return; } + Node originNode = origin.getNode(); //set node, wrap in filter node first to filter out children @@ -639,7 +642,15 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat Node kffn = new KnownFileFilterNode(drfn, KnownFileFilterNode.getSelectionContext(originNode)); // Create a TableFilterNode with knowledge of the node's type to allow for column order settings - if (originNode instanceof DisplayableItemNode) { + //Special case for when File Type Identification has not yet been run and + //there are no mime types to populate Files by Mime Type Tree + if (originNode instanceof FileTypesByMimeType.FileTypesByMimeTypeNode + && ((FileTypesByMimeType.FileTypesByMimeTypeNode) originNode).isEmpty()) { + EmptyNode emptyNode = new EmptyNode(); + Node emptyDrfn = new DataResultFilterNode(emptyNode, DirectoryTreeTopComponent.this.em); + Node emptyKffn = new KnownFileFilterNode(emptyDrfn, KnownFileFilterNode.getSelectionContext(emptyNode)); + dataResult.setNode(new TableFilterNode(emptyKffn, true, "This Node Is Empty")); + } else if (originNode instanceof DisplayableItemNode) { dataResult.setNode(new TableFilterNode(kffn, true, ((DisplayableItemNode) originNode).getItemType())); } else { dataResult.setNode(new TableFilterNode(kffn, true)); @@ -783,8 +794,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat * Set the selected node using a path to a previously selected node. * * @param previouslySelectedNodePath Path to a previously selected node. - * @param rootNodeName Name of the root node to match, may be - * null. + * @param rootNodeName Name of the root node to match, may be null. */ private void setSelectedNode(final String[] previouslySelectedNodePath, final String rootNodeName) { if (previouslySelectedNodePath == null) { From 8f0b9c057c970adcda350ffde1df89fb289cd9bf Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 23 Nov 2016 11:04:41 -0500 Subject: [PATCH 07/10] 1917-fixed re-opening project, and queries only returning files --- .../datamodel/DisplayableItemNodeVisitor.java | 9 ++++- .../datamodel/FileTypesByMimeType.java | 33 +++++++++++++++++-- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java index 2ec8b205bb..f7fdb96243 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java @@ -152,6 +152,8 @@ public interface DisplayableItemNodeVisitor { T visit(FileTypesByMimeType.MediaSubTypeNode ftByMimeTypeMediaSubType); + T visit(FileTypesByMimeType.EmptyNode.MessageNode aThis); + /** * Visitor with an implementable default behavior for all types. Override @@ -229,7 +231,12 @@ public interface DisplayableItemNodeVisitor { public T visit(FileTypesByMimeType.MediaSubTypeNode ftByMimeTypeMediaTypeNode) { return defaultVisit(ftByMimeTypeMediaTypeNode); } - + + @Override + public T visit(FileTypesByMimeType.EmptyNode.MessageNode ftByMimeTypeEmptyNode) { + return defaultVisit(ftByMimeTypeEmptyNode); + } + @Override public T visit(DeletedContentNode dcn) { return defaultVisit(dcn); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java index 892a34b653..444444b64a 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java @@ -119,7 +119,11 @@ public class FileTypesByMimeType extends Observable implements AutopsyVisitableI private void populateHashMap() { StringBuilder allDistinctMimeTypesQuery = new StringBuilder(); allDistinctMimeTypesQuery.append("SELECT DISTINCT mime_type from tsk_files where mime_type NOT null"); //NON-NLS - allDistinctMimeTypesQuery.append(" AND dir_type = ").append(TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue()).append(";"); //NON-NLS + allDistinctMimeTypesQuery.append(" AND dir_type = ").append(TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue()); //NON-NLS + allDistinctMimeTypesQuery.append(" AND (type IN (").append(TskData.TSK_DB_FILES_TYPE_ENUM.FS.ordinal()).append(","); //NON-NLS + allDistinctMimeTypesQuery.append(TskData.TSK_DB_FILES_TYPE_ENUM.CARVED.ordinal()).append(","); + allDistinctMimeTypesQuery.append(TskData.TSK_DB_FILES_TYPE_ENUM.DERIVED.ordinal()).append(","); + allDistinctMimeTypesQuery.append(TskData.TSK_DB_FILES_TYPE_ENUM.LOCAL.ordinal()).append("))"); synchronized (existingMimeTypes) { existingMimeTypes.clear(); } @@ -155,6 +159,7 @@ public class FileTypesByMimeType extends Observable implements AutopsyVisitableI IngestManager.getInstance().addIngestJobEventListener(pcl); IngestManager.getInstance().addIngestModuleEventListener(pcl); FileTypesByMimeType.skCase = skCase; + populateHashMap(); } /** @@ -417,6 +422,10 @@ public class FileTypesByMimeType extends Observable implements AutopsyVisitableI private static String createQuery(String mime_type) { StringBuilder query = new StringBuilder(); query.append("(dir_type = ").append(TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue()).append(")"); //NON-NLS + query.append(" AND (type IN (").append(TskData.TSK_DB_FILES_TYPE_ENUM.FS.ordinal()).append(","); //NON-NLS + query.append(TskData.TSK_DB_FILES_TYPE_ENUM.CARVED.ordinal()).append(","); + query.append(TskData.TSK_DB_FILES_TYPE_ENUM.DERIVED.ordinal()).append(","); + query.append(TskData.TSK_DB_FILES_TYPE_ENUM.LOCAL.ordinal()).append("))"); if (UserPreferences.hideKnownFilesInViewsTree()) { query.append(" AND (known IS NULL OR known != ").append(TskData.FileKnown.KNOWN.getFileKnownValue()).append(")"); //NON-NLS } @@ -499,7 +508,12 @@ public class FileTypesByMimeType extends Observable implements AutopsyVisitableI } - static class MessageNode extends AbstractNode { + /** + * MessageNode is is the info message that displays in the table view, + * by also extending a DisplayableItemNode type, rather than an + * AbstractNode type it doesn't throw an error when right clicked. + */ + static class MessageNode extends DisplayableItemNode { MessageNode(String name) { super(Children.LEAF); @@ -507,6 +521,21 @@ public class FileTypesByMimeType extends Observable implements AutopsyVisitableI setName(name); setDisplayName(name); } + + @Override + public boolean isLeafTypeNode() { + return true; + } + + @Override + public T accept(DisplayableItemNodeVisitor v) { + return v.visit(this); + } + + @Override + public String getItemType() { + return getClass().getName(); + } } } From ef94fd80a8584478c60fc361df4efd756bcccfd8 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 30 Nov 2016 10:29:40 -0500 Subject: [PATCH 08/10] 1917-fixed issue where mime nodes were not updating --- .../datamodel/FileTypesByMimeType.java | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java index 444444b64a..2d6393b000 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java @@ -312,10 +312,11 @@ public class FileTypesByMimeType extends Observable implements AutopsyVisitableI * Node which represents the media sub type in the By MIME type tree, the * media subtype is the portion of the MIME type following the /. */ - class MediaSubTypeNode extends DisplayableItemNode { + class MediaSubTypeNode extends DisplayableItemNode implements Observer { private MediaSubTypeNode(String mimeType) { super(Children.create(new MediaSubTypeNodeChildren(mimeType), true)); + addObserver(this); init(mimeType); } @@ -333,7 +334,9 @@ public class FileTypesByMimeType extends Observable implements AutopsyVisitableI * results */ private void updateDisplayName(String mimeType) { - final long count = MediaSubTypeNodeChildren.calculateItems(getSleuthkitCase(), mimeType); + + final long count = new MediaSubTypeNodeChildren(mimeType).calculateItems(getSleuthkitCase(), mimeType); + super.setDisplayName(mimeType.split("/")[1] + " (" + count + ")"); } @@ -358,6 +361,10 @@ public class FileTypesByMimeType extends Observable implements AutopsyVisitableI return getClass().getName(); } + @Override + public void update(Observable o, Object arg) { + updateDisplayName(getName()); + } } /** @@ -365,12 +372,13 @@ public class FileTypesByMimeType extends Observable implements AutopsyVisitableI * files that match MimeType which is represented by this position in the * tree. */ - private static class MediaSubTypeNodeChildren extends ChildFactory.Detachable { + private class MediaSubTypeNodeChildren extends ChildFactory.Detachable implements Observer { private final String mimeType; MediaSubTypeNodeChildren(String mimeType) { super(); + addObserver(this); this.mimeType = mimeType; } @@ -380,7 +388,7 @@ public class FileTypesByMimeType extends Observable implements AutopsyVisitableI * @return count(*) - the number of items that will be shown in this * items Directory Listing */ - private static long calculateItems(SleuthkitCase sleuthkitCase, String mime_type) { + private long calculateItems(SleuthkitCase sleuthkitCase, String mime_type) { try { return sleuthkitCase.countFilesWhere(createQuery(mime_type)); } catch (TskCoreException ex) { @@ -419,7 +427,7 @@ public class FileTypesByMimeType extends Observable implements AutopsyVisitableI * @return query.toString - portion of SQL query which will follow a * WHERE clause. */ - private static String createQuery(String mime_type) { + private String createQuery(String mime_type) { StringBuilder query = new StringBuilder(); query.append("(dir_type = ").append(TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue()).append(")"); //NON-NLS query.append(" AND (type IN (").append(TskData.TSK_DB_FILES_TYPE_ENUM.FS.ordinal()).append(","); //NON-NLS @@ -432,7 +440,13 @@ public class FileTypesByMimeType extends Observable implements AutopsyVisitableI query.append(" AND mime_type = '").append(mime_type).append("'"); //NON-NLS return query.toString(); } + + @Override + public void update(Observable o, Object arg) { + refresh(true); + } + /** * Creates the content to populate the Directory Listing Table view for * each file @@ -474,7 +488,6 @@ public class FileTypesByMimeType extends Observable implements AutopsyVisitableI } }); } - } /** From dc06e7727b1abfb9d85ad93d7d822a85cb526f6f Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Thu, 1 Dec 2016 12:21:57 -0500 Subject: [PATCH 09/10] 1917 Fixing broken multi-user query, by adding IS --- .../org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java index 2d6393b000..f0fcb90901 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByMimeType.java @@ -118,7 +118,7 @@ public class FileTypesByMimeType extends Observable implements AutopsyVisitableI */ private void populateHashMap() { StringBuilder allDistinctMimeTypesQuery = new StringBuilder(); - allDistinctMimeTypesQuery.append("SELECT DISTINCT mime_type from tsk_files where mime_type NOT null"); //NON-NLS + allDistinctMimeTypesQuery.append("SELECT DISTINCT mime_type from tsk_files where mime_type IS NOT null"); //NON-NLS allDistinctMimeTypesQuery.append(" AND dir_type = ").append(TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue()); //NON-NLS allDistinctMimeTypesQuery.append(" AND (type IN (").append(TskData.TSK_DB_FILES_TYPE_ENUM.FS.ordinal()).append(","); //NON-NLS allDistinctMimeTypesQuery.append(TskData.TSK_DB_FILES_TYPE_ENUM.CARVED.ordinal()).append(","); From 57e506b8ae76c6d57b2999b4cc4a2a09c640ac27 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Fri, 2 Dec 2016 12:30:06 -0500 Subject: [PATCH 10/10] Delete KWS issue report file, move into JIRA --- .../src/org/sleuthkit/autopsy/keywordsearch/notes.txt | 5 ----- 1 file changed, 5 deletions(-) delete mode 100755 KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/notes.txt diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/notes.txt b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/notes.txt deleted file mode 100755 index 1c771a55cd..0000000000 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/notes.txt +++ /dev/null @@ -1,5 +0,0 @@ -- Tika has a bug in the true type font parser included in fontbox. It should - be fixed in the next release of Tika (1.5, or a 1.4 point release). Until then - we bypass Tika when it detects a type of "application/x-font-ttf". See - AbstractFileTikaTextExtract::isSupported. This should be removed when we - update Tika. \ No newline at end of file