19 package org.sleuthkit.autopsy.directorytree;
21 import java.awt.Cursor;
22 import java.awt.EventQueue;
23 import java.beans.PropertyChangeEvent;
24 import java.beans.PropertyChangeListener;
25 import java.beans.PropertyVetoException;
26 import java.io.IOException;
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.Collections;
30 import java.util.EnumSet;
31 import java.util.HashSet;
32 import java.util.LinkedList;
33 import java.util.List;
35 import java.util.Objects;
36 import java.util.Optional;
38 import java.util.concurrent.ExecutionException;
39 import java.util.logging.Level;
40 import java.util.prefs.PreferenceChangeEvent;
41 import java.util.prefs.PreferenceChangeListener;
42 import java.util.stream.Collectors;
43 import java.util.stream.Stream;
44 import javax.swing.Action;
45 import javax.swing.SwingUtilities;
46 import javax.swing.SwingWorker;
47 import javax.swing.event.PopupMenuEvent;
48 import javax.swing.event.PopupMenuListener;
49 import javax.swing.tree.TreeSelectionModel;
50 import org.apache.commons.lang3.StringUtils;
51 import org.openide.explorer.ExplorerManager;
52 import org.openide.explorer.ExplorerUtils;
53 import org.openide.explorer.view.BeanTreeView;
54 import org.openide.nodes.AbstractNode;
55 import org.openide.nodes.Children;
56 import org.openide.nodes.Node;
57 import org.openide.nodes.NodeNotFoundException;
58 import org.openide.nodes.NodeOp;
59 import org.openide.util.NbBundle;
60 import org.openide.util.NbBundle.Messages;
61 import org.openide.windows.TopComponent;
62 import org.openide.windows.WindowManager;
95 import org.
sleuthkit.datamodel.BlackboardArtifact.Category;
109 "DirectoryTreeTopComponent.resultsView.title=Listing"
111 @SuppressWarnings(
"PMD.SingularField")
114 private final transient ExplorerManager em =
new ExplorerManager();
120 private static final String PREFERRED_ID =
"DirectoryTreeTopComponent";
126 private static final long DEFAULT_DATASOURCE_GROUPING_THRESHOLD = 5;
127 private static final String GROUPING_THRESHOLD_NAME =
"GroupDataSourceThreshold";
128 private static final String SETTINGS_FILE =
"CasePreferences.properties";
132 .collect(Collectors.toSet());
141 getTree().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
144 putClientProperty(TopComponent.PROP_CLOSING_DISABLED, Boolean.TRUE);
148 subscribeToChangeEvents();
149 associateLookup(ExplorerUtils.createLookup(em, getActionMap()));
152 this.backList =
new LinkedList<>();
153 this.forwardList =
new LinkedList<>();
154 backButton.setEnabled(
false);
155 forwardButton.setEnabled(
false);
157 viewPreferencesPopupMenu.add(viewPreferencesPanel);
158 viewPreferencesPopupMenu.setSize(viewPreferencesPanel.getPreferredSize().width + 6, viewPreferencesPanel.getPreferredSize().height + 6);
159 viewPreferencesPopupMenu.addPopupMenuListener(
new PopupMenuListener() {
161 public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
162 openViewPreferencesButton.setSelected(
true);
166 public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
167 openViewPreferencesButton.setSelected(
false);
171 public void popupMenuCanceled(PopupMenuEvent e) {
172 openViewPreferencesButton.setSelected(
false);
184 BeanTreeView tree = getTree();
187 Node[] rootChildrenNodes = rootChildren.getNodes(
true);
188 if (rootChildrenNodes == null || rootChildrenNodes.length < 1) {
194 Stream.of(rootChildrenNodes)
195 .flatMap((n) -> getHostNodesAndParents(n).stream())
196 .filter((n) -> n != null)
197 .forEach(tree::expandNode);
199 Stream.of(rootChildrenNodes)
200 .filter(n -> n != null && NODES_TO_EXPAND.contains(n.getName()))
201 .forEach(tree::expandNode);
215 return Collections.emptyList();
216 }
else if (node.getLookup().lookup(Person.class) != null
218 Children children = node.getChildren();
219 Node[] childNodes = children == null ? null : children.getNodes();
220 if (childNodes != null) {
221 return Stream.of(childNodes)
222 .flatMap((n) -> Stream.concat(Stream.of(n), getHostNodesAndParents(n).stream()))
223 .collect(Collectors.toList());
225 }
else if (node.getLookup().lookup(Host.class) != null) {
226 return Arrays.asList(node);
228 return Collections.emptyList();
237 public void preferenceChange(PreferenceChangeEvent evt) {
238 switch (evt.getKey()) {
247 refreshContentTreeSafe();
255 refreshContentTreeSafe();
262 this.em.addPropertyChangeListener(
this);
266 this.dataResult.requestActive();
270 this.dataResult.
open();
274 return this.dataResult;
283 return showRejectedResults;
293 this.showRejectedResults = showRejectedResults;
294 if (accounts != null) {
307 viewPreferencesPopupMenu =
new javax.swing.JPopupMenu();
308 treeView =
new ExpansionBeanTreeView();
309 backButton =
new javax.swing.JButton();
310 forwardButton =
new javax.swing.JButton();
311 openViewPreferencesButton =
new javax.swing.JButton();
313 treeView.setBorder(null);
315 backButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/btn_step_back.png")));
316 org.openide.awt.Mnemonics.setLocalizedText(backButton,
org.openide.util.NbBundle.getMessage(
DirectoryTreeTopComponent.class,
"DirectoryTreeTopComponent.backButton.text"));
317 backButton.setBorderPainted(
false);
318 backButton.setContentAreaFilled(
false);
319 backButton.setDisabledIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/btn_step_back_disabled.png")));
320 backButton.setMargin(
new java.awt.Insets(2, 0, 2, 0));
321 backButton.setMaximumSize(
new java.awt.Dimension(55, 100));
322 backButton.setMinimumSize(
new java.awt.Dimension(5, 5));
323 backButton.setPreferredSize(
new java.awt.Dimension(24, 24));
324 backButton.setRolloverIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/btn_step_back_hover.png")));
325 backButton.addActionListener(
new java.awt.event.ActionListener() {
326 public void actionPerformed(java.awt.event.ActionEvent evt) {
327 backButtonActionPerformed(evt);
331 forwardButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/btn_step_forward.png")));
332 org.openide.awt.Mnemonics.setLocalizedText(forwardButton,
org.openide.util.NbBundle.getMessage(
DirectoryTreeTopComponent.class,
"DirectoryTreeTopComponent.forwardButton.text"));
333 forwardButton.setBorderPainted(
false);
334 forwardButton.setContentAreaFilled(
false);
335 forwardButton.setDisabledIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/btn_step_forward_disabled.png")));
336 forwardButton.setMargin(
new java.awt.Insets(2, 0, 2, 0));
337 forwardButton.setMaximumSize(
new java.awt.Dimension(55, 100));
338 forwardButton.setMinimumSize(
new java.awt.Dimension(5, 5));
339 forwardButton.setPreferredSize(
new java.awt.Dimension(24, 24));
340 forwardButton.setRolloverIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/btn_step_forward_hover.png")));
341 forwardButton.addActionListener(
new java.awt.event.ActionListener() {
342 public void actionPerformed(java.awt.event.ActionEvent evt) {
343 forwardButtonActionPerformed(evt);
347 openViewPreferencesButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/view-preferences-23.png")));
348 org.openide.awt.Mnemonics.setLocalizedText(openViewPreferencesButton,
org.openide.util.NbBundle.getMessage(
DirectoryTreeTopComponent.class,
"DirectoryTreeTopComponent.openViewPreferencesButton.text"));
349 openViewPreferencesButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
350 openViewPreferencesButton.setBorderPainted(
false);
351 openViewPreferencesButton.setContentAreaFilled(
false);
352 openViewPreferencesButton.setMaximumSize(
new java.awt.Dimension(24, 24));
353 openViewPreferencesButton.setMinimumSize(
new java.awt.Dimension(24, 24));
354 openViewPreferencesButton.setPreferredSize(
new java.awt.Dimension(24, 24));
355 openViewPreferencesButton.addActionListener(
new java.awt.event.ActionListener() {
356 public void actionPerformed(java.awt.event.ActionEvent evt) {
357 openViewPreferencesButtonActionPerformed(evt);
361 javax.swing.GroupLayout layout =
new javax.swing.GroupLayout(
this);
362 this.setLayout(layout);
363 layout.setHorizontalGroup(
364 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
365 .addComponent(treeView)
366 .addGroup(layout.createSequentialGroup()
368 .addComponent(backButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
369 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
370 .addComponent(forwardButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
371 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 140, Short.MAX_VALUE)
372 .addComponent(openViewPreferencesButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
375 layout.setVerticalGroup(
376 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
377 .addGroup(layout.createSequentialGroup()
379 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
380 .addComponent(openViewPreferencesButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
381 .addComponent(backButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
382 .addComponent(forwardButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
383 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
384 .addComponent(treeView, javax.swing.GroupLayout.DEFAULT_SIZE, 919, Short.MAX_VALUE))
390 this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
393 String[] currentNodePath = backList.pollLast();
394 forwardList.addLast(currentNodePath);
395 forwardButton.setEnabled(
true);
402 String[] newCurrentNodePath = backList.peekLast();
405 if (backList.size() > 1) {
406 backButton.setEnabled(
true);
408 backButton.setEnabled(
false);
412 setSelectedNode(newCurrentNodePath, null);
414 this.setCursor(null);
419 this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
421 String[] newCurrentNodePath = forwardList.pollLast();
422 if (!forwardList.isEmpty()) {
423 forwardButton.setEnabled(
true);
425 forwardButton.setEnabled(
false);
428 backList.addLast(newCurrentNodePath);
429 backButton.setEnabled(
true);
432 setSelectedNode(newCurrentNodePath, null);
434 this.setCursor(null);
438 viewPreferencesPanel.
load();
439 viewPreferencesPopupMenu.show(openViewPreferencesButton, 0, openViewPreferencesButton.getHeight() - 1);
459 if (instance == null) {
472 WindowManager winManager = WindowManager.
getDefault();
473 TopComponent win = winManager.findTopComponent(PREFERRED_ID);
476 "Cannot find " + PREFERRED_ID +
" component. It will not be located properly in the window system.");
480 return (DirectoryTreeTopComponent) win;
483 "There seem to be multiple components with the '" + PREFERRED_ID
484 +
"' ID. That is a potential source of errors and unexpected behavior.");
496 return TopComponent.PERSISTENCE_NEVER;
507 GroupDataSourcesDialog dialog =
new GroupDataSourcesDialog(dataSourceCount);
509 if (dialog.groupByDataSourceSelected()) {
511 refreshContentTreeSafe();
525 @NbBundle.Messages({
"# {0} - dataSourceCount",
526 "DirectoryTreeTopComponent.componentOpened.groupDataSources.text=This case contains {0} data sources. Would you like to group by data source for faster loading?",
527 "DirectoryTreeTopComponent.componentOpened.groupDataSources.title=Group by data source?"})
531 this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
532 Case openCase = null;
538 final Case currentCase = openCase;
540 if (!caseHasData(currentCase)) {
541 getTree().setRootVisible(
false);
546 Long settingsThreshold = null;
550 }
catch (NumberFormatException ex) {
551 LOGGER.log(Level.SEVERE,
"Group data sources threshold is not a number", ex);
556 final long threshold = settingsThreshold == null ? DEFAULT_DATASOURCE_GROUPING_THRESHOLD : settingsThreshold;
558 new SwingWorker<Integer, Void>() {
560 protected Integer doInBackground()
throws Exception {
561 int dataSourceCount = 0;
564 }
catch (TskCoreException ex) {
565 LOGGER.log(Level.SEVERE,
"Error loading data sources", ex);
567 return dataSourceCount;
571 protected void done() {
572 int dataSourceCount = 0;
574 dataSourceCount =
get();
575 }
catch (ExecutionException | InterruptedException ex) {
576 LOGGER.log(Level.SEVERE,
"Error loading data sources and getting count on background thread", ex);
579 && dataSourceCount > threshold) {
580 promptForDataSourceGrouping(dataSourceCount);
588 autopsyTreeChildren = Children.create(autopsyTreeChildFactory,
true);
589 Node root =
new AbstractNode(autopsyTreeChildren) {
596 public Action[] getActions(
boolean popup) {
597 return new Action[]{};
603 public Node.Handle getHandle() {
604 return new Node.Handle() {
606 public Node getNode()
throws IOException {
607 return em.getRootContext();
613 root =
new DirectoryTreeFilterNode(root,
true);
615 em.setRootContext(root);
616 em.getRootContext().setName(currentCase.
getName());
617 em.getRootContext().setDisplayName(currentCase.
getName());
618 getTree().setRootVisible(
false);
622 new SwingWorker<Node[], Void>() {
624 protected Node[] doInBackground()
throws Exception {
625 Children rootChildren = em.getRootContext().getChildren();
626 preExpandNodes(rootChildren);
636 if (rootChildren.getNodesCount() > 0) {
637 return new Node[]{rootChildren.getNodeAt(0)};
643 protected void done() {
647 if (!dataResult.isOpened()) {
658 Node[] selections =
get();
659 if (selections != null && selections.length > 0) {
660 em.setSelectedNodes(selections);
662 }
catch (PropertyVetoException ex) {
663 LOGGER.log(Level.SEVERE,
"Error setting default selected node.", ex);
664 }
catch (InterruptedException | ExecutionException ex) {
665 LOGGER.log(Level.SEVERE,
"Error expanding tree to initial state.", ex);
683 autopsyTreeChildren = null;
686 void writeProperties(java.util.Properties p) {
689 p.setProperty(
"version",
"1.0");
693 Object readProperties(java.util.Properties p) {
694 if (instance == null) {
702 String version = p.getProperty(
"version");
725 return caseHasData(openCase) ==
false;
748 return new Action[]{};
759 Node[] selectedNodes = this.getExplorerManager().getSelectedNodes();
760 if (selectedNodes.length > 0) {
761 result = selectedNodes[0];
775 String changed =
event.getPropertyName();
785 if (event.getOldValue() != null &&
event.getNewValue() == null) {
787 SwingUtilities.invokeLater(() -> {
788 Node emptyNode =
new AbstractNode(Children.LEAF);
789 em.setRootContext(emptyNode);
791 }
else if (event.getNewValue() != null) {
793 Case newCase = (
Case) event.getNewValue();
794 final String newCaseName = newCase.
getName();
795 SwingUtilities.invokeLater(() -> {
796 em.getRootContext().setName(newCaseName);
797 em.getRootContext().setDisplayName(newCaseName);
827 SwingUtilities.invokeLater(() -> {
838 else if (changed.equals(ExplorerManager.PROP_SELECTED_NODES)) {
839 respondSelection((Node[]) event.getOldValue(), (Node[]) event.getNewValue());
852 @NbBundle.Messages(
"DirectoryTreeTopComponent.emptyMimeNode.text=Data not available. Run file type identification module.")
853 void respondSelection(
final Node[] oldNodes,
final Node[] newNodes) {
863 EventQueue.invokeLater(() -> {
865 DirectoryTreeTopComponent.this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
867 Node treeNode = DirectoryTreeTopComponent.this.getSelectedNode();
868 if (treeNode != null) {
869 Node originNode = ((DirectoryTreeFilterNode) treeNode).getOriginal();
871 Node drfn =
new DataResultFilterNode(originNode, DirectoryTreeTopComponent.this.em);
873 if (FileTypesByMimeType.isEmptyMimeTypeNode(originNode)) {
876 EmptyNode emptyNode =
new EmptyNode(Bundle.DirectoryTreeTopComponent_emptyMimeNode_text());
877 dataResult.
setNode(
new TableFilterNode(emptyNode,
true,
"This Node Is Empty"));
878 }
else if (originNode instanceof DisplayableItemNode) {
879 dataResult.
setNode(
new TableFilterNode(drfn,
true, ((DisplayableItemNode) originNode).getItemType()));
881 dataResult.
setNode(
new TableFilterNode(drfn,
true));
883 String displayName =
"";
884 Content content = originNode.getLookup().lookup(Content.class);
885 if (content != null) {
887 displayName = content.getUniquePath();
888 }
catch (TskCoreException ex) {
889 LOGGER.log(Level.SEVERE,
"Exception while calling Content.getUniquePath() for node: {0}", originNode);
891 }
else if (originNode.getLookup().lookup(String.class) != null) {
892 displayName = originNode.getLookup().lookup(String.class);
894 dataResult.
setPath(displayName);
897 if (oldNodes != null && newNodes != null
898 && (oldNodes.length == newNodes.length)) {
899 boolean sameNodes =
true;
900 for (
int i = 0; i < oldNodes.length; i++) {
901 sameNodes = sameNodes && oldNodes[i].getName().equals(newNodes[i].getName());
904 dataResult.requestActive();
913 updateHistory(em.getSelectedNodes());
917 if (selectedNodes.length == 0) {
921 Node selectedNode = selectedNodes[0];
922 String selectedNodeName = selectedNode.getName();
930 String[] currentLast = backList.peekLast();
931 String lastNodeName = null;
932 if (currentLast != null && currentLast.length > 0) {
933 lastNodeName = currentLast[currentLast.length - 1];
936 if (currentLast == null || !selectedNodeName.equals(lastNodeName)) {
938 final String[] selectedPath = NodeOp.createPath(selectedNode, em.getRootContext());
939 backList.addLast(selectedPath);
940 if (backList.size() > 1) {
941 backButton.setEnabled(
true);
943 backButton.setEnabled(
false);
947 forwardButton.setEnabled(
false);
959 backButton.setEnabled(
false);
960 forwardButton.setEnabled(
false);
968 BeanTreeView getTree() {
969 return (BeanTreeView) this.treeView;
976 SwingUtilities.invokeLater(this::rebuildTree);
983 SwingUtilities.invokeLater(() -> {
985 if (autopsyTreeChildren == null) {
990 for (Node dataSource : autopsyTreeChildren.getNodes()) {
992 if (tagsNode != null) {
999 if (tagsNode != null) {
1012 Case currentCase = null;
1019 if (!caseHasData(currentCase)) {
1029 new SwingWorker<Void, Void>() {
1032 protected Void doInBackground()
throws Exception {
1037 protected void done() {
1042 preExpandNodes(em.getRootContext().getChildren());
1043 }
catch (InterruptedException | ExecutionException ex) {
1044 LOGGER.log(Level.SEVERE,
"Error selecting tree node.", ex);
1060 if (null == currentCase) {
1063 hasData = currentCase.
hasData();
1075 private void setSelectedNode(
final String[] previouslySelectedNodePath,
final String rootNodeName) {
1076 if (previouslySelectedNodePath == null) {
1079 SwingUtilities.invokeLater(
new Runnable() {
1082 if (previouslySelectedNodePath.length > 0 && (rootNodeName == null || previouslySelectedNodePath[0].equals(rootNodeName))) {
1083 Node selectedNode = null;
1084 ArrayList<String> selectedNodePath =
new ArrayList<>(Arrays.asList(previouslySelectedNodePath));
1085 while (null == selectedNode && !selectedNodePath.isEmpty()) {
1087 selectedNode = NodeOp.findPath(em.getRootContext(), selectedNodePath.toArray(
new String[selectedNodePath.size()]));
1088 }
catch (NodeNotFoundException ex) {
1090 if (selectedNodePath.size() > 1) {
1091 selectedNodePath.remove(selectedNodePath.size() - 1);
1093 StringBuilder nodePath =
new StringBuilder();
1094 for (
int i = 0; i < previouslySelectedNodePath.length; ++i) {
1095 nodePath.append(previouslySelectedNodePath[i]).append(
"/");
1097 LOGGER.log(Level.WARNING,
"Failed to find any nodes to select on path " + nodePath.toString(), ex);
1103 if (null != selectedNode) {
1104 if (rootNodeName != null) {
1107 backList.pollLast();
1110 em.setExploredContextAndSelection(selectedNode,
new Node[]{selectedNode});
1111 }
catch (PropertyVetoException ex) {
1112 LOGGER.log(Level.WARNING,
"Property veto from ExplorerManager setting selection to " + selectedNode.getName(), ex);
1144 case ANALYSIS_RESULT:
1147 LOGGER.log(Level.WARNING,
"Unbale to find category of type: " + category.name());
1148 return Optional.empty();
1166 return Optional.empty();
1167 }
else if (node.getLookup().lookup(Host.class) != null
1168 || node.getLookup().lookup(Person.class) != null
1171 Children children = node.getChildren();
1173 Stream<Node> childNodeStream = children == null ? Stream.empty() : Stream.of(children.getNodes());
1174 return childNodeStream
1175 .map(childNode -> searchForCategoryNode(childNode, dataSourceId, category))
1176 .filter(Optional::isPresent)
1180 DataSource dataSource = node.getLookup().lookup(DataSource.class);
1182 if (dataSource != null && dataSource.getId() == dataSourceId) {
1183 Children dsChildren = node.getChildren();
1184 if (dsChildren != null) {
1185 return getCategoryNodeChild(dsChildren, category);
1189 return Optional.empty();
1203 Children rootChildren = em.getRootContext().getChildren();
1204 Optional<Node> categoryNode = getCategoryNodeChild(rootChildren, category);
1205 if (categoryNode.isPresent()) {
1206 return categoryNode;
1211 dataSourceId = art.getDataSource().getId();
1212 }
catch (TskCoreException ex) {
1213 LOGGER.log(Level.WARNING,
"There was an error fetching the data source id for artifact.", ex);
1217 Node[] rootNodes = rootChildren.getNodes();
1218 Stream<Node> rootNodesStream = rootNodes == null ? Stream.empty() : Stream.of(rootNodes);
1219 return rootNodesStream
1220 .map((rootNode) -> searchForCategoryNode(rootNode, dataSourceId, category))
1221 .filter(Optional::isPresent)
1238 return Optional.empty();
1241 Host nodeHost = node.getLookup().lookup(Host.class);
1242 if ((nodeHost != null && hosts != null && hosts.contains(nodeHost))
1243 || node.getLookup().lookup(DataSource.class) != null
1244 || node.getLookup().lookup(Person.class) != null
1247 return Stream.of(node.getChildren().getNodes(
true))
1248 .map(childNode -> getOsAccountListNode(childNode, osAccount, hosts))
1249 .filter(Optional::isPresent)
1256 return Optional.of(node);
1259 return Optional.empty();
1268 Set<Host> hosts = null;
1273 }
catch (TskCoreException ex) {
1274 LOGGER.log(Level.WARNING,
"Unable to get valid hosts for osAccount: " + osAccount, ex);
1279 final Set<Host> finalHosts = hosts;
1281 Optional<Node> osAccountListNodeOpt = Stream.of(em.getRootContext().getChildren().getNodes(
true))
1282 .map(nd -> getOsAccountListNode(nd, osAccount, finalHosts))
1283 .filter(Optional::isPresent)
1287 if (!osAccountListNodeOpt.isPresent()) {
1291 Node osAccountListNode = osAccountListNodeOpt.get();
1293 DisplayableItemNode undecoratedParentNode = (DisplayableItemNode) ((DirectoryTreeFilterNode) osAccountListNode).getOriginal();
1295 OsAccount osAcctOfNd = osAcctNd.getLookup().lookup(OsAccount.class);
1296 return osAcctOfNd != null && osAcctOfNd.getId() == osAccount.getId();
1298 getTree().expandNode(osAccountListNode);
1300 em.setExploredContextAndSelection(osAccountListNode,
new Node[]{osAccountListNode});
1301 }
catch (PropertyVetoException ex) {
1302 LOGGER.log(Level.WARNING,
"Property Veto: ", ex);
1313 private Optional<BlackboardArtifact.Type>
getType(
long artifactTypeId) {
1316 .filter(type -> type.getTypeID() == artifactTypeId)
1319 LOGGER.log(Level.WARNING,
"Error occurred while looking up blackboard artifact type for: " + artifactTypeId, ex);
1320 return Optional.empty();
1338 @SuppressWarnings(
"deprecation")
1339 public
void viewArtifact(final BlackboardArtifact art) {
1340 int typeID = art.getArtifactTypeID();
1341 String typeName = art.getArtifactTypeName();
1343 Optional<BlackboardArtifact.Type> typeOpt = getType(typeID);
1344 Optional<Children> categoryChildrenOpt = typeOpt
1345 .flatMap(type -> getCategoryNode(type.getCategory(), art))
1346 .flatMap(categoryNode -> Optional.ofNullable(categoryNode.getChildren()));
1348 if (!categoryChildrenOpt.isPresent()) {
1349 LOGGER.log(Level.WARNING, String.format(
"Category node children for artifact of typeID: %d and artifactID: %d not found.",
1350 typeID, art.getArtifactID()));
1354 Children typesChildren = categoryChildrenOpt.get();
1356 Node treeNode = null;
1357 if (typeID == BlackboardArtifact.Type.TSK_HASHSET_HIT.getTypeID()) {
1358 treeNode = getHashsetNode(typesChildren, art);
1359 }
else if (typeID == BlackboardArtifact.Type.TSK_KEYWORD_HIT.getTypeID()) {
1360 treeNode = getKeywordHitNode(typesChildren, art);
1361 }
else if (typeID == BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT.getTypeID()) {
1362 treeNode = getInterestingItemNode(typesChildren, BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT, art);
1363 }
else if (typeID == BlackboardArtifact.Type.TSK_INTERESTING_ARTIFACT_HIT.getTypeID()) {
1364 treeNode = getInterestingItemNode(typesChildren, BlackboardArtifact.Type.TSK_INTERESTING_ARTIFACT_HIT, art);
1365 }
else if (typeID == BlackboardArtifact.Type.TSK_INTERESTING_ITEM.getTypeID()) {
1366 treeNode = getInterestingItemNode(typesChildren, BlackboardArtifact.Type.TSK_INTERESTING_ITEM, art);
1367 }
else if (typeID == BlackboardArtifact.Type.TSK_EMAIL_MSG.getTypeID()) {
1368 treeNode = getEmailNode(typesChildren, art);
1369 }
else if (typeID == BlackboardArtifact.Type.TSK_ACCOUNT.getTypeID()) {
1370 treeNode = getAccountNode(typesChildren, art);
1372 treeNode = typesChildren.findChild(typeName);
1375 if (treeNode == null) {
1379 DisplayableItemNode undecoratedParentNode = (DisplayableItemNode) ((DirectoryTreeFilterNode) treeNode).getOriginal();
1381 getTree().expandNode(treeNode);
1382 if (this.getSelectedNode().equals(treeNode)) {
1383 this.setDirectoryListingActive();
1384 this.respondSelection(em.getSelectedNodes(),
new Node[]{treeNode});
1387 em.setExploredContextAndSelection(treeNode,
new Node[]{treeNode});
1388 }
catch (PropertyVetoException ex) {
1389 LOGGER.log(Level.WARNING,
"Property Veto: ", ex);
1407 Node hashsetRootNode = typesChildren.findChild(art.getArtifactTypeName());
1408 Children hashsetRootChilds = hashsetRootNode.getChildren();
1410 String setName = null;
1411 List<BlackboardAttribute> attributes = art.getAttributes();
1412 for (BlackboardAttribute att : attributes) {
1413 int typeId = att.getAttributeType().getTypeID();
1414 if (typeId == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()) {
1415 setName = att.getValueString();
1418 return hashsetRootChilds.findChild(setName);
1419 }
catch (TskCoreException ex) {
1420 LOGGER.log(Level.WARNING,
"Error retrieving attributes", ex);
1437 Node keywordRootNode = typesChildren.findChild(art.getArtifactTypeName());
1438 Children keywordRootChilds = keywordRootNode.getChildren();
1440 String listName = null;
1441 String keywordName = null;
1442 String regex = null;
1443 List<BlackboardAttribute> attributes = art.getAttributes();
1444 for (BlackboardAttribute att : attributes) {
1445 int typeId = att.getAttributeType().getTypeID();
1446 if (typeId == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()) {
1447 listName = att.getValueString();
1448 }
else if (typeId == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID()) {
1449 keywordName = att.getValueString();
1450 }
else if (typeId == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP.getTypeID()) {
1451 regex = att.getValueString();
1454 if (listName == null) {
1455 if (regex == null) {
1456 listName = NbBundle.getMessage(
KeywordHits.class,
"KeywordHits.simpleLiteralSearch.text");
1458 listName = NbBundle.getMessage(
KeywordHits.class,
"KeywordHits.singleRegexSearch.text");
1461 Node listNode = keywordRootChilds.findChild(listName);
1462 if (listNode == null) {
1465 Children listChildren = listNode.getChildren();
1466 if (listChildren == null) {
1469 if (regex != null) {
1470 Node regexNode = listChildren.findChild(listName);
1471 regexNode = (regexNode == null) ? listChildren.findChild(listName +
"_" + regex) : regexNode;
1472 if (regexNode == null) {
1475 listChildren = regexNode.getChildren();
1476 if (listChildren == null) {
1481 return listChildren.findChild(keywordName);
1482 }
catch (TskCoreException ex) {
1483 LOGGER.log(Level.WARNING,
"Error retrieving attributes", ex);
1502 Node interestingItemsRootNode = typesChildren.findChild(artifactType.getDisplayName());
1503 Children setNodeChildren = (interestingItemsRootNode == null) ? null : interestingItemsRootNode.getChildren();
1506 if (setNodeChildren == null) {
1510 String setName = null;
1512 setName = art.getAttributes().stream()
1513 .filter(attr -> attr.getAttributeType().getTypeID() == BlackboardAttribute.Type.TSK_SET_NAME.getTypeID())
1514 .map(attr -> attr.getValueString())
1518 }
catch (TskCoreException ex) {
1519 LOGGER.log(Level.WARNING,
"Error retrieving attributes", ex);
1524 if (setName == null) {
1529 final String finalSetName = setName;
1530 return Stream.of(setNodeChildren.getNodes(
true))
1531 .filter(setNode -> finalSetName.equals(setNode.getLookup().lookup(String.class)))
1544 private Node
getEmailNode(Children typesChildren, BlackboardArtifact art) {
1545 Node emailMsgRootNode = typesChildren.findChild(art.getArtifactTypeName());
1546 Children emailMsgRootChilds = emailMsgRootNode.getChildren();
1547 Map<String, String> parsedPath = null;
1549 List<BlackboardAttribute> attributes = art.getAttributes();
1550 for (BlackboardAttribute att : attributes) {
1551 int typeId = att.getAttributeType().getTypeID();
1552 if (typeId == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH.getTypeID()) {
1557 if (parsedPath == null) {
1560 Node defaultNode = emailMsgRootChilds.findChild(parsedPath.get(NbBundle.getMessage(
EmailExtracted.class,
"EmailExtracted.defaultAcct.text")));
1561 Children defaultChildren = defaultNode.getChildren();
1562 return defaultChildren.findChild(parsedPath.get(NbBundle.getMessage(
EmailExtracted.class,
"EmailExtracted.defaultFolder.text")));
1563 }
catch (TskCoreException ex) {
1564 LOGGER.log(Level.WARNING,
"Error retrieving attributes", ex);
1579 Node accountRootNode = typesChildren.findChild(art.getDisplayName());
1580 Children accountRootChilds = accountRootNode.getChildren();
1581 List<BlackboardAttribute> attributes;
1582 String accountType = null;
1583 String ccNumberName = null;
1585 attributes = art.getAttributes();
1586 for (BlackboardAttribute att : attributes) {
1587 int typeId = att.getAttributeType().getTypeID();
1588 if (typeId == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE.getTypeID()) {
1589 accountType = att.getValueString();
1591 if (typeId == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER.getTypeID()) {
1592 ccNumberName = att.getValueString();
1595 if (accountType == null) {
1599 if (accountType.equals(Account.Type.CREDIT_CARD.getTypeName())) {
1600 return getCreditCardAccountNode(accountRootChilds, ccNumberName);
1602 return accountRootChilds.findChild(accountType);
1604 }
catch (TskCoreException ex) {
1605 LOGGER.log(Level.WARNING,
"Error retrieving attributes", ex);
1621 Node accountNode = accountRootChildren.findChild(Account.Type.CREDIT_CARD.getDisplayName());
1622 if (accountNode == null) {
1625 Children accountChildren = accountNode.getChildren();
1626 if (accountChildren == null) {
1629 Node binNode = accountChildren.findChild(NbBundle.getMessage(
Accounts.class,
"Accounts.ByBINNode.name"));
1630 if (binNode == null) {
1633 Children binChildren = binNode.getChildren();
1634 if (ccNumberName == null) {
1639 String binName = StringUtils.rightPad(ccNumberName, 8,
"0");
1640 binName = binName.substring(0, 8);
1643 bin = Integer.parseInt(binName);
1644 }
catch (NumberFormatException ex) {
1645 LOGGER.log(Level.WARNING,
"Unable to parseInt a BIN for node selection from string binName=" + binName, ex);
1649 if (binInfo != null) {
1650 int startBin = ((
BINRange) binInfo).getBINstart();
1651 int endBin = ((
BINRange) binInfo).getBINend();
1652 if (startBin != endBin) {
1653 binName = Integer.toString(startBin) +
"-" + Integer.toString(endBin).substring(5);
1656 if (binName == null) {
1659 return binChildren.findChild(binName);
1664 NbBundle.getMessage(
this.getClass(),
"DirectoryTreeTopComponent.action.viewArtContent.text"),
static synchronized String getConfigSetting(String moduleName, String settingName)
List< Content > getDataSources()
TopComponent getTopComponent()
Children autopsyTreeChildren
static final String HIDE_SLACK_FILES_IN_VIEWS_TREE
Node getAccountNode(Children typesChildren, BlackboardArtifact art)
javax.swing.JScrollPane treeView
Node getCreditCardAccountNode(Children accountRootChildren, String ccNumberName)
static boolean caseHasData(Case currentCase)
static final String HIDE_KNOWN_FILES_IN_VIEWS_TREE
DataResultTopComponent getDirectoryListing()
final LinkedList< String[]> forwardList
void setDirectoryListingActive()
static boolean runningWithGUI
void setShowRejected(boolean showRejected)
static final String HIDE_SCO_COLUMNS
void setSelectedNode(final String[] previouslySelectedNodePath, final String rootNodeName)
Optional< Node > getCategoryNodeChild(Children children, Category category)
javax.swing.JButton openViewPreferencesButton
boolean hasMenuOpenAction()
static void openCoreWindows()
static final String TEXT_TRANSLATOR_NAME
void updateHistory(Node[] selectedNodes)
final LinkedList< String[]> backList
static synchronized BankIdentificationNumber getBINInfo(int bin)
void openDirectoryListing()
Optional< BlackboardArtifact.Type > getType(long artifactTypeId)
void refreshContentTreeSafe()
void readPropertiesImpl(java.util.Properties p)
void backButtonActionPerformed(java.awt.event.ActionEvent evt)
void setShowRejectedResults(boolean showRejectedResults)
static final String SHOW_ONLY_CURRENT_USER_TAGS
void propertyChange(PropertyChangeEvent event)
static final String HIDE_KNOWN_FILES_IN_DATA_SRCS_TREE
AutopsyTreeChildFactory autopsyTreeChildFactory
static String getUnknownPersonId()
Optional< Node > searchForCategoryNode(Node node, long dataSourceId, Category category)
Node getEmailNode(Children typesChildren, BlackboardArtifact art)
static synchronized boolean settingExists(String moduleName, String settingName)
Optional< Node > getOsAccountListNode(Node node, OsAccount osAccount, Set< Host > hosts)
DirectoryTreeTopComponent()
static synchronized DirectoryTreeTopComponent getDefault()
static final String DISPLAY_TIMES_IN_LOCAL_TIME
javax.swing.JButton forwardButton
static void setGroupItemsInTreeByDataSource(boolean value)
static final String KEEP_PREFERRED_VIEWER
static synchronized void setConfigSetting(String moduleName, String settingName, String settingVal)
Optional< Node > getCategoryNode(Category category, BlackboardArtifact art)
boolean showRejectedResults
void viewArtifactContent(BlackboardArtifact art)
static final String DISPLAY_TRANSLATED_NAMES
Node getHashsetNode(Children typesChildren, final BlackboardArtifact art)
void promptForDataSourceGrouping(int dataSourceCount)
ExplorerManager getExplorerManager()
javax.swing.JButton backButton
static final String HIDE_SLACK_FILES_IN_DATA_SRCS_TREE
SleuthkitCase getSleuthkitCase()
void preExpandNodes(Children rootChildren)
static Boolean getGroupItemsInTreeByDataSource()
static DirectoryTreeTopComponent instance
void addOnFinishedListener(PropertyChangeListener l)
Node getKeywordHitNode(Children typesChildren, BlackboardArtifact art)
static String getListName()
static final String MAIN_SETTINGS
static Case getCurrentCase()
synchronized static Logger getLogger(String name)
static Case getCurrentCaseThrows()
List< Node > getHostNodesAndParents(Node node)
boolean getShowRejectedResults()
static void addEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
static void addChangeListener(PreferenceChangeListener listener)
void viewOsAccount(OsAccount osAccount)
javax.swing.JPopupMenu viewPreferencesPopupMenu
void setChildNodeSelectionInfo(NodeSelectionInfo selectedChildNodeInfo)
void forwardButtonActionPerformed(java.awt.event.ActionEvent evt)
void subscribeToChangeEvents()
static synchronized DirectoryTreeTopComponent findInstance()
void setPath(String pathText)
static final String TIME_ZONE_FOR_DISPLAYS
static boolean isCaseOpen()
Node getInterestingItemNode(Children typesChildren, BlackboardArtifact.Type artifactType, BlackboardArtifact art)
void openViewPreferencesButtonActionPerformed(java.awt.event.ActionEvent evt)
void setNode(Node selectedNode)