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

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