Autopsy 4.22.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
DeletedContent.java
Go to the documentation of this file.
1/*
2 * Autopsy Forensic Browser
3 *
4 * Copyright 2011-2019 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 */
19package org.sleuthkit.autopsy.datamodel;
20
21import java.beans.PropertyChangeEvent;
22import java.beans.PropertyChangeListener;
23import java.util.ArrayList;
24import java.util.Arrays;
25import java.util.EnumSet;
26import java.util.List;
27import java.util.Observable;
28import java.util.Observer;
29import java.util.Set;
30import java.util.logging.Level;
31import org.openide.nodes.AbstractNode;
32import org.openide.nodes.ChildFactory;
33import org.openide.nodes.Children;
34import org.openide.nodes.Node;
35import org.openide.nodes.Sheet;
36import org.openide.util.NbBundle;
37import org.openide.util.lookup.Lookups;
38import org.sleuthkit.autopsy.casemodule.Case;
39import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
40import org.sleuthkit.autopsy.coreutils.Logger;
41import org.sleuthkit.autopsy.ingest.IngestManager;
42import static org.sleuthkit.autopsy.ingest.IngestManager.IngestModuleEvent.CONTENT_CHANGED;
43import org.sleuthkit.datamodel.AbstractFile;
44import org.sleuthkit.datamodel.Content;
45import org.sleuthkit.datamodel.ContentVisitor;
46import org.sleuthkit.datamodel.Directory;
47import org.sleuthkit.datamodel.File;
48import org.sleuthkit.datamodel.FsContent;
49import org.sleuthkit.datamodel.LayoutFile;
50import org.sleuthkit.datamodel.SleuthkitCase;
51import org.sleuthkit.datamodel.TskCoreException;
52import org.sleuthkit.datamodel.TskData;
53import org.sleuthkit.datamodel.VirtualDirectory;
54
58public class DeletedContent implements AutopsyVisitableItem {
59
60 private SleuthkitCase skCase;
61 private final long filteringDSObjId; // 0 if not filtering/grouping by data source
62
63 @NbBundle.Messages({"DeletedContent.fsDelFilter.text=File System",
64 "DeletedContent.allDelFilter.text=All"})
66
67 FS_DELETED_FILTER(0, "FS_DELETED_FILTER", //NON-NLS
68 Bundle.DeletedContent_fsDelFilter_text()),
69 ALL_DELETED_FILTER(1, "ALL_DELETED_FILTER", //NON-NLS
70 Bundle.DeletedContent_allDelFilter_text());
71
72 private int id;
73 private String name;
74 private String displayName;
75
76 private DeletedContentFilter(int id, String name, String displayName) {
77 this.id = id;
78 this.name = name;
79 this.displayName = displayName;
80
81 }
82
83 public String getName() {
84 return this.name;
85 }
86
87 public int getId() {
88 return this.id;
89 }
90
91 public String getDisplayName() {
92 return this.displayName;
93 }
94
95 @Override
96 public <T> T accept(AutopsyItemVisitor<T> visitor) {
97 return visitor.visit(this);
98 }
99 }
100
101 public DeletedContent(SleuthkitCase skCase) {
102 this(skCase, 0);
103 }
104
105 public DeletedContent(SleuthkitCase skCase, long dsObjId) {
106 this.skCase = skCase;
107 this.filteringDSObjId = dsObjId;
108 }
109
110 long filteringDataSourceObjId() {
111 return this.filteringDSObjId;
112 }
113
114 @Override
115 public <T> T accept(AutopsyItemVisitor<T> visitor) {
116 return visitor.visit(this);
117 }
118
119 public SleuthkitCase getSleuthkitCase() {
120 return this.skCase;
121 }
122
123 public static class DeletedContentsNode extends DisplayableItemNode {
124
125 @NbBundle.Messages("DeletedContent.deletedContentsNode.name=Deleted Files")
126 private static final String NAME = Bundle.DeletedContent_deletedContentsNode_name();
127
128 DeletedContentsNode(SleuthkitCase skCase, long datasourceObjId) {
129 super(Children.create(new DeletedContentsChildren(skCase, datasourceObjId), true), Lookups.singleton(NAME));
130 super.setName(NAME);
131 super.setDisplayName(NAME);
132 this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-icon-deleted.png"); //NON-NLS
133 }
134
135 @Override
136 public boolean isLeafTypeNode() {
137 return false;
138 }
139
140 @Override
141 public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
142 return visitor.visit(this);
143 }
144
145 @Override
146 @NbBundle.Messages({
147 "DeletedContent.createSheet.name.displayName=Name",
148 "DeletedContent.createSheet.name.desc=no description"})
149 protected Sheet createSheet() {
150 Sheet sheet = super.createSheet();
151 Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
152 if (sheetSet == null) {
153 sheetSet = Sheet.createPropertiesSet();
154 sheet.put(sheetSet);
155 }
156
157 sheetSet.put(new NodeProperty<>("Name", //NON-NLS
158 Bundle.DeletedContent_createSheet_name_displayName(),
159 Bundle.DeletedContent_createSheet_name_desc(),
160 NAME));
161 return sheet;
162 }
163
164 @Override
165 public String getItemType() {
166 return getClass().getName();
167 }
168 }
169
170 public static class DeletedContentsChildren extends ChildFactory<DeletedContent.DeletedContentFilter> {
171
172 private SleuthkitCase skCase;
173 private Observable notifier;
174 private final long datasourceObjId;
175 // true if we have already told user that not all files will be shown
176 private static volatile boolean maxFilesDialogShown = false;
177
178 public DeletedContentsChildren(SleuthkitCase skCase, long dsObjId) {
179 this.skCase = skCase;
180 this.datasourceObjId = dsObjId;
181 this.notifier = new DeletedContentsChildrenObservable();
182 }
183
188 private static final class DeletedContentsChildrenObservable extends Observable {
189
190 private static final Set<Case.Events> CASE_EVENTS_OF_INTEREST = EnumSet.of(
193 );
195 private static final Set<IngestManager.IngestModuleEvent> INGEST_MODULE_EVENTS_OF_INTEREST = EnumSet.of(CONTENT_CHANGED);
196
197 DeletedContentsChildrenObservable() {
201 }
202
209
210 private final PropertyChangeListener pcl = (PropertyChangeEvent evt) -> {
211 String eventType = evt.getPropertyName();
212 if (eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())) {
220 try {
222 // new file was added
223 // @@@ COULD CHECK If the new file is deleted before notifying...
224 update();
225 } catch (NoCurrentCaseException notUsed) {
229 }
230 } else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
231 || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())
232 || eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) {
239 try {
241 update();
242 } catch (NoCurrentCaseException notUsed) {
246 }
247 } else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
248 // case was closed. Remove listeners so that we don't get called with a stale case handle
249 if (evt.getNewValue() == null) {
251 }
252 maxFilesDialogShown = false;
253 }
254 };
255
256 private void update() {
257 setChanged();
258 notifyObservers();
259 }
260 }
261
262 @Override
263
264 protected boolean createKeys(List<DeletedContent.DeletedContentFilter> list) {
265 list.addAll(Arrays.asList(DeletedContent.DeletedContentFilter.values()));
266 return true;
267 }
268
269 @Override
270 protected Node createNodeForKey(DeletedContent.DeletedContentFilter key) {
272 }
273
274 public class DeletedContentNode extends DisplayableItemNode {
275
277 private final long datasourceObjId;
278
279 // Use version that has observer for updates
280 @Deprecated
281 DeletedContentNode(SleuthkitCase skCase, DeletedContent.DeletedContentFilter filter, long dsObjId) {
282 super(Children.create(new DeletedContentChildren(filter, skCase, null, dsObjId), true), Lookups.singleton(filter.getDisplayName()));
283 this.filter = filter;
284 this.datasourceObjId = dsObjId;
285 init();
286 }
287
288 DeletedContentNode(SleuthkitCase skCase, DeletedContent.DeletedContentFilter filter, Observable o, long dsObjId) {
289 super(Children.create(new DeletedContentChildren(filter, skCase, o, dsObjId), true), Lookups.singleton(filter.getDisplayName()));
290 this.filter = filter;
291 this.datasourceObjId = dsObjId;
292 init();
293 o.addObserver(new DeletedContentNodeObserver());
294 }
295
296 private void init() {
297 super.setName(filter.getName());
298
299 String tooltip = filter.getDisplayName();
300 this.setShortDescription(tooltip);
301 this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-icon-deleted.png"); //NON-NLS
303 }
304
305 // update the display name when new events are fired
306 private class DeletedContentNodeObserver implements Observer {
307
308 @Override
309 public void update(Observable o, Object arg) {
311 }
312 }
313
314 private void updateDisplayName() {
315 //get count of children without preloading all children nodes
316 final long count = DeletedContentChildren.calculateItems(skCase, filter, datasourceObjId);
317 //final long count = getChildren().getNodesCount(true);
318 super.setDisplayName(filter.getDisplayName() + " (" + count + ")");
319 }
320
321 @Override
322 public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
323 return visitor.visit(this);
324 }
325
326 @Override
327 @NbBundle.Messages({
328 "DeletedContent.createSheet.filterType.displayName=Type",
329 "DeletedContent.createSheet.filterType.desc=no description"})
330 protected Sheet createSheet() {
331 Sheet sheet = super.createSheet();
332 Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
333 if (sheetSet == null) {
334 sheetSet = Sheet.createPropertiesSet();
335 sheet.put(sheetSet);
336 }
337
338 sheetSet.put(new NodeProperty<>("Type", //NON_NLS
339 Bundle.DeletedContent_createSheet_filterType_displayName(),
340 Bundle.DeletedContent_createSheet_filterType_desc(),
341 filter.getDisplayName()));
342
343 return sheet;
344 }
345
346 @Override
347 public boolean isLeafTypeNode() {
348 return true;
349 }
350
351 @Override
352 public String getItemType() {
357 return DisplayableItemNode.FILE_PARENT_NODE_KEY;
358 }
359 }
360
361 static class DeletedContentChildren extends BaseChildFactory<AbstractFile> {
362
363 private final SleuthkitCase skCase;
365 private static final Logger logger = Logger.getLogger(DeletedContentChildren.class.getName());
366
367 private final Observable notifier;
368 private final long datasourceObjId;
369
370 DeletedContentChildren(DeletedContent.DeletedContentFilter filter, SleuthkitCase skCase, Observable o, long datasourceObjId) {
371 super(filter.getName(), new ViewsKnownAndSlackFilter<>());
372 this.skCase = skCase;
373 this.filter = filter;
374 this.notifier = o;
375 this.datasourceObjId = datasourceObjId;
376 }
377
378 private final Observer observer = new DeletedContentChildrenObserver();
379
380 @Override
381 protected List<AbstractFile> makeKeys() {
382 return runFsQuery();
383 }
384
385 // Cause refresh of children if there are changes
386 private class DeletedContentChildrenObserver implements Observer {
387
388 @Override
389 public void update(Observable o, Object arg) {
390 refresh(true);
391 }
392 }
393
394 @Override
395 protected void onAdd() {
396 if (notifier != null) {
397 notifier.addObserver(observer);
398 }
399 }
400
401 @Override
402 protected void onRemove() {
403 if (notifier != null) {
404 notifier.deleteObserver(observer);
405 }
406 }
407
408 static private String makeQuery(DeletedContent.DeletedContentFilter filter, long filteringDSObjId) {
409 String query = "";
410 switch (filter) {
411 case FS_DELETED_FILTER:
412 query = "dir_flags = " + TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC.getValue() //NON-NLS
413 + " AND meta_flags != " + TskData.TSK_FS_META_FLAG_ENUM.ORPHAN.getValue() //NON-NLS
414 + " AND type = " + TskData.TSK_DB_FILES_TYPE_ENUM.FS.getFileType(); //NON-NLS
415
416 break;
417 case ALL_DELETED_FILTER:
418 query = " ( "
419 + "( "
420 + "(dir_flags = " + TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC.getValue() //NON-NLS
421 + " OR " //NON-NLS
422 + "meta_flags = " + TskData.TSK_FS_META_FLAG_ENUM.ORPHAN.getValue() //NON-NLS
423 + ")"
424 + " AND type = " + TskData.TSK_DB_FILES_TYPE_ENUM.FS.getFileType() //NON-NLS
425 + " )"
426 + " OR type = " + TskData.TSK_DB_FILES_TYPE_ENUM.CARVED.getFileType() //NON-NLS
427 + " OR (dir_flags = " + TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC.getValue()
428 + " AND type = " + TskData.TSK_DB_FILES_TYPE_ENUM.LAYOUT_FILE.getFileType() + " )"
429 + " )";
430 //+ " AND type != " + TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS.getFileType()
431 //+ " AND type != " + TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS.getFileType()
432 //+ " AND type != " + TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS.getFileType()
433 //+ " AND type != " + TskData.TSK_DB_FILES_TYPE_ENUM.DERIVED.getFileType()
434 //+ " AND type != " + TskData.TSK_DB_FILES_TYPE_ENUM.LOCAL.getFileType()
435 //+ " AND type != " + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType();
436 break;
437
438 default:
439 logger.log(Level.SEVERE, "Unsupported filter type to get deleted content: {0}", filter); //NON-NLS
440
441 }
442
443 if (filteringDSObjId > 0) {
444 query += " AND data_source_obj_id = " + filteringDSObjId;
445 }
446 return query;
447 }
448
449 private List<AbstractFile> runFsQuery() {
450 List<AbstractFile> ret = new ArrayList<>();
451
452 String query = makeQuery(filter, datasourceObjId);
453 try {
454 ret = skCase.findAllFilesWhere(query);
455 } catch (TskCoreException e) {
456 logger.log(Level.SEVERE, "Error getting files for the deleted content view using: " + query, e); //NON-NLS
457 }
458
459 return ret;
460
461 }
462
471 static long calculateItems(SleuthkitCase sleuthkitCase, DeletedContent.DeletedContentFilter filter, long datasourceObjId) {
472 try {
473 return sleuthkitCase.countFilesWhere(makeQuery(filter, datasourceObjId));
474 } catch (TskCoreException ex) {
475 logger.log(Level.SEVERE, "Error getting deleted files search view count", ex); //NON-NLS
476 return 0;
477 }
478 }
479
480 @Override
481 protected Node createNodeForKey(AbstractFile key) {
482 return key.accept(new ContentVisitor.Default<AbstractNode>() {
483 public FileNode visit(AbstractFile f) {
484 return new FileNode(f, false);
485 }
486
487 public FileNode visit(FsContent f) {
488 return new FileNode(f, false);
489 }
490
491 @Override
492 public FileNode visit(LayoutFile f) {
493 return new FileNode(f, false);
494 }
495
496 @Override
497 public FileNode visit(File f) {
498 return new FileNode(f, false);
499 }
500
501 @Override
502 public FileNode visit(Directory f) {
503 return new FileNode(f, false);
504 }
505
506 @Override
507 public FileNode visit(VirtualDirectory f) {
508 return new FileNode(f, false);
509 }
510
511 @Override
512 protected AbstractNode defaultVisit(Content di) {
513 throw new UnsupportedOperationException("Not supported for this type of Displayable Item: " + di.toString());
514 }
515 });
516 }
517 }
518 }
519}
static void removeEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
Definition Case.java:757
static void addEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
Definition Case.java:712
synchronized static Logger getLogger(String name)
Definition Logger.java:124
boolean createKeys(List< DeletedContent.DeletedContentFilter > list)
DeletedContent(SleuthkitCase skCase, long dsObjId)
static synchronized IngestManager getInstance()
void removeIngestModuleEventListener(final PropertyChangeListener listener)
void removeIngestJobEventListener(final PropertyChangeListener listener)
void addIngestModuleEventListener(final PropertyChangeListener listener)
void addIngestJobEventListener(final PropertyChangeListener listener)
public< T > T accept(AutopsyItemVisitor< T > visitor)

Copyright © 2012-2024 Sleuth Kit Labs. Generated on:
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.