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.LOCAL.ordinal()
101 + (hideSlackFilesInViewsTree() ?
"" : (
"," + TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.ordinal()))
103 + (hideKnownFilesInViewsTree() ? (
" AND (known IS NULL OR known != " + TskData.FileKnown.KNOWN.getFileKnownValue() +
")") :
"");
117 String query =
"SELECT mime_type, count(*) AS count FROM tsk_files "
118 +
" WHERE mime_type IS NOT null "
120 +
" GROUP BY mime_type";
122 existingMimeTypeCounts.clear();
124 if (skCase == null) {
127 try (SleuthkitCase.CaseDbQuery dbQuery = skCase.executeQuery(query)) {
128 ResultSet resultSet = dbQuery.getResultSet();
129 while (resultSet.next()) {
130 final String mime_type = resultSet.getString(
"mime_type");
131 if (!mime_type.isEmpty()) {
133 final String mediaType = StringUtils.substringBefore(mime_type,
"/");
134 final String subType = StringUtils.removeStart(mime_type, mediaType +
"/");
135 if (!mediaType.isEmpty() && !subType.isEmpty()) {
136 final long count = resultSet.getLong(
"count");
137 existingMimeTypeCounts.computeIfAbsent(mediaType, t ->
new HashMap<>())
138 .put(subType, count);
142 }
catch (TskCoreException | SQLException ex) {
143 logger.log(Level.SEVERE,
"Unable to populate File Types by MIME Type tree view from DB: ", ex);
152 this.skCase = typesRoot.getSleuthkitCase();
154 this.pcl = (PropertyChangeEvent evt) -> {
155 String eventType = evt.getPropertyName();
168 typesRoot.updateShowCounts();
170 }
catch (NoCurrentCaseException notUsed) {
175 }
else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
176 if (evt.getNewValue() == null) {
181 IngestManager.getInstance().addIngestJobEventListener(pcl);
187 public <T> T accept(AutopsyItemVisitor<T> visitor) {
188 return visitor.visit(
this);
201 boolean isEmptyMimeNode =
false;
203 isEmptyMimeNode =
true;
205 return isEmptyMimeNode;
217 @NbBundle.Messages({
"FileTypesByMimeType.name.text=By MIME Type"})
219 final String NAME = Bundle.FileTypesByMimeType_name_text();
222 super(Children.create(
new ByMimeTypeNodeChildren(),
true), Lookups.singleton(Bundle.FileTypesByMimeType_name_text()));
224 super.setDisplayName(NAME);
225 this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/file_types.png");
229 public boolean isLeafTypeNode() {
234 public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
235 return visitor.visit(
this);
239 public String getItemType() {
240 return getClass().getName();
245 return existingMimeTypeCounts.isEmpty();
263 final List<String> keylist;
265 keylist =
new ArrayList<>(existingMimeTypeCounts.keySet());
267 Collections.sort(keylist);
268 mediaTypeNodes.addAll(keylist);
275 return new MediaTypeNode(key);
279 public void update(Observable o, Object arg) {
290 @NbBundle.Messages({
"FileTypesByMimeTypeNode.createSheet.mediaType.name=Type",
291 "FileTypesByMimeTypeNode.createSheet.mediaType.displayName=Type",
292 "FileTypesByMimeTypeNode.createSheet.mediaType.desc=no description"})
294 MediaTypeNode(String name) {
295 super(Children.create(
new MediaTypeNodeChildren(name),
true), Lookups.singleton(name));
297 setDisplayName(name);
298 this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/file_types.png");
302 public boolean isLeafTypeNode() {
307 public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
308 return visitor.visit(
this);
312 protected Sheet createSheet() {
313 Sheet sheet = super.createSheet();
314 Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
315 if (sheetSet == null) {
316 sheetSet = Sheet.createPropertiesSet();
319 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()));
324 public String getItemType() {
325 return getClass().getName();
341 this.mediaType = name;
346 mediaTypeNodes.addAll(existingMimeTypeCounts.get(mediaType).keySet());
352 String mimeType = mediaType +
"/" + subtype;
353 return new MediaSubTypeNode(mimeType);
357 public void update(Observable o, Object arg) {
367 class MediaSubTypeNode
extends FileTypes.BGCountUpdatingNode {
369 @NbBundle.Messages({
"FileTypesByMimeTypeNode.createSheet.mediaSubtype.name=Subtype",
370 "FileTypesByMimeTypeNode.createSheet.mediaSubtype.displayName=Subtype",
371 "FileTypesByMimeTypeNode.createSheet.mediaSubtype.desc=no description"})
372 private final String mimeType;
373 private final String subType;
375 private MediaSubTypeNode(String mimeType) {
376 super(typesRoot, Children.create(
new MediaSubTypeNodeChildren(mimeType),
true), Lookups.singleton(mimeType));
377 this.mimeType = mimeType;
378 this.subType = StringUtils.substringAfter(mimeType,
"/");
379 super.setName(mimeType);
380 super.setDisplayName(subType);
382 this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/file-filter-icon.png");
393 public boolean isLeafTypeNode() {
398 public <T> T accept(DisplayableItemNodeVisitor< T> visitor) {
399 return visitor.visit(
this);
403 protected Sheet createSheet() {
404 Sheet sheet = super.createSheet();
405 Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
406 if (sheetSet == null) {
407 sheetSet = Sheet.createPropertiesSet();
410 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()));
415 public String getItemType() {
416 return getClass().getName();
420 public void update(Observable o, Object arg) {
425 String getDisplayNameBase() {
430 long calculateChildCount() {
431 return existingMimeTypeCounts.get(StringUtils.substringBefore(mimeType,
"/")).
get(subType);
453 list.addAll(skCase.findAllFilesWhere(
createBaseWhereExpr() +
" AND mime_type = '" + mimeType +
"'")
454 .stream().map(f ->
new FileTypesKey(f)).collect(Collectors.toList()));
455 }
catch (TskCoreException ex) {
456 logger.log(Level.SEVERE,
"Couldn't get search results", ex);
462 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)
synchronized static Logger getLogger(String name)
static Case getCurrentCaseThrows()
static void removeEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
static String createBaseWhereExpr()
final FileTypes typesRoot
static final Logger logger