mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-17 18:17:43 +00:00
2800 resolve merge conflict with node clean up story
This commit is contained in:
commit
441c0297d1
@ -51,8 +51,10 @@ abstract class AbstractContentChildren<T> extends Keys<T> {
|
|||||||
* Uses lazy Content.Keys
|
* Uses lazy Content.Keys
|
||||||
*/
|
*/
|
||||||
AbstractContentChildren() {
|
AbstractContentChildren() {
|
||||||
/*This was turned off because we were getting out of memory errors when the
|
/*
|
||||||
filter nodes were hiding nodes. Turning this off seemed to help */
|
* This was turned off because we were getting out of memory errors when
|
||||||
|
* the filter nodes were hiding nodes. Turning this off seemed to help
|
||||||
|
*/
|
||||||
super(false); //don't use lazy behavior
|
super(false); //don't use lazy behavior
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,7 +140,7 @@ abstract class AbstractContentChildren<T> extends Keys<T> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AbstractNode visit(FileTypesByExtension sf) {
|
public AbstractNode visit(FileTypesByExtension sf) {
|
||||||
return new org.sleuthkit.autopsy.datamodel.FileTypesByExtension.FileTypesByExtNode(sf.getSleuthkitCase(), null);
|
return sf.new FileTypesByExtNode(sf.getSleuthkitCase(), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -198,7 +200,7 @@ abstract class AbstractContentChildren<T> extends Keys<T> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AbstractNode visit(FileTypes ft) {
|
public AbstractNode visit(FileTypes ft) {
|
||||||
return new FileTypesNode(ft.getSleuthkitCase());
|
return ft.new FileTypesNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -19,10 +19,18 @@
|
|||||||
package org.sleuthkit.autopsy.datamodel;
|
package org.sleuthkit.autopsy.datamodel;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Observable;
|
||||||
|
import java.util.Observer;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import javax.swing.SwingWorker;
|
||||||
import org.openide.nodes.AbstractNode;
|
import org.openide.nodes.AbstractNode;
|
||||||
|
import org.openide.nodes.Children;
|
||||||
import org.openide.nodes.Sheet;
|
import org.openide.nodes.Sheet;
|
||||||
|
import org.openide.util.Lookup;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.openide.util.lookup.Lookups;
|
import org.openide.util.lookup.Lookups;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.datamodel.Content;
|
import org.sleuthkit.datamodel.Content;
|
||||||
import org.sleuthkit.datamodel.ContentVisitor;
|
import org.sleuthkit.datamodel.ContentVisitor;
|
||||||
import org.sleuthkit.datamodel.DerivedFile;
|
import org.sleuthkit.datamodel.DerivedFile;
|
||||||
@ -32,13 +40,17 @@ import org.sleuthkit.datamodel.LayoutFile;
|
|||||||
import org.sleuthkit.datamodel.LocalFile;
|
import org.sleuthkit.datamodel.LocalFile;
|
||||||
import org.sleuthkit.datamodel.SlackFile;
|
import org.sleuthkit.datamodel.SlackFile;
|
||||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||||
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* File Types node support
|
* File Types node support
|
||||||
*/
|
*/
|
||||||
public final class FileTypes implements AutopsyVisitableItem {
|
public final class FileTypes implements AutopsyVisitableItem {
|
||||||
|
|
||||||
|
private final static Logger logger = Logger.getLogger(FileTypes.class.getName());
|
||||||
|
|
||||||
private final SleuthkitCase skCase;
|
private final SleuthkitCase skCase;
|
||||||
|
private boolean showCounts = true;
|
||||||
|
|
||||||
FileTypes(SleuthkitCase skCase) {
|
FileTypes(SleuthkitCase skCase) {
|
||||||
this.skCase = skCase;
|
this.skCase = skCase;
|
||||||
@ -53,22 +65,41 @@ public final class FileTypes implements AutopsyVisitableItem {
|
|||||||
return skCase;
|
return skCase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should the nodes show counts?
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @return True, unless the DB has more than 200k rows.
|
||||||
|
*/
|
||||||
|
boolean shouldShowCounts() {
|
||||||
|
if (showCounts) {
|
||||||
|
try {
|
||||||
|
if (skCase.countFilesWhere("1=1") > 200000) { //NON-NLS
|
||||||
|
showCounts = false;
|
||||||
|
}
|
||||||
|
} catch (TskCoreException tskCoreException) {
|
||||||
|
showCounts = false;
|
||||||
|
logger.log(Level.SEVERE, "Error counting files.", tskCoreException); //NON-NLS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return showCounts;
|
||||||
|
}
|
||||||
|
@NbBundle.Messages("FileTypes.name.text=File Types")
|
||||||
|
static private final String NAME = Bundle.FileTypes_name_text();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Node which will contain By Mime Type and By Extension nodes.
|
* Node which will contain By Mime Type and By Extension nodes.
|
||||||
*/
|
*/
|
||||||
public static final class FileTypesNode extends DisplayableItemNode {
|
public final class FileTypesNode extends DisplayableItemNode {
|
||||||
|
|
||||||
@NbBundle.Messages("FileTypes.name.text=File Types")
|
FileTypesNode() {
|
||||||
private static final String NAME = Bundle.FileTypes_name_text();
|
|
||||||
|
|
||||||
FileTypesNode(SleuthkitCase sleuthkitCase) {
|
|
||||||
super(new RootContentChildren(Arrays.asList(
|
super(new RootContentChildren(Arrays.asList(
|
||||||
new FileTypesByExtension(sleuthkitCase),
|
new FileTypesByExtension(FileTypes.this),
|
||||||
new FileTypesByMimeType(sleuthkitCase)
|
new FileTypesByMimeType(FileTypes.this))),
|
||||||
)), Lookups.singleton(NAME));
|
Lookups.singleton(NAME));
|
||||||
setName(NAME);
|
setName(NAME);
|
||||||
setDisplayName(NAME);
|
setDisplayName(NAME);
|
||||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file_types.png");
|
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file_types.png"); //NON-NLS
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -149,4 +180,67 @@ public final class FileTypes implements AutopsyVisitableItem {
|
|||||||
throw new UnsupportedOperationException(NbBundle.getMessage(this.getClass(), "FileTypeChildren.exception.notSupported.msg", di.toString()));
|
throw new UnsupportedOperationException(NbBundle.getMessage(this.getClass(), "FileTypeChildren.exception.notSupported.msg", di.toString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static abstract class BGCountUpdatingNode extends DisplayableItemNode implements Observer {
|
||||||
|
|
||||||
|
private long childCount = -1;
|
||||||
|
private FileTypes typesRoot;
|
||||||
|
|
||||||
|
BGCountUpdatingNode(FileTypes typesRoot, Children children) {
|
||||||
|
this(typesRoot, children, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
BGCountUpdatingNode(FileTypes typesRoot, Children children, Lookup lookup) {
|
||||||
|
super(children, lookup);
|
||||||
|
this.typesRoot = typesRoot;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(Observable o, Object arg) {
|
||||||
|
updateDisplayName();
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract String getDisplayNameBase();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the number of children of this node, possibly by querying
|
||||||
|
* the DB.
|
||||||
|
*
|
||||||
|
* @return @throws TskCoreException if there was an error querying the
|
||||||
|
* DB to calculate the number of children.
|
||||||
|
*/
|
||||||
|
abstract long calculateChildCount() throws TskCoreException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the display name of the mediaSubTypeNode to include the count
|
||||||
|
* of files which it represents.
|
||||||
|
*/
|
||||||
|
@NbBundle.Messages("FileTypes.bgCounting.placeholder=(counting...)")
|
||||||
|
void updateDisplayName() {
|
||||||
|
if (typesRoot.shouldShowCounts()) {
|
||||||
|
//only show "(counting...)" the first time, otherwise it is distracting.
|
||||||
|
setDisplayName(getDisplayNameBase() + ((childCount < 0) ? Bundle.FileTypes_bgCounting_placeholder()
|
||||||
|
: ("(" + childCount + ")"))); //NON-NLS
|
||||||
|
new SwingWorker<Long, Void>() {
|
||||||
|
@Override
|
||||||
|
protected Long doInBackground() throws Exception {
|
||||||
|
return calculateChildCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void done() {
|
||||||
|
try {
|
||||||
|
childCount = get();
|
||||||
|
setDisplayName(getDisplayNameBase() + " (" + childCount + ")"); //NON-NLS
|
||||||
|
} catch (InterruptedException | ExecutionException ex) {
|
||||||
|
setDisplayName(getDisplayNameBase());
|
||||||
|
logger.log(Level.WARNING, "Failed to get count of files for " + getDisplayNameBase(), ex); //NON-NLS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.execute();
|
||||||
|
} else {
|
||||||
|
setDisplayName(getDisplayNameBase() + ((childCount < 0) ? "" : ("(" + childCount + "+)"))); //NON-NLS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,6 @@ import org.sleuthkit.autopsy.casemodule.Case;
|
|||||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
|
||||||
import org.sleuthkit.datamodel.Content;
|
import org.sleuthkit.datamodel.Content;
|
||||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
@ -46,11 +45,13 @@ import org.sleuthkit.datamodel.TskData;
|
|||||||
*/
|
*/
|
||||||
public final class FileTypesByExtension implements AutopsyVisitableItem {
|
public final class FileTypesByExtension implements AutopsyVisitableItem {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(FileTypesByExtension.class.getName());
|
private final static Logger logger = Logger.getLogger(FileTypesByExtension.class.getName());
|
||||||
private final SleuthkitCase skCase;
|
private final SleuthkitCase skCase;
|
||||||
|
private final FileTypes typesRoot;
|
||||||
|
|
||||||
public FileTypesByExtension(SleuthkitCase skCase) {
|
public FileTypesByExtension(FileTypes typesRoot) {
|
||||||
this.skCase = skCase;
|
this.skCase = typesRoot.getSleuthkitCase();
|
||||||
|
this.typesRoot = typesRoot;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SleuthkitCase getSleuthkitCase() {
|
public SleuthkitCase getSleuthkitCase() {
|
||||||
@ -66,16 +67,18 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
|
|||||||
* Listens for case and ingest invest. Updates observers when events are
|
* Listens for case and ingest invest. Updates observers when events are
|
||||||
* fired. FileType and FileTypes nodes are all listening to this.
|
* fired. FileType and FileTypes nodes are all listening to this.
|
||||||
*/
|
*/
|
||||||
static private class FileTypesByExtObservable extends Observable {
|
private class FileTypesByExtObservable extends Observable {
|
||||||
|
|
||||||
private boolean showCounts = true;
|
|
||||||
private final PropertyChangeListener pcl;
|
private final PropertyChangeListener pcl;
|
||||||
|
|
||||||
private FileTypesByExtObservable(SleuthkitCase skCase) {
|
private FileTypesByExtObservable() {
|
||||||
super();
|
super();
|
||||||
this.pcl = (PropertyChangeEvent evt) -> {
|
this.pcl = (PropertyChangeEvent evt) -> {
|
||||||
String eventType = evt.getPropertyName();
|
String eventType = evt.getPropertyName();
|
||||||
if (eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString()) || eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString()) || eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) {
|
if (eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())
|
||||||
|
|| eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|
||||||
|
|| eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())
|
||||||
|
|| eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) {
|
||||||
/**
|
/**
|
||||||
* Checking for a current case is a stop gap measure until a
|
* Checking for a current case is a stop gap measure until a
|
||||||
* different way of handling the closing of cases is worked
|
* different way of handling the closing of cases is worked
|
||||||
@ -84,7 +87,7 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
|
|||||||
*/
|
*/
|
||||||
try {
|
try {
|
||||||
Case.getCurrentCase();
|
Case.getCurrentCase();
|
||||||
shouldShowCounts(skCase);
|
typesRoot.shouldShowCounts();
|
||||||
update();
|
update();
|
||||||
} catch (IllegalStateException notUsed) {
|
} catch (IllegalStateException notUsed) {
|
||||||
/**
|
/**
|
||||||
@ -105,26 +108,6 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Should the nodes show counts?
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @return True, unless the DB has more than 200k rows.
|
|
||||||
*/
|
|
||||||
private boolean shouldShowCounts(SleuthkitCase skCase) {
|
|
||||||
if (showCounts) {
|
|
||||||
try {
|
|
||||||
if (skCase.countFilesWhere("1=1") > 200000) {
|
|
||||||
showCounts = false;
|
|
||||||
}
|
|
||||||
} catch (TskCoreException tskCoreException) {
|
|
||||||
showCounts = false;
|
|
||||||
logger.log(Level.SEVERE, "Error counting files.", tskCoreException);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return showCounts;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void removeListeners() {
|
private void removeListeners() {
|
||||||
deleteObservers();
|
deleteObservers();
|
||||||
IngestManager.getInstance().removeIngestJobEventListener(pcl);
|
IngestManager.getInstance().removeIngestJobEventListener(pcl);
|
||||||
@ -137,13 +120,13 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
|
|||||||
notifyObservers();
|
notifyObservers();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private static final String FNAME = NbBundle.getMessage(FileTypesByExtNode.class, "FileTypesByExtNode.fname.text");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Node for root of file types view. Children are nodes for specific types.
|
* Node for root of file types view. Children are nodes for specific types.
|
||||||
*/
|
*/
|
||||||
static class FileTypesByExtNode extends DisplayableItemNode {
|
class FileTypesByExtNode extends DisplayableItemNode {
|
||||||
|
|
||||||
private static final String FNAME = NbBundle.getMessage(FileTypesByExtNode.class, "FileTypesByExtNode.fname.text");
|
|
||||||
private final FileTypesByExtension.RootFilter filter;
|
private final FileTypesByExtension.RootFilter filter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -153,9 +136,7 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
|
|||||||
* something to provide a sub-node.
|
* something to provide a sub-node.
|
||||||
*/
|
*/
|
||||||
FileTypesByExtNode(SleuthkitCase skCase, FileTypesByExtension.RootFilter filter) {
|
FileTypesByExtNode(SleuthkitCase skCase, FileTypesByExtension.RootFilter filter) {
|
||||||
super(Children.create(new FileTypesByExtNodeChildren(skCase, filter, null), true), Lookups.singleton(filter == null ? FNAME : filter.getDisplayName()));
|
this(skCase, filter, null);
|
||||||
this.filter = filter;
|
|
||||||
init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -166,12 +147,11 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
|
|||||||
* provides updates on events
|
* provides updates on events
|
||||||
*/
|
*/
|
||||||
private FileTypesByExtNode(SleuthkitCase skCase, FileTypesByExtension.RootFilter filter, FileTypesByExtObservable o) {
|
private FileTypesByExtNode(SleuthkitCase skCase, FileTypesByExtension.RootFilter filter, FileTypesByExtObservable o) {
|
||||||
super(Children.create(new FileTypesByExtNodeChildren(skCase, filter, o), true), Lookups.singleton(filter == null ? FNAME : filter.getDisplayName()));
|
|
||||||
this.filter = filter;
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void init() {
|
super(Children.create(new FileTypesByExtNodeChildren(skCase, filter, o), true),
|
||||||
|
Lookups.singleton(filter == null ? FNAME : filter.getDisplayName()));
|
||||||
|
this.filter = filter;
|
||||||
|
|
||||||
// root node of tree
|
// root node of tree
|
||||||
if (filter == null) {
|
if (filter == null) {
|
||||||
super.setName(FNAME);
|
super.setName(FNAME);
|
||||||
@ -230,68 +210,66 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
|
|||||||
return getClass().getName();
|
return getClass().getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class FileTypesByExtNodeChildren extends ChildFactory<FileTypesByExtension.SearchFilterInterface> {
|
}
|
||||||
|
|
||||||
private final SleuthkitCase skCase;
|
private class FileTypesByExtNodeChildren extends ChildFactory<FileTypesByExtension.SearchFilterInterface> {
|
||||||
private final FileTypesByExtension.RootFilter filter;
|
|
||||||
private final FileTypesByExtObservable notifier;
|
|
||||||
|
|
||||||
/**
|
private final SleuthkitCase skCase;
|
||||||
*
|
private final FileTypesByExtension.RootFilter filter;
|
||||||
* @param skCase
|
private final FileTypesByExtObservable notifier;
|
||||||
* @param filter Is null for root node
|
|
||||||
* @param o Observable that provides updates based on events
|
|
||||||
* being fired (or null if one needs to be created)
|
|
||||||
*/
|
|
||||||
private FileTypesByExtNodeChildren(SleuthkitCase skCase, FileTypesByExtension.RootFilter filter, FileTypesByExtObservable o) {
|
|
||||||
super();
|
|
||||||
this.skCase = skCase;
|
|
||||||
this.filter = filter;
|
|
||||||
if (o == null) {
|
|
||||||
this.notifier = new FileTypesByExtObservable(skCase);
|
|
||||||
} else {
|
|
||||||
this.notifier = o;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
protected boolean createKeys(List<FileTypesByExtension.SearchFilterInterface> list) {
|
*
|
||||||
// root node
|
* @param skCase
|
||||||
if (filter == null) {
|
* @param filter Is null for root node
|
||||||
list.addAll(Arrays.asList(FileTypesByExtension.RootFilter.values()));
|
* @param o Observable that provides updates based on events being
|
||||||
} // document and executable has another level of nodes
|
* fired (or null if one needs to be created)
|
||||||
else if (filter.equals(FileTypesByExtension.RootFilter.TSK_DOCUMENT_FILTER)) {
|
*/
|
||||||
list.addAll(Arrays.asList(FileTypesByExtension.DocumentFilter.values()));
|
private FileTypesByExtNodeChildren(SleuthkitCase skCase, FileTypesByExtension.RootFilter filter, FileTypesByExtObservable o) {
|
||||||
} else if (filter.equals(FileTypesByExtension.RootFilter.TSK_EXECUTABLE_FILTER)) {
|
super();
|
||||||
list.addAll(Arrays.asList(FileTypesByExtension.ExecutableFilter.values()));
|
this.skCase = skCase;
|
||||||
}
|
this.filter = filter;
|
||||||
return true;
|
if (o == null) {
|
||||||
}
|
this.notifier = new FileTypesByExtObservable();
|
||||||
|
} else {
|
||||||
@Override
|
this.notifier = o;
|
||||||
protected Node createNodeForKey(FileTypesByExtension.SearchFilterInterface key) {
|
|
||||||
// make new nodes for the sub-nodes
|
|
||||||
if (key.getName().equals(FileTypesByExtension.RootFilter.TSK_DOCUMENT_FILTER.getName())) {
|
|
||||||
return new FileTypesByExtNode(skCase, FileTypesByExtension.RootFilter.TSK_DOCUMENT_FILTER, notifier);
|
|
||||||
} else if (key.getName().equals(FileTypesByExtension.RootFilter.TSK_EXECUTABLE_FILTER.getName())) {
|
|
||||||
return new FileTypesByExtNode(skCase, FileTypesByExtension.RootFilter.TSK_EXECUTABLE_FILTER, notifier);
|
|
||||||
} else {
|
|
||||||
return new FileExtensionNode(key, skCase, notifier);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean createKeys(List<FileTypesByExtension.SearchFilterInterface> list) {
|
||||||
|
// root node
|
||||||
|
if (filter == null) {
|
||||||
|
list.addAll(Arrays.asList(FileTypesByExtension.RootFilter.values()));
|
||||||
|
} // document and executable has another level of nodes
|
||||||
|
else if (filter.equals(FileTypesByExtension.RootFilter.TSK_DOCUMENT_FILTER)) {
|
||||||
|
list.addAll(Arrays.asList(FileTypesByExtension.DocumentFilter.values()));
|
||||||
|
} else if (filter.equals(FileTypesByExtension.RootFilter.TSK_EXECUTABLE_FILTER)) {
|
||||||
|
list.addAll(Arrays.asList(FileTypesByExtension.ExecutableFilter.values()));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Node createNodeForKey(FileTypesByExtension.SearchFilterInterface key) {
|
||||||
|
// make new nodes for the sub-nodes
|
||||||
|
if (key.getName().equals(FileTypesByExtension.RootFilter.TSK_DOCUMENT_FILTER.getName())) {
|
||||||
|
return new FileTypesByExtNode(skCase, FileTypesByExtension.RootFilter.TSK_DOCUMENT_FILTER, notifier);
|
||||||
|
} else if (key.getName().equals(FileTypesByExtension.RootFilter.TSK_EXECUTABLE_FILTER.getName())) {
|
||||||
|
return new FileTypesByExtNode(skCase, FileTypesByExtension.RootFilter.TSK_EXECUTABLE_FILTER, notifier);
|
||||||
|
} else {
|
||||||
|
return new FileExtensionNode(key, skCase, notifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Node for a specific file type / extension. Children of it will be the
|
* Node for a specific file type / extension. Children of it will be the
|
||||||
* files of that type.
|
* files of that type.
|
||||||
*/
|
*/
|
||||||
static class FileExtensionNode extends DisplayableItemNode {
|
class FileExtensionNode extends FileTypes.BGCountUpdatingNode {
|
||||||
|
|
||||||
FileTypesByExtension.SearchFilterInterface filter;
|
private final FileTypesByExtension.SearchFilterInterface filter;
|
||||||
SleuthkitCase skCase;
|
|
||||||
private final FileTypesByExtObservable notifier;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -301,34 +279,14 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
|
|||||||
* should refresh
|
* should refresh
|
||||||
*/
|
*/
|
||||||
FileExtensionNode(FileTypesByExtension.SearchFilterInterface filter, SleuthkitCase skCase, FileTypesByExtObservable o) {
|
FileExtensionNode(FileTypesByExtension.SearchFilterInterface filter, SleuthkitCase skCase, FileTypesByExtObservable o) {
|
||||||
super(Children.create(new FileExtensionNodeChildren(filter, skCase, o), true), Lookups.singleton(filter.getDisplayName()));
|
super(typesRoot, Children.create(new FileExtensionNodeChildren(filter, skCase, o), true),
|
||||||
|
Lookups.singleton(filter.getDisplayName()));
|
||||||
this.filter = filter;
|
this.filter = filter;
|
||||||
this.skCase = skCase;
|
|
||||||
this.notifier = o;
|
|
||||||
init();
|
|
||||||
o.addObserver(new ByExtNodeObserver());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void init() {
|
|
||||||
super.setName(filter.getDisplayName());
|
super.setName(filter.getDisplayName());
|
||||||
updateDisplayName();
|
updateDisplayName();
|
||||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-filter-icon.png"); //NON-NLS
|
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-filter-icon.png"); //NON-NLS
|
||||||
}
|
|
||||||
|
|
||||||
// update the display name when new events are fired
|
o.addObserver(this);
|
||||||
private class ByExtNodeObserver implements Observer {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void update(Observable o, Object arg) {
|
|
||||||
updateDisplayName();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateDisplayName() {
|
|
||||||
final String count = notifier.shouldShowCounts(skCase)
|
|
||||||
? " (" + Long.toString(FileExtensionNodeChildren.calculateItems(skCase, filter)) + ")"
|
|
||||||
: "";
|
|
||||||
super.setDisplayName(filter.getDisplayName() + count);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -344,13 +302,15 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
|
|||||||
ss = Sheet.createPropertiesSet();
|
ss = Sheet.createPropertiesSet();
|
||||||
s.put(ss);
|
s.put(ss);
|
||||||
}
|
}
|
||||||
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.filterType.name"), NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.filterType.displayName"), NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.filterType.desc"), filter.getDisplayName()));
|
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.filterType.name"),
|
||||||
String extensions = "";
|
NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.filterType.displayName"),
|
||||||
for (String ext : filter.getFilter()) {
|
NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.filterType.desc"),
|
||||||
extensions += "'" + ext + "', ";
|
filter.getDisplayName()));
|
||||||
}
|
|
||||||
extensions = extensions.substring(0, extensions.lastIndexOf(','));
|
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.fileExt.name"),
|
||||||
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.fileExt.name"), NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.fileExt.displayName"), NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.fileExt.desc"), extensions));
|
NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.fileExt.displayName"),
|
||||||
|
NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.fileExt.desc"),
|
||||||
|
String.join(", ", filter.getFilter())));
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -369,98 +329,86 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
|
|||||||
return DisplayableItemNode.FILE_PARENT_NODE_KEY;
|
return DisplayableItemNode.FILE_PARENT_NODE_KEY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
String getDisplayNameBase() {
|
||||||
|
return filter.getDisplayName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
long calculateChildCount() throws TskCoreException {
|
||||||
|
return skCase.countFilesWhere(createQuery(filter));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String createQuery(FileTypesByExtension.SearchFilterInterface filter) {
|
||||||
|
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 (NULL"); //NON-NLS
|
||||||
|
for (String s : filter.getFilter()) {
|
||||||
|
query.append(" OR LOWER(name) LIKE LOWER('%").append(s).append("')"); //NON-NLS
|
||||||
|
}
|
||||||
|
query.append(')');
|
||||||
|
return query.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Child node factory for a specific file type - does the database query.
|
||||||
|
*/
|
||||||
|
private static class FileExtensionNodeChildren extends ChildFactory.Detachable<Content> implements Observer {
|
||||||
|
|
||||||
|
private final SleuthkitCase skCase;
|
||||||
|
private final FileTypesByExtension.SearchFilterInterface filter;
|
||||||
|
private final Observable notifier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Child node factory for a specific file type - does the database
|
*
|
||||||
* query.
|
* @param filter Extensions to display
|
||||||
|
* @param skCase
|
||||||
|
* @param o Observable that will notify when there could be new
|
||||||
|
* data to display
|
||||||
*/
|
*/
|
||||||
private static class FileExtensionNodeChildren extends ChildFactory.Detachable<Content> {
|
private FileExtensionNodeChildren(FileTypesByExtension.SearchFilterInterface filter, SleuthkitCase skCase, Observable o) {
|
||||||
|
super();
|
||||||
|
this.filter = filter;
|
||||||
|
this.skCase = skCase;
|
||||||
|
notifier = o;
|
||||||
|
}
|
||||||
|
|
||||||
private final SleuthkitCase skCase;
|
@Override
|
||||||
private final FileTypesByExtension.SearchFilterInterface filter;
|
protected void addNotify() {
|
||||||
private static final Logger LOGGER = Logger.getLogger(FileExtensionNodeChildren.class.getName());
|
if (notifier != null) {
|
||||||
private final Observable notifier;
|
notifier.addObserver(this);
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param filter Extensions to display
|
|
||||||
* @param skCase
|
|
||||||
* @param o Observable that will notify when there could be new
|
|
||||||
* data to display
|
|
||||||
*/
|
|
||||||
private FileExtensionNodeChildren(FileTypesByExtension.SearchFilterInterface filter, SleuthkitCase skCase, Observable o) {
|
|
||||||
super();
|
|
||||||
this.filter = filter;
|
|
||||||
this.skCase = skCase;
|
|
||||||
notifier = o;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void addNotify() {
|
protected void removeNotify() {
|
||||||
if (notifier != null) {
|
if (notifier != null) {
|
||||||
notifier.addObserver(observer);
|
notifier.deleteObserver(this);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void removeNotify() {
|
public void update(Observable o, Object arg) {
|
||||||
if (notifier != null) {
|
refresh(true);
|
||||||
notifier.deleteObserver(observer);
|
}
|
||||||
}
|
|
||||||
|
@Override
|
||||||
|
protected boolean createKeys(List<Content> list) {
|
||||||
|
try {
|
||||||
|
list.addAll(skCase.findAllFilesWhere(createQuery(filter)));
|
||||||
|
} catch (TskCoreException ex) {
|
||||||
|
logger.log(Level.SEVERE, "Couldn't get search results", ex); //NON-NLS
|
||||||
}
|
}
|
||||||
private final Observer observer = new FileTypeChildFactoryObserver();
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Cause refresh of children if there are changes
|
@Override
|
||||||
private class FileTypeChildFactoryObserver implements Observer {
|
protected Node createNodeForKey(Content key) {
|
||||||
|
return key.accept(new FileTypes.FileNodeCreationVisitor());
|
||||||
@Override
|
|
||||||
public void update(Observable o, Object arg) {
|
|
||||||
refresh(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get children count without actually loading all nodes
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private static long calculateItems(SleuthkitCase sleuthkitCase, FileTypesByExtension.SearchFilterInterface filter) {
|
|
||||||
try {
|
|
||||||
return sleuthkitCase.countFilesWhere(createQuery(filter));
|
|
||||||
} catch (TskCoreException ex) {
|
|
||||||
LOGGER.log(Level.SEVERE, "Error getting file search view count", ex); //NON-NLS
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean createKeys(List<Content> list) {
|
|
||||||
try {
|
|
||||||
List<AbstractFile> files = skCase.findAllFilesWhere(createQuery(filter));
|
|
||||||
list.addAll(files);
|
|
||||||
} catch (TskCoreException ex) {
|
|
||||||
LOGGER.log(Level.SEVERE, "Couldn't get search results", ex); //NON-NLS
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String createQuery(FileTypesByExtension.SearchFilterInterface filter) {
|
|
||||||
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 (NULL"); //NON-NLS
|
|
||||||
for (String s : filter.getFilter()) {
|
|
||||||
query.append(" OR LOWER(name) LIKE LOWER('%").append(s).append("')"); //NON-NLS
|
|
||||||
}
|
|
||||||
query.append(')');
|
|
||||||
return query.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Node createNodeForKey(Content key) {
|
|
||||||
return key.accept(new FileTypes.FileNodeCreationVisitor());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -637,5 +585,6 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
|
|||||||
public String getDisplayName();
|
public String getDisplayName();
|
||||||
|
|
||||||
public List<String> getFilter();
|
public List<String> getFilter();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,10 +26,10 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Observable;
|
import java.util.Observable;
|
||||||
import java.util.Observer;
|
import java.util.Observer;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.openide.nodes.ChildFactory;
|
import org.openide.nodes.ChildFactory;
|
||||||
import org.openide.nodes.Children;
|
import org.openide.nodes.Children;
|
||||||
@ -52,20 +52,20 @@ import org.sleuthkit.datamodel.TskData;
|
|||||||
* File Types view, shows all files with a mime type. Will initially be empty
|
* 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
|
* until file type identification has been performed. Contains a Property Change
|
||||||
* Listener which is checking for changes in IngestJobEvent Completed or
|
* Listener which is checking for changes in IngestJobEvent Completed or
|
||||||
* Cancelled and IngestModuleEvent Content Changed.
|
* Canceled and IngestModuleEvent Content Changed.
|
||||||
*/
|
*/
|
||||||
public final class FileTypesByMimeType extends Observable implements AutopsyVisitableItem {
|
public final class FileTypesByMimeType extends Observable implements AutopsyVisitableItem {
|
||||||
|
|
||||||
|
private final static Logger logger = Logger.getLogger(FileTypesByMimeType.class.getName());
|
||||||
private final SleuthkitCase skCase;
|
private final SleuthkitCase skCase;
|
||||||
/**
|
/**
|
||||||
* The nodes of this tree will be determined dynamically by the mimetypes
|
* 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
|
* 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.
|
* type as the key and a Map, from media subtype to count, as the value.
|
||||||
*/
|
*/
|
||||||
private final HashMap<String, List<String>> existingMimeTypes = new HashMap<>();
|
private final HashMap<String, Map<String, Long>> existingMimeTypeCounts = new HashMap<>();
|
||||||
private static final Logger LOGGER = Logger.getLogger(FileTypesByMimeType.class.getName());
|
private static final Logger LOGGER = Logger.getLogger(FileTypesByMimeType.class.getName());
|
||||||
|
private final FileTypes typesRoot;
|
||||||
private boolean showCounts = true;
|
|
||||||
|
|
||||||
private void removeListeners() {
|
private void removeListeners() {
|
||||||
deleteObservers();
|
deleteObservers();
|
||||||
@ -78,54 +78,40 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
|
|||||||
*/
|
*/
|
||||||
private final PropertyChangeListener pcl;
|
private final PropertyChangeListener pcl;
|
||||||
|
|
||||||
/**
|
|
||||||
* 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<String> getMediaTypeList() {
|
|
||||||
synchronized (existingMimeTypes) {
|
|
||||||
List<String> mediaTypes = new ArrayList<>(existingMimeTypes.keySet());
|
|
||||||
Collections.sort(mediaTypes);
|
|
||||||
return mediaTypes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs the query on the database to get all distinct MIME types of
|
* Performs the query on the database to get all distinct MIME types of
|
||||||
* files in it, and populate the hashmap with those results.
|
* files in it, and populate the hashmap with those results.
|
||||||
*/
|
*/
|
||||||
private void populateHashMap() {
|
private void populateHashMap() {
|
||||||
StringBuilder allDistinctMimeTypesQuery = new StringBuilder();
|
String query = "SELECT mime_type,count(*) as count from tsk_files "
|
||||||
allDistinctMimeTypesQuery.append("SELECT DISTINCT mime_type from tsk_files where mime_type IS NOT null"); //NON-NLS
|
+ " where mime_type IS NOT null "
|
||||||
allDistinctMimeTypesQuery.append(" AND dir_type = ").append(TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue()); //NON-NLS
|
+ " AND dir_type = " + TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue()
|
||||||
allDistinctMimeTypesQuery.append(" AND (type IN (").append(TskData.TSK_DB_FILES_TYPE_ENUM.FS.ordinal()).append(","); //NON-NLS
|
+ " AND (type IN ("
|
||||||
allDistinctMimeTypesQuery.append(TskData.TSK_DB_FILES_TYPE_ENUM.CARVED.ordinal()).append(",");
|
+ TskData.TSK_DB_FILES_TYPE_ENUM.FS.ordinal() + ","
|
||||||
allDistinctMimeTypesQuery.append(TskData.TSK_DB_FILES_TYPE_ENUM.DERIVED.ordinal()).append(",");
|
+ TskData.TSK_DB_FILES_TYPE_ENUM.CARVED.ordinal() + ","
|
||||||
if (!UserPreferences.hideSlackFilesInViewsTree()) {
|
+ TskData.TSK_DB_FILES_TYPE_ENUM.DERIVED.ordinal() + ","
|
||||||
allDistinctMimeTypesQuery.append(TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.ordinal()).append(",");
|
+ TskData.TSK_DB_FILES_TYPE_ENUM.LOCAL.ordinal()
|
||||||
}
|
+ ((UserPreferences.hideSlackFilesInViewsTree()) ? ""
|
||||||
allDistinctMimeTypesQuery.append(TskData.TSK_DB_FILES_TYPE_ENUM.LOCAL.ordinal()).append("))");
|
: ("," + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.ordinal()))
|
||||||
synchronized (existingMimeTypes) {
|
+ "))" + " GROUP BY mime_type";
|
||||||
existingMimeTypes.clear();
|
synchronized (existingMimeTypeCounts) {
|
||||||
|
existingMimeTypeCounts.clear();
|
||||||
|
|
||||||
if (skCase == null) {
|
if (skCase == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try (SleuthkitCase.CaseDbQuery dbQuery = skCase.executeQuery(allDistinctMimeTypesQuery.toString())) {
|
try (SleuthkitCase.CaseDbQuery dbQuery = skCase.executeQuery(query)) {
|
||||||
ResultSet resultSet = dbQuery.getResultSet();
|
ResultSet resultSet = dbQuery.getResultSet();
|
||||||
while (resultSet.next()) {
|
while (resultSet.next()) {
|
||||||
final String mime_type = resultSet.getString("mime_type"); //NON-NLS
|
final String mime_type = resultSet.getString("mime_type"); //NON-NLS
|
||||||
if (!mime_type.isEmpty()) {
|
if (!mime_type.isEmpty()) {
|
||||||
String mimeType[] = mime_type.split("/");
|
|
||||||
//if the mime_type contained multiple slashes then everything after the first slash will become the subtype
|
//if the mime_type contained multiple slashes then everything after the first slash will become the subtype
|
||||||
final String mimeMediaSubType = StringUtils.join(ArrayUtils.subarray(mimeType, 1, mimeType.length), "/");
|
final String mediaType = StringUtils.substringBefore(mime_type, "/");
|
||||||
if (mimeType.length > 1 && !mimeType[0].isEmpty() && !mimeMediaSubType.isEmpty()) {
|
final String subType = StringUtils.removeStart(mime_type, mediaType + "/");
|
||||||
if (!existingMimeTypes.containsKey(mimeType[0])) {
|
if (!mediaType.isEmpty() && !subType.isEmpty()) {
|
||||||
existingMimeTypes.put(mimeType[0], new ArrayList<>());
|
final long count = resultSet.getLong("count");
|
||||||
}
|
existingMimeTypeCounts.computeIfAbsent(mediaType, t -> new HashMap<>())
|
||||||
existingMimeTypes.get(mimeType[0]).add(mimeMediaSubType);
|
.put(subType, count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -135,11 +121,12 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
|
|||||||
}
|
}
|
||||||
|
|
||||||
setChanged();
|
setChanged();
|
||||||
|
|
||||||
notifyObservers();
|
notifyObservers();
|
||||||
}
|
}
|
||||||
|
|
||||||
FileTypesByMimeType(SleuthkitCase skCase) {
|
FileTypesByMimeType(FileTypes typesRoot) {
|
||||||
|
this.skCase = typesRoot.getSleuthkitCase();
|
||||||
|
this.typesRoot = typesRoot;
|
||||||
this.pcl = (PropertyChangeEvent evt) -> {
|
this.pcl = (PropertyChangeEvent evt) -> {
|
||||||
String eventType = evt.getPropertyName();
|
String eventType = evt.getPropertyName();
|
||||||
if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|
if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|
||||||
@ -153,8 +140,7 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
|
|||||||
*/
|
*/
|
||||||
try {
|
try {
|
||||||
Case.getCurrentCase();
|
Case.getCurrentCase();
|
||||||
shouldShowCounts(skCase);
|
typesRoot.shouldShowCounts();
|
||||||
|
|
||||||
populateHashMap();
|
populateHashMap();
|
||||||
} catch (IllegalStateException notUsed) {
|
} catch (IllegalStateException notUsed) {
|
||||||
/**
|
/**
|
||||||
@ -169,30 +155,9 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
|
|||||||
};
|
};
|
||||||
IngestManager.getInstance().addIngestJobEventListener(pcl);
|
IngestManager.getInstance().addIngestJobEventListener(pcl);
|
||||||
Case.addPropertyChangeListener(pcl);
|
Case.addPropertyChangeListener(pcl);
|
||||||
this.skCase = skCase;
|
|
||||||
populateHashMap();
|
populateHashMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Should the nodes show counts?
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @return True, unless the DB has more than 200k rows.
|
|
||||||
*/
|
|
||||||
private boolean shouldShowCounts(final SleuthkitCase skCase) {
|
|
||||||
if (showCounts) {
|
|
||||||
try {
|
|
||||||
if (skCase.countFilesWhere("1=1") > 200000) {
|
|
||||||
showCounts = false;
|
|
||||||
}
|
|
||||||
} catch (TskCoreException tskCoreException) {
|
|
||||||
showCounts = false;
|
|
||||||
LOGGER.log(Level.SEVERE, "Error counting files.", tskCoreException);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return showCounts;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> T accept(AutopsyItemVisitor<T> v) {
|
public <T> T accept(AutopsyItemVisitor<T> v) {
|
||||||
return v.visit(this);
|
return v.visit(this);
|
||||||
@ -251,9 +216,10 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
|
|||||||
}
|
}
|
||||||
|
|
||||||
boolean isEmpty() {
|
boolean isEmpty() {
|
||||||
return existingMimeTypes.isEmpty();
|
synchronized (existingMimeTypeCounts) {
|
||||||
|
return existingMimeTypeCounts.isEmpty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -269,9 +235,13 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean createKeys(List<String> mediaTypeNodes) {
|
protected boolean createKeys(List<String> mediaTypeNodes) {
|
||||||
if (!existingMimeTypes.isEmpty()) {
|
final List<String> keylist;
|
||||||
mediaTypeNodes.addAll(getMediaTypeList());
|
synchronized (existingMimeTypeCounts) {
|
||||||
|
keylist = new ArrayList<>(existingMimeTypeCounts.keySet());
|
||||||
}
|
}
|
||||||
|
Collections.sort(keylist);
|
||||||
|
mediaTypeNodes.addAll(keylist);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,7 +254,6 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
|
|||||||
public void update(Observable o, Object arg) {
|
public void update(Observable o, Object arg) {
|
||||||
refresh(true);
|
refresh(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -349,7 +318,7 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean createKeys(List<String> mediaTypeNodes) {
|
protected boolean createKeys(List<String> mediaTypeNodes) {
|
||||||
mediaTypeNodes.addAll(existingMimeTypes.get(mediaType));
|
mediaTypeNodes.addAll(existingMimeTypeCounts.get(mediaType).keySet());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -370,33 +339,22 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
|
|||||||
* Node which represents the media sub type in the By MIME type tree, the
|
* 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 /.
|
* media subtype is the portion of the MIME type following the /.
|
||||||
*/
|
*/
|
||||||
class MediaSubTypeNode extends DisplayableItemNode implements Observer {
|
class MediaSubTypeNode extends FileTypes.BGCountUpdatingNode {
|
||||||
@NbBundle.Messages({"FileTypesByMimeTypeNode.createSheet.mediaSubtype.name=Subtype",
|
@NbBundle.Messages({"FileTypesByMimeTypeNode.createSheet.mediaSubtype.name=Subtype",
|
||||||
"FileTypesByMimeTypeNode.createSheet.mediaSubtype.displayName=Subtype",
|
"FileTypesByMimeTypeNode.createSheet.mediaSubtype.displayName=Subtype",
|
||||||
"FileTypesByMimeTypeNode.createSheet.mediaSubtype.desc=no description"})
|
"FileTypesByMimeTypeNode.createSheet.mediaSubtype.desc=no description"})
|
||||||
|
private final String mimeType;
|
||||||
|
private final String subType;
|
||||||
|
|
||||||
private MediaSubTypeNode(String mimeType) {
|
private MediaSubTypeNode(String mimeType) {
|
||||||
super(Children.create(new MediaSubTypeNodeChildren(mimeType), true),Lookups.singleton(mimeType));
|
super(typesRoot, Children.create(new MediaSubTypeNodeChildren(mimeType), true), Lookups.singleton(mimeType));
|
||||||
addObserver(this);
|
this.mimeType = mimeType;
|
||||||
init(mimeType);
|
this.subType = StringUtils.substringAfter(mimeType, "/");
|
||||||
}
|
|
||||||
|
|
||||||
private void init(String mimeType) {
|
|
||||||
super.setName(mimeType);
|
super.setName(mimeType);
|
||||||
updateDisplayName(mimeType);
|
super.setDisplayName(subType);
|
||||||
|
updateDisplayName();
|
||||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-filter-icon.png"); //NON-NLS
|
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-filter-icon.png"); //NON-NLS
|
||||||
}
|
addObserver(this);
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 = calculateItems(skCase, mimeType);
|
|
||||||
//only the part of the mimeType after the media type
|
|
||||||
super.setDisplayName(StringUtils.substringAfter(mimeType, "/") + " (" + count + ")");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -411,7 +369,7 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
|
public <T> T accept(DisplayableItemNodeVisitor< T> v) {
|
||||||
return v.visit(this);
|
return v.visit(this);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
@ -433,22 +391,17 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(Observable o, Object arg) {
|
public void update(Observable o, Object arg) {
|
||||||
updateDisplayName(getName());
|
updateDisplayName();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Get children count without actually loading all nodes
|
String getDisplayNameBase() {
|
||||||
*
|
return subType;
|
||||||
* @return count(*) - the number of items that will be shown in this items
|
}
|
||||||
* Directory Listing
|
|
||||||
*/
|
@Override
|
||||||
static private long calculateItems(SleuthkitCase sleuthkitCase, String mime_type) {
|
long calculateChildCount() {
|
||||||
try {
|
return existingMimeTypeCounts.get(StringUtils.substringBefore(mimeType, "/")).get(subType);
|
||||||
return sleuthkitCase.countFilesWhere(createQuery(mime_type));
|
|
||||||
} catch (TskCoreException ex) {
|
|
||||||
LOGGER.log(Level.SEVERE, "Error getting file search view count", ex); //NON-NLS
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ class FactoryClassNameNormalizer {
|
|||||||
// of their file name. This block of code gets rid of that variable
|
// of their file name. This block of code gets rid of that variable
|
||||||
// instance number and helps maitains constant module name over
|
// instance number and helps maitains constant module name over
|
||||||
// multiple runs.
|
// multiple runs.
|
||||||
String moduleClassName = canonicalClassName.replaceAll("\\d*$", ""); //NON-NLS NON-NLS
|
String moduleClassName = canonicalClassName.replaceAll("\\$\\d*$", ""); //NON-NLS NON-NLS
|
||||||
return moduleClassName;
|
return moduleClassName;
|
||||||
}
|
}
|
||||||
return canonicalClassName;
|
return canonicalClassName;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user