19 package org.sleuthkit.autopsy.datamodel;
21 import java.beans.PropertyChangeEvent;
22 import java.beans.PropertyChangeListener;
23 import java.util.ArrayList;
24 import java.util.Arrays;
25 import java.util.EnumSet;
26 import java.util.List;
27 import java.util.Observable;
28 import java.util.Observer;
30 import java.util.logging.Level;
31 import javax.swing.JOptionPane;
32 import javax.swing.SwingUtilities;
33 import org.openide.nodes.AbstractNode;
34 import org.openide.nodes.ChildFactory;
35 import org.openide.nodes.Children;
36 import org.openide.nodes.Node;
37 import org.openide.nodes.Sheet;
38 import org.openide.util.NbBundle;
39 import org.openide.util.lookup.Lookups;
40 import org.openide.windows.WindowManager;
64 @NbBundle.Messages({
"DeletedContent.fsDelFilter.text=File System",
65 "DeletedContent.allDelFilter.text=All"})
68 FS_DELETED_FILTER(0,
"FS_DELETED_FILTER",
69 Bundle.DeletedContent_fsDelFilter_text()),
70 ALL_DELETED_FILTER(1,
"ALL_DELETED_FILTER",
71 Bundle.DeletedContent_allDelFilter_text());
80 this.displayName = displayName;
93 return this.displayName;
108 return v.
visit(
this);
117 @NbBundle.Messages(
"DeletedContent.deletedContentsNode.name=Deleted Files")
118 private static final String
NAME = Bundle.DeletedContent_deletedContentsNode_name();
123 super.setDisplayName(NAME);
124 this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/file-icon-deleted.png");
134 return v.
visit(
this);
139 "DeletedContent.createSheet.name.displayName=Name",
140 "DeletedContent.createSheet.name.desc=no description"})
142 Sheet s = super.createSheet();
143 Sheet.Set ss = s.get(Sheet.PROPERTIES);
145 ss = Sheet.createPropertiesSet();
150 Bundle.DeletedContent_createSheet_name_displayName(),
151 Bundle.DeletedContent_createSheet_name_desc(),
158 return getClass().getName();
197 private final PropertyChangeListener
pcl = (PropertyChangeEvent evt) -> {
198 String eventType = evt.getPropertyName();
213 }
catch (IllegalStateException notUsed) {
230 }
catch (IllegalStateException notUsed) {
237 if (evt.getNewValue() == null) {
240 maxFilesDialogShown =
false;
252 protected boolean createKeys(List<DeletedContent.DeletedContentFilter> list) {
269 super(Children.create(
new DeletedContentChildren(
filter, skCase, null),
true), Lookups.singleton(
filter.getDisplayName()));
275 super(Children.create(
new DeletedContentChildren(
filter, skCase, o),
true), Lookups.singleton(
filter.getDisplayName()));
278 o.addObserver(
new DeletedContentNodeObserver());
282 super.setName(
filter.getName());
284 String tooltip =
filter.getDisplayName();
285 this.setShortDescription(tooltip);
286 this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/file-icon-deleted.png");
294 public void update(Observable o, Object arg) {
301 final long count = DeletedContentChildren.calculateItems(skCase,
filter);
303 super.setDisplayName(
filter.getDisplayName() +
" (" + count +
")");
308 return v.
visit(
this);
313 "DeletedContent.createSheet.filterType.displayName=Type",
314 "DeletedContent.createSheet.filterType.desc=no description"})
316 Sheet s = super.createSheet();
317 Sheet.Set ss = s.get(Sheet.PROPERTIES);
319 ss = Sheet.createPropertiesSet();
324 Bundle.DeletedContent_createSheet_filterType_displayName(),
325 Bundle.DeletedContent_createSheet_filterType_desc(),
326 filter.getDisplayName()));
346 static class DeletedContentChildren
extends ChildFactory.Detachable<AbstractFile> {
348 private final SleuthkitCase
skCase;
351 private static final int MAX_OBJECTS = 10001;
356 this.filter = filter;
360 private final Observer observer =
new DeletedContentChildrenObserver();
366 public void update(Observable o, Object arg) {
372 protected void addNotify() {
373 if (notifier != null) {
374 notifier.addObserver(observer);
379 protected void removeNotify() {
380 if (notifier != null) {
381 notifier.deleteObserver(observer);
386 @NbBundle.Messages({
"# {0} - The deleted files threshold",
387 "DeletedContent.createKeys.maxObjects.msg="
388 +
"There are more Deleted Files than can be displayed."
389 +
" Only the first {0} Deleted Files will be shown."})
390 protected boolean createKeys(List<AbstractFile> list) {
391 List<AbstractFile> queryList = runFsQuery();
392 if (queryList.size() == MAX_OBJECTS) {
393 queryList.remove(queryList.size() - 1);
395 if (maxFilesDialogShown ==
false) {
396 maxFilesDialogShown =
true;
397 SwingUtilities.invokeLater(()
398 -> JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
399 DeletedContent_createKeys_maxObjects_msg(MAX_OBJECTS - 1))
403 list.addAll(queryList);
407 static private String makeQuery(
DeletedContent.DeletedContentFilter filter) {
410 case FS_DELETED_FILTER:
411 query =
"dir_flags = " + TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC.getValue()
412 +
" AND meta_flags != " + TskData.TSK_FS_META_FLAG_ENUM.ORPHAN.getValue()
413 +
" AND type = " + TskData.TSK_DB_FILES_TYPE_ENUM.FS.getFileType();
416 case ALL_DELETED_FILTER:
419 +
"(dir_flags = " + TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC.getValue()
421 +
"meta_flags = " + TskData.TSK_FS_META_FLAG_ENUM.ORPHAN.getValue()
423 +
" AND type = " + TskData.TSK_DB_FILES_TYPE_ENUM.FS.getFileType()
425 +
" OR type = " + TskData.TSK_DB_FILES_TYPE_ENUM.CARVED.getFileType()
436 logger.log(Level.SEVERE,
"Unsupported filter type to get deleted content: {0}", filter);
440 if (UserPreferences.hideKnownFilesInViewsTree()) {
441 query +=
" AND (known != " + TskData.FileKnown.KNOWN.getFileKnownValue()
442 +
" OR known IS NULL)";
445 query +=
" LIMIT " + MAX_OBJECTS;
449 private List<AbstractFile> runFsQuery() {
450 List<AbstractFile> ret =
new ArrayList<>();
452 String query = makeQuery(filter);
454 ret = skCase.findAllFilesWhere(query);
455 }
catch (TskCoreException e) {
456 logger.log(Level.SEVERE,
"Error getting files for the deleted content view using: " + query, e);
471 static long calculateItems(SleuthkitCase sleuthkitCase,
DeletedContent.DeletedContentFilter filter) {
473 return sleuthkitCase.countFilesWhere(makeQuery(filter));
474 }
catch (TskCoreException ex) {
475 logger.log(Level.SEVERE,
"Error getting deleted files search view count", ex);
482 return key.accept(
new ContentVisitor.Default<AbstractNode>() {
483 public FileNode visit(AbstractFile f) {
484 return new FileNode(f, false);
487 public FileNode visit(FsContent f) {
488 return new FileNode(f,
false);
492 public FileNode visit(LayoutFile f) {
493 return new FileNode(f,
false);
497 public FileNode visit(File f) {
498 return new FileNode(f,
false);
502 public FileNode visit(Directory f) {
503 return new FileNode(f,
false);
507 protected AbstractNode defaultVisit(Content di) {
508 throw new UnsupportedOperationException(
"Not supported for this type of Displayable Item: " + di.toString());
void removeIngestModuleEventListener(final PropertyChangeListener listener)
static synchronized IngestManager getInstance()
public< T > T accept(AutopsyItemVisitor< T > v)
void update(Observable o, Object arg)
static volatile boolean maxFilesDialogShown
static final Set< Case.Events > CASE_EVENTS_OF_INTEREST
T visit(DataSourcesNode in)
final DeletedContent.DeletedContentFilter filter
void removeIngestJobEventListener(final PropertyChangeListener listener)
DeletedContentFilter(int id, String name, String displayName)
boolean createKeys(List< DeletedContent.DeletedContentFilter > list)
SleuthkitCase getSleuthkitCase()
void addIngestJobEventListener(final PropertyChangeListener listener)
final PropertyChangeListener pcl
DeletedContentsChildren(SleuthkitCase skCase)
void addIngestModuleEventListener(final PropertyChangeListener listener)
static Case getCurrentCase()
synchronized static Logger getLogger(String name)
static void addEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
Node createNodeForKey(DeletedContent.DeletedContentFilter key)
DeletedContent(SleuthkitCase skCase)
void update(Observable o, Object arg)
static void removeEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)