Autopsy  4.4.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
FileTypesByExtension.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2011-2017 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.Arrays;
24 import java.util.EnumSet;
25 import java.util.List;
26 import java.util.Observable;
27 import java.util.Observer;
28 import java.util.Set;
29 import java.util.logging.Level;
30 import java.util.stream.Collectors;
31 import org.apache.commons.lang.StringUtils;
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.SleuthkitCase;
44 import org.sleuthkit.datamodel.TskCoreException;
45 import org.sleuthkit.datamodel.TskData;
46 
50 public final class FileTypesByExtension implements AutopsyVisitableItem {
51 
52  private final static Logger logger = Logger.getLogger(FileTypesByExtension.class.getName());
53  private final SleuthkitCase skCase;
54  private final FileTypes typesRoot;
55 
56  public FileTypesByExtension(FileTypes typesRoot) {
57  this.skCase = typesRoot.getSleuthkitCase();
58  this.typesRoot = typesRoot;
59  }
60 
61  public SleuthkitCase getSleuthkitCase() {
62  return this.skCase;
63  }
64 
65  @Override
66  public <T> T accept(AutopsyItemVisitor<T> v) {
67  return v.visit(this);
68  }
69 
74  private class FileTypesByExtObservable extends Observable {
75 
76  private final PropertyChangeListener pcl;
77  private final Set<Case.Events> CASE_EVENTS_OF_INTEREST;
78 
80  super();
82  this.pcl = (PropertyChangeEvent evt) -> {
83  String eventType = evt.getPropertyName();
84  if (eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())
85  || eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
86  || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())
87  || eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) {
94  try {
96  typesRoot.updateShowCounts();
97  update();
98  } catch (IllegalStateException notUsed) {
102  }
103  } else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
104  // case was closed. Remove listeners so that we don't get called with a stale case handle
105  if (evt.getNewValue() == null) {
106  removeListeners();
107  }
108  }
109  };
110 
114  }
115 
116  private void removeListeners() {
117  deleteObservers();
121  }
122 
123  private void update() {
124  setChanged();
125  notifyObservers();
126  }
127  }
128  private static final String FNAME = NbBundle.getMessage(FileTypesByExtNode.class, "FileTypesByExtNode.fname.text");
129 
133  class FileTypesByExtNode extends DisplayableItemNode {
134 
135  private final FileTypesByExtension.RootFilter filter;
136 
143  FileTypesByExtNode(SleuthkitCase skCase, FileTypesByExtension.RootFilter filter) {
144  this(skCase, filter, null);
145  }
146 
154  private FileTypesByExtNode(SleuthkitCase skCase, FileTypesByExtension.RootFilter filter, FileTypesByExtObservable o) {
155 
156  super(Children.create(new FileTypesByExtNodeChildren(skCase, filter, o), true),
157  Lookups.singleton(filter == null ? FNAME : filter.getDisplayName()));
158  this.filter = filter;
159 
160  // root node of tree
161  if (filter == null) {
162  super.setName(FNAME);
163  super.setDisplayName(FNAME);
164  } // sub-node in file tree (i.e. documents, exec, etc.)
165  else {
166  super.setName(filter.getDisplayName());
167  super.setDisplayName(filter.getDisplayName());
168  }
169  this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file_types.png"); //NON-NLS
170  }
171 
172  @Override
173  public boolean isLeafTypeNode() {
174  return false;
175  }
176 
177  @Override
178  public <T> T accept(DisplayableItemNodeVisitor<T> v) {
179  return v.visit(this);
180  }
181 
182  @Override
183  protected Sheet createSheet() {
184  Sheet s = super.createSheet();
185  Sheet.Set ss = s.get(Sheet.PROPERTIES);
186  if (ss == null) {
187  ss = Sheet.createPropertiesSet();
188  s.put(ss);
189  }
190  if (filter != null && (filter.equals(FileTypesByExtension.RootFilter.TSK_DOCUMENT_FILTER) || filter.equals(FileTypesByExtension.RootFilter.TSK_EXECUTABLE_FILTER))) {
191  String extensions = "";
192  for (String ext : filter.getFilter()) {
193  extensions += "'" + ext + "', ";
194  }
195  extensions = extensions.substring(0, extensions.lastIndexOf(','));
196  ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.fileExt.name"), NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.fileExt.displayName"), NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.fileExt.desc"), extensions));
197  } else {
198  ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.name.name"), NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.name.displayName"), NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.name.desc"), getDisplayName()));
199  }
200  return s;
201  }
202 
203  @Override
204  public String getItemType() {
209  if (filter == null) {
210  return getClass().getName();
211  }
213  return getClass().getName() + filter.getName();
214  }
215  return getClass().getName();
216  }
217 
218  }
219 
220  private class FileTypesByExtNodeChildren extends ChildFactory<FileTypesByExtension.SearchFilterInterface> {
221 
222  private final SleuthkitCase skCase;
225 
234  super();
235  this.skCase = skCase;
236  this.filter = filter;
237  if (o == null) {
238  this.notifier = new FileTypesByExtObservable();
239  } else {
240  this.notifier = o;
241  }
242  }
243 
244  @Override
245  protected boolean createKeys(List<FileTypesByExtension.SearchFilterInterface> list) {
246  // root node
247  if (filter == null) {
248  list.addAll(Arrays.asList(FileTypesByExtension.RootFilter.values()));
249  } // document and executable has another level of nodes
251  list.addAll(Arrays.asList(FileTypesByExtension.DocumentFilter.values()));
253  list.addAll(Arrays.asList(FileTypesByExtension.ExecutableFilter.values()));
254  }
255  return true;
256  }
257 
258  @Override
260  // make new nodes for the sub-nodes
261  if (key.getName().equals(FileTypesByExtension.RootFilter.TSK_DOCUMENT_FILTER.getName())) {
262  return new FileTypesByExtNode(skCase, FileTypesByExtension.RootFilter.TSK_DOCUMENT_FILTER, notifier);
263  } else if (key.getName().equals(FileTypesByExtension.RootFilter.TSK_EXECUTABLE_FILTER.getName())) {
264  return new FileTypesByExtNode(skCase, FileTypesByExtension.RootFilter.TSK_EXECUTABLE_FILTER, notifier);
265  } else {
266  return new FileExtensionNode(key, skCase, notifier);
267  }
268  }
269  }
270 
275  class FileExtensionNode extends FileTypes.BGCountUpdatingNode {
276 
277  private final FileTypesByExtension.SearchFilterInterface filter;
278 
286  FileExtensionNode(FileTypesByExtension.SearchFilterInterface filter, SleuthkitCase skCase, FileTypesByExtObservable o) {
287  super(typesRoot, Children.create(new FileExtensionNodeChildren(filter, skCase, o), true),
288  Lookups.singleton(filter.getDisplayName()));
289  this.filter = filter;
290  super.setName(filter.getDisplayName());
291  updateDisplayName();
292  this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-filter-icon.png"); //NON-NLS
293 
294  o.addObserver(this);
295  }
296 
297  @Override
298  public <T> T accept(DisplayableItemNodeVisitor<T> v) {
299  return v.visit(this);
300  }
301 
302  @Override
303  protected Sheet createSheet() {
304  Sheet s = super.createSheet();
305  Sheet.Set ss = s.get(Sheet.PROPERTIES);
306  if (ss == null) {
307  ss = Sheet.createPropertiesSet();
308  s.put(ss);
309  }
310  ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.filterType.name"),
311  NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.filterType.displayName"),
312  NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.filterType.desc"),
313  filter.getDisplayName()));
314 
315  ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.fileExt.name"),
316  NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.fileExt.displayName"),
317  NbBundle.getMessage(this.getClass(), "FileTypesByExtNode.createSheet.fileExt.desc"),
318  String.join(", ", filter.getFilter())));
319  return s;
320  }
321 
322  @Override
323  public boolean isLeafTypeNode() {
324  return true;
325  }
326 
332  @Override
333  public String getItemType() {
334  return DisplayableItemNode.FILE_PARENT_NODE_KEY;
335  }
336 
337  @Override
338  String getDisplayNameBase() {
339  return filter.getDisplayName();
340  }
341 
342  @Override
343  long calculateChildCount() throws TskCoreException {
344  return skCase.countFilesWhere(createQuery(filter));
345  }
346  }
347 
349  if (filter.getFilter().isEmpty()) {
350  // We should never be given a search filter without extensions
351  // but if we are it is clearly a programming error so we throw
352  // an IllegalArgumentException.
353  throw new IllegalArgumentException("Empty filter list passed to createQuery()"); // NON-NLS
354  }
355 
356  return "(dir_type = " + TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue() + ")"
358  ? " AND (known IS NULL OR known != " + TskData.FileKnown.KNOWN.getFileKnownValue() + ")"
359  : " ")
360  + " AND (extension IN (" + filter.getFilter().stream()
361  .map(String::toLowerCase)
362  .map(s -> "'"+StringUtils.substringAfter(s, ".")+"'")
363  .collect(Collectors.joining(", ")) + "))";
364  }
365 
369  private class FileExtensionNodeChildren extends ChildFactory.Detachable<FileTypesKey> implements Observer {
370 
371  private final SleuthkitCase skCase;
373  private final Observable notifier;
374 
382  private FileExtensionNodeChildren(FileTypesByExtension.SearchFilterInterface filter, SleuthkitCase skCase, Observable o) {
383  super();
384  this.filter = filter;
385  this.skCase = skCase;
386  notifier = o;
387  }
388 
389  @Override
390  protected void addNotify() {
391  if (notifier != null) {
392  notifier.addObserver(this);
393  }
394  }
395 
396  @Override
397  protected void removeNotify() {
398  if (notifier != null) {
399  notifier.deleteObserver(this);
400  }
401  }
402 
403  @Override
404  public void update(Observable o, Object arg) {
405  refresh(true);
406  }
407 
408  @Override
409  protected boolean createKeys(List<FileTypesKey> list) {
410  try {
411  list.addAll(skCase.findAllFilesWhere(createQuery(filter))
412  .stream().map(f -> new FileTypesKey(f)).collect(Collectors.toList()));
413  } catch (TskCoreException ex) {
414  logger.log(Level.SEVERE, "Couldn't get search results", ex); //NON-NLS
415  }
416  return true;
417  }
418 
419  @Override
420  protected Node createNodeForKey(FileTypesKey key) {
421  return key.accept(new FileTypes.FileNodeCreationVisitor());
422  }
423  }
424 
425  // root node filters
426  public static enum RootFilter implements AutopsyVisitableItem, SearchFilterInterface {
427 
428  TSK_IMAGE_FILTER(0, "TSK_IMAGE_FILTER", //NON-NLS
429  NbBundle.getMessage(FileTypesByExtension.class, "FileTypeExtensionFilters.tskImgFilter.text"),
431  TSK_VIDEO_FILTER(1, "TSK_VIDEO_FILTER", //NON-NLS
432  NbBundle.getMessage(FileTypesByExtension.class, "FileTypeExtensionFilters.tskVideoFilter.text"),
434  TSK_AUDIO_FILTER(2, "TSK_AUDIO_FILTER", //NON-NLS
435  NbBundle.getMessage(FileTypesByExtension.class, "FileTypeExtensionFilters.tskAudioFilter.text"),
437  TSK_ARCHIVE_FILTER(3, "TSK_ARCHIVE_FILTER", //NON-NLS
438  NbBundle.getMessage(FileTypesByExtension.class, "FileTypeExtensionFilters.tskArchiveFilter.text"),
440  TSK_DOCUMENT_FILTER(3, "TSK_DOCUMENT_FILTER", //NON-NLS
441  NbBundle.getMessage(FileTypesByExtension.class, "FileTypeExtensionFilters.tskDocumentFilter.text"),
442  Arrays.asList(".htm", ".html", ".doc", ".docx", ".odt", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".rtf")), //NON-NLS
443  TSK_EXECUTABLE_FILTER(3, "TSK_EXECUTABLE_FILTER", //NON-NLS
444  NbBundle.getMessage(FileTypesByExtension.class, "FileTypeExtensionFilters.tskExecFilter.text"),
446 
447  private final int id;
448  private final String name;
449  private final String displayName;
450  private final List<String> filter;
451 
452  private RootFilter(int id, String name, String displayName, List<String> filter) {
453  this.id = id;
454  this.name = name;
455  this.displayName = displayName;
456  this.filter = filter;
457  }
458 
459  @Override
460  public <T> T accept(AutopsyItemVisitor<T> v) {
461  return v.visit(this);
462  }
463 
464  @Override
465  public String getName() {
466  return this.name;
467  }
468 
469  @Override
470  public int getId() {
471  return this.id;
472  }
473 
474  @Override
475  public String getDisplayName() {
476  return this.displayName;
477  }
478 
479  @Override
480  public List<String> getFilter() {
481  return this.filter;
482  }
483  }
484 
485  // document sub-node filters
486  public static enum DocumentFilter implements AutopsyVisitableItem, SearchFilterInterface {
487 
488  AUT_DOC_HTML(0, "AUT_DOC_HTML", //NON-NLS
489  NbBundle.getMessage(FileTypesByExtension.class, "FileTypeExtensionFilters.autDocHtmlFilter.text"),
490  Arrays.asList(".htm", ".html")), //NON-NLS
491  AUT_DOC_OFFICE(1, "AUT_DOC_OFFICE", //NON-NLS
492  NbBundle.getMessage(FileTypesByExtension.class, "FileTypeExtensionFilters.autDocOfficeFilter.text"),
493  Arrays.asList(".doc", ".docx", ".odt", ".xls", ".xlsx", ".ppt", ".pptx")), //NON-NLS
494  AUT_DOC_PDF(2, "AUT_DOC_PDF", //NON-NLS
495  NbBundle.getMessage(FileTypesByExtension.class, "FileTypeExtensionFilters.autoDocPdfFilter.text"),
496  Arrays.asList(".pdf")), //NON-NLS
497  AUT_DOC_TXT(3, "AUT_DOC_TXT", //NON-NLS
498  NbBundle.getMessage(FileTypesByExtension.class, "FileTypeExtensionFilters.autDocTxtFilter.text"),
499  Arrays.asList(".txt")), //NON-NLS
500  AUT_DOC_RTF(4, "AUT_DOC_RTF", //NON-NLS
501  NbBundle.getMessage(FileTypesByExtension.class, "FileTypeExtensionFilters.autDocRtfFilter.text"),
502  Arrays.asList(".rtf")); //NON-NLS
503 
504  private final int id;
505  private final String name;
506  private final String displayName;
507  private final List<String> filter;
508 
509  private DocumentFilter(int id, String name, String displayName, List<String> filter) {
510  this.id = id;
511  this.name = name;
512  this.displayName = displayName;
513  this.filter = filter;
514  }
515 
516  @Override
517  public <T> T accept(AutopsyItemVisitor<T> v) {
518  return v.visit(this);
519  }
520 
521  @Override
522  public String getName() {
523  return this.name;
524  }
525 
526  @Override
527  public int getId() {
528  return this.id;
529  }
530 
531  @Override
532  public String getDisplayName() {
533  return this.displayName;
534  }
535 
536  @Override
537  public List<String> getFilter() {
538  return this.filter;
539  }
540  }
541 
542  // executable sub-node filters
543  public static enum ExecutableFilter implements AutopsyVisitableItem, SearchFilterInterface {
544 
545  ExecutableFilter_EXE(0, "ExecutableFilter_EXE", ".exe", Arrays.asList(".exe")), //NON-NLS
546  ExecutableFilter_DLL(1, "ExecutableFilter_DLL", ".dll", Arrays.asList(".dll")), //NON-NLS
547  ExecutableFilter_BAT(2, "ExecutableFilter_BAT", ".bat", Arrays.asList(".bat")), //NON-NLS
548  ExecutableFilter_CMD(3, "ExecutableFilter_CMD", ".cmd", Arrays.asList(".cmd")), //NON-NLS
549  ExecutableFilter_COM(4, "ExecutableFilter_COM", ".com", Arrays.asList(".com")); //NON-NLS
550 
551  private final int id;
552  private final String name;
553  private final String displayName;
554  private final List<String> filter;
555 
556  private ExecutableFilter(int id, String name, String displayName, List<String> filter) {
557  this.id = id;
558  this.name = name;
559  this.displayName = displayName;
560  this.filter = filter;
561  }
562 
563  @Override
564  public <T> T accept(AutopsyItemVisitor<T> v) {
565  return v.visit(this);
566  }
567 
568  @Override
569  public String getName() {
570  return this.name;
571  }
572 
573  @Override
574  public int getId() {
575  return this.id;
576  }
577 
578  @Override
579  public String getDisplayName() {
580  return this.displayName;
581  }
582 
583  @Override
584  public List<String> getFilter() {
585  return this.filter;
586  }
587  }
588 
589  interface SearchFilterInterface {
590 
591  public String getName();
592 
593  public int getId();
594 
595  public String getDisplayName();
596 
597  public List<String> getFilter();
598 
599  }
600 }
void removeIngestModuleEventListener(final PropertyChangeListener listener)
static synchronized IngestManager getInstance()
void removeIngestJobEventListener(final PropertyChangeListener listener)
String createQuery(FileTypesByExtension.SearchFilterInterface filter)
void addIngestJobEventListener(final PropertyChangeListener listener)
boolean createKeys(List< FileTypesByExtension.SearchFilterInterface > list)
FileTypesByExtNodeChildren(SleuthkitCase skCase, FileTypesByExtension.RootFilter filter, FileTypesByExtObservable o)
RootFilter(int id, String name, String displayName, List< String > filter)
DocumentFilter(int id, String name, String displayName, List< String > filter)
void addIngestModuleEventListener(final PropertyChangeListener listener)
FileExtensionNodeChildren(FileTypesByExtension.SearchFilterInterface filter, SleuthkitCase skCase, Observable o)
synchronized static Logger getLogger(String name)
Definition: Logger.java:161
static void addEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
Definition: Case.java:395
ExecutableFilter(int id, String name, String displayName, List< String > filter)
static void removeEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
Definition: Case.java:440

Copyright © 2012-2016 Basis Technology. Generated on: Fri Sep 29 2017
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.