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-2016 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 javax.swing.AbstractAction;
27 import javax.swing.Action;
28 import org.openide.explorer.ExplorerManager;
29 import org.openide.nodes.AbstractNode;
30 import org.openide.nodes.FilterNode;
31 import org.openide.nodes.Node;
32 import org.openide.nodes.Sheet;
33 import org.openide.util.NbBundle;
51 import org.sleuthkit.datamodel.AbstractFile;
52 import org.sleuthkit.datamodel.BlackboardArtifact;
53 import org.sleuthkit.datamodel.BlackboardAttribute;
54 import org.sleuthkit.datamodel.Content;
55 import org.sleuthkit.datamodel.DerivedFile;
56 import org.sleuthkit.datamodel.Directory;
57 import org.sleuthkit.datamodel.File;
58 import org.sleuthkit.datamodel.LayoutFile;
59 import org.sleuthkit.datamodel.LocalFile;
60 import org.sleuthkit.datamodel.SlackFile;
61 import org.sleuthkit.datamodel.TskException;
62 import org.sleuthkit.datamodel.VirtualDirectory;
63 
68 public class DataResultFilterNode extends FilterNode {
69 
70  private ExplorerManager sourceEm;
71 
73 
75 
81  public DataResultFilterNode(Node node, ExplorerManager em) {
82  super(node, new DataResultFilterChildren(node, em));
83  this.sourceEm = em;
84  getActionsDIV = new GetPopupActionsDisplayableItemNodeVisitor();
85  getPreferredActionsDIV = new GetPreferredActionsDisplayableItemNodeVisitor();
86  }
87 
96  @Override
97  public Action[] getActions(boolean popup) {
98 
99  List<Action> actions = new ArrayList<>();
100 
101  final DisplayableItemNode originalNode = (DisplayableItemNode) this.getOriginal();
102  List<Action> accept = originalNode.accept(getActionsDIV);
103  if (accept != null) {
104  actions.addAll(accept);
105  }
106 
107  //actions.add(new IndexContentFilesAction(nodeContent, "Index"));
108  return actions.toArray(new Action[actions.size()]);
109  }
110 
117  @Override
118  public Action getPreferredAction() {
119  final Node original = this.getOriginal();
120  // Once had a org.openide.nodes.ChildFactory$WaitFilterNode passed in
121  if ((original instanceof DisplayableItemNode) == false) {
122  return null;
123  }
124 
125  final DisplayableItemNode originalNode = (DisplayableItemNode) this.getOriginal();
126  return originalNode.accept(getPreferredActionsDIV);
127  }
128 
129  @Override
130  public Node.PropertySet[] getPropertySets() {
131  Node.PropertySet[] propertySets = super.getPropertySets();
132 
133  for (int i = 0; i < propertySets.length; i++) {
134  Node.PropertySet ps = propertySets[i];
135 
136  if (ps.getName().equals(Sheet.PROPERTIES)) {
137  Sheet.Set newPs = new Sheet.Set();
138  newPs.setName(ps.getName());
139  newPs.setDisplayName(ps.getDisplayName());
140  newPs.setShortDescription(ps.getShortDescription());
141 
142  newPs.put(ps.getProperties());
143  if (newPs.remove(AbstractFsContentNode.HIDE_PARENT) != null) {
144  newPs.remove(AbstractFilePropertyType.LOCATION.toString());
145  }
146  propertySets[i] = newPs;
147  }
148  }
149 
150  return propertySets;
151  }
152 
157  private static class GetPopupActionsDisplayableItemNodeVisitor extends DisplayableItemNodeVisitor.Default<List<Action>> {
158 
159  @Override
160  public List<Action> visit(BlackboardArtifactNode ban) {
161  //set up actions for artifact node based on its Content object
162  //TODO all actions need to be consolidated in single place!
163  //they should be set in individual Node subclass and using a utility to get Actions per Content sub-type
164  // TODO UPDATE: There is now a DataModelActionsFactory utility;
165 
166  List<Action> actions = new ArrayList<>();
167 
168  //merge predefined specific node actions if bban subclasses have their own
169  for (Action a : ban.getActions(true)) {
170  actions.add(a);
171  }
172  BlackboardArtifact ba = ban.getLookup().lookup(BlackboardArtifact.class);
173  final int artifactTypeID = ba.getArtifactTypeID();
174 
175  if (artifactTypeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID()
176  || artifactTypeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) {
177  actions.add(new ViewContextAction(
178  NbBundle.getMessage(this.getClass(), "DataResultFilterNode.action.viewFileInDir.text"), ban));
179  } else {
180  // if the artifact links to another file, add an action to go to
181  // that file
182  Content c = findLinked(ban);
183  if (c != null) {
184  actions.add(new ViewContextAction(
185  NbBundle.getMessage(this.getClass(), "DataResultFilterNode.action.viewFileInDir.text"), c));
186  }
187  // action to go to the source file of the artifact
188  actions.add(new ViewContextAction(
189  NbBundle.getMessage(this.getClass(), "DataResultFilterNode.action.viewSrcFileInDir.text"), ban));
190  }
191  Content c = ban.getLookup().lookup(File.class);
192  Node n = null;
193  boolean md5Action = false;
194  if (c != null) {
195  n = new FileNode((AbstractFile) c);
196  md5Action = true;
197  } else if ((c = ban.getLookup().lookup(Directory.class)) != null) {
198  n = new DirectoryNode((Directory) c);
199  } else if ((c = ban.getLookup().lookup(VirtualDirectory.class)) != null) {
200  n = new VirtualDirectoryNode((VirtualDirectory) c);
201  } else if ((c = ban.getLookup().lookup(LayoutFile.class)) != null) {
202  n = new LayoutFileNode((LayoutFile) c);
203  } else if ((c = ban.getLookup().lookup(LocalFile.class)) != null
204  || (c = ban.getLookup().lookup(DerivedFile.class)) != null) {
205  n = new LocalFileNode((AbstractFile) c);
206  } else if ((c = ban.getLookup().lookup(SlackFile.class)) != null) {
207  n = new SlackFileNode((SlackFile) c);
208  }
209  if (n != null) {
210  actions.add(null); // creates a menu separator
211  actions.add(new NewWindowViewAction(
212  NbBundle.getMessage(this.getClass(), "DataResultFilterNode.action.viewInNewWin.text"), n));
213  actions.add(new ExternalViewerAction(
214  NbBundle.getMessage(this.getClass(), "DataResultFilterNode.action.openInExtViewer.text"), n));
215  actions.add(null); // creates a menu separator
216  actions.add(ExtractAction.getInstance());
217  if (md5Action) {
218  actions.add(new HashSearchAction(
219  NbBundle.getMessage(this.getClass(), "DataResultFilterNode.action.searchFilesSameMd5.text"), n));
220  }
221  actions.add(null); // creates a menu separator
222  actions.add(AddContentTagAction.getInstance());
224  actions.addAll(ContextMenuExtensionPoint.getActions());
225  } else {
226  // There's no specific file associated with the artifact, but
227  // we can still tag the artifact itself
228  actions.add(null);
230  }
231  return actions;
232  }
233 
234  @Override
235  public List<Action> visit(Reports.ReportsListNode ditem) {
236  // The base class Action is "Collapse All", inappropriate.
237  return null;
238  }
239 
240  @Override
241  public List<Action> visit(FileTypesNode fileTypes) {
242  return defaultVisit(fileTypes);
243  }
244 
245 
246  @Override
247  protected List<Action> defaultVisit(DisplayableItemNode ditem) {
248  //preserve the default node's actions
249  List<Action> actions = new ArrayList<>();
250 
251  for (Action action : ditem.getActions(true)) {
252  actions.add(action);
253  }
254 
255  return actions;
256  }
257 
258  private Content findLinked(BlackboardArtifactNode ba) {
259  BlackboardArtifact art = ba.getLookup().lookup(BlackboardArtifact.class);
260  Content c = null;
261  try {
262  for (BlackboardAttribute attr : art.getAttributes()) {
263  if (attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID()) {
264  switch (attr.getAttributeType().getValueType()) {
265  case INTEGER:
266  int i = attr.getValueInt();
267  if (i != -1) {
268  c = art.getSleuthkitCase().getContentById(i);
269  }
270  break;
271  case LONG:
272  long l = attr.getValueLong();
273  if (l != -1) {
274  c = art.getSleuthkitCase().getContentById(l);
275  }
276  break;
277  }
278  }
279  }
280  } catch (TskException ex) {
281  Logger.getLogger(this.getClass().getName()).log(Level.WARNING, "Error getting linked file", ex); //NON-NLS
282  }
283  return c;
284  }
285 
286  }
287 
288  /*
289  * Action for double-click / preferred action on nodes.
290  */
291  private class GetPreferredActionsDisplayableItemNodeVisitor extends DisplayableItemNodeVisitor.Default<AbstractAction> {
292 
293  @Override
294  public AbstractAction visit(BlackboardArtifactNode ban) {
295  return new ViewContextAction(
296  NbBundle.getMessage(this.getClass(), "DataResultFilterNode.action.viewInDir.text"), ban);
297  }
298 
299  @Override
300  public AbstractAction visit(DirectoryNode dn) {
301  if (dn.getDisplayName().equals(DirectoryNode.DOTDOTDIR)) {
302  return openParent(dn);
303  } else if (dn.getDisplayName().equals(DirectoryNode.DOTDIR) == false) {
304  return openChild(dn);
305  } else {
306  return null;
307  }
308  }
309 
310  @Override
311  public AbstractAction visit(FileNode fn) {
312  if (fn.hasContentChildren()) {
313  return openChild(fn);
314  } else {
315  return null;
316  }
317  }
318 
319  @Override
320  public AbstractAction visit(LocalFileNode dfn) {
321  if (dfn.hasContentChildren()) {
322  return openChild(dfn);
323  } else {
324  return null;
325  }
326  }
327 
328  @Override
329  public AbstractAction visit(Reports.ReportNode reportNode) {
330  return reportNode.getPreferredAction();
331  }
332 
333  @Override
334  protected AbstractAction defaultVisit(DisplayableItemNode c) {
335  return openChild(c);
336  }
337 
338  @Override
339  public AbstractAction visit(FileTypesNode fileTypes) {
340  return openChild(fileTypes);
341  }
342 
343 
344 
353  private AbstractAction openChild(final AbstractNode dataModelNode) {
354  // get the current selection from the directory tree explorer manager,
355  // which is a DirectoryTreeFilterNode. One of that node's children
356  // is a DirectoryTreeFilterNode that wraps the dataModelNode. We need
357  // to set that wrapped node as the selection and root context of the
358  // directory tree explorer manager (sourceEm)
359  final Node currentSelectionInDirectoryTree = sourceEm.getSelectedNodes()[0];
360 
361  return new AbstractAction() {
362  @Override
363  public void actionPerformed(ActionEvent e) {
364  if (currentSelectionInDirectoryTree != null) {
365  // Find the filter version of the passed in dataModelNode.
366  final org.openide.nodes.Children children = currentSelectionInDirectoryTree.getChildren();
367  // This call could break if the DirectoryTree is re-implemented with lazy ChildFactory objects.
368  Node newSelection = children.findChild(dataModelNode.getName());
369 
370  /*
371  * We got null here when we were viewing a ZIP file in
372  * the Views -> Archives area and double clicking on it
373  * got to this code. It tried to find the child in the
374  * tree and didn't find it. An exception was then thrown
375  * from setting the selected node to be null.
376  */
377  if (newSelection != null) {
378  try {
379  sourceEm.setExploredContextAndSelection(newSelection, new Node[]{newSelection});
380  } catch (PropertyVetoException ex) {
381  Logger logger = Logger.getLogger(DataResultFilterNode.class.getName());
382  logger.log(Level.WARNING, "Error: can't open the selected directory.", ex); //NON-NLS
383  }
384  }
385  }
386  }
387  };
388  }
389 
398  private AbstractAction openParent(AbstractNode node) {
399  // @@@ Why do we ignore node?
400  Node[] selectedFilterNodes = sourceEm.getSelectedNodes();
401  Node selectedFilterNode = selectedFilterNodes[0];
402  final Node parentNode = selectedFilterNode.getParentNode();
403 
404  return new AbstractAction() {
405  @Override
406  public void actionPerformed(ActionEvent e) {
407  try {
408  sourceEm.setSelectedNodes(new Node[]{parentNode});
409  } catch (PropertyVetoException ex) {
410  Logger logger = Logger.getLogger(DataResultFilterNode.class.getName());
411  logger.log(Level.WARNING, "Error: can't open the parent directory.", ex); //NON-NLS
412  }
413  }
414  };
415  }
416  }
417 }
final DisplayableItemNodeVisitor< List< Action > > getActionsDIV
static synchronized AddBlackboardArtifactTagAction getInstance()
abstract< T > T accept(DisplayableItemNodeVisitor< T > v)
static synchronized ExtractAction getInstance()
final DisplayableItemNodeVisitor< AbstractAction > getPreferredActionsDIV
synchronized static Logger getLogger(String name)
Definition: Logger.java:161
static synchronized AddContentTagAction getInstance()

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