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.LinkedList;
32 import java.util.List;
34 import java.util.Objects;
35 import java.util.Optional;
37 import java.util.concurrent.ExecutionException;
38 import java.util.logging.Level;
39 import java.util.prefs.PreferenceChangeEvent;
40 import java.util.prefs.PreferenceChangeListener;
41 import java.util.stream.Collectors;
42 import java.util.stream.Stream;
43 import javax.swing.Action;
44 import javax.swing.SwingUtilities;
45 import javax.swing.SwingWorker;
46 import javax.swing.event.PopupMenuEvent;
47 import javax.swing.event.PopupMenuListener;
48 import javax.swing.tree.TreeSelectionModel;
49 import org.apache.commons.lang3.StringUtils;
50 import org.openide.explorer.ExplorerManager;
51 import org.openide.explorer.ExplorerUtils;
52 import org.openide.explorer.view.BeanTreeView;
53 import org.openide.nodes.AbstractNode;
54 import org.openide.nodes.Children;
55 import org.openide.nodes.Node;
56 import org.openide.nodes.NodeNotFoundException;
57 import org.openide.nodes.NodeOp;
58 import org.openide.util.NbBundle;
59 import org.openide.util.NbBundle.Messages;
60 import org.openide.windows.TopComponent;
61 import org.openide.windows.WindowManager;
93 import org.
sleuthkit.datamodel.BlackboardArtifact.Category;
106 "DirectoryTreeTopComponent.resultsView.title=Listing"
108 @SuppressWarnings(
"PMD.SingularField")
111 private final transient ExplorerManager em =
new ExplorerManager();
117 private static final String PREFERRED_ID =
"DirectoryTreeTopComponent";
123 private static final long DEFAULT_DATASOURCE_GROUPING_THRESHOLD = 5;
124 private static final String GROUPING_THRESHOLD_NAME =
"GroupDataSourceThreshold";
125 private static final String SETTINGS_FILE =
"CasePreferences.properties";
129 .collect(Collectors.toSet());
138 getTree().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
141 putClientProperty(TopComponent.PROP_CLOSING_DISABLED, Boolean.TRUE);
145 subscribeToChangeEvents();
146 associateLookup(ExplorerUtils.createLookup(em, getActionMap()));
149 this.backList =
new LinkedList<>();
150 this.forwardList =
new LinkedList<>();
151 backButton.setEnabled(
false);
152 forwardButton.setEnabled(
false);
154 viewPreferencesPopupMenu.add(viewPreferencesPanel);
155 viewPreferencesPopupMenu.setSize(viewPreferencesPanel.getPreferredSize().width + 6, viewPreferencesPanel.getPreferredSize().height + 6);
156 viewPreferencesPopupMenu.addPopupMenuListener(
new PopupMenuListener() {
158 public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
159 openViewPreferencesButton.setSelected(
true);
163 public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
164 openViewPreferencesButton.setSelected(
false);
168 public void popupMenuCanceled(PopupMenuEvent e) {
169 openViewPreferencesButton.setSelected(
false);
181 BeanTreeView tree = getTree();
184 Node[] rootChildrenNodes = rootChildren.getNodes(
true);
185 if (rootChildrenNodes == null || rootChildrenNodes.length < 1) {
191 Stream.of(rootChildrenNodes)
192 .flatMap((n) -> getHostNodesAndParents(n).stream())
193 .filter((n) -> n != null)
194 .forEach(tree::expandNode);
196 Stream.of(rootChildrenNodes)
197 .filter(n -> n != null && NODES_TO_EXPAND.contains(n.getName()))
198 .forEach(tree::expandNode);
212 return Collections.emptyList();
213 }
else if (node.getLookup().lookup(Person.class) != null
215 Children children = node.getChildren();
216 Node[] childNodes = children == null ? null : children.getNodes();
217 if (childNodes != null) {
218 return Stream.of(childNodes)
219 .flatMap((n) -> Stream.concat(Stream.of(n), getHostNodesAndParents(n).stream()))
220 .collect(Collectors.toList());
222 }
else if (node.getLookup().lookup(Host.class) != null) {
223 return Arrays.asList(node);
225 return Collections.emptyList();
234 public void preferenceChange(PreferenceChangeEvent evt) {
235 switch (evt.getKey()) {
244 refreshContentTreeSafe();
252 refreshContentTreeSafe();
259 this.em.addPropertyChangeListener(
this);
263 this.dataResult.requestActive();
267 this.dataResult.
open();
271 return this.dataResult;
280 return showRejectedResults;
290 this.showRejectedResults = showRejectedResults;
291 if (accounts != null) {
304 viewPreferencesPopupMenu =
new javax.swing.JPopupMenu();
305 treeView =
new ExpansionBeanTreeView();
306 backButton =
new javax.swing.JButton();
307 forwardButton =
new javax.swing.JButton();
308 openViewPreferencesButton =
new javax.swing.JButton();
310 treeView.setBorder(null);
312 backButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/btn_step_back.png")));
313 org.openide.awt.Mnemonics.setLocalizedText(backButton,
org.openide.util.NbBundle.getMessage(
DirectoryTreeTopComponent.class,
"DirectoryTreeTopComponent.backButton.text"));
314 backButton.setBorderPainted(
false);
315 backButton.setContentAreaFilled(
false);
316 backButton.setDisabledIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/btn_step_back_disabled.png")));
317 backButton.setMargin(
new java.awt.Insets(2, 0, 2, 0));
318 backButton.setMaximumSize(
new java.awt.Dimension(55, 100));
319 backButton.setMinimumSize(
new java.awt.Dimension(5, 5));
320 backButton.setPreferredSize(
new java.awt.Dimension(24, 24));
321 backButton.setRolloverIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/btn_step_back_hover.png")));
322 backButton.addActionListener(
new java.awt.event.ActionListener() {
323 public void actionPerformed(java.awt.event.ActionEvent evt) {
324 backButtonActionPerformed(evt);
328 forwardButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/btn_step_forward.png")));
329 org.openide.awt.Mnemonics.setLocalizedText(forwardButton,
org.openide.util.NbBundle.getMessage(
DirectoryTreeTopComponent.class,
"DirectoryTreeTopComponent.forwardButton.text"));
330 forwardButton.setBorderPainted(
false);
331 forwardButton.setContentAreaFilled(
false);
332 forwardButton.setDisabledIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/btn_step_forward_disabled.png")));
333 forwardButton.setMargin(
new java.awt.Insets(2, 0, 2, 0));
334 forwardButton.setMaximumSize(
new java.awt.Dimension(55, 100));
335 forwardButton.setMinimumSize(
new java.awt.Dimension(5, 5));
336 forwardButton.setPreferredSize(
new java.awt.Dimension(24, 24));
337 forwardButton.setRolloverIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/btn_step_forward_hover.png")));
338 forwardButton.addActionListener(
new java.awt.event.ActionListener() {
339 public void actionPerformed(java.awt.event.ActionEvent evt) {
340 forwardButtonActionPerformed(evt);
344 openViewPreferencesButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/directorytree/view-preferences-23.png")));
345 org.openide.awt.Mnemonics.setLocalizedText(openViewPreferencesButton,
org.openide.util.NbBundle.getMessage(
DirectoryTreeTopComponent.class,
"DirectoryTreeTopComponent.openViewPreferencesButton.text"));
346 openViewPreferencesButton.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
347 openViewPreferencesButton.setBorderPainted(
false);
348 openViewPreferencesButton.setContentAreaFilled(
false);
349 openViewPreferencesButton.setMaximumSize(
new java.awt.Dimension(24, 24));
350 openViewPreferencesButton.setMinimumSize(
new java.awt.Dimension(24, 24));
351 openViewPreferencesButton.setPreferredSize(
new java.awt.Dimension(24, 24));
352 openViewPreferencesButton.addActionListener(
new java.awt.event.ActionListener() {
353 public void actionPerformed(java.awt.event.ActionEvent evt) {
354 openViewPreferencesButtonActionPerformed(evt);
358 javax.swing.GroupLayout layout =
new javax.swing.GroupLayout(
this);
359 this.setLayout(layout);
360 layout.setHorizontalGroup(
361 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
362 .addComponent(treeView)
363 .addGroup(layout.createSequentialGroup()
365 .addComponent(backButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
366 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
367 .addComponent(forwardButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
368 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 140, Short.MAX_VALUE)
369 .addComponent(openViewPreferencesButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
372 layout.setVerticalGroup(
373 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
374 .addGroup(layout.createSequentialGroup()
376 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
377 .addComponent(openViewPreferencesButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
378 .addComponent(backButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
379 .addComponent(forwardButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
380 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
381 .addComponent(treeView, javax.swing.GroupLayout.DEFAULT_SIZE, 919, Short.MAX_VALUE))
387 this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
390 String[] currentNodePath = backList.pollLast();
391 forwardList.addLast(currentNodePath);
392 forwardButton.setEnabled(
true);
399 String[] newCurrentNodePath = backList.peekLast();
402 if (backList.size() > 1) {
403 backButton.setEnabled(
true);
405 backButton.setEnabled(
false);
409 setSelectedNode(newCurrentNodePath, null);
411 this.setCursor(null);
416 this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
418 String[] newCurrentNodePath = forwardList.pollLast();
419 if (!forwardList.isEmpty()) {
420 forwardButton.setEnabled(
true);
422 forwardButton.setEnabled(
false);
425 backList.addLast(newCurrentNodePath);
426 backButton.setEnabled(
true);
429 setSelectedNode(newCurrentNodePath, null);
431 this.setCursor(null);
435 viewPreferencesPanel.
load();
436 viewPreferencesPopupMenu.show(openViewPreferencesButton, 0, openViewPreferencesButton.getHeight() - 1);
456 if (instance == null) {
469 WindowManager winManager = WindowManager.
getDefault();
470 TopComponent win = winManager.findTopComponent(PREFERRED_ID);
473 "Cannot find " + PREFERRED_ID +
" component. It will not be located properly in the window system.");
477 return (DirectoryTreeTopComponent) win;
480 "There seem to be multiple components with the '" + PREFERRED_ID
481 +
"' ID. That is a potential source of errors and unexpected behavior.");
493 return TopComponent.PERSISTENCE_NEVER;
504 GroupDataSourcesDialog dialog =
new GroupDataSourcesDialog(dataSourceCount);
506 if (dialog.groupByDataSourceSelected()) {
508 refreshContentTreeSafe();
522 @NbBundle.Messages({
"# {0} - dataSourceCount",
523 "DirectoryTreeTopComponent.componentOpened.groupDataSources.text=This case contains {0} data sources. Would you like to group by data source for faster loading?",
524 "DirectoryTreeTopComponent.componentOpened.groupDataSources.title=Group by data source?"})
528 this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
529 Case openCase = null;
535 final Case currentCase = openCase;
537 if (!caseHasData(currentCase)) {
538 getTree().setRootVisible(
false);
543 Long settingsThreshold = null;
547 }
catch (NumberFormatException ex) {
548 LOGGER.log(Level.SEVERE,
"Group data sources threshold is not a number", ex);
553 final long threshold = settingsThreshold == null ? DEFAULT_DATASOURCE_GROUPING_THRESHOLD : settingsThreshold;
555 new SwingWorker<Integer, Void>() {
557 protected Integer doInBackground()
throws Exception {
558 int dataSourceCount = 0;
561 }
catch (TskCoreException ex) {
562 LOGGER.log(Level.SEVERE,
"Error loading data sources", ex);
564 return dataSourceCount;
568 protected void done() {
569 int dataSourceCount = 0;
571 dataSourceCount =
get();
572 }
catch (ExecutionException | InterruptedException ex) {
573 LOGGER.log(Level.SEVERE,
"Error loading data sources and getting count on background thread", ex);
576 && dataSourceCount > threshold) {
577 promptForDataSourceGrouping(dataSourceCount);
585 autopsyTreeChildren = Children.create(autopsyTreeChildFactory,
true);
586 Node root =
new AbstractNode(autopsyTreeChildren) {
593 public Action[] getActions(
boolean popup) {
594 return new Action[]{};
600 public Node.Handle getHandle() {
601 return new Node.Handle() {
603 public Node getNode()
throws IOException {
604 return em.getRootContext();
610 root =
new DirectoryTreeFilterNode(root,
true);
612 em.setRootContext(root);
613 em.getRootContext().setName(currentCase.
getName());
614 em.getRootContext().setDisplayName(currentCase.
getName());
615 getTree().setRootVisible(
false);
619 new SwingWorker<Node[], Void>() {
621 protected Node[] doInBackground()
throws Exception {
622 Children rootChildren = em.getRootContext().getChildren();
623 preExpandNodes(rootChildren);
633 if (rootChildren.getNodesCount() > 0) {
634 return new Node[]{rootChildren.getNodeAt(0)};
640 protected void done() {
644 if (!dataResult.isOpened()) {
655 Node[] selections =
get();
656 if (selections != null && selections.length > 0) {
657 em.setSelectedNodes(selections);
659 }
catch (PropertyVetoException ex) {
660 LOGGER.log(Level.SEVERE,
"Error setting default selected node.", ex);
661 }
catch (InterruptedException | ExecutionException ex) {
662 LOGGER.log(Level.SEVERE,
"Error expanding tree to initial state.", ex);
680 autopsyTreeChildren = null;
683 void writeProperties(java.util.Properties p) {
686 p.setProperty(
"version",
"1.0");
690 Object readProperties(java.util.Properties p) {
691 if (instance == null) {
699 String version = p.getProperty(
"version");
722 return caseHasData(openCase) ==
false;
745 return new Action[]{};
756 Node[] selectedNodes = this.getExplorerManager().getSelectedNodes();
757 if (selectedNodes.length > 0) {
758 result = selectedNodes[0];
772 String changed =
event.getPropertyName();
782 if (event.getOldValue() != null &&
event.getNewValue() == null) {
784 SwingUtilities.invokeLater(() -> {
785 Node emptyNode =
new AbstractNode(Children.LEAF);
786 em.setRootContext(emptyNode);
788 }
else if (event.getNewValue() != null) {
790 Case newCase = (
Case) event.getNewValue();
791 final String newCaseName = newCase.
getName();
792 SwingUtilities.invokeLater(() -> {
793 em.getRootContext().setName(newCaseName);
794 em.getRootContext().setDisplayName(newCaseName);
824 SwingUtilities.invokeLater(() -> {
835 else if (changed.equals(ExplorerManager.PROP_SELECTED_NODES)) {
836 respondSelection((Node[]) event.getOldValue(), (Node[]) event.getNewValue());
849 @NbBundle.Messages(
"DirectoryTreeTopComponent.emptyMimeNode.text=Data not available. Run file type identification module.")
850 void respondSelection(
final Node[] oldNodes,
final Node[] newNodes) {
860 EventQueue.invokeLater(() -> {
862 DirectoryTreeTopComponent.this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
864 Node treeNode = DirectoryTreeTopComponent.this.getSelectedNode();
865 if (treeNode != null) {
866 Node originNode = ((DirectoryTreeFilterNode) treeNode).getOriginal();
868 Node drfn =
new DataResultFilterNode(originNode, DirectoryTreeTopComponent.this.em);
870 if (FileTypesByMimeType.isEmptyMimeTypeNode(originNode)) {
873 EmptyNode emptyNode =
new EmptyNode(Bundle.DirectoryTreeTopComponent_emptyMimeNode_text());
874 dataResult.
setNode(
new TableFilterNode(emptyNode,
true,
"This Node Is Empty"));
875 }
else if (originNode instanceof DisplayableItemNode) {
876 dataResult.
setNode(
new TableFilterNode(drfn,
true, ((DisplayableItemNode) originNode).getItemType()));
878 dataResult.
setNode(
new TableFilterNode(drfn,
true));
880 String displayName =
"";
881 Content content = originNode.getLookup().lookup(Content.class);
882 if (content != null) {
884 displayName = content.getUniquePath();
885 }
catch (TskCoreException ex) {
886 LOGGER.log(Level.SEVERE,
"Exception while calling Content.getUniquePath() for node: {0}", originNode);
888 }
else if (originNode.getLookup().lookup(String.class) != null) {
889 displayName = originNode.getLookup().lookup(String.class);
891 dataResult.
setPath(displayName);
894 if (oldNodes != null && newNodes != null
895 && (oldNodes.length == newNodes.length)) {
896 boolean sameNodes =
true;
897 for (
int i = 0; i < oldNodes.length; i++) {
898 sameNodes = sameNodes && oldNodes[i].getName().equals(newNodes[i].getName());
901 dataResult.requestActive();
910 updateHistory(em.getSelectedNodes());
914 if (selectedNodes.length == 0) {
918 Node selectedNode = selectedNodes[0];
919 String selectedNodeName = selectedNode.getName();
927 String[] currentLast = backList.peekLast();
928 String lastNodeName = null;
929 if (currentLast != null && currentLast.length > 0) {
930 lastNodeName = currentLast[currentLast.length - 1];
933 if (currentLast == null || !selectedNodeName.equals(lastNodeName)) {
935 final String[] selectedPath = NodeOp.createPath(selectedNode, em.getRootContext());
936 backList.addLast(selectedPath);
937 if (backList.size() > 1) {
938 backButton.setEnabled(
true);
940 backButton.setEnabled(
false);
944 forwardButton.setEnabled(
false);
956 backButton.setEnabled(
false);
957 forwardButton.setEnabled(
false);
965 BeanTreeView getTree() {
966 return (BeanTreeView) this.treeView;
973 SwingUtilities.invokeLater(this::rebuildTree);
980 SwingUtilities.invokeLater(() -> {
982 if (autopsyTreeChildren == null) {
987 for (Node dataSource : autopsyTreeChildren.getNodes()) {
989 if (tagsNode != null) {
996 if (tagsNode != null) {
1009 Case currentCase = null;
1016 if (!caseHasData(currentCase)) {
1026 new SwingWorker<Void, Void>() {
1029 protected Void doInBackground()
throws Exception {
1034 protected void done() {
1039 preExpandNodes(em.getRootContext().getChildren());
1040 }
catch (InterruptedException | ExecutionException ex) {
1041 LOGGER.log(Level.SEVERE,
"Error selecting tree node.", ex);
1057 if (null == currentCase) {
1060 hasData = currentCase.
hasData();
1072 private void setSelectedNode(
final String[] previouslySelectedNodePath,
final String rootNodeName) {
1073 if (previouslySelectedNodePath == null) {
1076 SwingUtilities.invokeLater(
new Runnable() {
1079 if (previouslySelectedNodePath.length > 0 && (rootNodeName == null || previouslySelectedNodePath[0].equals(rootNodeName))) {
1080 Node selectedNode = null;
1081 ArrayList<String> selectedNodePath =
new ArrayList<>(Arrays.asList(previouslySelectedNodePath));
1082 while (null == selectedNode && !selectedNodePath.isEmpty()) {
1084 selectedNode = NodeOp.findPath(em.getRootContext(), selectedNodePath.toArray(
new String[selectedNodePath.size()]));
1085 }
catch (NodeNotFoundException ex) {
1087 if (selectedNodePath.size() > 1) {
1088 selectedNodePath.remove(selectedNodePath.size() - 1);
1090 StringBuilder nodePath =
new StringBuilder();
1091 for (
int i = 0; i < previouslySelectedNodePath.length; ++i) {
1092 nodePath.append(previouslySelectedNodePath[i]).append(
"/");
1094 LOGGER.log(Level.WARNING,
"Failed to find any nodes to select on path " + nodePath.toString(), ex);
1100 if (null != selectedNode) {
1101 if (rootNodeName != null) {
1104 backList.pollLast();
1107 em.setExploredContextAndSelection(selectedNode,
new Node[]{selectedNode});
1108 }
catch (PropertyVetoException ex) {
1109 LOGGER.log(Level.WARNING,
"Property veto from ExplorerManager setting selection to " + selectedNode.getName(), ex);
1141 case ANALYSIS_RESULT:
1144 LOGGER.log(Level.WARNING,
"Unbale to find category of type: " + category.name());
1145 return Optional.empty();
1163 return Optional.empty();
1164 }
else if (node.getLookup().lookup(Host.class) != null
1165 || node.getLookup().lookup(Person.class) != null
1168 Children children = node.getChildren();
1170 Stream<Node> childNodeStream = children == null ? Stream.empty() : Stream.of(children.getNodes());
1171 return childNodeStream
1172 .map(childNode -> searchForCategoryNode(childNode, dataSourceId, category))
1173 .filter(Optional::isPresent)
1177 DataSource dataSource = node.getLookup().lookup(DataSource.class);
1179 if (dataSource != null && dataSource.getId() == dataSourceId) {
1180 Children dsChildren = node.getChildren();
1181 if (dsChildren != null) {
1182 return getCategoryNodeChild(dsChildren, category);
1186 return Optional.empty();
1200 Children rootChildren = em.getRootContext().getChildren();
1201 Optional<Node> categoryNode = getCategoryNodeChild(rootChildren, category);
1202 if (categoryNode.isPresent()) {
1203 return categoryNode;
1208 dataSourceId = art.getDataSource().getId();
1209 }
catch (TskCoreException ex) {
1210 LOGGER.log(Level.WARNING,
"There was an error fetching the data source id for artifact.", ex);
1214 Node[] rootNodes = rootChildren.getNodes();
1215 Stream<Node> rootNodesStream = rootNodes == null ? Stream.empty() : Stream.of(rootNodes);
1216 return rootNodesStream
1217 .map((rootNode) -> searchForCategoryNode(rootNode, dataSourceId, category))
1218 .filter(Optional::isPresent)
1230 private Optional<BlackboardArtifact.Type>
getType(
long artifactTypeId) {
1233 .filter(type -> type.getTypeID() == artifactTypeId)
1236 LOGGER.log(Level.WARNING,
"Error occurred while looking up blackboard artifact type for: " + artifactTypeId, ex);
1237 return Optional.empty();
1253 int typeID = art.getArtifactTypeID();
1254 String typeName = art.getArtifactTypeName();
1256 Optional<BlackboardArtifact.Type> typeOpt = getType(typeID);
1257 Optional<Children> categoryChildrenOpt = typeOpt
1258 .flatMap(type -> getCategoryNode(type.getCategory(), art))
1259 .flatMap(categoryNode -> Optional.ofNullable(categoryNode.getChildren()));
1261 if (!categoryChildrenOpt.isPresent()) {
1262 LOGGER.log(Level.WARNING, String.format(
"Category node children for artifact of typeID: %d and artifactID: %d not found.",
1263 typeID, art.getArtifactID()));
1267 Children typesChildren = categoryChildrenOpt.get();
1269 Node treeNode = null;
1270 if (typeID == BlackboardArtifact.Type.TSK_HASHSET_HIT.getTypeID()) {
1271 treeNode = getHashsetNode(typesChildren, art);
1272 }
else if (typeID == BlackboardArtifact.Type.TSK_KEYWORD_HIT.getTypeID()) {
1273 treeNode = getKeywordHitNode(typesChildren, art);
1274 }
else if (typeID == BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT.getTypeID()
1275 || typeID == BlackboardArtifact.Type.TSK_INTERESTING_ARTIFACT_HIT.getTypeID()) {
1276 treeNode = getInterestingItemNode(typesChildren, art);
1277 }
else if (typeID == BlackboardArtifact.Type.TSK_EMAIL_MSG.getTypeID()) {
1278 treeNode = getEmailNode(typesChildren, art);
1279 }
else if (typeID == BlackboardArtifact.Type.TSK_ACCOUNT.getTypeID()) {
1280 treeNode = getAccountNode(typesChildren, art);
1282 treeNode = typesChildren.findChild(typeName);
1285 if (treeNode == null) {
1289 DisplayableItemNode undecoratedParentNode = (DisplayableItemNode) ((DirectoryTreeFilterNode) treeNode).getOriginal();
1291 getTree().expandNode(treeNode);
1292 if (this.getSelectedNode().equals(treeNode)) {
1293 this.setDirectoryListingActive();
1294 this.respondSelection(em.getSelectedNodes(),
new Node[]{treeNode});
1297 em.setExploredContextAndSelection(treeNode,
new Node[]{treeNode});
1298 }
catch (PropertyVetoException ex) {
1299 LOGGER.log(Level.WARNING,
"Property Veto: ", ex);
1317 Node hashsetRootNode = typesChildren.findChild(art.getArtifactTypeName());
1318 Children hashsetRootChilds = hashsetRootNode.getChildren();
1320 String setName = null;
1321 List<BlackboardAttribute> attributes = art.getAttributes();
1322 for (BlackboardAttribute att : attributes) {
1323 int typeId = att.getAttributeType().getTypeID();
1324 if (typeId == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()) {
1325 setName = att.getValueString();
1328 return hashsetRootChilds.findChild(setName);
1329 }
catch (TskCoreException ex) {
1330 LOGGER.log(Level.WARNING,
"Error retrieving attributes", ex);
1347 Node keywordRootNode = typesChildren.findChild(art.getArtifactTypeName());
1348 Children keywordRootChilds = keywordRootNode.getChildren();
1350 String listName = null;
1351 String keywordName = null;
1352 String regex = null;
1353 List<BlackboardAttribute> attributes = art.getAttributes();
1354 for (BlackboardAttribute att : attributes) {
1355 int typeId = att.getAttributeType().getTypeID();
1356 if (typeId == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()) {
1357 listName = att.getValueString();
1358 }
else if (typeId == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID()) {
1359 keywordName = att.getValueString();
1360 }
else if (typeId == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP.getTypeID()) {
1361 regex = att.getValueString();
1364 if (listName == null) {
1365 if (regex == null) {
1366 listName = NbBundle.getMessage(
KeywordHits.class,
"KeywordHits.simpleLiteralSearch.text");
1368 listName = NbBundle.getMessage(
KeywordHits.class,
"KeywordHits.singleRegexSearch.text");
1371 Node listNode = keywordRootChilds.findChild(listName);
1372 if (listNode == null) {
1375 Children listChildren = listNode.getChildren();
1376 if (listChildren == null) {
1379 if (regex != null) {
1380 Node regexNode = listChildren.findChild(listName);
1381 regexNode = (regexNode == null) ? listChildren.findChild(listName +
"_" + regex) : regexNode;
1382 if (regexNode == null) {
1385 listChildren = regexNode.getChildren();
1386 if (listChildren == null) {
1391 return listChildren.findChild(keywordName);
1392 }
catch (TskCoreException ex) {
1393 LOGGER.log(Level.WARNING,
"Error retrieving attributes", ex);
1410 Node interestingItemsRootNode = typesChildren.findChild(NbBundle
1411 .getMessage(
InterestingHits.class,
"InterestingHits.interestingItems.text"));
1412 Children interestingItemsRootChildren = interestingItemsRootNode.getChildren();
1414 String setName = null;
1415 List<BlackboardAttribute> attributes = art.getAttributes();
1416 for (BlackboardAttribute att : attributes) {
1417 int typeId = att.getAttributeType().getTypeID();
1418 if (typeId == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()) {
1419 setName = att.getValueString();
1422 Node setNode = interestingItemsRootChildren.findChild(setName);
1423 if (setNode == null) {
1427 Children fileArtifactChildren = setNode.getChildren();
1428 Node[] fileArtifactNodes = fileArtifactChildren == null ? null : fileArtifactChildren.getNodes();
1429 if (fileArtifactNodes == null || fileArtifactNodes.length != 2) {
1433 return (art.getArtifactTypeID() == BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT.getTypeID())
1434 ? fileArtifactNodes[0]
1435 : fileArtifactNodes[1];
1436 }
catch (TskCoreException ex) {
1437 LOGGER.log(Level.WARNING,
"Error retrieving attributes", ex);
1450 private Node
getEmailNode(Children typesChildren, BlackboardArtifact art) {
1451 Node emailMsgRootNode = typesChildren.findChild(art.getArtifactTypeName());
1452 Children emailMsgRootChilds = emailMsgRootNode.getChildren();
1453 Map<String, String> parsedPath = null;
1455 List<BlackboardAttribute> attributes = art.getAttributes();
1456 for (BlackboardAttribute att : attributes) {
1457 int typeId = att.getAttributeType().getTypeID();
1458 if (typeId == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH.getTypeID()) {
1463 if (parsedPath == null) {
1466 Node defaultNode = emailMsgRootChilds.findChild(parsedPath.get(NbBundle.getMessage(
EmailExtracted.class,
"EmailExtracted.defaultAcct.text")));
1467 Children defaultChildren = defaultNode.getChildren();
1468 return defaultChildren.findChild(parsedPath.get(NbBundle.getMessage(
EmailExtracted.class,
"EmailExtracted.defaultFolder.text")));
1469 }
catch (TskCoreException ex) {
1470 LOGGER.log(Level.WARNING,
"Error retrieving attributes", ex);
1485 Node accountRootNode = typesChildren.findChild(art.getDisplayName());
1486 Children accountRootChilds = accountRootNode.getChildren();
1487 List<BlackboardAttribute> attributes;
1488 String accountType = null;
1489 String ccNumberName = null;
1491 attributes = art.getAttributes();
1492 for (BlackboardAttribute att : attributes) {
1493 int typeId = att.getAttributeType().getTypeID();
1494 if (typeId == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE.getTypeID()) {
1495 accountType = att.getValueString();
1497 if (typeId == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER.getTypeID()) {
1498 ccNumberName = att.getValueString();
1501 if (accountType == null) {
1505 if (accountType.equals(Account.Type.CREDIT_CARD.getTypeName())) {
1506 return getCreditCardAccountNode(accountRootChilds, ccNumberName);
1508 return accountRootChilds.findChild(accountType);
1510 }
catch (TskCoreException ex) {
1511 LOGGER.log(Level.WARNING,
"Error retrieving attributes", ex);
1527 Node accountNode = accountRootChildren.findChild(Account.Type.CREDIT_CARD.getDisplayName());
1528 if (accountNode == null) {
1531 Children accountChildren = accountNode.getChildren();
1532 if (accountChildren == null) {
1535 Node binNode = accountChildren.findChild(NbBundle.getMessage(
Accounts.class,
"Accounts.ByBINNode.name"));
1536 if (binNode == null) {
1539 Children binChildren = binNode.getChildren();
1540 if (ccNumberName == null) {
1545 String binName = StringUtils.rightPad(ccNumberName, 8,
"0");
1546 binName = binName.substring(0, 8);
1549 bin = Integer.parseInt(binName);
1550 }
catch (NumberFormatException ex) {
1551 LOGGER.log(Level.WARNING,
"Unable to parseInt a BIN for node selection from string binName=" + binName, ex);
1555 if (binInfo != null) {
1556 int startBin = ((
BINRange) binInfo).getBINstart();
1557 int endBin = ((
BINRange) binInfo).getBINend();
1558 if (startBin != endBin) {
1559 binName = Integer.toString(startBin) +
"-" + Integer.toString(endBin).substring(5);
1562 if (binName == null) {
1565 return binChildren.findChild(binName);
1570 NbBundle.getMessage(
this.getClass(),
"DirectoryTreeTopComponent.action.viewArtContent.text"),
static synchronized String getConfigSetting(String moduleName, String settingName)
List< Content > getDataSources()
TopComponent getTopComponent()
Children autopsyTreeChildren
void viewArtifact(final BlackboardArtifact art)
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)
Node getInterestingItemNode(Children typesChildren, BlackboardArtifact art)
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)
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 final String MAIN_SETTINGS
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)
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()
void openViewPreferencesButtonActionPerformed(java.awt.event.ActionEvent evt)
void setNode(Node selectedNode)