Autopsy  4.9.1
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-2018 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.Objects;
28 import java.util.Observable;
29 import java.util.Observer;
30 import java.util.Set;
31 import java.util.logging.Level;
32 import org.openide.nodes.AbstractNode;
33 import org.openide.nodes.ChildFactory;
34 import org.openide.nodes.Children;
35 import org.openide.nodes.Node;
36 import org.openide.nodes.Sheet;
37 import org.openide.util.NbBundle;
38 import org.openide.util.lookup.Lookups;
45 import org.sleuthkit.datamodel.AbstractFile;
46 import org.sleuthkit.datamodel.Content;
47 import org.sleuthkit.datamodel.ContentVisitor;
48 import org.sleuthkit.datamodel.Directory;
49 import org.sleuthkit.datamodel.File;
50 import org.sleuthkit.datamodel.FsContent;
51 import org.sleuthkit.datamodel.LayoutFile;
52 import org.sleuthkit.datamodel.SleuthkitCase;
53 import org.sleuthkit.datamodel.TskCoreException;
54 import org.sleuthkit.datamodel.TskData;
55 import org.sleuthkit.datamodel.VirtualDirectory;
56 
60 public class DeletedContent implements AutopsyVisitableItem {
61 
62  private SleuthkitCase skCase;
63  private final long datasourceObjId;
64 
65  @NbBundle.Messages({"DeletedContent.fsDelFilter.text=File System",
66  "DeletedContent.allDelFilter.text=All"})
67  public enum DeletedContentFilter implements AutopsyVisitableItem {
68 
69  FS_DELETED_FILTER(0, "FS_DELETED_FILTER", //NON-NLS
70  Bundle.DeletedContent_fsDelFilter_text()),
71  ALL_DELETED_FILTER(1, "ALL_DELETED_FILTER", //NON-NLS
72  Bundle.DeletedContent_allDelFilter_text());
73 
74  private int id;
75  private String name;
76  private String displayName;
77 
78  private DeletedContentFilter(int id, String name, String displayName) {
79  this.id = id;
80  this.name = name;
81  this.displayName = displayName;
82 
83  }
84 
85  public String getName() {
86  return this.name;
87  }
88 
89  public int getId() {
90  return this.id;
91  }
92 
93  public String getDisplayName() {
94  return this.displayName;
95  }
96 
97  @Override
98  public <T> T accept(AutopsyItemVisitor<T> visitor) {
99  return visitor.visit(this);
100  }
101  }
102 
103  public DeletedContent(SleuthkitCase skCase) {
104  this(skCase, 0);
105  }
106 
107  public DeletedContent(SleuthkitCase skCase, long dsObjId) {
108  this.skCase = skCase;
109  this.datasourceObjId = dsObjId;
110  }
111 
112  long filteringDataSourceObjId() {
113  return this.datasourceObjId;
114  }
115 
116  @Override
117  public <T> T accept(AutopsyItemVisitor<T> visitor) {
118  return visitor.visit(this);
119  }
120 
121  public SleuthkitCase getSleuthkitCase() {
122  return this.skCase;
123  }
124 
125  public static class DeletedContentsNode extends DisplayableItemNode {
126 
127  @NbBundle.Messages("DeletedContent.deletedContentsNode.name=Deleted Files")
128  private static final String NAME = Bundle.DeletedContent_deletedContentsNode_name();
129 
130  DeletedContentsNode(SleuthkitCase skCase, long datasourceObjId) {
131  super(Children.create(new DeletedContentsChildren(skCase, datasourceObjId), true), Lookups.singleton(NAME));
132  super.setName(NAME);
133  super.setDisplayName(NAME);
134  this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-icon-deleted.png"); //NON-NLS
135  }
136 
137  @Override
138  public boolean isLeafTypeNode() {
139  return false;
140  }
141 
142  @Override
143  public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
144  return visitor.visit(this);
145  }
146 
147  @Override
148  @NbBundle.Messages({
149  "DeletedContent.createSheet.name.displayName=Name",
150  "DeletedContent.createSheet.name.desc=no description"})
151  protected Sheet createSheet() {
152  Sheet sheet = super.createSheet();
153  Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
154  if (sheetSet == null) {
155  sheetSet = Sheet.createPropertiesSet();
156  sheet.put(sheetSet);
157  }
158 
159  sheetSet.put(new NodeProperty<>("Name", //NON-NLS
160  Bundle.DeletedContent_createSheet_name_displayName(),
161  Bundle.DeletedContent_createSheet_name_desc(),
162  NAME));
163  return sheet;
164  }
165 
166  @Override
167  public String getItemType() {
168  return getClass().getName();
169  }
170  }
171 
172  public static class DeletedContentsChildren extends ChildFactory<DeletedContent.DeletedContentFilter> {
173 
174  private SleuthkitCase skCase;
175  private Observable notifier;
176  private final long datasourceObjId;
177  // true if we have already told user that not all files will be shown
178  private static volatile boolean maxFilesDialogShown = false;
179 
180  public DeletedContentsChildren(SleuthkitCase skCase, long dsObjId) {
181  this.skCase = skCase;
182  this.datasourceObjId = dsObjId;
183  this.notifier = new DeletedContentsChildrenObservable();
184  }
185 
190  private static final class DeletedContentsChildrenObservable extends Observable {
191 
192  private static final Set<Case.Events> CASE_EVENTS_OF_INTEREST = EnumSet.of(
195  );
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 ChildFactory.Detachable<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  this.skCase = skCase;
372  this.filter = filter;
373  this.notifier = o;
374  this.datasourceObjId = datasourceObjId;
375  }
376 
377  private final Observer observer = new DeletedContentChildrenObserver();
378 
379  // Cause refresh of children if there are changes
380  private class DeletedContentChildrenObserver implements Observer {
381 
382  @Override
383  public void update(Observable o, Object arg) {
384  refresh(true);
385  }
386  }
387 
388  @Override
389  protected void addNotify() {
390  if (notifier != null) {
391  notifier.addObserver(observer);
392  }
393  }
394 
395  @Override
396  protected void removeNotify() {
397  if (notifier != null) {
398  notifier.deleteObserver(observer);
399  }
400  }
401 
402  @Override
403  protected boolean createKeys(List<AbstractFile> list) {
404  list.addAll(runFsQuery());
405  return true;
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  + " )";
428  //+ " AND type != " + TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS.getFileType()
429  //+ " AND type != " + TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS.getFileType()
430  //+ " AND type != " + TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS.getFileType()
431  //+ " AND type != " + TskData.TSK_DB_FILES_TYPE_ENUM.DERIVED.getFileType()
432  //+ " AND type != " + TskData.TSK_DB_FILES_TYPE_ENUM.LOCAL.getFileType()
433  //+ " AND type != " + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType();
434  break;
435 
436  default:
437  logger.log(Level.SEVERE, "Unsupported filter type to get deleted content: {0}", filter); //NON-NLS
438 
439  }
440 
441  if (UserPreferences.hideKnownFilesInViewsTree()) {
442  query += " AND (known != " + TskData.FileKnown.KNOWN.getFileKnownValue() //NON-NLS
443  + " OR known IS NULL)"; //NON-NLS
444  }
445 
446  if (Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true)) {
447  query += " AND data_source_obj_id = " + filteringDSObjId;
448  }
449  return query;
450  }
451 
452  private List<AbstractFile> runFsQuery() {
453  List<AbstractFile> ret = new ArrayList<>();
454 
455  String query = makeQuery(filter, datasourceObjId);
456  try {
457  ret = skCase.findAllFilesWhere(query);
458  } catch (TskCoreException e) {
459  logger.log(Level.SEVERE, "Error getting files for the deleted content view using: " + query, e); //NON-NLS
460  }
461 
462  return ret;
463 
464  }
465 
474  static long calculateItems(SleuthkitCase sleuthkitCase, DeletedContent.DeletedContentFilter filter, long datasourceObjId) {
475  try {
476  return sleuthkitCase.countFilesWhere(makeQuery(filter, datasourceObjId));
477  } catch (TskCoreException ex) {
478  logger.log(Level.SEVERE, "Error getting deleted files search view count", ex); //NON-NLS
479  return 0;
480  }
481  }
482 
483  @Override
484  protected Node createNodeForKey(AbstractFile key) {
485  return key.accept(new ContentVisitor.Default<AbstractNode>() {
486  public FileNode visit(AbstractFile f) {
487  return new FileNode(f, false);
488  }
489 
490  public FileNode visit(FsContent f) {
491  return new FileNode(f, false);
492  }
493 
494  @Override
495  public FileNode visit(LayoutFile f) {
496  return new FileNode(f, false);
497  }
498 
499  @Override
500  public FileNode visit(File f) {
501  return new FileNode(f, false);
502  }
503 
504  @Override
505  public FileNode visit(Directory f) {
506  return new FileNode(f, false);
507  }
508 
509  @Override
510  public FileNode visit(VirtualDirectory f) {
511  return new FileNode(f, false);
512  }
513 
514  @Override
515  protected AbstractNode defaultVisit(Content di) {
516  throw new UnsupportedOperationException("Not supported for this type of Displayable Item: " + di.toString());
517  }
518  });
519  }
520  }
521  }
522 }
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:429
Node createNodeForKey(DeletedContent.DeletedContentFilter key)
static void removeEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
Definition: Case.java:474
DeletedContent(SleuthkitCase skCase, long dsObjId)

Copyright © 2012-2018 Basis Technology. Generated on: Tue Dec 18 2018
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.