Autopsy  4.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
DataResultFilterNode.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2011-2017 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  */
19 package org.sleuthkit.autopsy.directorytree;
20 
21 import java.awt.event.ActionEvent;
22 import java.beans.PropertyVetoException;
23 import java.util.ArrayList;
24 import java.util.List;
25 import java.util.logging.Level;
26 import java.util.prefs.PreferenceChangeEvent;
27 import java.util.prefs.PreferenceChangeListener;
28 import javax.swing.AbstractAction;
29 import javax.swing.Action;
30 import org.openide.explorer.ExplorerManager;
31 import org.openide.nodes.AbstractNode;
32 import org.openide.nodes.FilterNode;
33 import org.openide.nodes.Node;
34 import org.openide.nodes.Sheet;
35 import org.openide.util.NbBundle;
67 
72 public class DataResultFilterNode extends FilterNode {
73 
78 
79  static {
80  UserPreferences.addChangeListener(new PreferenceChangeListener() {
81  @Override
82  public void preferenceChange(PreferenceChangeEvent evt) {
83  switch (evt.getKey()) {
85  filterKnownFromDataSources = UserPreferences.hideKnownFilesInDataSourcesTree();
86  break;
88  filterKnownFromViews = UserPreferences.hideKnownFilesInViewsTree();
89  break;
91  filterSlackFromDataSources = UserPreferences.hideSlackFilesInDataSourcesTree();
92  break;
94  filterSlackFromViews = UserPreferences.hideSlackFilesInViewsTree();
95  break;
96  }
97  }
98  });
99  }
100 
103 
104  private final ExplorerManager sourceEm;
105 
111  public DataResultFilterNode(Node node, ExplorerManager em) {
112  super(node, new DataResultFilterChildren(node, em));
113  this.sourceEm = em;
114 
115  }
116 
122  private DataResultFilterNode(Node node, ExplorerManager em, boolean filterKnown, boolean filterSlack) {
123  super(node, new DataResultFilterChildren(node, em, filterKnown, filterSlack));
124  this.sourceEm = em;
125  }
126 
135  @Override
136  public Action[] getActions(boolean popup) {
137 
138  List<Action> actions = new ArrayList<>();
139 
140  final DisplayableItemNode originalNode = (DisplayableItemNode) this.getOriginal();
141  List<Action> accept = originalNode.accept(getActionsDIV);
142  if (accept != null) {
143  actions.addAll(accept);
144  }
145 
146  //actions.add(new IndexContentFilesAction(nodeContent, "Index"));
147  return actions.toArray(new Action[actions.size()]);
148  }
149 
156  @Override
157  public Action getPreferredAction() {
158  final Node original = this.getOriginal();
159  // Once had a org.openide.nodes.ChildFactory$WaitFilterNode passed in
160  if ((original instanceof DisplayableItemNode) == false) {
161  return null;
162  }
163 
164  final DisplayableItemNode originalNode = (DisplayableItemNode) this.getOriginal();
165  return originalNode.accept(getPreferredActionsDIV);
166  }
167 
168  @Override
169  public Node.PropertySet[] getPropertySets() {
170  Node.PropertySet[] propertySets = super.getPropertySets();
171 
172  for (int i = 0; i < propertySets.length; i++) {
173  Node.PropertySet ps = propertySets[i];
174 
175  if (ps.getName().equals(Sheet.PROPERTIES)) {
176  Sheet.Set newPs = new Sheet.Set();
177  newPs.setName(ps.getName());
178  newPs.setDisplayName(ps.getDisplayName());
179  newPs.setShortDescription(ps.getShortDescription());
180 
181  newPs.put(ps.getProperties());
182  if (newPs.remove(AbstractFsContentNode.HIDE_PARENT) != null) {
183  newPs.remove(AbstractFilePropertyType.LOCATION.toString());
184  }
185  propertySets[i] = newPs;
186  }
187  }
188 
189  return propertySets;
190  }
191 
197  private static class DataResultFilterChildren extends FilterNode.Children {
198 
199  private final ExplorerManager sourceEm;
200 
201  private boolean filterKnown;
202  private boolean filterSlack;
203 
207  private DataResultFilterChildren(Node arg, ExplorerManager sourceEm) {
208  super(arg);
209  switch (SelectionContext.getSelectionContext(arg)) {
210  case DATA_SOURCES:
211  filterSlack = filterSlackFromDataSources;
212  filterKnown = filterKnownFromDataSources;
213  break;
214  case VIEWS:
215  filterSlack = filterSlackFromViews;
216  filterKnown = filterKnownFromViews;
217  break;
218  default:
219  filterSlack = false;
220  filterKnown = false;
221  break;
222  }
223  this.sourceEm = sourceEm;
224  }
225 
226  private DataResultFilterChildren(Node arg, ExplorerManager sourceEm, boolean filterKnown, boolean filterSlack) {
227  super(arg);
228  this.filterKnown = filterKnown;
229  this.filterSlack = filterSlack;
230  this.sourceEm = sourceEm;
231  }
232 
233  @Override
234  protected Node[] createNodes(Node key) {
235  AbstractFile file = key.getLookup().lookup(AbstractFile.class);
236  if (file != null) {
237  if (filterKnown && (file.getKnown() == TskData.FileKnown.KNOWN)) {
238  // Filter out child nodes that represent known files
239  return new Node[]{};
240  }
241  if (filterSlack && file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.SLACK)) {
242  // Filter out child nodes that represent slack files
243  return new Node[]{};
244  }
245  }
246  return new Node[]{new DataResultFilterNode(key, sourceEm, filterKnown, filterSlack)};
247  }
248  }
249 
254  private static class GetPopupActionsDisplayableItemNodeVisitor extends DisplayableItemNodeVisitor.Default<List<Action>> {
255 
256  @Override
257  public List<Action> visit(BlackboardArtifactNode ban) {
258  //set up actions for artifact node based on its Content object
259  //TODO all actions need to be consolidated in single place!
260  //they should be set in individual Node subclass and using a utility to get Actions per Content sub-type
261  // TODO UPDATE: There is now a DataModelActionsFactory utility;
262 
263  List<Action> actions = new ArrayList<>();
264 
265  //merge predefined specific node actions if bban subclasses have their own
266  for (Action a : ban.getActions(true)) {
267  actions.add(a);
268  }
269  BlackboardArtifact ba = ban.getLookup().lookup(BlackboardArtifact.class);
270  final int artifactTypeID = ba.getArtifactTypeID();
271 
272  if (artifactTypeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID()
273  || artifactTypeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) {
274  actions.add(new ViewContextAction(
275  NbBundle.getMessage(this.getClass(), "DataResultFilterNode.action.viewFileInDir.text"), ban));
276  } else {
277  // if the artifact links to another file, add an action to go to
278  // that file
279  Content c = findLinked(ban);
280  if (c != null) {
281  actions.add(new ViewContextAction(
282  NbBundle.getMessage(this.getClass(), "DataResultFilterNode.action.viewFileInDir.text"), c));
283  }
284  // action to go to the source file of the artifact
285  actions.add(new ViewContextAction(
286  NbBundle.getMessage(this.getClass(), "DataResultFilterNode.action.viewSrcFileInDir.text"), ban));
287  }
288  Content c = ban.getLookup().lookup(File.class);
289  Node n = null;
290  boolean md5Action = false;
291  if (c != null) {
292  n = new FileNode((AbstractFile) c);
293  md5Action = true;
294  } else if ((c = ban.getLookup().lookup(Directory.class)) != null) {
295  n = new DirectoryNode((Directory) c);
296  } else if ((c = ban.getLookup().lookup(VirtualDirectory.class)) != null) {
298  } else if ((c = ban.getLookup().lookup(LayoutFile.class)) != null) {
299  n = new LayoutFileNode((LayoutFile) c);
300  } else if ((c = ban.getLookup().lookup(LocalFile.class)) != null
301  || (c = ban.getLookup().lookup(DerivedFile.class)) != null) {
302  n = new LocalFileNode((AbstractFile) c);
303  } else if ((c = ban.getLookup().lookup(SlackFile.class)) != null) {
304  n = new SlackFileNode((SlackFile) c);
305  }
306  if (n != null) {
307  actions.add(null); // creates a menu separator
308  actions.add(new NewWindowViewAction(
309  NbBundle.getMessage(this.getClass(), "DataResultFilterNode.action.viewInNewWin.text"), n));
310  actions.add(new ExternalViewerAction(
311  NbBundle.getMessage(this.getClass(), "DataResultFilterNode.action.openInExtViewer.text"), n));
312  actions.add(null); // creates a menu separator
313  actions.add(ExtractAction.getInstance());
314  if (md5Action) {
315  actions.add(new HashSearchAction(
316  NbBundle.getMessage(this.getClass(), "DataResultFilterNode.action.searchFilesSameMd5.text"), n));
317  }
318  actions.add(null); // creates a menu separator
319  actions.add(AddContentTagAction.getInstance());
321  actions.addAll(ContextMenuExtensionPoint.getActions());
322  } else {
323  // There's no specific file associated with the artifact, but
324  // we can still tag the artifact itself
325  actions.add(null);
327  }
328  return actions;
329  }
330 
331  @Override
332  public List<Action> visit(Reports.ReportsListNode ditem) {
333  // The base class Action is "Collapse All", inappropriate.
334  return null;
335  }
336 
337  @Override
338  public List<Action> visit(FileTypesNode fileTypes) {
339  return defaultVisit(fileTypes);
340  }
341 
342 
343  @Override
344  protected List<Action> defaultVisit(DisplayableItemNode ditem) {
345  //preserve the default node's actions
346  List<Action> actions = new ArrayList<>();
347 
348  for (Action action : ditem.getActions(true)) {
349  actions.add(action);
350  }
351 
352  return actions;
353  }
354 
356  BlackboardArtifact art = ba.getLookup().lookup(BlackboardArtifact.class);
357  Content c = null;
358  try {
359  for (BlackboardAttribute attr : art.getAttributes()) {
360  if (attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID()) {
361  switch (attr.getAttributeType().getValueType()) {
362  case INTEGER:
363  int i = attr.getValueInt();
364  if (i != -1) {
365  c = art.getSleuthkitCase().getContentById(i);
366  }
367  break;
368  case LONG:
369  long l = attr.getValueLong();
370  if (l != -1) {
371  c = art.getSleuthkitCase().getContentById(l);
372  }
373  break;
374  }
375  }
376  }
377  } catch (TskException ex) {
378  Logger.getLogger(this.getClass().getName()).log(Level.WARNING, "Error getting linked file", ex); //NON-NLS
379  }
380  return c;
381  }
382 
383  }
384 
385  /*
386  * Action for double-click / preferred action on nodes.
387  */
388  private class GetPreferredActionsDisplayableItemNodeVisitor extends DisplayableItemNodeVisitor.Default<AbstractAction> {
389 
390  @Override
391  public AbstractAction visit(BlackboardArtifactNode ban) {
392  return new ViewContextAction(
393  NbBundle.getMessage(this.getClass(), "DataResultFilterNode.action.viewInDir.text"), ban);
394  }
395 
396  @Override
397  public AbstractAction visit(DirectoryNode dn) {
398  if (dn.getDisplayName().equals(DirectoryNode.DOTDOTDIR)) {
399  return openParent(dn);
400  } else if (dn.getDisplayName().equals(DirectoryNode.DOTDIR) == false) {
401  return openChild(dn);
402  } else {
403  return null;
404  }
405  }
406 
407  @Override
408  public AbstractAction visit(FileNode fn) {
409  if (fn.hasContentChildren()) {
410  return openChild(fn);
411  } else {
412  return null;
413  }
414  }
415 
416  @Override
417  public AbstractAction visit(LocalFileNode dfn) {
418  if (dfn.hasContentChildren()) {
419  return openChild(dfn);
420  } else {
421  return null;
422  }
423  }
424 
425  @Override
426  public AbstractAction visit(Reports.ReportNode reportNode) {
427  return reportNode.getPreferredAction();
428  }
429 
430  @Override
431  protected AbstractAction defaultVisit(DisplayableItemNode c) {
432  return openChild(c);
433  }
434 
435  @Override
436  public AbstractAction visit(FileTypesNode fileTypes) {
437  return openChild(fileTypes);
438  }
439 
440 
441 
450  private AbstractAction openChild(final AbstractNode dataModelNode) {
451  // get the current selection from the directory tree explorer manager,
452  // which is a DirectoryTreeFilterNode. One of that node's children
453  // is a DirectoryTreeFilterNode that wraps the dataModelNode. We need
454  // to set that wrapped node as the selection and root context of the
455  // directory tree explorer manager (sourceEm)
456  final Node currentSelectionInDirectoryTree = sourceEm.getSelectedNodes()[0];
457 
458  return new AbstractAction() {
459  @Override
460  public void actionPerformed(ActionEvent e) {
461  if (currentSelectionInDirectoryTree != null) {
462  // Find the filter version of the passed in dataModelNode.
463  final org.openide.nodes.Children children = currentSelectionInDirectoryTree.getChildren();
464  // This call could break if the DirectoryTree is re-implemented with lazy ChildFactory objects.
465  Node newSelection = children.findChild(dataModelNode.getName());
466 
467  /*
468  * We got null here when we were viewing a ZIP file in
469  * the Views -> Archives area and double clicking on it
470  * got to this code. It tried to find the child in the
471  * tree and didn't find it. An exception was then thrown
472  * from setting the selected node to be null.
473  */
474  if (newSelection != null) {
475  try {
476  sourceEm.setExploredContextAndSelection(newSelection, new Node[]{newSelection});
477  } catch (PropertyVetoException ex) {
478  Logger logger = Logger.getLogger(DataResultFilterNode.class.getName());
479  logger.log(Level.WARNING, "Error: can't open the selected directory.", ex); //NON-NLS
480  }
481  }
482  }
483  }
484  };
485  }
486 
495  private AbstractAction openParent(AbstractNode node) {
496  // @@@ Why do we ignore node?
497  Node[] selectedFilterNodes = sourceEm.getSelectedNodes();
498  Node selectedFilterNode = selectedFilterNodes[0];
499  final Node parentNode = selectedFilterNode.getParentNode();
500 
501  return new AbstractAction() {
502  @Override
503  public void actionPerformed(ActionEvent e) {
504  try {
505  sourceEm.setSelectedNodes(new Node[]{parentNode});
506  } catch (PropertyVetoException ex) {
507  Logger logger = Logger.getLogger(DataResultFilterNode.class.getName());
508  logger.log(Level.WARNING, "Error: can't open the parent directory.", ex); //NON-NLS
509  }
510  }
511  };
512  }
513  }
514 }
static final DisplayableItemNodeVisitor< List< Action > > getActionsDIV
static synchronized AddBlackboardArtifactTagAction getInstance()
TskData.TSK_DB_FILES_TYPE_ENUM getType()
DataResultFilterChildren(Node arg, ExplorerManager sourceEm, boolean filterKnown, boolean filterSlack)
abstract< T > T accept(DisplayableItemNodeVisitor< T > v)
static synchronized ExtractAction getInstance()
final DisplayableItemNodeVisitor< AbstractAction > getPreferredActionsDIV
List< BlackboardAttribute > getAttributes()
synchronized static Logger getLogger(String name)
Definition: Logger.java:161
static void addChangeListener(PreferenceChangeListener listener)
static synchronized AddContentTagAction getInstance()
DataResultFilterNode(Node node, ExplorerManager em, boolean filterKnown, boolean filterSlack)

Copyright © 2012-2016 Basis Technology. Generated on: Mon Apr 24 2017
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.