Autopsy  4.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
FileSize.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2013-2015 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 org.openide.nodes.AbstractNode;
30 import org.openide.nodes.ChildFactory;
31 import org.openide.nodes.Children;
32 import org.openide.nodes.Node;
33 import org.openide.nodes.Sheet;
34 import org.openide.util.NbBundle;
35 import org.openide.util.lookup.Lookups;
39 import org.sleuthkit.datamodel.AbstractFile;
40 import org.sleuthkit.datamodel.Content;
41 import org.sleuthkit.datamodel.ContentVisitor;
42 import org.sleuthkit.datamodel.DerivedFile;
43 import org.sleuthkit.datamodel.Directory;
44 import org.sleuthkit.datamodel.File;
45 import org.sleuthkit.datamodel.FsContent;
46 import org.sleuthkit.datamodel.LayoutFile;
47 import org.sleuthkit.datamodel.LocalFile;
48 import org.sleuthkit.datamodel.SleuthkitCase;
49 import org.sleuthkit.datamodel.TskCoreException;
50 import org.sleuthkit.datamodel.TskData;
51 import org.sleuthkit.datamodel.VirtualDirectory;
52 
56 public class FileSize implements AutopsyVisitableItem {
57 
58  private SleuthkitCase skCase;
59 
60  public enum FileSizeFilter implements AutopsyVisitableItem {
61 
62  SIZE_50_200(0, "SIZE_50_200", "50 - 200MB"), //NON-NLS
63  SIZE_200_1000(1, "SIZE_200_1GB", "200MB - 1GB"), //NON-NLS
64  SIZE_1000_(2, "SIZE_1000+", "1GB+"); //NON-NLS
65  private int id;
66  private String name;
67  private String displayName;
68 
69  private FileSizeFilter(int id, String name, String displayName) {
70  this.id = id;
71  this.name = name;
72  this.displayName = displayName;
73 
74  }
75 
76  public String getName() {
77  return this.name;
78  }
79 
80  public int getId() {
81  return this.id;
82  }
83 
84  public String getDisplayName() {
85  return this.displayName;
86  }
87 
88  @Override
89  public <T> T accept(AutopsyItemVisitor<T> v) {
90  return v.visit(this);
91  }
92  }
93 
94  public FileSize(SleuthkitCase skCase) {
95  this.skCase = skCase;
96  }
97 
98  @Override
99  public <T> T accept(AutopsyItemVisitor<T> v) {
100  return v.visit(this);
101  }
102 
103  public SleuthkitCase getSleuthkitCase() {
104  return this.skCase;
105  }
106 
107  /*
108  * Root node. Children are nodes for specific sizes.
109  */
110  public static class FileSizeRootNode extends DisplayableItemNode {
111 
112  private static final String NAME = NbBundle.getMessage(FileSize.class, "FileSize.fileSizeRootNode.name");
113 
114  FileSizeRootNode(SleuthkitCase skCase) {
115  super(Children.create(new FileSizeRootChildren(skCase), true), Lookups.singleton(NAME));
116  super.setName(NAME);
117  super.setDisplayName(NAME);
118  this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-size-16.png"); //NON-NLS
119  }
120 
121  @Override
122  public boolean isLeafTypeNode() {
123  return false;
124  }
125 
126  @Override
127  public <T> T accept(DisplayableItemNodeVisitor<T> v) {
128  return v.visit(this);
129  }
130 
131  @Override
132  protected Sheet createSheet() {
133  Sheet s = super.createSheet();
134  Sheet.Set ss = s.get(Sheet.PROPERTIES);
135  if (ss == null) {
136  ss = Sheet.createPropertiesSet();
137  s.put(ss);
138  }
139 
140  ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "FileSize.createSheet.name.name"),
141  NbBundle.getMessage(this.getClass(), "FileSize.createSheet.name.displayName"),
142  NbBundle.getMessage(this.getClass(), "FileSize.createSheet.name.desc"),
143  NAME));
144  return s;
145  }
146 
147  /*
148  * TODO (AUT-1849): Correct or remove peristent column reordering code
149  *
150  * Added to support this feature.
151  */
152 // @Override
153 // public String getItemType() {
154 // return "FileSizeRoot"; //NON-NLS
155 // }
156  }
157 
158  /*
159  * Makes the children for specific sizes
160  */
161  public static class FileSizeRootChildren extends ChildFactory<org.sleuthkit.autopsy.datamodel.FileSize.FileSizeFilter> {
162 
163  private SleuthkitCase skCase;
164  private Observable notifier;
165 
166  public FileSizeRootChildren(SleuthkitCase skCase) {
167  this.skCase = skCase;
168  notifier = new FileSizeRootChildrenObservable();
169  }
170 
175  private final class FileSizeRootChildrenObservable extends Observable {
176 
181  }
182 
183  private void removeListeners() {
184  deleteObservers();
188  }
189 
190  private final PropertyChangeListener pcl = new PropertyChangeListener() {
191  @Override
192  public void propertyChange(PropertyChangeEvent evt) {
193  String eventType = evt.getPropertyName();
194 
195  if (eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())) {
202  try {
203  // new file was added
204  // @@@ could check the size here and only fire off updates if we know the file meets the min size criteria
206  update();
207  } catch (IllegalStateException notUsed) {
211  }
212  } else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
213  || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())
214  || eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) {
221  try {
223  update();
224  } catch (IllegalStateException notUsed) {
228  }
229  } else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
230  // case was closed. Remove listeners so that we don't get called with a stale case handle
231  if (evt.getNewValue() == null) {
232  removeListeners();
233  }
234  }
235  }
236  };
237 
238  private void update() {
239  setChanged();
240  notifyObservers();
241  }
242  }
243 
244  @Override
245  protected boolean createKeys(List<FileSizeFilter> list) {
246  list.addAll(Arrays.asList(FileSizeFilter.values()));
247  return true;
248  }
249 
250  @Override
251  protected Node createNodeForKey(FileSizeFilter key) {
252  return new FileSizeNode(skCase, key, notifier);
253  }
254 
255  /*
256  * Node for a specific size range. Children are files.
257  */
258  public class FileSizeNode extends DisplayableItemNode {
259 
261 
262  // use version with observer instead so that it updates
263  @Deprecated
264  FileSizeNode(SleuthkitCase skCase, FileSizeFilter filter) {
265  super(Children.create(new FileSizeChildren(filter, skCase, null), true), Lookups.singleton(filter.getDisplayName()));
266  this.filter = filter;
267  init();
268  }
269 
277  FileSizeNode(SleuthkitCase skCase, FileSizeFilter filter, Observable o) {
278  super(Children.create(new FileSizeChildren(filter, skCase, o), true), Lookups.singleton(filter.getDisplayName()));
279  this.filter = filter;
280  init();
281  o.addObserver(new FileSizeNodeObserver());
282  }
283 
284  private void init() {
285  super.setName(filter.getName());
286 
287  String tooltip = filter.getDisplayName();
288  this.setShortDescription(tooltip);
289  this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-size-16.png"); //NON-NLS
290 
292  }
293 
294  /*
295  * TODO (AUT-1849): Correct or remove peristent column reordering
296  * code
297  *
298  * Added to support this feature.
299  */
300 // @Override
301 // public String getItemType() {
302 // return "FileSize"; //NON-NLS
303 // }
304  // update the display name when new events are fired
305  private class FileSizeNodeObserver implements Observer {
306 
307  @Override
308  public void update(Observable o, Object arg) {
310  }
311  }
312 
313  private void updateDisplayName() {
314  final long count = FileSizeChildren.calculateItems(skCase, filter);
315  super.setDisplayName(filter.getDisplayName() + " (" + count + ")");
316  }
317 
318  @Override
319  public <T> T accept(DisplayableItemNodeVisitor<T> v) {
320  return v.visit(this);
321  }
322 
323  @Override
324  protected Sheet createSheet() {
325  Sheet s = super.createSheet();
326  Sheet.Set ss = s.get(Sheet.PROPERTIES);
327  if (ss == null) {
328  ss = Sheet.createPropertiesSet();
329  s.put(ss);
330  }
331 
332  ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "FileSize.createSheet.filterType.name"),
333  NbBundle.getMessage(this.getClass(), "FileSize.createSheet.filterType.displayName"),
334  NbBundle.getMessage(this.getClass(), "FileSize.createSheet.filterType.desc"),
335  filter.getDisplayName()));
336 
337  return s;
338  }
339 
340  @Override
341  public boolean isLeafTypeNode() {
342  return true;
343  }
344  }
345 
346  /*
347  * Makes children, which are nodes for files of a given range
348  */
349  static class FileSizeChildren extends ChildFactory.Detachable<AbstractFile> {
350 
351  private final SleuthkitCase skCase;
352  private final FileSizeFilter filter;
353  private final Observable notifier;
354  private static final Logger logger = Logger.getLogger(FileSizeChildren.class.getName());
355 
363  FileSizeChildren(FileSizeFilter filter, SleuthkitCase skCase, Observable o) {
364  this.skCase = skCase;
365  this.filter = filter;
366  this.notifier = o;
367  }
368 
369  @Override
370  protected void addNotify() {
371  if (notifier != null) {
372  notifier.addObserver(observer);
373  }
374  }
375 
376  @Override
377  protected void removeNotify() {
378  if (notifier != null) {
379  notifier.deleteObserver(observer);
380  }
381  }
382 
383  private final Observer observer = new FileSizeChildrenObserver();
384 
385  // Cause refresh of children if there are changes
386  private class FileSizeChildrenObserver implements Observer {
387 
388  @Override
389  public void update(Observable o, Object arg) {
390  refresh(true);
391  }
392  }
393 
394  @Override
395  protected boolean createKeys(List<AbstractFile> list) {
396  list.addAll(runFsQuery());
397  return true;
398  }
399 
400  private static String makeQuery(FileSizeFilter filter) {
401  String query;
402  switch (filter) {
403  case SIZE_50_200:
404  query = "(size >= 50000000 AND size < 200000000)"; //NON-NLS
405  break;
406  case SIZE_200_1000:
407  query = "(size >= 200000000 AND size < 1000000000)"; //NON-NLS
408  break;
409 
410  case SIZE_1000_:
411  query = "(size >= 1000000000)"; //NON-NLS
412  break;
413 
414  default:
415  throw new IllegalArgumentException("Unsupported filter type to get files by size: " + filter); //NON-NLS
416  }
417  // ignore unalloc block files
418  query = query + " AND (type != " + TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS.getFileType() + ")"; //NON-NLS
419 
420  return query;
421  }
422 
423  private List<AbstractFile> runFsQuery() {
424  List<AbstractFile> ret = new ArrayList<>();
425 
426  try {
427  String query = makeQuery(filter);
428 
429  ret = skCase.findAllFilesWhere(query);
430  } catch (Exception e) {
431  logger.log(Level.SEVERE, "Error getting files for the file size view: " + e.getMessage()); //NON-NLS
432  }
433 
434  return ret;
435  }
436 
442  static long calculateItems(SleuthkitCase sleuthkitCase, FileSizeFilter filter) {
443  try {
444  return sleuthkitCase.countFilesWhere(makeQuery(filter));
445  } catch (TskCoreException ex) {
446  logger.log(Level.SEVERE, "Error getting files by size search view count", ex); //NON-NLS
447  return 0;
448  }
449  }
450 
451  @Override
452  protected Node createNodeForKey(AbstractFile key) {
453  return key.accept(new ContentVisitor.Default<AbstractNode>() {
454  public FileNode visit(AbstractFile f) {
455  return new FileNode(f, false);
456  }
457 
458  public FileNode visit(FsContent f) {
459  return new FileNode(f, false);
460  }
461 
462  @Override
463  public FileNode visit(LayoutFile f) {
464  return new FileNode(f, false);
465  }
466 
467  @Override
468  public FileNode visit(File f) {
469  return new FileNode(f, false);
470  }
471 
472  @Override
473  public FileNode visit(Directory f) {
474  return new FileNode(f, false);
475  }
476 
477  @Override
478  public FileNode visit(LocalFile f) {
479  return new FileNode(f, false);
480  }
481 
482  @Override
483  public FileNode visit(DerivedFile f) {
484  return new FileNode(f, false);
485  }
486 
487  @Override
488  public FileNode visit(VirtualDirectory f) {
489  return new FileNode(f, false);
490  }
491 
492  @Override
493  protected AbstractNode defaultVisit(Content di) {
494  throw new UnsupportedOperationException(
495  NbBundle.getMessage(this.getClass(),
496  "FileSize.exception.notSupported.msg",
497  di.toString()));
498  }
499  });
500  }
501  }
502  }
503 }
public< T > T accept(AutopsyItemVisitor< T > v)
Definition: FileSize.java:89
void removeIngestModuleEventListener(final PropertyChangeListener listener)
static synchronized IngestManager getInstance()
static void removePropertyChangeListener(PropertyChangeListener listener)
Definition: Case.java:318
void removeIngestJobEventListener(final PropertyChangeListener listener)
void addIngestJobEventListener(final PropertyChangeListener listener)
static void addPropertyChangeListener(PropertyChangeListener listener)
Definition: Case.java:306
FileSizeFilter(int id, String name, String displayName)
Definition: FileSize.java:69
void addIngestModuleEventListener(final PropertyChangeListener listener)
synchronized static Logger getLogger(String name)
Definition: Logger.java:161

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