19 package org.sleuthkit.autopsy.datamodel;
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.EnumSet;
28 import java.util.HashMap;
29 import java.util.List;
31 import java.util.Observable;
32 import java.util.Observer;
34 import java.util.logging.Level;
35 import java.util.stream.Collectors;
36 import org.apache.commons.lang3.StringUtils;
37 import org.openide.nodes.ChildFactory;
38 import org.openide.nodes.Children;
39 import org.openide.nodes.Node;
40 import org.openide.nodes.Sheet;
41 import org.openide.util.NbBundle;
42 import org.openide.util.lookup.Lookups;
81 private final PropertyChangeListener
pcl;
94 return "(dir_type = " + TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue() +
")"
96 + TskData.TSK_DB_FILES_TYPE_ENUM.FS.ordinal() +
","
97 + TskData.TSK_DB_FILES_TYPE_ENUM.CARVED.ordinal() +
","
98 + TskData.TSK_DB_FILES_TYPE_ENUM.DERIVED.ordinal() +
","
99 + TskData.TSK_DB_FILES_TYPE_ENUM.LOCAL.ordinal()
100 + (hideSlackFilesInViewsTree() ?
"" : (
"," + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.ordinal()))
102 + (hideKnownFilesInViewsTree() ? (
" AND (known IS NULL OR known != " + TskData.FileKnown.KNOWN.getFileKnownValue() +
")") :
"");
116 String query =
"SELECT mime_type, count(*) AS count FROM tsk_files "
117 +
" WHERE mime_type IS NOT null "
119 +
" GROUP BY mime_type";
121 existingMimeTypeCounts.clear();
123 if (skCase == null) {
126 try (SleuthkitCase.CaseDbQuery dbQuery = skCase.executeQuery(query)) {
127 ResultSet resultSet = dbQuery.getResultSet();
128 while (resultSet.next()) {
129 final String mime_type = resultSet.getString(
"mime_type");
130 if (!mime_type.isEmpty()) {
132 final String mediaType = StringUtils.substringBefore(mime_type,
"/");
133 final String subType = StringUtils.removeStart(mime_type, mediaType +
"/");
134 if (!mediaType.isEmpty() && !subType.isEmpty()) {
135 final long count = resultSet.getLong(
"count");
136 existingMimeTypeCounts.computeIfAbsent(mediaType, t ->
new HashMap<>())
137 .put(subType, count);
141 }
catch (TskCoreException | SQLException ex) {
142 logger.log(Level.SEVERE,
"Unable to populate File Types by MIME Type tree view from DB: ", ex);
151 this.skCase = typesRoot.getSleuthkitCase();
153 this.pcl = (PropertyChangeEvent evt) -> {
154 String eventType = evt.getPropertyName();
167 typesRoot.updateShowCounts();
169 }
catch (IllegalStateException notUsed) {
174 }
else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
175 if (evt.getNewValue() == null) {
180 IngestManager.getInstance().addIngestJobEventListener(pcl);
186 public <T> T accept(AutopsyItemVisitor<T> v) {
187 return v.visit(
this);
200 boolean isEmptyMimeNode =
false;
202 isEmptyMimeNode =
true;
204 return isEmptyMimeNode;
216 @NbBundle.Messages({
"FileTypesByMimeType.name.text=By MIME Type"})
218 final String NAME = Bundle.FileTypesByMimeType_name_text();
221 super(Children.create(
new ByMimeTypeNodeChildren(),
true), Lookups.singleton(Bundle.FileTypesByMimeType_name_text()));
223 super.setDisplayName(NAME);
224 this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/file_types.png");
228 public boolean isLeafTypeNode() {
233 public <T> T accept(DisplayableItemNodeVisitor<T> v) {
234 return v.visit(
this);
238 public String getItemType() {
239 return getClass().getName();
244 return existingMimeTypeCounts.isEmpty();
262 final List<String> keylist;
264 keylist =
new ArrayList<>(existingMimeTypeCounts.keySet());
266 Collections.sort(keylist);
267 mediaTypeNodes.addAll(keylist);
274 return new MediaTypeNode(key);
278 public void update(Observable o, Object arg) {
289 @NbBundle.Messages({
"FileTypesByMimeTypeNode.createSheet.mediaType.name=Type",
290 "FileTypesByMimeTypeNode.createSheet.mediaType.displayName=Type",
291 "FileTypesByMimeTypeNode.createSheet.mediaType.desc=no description"})
293 MediaTypeNode(String name) {
294 super(Children.create(
new MediaTypeNodeChildren(name),
true), Lookups.singleton(name));
296 setDisplayName(name);
297 this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/file_types.png");
301 public boolean isLeafTypeNode() {
306 public <T> T accept(DisplayableItemNodeVisitor<T> v) {
307 return v.visit(
this);
311 protected Sheet createSheet() {
312 Sheet s = super.createSheet();
313 Sheet.Set ss = s.get(Sheet.PROPERTIES);
315 ss = Sheet.createPropertiesSet();
318 ss.put(
new NodeProperty<>(NbBundle.getMessage(
this.getClass(),
"FileTypesByMimeTypeNode.createSheet.mediaType.name"), NbBundle.getMessage(
this.getClass(),
"FileTypesByMimeTypeNode.createSheet.mediaType.displayName"), NbBundle.getMessage(
this.getClass(),
"FileTypesByMimeTypeNode.createSheet.mediaType.desc"), getDisplayName()));
323 public String getItemType() {
324 return getClass().getName();
340 this.mediaType = name;
345 mediaTypeNodes.addAll(existingMimeTypeCounts.get(mediaType).keySet());
351 String mimeType = mediaType +
"/" + subtype;
352 return new MediaSubTypeNode(mimeType);
356 public void update(Observable o, Object arg) {
366 class MediaSubTypeNode
extends FileTypes.BGCountUpdatingNode {
368 @NbBundle.Messages({
"FileTypesByMimeTypeNode.createSheet.mediaSubtype.name=Subtype",
369 "FileTypesByMimeTypeNode.createSheet.mediaSubtype.displayName=Subtype",
370 "FileTypesByMimeTypeNode.createSheet.mediaSubtype.desc=no description"})
371 private final String mimeType;
372 private final String subType;
374 private MediaSubTypeNode(String mimeType) {
375 super(typesRoot, Children.create(
new MediaSubTypeNodeChildren(mimeType),
true), Lookups.singleton(mimeType));
376 this.mimeType = mimeType;
377 this.subType = StringUtils.substringAfter(mimeType,
"/");
378 super.setName(mimeType);
379 super.setDisplayName(subType);
381 this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/file-filter-icon.png");
392 public boolean isLeafTypeNode() {
397 public <T> T accept(DisplayableItemNodeVisitor< T> v) {
398 return v.visit(
this);
402 protected Sheet createSheet() {
403 Sheet s = super.createSheet();
404 Sheet.Set ss = s.get(Sheet.PROPERTIES);
406 ss = Sheet.createPropertiesSet();
409 ss.put(
new NodeProperty<>(NbBundle.getMessage(
this.getClass(),
"FileTypesByMimeTypeNode.createSheet.mediaSubtype.name"), NbBundle.getMessage(
this.getClass(),
"FileTypesByMimeTypeNode.createSheet.mediaSubtype.displayName"), NbBundle.getMessage(
this.getClass(),
"FileTypesByMimeTypeNode.createSheet.mediaSubtype.desc"), getDisplayName()));
414 public String getItemType() {
415 return getClass().getName();
419 public void update(Observable o, Object arg) {
424 String getDisplayNameBase() {
429 long calculateChildCount() {
430 return existingMimeTypeCounts.get(StringUtils.substringBefore(mimeType,
"/")).
get(subType);
452 list.addAll(skCase.findAllFilesWhere(
createBaseWhereExpr() +
" AND mime_type = '" + mimeType +
"'")
453 .stream().map(f ->
new FileTypesKey(f)).collect(Collectors.toList()));
454 }
catch (TskCoreException ex) {
455 logger.log(Level.SEVERE,
"Couldn't get search results", ex);
461 public void update(Observable o, Object arg) {
final SleuthkitCase skCase
static synchronized IngestManager getInstance()
boolean createKeys(List< String > mediaTypeNodes)
static final Set< Case.Events > CASE_EVENTS_OF_INTEREST
void update(Observable o, Object arg)
static boolean hideKnownFilesInViewsTree()
void removeIngestJobEventListener(final PropertyChangeListener listener)
final PropertyChangeListener pcl
static boolean hideSlackFilesInViewsTree()
final HashMap< String, Map< String, Long > > existingMimeTypeCounts
Node createNodeForKey(String key)
static boolean isEmptyMimeTypeNode(Node node)
static Case getCurrentCase()
synchronized static Logger getLogger(String name)
static void removeEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
static String createBaseWhereExpr()
final FileTypes typesRoot
static final Logger logger