Autopsy  3.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 2013-2014 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.List;
26 import java.util.Observable;
27 import java.util.Observer;
28 import java.util.logging.Level;
29 import javax.swing.JOptionPane;
30 import javax.swing.SwingUtilities;
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;
38 import org.openide.windows.WindowManager;
52 
56 public class DeletedContent implements AutopsyVisitableItem {
57 
59 
60  public enum DeletedContentFilter implements AutopsyVisitableItem {
61 
62  FS_DELETED_FILTER(0,
63  "FS_DELETED_FILTER", //NON-NLS
64  NbBundle.getMessage(DeletedContent.class, "DeletedContent.fsDelFilter.text")),
65  ALL_DELETED_FILTER(1,
66  "ALL_DELETED_FILTER", //NON-NLS
67  NbBundle.getMessage(DeletedContent.class, "DeletedContent.allDelFilter.text"));
68  private int id;
69  private String name;
70  private String displayName;
71 
72  private DeletedContentFilter(int id, String name, String displayName) {
73  this.id = id;
74  this.name = name;
75  this.displayName = displayName;
76 
77  }
78 
79  public String getName() {
80  return this.name;
81  }
82 
83  public int getId() {
84  return this.id;
85  }
86 
87  public String getDisplayName() {
88  return this.displayName;
89  }
90 
91  @Override
92  public <T> T accept(AutopsyItemVisitor<T> v) {
93  return v.visit(this);
94  }
95  }
96 
97  public DeletedContent(SleuthkitCase skCase) {
98  this.skCase = skCase;
99  }
100 
101  @Override
102  public <T> T accept(AutopsyItemVisitor<T> v) {
103  return v.visit(this);
104  }
105 
107  return this.skCase;
108  }
109 
110  public static class DeletedContentsNode extends DisplayableItemNode {
111 
112  private static final String NAME = NbBundle.getMessage(DeletedContent.class,
113  "DeletedContent.deletedContentsNode.name");
115 
116 
118  super(Children.create(new DeletedContentsChildren(skCase), true), Lookups.singleton(NAME));
119  super.setName(NAME);
120  super.setDisplayName(NAME);
121  this.skCase = skCase;
122  this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-icon-deleted.png"); //NON-NLS
123  }
124 
125  @Override
126  public boolean isLeafTypeNode() {
127  return false;
128  }
129 
130  @Override
131  public <T> T accept(DisplayableItemNodeVisitor<T> v) {
132  return v.visit(this);
133  }
134 
135  @Override
136  protected Sheet createSheet() {
137  Sheet s = super.createSheet();
138  Sheet.Set ss = s.get(Sheet.PROPERTIES);
139  if (ss == null) {
140  ss = Sheet.createPropertiesSet();
141  s.put(ss);
142  }
143 
144  ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "DeletedContent.createSheet.name.name"),
145  NbBundle.getMessage(this.getClass(), "DeletedContent.createSheet.name.displayName"),
146  NbBundle.getMessage(this.getClass(), "DeletedContent.createSheet.name.desc"),
147  NAME));
148  return s;
149  }
150  }
151 
152  public static class DeletedContentsChildren extends ChildFactory<DeletedContent.DeletedContentFilter> {
153 
155  private Observable notifier;
156  // true if we have already told user that not all files will be shown
157  private static boolean maxFilesDialogShown = false;
158 
160  this.skCase = skCase;
161  this.notifier = new DeletedContentsChildrenObservable();
162  }
163 
168  private final class DeletedContentsChildrenObservable extends Observable {
169 
174  }
175 
176  private void removeListeners() {
177  deleteObservers();
181  }
182 
183  private final PropertyChangeListener pcl = new PropertyChangeListener() {
184  @Override
185  public void propertyChange(PropertyChangeEvent evt) {
186  String eventType = evt.getPropertyName();
187 
188  // new file was added
189  if (eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())) {
190  // @@@ COULD CHECK If the new file is deleted before notifying...
191  update();
192  } else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
193  || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) {
194  update();
195  } else if (eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) {
196  update();
197  } else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
198  // case was closed. Remove listeners so that we don't get called with a stale case handle
199  if (evt.getNewValue() == null) {
200  removeListeners();
201  }
202  maxFilesDialogShown = false;
203  }
204  }
205  };
206 
207  private void update() {
208  setChanged();
209  notifyObservers();
210  }
211  }
212 
213 
214  @Override
215  protected boolean createKeys(List<DeletedContent.DeletedContentFilter> list) {
216  list.addAll(Arrays.asList(DeletedContent.DeletedContentFilter.values()));
217  return true;
218  }
219 
220  @Override
222  return new DeletedContentNode(skCase, key, notifier);
223  }
224 
226 
228  private final Logger logger = Logger.getLogger(DeletedContentNode.class.getName());
229 
230  // Use version that has observer for updates
231  @Deprecated
233  super(Children.create(new DeletedContentChildren(filter, skCase, null), true), Lookups.singleton(filter.getDisplayName()));
234  this.filter = filter;
235  init();
236  }
237 
239  super(Children.create(new DeletedContentChildren(filter, skCase, o), true), Lookups.singleton(filter.getDisplayName()));
240  this.filter = filter;
241  init();
242  o.addObserver(new DeletedContentNodeObserver());
243  }
244 
245  private void init() {
246  super.setName(filter.getName());
247 
248  String tooltip = filter.getDisplayName();
249  this.setShortDescription(tooltip);
250  this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-icon-deleted.png"); //NON-NLS
252  }
253 
254  // update the display name when new events are fired
255  private class DeletedContentNodeObserver implements Observer {
256  @Override
257  public void update(Observable o, Object arg) {
259  }
260  }
261 
262  private void updateDisplayName() {
263  //get count of children without preloading all children nodes
264  final long count = DeletedContentChildren.calculateItems(skCase, filter);
265  //final long count = getChildren().getNodesCount(true);
266  super.setDisplayName(filter.getDisplayName() + " (" + count + ")");
267  }
268 
269  @Override
270  public <T> T accept(DisplayableItemNodeVisitor<T> v) {
271  return v.visit(this);
272  }
273 
274  @Override
275  protected Sheet createSheet() {
276  Sheet s = super.createSheet();
277  Sheet.Set ss = s.get(Sheet.PROPERTIES);
278  if (ss == null) {
279  ss = Sheet.createPropertiesSet();
280  s.put(ss);
281  }
282 
283  ss.put(new NodeProperty<>(
284  NbBundle.getMessage(this.getClass(), "DeletedContent.createSheet.filterType.name"),
285  NbBundle.getMessage(this.getClass(), "DeletedContent.createSheet.filterType.displayName"),
286  NbBundle.getMessage(this.getClass(), "DeletedContent.createSheet.filterType.desc"),
287  filter.getDisplayName()));
288 
289  return s;
290  }
291 
292  @Override
293  public boolean isLeafTypeNode() {
294  return true;
295  }
296  }
297 
298  static class DeletedContentChildren extends ChildFactory.Detachable<AbstractFile> {
299 
300  private SleuthkitCase skCase;
301  private DeletedContent.DeletedContentFilter filter;
302  private static final Logger logger = Logger.getLogger(DeletedContentChildren.class.getName());
303  private static final int MAX_OBJECTS = 10001;
304  private final Observable notifier;
305 
306  DeletedContentChildren(DeletedContent.DeletedContentFilter filter, SleuthkitCase skCase, Observable o) {
307  this.skCase = skCase;
308  this.filter = filter;
309  this.notifier = o;
310  }
311 
312  private final Observer observer = new DeletedContentChildrenObserver();
313  // Cause refresh of children if there are changes
314  private class DeletedContentChildrenObserver implements Observer {
315  @Override
316  public void update(Observable o, Object arg) {
317  refresh(true);
318  }
319  }
320 
321  @Override
322  protected void addNotify() {
323  if (notifier != null) {
324  notifier.addObserver(observer);
325  }
326  }
327 
328  @Override
329  protected void removeNotify() {
330  if (notifier != null) {
331  notifier.deleteObserver(observer);
332  }
333  }
334 
335 
336  @Override
337  protected boolean createKeys(List<AbstractFile> list) {
338  List<AbstractFile> queryList = runFsQuery();
339  if (queryList.size() == MAX_OBJECTS) {
340  queryList.remove(queryList.size() - 1);
341 
342  // only show the dialog once - not each time we refresh
343  if (maxFilesDialogShown == false) {
344  maxFilesDialogShown = true;
345  SwingUtilities.invokeLater(new Runnable() {
346  @Override
347  public void run() {
348  JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(), NbBundle.getMessage(this.getClass(),
349  "DeletedContent.createKeys.maxObjects.msg",
350  MAX_OBJECTS - 1));
351  }
352  });
353  }
354  }
355  list.addAll(queryList);
356  return true;
357  }
358 
359  static private String makeQuery(DeletedContent.DeletedContentFilter filter) {
360  String query = "";
361  switch (filter) {
362  case FS_DELETED_FILTER:
363  query = "dir_flags = " + TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC.getValue() //NON-NLS
364  + " AND meta_flags != " + TskData.TSK_FS_META_FLAG_ENUM.ORPHAN.getValue() //NON-NLS
365  + " AND type = " + TskData.TSK_DB_FILES_TYPE_ENUM.FS.getFileType(); //NON-NLS
366 
367  break;
368  case ALL_DELETED_FILTER:
369  query = " ( "
370  + "( "
371  + "(dir_flags = " + TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC.getValue() //NON-NLS
372  + " OR " //NON-NLS
373  + "meta_flags = " + TskData.TSK_FS_META_FLAG_ENUM.ORPHAN.getValue() //NON-NLS
374  + ")"
375  + " AND type = " + TskData.TSK_DB_FILES_TYPE_ENUM.FS.getFileType() //NON-NLS
376  + " )"
377  + " OR type = " + TskData.TSK_DB_FILES_TYPE_ENUM.CARVED.getFileType() //NON-NLS
378  + " )";
379  //+ " AND type != " + TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS.getFileType()
380  //+ " AND type != " + TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS.getFileType()
381  //+ " AND type != " + TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS.getFileType()
382  //+ " AND type != " + TskData.TSK_DB_FILES_TYPE_ENUM.DERIVED.getFileType()
383  //+ " AND type != " + TskData.TSK_DB_FILES_TYPE_ENUM.LOCAL.getFileType()
384  //+ " AND type != " + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType();
385  break;
386 
387  default:
388  logger.log(Level.SEVERE, "Unsupported filter type to get deleted content: {0}", filter); //NON-NLS
389 
390  }
391 
392  query += " LIMIT " + MAX_OBJECTS; //NON-NLS
393  return query;
394  }
395 
396  private List<AbstractFile> runFsQuery() {
397  List<AbstractFile> ret = new ArrayList<>();
398 
399  String query = makeQuery(filter);
400  try {
401  ret = skCase.findAllFilesWhere(query);
402  } catch (TskCoreException e) {
403  logger.log(Level.SEVERE, "Error getting files for the deleted content view using: " + query, e); //NON-NLS
404  }
405 
406  return ret;
407 
408  }
409 
415  static long calculateItems(SleuthkitCase sleuthkitCase, DeletedContent.DeletedContentFilter filter) {
416  try {
417  return sleuthkitCase.countFilesWhere(makeQuery(filter));
418  } catch (TskCoreException ex) {
419  logger.log(Level.SEVERE, "Error getting deleted files search view count", ex); //NON-NLS
420  return 0;
421  }
422  }
423 
424  @Override
425  protected Node createNodeForKey(AbstractFile key) {
426  return key.accept(new ContentVisitor.Default<AbstractNode>() {
427  public FileNode visit(AbstractFile f) {
428  return new FileNode(f, false);
429  }
430 
431  public FileNode visit(FsContent f) {
432  return new FileNode(f, false);
433  }
434 
435  @Override
436  public FileNode visit(LayoutFile f) {
437  return new FileNode(f, false);
438  }
439 
440  @Override
441  public FileNode visit(File f) {
442  return new FileNode(f, false);
443  }
444 
445  @Override
446  public FileNode visit(Directory f) {
447  return new FileNode(f, false);
448  }
449 
450  @Override
451  protected AbstractNode defaultVisit(Content di) {
452  throw new UnsupportedOperationException(NbBundle.getMessage(this.getClass(),
453  "DeletedContent.createNodeForKey.typeNotSupported.msg",
454  di.toString()));
455  }
456  });
457  }
458  }
459  }
460 }
void removeIngestModuleEventListener(final PropertyChangeListener listener)
static synchronized IngestManager getInstance()
void removeIngestJobEventListener(final PropertyChangeListener listener)
boolean createKeys(List< DeletedContent.DeletedContentFilter > list)
void addIngestJobEventListener(final PropertyChangeListener listener)
static synchronized void removePropertyChangeListener(PropertyChangeListener listener)
Definition: Case.java:837
void addIngestModuleEventListener(final PropertyChangeListener listener)
static synchronized void addPropertyChangeListener(PropertyChangeListener listener)
Definition: Case.java:833
List< AbstractFile > findAllFilesWhere(String sqlWhereClause)
Node createNodeForKey(DeletedContent.DeletedContentFilter key)
static Logger getLogger(String name)
Definition: Logger.java:131

Copyright © 2012-2015 Basis Technology. Generated on: Mon Oct 19 2015
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.