Autopsy  4.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
FileTypesByMimeType.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2011-2016 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.sql.ResultSet;
24 import java.sql.SQLException;
25 import java.util.ArrayList;
26 import java.util.Collections;
27 import java.util.HashMap;
28 import java.util.List;
29 import java.util.Observable;
30 import java.util.Observer;
31 import java.util.logging.Level;
32 import org.openide.nodes.AbstractNode;
33 import org.openide.nodes.ChildFactory;
34 import org.openide.nodes.Children;
35 import org.openide.nodes.Node;
36 import org.openide.util.NbBundle;
41 import org.sleuthkit.datamodel.AbstractFile;
42 import org.sleuthkit.datamodel.Content;
43 import org.sleuthkit.datamodel.ContentVisitor;
44 import org.sleuthkit.datamodel.DerivedFile;
45 import org.sleuthkit.datamodel.Directory;
46 import org.sleuthkit.datamodel.File;
47 import org.sleuthkit.datamodel.LayoutFile;
48 import org.sleuthkit.datamodel.LocalFile;
49 import org.sleuthkit.datamodel.SleuthkitCase;
50 import org.sleuthkit.datamodel.TskCoreException;
51 import org.sleuthkit.datamodel.TskData;
52 
60 public final class FileTypesByMimeType extends Observable implements AutopsyVisitableItem {
61 
62  private final SleuthkitCase skCase;
68  private final HashMap<String, List<String>> existingMimeTypes = new HashMap<>();
69  private static final Logger LOGGER = Logger.getLogger(FileTypesByMimeType.class.getName());
70 
71  private void removeListeners() {
72  deleteObservers();
75  }
76 
77  /*
78  * The pcl is in the class because it has the easiest mechanisms to add
79  * and remove itself during its life cycles.
80  */
81  private final PropertyChangeListener pcl = (PropertyChangeEvent evt) -> {
82  String eventType = evt.getPropertyName();
83  if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
84  || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) {
85 
92  try {
95  } catch (IllegalStateException notUsed) {
99  }
100  } else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
101  if (evt.getNewValue() == null) {
102  removeListeners();
103  }
104  }
105  };
106 
113  private List<String> getMediaTypeList() {
114  synchronized (existingMimeTypes) {
115  List<String> mediaTypes = new ArrayList<>(existingMimeTypes.keySet());
116  Collections.sort(mediaTypes);
117  return mediaTypes;
118  }
119  }
120 
125  private void populateHashMap() {
126  StringBuilder allDistinctMimeTypesQuery = new StringBuilder();
127  allDistinctMimeTypesQuery.append("SELECT DISTINCT mime_type from tsk_files where mime_type IS NOT null"); //NON-NLS
128  allDistinctMimeTypesQuery.append(" AND dir_type = ").append(TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue()); //NON-NLS
129  allDistinctMimeTypesQuery.append(" AND (type IN (").append(TskData.TSK_DB_FILES_TYPE_ENUM.FS.ordinal()).append(","); //NON-NLS
130  allDistinctMimeTypesQuery.append(TskData.TSK_DB_FILES_TYPE_ENUM.CARVED.ordinal()).append(",");
131  allDistinctMimeTypesQuery.append(TskData.TSK_DB_FILES_TYPE_ENUM.DERIVED.ordinal()).append(",");
132  allDistinctMimeTypesQuery.append(TskData.TSK_DB_FILES_TYPE_ENUM.LOCAL.ordinal()).append("))");
133  synchronized (existingMimeTypes) {
134  existingMimeTypes.clear();
135 
136  if (skCase == null) {
137 
138  return;
139  }
140  try (SleuthkitCase.CaseDbQuery dbQuery = skCase.executeQuery(allDistinctMimeTypesQuery.toString())) {
141  ResultSet resultSet = dbQuery.getResultSet();
142  while (resultSet.next()) {
143  final String mime_type = resultSet.getString("mime_type"); //NON-NLS
144  if (!mime_type.isEmpty()) {
145  String mimeType[] = mime_type.split("/");
146  if (!mimeType[0].isEmpty() && !mimeType[1].isEmpty()) {
147  if (!existingMimeTypes.containsKey(mimeType[0])) {
148  existingMimeTypes.put(mimeType[0], new ArrayList<>());
149  }
150  existingMimeTypes.get(mimeType[0]).add(mimeType[1]);
151  }
152  }
153  }
154  } catch (TskCoreException | SQLException ex) {
155  LOGGER.log(Level.SEVERE, "Unable to populate File Types by MIME Type tree view from DB: ", ex); //NON-NLS
156  }
157  }
158 
159  setChanged();
160 
161  notifyObservers();
162  }
163 
164  FileTypesByMimeType(SleuthkitCase skCase) {
167  this.skCase = skCase;
168  populateHashMap();
169  }
170 
171  @Override
172  public <T> T accept(AutopsyItemVisitor<T> v) {
173  return v.visit(this);
174  }
175 
184  public static boolean isEmptyMimeTypeNode(Node node) {
185  boolean isEmptyMimeNode = false;
186  if (node instanceof FileTypesByMimeType.ByMimeTypeNode && ((FileTypesByMimeType.ByMimeTypeNode) node).isEmpty()) {
187  isEmptyMimeNode = true;
188  }
189  return isEmptyMimeNode;
190 
191  }
192 
199  class ByMimeTypeNode extends DisplayableItemNode {
200 
201  @NbBundle.Messages("FileTypesByMimeType.name.text=By MIME Type")
202  final String NAME = Bundle.FileTypesByMimeType_name_text();
203 
204  ByMimeTypeNode() {
205  super(Children.create(new ByMimeTypeNodeChildren(), true));
206  super.setName(NAME);
207  super.setDisplayName(NAME);
208  this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file_types.png");
209  }
210 
211  @Override
212  public boolean isLeafTypeNode() {
213  return false;
214  }
215 
216  @Override
217  public <T> T accept(DisplayableItemNodeVisitor<T> v) {
218  return v.visit(this);
219  }
220 
221  @Override
222  public String getItemType() {
223  return getClass().getName();
224  }
225 
226  boolean isEmpty() {
227  return existingMimeTypes.isEmpty();
228  }
229 
230  }
231 
236  private class ByMimeTypeNodeChildren extends ChildFactory<String> implements Observer {
237 
239  super();
240  addObserver(this);
241  }
242 
243  @Override
244  protected boolean createKeys(List<String> mediaTypeNodes) {
245  if (!existingMimeTypes.isEmpty()) {
246  mediaTypeNodes.addAll(getMediaTypeList());
247  }
248  return true;
249  }
250 
251  @Override
252  protected Node createNodeForKey(String key) {
253  return new MediaTypeNode(key);
254  }
255 
256  @Override
257  public void update(Observable o, Object arg) {
258  refresh(true);
259  }
260 
261  }
262 
267  class MediaTypeNode extends DisplayableItemNode {
268 
269  MediaTypeNode(String name) {
270  super(Children.create(new MediaTypeNodeChildren(name), true));
271  setName(name);
272  setDisplayName(name);
273  this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file_types.png");
274  }
275 
276  @Override
277  public boolean isLeafTypeNode() {
278  return false;
279  }
280 
281  @Override
282  public <T> T accept(DisplayableItemNodeVisitor<T> v) {
283  return v.visit(this);
284  }
285 
286  @Override
287  public String getItemType() {
288  return getClass().getName();
289  }
290 
291  }
292 
298  private class MediaTypeNodeChildren extends ChildFactory<String> implements Observer {
299 
300  String mediaType;
301 
302  MediaTypeNodeChildren(String name) {
303  addObserver(this);
304  this.mediaType = name;
305  }
306 
307  @Override
308  protected boolean createKeys(List<String> mediaTypeNodes) {
309  mediaTypeNodes.addAll(existingMimeTypes.get(mediaType));
310  return true;
311  }
312 
313  @Override
314  protected Node createNodeForKey(String subtype) {
315  String mimeType = mediaType + "/" + subtype;
316  return new MediaSubTypeNode(mimeType);
317  }
318 
319  @Override
320  public void update(Observable o, Object arg) {
321  refresh(true);
322  }
323 
324  }
325 
330  class MediaSubTypeNode extends DisplayableItemNode implements Observer {
331 
332  private MediaSubTypeNode(String mimeType) {
333  super(Children.create(new MediaSubTypeNodeChildren(mimeType), true));
334  addObserver(this);
335  init(mimeType);
336  }
337 
338  private void init(String mimeType) {
339  super.setName(mimeType);
340  updateDisplayName(mimeType);
341  this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-filter-icon.png"); //NON-NLS
342  }
343 
351  private void updateDisplayName(String mimeType) {
352 
353  final long count = new MediaSubTypeNodeChildren(mimeType).calculateItems(skCase, mimeType);
354 
355  super.setDisplayName(mimeType.split("/")[1] + " (" + count + ")");
356  }
357 
364  @Override
365  public boolean isLeafTypeNode() {
366  return true;
367  }
368 
369  @Override
370  public <T> T accept(DisplayableItemNodeVisitor<T> v) {
371  return v.visit(this);
372  }
373 
374  @Override
375  public String getItemType() {
376  return getClass().getName();
377  }
378 
379  @Override
380  public void update(Observable o, Object arg) {
381  updateDisplayName(getName());
382  }
383  }
384 
390  private class MediaSubTypeNodeChildren extends ChildFactory.Detachable<Content> implements Observer {
391 
392  private final String mimeType;
393 
394  private MediaSubTypeNodeChildren(String mimeType) {
395  super();
396  addObserver(this);
397  this.mimeType = mimeType;
398  }
399 
406  private long calculateItems(SleuthkitCase sleuthkitCase, String mime_type) {
407  try {
408  return sleuthkitCase.countFilesWhere(createQuery(mime_type));
409  } catch (TskCoreException ex) {
410  LOGGER.log(Level.SEVERE, "Error getting file search view count", ex); //NON-NLS
411  return 0;
412  }
413  }
414 
424  @Override
425  protected boolean createKeys(List<Content> list) {
426  try {
427  List<AbstractFile> files = skCase.findAllFilesWhere(createQuery(mimeType));
428  list.addAll(files);
429  } catch (TskCoreException ex) {
430  LOGGER.log(Level.SEVERE, "Couldn't get search results", ex); //NON-NLS
431  }
432  return true;
433  }
434 
445  private String createQuery(String mime_type) {
446  StringBuilder query = new StringBuilder();
447  query.append("(dir_type = ").append(TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue()).append(")"); //NON-NLS
448  query.append(" AND (type IN (").append(TskData.TSK_DB_FILES_TYPE_ENUM.FS.ordinal()).append(","); //NON-NLS
449  query.append(TskData.TSK_DB_FILES_TYPE_ENUM.CARVED.ordinal()).append(",");
450  query.append(TskData.TSK_DB_FILES_TYPE_ENUM.DERIVED.ordinal()).append(",");
451  query.append(TskData.TSK_DB_FILES_TYPE_ENUM.LOCAL.ordinal()).append("))");
453  query.append(" AND (known IS NULL OR known != ").append(TskData.FileKnown.KNOWN.getFileKnownValue()).append(")"); //NON-NLS
454  }
455  query.append(" AND mime_type = '").append(mime_type).append("'"); //NON-NLS
456  return query.toString();
457  }
458 
459  @Override
460  public void update(Observable o, Object arg) {
461  refresh(true);
462  }
463 
471  @Override
472  protected Node createNodeForKey(Content key) {
473  return key.accept(new ContentVisitor.Default<AbstractNode>() {
474  @Override
475  public FileNode visit(File f) {
476  return new FileNode(f, false);
477  }
478 
479  @Override
480  public DirectoryNode visit(Directory d) {
481  return new DirectoryNode(d);
482  }
483 
484  @Override
485  public LayoutFileNode visit(LayoutFile lf) {
486  return new LayoutFileNode(lf);
487  }
488 
489  @Override
490  public LocalFileNode visit(DerivedFile df) {
491  return new LocalFileNode(df);
492  }
493 
494  @Override
495  public LocalFileNode visit(LocalFile lf) {
496  return new LocalFileNode(lf);
497  }
498 
499  @Override
500  protected AbstractNode defaultVisit(Content di) {
501  throw new UnsupportedOperationException(NbBundle.getMessage(this.getClass(), "FileTypeChildren.exception.notSupported.msg", di.toString()));
502  }
503  });
504  }
505  }
506 
507 }
static synchronized IngestManager getInstance()
static void removePropertyChangeListener(PropertyChangeListener listener)
Definition: Case.java:318
void removeIngestJobEventListener(final PropertyChangeListener listener)
void addIngestJobEventListener(final PropertyChangeListener listener)
final HashMap< String, List< String > > existingMimeTypes
static void addPropertyChangeListener(PropertyChangeListener listener)
Definition: Case.java:306
synchronized static Logger getLogger(String name)
Definition: Logger.java:161

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