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;
83 private final PropertyChangeListener
pcl;
102 return "(dir_type = " + TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue() +
")"
104 + TskData.TSK_DB_FILES_TYPE_ENUM.FS.ordinal() +
","
105 + TskData.TSK_DB_FILES_TYPE_ENUM.CARVED.ordinal() +
","
106 + TskData.TSK_DB_FILES_TYPE_ENUM.DERIVED.ordinal() +
","
107 + TskData.TSK_DB_FILES_TYPE_ENUM.LAYOUT_FILE.ordinal() +
","
108 + TskData.TSK_DB_FILES_TYPE_ENUM.LOCAL.ordinal()
109 + (hideSlackFilesInViewsTree() ?
"" : (
"," + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.ordinal()))
111 + ((filteringDataSourceObjId() > 0) ?
" AND data_source_obj_id = " + this.filteringDataSourceObjId() :
" ")
112 + (hideKnownFilesInViewsTree() ? (
" AND (known IS NULL OR known != " + TskData.FileKnown.KNOWN.getFileKnownValue() +
")") :
"");
127 String query =
"SELECT mime_type, count(*) AS count FROM tsk_files "
128 +
" WHERE mime_type IS NOT null "
130 +
" GROUP BY mime_type";
132 existingMimeTypeCounts.clear();
134 if (skCase == null) {
137 try (SleuthkitCase.CaseDbQuery dbQuery = skCase.executeQuery(query)) {
138 ResultSet resultSet = dbQuery.getResultSet();
139 while (resultSet.next()) {
140 final String mime_type = resultSet.getString(
"mime_type");
141 if (!mime_type.isEmpty()) {
143 final String mediaType = StringUtils.substringBefore(mime_type,
"/");
144 final String subType = StringUtils.removeStart(mime_type, mediaType +
"/");
145 if (!mediaType.isEmpty() && !subType.isEmpty()) {
146 final long count = resultSet.getLong(
"count");
147 existingMimeTypeCounts.computeIfAbsent(mediaType, t ->
new HashMap<>())
148 .put(subType, count);
152 }
catch (TskCoreException | SQLException ex) {
153 logger.log(Level.SEVERE,
"Unable to populate File Types by MIME Type tree view from DB: ", ex);
162 this.skCase = typesRoot.getSleuthkitCase();
164 this.pcl = (PropertyChangeEvent evt) -> {
165 String eventType = evt.getPropertyName();
171 }
else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
172 if (evt.getNewValue() == null) {
177 refreshThrottler =
new RefreshThrottler(
new FileTypesByMimeTypeRefresher());
185 public <T> T accept(AutopsyItemVisitor<T> visitor) {
186 return visitor.visit(
this);
189 long filteringDataSourceObjId() {
190 return typesRoot.filteringDataSourceObjId();
203 boolean isEmptyMimeNode =
false;
205 isEmptyMimeNode =
true;
207 return isEmptyMimeNode;
219 typesRoot.updateShowCounts();
254 @NbBundle.Messages({
"FileTypesByMimeType.name.text=By MIME Type"})
256 final String NAME = Bundle.FileTypesByMimeType_name_text();
259 super(Children.create(
new ByMimeTypeNodeChildren(),
true), Lookups.singleton(Bundle.FileTypesByMimeType_name_text()));
261 super.setDisplayName(NAME);
262 this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/file_types.png");
266 public boolean isLeafTypeNode() {
271 public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
272 return visitor.visit(
this);
276 public String getItemType() {
277 return getClass().getName();
282 return existingMimeTypeCounts.isEmpty();
300 final List<String> keylist;
302 keylist =
new ArrayList<>(existingMimeTypeCounts.keySet());
304 Collections.sort(keylist);
305 mediaTypeNodes.addAll(keylist);
312 return new MediaTypeNode(key);
316 public void update(Observable o, Object arg) {
327 @NbBundle.Messages({
"FileTypesByMimeTypeNode.createSheet.mediaType.name=Type",
328 "FileTypesByMimeTypeNode.createSheet.mediaType.displayName=Type",
329 "FileTypesByMimeTypeNode.createSheet.mediaType.desc=no description"})
331 MediaTypeNode(String name) {
332 super(Children.create(
new MediaTypeNodeChildren(name),
true), Lookups.singleton(name));
334 setDisplayName(name);
335 this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/file_types.png");
339 public boolean isLeafTypeNode() {
344 public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
345 return visitor.visit(
this);
349 protected Sheet createSheet() {
350 Sheet sheet = super.createSheet();
351 Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
352 if (sheetSet == null) {
353 sheetSet = Sheet.createPropertiesSet();
356 sheetSet.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()));
361 public String getItemType() {
362 return getClass().getName();
378 this.mediaType = name;
383 mediaTypeNodes.addAll(existingMimeTypeCounts.get(mediaType).keySet());
389 String mimeType = mediaType +
"/" + subtype;
390 return new MediaSubTypeNode(mimeType);
394 public void update(Observable o, Object arg) {
404 final class MediaSubTypeNode
extends FileTypes.BGCountUpdatingNode {
406 @NbBundle.Messages({
"FileTypesByMimeTypeNode.createSheet.mediaSubtype.name=Subtype",
407 "FileTypesByMimeTypeNode.createSheet.mediaSubtype.displayName=Subtype",
408 "FileTypesByMimeTypeNode.createSheet.mediaSubtype.desc=no description"})
409 private final String mimeType;
410 private final String subType;
412 private MediaSubTypeNode(String mimeType) {
413 super(typesRoot, Children.create(
new MediaSubTypeNodeChildren(mimeType),
true), Lookups.singleton(mimeType));
414 this.mimeType = mimeType;
415 this.subType = StringUtils.substringAfter(mimeType,
"/");
416 super.setName(mimeType);
417 super.setDisplayName(subType);
419 this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/file-filter-icon.png");
430 public boolean isLeafTypeNode() {
435 public <T> T accept(DisplayableItemNodeVisitor< T> visitor) {
436 return visitor.visit(
this);
440 protected Sheet createSheet() {
441 Sheet sheet = super.createSheet();
442 Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
443 if (sheetSet == null) {
444 sheetSet = Sheet.createPropertiesSet();
447 sheetSet.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()));
452 public String getItemType() {
453 return getClass().getName();
457 public void update(Observable o, Object arg) {
462 String getDisplayNameBase() {
467 long calculateChildCount() {
468 return existingMimeTypeCounts.get(StringUtils.substringBefore(mimeType,
"/")).
get(subType);
482 super(mimeType,
new ViewsKnownAndSlackFilter<>());
488 public void update(Observable o, Object arg) {
500 return skCase.findAllFilesWhere(
createBaseWhereExpr() +
" AND mime_type = '" + mimeType +
"'")
501 .stream().map(f ->
new FileTypesKey(f)).collect(Collectors.toList());
502 }
catch (TskCoreException ex) {
503 logger.log(Level.SEVERE,
"Couldn't get search results", ex);
505 return Collections.emptyList();
void registerForIngestModuleEvents()
String createBaseWhereExpr()
final SleuthkitCase skCase
static synchronized IngestManager getInstance()
boolean createKeys(List< String > mediaTypeNodes)
static final Set< Case.Events > CASE_EVENTS_OF_INTEREST
void unregisterEventListener()
void update(Observable o, Object arg)
static boolean hideKnownFilesInViewsTree()
void removeIngestJobEventListener(final PropertyChangeListener listener)
final RefreshThrottler refreshThrottler
final PropertyChangeListener pcl
static boolean hideSlackFilesInViewsTree()
boolean isRefreshRequired(PropertyChangeEvent evt)
final HashMap< String, Map< String, Long > > existingMimeTypeCounts
Node createNodeForKey(String key)
static boolean isEmptyMimeTypeNode(Node node)
synchronized static Logger getLogger(String name)
static Case getCurrentCaseThrows()
static final Set< IngestManager.IngestJobEvent > INGEST_JOB_EVENTS_OF_INTEREST
static void removeEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
final FileTypes typesRoot
static final Logger logger