Autopsy  4.6.0
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-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.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.DerivedFile;
47 import org.sleuthkit.datamodel.Directory;
48 import org.sleuthkit.datamodel.File;
49 import org.sleuthkit.datamodel.FsContent;
50 import org.sleuthkit.datamodel.LayoutFile;
51 import org.sleuthkit.datamodel.LocalFile;
52 import org.sleuthkit.datamodel.SlackFile;
53 import org.sleuthkit.datamodel.SleuthkitCase;
54 import org.sleuthkit.datamodel.TskCoreException;
55 import org.sleuthkit.datamodel.TskData;
56 import org.sleuthkit.datamodel.VirtualDirectory;
57 
61 public class FileSize implements AutopsyVisitableItem {
62 
63  private SleuthkitCase skCase;
64 
65  public enum FileSizeFilter implements AutopsyVisitableItem {
66 
67  SIZE_50_200(0, "SIZE_50_200", "50 - 200MB"), //NON-NLS
68  SIZE_200_1000(1, "SIZE_200_1GB", "200MB - 1GB"), //NON-NLS
69  SIZE_1000_(2, "SIZE_1000+", "1GB+"); //NON-NLS
70  private int id;
71  private String name;
72  private String displayName;
73 
74  private FileSizeFilter(int id, String name, String displayName) {
75  this.id = id;
76  this.name = name;
77  this.displayName = displayName;
78 
79  }
80 
81  public String getName() {
82  return this.name;
83  }
84 
85  public int getId() {
86  return this.id;
87  }
88 
89  public String getDisplayName() {
90  return this.displayName;
91  }
92 
93  @Override
94  public <T> T accept(AutopsyItemVisitor<T> visitor) {
95  return visitor.visit(this);
96  }
97  }
98 
99  public FileSize(SleuthkitCase skCase) {
100  this.skCase = skCase;
101  }
102 
103  @Override
104  public <T> T accept(AutopsyItemVisitor<T> visitor) {
105  return visitor.visit(this);
106  }
107 
108  public SleuthkitCase getSleuthkitCase() {
109  return this.skCase;
110  }
111 
112  /*
113  * Root node. Children are nodes for specific sizes.
114  */
115  public static class FileSizeRootNode extends DisplayableItemNode {
116 
117  private static final String NAME = NbBundle.getMessage(FileSize.class, "FileSize.fileSizeRootNode.name");
118 
119  FileSizeRootNode(SleuthkitCase skCase) {
120  super(Children.create(new FileSizeRootChildren(skCase), true), Lookups.singleton(NAME));
121  super.setName(NAME);
122  super.setDisplayName(NAME);
123  this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-size-16.png"); //NON-NLS
124  }
125 
126  @Override
127  public boolean isLeafTypeNode() {
128  return false;
129  }
130 
131  @Override
132  public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
133  return visitor.visit(this);
134  }
135 
136  @Override
137  protected Sheet createSheet() {
138  Sheet sheet = super.createSheet();
139  Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
140  if (sheetSet == null) {
141  sheetSet = Sheet.createPropertiesSet();
142  sheet.put(sheetSet);
143  }
144 
145  sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "FileSize.createSheet.name.name"),
146  NbBundle.getMessage(this.getClass(), "FileSize.createSheet.name.displayName"),
147  NbBundle.getMessage(this.getClass(), "FileSize.createSheet.name.desc"),
148  NAME));
149  return sheet;
150  }
151 
152  @Override
153  public String getItemType() {
154  return getClass().getName();
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 static final class FileSizeRootChildrenObservable extends Observable {
176 
178 
183  }
184 
185  private void removeListeners() {
186  deleteObservers();
190  }
191 
192  private final PropertyChangeListener pcl = (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
205  Case.getOpenCase();
206  update();
207  } catch (NoCurrentCaseException 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 {
222  Case.getOpenCase();
223  update();
224  } catch (NoCurrentCaseException 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  private void update() {
238  setChanged();
239  notifyObservers();
240  }
241  }
242 
243  @Override
244  protected boolean createKeys(List<FileSizeFilter> list) {
245  list.addAll(Arrays.asList(FileSizeFilter.values()));
246  return true;
247  }
248 
249  @Override
250  protected Node createNodeForKey(FileSizeFilter key) {
251  return new FileSizeNode(skCase, key, notifier);
252  }
253 
254  /*
255  * Node for a specific size range. Children are files.
256  */
257  public class FileSizeNode extends DisplayableItemNode {
258 
260 
261  // use version with observer instead so that it updates
262  @Deprecated
263  FileSizeNode(SleuthkitCase skCase, FileSizeFilter filter) {
264  super(Children.create(new FileSizeChildren(filter, skCase, null), true), Lookups.singleton(filter.getDisplayName()));
265  this.filter = filter;
266  init();
267  }
268 
276  FileSizeNode(SleuthkitCase skCase, FileSizeFilter filter, Observable o) {
277  super(Children.create(new FileSizeChildren(filter, skCase, o), true), Lookups.singleton(filter.getDisplayName()));
278  this.filter = filter;
279  init();
280  o.addObserver(new FileSizeNodeObserver());
281  }
282 
283  private void init() {
284  super.setName(filter.getName());
285 
286  String tooltip = filter.getDisplayName();
287  this.setShortDescription(tooltip);
288  this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-size-16.png"); //NON-NLS
289 
291  }
292 
293  @Override
294  public String getItemType() {
299  return DisplayableItemNode.FILE_PARENT_NODE_KEY;
300  }
301 
302  // update the display name when new events are fired
303  private class FileSizeNodeObserver implements Observer {
304 
305  @Override
306  public void update(Observable o, Object arg) {
308  }
309  }
310 
311  private void updateDisplayName() {
312  final long numVisibleChildren = FileSizeChildren.calculateItems(skCase, filter);
313  super.setDisplayName(filter.getDisplayName() + " (" + numVisibleChildren + ")");
314  }
315 
316  @Override
317  public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
318  return visitor.visit(this);
319  }
320 
321  @Override
322  protected Sheet createSheet() {
323  Sheet sheet = super.createSheet();
324  Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
325  if (sheetSet == null) {
326  sheetSet = Sheet.createPropertiesSet();
327  sheet.put(sheetSet);
328  }
329 
330  sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "FileSize.createSheet.filterType.name"),
331  NbBundle.getMessage(this.getClass(), "FileSize.createSheet.filterType.displayName"),
332  NbBundle.getMessage(this.getClass(), "FileSize.createSheet.filterType.desc"),
333  filter.getDisplayName()));
334 
335  return sheet;
336  }
337 
338  @Override
339  public boolean isLeafTypeNode() {
340  return true;
341  }
342  }
343 
344  /*
345  * Makes children, which are nodes for files of a given range
346  */
347  static class FileSizeChildren extends ChildFactory.Detachable<AbstractFile> {
348 
349  private final SleuthkitCase skCase;
350  private final FileSizeFilter filter;
351  private final Observable notifier;
352  private static final Logger logger = Logger.getLogger(FileSizeChildren.class.getName());
353 
361  FileSizeChildren(FileSizeFilter filter, SleuthkitCase skCase, Observable o) {
362  this.skCase = skCase;
363  this.filter = filter;
364  this.notifier = o;
365  }
366 
367  @Override
368  protected void addNotify() {
369  if (notifier != null) {
370  notifier.addObserver(observer);
371  }
372  }
373 
374  @Override
375  protected void removeNotify() {
376  if (notifier != null) {
377  notifier.deleteObserver(observer);
378  }
379  }
380 
381  private final Observer observer = new FileSizeChildrenObserver();
382 
383  // Cause refresh of children if there are changes
384  private class FileSizeChildrenObserver implements Observer {
385 
386  @Override
387  public void update(Observable o, Object arg) {
388  refresh(true);
389  }
390  }
391 
392  @Override
393  protected boolean createKeys(List<AbstractFile> list) {
394  list.addAll(runFsQuery());
395  return true;
396  }
397 
398  private static String makeQuery(FileSizeFilter filter) {
399  String query;
400  switch (filter) {
401  case SIZE_50_200:
402  query = "(size >= 50000000 AND size < 200000000)"; //NON-NLS
403  break;
404  case SIZE_200_1000:
405  query = "(size >= 200000000 AND size < 1000000000)"; //NON-NLS
406  break;
407 
408  case SIZE_1000_:
409  query = "(size >= 1000000000)"; //NON-NLS
410  break;
411 
412  default:
413  throw new IllegalArgumentException("Unsupported filter type to get files by size: " + filter); //NON-NLS
414  }
415 
416  // Ignore unallocated block files.
417  query = query + " AND (type != " + TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS.getFileType() + ")"; //NON-NLS
418 
419  // Hide known files if indicated in the user preferences.
421  query += " AND (known != " + TskData.FileKnown.KNOWN.getFileKnownValue() //NON-NLS
422  + " OR known IS NULL)"; //NON-NLS
423  }
424 
425  // Hide slack files if indicated in the user preferences.
426  if(UserPreferences.hideSlackFilesInViewsTree()) {
427  query += " AND (type != " + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.getFileType() + ")"; //NON-NLS
428  }
429 
430  return query;
431  }
432 
433  private List<AbstractFile> runFsQuery() {
434  List<AbstractFile> ret = new ArrayList<>();
435 
436  try {
437  String query = makeQuery(filter);
438 
439  ret = skCase.findAllFilesWhere(query);
440  } catch (Exception e) {
441  logger.log(Level.SEVERE, "Error getting files for the file size view: " + e.getMessage()); //NON-NLS
442  }
443 
444  return ret;
445  }
446 
452  static long calculateItems(SleuthkitCase sleuthkitCase, FileSizeFilter filter) {
453  try {
454  return sleuthkitCase.countFilesWhere(makeQuery(filter));
455  } catch (TskCoreException ex) {
456  logger.log(Level.SEVERE, "Error getting files by size search view count", ex); //NON-NLS
457  return 0;
458  }
459  }
460 
461  @Override
462  protected Node createNodeForKey(AbstractFile key) {
463  return key.accept(new ContentVisitor.Default<AbstractNode>() {
464  public FileNode visit(AbstractFile f) {
465  return new FileNode(f, false);
466  }
467 
468  public FileNode visit(FsContent f) {
469  return new FileNode(f, false);
470  }
471 
472  @Override
473  public FileNode visit(LayoutFile f) {
474  return new FileNode(f, false);
475  }
476 
477  @Override
478  public FileNode visit(File f) {
479  return new FileNode(f, false);
480  }
481 
482  @Override
483  public FileNode visit(Directory f) {
484  return new FileNode(f, false);
485  }
486 
487  @Override
488  public FileNode visit(LocalFile f) {
489  return new FileNode(f, false);
490  }
491 
492  @Override
493  public FileNode visit(DerivedFile f) {
494  return new FileNode(f, false);
495  }
496 
497  @Override
498  public FileNode visit(VirtualDirectory f) {
499  return new FileNode(f, false);
500  }
501 
502  @Override
503  public FileNode visit(SlackFile f) {
504  return new FileNode(f, false);
505  }
506 
507  @Override
508  protected AbstractNode defaultVisit(Content di) {
509  throw new UnsupportedOperationException(
510  NbBundle.getMessage(this.getClass(),
511  "FileSize.exception.notSupported.msg",
512  di.toString()));
513  }
514  });
515  }
516  }
517  }
518 }
void removeIngestModuleEventListener(final PropertyChangeListener listener)
static synchronized IngestManager getInstance()
void removeIngestJobEventListener(final PropertyChangeListener listener)
void addIngestJobEventListener(final PropertyChangeListener listener)
FileSizeFilter(int id, String name, String displayName)
Definition: FileSize.java:74
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:420
public< T > T accept(AutopsyItemVisitor< T > visitor)
Definition: FileSize.java:94
static void removeEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
Definition: Case.java:465

Copyright © 2012-2016 Basis Technology. Generated on: Mon May 7 2018
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.