Autopsy  4.20.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
DeletedContent.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2011-2019 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.autopsy.datamodel;
20 
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;
29 import java.util.Set;
30 import java.util.logging.Level;
31 import org.openide.nodes.AbstractNode;
32 import org.openide.nodes.ChildFactory;
33 import org.openide.nodes.Children;
34 import org.openide.nodes.Node;
35 import org.openide.nodes.Sheet;
36 import org.openide.util.NbBundle;
37 import org.openide.util.lookup.Lookups;
43 import org.sleuthkit.datamodel.AbstractFile;
44 import org.sleuthkit.datamodel.Content;
45 import org.sleuthkit.datamodel.ContentVisitor;
46 import org.sleuthkit.datamodel.Directory;
47 import org.sleuthkit.datamodel.File;
48 import org.sleuthkit.datamodel.FsContent;
49 import org.sleuthkit.datamodel.LayoutFile;
50 import org.sleuthkit.datamodel.SleuthkitCase;
51 import org.sleuthkit.datamodel.TskCoreException;
52 import org.sleuthkit.datamodel.TskData;
53 import org.sleuthkit.datamodel.VirtualDirectory;
54 
58 public class DeletedContent implements AutopsyVisitableItem {
59 
60  private SleuthkitCase skCase;
61  private final long filteringDSObjId; // 0 if not filtering/grouping by data source
62 
63  @NbBundle.Messages({"DeletedContent.fsDelFilter.text=File System",
64  "DeletedContent.allDelFilter.text=All"})
65  public enum DeletedContentFilter implements AutopsyVisitableItem {
66 
67  FS_DELETED_FILTER(0, "FS_DELETED_FILTER", //NON-NLS
68  Bundle.DeletedContent_fsDelFilter_text()),
69  ALL_DELETED_FILTER(1, "ALL_DELETED_FILTER", //NON-NLS
70  Bundle.DeletedContent_allDelFilter_text());
71 
72  private int id;
73  private String name;
74  private String displayName;
75 
76  private DeletedContentFilter(int id, String name, String displayName) {
77  this.id = id;
78  this.name = name;
79  this.displayName = displayName;
80 
81  }
82 
83  public String getName() {
84  return this.name;
85  }
86 
87  public int getId() {
88  return this.id;
89  }
90 
91  public String getDisplayName() {
92  return this.displayName;
93  }
94 
95  @Override
96  public <T> T accept(AutopsyItemVisitor<T> visitor) {
97  return visitor.visit(this);
98  }
99  }
100 
101  public DeletedContent(SleuthkitCase skCase) {
102  this(skCase, 0);
103  }
104 
105  public DeletedContent(SleuthkitCase skCase, long dsObjId) {
106  this.skCase = skCase;
107  this.filteringDSObjId = dsObjId;
108  }
109 
110  long filteringDataSourceObjId() {
111  return this.filteringDSObjId;
112  }
113 
114  @Override
115  public <T> T accept(AutopsyItemVisitor<T> visitor) {
116  return visitor.visit(this);
117  }
118 
119  public SleuthkitCase getSleuthkitCase() {
120  return this.skCase;
121  }
122 
123  public static class DeletedContentsNode extends DisplayableItemNode {
124 
125  @NbBundle.Messages("DeletedContent.deletedContentsNode.name=Deleted Files")
126  private static final String NAME = Bundle.DeletedContent_deletedContentsNode_name();
127 
128  DeletedContentsNode(SleuthkitCase skCase, long datasourceObjId) {
129  super(Children.create(new DeletedContentsChildren(skCase, datasourceObjId), true), Lookups.singleton(NAME));
130  super.setName(NAME);
131  super.setDisplayName(NAME);
132  this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-icon-deleted.png"); //NON-NLS
133  }
134 
135  @Override
136  public boolean isLeafTypeNode() {
137  return false;
138  }
139 
140  @Override
141  public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
142  return visitor.visit(this);
143  }
144 
145  @Override
146  @NbBundle.Messages({
147  "DeletedContent.createSheet.name.displayName=Name",
148  "DeletedContent.createSheet.name.desc=no description"})
149  protected Sheet createSheet() {
150  Sheet sheet = super.createSheet();
151  Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
152  if (sheetSet == null) {
153  sheetSet = Sheet.createPropertiesSet();
154  sheet.put(sheetSet);
155  }
156 
157  sheetSet.put(new NodeProperty<>("Name", //NON-NLS
158  Bundle.DeletedContent_createSheet_name_displayName(),
159  Bundle.DeletedContent_createSheet_name_desc(),
160  NAME));
161  return sheet;
162  }
163 
164  @Override
165  public String getItemType() {
166  return getClass().getName();
167  }
168  }
169 
170  public static class DeletedContentsChildren extends ChildFactory<DeletedContent.DeletedContentFilter> {
171 
172  private SleuthkitCase skCase;
173  private Observable notifier;
174  private final long datasourceObjId;
175  // true if we have already told user that not all files will be shown
176  private static volatile boolean maxFilesDialogShown = false;
177 
178  public DeletedContentsChildren(SleuthkitCase skCase, long dsObjId) {
179  this.skCase = skCase;
180  this.datasourceObjId = dsObjId;
181  this.notifier = new DeletedContentsChildrenObservable();
182  }
183 
188  private static final class DeletedContentsChildrenObservable extends Observable {
189 
190  private static final Set<Case.Events> CASE_EVENTS_OF_INTEREST = EnumSet.of(
193  );
195  private static final Set<IngestManager.IngestModuleEvent> INGEST_MODULE_EVENTS_OF_INTEREST = EnumSet.of(CONTENT_CHANGED);
196 
201  }
202 
203  private void removeListeners() {
204  deleteObservers();
208  }
209 
210  private final PropertyChangeListener pcl = (PropertyChangeEvent evt) -> {
211  String eventType = evt.getPropertyName();
212  if (eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())) {
220  try {
222  // new file was added
223  // @@@ COULD CHECK If the new file is deleted before notifying...
224  update();
225  } catch (NoCurrentCaseException notUsed) {
229  }
230  } else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
231  || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())
232  || eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) {
239  try {
241  update();
242  } catch (NoCurrentCaseException notUsed) {
246  }
247  } else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
248  // case was closed. Remove listeners so that we don't get called with a stale case handle
249  if (evt.getNewValue() == null) {
250  removeListeners();
251  }
252  maxFilesDialogShown = false;
253  }
254  };
255 
256  private void update() {
257  setChanged();
258  notifyObservers();
259  }
260  }
261 
262  @Override
263 
264  protected boolean createKeys(List<DeletedContent.DeletedContentFilter> list) {
265  list.addAll(Arrays.asList(DeletedContent.DeletedContentFilter.values()));
266  return true;
267  }
268 
269  @Override
271  return new DeletedContentNode(skCase, key, notifier, datasourceObjId);
272  }
273 
275 
277  private final long datasourceObjId;
278 
279  // Use version that has observer for updates
280  @Deprecated
281  DeletedContentNode(SleuthkitCase skCase, DeletedContent.DeletedContentFilter filter, long dsObjId) {
282  super(Children.create(new DeletedContentChildren(filter, skCase, null, dsObjId), true), Lookups.singleton(filter.getDisplayName()));
283  this.filter = filter;
284  this.datasourceObjId = dsObjId;
285  init();
286  }
287 
288  DeletedContentNode(SleuthkitCase skCase, DeletedContent.DeletedContentFilter filter, Observable o, long dsObjId) {
289  super(Children.create(new DeletedContentChildren(filter, skCase, o, dsObjId), true), Lookups.singleton(filter.getDisplayName()));
290  this.filter = filter;
291  this.datasourceObjId = dsObjId;
292  init();
293  o.addObserver(new DeletedContentNodeObserver());
294  }
295 
296  private void init() {
297  super.setName(filter.getName());
298 
299  String tooltip = filter.getDisplayName();
300  this.setShortDescription(tooltip);
301  this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-icon-deleted.png"); //NON-NLS
303  }
304 
305  // update the display name when new events are fired
306  private class DeletedContentNodeObserver implements Observer {
307 
308  @Override
309  public void update(Observable o, Object arg) {
311  }
312  }
313 
314  private void updateDisplayName() {
315  //get count of children without preloading all children nodes
316  final long count = DeletedContentChildren.calculateItems(skCase, filter, datasourceObjId);
317  //final long count = getChildren().getNodesCount(true);
318  super.setDisplayName(filter.getDisplayName() + " (" + count + ")");
319  }
320 
321  @Override
322  public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
323  return visitor.visit(this);
324  }
325 
326  @Override
327  @NbBundle.Messages({
328  "DeletedContent.createSheet.filterType.displayName=Type",
329  "DeletedContent.createSheet.filterType.desc=no description"})
330  protected Sheet createSheet() {
331  Sheet sheet = super.createSheet();
332  Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
333  if (sheetSet == null) {
334  sheetSet = Sheet.createPropertiesSet();
335  sheet.put(sheetSet);
336  }
337 
338  sheetSet.put(new NodeProperty<>("Type", //NON_NLS
339  Bundle.DeletedContent_createSheet_filterType_displayName(),
340  Bundle.DeletedContent_createSheet_filterType_desc(),
341  filter.getDisplayName()));
342 
343  return sheet;
344  }
345 
346  @Override
347  public boolean isLeafTypeNode() {
348  return true;
349  }
350 
351  @Override
352  public String getItemType() {
357  return DisplayableItemNode.FILE_PARENT_NODE_KEY;
358  }
359  }
360 
361  static class DeletedContentChildren extends BaseChildFactory<AbstractFile> {
362 
363  private final SleuthkitCase skCase;
364  private final DeletedContent.DeletedContentFilter filter;
365  private static final Logger logger = Logger.getLogger(DeletedContentChildren.class.getName());
366 
367  private final Observable notifier;
368  private final long datasourceObjId;
369 
370  DeletedContentChildren(DeletedContent.DeletedContentFilter filter, SleuthkitCase skCase, Observable o, long datasourceObjId) {
371  super(filter.getName(), new ViewsKnownAndSlackFilter<>());
372  this.skCase = skCase;
373  this.filter = filter;
374  this.notifier = o;
375  this.datasourceObjId = datasourceObjId;
376  }
377 
378  private final Observer observer = new DeletedContentChildrenObserver();
379 
380  @Override
381  protected List<AbstractFile> makeKeys() {
382  return runFsQuery();
383  }
384 
385  // Cause refresh of children if there are changes
386  private class DeletedContentChildrenObserver implements Observer {
387 
388  @Override
389  public void update(Observable o, Object arg) {
390  refresh(true);
391  }
392  }
393 
394  @Override
395  protected void onAdd() {
396  if (notifier != null) {
397  notifier.addObserver(observer);
398  }
399  }
400 
401  @Override
402  protected void onRemove() {
403  if (notifier != null) {
404  notifier.deleteObserver(observer);
405  }
406  }
407 
408  static private String makeQuery(DeletedContent.DeletedContentFilter filter, long filteringDSObjId) {
409  String query = "";
410  switch (filter) {
411  case FS_DELETED_FILTER:
412  query = "dir_flags = " + TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC.getValue() //NON-NLS
413  + " AND meta_flags != " + TskData.TSK_FS_META_FLAG_ENUM.ORPHAN.getValue() //NON-NLS
414  + " AND type = " + TskData.TSK_DB_FILES_TYPE_ENUM.FS.getFileType(); //NON-NLS
415 
416  break;
417  case ALL_DELETED_FILTER:
418  query = " ( "
419  + "( "
420  + "(dir_flags = " + TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC.getValue() //NON-NLS
421  + " OR " //NON-NLS
422  + "meta_flags = " + TskData.TSK_FS_META_FLAG_ENUM.ORPHAN.getValue() //NON-NLS
423  + ")"
424  + " AND type = " + TskData.TSK_DB_FILES_TYPE_ENUM.FS.getFileType() //NON-NLS
425  + " )"
426  + " OR type = " + TskData.TSK_DB_FILES_TYPE_ENUM.CARVED.getFileType() //NON-NLS
427  + " OR (dir_flags = " + TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC.getValue()
428  + " AND type = " + TskData.TSK_DB_FILES_TYPE_ENUM.LAYOUT_FILE.getFileType() + " )"
429  + " )";
430  //+ " AND type != " + TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS.getFileType()
431  //+ " AND type != " + TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS.getFileType()
432  //+ " AND type != " + TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS.getFileType()
433  //+ " AND type != " + TskData.TSK_DB_FILES_TYPE_ENUM.DERIVED.getFileType()
434  //+ " AND type != " + TskData.TSK_DB_FILES_TYPE_ENUM.LOCAL.getFileType()
435  //+ " AND type != " + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType();
436  break;
437 
438  default:
439  logger.log(Level.SEVERE, "Unsupported filter type to get deleted content: {0}", filter); //NON-NLS
440 
441  }
442 
443  if (filteringDSObjId > 0) {
444  query += " AND data_source_obj_id = " + filteringDSObjId;
445  }
446  return query;
447  }
448 
449  private List<AbstractFile> runFsQuery() {
450  List<AbstractFile> ret = new ArrayList<>();
451 
452  String query = makeQuery(filter, datasourceObjId);
453  try {
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); //NON-NLS
457  }
458 
459  return ret;
460 
461  }
462 
471  static long calculateItems(SleuthkitCase sleuthkitCase, DeletedContent.DeletedContentFilter filter, long datasourceObjId) {
472  try {
473  return sleuthkitCase.countFilesWhere(makeQuery(filter, datasourceObjId));
474  } catch (TskCoreException ex) {
475  logger.log(Level.SEVERE, "Error getting deleted files search view count", ex); //NON-NLS
476  return 0;
477  }
478  }
479 
480  @Override
481  protected Node createNodeForKey(AbstractFile key) {
482  return key.accept(new ContentVisitor.Default<AbstractNode>() {
483  public FileNode visit(AbstractFile f) {
484  return new FileNode(f, false);
485  }
486 
487  public FileNode visit(FsContent f) {
488  return new FileNode(f, false);
489  }
490 
491  @Override
492  public FileNode visit(LayoutFile f) {
493  return new FileNode(f, false);
494  }
495 
496  @Override
497  public FileNode visit(File f) {
498  return new FileNode(f, false);
499  }
500 
501  @Override
502  public FileNode visit(Directory f) {
503  return new FileNode(f, false);
504  }
505 
506  @Override
507  public FileNode visit(VirtualDirectory f) {
508  return new FileNode(f, false);
509  }
510 
511  @Override
512  protected AbstractNode defaultVisit(Content di) {
513  throw new UnsupportedOperationException("Not supported for this type of Displayable Item: " + di.toString());
514  }
515  });
516  }
517  }
518  }
519 }
void removeIngestModuleEventListener(final PropertyChangeListener listener)
static synchronized IngestManager getInstance()
public< T > T accept(AutopsyItemVisitor< T > visitor)
void removeIngestJobEventListener(final PropertyChangeListener listener)
boolean createKeys(List< DeletedContent.DeletedContentFilter > list)
void addIngestJobEventListener(final PropertyChangeListener listener)
void addIngestModuleEventListener(final PropertyChangeListener listener)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
static void addEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
Definition: Case.java:704
Node createNodeForKey(DeletedContent.DeletedContentFilter key)
static void removeEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
Definition: Case.java:749
DeletedContent(SleuthkitCase skCase, long dsObjId)

Copyright © 2012-2022 Basis Technology. Generated on: Tue Aug 1 2023
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.