mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-17 18:17:43 +00:00
3757: Group views in the case tree by data source
This commit is contained in:
parent
bdfa460d5d
commit
c05e92aec2
@ -69,6 +69,7 @@ public final class UserPreferences {
|
|||||||
private static final String MODE = "AutopsyMode"; // NON-NLS
|
private static final String MODE = "AutopsyMode"; // NON-NLS
|
||||||
private static final String MAX_NUM_OF_LOG_FILE = "MaximumNumberOfLogFiles";
|
private static final String MAX_NUM_OF_LOG_FILE = "MaximumNumberOfLogFiles";
|
||||||
private static final int LOG_FILE_NUM_INT = 10;
|
private static final int LOG_FILE_NUM_INT = 10;
|
||||||
|
public static final String GROUP_ITEMS_IN_TREE_BY_DATASOURCE = "GroupItemsInTreeByDataSource"; //NON-NLS
|
||||||
|
|
||||||
// Prevent instantiation.
|
// Prevent instantiation.
|
||||||
private UserPreferences() {
|
private UserPreferences() {
|
||||||
@ -187,6 +188,14 @@ public final class UserPreferences {
|
|||||||
preferences.putInt(NUMBER_OF_FILE_INGEST_THREADS, value);
|
preferences.putInt(NUMBER_OF_FILE_INGEST_THREADS, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean groupItemsInTreeByDatasource() {
|
||||||
|
return preferences.getBoolean(GROUP_ITEMS_IN_TREE_BY_DATASOURCE, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setGroupItemsInTreeByDatasource(boolean value) {
|
||||||
|
preferences.putBoolean(GROUP_ITEMS_IN_TREE_BY_DATASOURCE, value);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads persisted case database connection info.
|
* Reads persisted case database connection info.
|
||||||
*
|
*
|
||||||
|
@ -162,12 +162,12 @@ abstract class AbstractContentChildren<T> extends Keys<T> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AbstractNode visit(DeletedContent dc) {
|
public AbstractNode visit(DeletedContent dc) {
|
||||||
return new DeletedContent.DeletedContentsNode(dc.getSleuthkitCase());
|
return new DeletedContent.DeletedContentsNode(dc.getSleuthkitCase(), dc.filteringDataSourceObjId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AbstractNode visit(FileSize dc) {
|
public AbstractNode visit(FileSize dc) {
|
||||||
return new FileSize.FileSizeRootNode(dc.getSleuthkitCase());
|
return new FileSize.FileSizeRootNode(dc.getSleuthkitCase(), dc.filteringDataSourceObjId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -234,7 +234,7 @@ abstract class AbstractContentChildren<T> extends Keys<T> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AbstractNode visit(FileTypesByMimeType ftByMimeTypeItem) {
|
public AbstractNode visit(FileTypesByMimeType ftByMimeTypeItem) {
|
||||||
return ftByMimeTypeItem.new ByMimeTypeNode();
|
return ftByMimeTypeItem.new ByMimeTypeNode(/*ftByMimeTypeItem.filteringDataSourceObjId()*/);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2018 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
import org.sleuthkit.autopsy.datamodel.DataSourcesLayerChildren.SubtreeEnum;
|
||||||
|
import org.sleuthkit.datamodel.DataSource;
|
||||||
|
import org.sleuthkit.datamodel.Image;
|
||||||
|
import org.sleuthkit.datamodel.LocalFilesDataSource;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Datasource layer node - an optional grouping node in the data tree view
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class DataSourceLayerNode extends DisplayableItemNode {
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger(DataSourceLayerNode.class.getName());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the Datasource node for the given data source,
|
||||||
|
* and initializes the children nodes under it based on the subtree specified
|
||||||
|
*
|
||||||
|
* @param dataSourceLayerInfo specifies the
|
||||||
|
*/
|
||||||
|
DataSourceLayerNode(DataSourcesLayerChildren.DataSourceLayerInfo dataSourceLayerInfo) {
|
||||||
|
|
||||||
|
super (Optional.ofNullable(createDSLayerNodeChildren(dataSourceLayerInfo))
|
||||||
|
.orElse(new RootContentChildren(Arrays.asList(Collections.EMPTY_LIST))));
|
||||||
|
|
||||||
|
DataSource dataSource = dataSourceLayerInfo.getDataSource();
|
||||||
|
if (dataSource instanceof Image) {
|
||||||
|
Image image = (Image) dataSource;
|
||||||
|
|
||||||
|
super.setName(image.getName());
|
||||||
|
super.setDisplayName(image.getName());
|
||||||
|
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/image.png");
|
||||||
|
} else if (dataSource instanceof LocalFilesDataSource) {
|
||||||
|
LocalFilesDataSource localFilesDataSource = (LocalFilesDataSource) dataSource;
|
||||||
|
|
||||||
|
super.setName(localFilesDataSource.getName());
|
||||||
|
super.setDisplayName(localFilesDataSource.getName());
|
||||||
|
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/fileset-icon-16.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLeafTypeNode() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static RootContentChildren createDSLayerNodeChildren(DataSourcesLayerChildren.DataSourceLayerInfo dataSourceLayerInfo) {
|
||||||
|
|
||||||
|
SubtreeEnum subtree = dataSourceLayerInfo.getSubtree();
|
||||||
|
long dsObjId = dataSourceLayerInfo.getDataSource().getId();
|
||||||
|
|
||||||
|
try {
|
||||||
|
switch (subtree) {
|
||||||
|
case VIEWS:
|
||||||
|
return new RootContentChildren(Arrays.asList(
|
||||||
|
new FileTypes(Case.getOpenCase().getSleuthkitCase(), dsObjId),
|
||||||
|
new DeletedContent(Case.getOpenCase().getSleuthkitCase(), dsObjId),
|
||||||
|
new FileSize(Case.getOpenCase().getSleuthkitCase(), dsObjId))
|
||||||
|
);
|
||||||
|
|
||||||
|
case RESULTS: // TBD:
|
||||||
|
case TAGS: // TBD:
|
||||||
|
case REPORTS: // TBD:
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
logger.log(Level.SEVERE, "Unknown subtree type " + subtree.name()); //NON-NLS
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (NoCurrentCaseException ex) {
|
||||||
|
logger.log(Level.SEVERE, "Error getting open case.", ex); //NON-NLS
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
|
||||||
|
return visitor.visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getItemType() {
|
||||||
|
return getClass().getName();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,134 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2018 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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.util.Collections;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import org.openide.nodes.Children;
|
||||||
|
import org.openide.nodes.Node;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
import org.sleuthkit.datamodel.DataSource;
|
||||||
|
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||||
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Child factory for DataSource node layer in the Results, Views Tags subtrees
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class DataSourcesLayerChildren extends Children.Keys<DataSource> {
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger(DataSourcesLayerChildren.class.getName());
|
||||||
|
private final SleuthkitCase sleuthkitCase;
|
||||||
|
private final SubtreeEnum subTree;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subtree in which this DataSourcesLayerChildren exist
|
||||||
|
*/
|
||||||
|
public enum SubtreeEnum {
|
||||||
|
VIEWS,
|
||||||
|
RESULTS,
|
||||||
|
TAGS,
|
||||||
|
REPORTS
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple wrapper class to pass Datasource and subtree down to children nodes
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class DataSourceLayerInfo {
|
||||||
|
|
||||||
|
private final DataSource dataSource;
|
||||||
|
private final SubtreeEnum subTree;
|
||||||
|
|
||||||
|
DataSourceLayerInfo(DataSource dataSource, SubtreeEnum subTree) {
|
||||||
|
this.dataSource = dataSource;
|
||||||
|
this.subTree = subTree;
|
||||||
|
}
|
||||||
|
|
||||||
|
DataSource getDataSource() {
|
||||||
|
return this.dataSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
SubtreeEnum getSubtree() {
|
||||||
|
return this.subTree;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs the factory to create optional datasource nodes
|
||||||
|
*
|
||||||
|
* @param tskCase - Case DB
|
||||||
|
* @param subTree - subtree under which data source nodes are to be created
|
||||||
|
*/
|
||||||
|
public DataSourcesLayerChildren(SleuthkitCase tskCase, SubtreeEnum subTree) {
|
||||||
|
// super(true);
|
||||||
|
super(false);
|
||||||
|
|
||||||
|
this.sleuthkitCase = tskCase;
|
||||||
|
this.subTree = subTree;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final PropertyChangeListener pcl = new PropertyChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void propertyChange(PropertyChangeEvent evt) {
|
||||||
|
String eventType = evt.getPropertyName();
|
||||||
|
if (eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) {
|
||||||
|
reloadKeys();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private void reloadKeys() {
|
||||||
|
try {
|
||||||
|
List<DataSource> keys = sleuthkitCase.getDataSources();
|
||||||
|
setKeys(keys);
|
||||||
|
} catch (TskCoreException ex) {
|
||||||
|
logger.log(Level.SEVERE, "Failed to get Datasources from DB", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addNotify() {
|
||||||
|
super.addNotify();
|
||||||
|
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.DATA_SOURCE_ADDED), pcl);
|
||||||
|
reloadKeys();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void removeNotify() {
|
||||||
|
super.removeNotify();
|
||||||
|
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.DATA_SOURCE_ADDED), pcl);
|
||||||
|
setKeys(Collections.emptyList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Node[] createNodes(DataSource ds) {
|
||||||
|
return new Node[]{createNodeForKey(ds)};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Node createNodeForKey(DataSource ds) {
|
||||||
|
return new DataSourceLayerNode(new DataSourceLayerInfo(ds, subTree));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -61,6 +61,7 @@ import org.sleuthkit.datamodel.TskData;
|
|||||||
public class DeletedContent implements AutopsyVisitableItem {
|
public class DeletedContent implements AutopsyVisitableItem {
|
||||||
|
|
||||||
private SleuthkitCase skCase;
|
private SleuthkitCase skCase;
|
||||||
|
private final long datasourceObjId;
|
||||||
|
|
||||||
@NbBundle.Messages({"DeletedContent.fsDelFilter.text=File System",
|
@NbBundle.Messages({"DeletedContent.fsDelFilter.text=File System",
|
||||||
"DeletedContent.allDelFilter.text=All"})
|
"DeletedContent.allDelFilter.text=All"})
|
||||||
@ -101,9 +102,18 @@ public class DeletedContent implements AutopsyVisitableItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public DeletedContent(SleuthkitCase skCase) {
|
public DeletedContent(SleuthkitCase skCase) {
|
||||||
this.skCase = skCase;
|
this(skCase, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DeletedContent(SleuthkitCase skCase, long dsObjId) {
|
||||||
|
this.skCase = skCase;
|
||||||
|
this.datasourceObjId = dsObjId;
|
||||||
|
}
|
||||||
|
|
||||||
|
long filteringDataSourceObjId() {
|
||||||
|
return this.datasourceObjId;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> T accept(AutopsyItemVisitor<T> v) {
|
public <T> T accept(AutopsyItemVisitor<T> v) {
|
||||||
return v.visit(this);
|
return v.visit(this);
|
||||||
@ -118,8 +128,8 @@ public class DeletedContent implements AutopsyVisitableItem {
|
|||||||
@NbBundle.Messages("DeletedContent.deletedContentsNode.name=Deleted Files")
|
@NbBundle.Messages("DeletedContent.deletedContentsNode.name=Deleted Files")
|
||||||
private static final String NAME = Bundle.DeletedContent_deletedContentsNode_name();
|
private static final String NAME = Bundle.DeletedContent_deletedContentsNode_name();
|
||||||
|
|
||||||
DeletedContentsNode(SleuthkitCase skCase) {
|
DeletedContentsNode(SleuthkitCase skCase, long datasourceObjId) {
|
||||||
super(Children.create(new DeletedContentsChildren(skCase), true), Lookups.singleton(NAME));
|
super(Children.create(new DeletedContentsChildren(skCase, datasourceObjId), true), Lookups.singleton(NAME));
|
||||||
super.setName(NAME);
|
super.setName(NAME);
|
||||||
super.setDisplayName(NAME);
|
super.setDisplayName(NAME);
|
||||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-icon-deleted.png"); //NON-NLS
|
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-icon-deleted.png"); //NON-NLS
|
||||||
@ -164,11 +174,13 @@ public class DeletedContent implements AutopsyVisitableItem {
|
|||||||
|
|
||||||
private SleuthkitCase skCase;
|
private SleuthkitCase skCase;
|
||||||
private Observable notifier;
|
private Observable notifier;
|
||||||
|
private final long datasourceObjId;
|
||||||
// true if we have already told user that not all files will be shown
|
// true if we have already told user that not all files will be shown
|
||||||
private static volatile boolean maxFilesDialogShown = false;
|
private static volatile boolean maxFilesDialogShown = false;
|
||||||
|
|
||||||
public DeletedContentsChildren(SleuthkitCase skCase) {
|
public DeletedContentsChildren(SleuthkitCase skCase, long dsObjId) {
|
||||||
this.skCase = skCase;
|
this.skCase = skCase;
|
||||||
|
this.datasourceObjId = dsObjId;
|
||||||
this.notifier = new DeletedContentsChildrenObservable();
|
this.notifier = new DeletedContentsChildrenObservable();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -257,24 +269,27 @@ public class DeletedContent implements AutopsyVisitableItem {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Node createNodeForKey(DeletedContent.DeletedContentFilter key) {
|
protected Node createNodeForKey(DeletedContent.DeletedContentFilter key) {
|
||||||
return new DeletedContentNode(skCase, key, notifier);
|
return new DeletedContentNode(skCase, key, notifier, datasourceObjId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DeletedContentNode extends DisplayableItemNode {
|
public class DeletedContentNode extends DisplayableItemNode {
|
||||||
|
|
||||||
private final DeletedContent.DeletedContentFilter filter;
|
private final DeletedContent.DeletedContentFilter filter;
|
||||||
|
private final long datasourceObjId;
|
||||||
|
|
||||||
// Use version that has observer for updates
|
// Use version that has observer for updates
|
||||||
@Deprecated
|
@Deprecated
|
||||||
DeletedContentNode(SleuthkitCase skCase, DeletedContent.DeletedContentFilter filter) {
|
DeletedContentNode(SleuthkitCase skCase, DeletedContent.DeletedContentFilter filter, long dsObjId) {
|
||||||
super(Children.create(new DeletedContentChildren(filter, skCase, null), true), Lookups.singleton(filter.getDisplayName()));
|
super(Children.create(new DeletedContentChildren(filter, skCase, null, dsObjId ), true), Lookups.singleton(filter.getDisplayName()));
|
||||||
this.filter = filter;
|
this.filter = filter;
|
||||||
|
this.datasourceObjId = dsObjId;
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
DeletedContentNode(SleuthkitCase skCase, DeletedContent.DeletedContentFilter filter, Observable o) {
|
DeletedContentNode(SleuthkitCase skCase, DeletedContent.DeletedContentFilter filter, Observable o, long dsObjId) {
|
||||||
super(Children.create(new DeletedContentChildren(filter, skCase, o), true), Lookups.singleton(filter.getDisplayName()));
|
super(Children.create(new DeletedContentChildren(filter, skCase, o, dsObjId), true), Lookups.singleton(filter.getDisplayName()));
|
||||||
this.filter = filter;
|
this.filter = filter;
|
||||||
|
this.datasourceObjId = dsObjId;
|
||||||
init();
|
init();
|
||||||
o.addObserver(new DeletedContentNodeObserver());
|
o.addObserver(new DeletedContentNodeObserver());
|
||||||
}
|
}
|
||||||
@ -299,7 +314,7 @@ public class DeletedContent implements AutopsyVisitableItem {
|
|||||||
|
|
||||||
private void updateDisplayName() {
|
private void updateDisplayName() {
|
||||||
//get count of children without preloading all children nodes
|
//get count of children without preloading all children nodes
|
||||||
final long count = DeletedContentChildren.calculateItems(skCase, filter);
|
final long count = DeletedContentChildren.calculateItems(skCase, filter, datasourceObjId);
|
||||||
//final long count = getChildren().getNodesCount(true);
|
//final long count = getChildren().getNodesCount(true);
|
||||||
super.setDisplayName(filter.getDisplayName() + " (" + count + ")");
|
super.setDisplayName(filter.getDisplayName() + " (" + count + ")");
|
||||||
}
|
}
|
||||||
@ -351,11 +366,13 @@ public class DeletedContent implements AutopsyVisitableItem {
|
|||||||
private static final Logger logger = Logger.getLogger(DeletedContentChildren.class.getName());
|
private static final Logger logger = Logger.getLogger(DeletedContentChildren.class.getName());
|
||||||
private static final int MAX_OBJECTS = 10001;
|
private static final int MAX_OBJECTS = 10001;
|
||||||
private final Observable notifier;
|
private final Observable notifier;
|
||||||
|
private final long datasourceObjId;
|
||||||
|
|
||||||
DeletedContentChildren(DeletedContent.DeletedContentFilter filter, SleuthkitCase skCase, Observable o) {
|
DeletedContentChildren(DeletedContent.DeletedContentFilter filter, SleuthkitCase skCase, Observable o, long datasourceObjId) {
|
||||||
this.skCase = skCase;
|
this.skCase = skCase;
|
||||||
this.filter = filter;
|
this.filter = filter;
|
||||||
this.notifier = o;
|
this.notifier = o;
|
||||||
|
this.datasourceObjId = datasourceObjId;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Observer observer = new DeletedContentChildrenObserver();
|
private final Observer observer = new DeletedContentChildrenObserver();
|
||||||
@ -405,7 +422,7 @@ public class DeletedContent implements AutopsyVisitableItem {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static private String makeQuery(DeletedContent.DeletedContentFilter filter) {
|
static private String makeQuery(DeletedContent.DeletedContentFilter filter, long filteringDSObjId) {
|
||||||
String query = "";
|
String query = "";
|
||||||
switch (filter) {
|
switch (filter) {
|
||||||
case FS_DELETED_FILTER:
|
case FS_DELETED_FILTER:
|
||||||
@ -443,6 +460,10 @@ public class DeletedContent implements AutopsyVisitableItem {
|
|||||||
+ " OR known IS NULL)"; //NON-NLS
|
+ " OR known IS NULL)"; //NON-NLS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (UserPreferences.groupItemsInTreeByDatasource()) {
|
||||||
|
query += " AND data_source_obj_id = " + filteringDSObjId;
|
||||||
|
}
|
||||||
|
|
||||||
query += " LIMIT " + MAX_OBJECTS; //NON-NLS
|
query += " LIMIT " + MAX_OBJECTS; //NON-NLS
|
||||||
return query;
|
return query;
|
||||||
}
|
}
|
||||||
@ -450,7 +471,7 @@ public class DeletedContent implements AutopsyVisitableItem {
|
|||||||
private List<AbstractFile> runFsQuery() {
|
private List<AbstractFile> runFsQuery() {
|
||||||
List<AbstractFile> ret = new ArrayList<>();
|
List<AbstractFile> ret = new ArrayList<>();
|
||||||
|
|
||||||
String query = makeQuery(filter);
|
String query = makeQuery(filter, datasourceObjId);
|
||||||
try {
|
try {
|
||||||
ret = skCase.findAllFilesWhere(query);
|
ret = skCase.findAllFilesWhere(query);
|
||||||
} catch (TskCoreException e) {
|
} catch (TskCoreException e) {
|
||||||
@ -469,9 +490,9 @@ public class DeletedContent implements AutopsyVisitableItem {
|
|||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
static long calculateItems(SleuthkitCase sleuthkitCase, DeletedContent.DeletedContentFilter filter) {
|
static long calculateItems(SleuthkitCase sleuthkitCase, DeletedContent.DeletedContentFilter filter, long datasourceObjId) {
|
||||||
try {
|
try {
|
||||||
return sleuthkitCase.countFilesWhere(makeQuery(filter));
|
return sleuthkitCase.countFilesWhere(makeQuery(filter, datasourceObjId));
|
||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
logger.log(Level.SEVERE, "Error getting deleted files search view count", ex); //NON-NLS
|
logger.log(Level.SEVERE, "Error getting deleted files search view count", ex); //NON-NLS
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -60,6 +60,8 @@ public interface DisplayableItemNodeVisitor<T> {
|
|||||||
*/
|
*/
|
||||||
T visit(ViewsNode vn);
|
T visit(ViewsNode vn);
|
||||||
|
|
||||||
|
T visit(DataSourceLayerNode vn);
|
||||||
|
|
||||||
T visit(org.sleuthkit.autopsy.datamodel.FileTypesByExtension.FileExtensionNode fsfn);
|
T visit(org.sleuthkit.autopsy.datamodel.FileTypesByExtension.FileExtensionNode fsfn);
|
||||||
|
|
||||||
T visit(DeletedContentNode dcn);
|
T visit(DeletedContentNode dcn);
|
||||||
@ -307,6 +309,11 @@ public interface DisplayableItemNodeVisitor<T> {
|
|||||||
return defaultVisit(vn);
|
return defaultVisit(vn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T visit(DataSourceLayerNode vn) {
|
||||||
|
return defaultVisit(vn);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T visit(ResultsNode rn) {
|
public T visit(ResultsNode rn) {
|
||||||
return defaultVisit(rn);
|
return defaultVisit(rn);
|
||||||
|
@ -61,6 +61,7 @@ import org.sleuthkit.datamodel.VirtualDirectory;
|
|||||||
public class FileSize implements AutopsyVisitableItem {
|
public class FileSize implements AutopsyVisitableItem {
|
||||||
|
|
||||||
private SleuthkitCase skCase;
|
private SleuthkitCase skCase;
|
||||||
|
private final long datasourceObjId;
|
||||||
|
|
||||||
public enum FileSizeFilter implements AutopsyVisitableItem {
|
public enum FileSizeFilter implements AutopsyVisitableItem {
|
||||||
|
|
||||||
@ -97,9 +98,14 @@ public class FileSize implements AutopsyVisitableItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public FileSize(SleuthkitCase skCase) {
|
public FileSize(SleuthkitCase skCase) {
|
||||||
this.skCase = skCase;
|
this(skCase, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public FileSize(SleuthkitCase skCase, long dsObjId) {
|
||||||
|
this.skCase = skCase;
|
||||||
|
this.datasourceObjId = dsObjId;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> T accept(AutopsyItemVisitor<T> v) {
|
public <T> T accept(AutopsyItemVisitor<T> v) {
|
||||||
return v.visit(this);
|
return v.visit(this);
|
||||||
@ -109,6 +115,9 @@ public class FileSize implements AutopsyVisitableItem {
|
|||||||
return this.skCase;
|
return this.skCase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
long filteringDataSourceObjId() {
|
||||||
|
return this.datasourceObjId;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* Root node. Children are nodes for specific sizes.
|
* Root node. Children are nodes for specific sizes.
|
||||||
*/
|
*/
|
||||||
@ -116,8 +125,8 @@ public class FileSize implements AutopsyVisitableItem {
|
|||||||
|
|
||||||
private static final String NAME = NbBundle.getMessage(FileSize.class, "FileSize.fileSizeRootNode.name");
|
private static final String NAME = NbBundle.getMessage(FileSize.class, "FileSize.fileSizeRootNode.name");
|
||||||
|
|
||||||
FileSizeRootNode(SleuthkitCase skCase) {
|
FileSizeRootNode(SleuthkitCase skCase, long datasourceObjId) {
|
||||||
super(Children.create(new FileSizeRootChildren(skCase), true), Lookups.singleton(NAME));
|
super(Children.create(new FileSizeRootChildren(skCase, datasourceObjId), true), Lookups.singleton(NAME));
|
||||||
super.setName(NAME);
|
super.setName(NAME);
|
||||||
super.setDisplayName(NAME);
|
super.setDisplayName(NAME);
|
||||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-size-16.png"); //NON-NLS
|
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-size-16.png"); //NON-NLS
|
||||||
@ -161,10 +170,12 @@ public class FileSize implements AutopsyVisitableItem {
|
|||||||
public static class FileSizeRootChildren extends ChildFactory<org.sleuthkit.autopsy.datamodel.FileSize.FileSizeFilter> {
|
public static class FileSizeRootChildren extends ChildFactory<org.sleuthkit.autopsy.datamodel.FileSize.FileSizeFilter> {
|
||||||
|
|
||||||
private SleuthkitCase skCase;
|
private SleuthkitCase skCase;
|
||||||
|
private long datasourceObjId;
|
||||||
private Observable notifier;
|
private Observable notifier;
|
||||||
|
|
||||||
public FileSizeRootChildren(SleuthkitCase skCase) {
|
public FileSizeRootChildren(SleuthkitCase skCase, long datasourceObjId) {
|
||||||
this.skCase = skCase;
|
this.skCase = skCase;
|
||||||
|
this.datasourceObjId = datasourceObjId;
|
||||||
notifier = new FileSizeRootChildrenObservable();
|
notifier = new FileSizeRootChildrenObservable();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -248,7 +259,7 @@ public class FileSize implements AutopsyVisitableItem {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Node createNodeForKey(FileSizeFilter key) {
|
protected Node createNodeForKey(FileSizeFilter key) {
|
||||||
return new FileSizeNode(skCase, key, notifier);
|
return new FileSizeNode(skCase, key, notifier, datasourceObjId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -257,12 +268,14 @@ public class FileSize implements AutopsyVisitableItem {
|
|||||||
public class FileSizeNode extends DisplayableItemNode {
|
public class FileSizeNode extends DisplayableItemNode {
|
||||||
|
|
||||||
private FileSizeFilter filter;
|
private FileSizeFilter filter;
|
||||||
|
private final long datasourceObjId;
|
||||||
|
|
||||||
// use version with observer instead so that it updates
|
// use version with observer instead so that it updates
|
||||||
@Deprecated
|
@Deprecated
|
||||||
FileSizeNode(SleuthkitCase skCase, FileSizeFilter filter) {
|
FileSizeNode(SleuthkitCase skCase, FileSizeFilter filter, long datasourceObjId) {
|
||||||
super(Children.create(new FileSizeChildren(filter, skCase, null), true), Lookups.singleton(filter.getDisplayName()));
|
super(Children.create(new FileSizeChildren(filter, skCase, null, datasourceObjId), true), Lookups.singleton(filter.getDisplayName()));
|
||||||
this.filter = filter;
|
this.filter = filter;
|
||||||
|
this.datasourceObjId = datasourceObjId;
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,10 +285,12 @@ public class FileSize implements AutopsyVisitableItem {
|
|||||||
* @param filter
|
* @param filter
|
||||||
* @param o Observable that provides updates when events are
|
* @param o Observable that provides updates when events are
|
||||||
* fired
|
* fired
|
||||||
|
* @param datasourceObjId filter by data source, if configured in user preferences
|
||||||
*/
|
*/
|
||||||
FileSizeNode(SleuthkitCase skCase, FileSizeFilter filter, Observable o) {
|
FileSizeNode(SleuthkitCase skCase, FileSizeFilter filter, Observable o, long datasourceObjId) {
|
||||||
super(Children.create(new FileSizeChildren(filter, skCase, o), true), Lookups.singleton(filter.getDisplayName()));
|
super(Children.create(new FileSizeChildren(filter, skCase, o, datasourceObjId), true), Lookups.singleton(filter.getDisplayName()));
|
||||||
this.filter = filter;
|
this.filter = filter;
|
||||||
|
this.datasourceObjId = datasourceObjId;
|
||||||
init();
|
init();
|
||||||
o.addObserver(new FileSizeNodeObserver());
|
o.addObserver(new FileSizeNodeObserver());
|
||||||
}
|
}
|
||||||
@ -309,7 +324,7 @@ public class FileSize implements AutopsyVisitableItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void updateDisplayName() {
|
private void updateDisplayName() {
|
||||||
final long numVisibleChildren = FileSizeChildren.calculateItems(skCase, filter);
|
final long numVisibleChildren = FileSizeChildren.calculateItems(skCase, filter, datasourceObjId);
|
||||||
super.setDisplayName(filter.getDisplayName() + " (" + numVisibleChildren + ")");
|
super.setDisplayName(filter.getDisplayName() + " (" + numVisibleChildren + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -349,6 +364,7 @@ public class FileSize implements AutopsyVisitableItem {
|
|||||||
private final SleuthkitCase skCase;
|
private final SleuthkitCase skCase;
|
||||||
private final FileSizeFilter filter;
|
private final FileSizeFilter filter;
|
||||||
private final Observable notifier;
|
private final Observable notifier;
|
||||||
|
private final long datasourceObjId;
|
||||||
private static final Logger logger = Logger.getLogger(FileSizeChildren.class.getName());
|
private static final Logger logger = Logger.getLogger(FileSizeChildren.class.getName());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -358,10 +374,12 @@ public class FileSize implements AutopsyVisitableItem {
|
|||||||
* @param o Observable that provides updates when new files are
|
* @param o Observable that provides updates when new files are
|
||||||
* added to case
|
* added to case
|
||||||
*/
|
*/
|
||||||
FileSizeChildren(FileSizeFilter filter, SleuthkitCase skCase, Observable o) {
|
FileSizeChildren(FileSizeFilter filter, SleuthkitCase skCase, Observable o, long dsObjId) {
|
||||||
this.skCase = skCase;
|
this.skCase = skCase;
|
||||||
this.filter = filter;
|
this.filter = filter;
|
||||||
this.notifier = o;
|
this.notifier = o;
|
||||||
|
this.datasourceObjId = dsObjId;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -395,7 +413,7 @@ public class FileSize implements AutopsyVisitableItem {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String makeQuery(FileSizeFilter filter) {
|
private static String makeQuery(FileSizeFilter filter, long filteringDSObjId) {
|
||||||
String query;
|
String query;
|
||||||
switch (filter) {
|
switch (filter) {
|
||||||
case SIZE_50_200:
|
case SIZE_50_200:
|
||||||
@ -427,6 +445,11 @@ public class FileSize implements AutopsyVisitableItem {
|
|||||||
query += " AND (type != " + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.getFileType() + ")"; //NON-NLS
|
query += " AND (type != " + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.getFileType() + ")"; //NON-NLS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// filter by datasource if indicated in user preferences
|
||||||
|
if (UserPreferences.groupItemsInTreeByDatasource()) {
|
||||||
|
query += " AND data_source_obj_id = " + filteringDSObjId;
|
||||||
|
}
|
||||||
|
|
||||||
return query;
|
return query;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -434,7 +457,7 @@ public class FileSize implements AutopsyVisitableItem {
|
|||||||
List<AbstractFile> ret = new ArrayList<>();
|
List<AbstractFile> ret = new ArrayList<>();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String query = makeQuery(filter);
|
String query = makeQuery(filter, datasourceObjId);
|
||||||
|
|
||||||
ret = skCase.findAllFilesWhere(query);
|
ret = skCase.findAllFilesWhere(query);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -449,9 +472,9 @@ public class FileSize implements AutopsyVisitableItem {
|
|||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
static long calculateItems(SleuthkitCase sleuthkitCase, FileSizeFilter filter) {
|
static long calculateItems(SleuthkitCase sleuthkitCase, FileSizeFilter filter, long datasourceObjId) {
|
||||||
try {
|
try {
|
||||||
return sleuthkitCase.countFilesWhere(makeQuery(filter));
|
return sleuthkitCase.countFilesWhere(makeQuery(filter, datasourceObjId));
|
||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
logger.log(Level.SEVERE, "Error getting files by size search view count", ex); //NON-NLS
|
logger.log(Level.SEVERE, "Error getting files by size search view count", ex); //NON-NLS
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -72,11 +72,18 @@ public final class FileTypes implements AutopsyVisitableItem {
|
|||||||
|
|
||||||
private final SleuthkitCase skCase;
|
private final SleuthkitCase skCase;
|
||||||
|
|
||||||
|
private final long datasourceObjId;
|
||||||
|
|
||||||
FileTypes(SleuthkitCase skCase) {
|
FileTypes(SleuthkitCase skCase) {
|
||||||
this.skCase = skCase;
|
this(skCase, 0);
|
||||||
updateShowCounts();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FileTypes(SleuthkitCase skCase, long dsObjId) {
|
||||||
|
this.skCase = skCase;
|
||||||
|
this.datasourceObjId = dsObjId;
|
||||||
|
updateShowCounts();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> T accept(AutopsyItemVisitor<T> v) {
|
public <T> T accept(AutopsyItemVisitor<T> v) {
|
||||||
return v.visit(this);
|
return v.visit(this);
|
||||||
@ -86,6 +93,9 @@ public final class FileTypes implements AutopsyVisitableItem {
|
|||||||
return skCase;
|
return skCase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
long filteringDataSourceObjId() {
|
||||||
|
return this.datasourceObjId;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Check the db to determine if the nodes should show child counts.
|
* Check the db to determine if the nodes should show child counts.
|
||||||
*/
|
*/
|
||||||
|
@ -69,6 +69,10 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
|
|||||||
return v.visit(this);
|
return v.visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
long filteringDataSourceObjId() {
|
||||||
|
return typesRoot.filteringDataSourceObjId();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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.
|
||||||
@ -153,7 +157,7 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
|
|||||||
* @param o Observable that was created by a higher-level node that
|
* @param o Observable that was created by a higher-level node that
|
||||||
* 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 /*, long datasourceObjId */) {
|
||||||
|
|
||||||
super(Children.create(new FileTypesByExtNodeChildren(skCase, filter, o), true),
|
super(Children.create(new FileTypesByExtNodeChildren(skCase, filter, o), true),
|
||||||
Lookups.singleton(filter == null ? FNAME : filter.getDisplayName()));
|
Lookups.singleton(filter == null ? FNAME : filter.getDisplayName()));
|
||||||
@ -359,6 +363,9 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
|
|||||||
+ (UserPreferences.hideKnownFilesInViewsTree()
|
+ (UserPreferences.hideKnownFilesInViewsTree()
|
||||||
? " AND (known IS NULL OR known != " + TskData.FileKnown.KNOWN.getFileKnownValue() + ")"
|
? " AND (known IS NULL OR known != " + TskData.FileKnown.KNOWN.getFileKnownValue() + ")"
|
||||||
: " ")
|
: " ")
|
||||||
|
+ (UserPreferences.groupItemsInTreeByDatasource()
|
||||||
|
? " AND data_source_obj_id = " + FileTypesByExtension.this.filteringDataSourceObjId()
|
||||||
|
: " ")
|
||||||
+ " AND (extension IN (" + filter.getFilter().stream()
|
+ " AND (extension IN (" + filter.getFilter().stream()
|
||||||
.map(String::toLowerCase)
|
.map(String::toLowerCase)
|
||||||
.map(s -> "'"+StringUtils.substringAfter(s, ".")+"'")
|
.map(s -> "'"+StringUtils.substringAfter(s, ".")+"'")
|
||||||
|
@ -42,6 +42,7 @@ import org.openide.util.NbBundle;
|
|||||||
import org.openide.util.lookup.Lookups;
|
import org.openide.util.lookup.Lookups;
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||||
|
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||||
import static org.sleuthkit.autopsy.core.UserPreferences.hideKnownFilesInViewsTree;
|
import static org.sleuthkit.autopsy.core.UserPreferences.hideKnownFilesInViewsTree;
|
||||||
import static org.sleuthkit.autopsy.core.UserPreferences.hideSlackFilesInViewsTree;
|
import static org.sleuthkit.autopsy.core.UserPreferences.hideSlackFilesInViewsTree;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
@ -91,15 +92,16 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
|
|||||||
* @return The base expression to be used in the where clause of queries for
|
* @return The base expression to be used in the where clause of queries for
|
||||||
* files by mime type.
|
* files by mime type.
|
||||||
*/
|
*/
|
||||||
static private String createBaseWhereExpr() {
|
private String createBaseWhereExpr() {
|
||||||
return "(dir_type = " + TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue() + ")"
|
return "(dir_type = " + TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue() + ")"
|
||||||
+ " AND (type IN ("
|
+ " AND (type IN ("
|
||||||
+ TskData.TSK_DB_FILES_TYPE_ENUM.FS.ordinal() + ","
|
+ TskData.TSK_DB_FILES_TYPE_ENUM.FS.ordinal() + ","
|
||||||
+ TskData.TSK_DB_FILES_TYPE_ENUM.CARVED.ordinal() + ","
|
+ TskData.TSK_DB_FILES_TYPE_ENUM.CARVED.ordinal() + ","
|
||||||
+ TskData.TSK_DB_FILES_TYPE_ENUM.DERIVED.ordinal() + ","
|
+ TskData.TSK_DB_FILES_TYPE_ENUM.DERIVED.ordinal() + ","
|
||||||
+ TskData.TSK_DB_FILES_TYPE_ENUM.LOCAL.ordinal()
|
+ TskData.TSK_DB_FILES_TYPE_ENUM.LOCAL.ordinal()
|
||||||
+ (hideSlackFilesInViewsTree() ? "" : ("," + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.ordinal()))
|
+ (hideSlackFilesInViewsTree() ? "" : ("," + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.ordinal()))
|
||||||
+ "))"
|
+ "))"
|
||||||
|
+ ( UserPreferences.groupItemsInTreeByDatasource() ? " AND data_source_obj_id = " + this.filteringDataSourceObjId() : " ")
|
||||||
+ (hideKnownFilesInViewsTree() ? (" AND (known IS NULL OR known != " + TskData.FileKnown.KNOWN.getFileKnownValue() + ")") : "");
|
+ (hideKnownFilesInViewsTree() ? (" AND (known IS NULL OR known != " + TskData.FileKnown.KNOWN.getFileKnownValue() + ")") : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,6 +190,10 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
|
|||||||
return v.visit(this);
|
return v.visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
long filteringDataSourceObjId() {
|
||||||
|
return typesRoot.filteringDataSourceObjId();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to check if the node in question is a ByMimeTypeNode which is
|
* Method to check if the node in question is a ByMimeTypeNode which is
|
||||||
* empty.
|
* empty.
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011-2014 Basis Technology Corp.
|
* Copyright 2011-2018 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -22,6 +22,8 @@ import java.util.Arrays;
|
|||||||
import org.openide.nodes.Sheet;
|
import org.openide.nodes.Sheet;
|
||||||
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.core.UserPreferences;
|
||||||
|
import org.sleuthkit.autopsy.datamodel.DataSourcesLayerChildren.SubtreeEnum;
|
||||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -34,14 +36,19 @@ public class ViewsNode extends DisplayableItemNode {
|
|||||||
public static final String NAME = NbBundle.getMessage(ViewsNode.class, "ViewsNode.name.text");
|
public static final String NAME = NbBundle.getMessage(ViewsNode.class, "ViewsNode.name.text");
|
||||||
|
|
||||||
public ViewsNode(SleuthkitCase sleuthkitCase) {
|
public ViewsNode(SleuthkitCase sleuthkitCase) {
|
||||||
super(new RootContentChildren(Arrays.asList(
|
|
||||||
new FileTypes(sleuthkitCase),
|
super( UserPreferences.groupItemsInTreeByDatasource() ?
|
||||||
// June '15: Recent Files was removed because it was not useful w/out filtering
|
new DataSourcesLayerChildren(sleuthkitCase, SubtreeEnum.VIEWS) :
|
||||||
// add it back in if we can filter the results to a more managable size.
|
new RootContentChildren(Arrays.asList(
|
||||||
// new RecentFiles(sleuthkitCase),
|
new FileTypes(sleuthkitCase),
|
||||||
new DeletedContent(sleuthkitCase),
|
// June '15: Recent Files was removed because it was not useful w/out filtering
|
||||||
new FileSize(sleuthkitCase))),
|
// add it back in if we can filter the results to a more managable size.
|
||||||
Lookups.singleton(NAME));
|
// new RecentFiles(sleuthkitCase),
|
||||||
|
new DeletedContent(sleuthkitCase),
|
||||||
|
new FileSize(sleuthkitCase))
|
||||||
|
),
|
||||||
|
Lookups.singleton(NAME)
|
||||||
|
);
|
||||||
setName(NAME);
|
setName(NAME);
|
||||||
setDisplayName(NAME);
|
setDisplayName(NAME);
|
||||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/views.png"); //NON-NLS
|
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/views.png"); //NON-NLS
|
||||||
|
@ -119,3 +119,4 @@ AddExternalViewerRulePanel.browseButton.text=Browse
|
|||||||
AddExternalViewerRulePanel.exePathTextField.text=
|
AddExternalViewerRulePanel.exePathTextField.text=
|
||||||
AddExternalViewerRulePanel.exePathLabel.text=Path of the program to use for files with this type or extension
|
AddExternalViewerRulePanel.exePathLabel.text=Path of the program to use for files with this type or extension
|
||||||
AddExternalViewerRulePanel.extRadioButton.text=Extension
|
AddExternalViewerRulePanel.extRadioButton.text=Extension
|
||||||
|
DirectoryTreeTopComponent.groupByDatasourceCheckBox.text=Group by Data Source
|
||||||
|
@ -16,14 +16,17 @@
|
|||||||
<Layout>
|
<Layout>
|
||||||
<DimensionLayout dim="0">
|
<DimensionLayout dim="0">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Component id="treeView" alignment="0" pref="262" max="32767" attributes="0"/>
|
<Component id="treeView" alignment="0" max="32767" attributes="0"/>
|
||||||
<Group type="102" attributes="0">
|
<Group type="102" alignment="0" attributes="0">
|
||||||
<EmptySpace min="-2" pref="5" max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Component id="backButton" min="-2" pref="23" max="-2" attributes="0"/>
|
<Component id="backButton" min="-2" pref="23" max="-2" attributes="0"/>
|
||||||
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
||||||
<Component id="forwardButton" min="-2" pref="23" max="-2" attributes="0"/>
|
<Component id="forwardButton" min="-2" pref="23" max="-2" attributes="0"/>
|
||||||
<EmptySpace pref="46" max="32767" attributes="0"/>
|
<EmptySpace pref="65" max="32767" attributes="0"/>
|
||||||
<Component id="showRejectedCheckBox" min="-2" max="-2" attributes="0"/>
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Component id="showRejectedCheckBox" min="-2" max="-2" attributes="0"/>
|
||||||
|
<Component id="groupByDatasourceCheckBox" min="-2" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
@ -31,14 +34,23 @@
|
|||||||
<DimensionLayout dim="1">
|
<DimensionLayout dim="1">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Group type="102" alignment="0" attributes="0">
|
<Group type="102" alignment="0" attributes="0">
|
||||||
<EmptySpace min="-2" pref="5" max="-2" attributes="0"/>
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Group type="103" groupAlignment="1" attributes="0">
|
<Group type="102" attributes="0">
|
||||||
<Component id="forwardButton" min="-2" pref="26" max="-2" attributes="1"/>
|
<EmptySpace min="-2" pref="5" max="-2" attributes="0"/>
|
||||||
<Component id="backButton" min="-2" pref="26" max="-2" attributes="1"/>
|
<Component id="showRejectedCheckBox" min="-2" max="-2" attributes="0"/>
|
||||||
<Component id="showRejectedCheckBox" min="-2" max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Component id="groupByDatasourceCheckBox" min="-2" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
<Group type="102" alignment="0" attributes="0">
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Group type="103" groupAlignment="1" attributes="0">
|
||||||
|
<Component id="forwardButton" min="-2" pref="26" max="-2" attributes="1"/>
|
||||||
|
<Component id="backButton" min="-2" pref="26" max="-2" attributes="1"/>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Component id="treeView" pref="854" max="32767" attributes="0"/>
|
<Component id="treeView" pref="838" max="32767" attributes="0"/>
|
||||||
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
@ -130,5 +142,15 @@
|
|||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
</Component>
|
</Component>
|
||||||
|
<Component class="javax.swing.JCheckBox" name="groupByDatasourceCheckBox">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/directorytree/Bundle.properties" key="DirectoryTreeTopComponent.groupByDatasourceCheckBox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<Events>
|
||||||
|
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="groupByDatasourceCheckBoxActionPerformed"/>
|
||||||
|
</Events>
|
||||||
|
</Component>
|
||||||
</SubComponents>
|
</SubComponents>
|
||||||
</Form>
|
</Form>
|
||||||
|
@ -141,6 +141,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
switch (evt.getKey()) {
|
switch (evt.getKey()) {
|
||||||
case UserPreferences.HIDE_KNOWN_FILES_IN_DATA_SRCS_TREE:
|
case UserPreferences.HIDE_KNOWN_FILES_IN_DATA_SRCS_TREE:
|
||||||
case UserPreferences.HIDE_SLACK_FILES_IN_DATA_SRCS_TREE:
|
case UserPreferences.HIDE_SLACK_FILES_IN_DATA_SRCS_TREE:
|
||||||
|
case UserPreferences.GROUP_ITEMS_IN_TREE_BY_DATASOURCE:
|
||||||
refreshContentTreeSafe();
|
refreshContentTreeSafe();
|
||||||
break;
|
break;
|
||||||
case UserPreferences.HIDE_KNOWN_FILES_IN_VIEWS_TREE:
|
case UserPreferences.HIDE_KNOWN_FILES_IN_VIEWS_TREE:
|
||||||
@ -181,6 +182,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
backButton = new javax.swing.JButton();
|
backButton = new javax.swing.JButton();
|
||||||
forwardButton = new javax.swing.JButton();
|
forwardButton = new javax.swing.JButton();
|
||||||
showRejectedCheckBox = new javax.swing.JCheckBox();
|
showRejectedCheckBox = new javax.swing.JCheckBox();
|
||||||
|
groupByDatasourceCheckBox = new javax.swing.JCheckBox();
|
||||||
|
|
||||||
treeView.setBorder(null);
|
treeView.setBorder(null);
|
||||||
|
|
||||||
@ -218,30 +220,45 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
|
|
||||||
org.openide.awt.Mnemonics.setLocalizedText(showRejectedCheckBox, org.openide.util.NbBundle.getMessage(DirectoryTreeTopComponent.class, "DirectoryTreeTopComponent.showRejectedCheckBox.text")); // NOI18N
|
org.openide.awt.Mnemonics.setLocalizedText(showRejectedCheckBox, org.openide.util.NbBundle.getMessage(DirectoryTreeTopComponent.class, "DirectoryTreeTopComponent.showRejectedCheckBox.text")); // NOI18N
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(groupByDatasourceCheckBox, org.openide.util.NbBundle.getMessage(DirectoryTreeTopComponent.class, "DirectoryTreeTopComponent.groupByDatasourceCheckBox.text")); // NOI18N
|
||||||
|
groupByDatasourceCheckBox.addActionListener(new java.awt.event.ActionListener() {
|
||||||
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
|
groupByDatasourceCheckBoxActionPerformed(evt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||||
this.setLayout(layout);
|
this.setLayout(layout);
|
||||||
layout.setHorizontalGroup(
|
layout.setHorizontalGroup(
|
||||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addComponent(treeView, javax.swing.GroupLayout.DEFAULT_SIZE, 262, Short.MAX_VALUE)
|
.addComponent(treeView)
|
||||||
.addGroup(layout.createSequentialGroup()
|
.addGroup(layout.createSequentialGroup()
|
||||||
.addGap(5, 5, 5)
|
.addContainerGap()
|
||||||
.addComponent(backButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
|
.addComponent(backButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
.addGap(0, 0, 0)
|
.addGap(0, 0, 0)
|
||||||
.addComponent(forwardButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
|
.addComponent(forwardButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 46, Short.MAX_VALUE)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 65, Short.MAX_VALUE)
|
||||||
.addComponent(showRejectedCheckBox)
|
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addComponent(showRejectedCheckBox)
|
||||||
|
.addComponent(groupByDatasourceCheckBox))
|
||||||
.addContainerGap())
|
.addContainerGap())
|
||||||
);
|
);
|
||||||
layout.setVerticalGroup(
|
layout.setVerticalGroup(
|
||||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addGroup(layout.createSequentialGroup()
|
.addGroup(layout.createSequentialGroup()
|
||||||
.addGap(5, 5, 5)
|
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
.addGroup(layout.createSequentialGroup()
|
||||||
.addComponent(forwardButton, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
|
.addGap(5, 5, 5)
|
||||||
.addComponent(backButton, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
|
.addComponent(showRejectedCheckBox)
|
||||||
.addComponent(showRejectedCheckBox))
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
|
.addComponent(groupByDatasourceCheckBox))
|
||||||
|
.addGroup(layout.createSequentialGroup()
|
||||||
|
.addContainerGap()
|
||||||
|
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||||
|
.addComponent(forwardButton, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
|
.addComponent(backButton, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE))))
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addComponent(treeView, javax.swing.GroupLayout.DEFAULT_SIZE, 854, Short.MAX_VALUE)
|
.addComponent(treeView, javax.swing.GroupLayout.DEFAULT_SIZE, 838, Short.MAX_VALUE)
|
||||||
.addGap(0, 0, 0))
|
.addGap(0, 0, 0))
|
||||||
);
|
);
|
||||||
}// </editor-fold>//GEN-END:initComponents
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
@ -295,9 +312,14 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
this.setCursor(null);
|
this.setCursor(null);
|
||||||
}//GEN-LAST:event_forwardButtonActionPerformed
|
}//GEN-LAST:event_forwardButtonActionPerformed
|
||||||
|
|
||||||
|
private void groupByDatasourceCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_groupByDatasourceCheckBoxActionPerformed
|
||||||
|
UserPreferences.setGroupItemsInTreeByDatasource(this.groupByDatasourceCheckBox.isSelected());
|
||||||
|
}//GEN-LAST:event_groupByDatasourceCheckBoxActionPerformed
|
||||||
|
|
||||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
private javax.swing.JButton backButton;
|
private javax.swing.JButton backButton;
|
||||||
private javax.swing.JButton forwardButton;
|
private javax.swing.JButton forwardButton;
|
||||||
|
private javax.swing.JCheckBox groupByDatasourceCheckBox;
|
||||||
private javax.swing.JCheckBox showRejectedCheckBox;
|
private javax.swing.JCheckBox showRejectedCheckBox;
|
||||||
private javax.swing.JScrollPane treeView;
|
private javax.swing.JScrollPane treeView;
|
||||||
// End of variables declaration//GEN-END:variables
|
// End of variables declaration//GEN-END:variables
|
||||||
@ -429,6 +451,8 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
showRejectedCheckBox.setAction(accounts.newToggleShowRejectedAction());
|
showRejectedCheckBox.setAction(accounts.newToggleShowRejectedAction());
|
||||||
showRejectedCheckBox.setSelected(false);
|
showRejectedCheckBox.setSelected(false);
|
||||||
|
|
||||||
|
groupByDatasourceCheckBox.setSelected(UserPreferences.groupItemsInTreeByDatasource());
|
||||||
|
|
||||||
Node views = rootChildren.findChild(ViewsNode.NAME);
|
Node views = rootChildren.findChild(ViewsNode.NAME);
|
||||||
Arrays.stream(views.getChildren().getNodes()).forEach(tree::expandNode);
|
Arrays.stream(views.getChildren().getNodes()).forEach(tree::expandNode);
|
||||||
tree.collapseNode(views);
|
tree.collapseNode(views);
|
||||||
@ -772,7 +796,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
* Refresh the content node part of the dir tree safely in the EDT thread
|
* Refresh the content node part of the dir tree safely in the EDT thread
|
||||||
*/
|
*/
|
||||||
public void refreshContentTreeSafe() {
|
public void refreshContentTreeSafe() {
|
||||||
SwingUtilities.invokeLater(this::refreshDataSourceTree);
|
SwingUtilities.invokeLater(this::refreshTree);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -793,6 +817,18 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
setSelectedNode(selectedPath, DataSourcesNode.NAME);
|
setSelectedNode(selectedPath, DataSourcesNode.NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refreshes the entire tree
|
||||||
|
*/
|
||||||
|
private void refreshTree() {
|
||||||
|
Node selectedNode = getSelectedNode();
|
||||||
|
final String[] selectedPath = NodeOp.createPath(selectedNode, em.getRootContext());
|
||||||
|
|
||||||
|
contentChildren.refreshContentKeys();
|
||||||
|
|
||||||
|
setSelectedNode(selectedPath, DataSourcesNode.NAME);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the selected node using a path to a previously selected node.
|
* Set the selected node using a path to a previously selected node.
|
||||||
*
|
*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user