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

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