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;
82 private final PropertyChangeListener
pcl;
95 return "(dir_type = " + TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue() +
")"
97 + TskData.TSK_DB_FILES_TYPE_ENUM.FS.ordinal() +
","
98 + TskData.TSK_DB_FILES_TYPE_ENUM.CARVED.ordinal() +
","
99 + TskData.TSK_DB_FILES_TYPE_ENUM.DERIVED.ordinal() +
","
100 + TskData.TSK_DB_FILES_TYPE_ENUM.LAYOUT_FILE.ordinal() +
","
101 + TskData.TSK_DB_FILES_TYPE_ENUM.LOCAL.ordinal()
102 + (hideSlackFilesInViewsTree() ?
"" : (
"," + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.ordinal()))
104 + ((filteringDataSourceObjId() > 0) ?
" AND data_source_obj_id = " + this.filteringDataSourceObjId() :
" ")
105 + (hideKnownFilesInViewsTree() ? (
" AND (known IS NULL OR known != " + TskData.FileKnown.KNOWN.getFileKnownValue() +
")") :
"");
119 String query =
"SELECT mime_type, count(*) AS count FROM tsk_files "
120 +
" WHERE mime_type IS NOT null "
122 +
" GROUP BY mime_type";
124 existingMimeTypeCounts.clear();
126 if (skCase == null) {
129 try (SleuthkitCase.CaseDbQuery dbQuery = skCase.executeQuery(query)) {
130 ResultSet resultSet = dbQuery.getResultSet();
131 while (resultSet.next()) {
132 final String mime_type = resultSet.getString(
"mime_type");
133 if (!mime_type.isEmpty()) {
135 final String mediaType = StringUtils.substringBefore(mime_type,
"/");
136 final String subType = StringUtils.removeStart(mime_type, mediaType +
"/");
137 if (!mediaType.isEmpty() && !subType.isEmpty()) {
138 final long count = resultSet.getLong(
"count");
139 existingMimeTypeCounts.computeIfAbsent(mediaType, t ->
new HashMap<>())
140 .put(subType, count);
144 }
catch (TskCoreException | SQLException ex) {
145 logger.log(Level.SEVERE,
"Unable to populate File Types by MIME Type tree view from DB: ", ex);
154 this.skCase = typesRoot.getSleuthkitCase();
156 this.pcl = (PropertyChangeEvent evt) -> {
157 String eventType = evt.getPropertyName();
170 typesRoot.updateShowCounts();
172 }
catch (NoCurrentCaseException notUsed) {
177 }
else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
178 if (evt.getNewValue() == null) {
189 public <T> T accept(AutopsyItemVisitor<T> visitor) {
190 return visitor.visit(
this);
193 long filteringDataSourceObjId() {
194 return typesRoot.filteringDataSourceObjId();
207 boolean isEmptyMimeNode =
false;
209 isEmptyMimeNode =
true;
211 return isEmptyMimeNode;
223 @NbBundle.Messages({
"FileTypesByMimeType.name.text=By MIME Type"})
225 final String NAME = Bundle.FileTypesByMimeType_name_text();
228 super(Children.create(
new ByMimeTypeNodeChildren(),
true), Lookups.singleton(Bundle.FileTypesByMimeType_name_text()));
230 super.setDisplayName(NAME);
231 this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/file_types.png");
235 public boolean isLeafTypeNode() {
240 public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
241 return visitor.visit(
this);
245 public String getItemType() {
246 return getClass().getName();
251 return existingMimeTypeCounts.isEmpty();
269 final List<String> keylist;
271 keylist =
new ArrayList<>(existingMimeTypeCounts.keySet());
273 Collections.sort(keylist);
274 mediaTypeNodes.addAll(keylist);
281 return new MediaTypeNode(key);
285 public void update(Observable o, Object arg) {
296 @NbBundle.Messages({
"FileTypesByMimeTypeNode.createSheet.mediaType.name=Type",
297 "FileTypesByMimeTypeNode.createSheet.mediaType.displayName=Type",
298 "FileTypesByMimeTypeNode.createSheet.mediaType.desc=no description"})
300 MediaTypeNode(String name) {
301 super(Children.create(
new MediaTypeNodeChildren(name),
true), Lookups.singleton(name));
303 setDisplayName(name);
304 this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/file_types.png");
308 public boolean isLeafTypeNode() {
313 public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
314 return visitor.visit(
this);
318 protected Sheet createSheet() {
319 Sheet sheet = super.createSheet();
320 Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
321 if (sheetSet == null) {
322 sheetSet = Sheet.createPropertiesSet();
325 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()));
330 public String getItemType() {
331 return getClass().getName();
347 this.mediaType = name;
352 mediaTypeNodes.addAll(existingMimeTypeCounts.get(mediaType).keySet());
358 String mimeType = mediaType +
"/" + subtype;
359 return new MediaSubTypeNode(mimeType);
363 public void update(Observable o, Object arg) {
373 final class MediaSubTypeNode
extends FileTypes.BGCountUpdatingNode {
375 @NbBundle.Messages({
"FileTypesByMimeTypeNode.createSheet.mediaSubtype.name=Subtype",
376 "FileTypesByMimeTypeNode.createSheet.mediaSubtype.displayName=Subtype",
377 "FileTypesByMimeTypeNode.createSheet.mediaSubtype.desc=no description"})
378 private final String mimeType;
379 private final String subType;
381 private MediaSubTypeNode(String mimeType) {
382 super(typesRoot, Children.create(
new MediaSubTypeNodeChildren(mimeType),
true), Lookups.singleton(mimeType));
383 this.mimeType = mimeType;
384 this.subType = StringUtils.substringAfter(mimeType,
"/");
385 super.setName(mimeType);
386 super.setDisplayName(subType);
388 this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/file-filter-icon.png");
399 public boolean isLeafTypeNode() {
404 public <T> T accept(DisplayableItemNodeVisitor< T> visitor) {
405 return visitor.visit(
this);
409 protected Sheet createSheet() {
410 Sheet sheet = super.createSheet();
411 Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
412 if (sheetSet == null) {
413 sheetSet = Sheet.createPropertiesSet();
416 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()));
421 public String getItemType() {
422 return getClass().getName();
426 public void update(Observable o, Object arg) {
431 String getDisplayNameBase() {
436 long calculateChildCount() {
437 return existingMimeTypeCounts.get(StringUtils.substringBefore(mimeType,
"/")).
get(subType);
451 super(mimeType,
new ViewsKnownAndSlackFilter<>());
457 public void update(Observable o, Object arg) {
469 return skCase.findAllFilesWhere(
createBaseWhereExpr() +
" AND mime_type = '" + mimeType +
"'")
470 .stream().map(f ->
new FileTypesKey(f)).collect(Collectors.toList());
471 }
catch (TskCoreException ex) {
472 logger.log(Level.SEVERE,
"Couldn't get search results", ex);
474 return Collections.emptyList();
String createBaseWhereExpr()
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)
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