19 package org.sleuthkit.autopsy.centralrepository.contentviewer;
21 import java.awt.Component;
22 import java.awt.event.ActionEvent;
23 import java.awt.event.ActionListener;
24 import java.awt.event.ComponentAdapter;
25 import java.awt.event.ComponentEvent;
26 import java.io.BufferedWriter;
28 import java.io.IOException;
29 import java.nio.file.Files;
30 import java.text.DateFormat;
31 import java.text.ParseException;
32 import java.text.SimpleDateFormat;
33 import java.util.ArrayList;
34 import java.util.Calendar;
35 import java.util.Collection;
36 import java.util.HashMap;
37 import java.util.HashSet;
38 import java.util.List;
39 import java.util.Locale;
41 import java.util.Objects;
43 import java.util.logging.Level;
45 import javax.swing.JFileChooser;
46 import javax.swing.JMenuItem;
47 import javax.swing.JOptionPane;
48 import static javax.swing.JOptionPane.DEFAULT_OPTION;
49 import static javax.swing.JOptionPane.PLAIN_MESSAGE;
50 import static javax.swing.JOptionPane.ERROR_MESSAGE;
51 import javax.swing.JPanel;
52 import javax.swing.filechooser.FileNameExtensionFilter;
53 import javax.swing.table.TableModel;
54 import javax.swing.table.TableRowSorter;
55 import org.joda.time.DateTimeZone;
56 import org.joda.time.LocalDateTime;
57 import org.openide.nodes.Node;
58 import org.openide.util.NbBundle.Messages;
59 import org.openide.util.lookup.ServiceProvider;
83 @SuppressWarnings(
"PMD.SingularField")
84 @ServiceProvider(service = DataContentViewer.class, position = 9)
85 @Messages({
"DataContentViewerOtherCases.title=Other Occurrences",
86 "DataContentViewerOtherCases.toolTip=Displays instances of the selected file/artifact from other occurrences.",
87 "DataContentViewerOtherCases.table.noArtifacts=Item has no attributes with which to search.",
88 "DataContentViewerOtherCases.table.noResultsFound=No results found."})
91 private static final long serialVersionUID = -1L;
92 private static final String UUID_PLACEHOLDER_STRING =
"NoCorrelationAttributeInstance";
94 private static final CorrelationCaseWrapper NO_ARTIFACTS_CASE =
new CorrelationCaseWrapper(Bundle.DataContentViewerOtherCases_table_noArtifacts());
95 private static final CorrelationCaseWrapper NO_RESULTS_CASE =
new CorrelationCaseWrapper(Bundle.DataContentViewerOtherCases_table_noResultsFound());
101 private String dataSourceName =
"";
102 private String deviceId =
"";
114 this.dataSourcesTableModel =
new OtherOccurrencesDataSourcesTableModel();
115 this.correlationAttributes =
new ArrayList<>();
116 occurrencePanel =
new OccurrencePanel();
118 customizeComponents();
120 detailsPanelScrollPane.addComponentListener(
new ComponentAdapter() {
122 public void componentResized(ComponentEvent componentEvent) {
124 occurrencePanel.setPreferredSize(
new java.awt.Dimension(detailsPanelScrollPane.getPreferredSize().width, occurrencePanel.getPreferredSize().height));
125 detailsPanelScrollPane.setViewportView(occurrencePanel);
137 static String getPlaceholderUUID() {
138 return UUID_PLACEHOLDER_STRING;
142 ActionListener actList = (ActionEvent e) -> {
143 JMenuItem jmi = (JMenuItem) e.getSource();
144 if (jmi.equals(showCaseDetailsMenuItem)) {
145 showCaseDetails(filesTable.getSelectedRow());
146 }
else if (jmi.equals(exportToCSVMenuItem)) {
150 LOGGER.log(Level.SEVERE,
"Exception while getting open case.", ex);
152 }
else if (jmi.equals(showCommonalityMenuItem)) {
153 showCommonalityDetails();
157 exportToCSVMenuItem.addActionListener(actList);
158 showCaseDetailsMenuItem.addActionListener(actList);
159 showCommonalityMenuItem.addActionListener(actList);
162 TableRowSorter<TableModel> sorter =
new TableRowSorter<>(filesTable.getModel());
163 filesTable.setRowSorter(sorter);
164 casesTable.getSelectionModel().addListSelectionListener((e) -> {
166 updateOnCaseSelection();
169 dataSourcesTable.getSelectionModel().addListSelectionListener((e) -> {
171 updateOnDataSourceSelection();
176 filesTable.getSelectionModel().addListSelectionListener((e) -> {
178 occurrencePanel =
new OccurrencePanel();
179 updateOnFileSelection();
183 casesTable.getRowSorter().toggleSortOrder(0);
184 dataSourcesTable.getRowSorter().toggleSortOrder(0);
185 filesTable.getRowSorter().toggleSortOrder(0);
188 @Messages({
"DataContentViewerOtherCases.correlatedArtifacts.isEmpty=There are no files or artifacts to correlate.",
189 "# {0} - commonality percentage",
190 "# {1} - correlation type",
191 "# {2} - correlation value",
192 "DataContentViewerOtherCases.correlatedArtifacts.byType={0}% of data sources have {2} (type: {1})\n",
193 "DataContentViewerOtherCases.correlatedArtifacts.title=Attribute Frequency",
194 "DataContentViewerOtherCases.correlatedArtifacts.failed=Failed to get frequency details."})
200 if (correlationAttributes.isEmpty()) {
201 JOptionPane.showConfirmDialog(showCommonalityMenuItem,
202 Bundle.DataContentViewerOtherCases_correlatedArtifacts_isEmpty(),
203 Bundle.DataContentViewerOtherCases_correlatedArtifacts_title(),
204 DEFAULT_OPTION, PLAIN_MESSAGE);
206 StringBuilder msg =
new StringBuilder(correlationAttributes.size());
213 msg.append(Bundle.DataContentViewerOtherCases_correlatedArtifacts_byType(percentage,
214 eamArtifact.getCorrelationType().getDisplayName(),
215 eamArtifact.getCorrelationValue()));
217 LOGGER.log(Level.WARNING, String.format(
"Error getting commonality details for artifact with ID: %s.", eamArtifact.getID()), ex);
220 JOptionPane.showConfirmDialog(showCommonalityMenuItem,
222 Bundle.DataContentViewerOtherCases_correlatedArtifacts_title(),
223 DEFAULT_OPTION, PLAIN_MESSAGE);
225 LOGGER.log(Level.SEVERE,
"Error getting commonality details.", ex);
226 JOptionPane.showConfirmDialog(showCommonalityMenuItem,
227 Bundle.DataContentViewerOtherCases_correlatedArtifacts_failed(),
228 Bundle.DataContentViewerOtherCases_correlatedArtifacts_title(),
229 DEFAULT_OPTION, ERROR_MESSAGE);
234 @Messages({
"DataContentViewerOtherCases.caseDetailsDialog.notSelected=No Row Selected",
235 "DataContentViewerOtherCases.caseDetailsDialog.noDetails=No details for this case.",
236 "DataContentViewerOtherCases.caseDetailsDialog.noDetailsReference=No case details for Global reference properties.",
237 "DataContentViewerOtherCases.caseDetailsDialog.noCaseNameError=Error",
238 "DataContentViewerOtherCases.noOpenCase.errMsg=No open case available."})
240 String caseDisplayName = Bundle.DataContentViewerOtherCases_caseDetailsDialog_noCaseNameError();
241 String details = Bundle.DataContentViewerOtherCases_caseDetailsDialog_noDetails();
243 if (-1 != selectedRowViewIdx) {
245 int selectedRowModelIdx = filesTable.convertRowIndexToModel(selectedRowViewIdx);
246 List<OtherOccurrenceNodeData> rowList = filesTableModel.getListOfNodesForFile(selectedRowModelIdx);
247 if (!rowList.isEmpty()) {
248 if (rowList.get(0) instanceof OtherOccurrenceNodeInstanceData) {
249 CorrelationCase eamCasePartial = ((OtherOccurrenceNodeInstanceData) rowList.get(0)).getCorrelationAttributeInstance().getCorrelationCase();
253 if (eamCase != null) {
256 details = Bundle.DataContentViewerOtherCases_caseDetailsDialog_noDetails();
259 details = Bundle.DataContentViewerOtherCases_caseDetailsDialog_notSelected();
262 details = Bundle.DataContentViewerOtherCases_caseDetailsDialog_noDetailsReference();
266 LOGGER.log(Level.SEVERE,
"Error loading case details", ex);
268 JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
271 DEFAULT_OPTION, PLAIN_MESSAGE);
277 Calendar now = Calendar.getInstance();
278 String fileName = String.format(
"%1$tY%1$tm%1$te%1$tI%1$tM%1$tS_other_data_sources.csv", now);
280 CSVFileChooser.setSelectedFile(
new File(fileName));
281 CSVFileChooser.setFileFilter(
new FileNameExtensionFilter(
"csv file",
"csv"));
283 int returnVal = CSVFileChooser.showSaveDialog(filesTable);
284 if (returnVal == JFileChooser.APPROVE_OPTION) {
286 File selectedFile = CSVFileChooser.getSelectedFile();
287 if (!selectedFile.getName().endsWith(
".csv")) {
288 selectedFile =
new File(selectedFile.toString() +
".csv");
290 writeOtherOccurrencesToFileAsCSV(selectedFile);
296 "DataContentViewerOtherCasesModel.csvHeader.case=Case",
297 "DataContentViewerOtherCasesModel.csvHeader.device=Device",
298 "DataContentViewerOtherCasesModel.csvHeader.dataSource=Data Source",
299 "DataContentViewerOtherCasesModel.csvHeader.attribute=Matched Attribute",
300 "DataContentViewerOtherCasesModel.csvHeader.value=Attribute Value",
301 "DataContentViewerOtherCasesModel.csvHeader.known=Known",
302 "DataContentViewerOtherCasesModel.csvHeader.path=Path",
303 "DataContentViewerOtherCasesModel.csvHeader.comment=Comment"
309 try (BufferedWriter writer = Files.newBufferedWriter(destFile.toPath())) {
311 StringBuilder headers =
new StringBuilder(
"\"");
312 headers.append(Bundle.DataContentViewerOtherCasesModel_csvHeader_case())
313 .append(OtherOccurrenceNodeInstanceData.getCsvItemSeparator()).append(Bundle.DataContentViewerOtherCasesModel_csvHeader_dataSource())
314 .append(OtherOccurrenceNodeInstanceData.getCsvItemSeparator()).append(Bundle.DataContentViewerOtherCasesModel_csvHeader_attribute())
315 .append(OtherOccurrenceNodeInstanceData.getCsvItemSeparator()).append(Bundle.DataContentViewerOtherCasesModel_csvHeader_value())
316 .append(OtherOccurrenceNodeInstanceData.getCsvItemSeparator()).append(Bundle.DataContentViewerOtherCasesModel_csvHeader_known())
317 .append(OtherOccurrenceNodeInstanceData.getCsvItemSeparator()).append(Bundle.DataContentViewerOtherCasesModel_csvHeader_path())
318 .append(OtherOccurrenceNodeInstanceData.getCsvItemSeparator()).append(Bundle.DataContentViewerOtherCasesModel_csvHeader_comment())
319 .append(
'"').append(System.getProperty(
"line.separator"));
320 writer.write(headers.toString());
323 Map<UniquePathKey, OtherOccurrenceNodeInstanceData> correlatedNodeDataMap =
new HashMap<>(0);
325 correlatedNodeDataMap.putAll(getCorrelatedInstances(corAttr, dataSourceName, deviceId));
326 for (OtherOccurrenceNodeInstanceData nodeData : correlatedNodeDataMap.values()) {
327 writer.write(nodeData.toCsvString());
330 }
catch (IOException ex) {
331 LOGGER.log(Level.SEVERE,
"Error writing selected rows to CSV.", ex);
340 casesTableModel.clearTable();
341 dataSourcesTableModel.clearTable();
342 filesTableModel.clearTable();
343 correlationAttributes.clear();
344 earliestCaseDate.setText(Bundle.DataContentViewerOtherCases_earliestCaseNotAvailable());
345 foundInLabel.setText(
"");
347 occurrencePanel =
new OccurrencePanel();
348 occurrencePanel.getPreferredSize();
349 detailsPanelScrollPane.setViewportView(occurrencePanel);
354 return Bundle.DataContentViewerOtherCases_title();
359 return Bundle.DataContentViewerOtherCases_toolTip();
390 private BlackboardArtifact
392 BlackboardArtifactTag nodeBbArtifactTag = node.getLookup().lookup(BlackboardArtifactTag.class
394 BlackboardArtifact nodeBbArtifact = node.getLookup().lookup(BlackboardArtifact.class
397 if (nodeBbArtifactTag != null) {
398 return nodeBbArtifactTag.getArtifact();
399 }
else if (nodeBbArtifact != null) {
400 return nodeBbArtifact;
415 BlackboardArtifactTag nodeBbArtifactTag = node.getLookup().lookup(BlackboardArtifactTag.class
417 ContentTag nodeContentTag = node.getLookup().lookup(ContentTag.class
419 BlackboardArtifact nodeBbArtifact = node.getLookup().lookup(BlackboardArtifact.class
421 AbstractFile nodeAbstractFile = node.getLookup().lookup(AbstractFile.class
424 if (nodeBbArtifactTag != null) {
425 Content content = nodeBbArtifactTag.getContent();
426 if (content instanceof AbstractFile) {
427 return (AbstractFile) content;
429 }
else if (nodeContentTag != null) {
430 Content content = nodeContentTag.getContent();
431 if (content instanceof AbstractFile) {
432 return (AbstractFile) content;
434 }
else if (nodeBbArtifact != null) {
437 content = nodeBbArtifact.getSleuthkitCase().getContentById(nodeBbArtifact.getObjectID());
438 }
catch (TskCoreException ex) {
439 LOGGER.log(Level.SEVERE,
"Error retrieving blackboard artifact", ex);
443 if (content instanceof AbstractFile) {
444 return (AbstractFile) content;
446 }
else if (nodeAbstractFile != null) {
447 return nodeAbstractFile;
462 Collection<CorrelationAttributeInstance> ret =
new ArrayList<>();
465 BlackboardArtifact bbArtifact = getBlackboardArtifactFromNode(node);
475 String md5 = this.file.getMd5Hash();
476 if (md5 != null && !md5.isEmpty() && null != artifactTypes && !artifactTypes.isEmpty()) {
486 file.getParentPath() + file.
getName(),
491 LOGGER.log(Level.INFO, String.format(
"Unable to check create CorrelationAttribtueInstance for value %s and type %s.", md5, aType.toString()), ex);
498 LOGGER.log(Level.SEVERE,
"Error connecting to DB", ex);
501 }
else if (this.file != null && this.file.getSize() > 0) {
502 String md5 = this.file.getMd5Hash();
503 if (md5 != null && !md5.isEmpty()) {
514 LOGGER.log(Level.SEVERE,
"Error connecting to DB", ex);
516 LOGGER.log(Level.INFO, String.format(
"Unable to create CorrelationAttributeInstance for value %s", md5), ex);
524 @Messages({
"DataContentViewerOtherCases.earliestCaseNotAvailable= Not Enabled."})
530 String dateStringDisplay = Bundle.DataContentViewerOtherCases_earliestCaseNotAvailable();
533 LocalDateTime earliestDate = LocalDateTime.now(DateTimeZone.UTC);
534 DateFormat datetimeFormat =
new SimpleDateFormat(
"yyyy/MM/dd HH:mm:ss", Locale.US);
537 List<CorrelationCase> cases = dbManager.
getCases();
539 LocalDateTime caseDate = LocalDateTime.fromDateFields(datetimeFormat.parse(aCase.getCreationDate()));
541 if (caseDate.isBefore(earliestDate)) {
542 earliestDate = caseDate;
543 dateStringDisplay = aCase.getCreationDate();
549 LOGGER.log(Level.SEVERE,
"Error getting list of cases from database.", ex);
550 }
catch (ParseException ex) {
551 LOGGER.log(Level.SEVERE,
"Error parsing date of cases from database.", ex);
555 earliestCaseDate.setText(dateStringDisplay);
574 String caseUUID = openCase.
getName();
575 HashMap<UniquePathKey, OtherOccurrenceNodeInstanceData> nodeDataMap =
new HashMap<>();
588 if (!artifactInstance.getCorrelationCase().getCaseUUID().equals(caseUUID)
589 || !artifactInstance.getCorrelationDataSource().getName().equals(dataSourceName)
590 || !artifactInstance.getCorrelationDataSource().getDeviceID().equals(deviceId)
591 || !artifactInstance.getFilePath().equalsIgnoreCase(file.getParentPath() + file.getName())) {
595 nodeDataMap.put(uniquePathKey, newNode);
600 List<AbstractFile> caseDbFiles = getCaseDbMatches(corAttr, openCase);
602 for (AbstractFile caseDbFile : caseDbFiles) {
603 addOrUpdateNodeData(openCase, nodeDataMap, caseDbFile);
608 LOGGER.log(Level.SEVERE,
"Error getting artifact instances from database.", ex);
610 LOGGER.log(Level.INFO,
"Error getting artifact instances from database.", ex);
612 LOGGER.log(Level.SEVERE,
"Exception while getting open case.", ex);
613 }
catch (TskCoreException ex) {
616 LOGGER.log(Level.SEVERE,
"Exception while querying open case.", ex);
619 return new HashMap<>(0);
636 String md5 = corAttr.getCorrelationValue();
637 SleuthkitCase tsk = openCase.getSleuthkitCase();
638 List<AbstractFile> matches = tsk.findAllFilesWhere(String.format(
"md5 = '%s'",
new Object[]{md5}));
640 List<AbstractFile> caseDbArtifactInstances =
new ArrayList<>();
641 for (AbstractFile fileMatch : matches) {
642 if (this.file.equals(fileMatch)) {
645 caseDbArtifactInstances.add(fileMatch);
647 return caseDbArtifactInstances;
663 OtherOccurrenceNodeInstanceData newNode =
new OtherOccurrenceNodeInstanceData(newFile, autopsyCase);
667 if (newNode.getKnown() != TskData.FileKnown.BAD) {
668 List<ContentTag> fileMatchTags = autopsyCase.getServices().getTagsManager().getContentTagsByContent(newFile);
669 for (ContentTag tag : fileMatchTags) {
670 TskData.FileKnown tagKnownStatus = tag.getName().getKnownStatus();
671 if (tagKnownStatus.equals(TskData.FileKnown.BAD)) {
672 newNode.updateKnown(TskData.FileKnown.BAD);
684 if (nodeDataMap.containsKey(uniquePathKey)) {
685 if (newNode.getKnown() == TskData.FileKnown.BAD) {
686 OtherOccurrenceNodeInstanceData prevInstance = nodeDataMap.get(uniquePathKey);
687 prevInstance.updateKnown(newNode.getKnown());
690 nodeDataMap.put(uniquePathKey, newNode);
701 this.file = this.getAbstractFileFromNode(node);
703 return !getCorrelationAttributesFromNode(node).isEmpty();
705 return this.file != null
706 && this.file.getSize() > 0
707 && ((this.file.getMd5Hash() != null) && (!this.file.getMd5Hash().isEmpty()));
719 this.file = this.getAbstractFileFromNode(node);
731 "DataContentViewerOtherCases.dataSources.header.text=Data Source Name",
732 "DataContentViewerOtherCases.foundIn.text=Found %d instances in %d cases and %d data sources."
736 if (this.file != null) {
737 Content dataSource = this.file.getDataSource();
738 dataSourceName = dataSource.getName();
741 }
catch (TskException | NoCurrentCaseException ex) {
747 correlationAttributes.addAll(getCorrelationAttributesFromNode(node));
748 Map<String, CorrelationCase> caseNames =
new HashMap<>();
750 Set<String> dataSources =
new HashSet<>();
752 Map<UniquePathKey, OtherOccurrenceNodeInstanceData> correlatedNodeDataMap =
new HashMap<>(0);
755 correlatedNodeDataMap.putAll(getCorrelatedInstances(corAttr, dataSourceName, deviceId));
756 for (OtherOccurrenceNodeInstanceData nodeData : correlatedNodeDataMap.values()) {
757 if (nodeData.isCentralRepoNode()) {
759 dataSources.add(makeDataSourceString(nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID(), nodeData.getDeviceID(), nodeData.getDataSourceName()));
760 caseNames.put(nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID(), nodeData.getCorrelationAttributeInstance().getCorrelationCase());
762 LOGGER.log(Level.WARNING,
"Unable to get correlation case for displaying other occurrence for case: " + nodeData.getCaseName(), ex);
768 }
catch (NoCurrentCaseException ex) {
769 LOGGER.log(Level.WARNING,
"No current case open for other occurrences", ex);
776 casesTableModel.addCorrelationCase(
new CorrelationCaseWrapper(corCase));
779 if (correlationAttributes.isEmpty()) {
780 casesTableModel.addCorrelationCase(NO_ARTIFACTS_CASE);
781 }
else if (caseCount == 0) {
782 casesTableModel.addCorrelationCase(NO_RESULTS_CASE);
784 setEarliestCaseDate();
785 foundInLabel.setText(String.format(Bundle.DataContentViewerOtherCases_foundIn_text(), totalCount, caseCount, dataSources.size()));
787 casesTable.setRowSelectionInterval(0, 0);
796 return caseUUID + deviceId + dataSourceName;
803 int[] selectedCaseIndexes = casesTable.getSelectedRows();
804 dataSourcesTableModel.clearTable();
805 filesTableModel.clearTable();
807 if (selectedCaseIndexes.length == 0) {
809 occurrencePanel =
new OccurrencePanel();
810 occurrencePanel.getPreferredSize();
811 detailsPanelScrollPane.setViewportView(occurrencePanel);
813 String currentCaseName;
816 }
catch (NoCurrentCaseException ex) {
817 currentCaseName = null;
818 LOGGER.log(Level.WARNING,
"Unable to get current case for other occurrences content viewer", ex);
821 Map<UniquePathKey, OtherOccurrenceNodeInstanceData> correlatedNodeDataMap =
new HashMap<>(0);
824 correlatedNodeDataMap.putAll(getCorrelatedInstances(corAttr, dataSourceName, deviceId));
825 for (OtherOccurrenceNodeInstanceData nodeData : correlatedNodeDataMap.values()) {
826 for (
int selectedRow : selectedCaseIndexes) {
828 if (nodeData.isCentralRepoNode()) {
829 if (casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(selectedRow)) != null
830 && casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(selectedRow)).getCaseUUID().equals(nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID())) {
831 dataSourcesTableModel.addNodeData(nodeData);
833 }
else if (currentCaseName != null && (casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(selectedRow)).getCaseUUID().equals(currentCaseName))) {
834 dataSourcesTableModel.addNodeData(nodeData);
837 LOGGER.log(Level.WARNING,
"Unable to get correlation attribute instance from OtherOccurrenceNodeInstanceData for case " + nodeData.getCaseName(), ex);
842 if (dataSourcesTable.getRowCount() > 0) {
843 dataSourcesTable.setRowSelectionInterval(0, 0);
853 int[] selectedDataSources = dataSourcesTable.getSelectedRows();
854 filesTableModel.clearTable();
856 Map<UniquePathKey, OtherOccurrenceNodeInstanceData> correlatedNodeDataMap =
new HashMap<>(0);
859 correlatedNodeDataMap.putAll(getCorrelatedInstances(corAttr, dataSourceName, deviceId));
860 for (OtherOccurrenceNodeInstanceData nodeData : correlatedNodeDataMap.values()) {
861 for (
int selectedDataSourceRow : selectedDataSources) {
863 if (nodeData.isCentralRepoNode()) {
864 if (dataSourcesTableModel.getCaseUUIDForRow(dataSourcesTable.convertRowIndexToModel(selectedDataSourceRow)).equals(nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID())
865 && dataSourcesTableModel.getDeviceIdForRow(dataSourcesTable.convertRowIndexToModel(selectedDataSourceRow)).equals(nodeData.getDeviceID())) {
866 filesTableModel.addNodeData(nodeData);
869 if (dataSourcesTableModel.getDeviceIdForRow(dataSourcesTable.convertRowIndexToModel(selectedDataSourceRow)).equals(nodeData.getDeviceID())) {
870 filesTableModel.addNodeData(nodeData);
874 LOGGER.log(Level.WARNING,
"Unable to get correlation attribute instance from OtherOccurrenceNodeInstanceData for case " + nodeData.getCaseName(), ex);
879 if (filesTable.getRowCount() > 0) {
880 filesTable.setRowSelectionInterval(0, 0);
889 if (filesTable.getSelectedRowCount() == 1) {
891 occurrencePanel =
new OccurrencePanel(filesTableModel.getListOfNodesForFile(filesTable.convertRowIndexToModel(filesTable.getSelectedRow())));
892 }
else if (dataSourcesTable.getSelectedRowCount() == 1) {
894 String caseName = dataSourcesTableModel.getCaseNameForRow(dataSourcesTable.convertRowIndexToModel(dataSourcesTable.getSelectedRow()));
895 String dsName = dataSourcesTableModel.getValueAt(dataSourcesTable.convertRowIndexToModel(dataSourcesTable.getSelectedRow()), 0).toString();
896 String caseCreatedDate =
"";
897 for (
int row : casesTable.getSelectedRows()) {
898 if (casesTableModel.
getValueAt(casesTable.convertRowIndexToModel(row), 0).toString().equals(caseName)) {
899 caseCreatedDate = getCaseCreatedDate(row);
903 occurrencePanel =
new OccurrencePanel(caseName, caseCreatedDate, dsName);
904 }
else if (casesTable.getSelectedRowCount() == 1) {
907 String createdDate =
"";
908 String caseName =
"";
909 if (casesTable.getRowCount() > 0) {
910 caseName = casesTableModel.
getValueAt(casesTable.convertRowIndexToModel(casesTable.getSelectedRow()), 0).toString();
912 if (caseName.isEmpty()) {
913 occurrencePanel =
new OccurrencePanel();
915 createdDate = getCaseCreatedDate(casesTable.getSelectedRow());
916 occurrencePanel =
new OccurrencePanel(caseName, createdDate);
920 occurrencePanel =
new OccurrencePanel();
923 occurrencePanel.getPreferredSize();
924 detailsPanelScrollPane.setViewportView(occurrencePanel);
939 partialCase = casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(caseTableRowIdx));
940 if (partialCase == null) {
948 LOGGER.log(Level.WARNING,
"Error getting case created date for row: " + caseTableRowIdx, ex);
958 @SuppressWarnings(
"unchecked")
960 private
void initComponents() {
962 rightClickPopupMenu =
new javax.swing.JPopupMenu();
963 exportToCSVMenuItem =
new javax.swing.JMenuItem();
964 showCaseDetailsMenuItem =
new javax.swing.JMenuItem();
965 showCommonalityMenuItem =
new javax.swing.JMenuItem();
966 CSVFileChooser =
new javax.swing.JFileChooser();
967 tableContainerPanel =
new javax.swing.JPanel();
968 earliestCaseLabel =
new javax.swing.JLabel();
969 earliestCaseDate =
new javax.swing.JLabel();
970 foundInLabel =
new javax.swing.JLabel();
971 tablesViewerSplitPane =
new javax.swing.JSplitPane();
972 caseDatasourceFileSplitPane =
new javax.swing.JSplitPane();
973 caseDatasourceSplitPane =
new javax.swing.JSplitPane();
974 caseScrollPane =
new javax.swing.JScrollPane();
975 casesTable =
new javax.swing.JTable();
976 dataSourceScrollPane =
new javax.swing.JScrollPane();
977 dataSourcesTable =
new javax.swing.JTable();
978 filesTableScrollPane =
new javax.swing.JScrollPane();
979 filesTable =
new javax.swing.JTable();
980 detailsPanelScrollPane =
new javax.swing.JScrollPane();
982 rightClickPopupMenu.addPopupMenuListener(
new javax.swing.event.PopupMenuListener() {
983 public void popupMenuCanceled(javax.swing.event.PopupMenuEvent evt) {
985 public void popupMenuWillBecomeInvisible(javax.swing.event.PopupMenuEvent evt) {
987 public void popupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent evt) {
988 rightClickPopupMenuPopupMenuWillBecomeVisible(evt);
992 org.openide.awt.Mnemonics.setLocalizedText(exportToCSVMenuItem,
org.openide.util.NbBundle.getMessage(
DataContentViewerOtherCases.class,
"DataContentViewerOtherCases.exportToCSVMenuItem.text"));
993 rightClickPopupMenu.add(exportToCSVMenuItem);
995 org.openide.awt.Mnemonics.setLocalizedText(showCaseDetailsMenuItem,
org.openide.util.NbBundle.getMessage(
DataContentViewerOtherCases.class,
"DataContentViewerOtherCases.showCaseDetailsMenuItem.text"));
996 rightClickPopupMenu.add(showCaseDetailsMenuItem);
998 org.openide.awt.Mnemonics.setLocalizedText(showCommonalityMenuItem,
org.openide.util.NbBundle.getMessage(
DataContentViewerOtherCases.class,
"DataContentViewerOtherCases.showCommonalityMenuItem.text"));
999 rightClickPopupMenu.add(showCommonalityMenuItem);
1001 setMinimumSize(
new java.awt.Dimension(1000, 10));
1003 setPreferredSize(
new java.awt.Dimension(1000, 63));
1005 tableContainerPanel.setPreferredSize(
new java.awt.Dimension(600, 63));
1006 tableContainerPanel.setRequestFocusEnabled(
false);
1008 org.openide.awt.Mnemonics.setLocalizedText(earliestCaseLabel,
org.openide.util.NbBundle.getMessage(
DataContentViewerOtherCases.class,
"DataContentViewerOtherCases.earliestCaseLabel.text"));
1009 earliestCaseLabel.setToolTipText(
org.openide.util.NbBundle.getMessage(
DataContentViewerOtherCases.class,
"DataContentViewerOtherCases.earliestCaseLabel.toolTipText"));
1011 org.openide.awt.Mnemonics.setLocalizedText(earliestCaseDate,
org.openide.util.NbBundle.getMessage(
DataContentViewerOtherCases.class,
"DataContentViewerOtherCases.earliestCaseDate.text"));
1013 org.openide.awt.Mnemonics.setLocalizedText(foundInLabel,
org.openide.util.NbBundle.getMessage(
DataContentViewerOtherCases.class,
"DataContentViewerOtherCases.foundInLabel.text"));
1015 tablesViewerSplitPane.setDividerLocation(450);
1016 tablesViewerSplitPane.setResizeWeight(0.75);
1018 caseDatasourceFileSplitPane.setDividerLocation(300);
1019 caseDatasourceFileSplitPane.setResizeWeight(0.66);
1020 caseDatasourceFileSplitPane.setToolTipText(
"");
1022 caseDatasourceSplitPane.setDividerLocation(150);
1023 caseDatasourceSplitPane.setResizeWeight(0.5);
1025 caseScrollPane.setPreferredSize(
new java.awt.Dimension(150, 30));
1027 casesTable.setAutoCreateRowSorter(
true);
1028 casesTable.setModel(casesTableModel);
1029 caseScrollPane.setViewportView(casesTable);
1031 caseDatasourceSplitPane.setLeftComponent(caseScrollPane);
1033 dataSourceScrollPane.setPreferredSize(
new java.awt.Dimension(150, 30));
1035 dataSourcesTable.setAutoCreateRowSorter(
true);
1036 dataSourcesTable.setModel(dataSourcesTableModel);
1037 dataSourceScrollPane.setViewportView(dataSourcesTable);
1039 caseDatasourceSplitPane.setRightComponent(dataSourceScrollPane);
1041 caseDatasourceFileSplitPane.setLeftComponent(caseDatasourceSplitPane);
1043 filesTableScrollPane.setPreferredSize(
new java.awt.Dimension(150, 30));
1045 filesTable.setAutoCreateRowSorter(
true);
1046 filesTable.setModel(filesTableModel);
1047 filesTable.setToolTipText(
org.openide.util.NbBundle.getMessage(
DataContentViewerOtherCases.class,
"DataContentViewerOtherCases.table.toolTip.text"));
1048 filesTable.setComponentPopupMenu(rightClickPopupMenu);
1049 filesTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
1050 filesTableScrollPane.setViewportView(filesTable);
1052 caseDatasourceFileSplitPane.setRightComponent(filesTableScrollPane);
1054 tablesViewerSplitPane.setLeftComponent(caseDatasourceFileSplitPane);
1056 detailsPanelScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
1057 detailsPanelScrollPane.setPreferredSize(
new java.awt.Dimension(300, 100));
1058 tablesViewerSplitPane.setRightComponent(detailsPanelScrollPane);
1060 javax.swing.GroupLayout tableContainerPanelLayout =
new javax.swing.GroupLayout(tableContainerPanel);
1061 tableContainerPanel.setLayout(tableContainerPanelLayout);
1062 tableContainerPanelLayout.setHorizontalGroup(
1063 tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
1064 .addGroup(tableContainerPanelLayout.createSequentialGroup()
1065 .addGroup(tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
1066 .addGroup(tableContainerPanelLayout.createSequentialGroup()
1067 .addComponent(earliestCaseLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 161, javax.swing.GroupLayout.PREFERRED_SIZE)
1068 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
1069 .addComponent(earliestCaseDate, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
1070 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
1071 .addComponent(foundInLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
1072 .addComponent(tablesViewerSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 990, Short.MAX_VALUE))
1075 tableContainerPanelLayout.setVerticalGroup(
1076 tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
1077 .addGroup(tableContainerPanelLayout.createSequentialGroup()
1079 .addComponent(tablesViewerSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 33, Short.MAX_VALUE)
1080 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
1081 .addGroup(tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
1082 .addGroup(tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
1083 .addComponent(earliestCaseLabel)
1084 .addComponent(earliestCaseDate))
1085 .addComponent(foundInLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE))
1089 javax.swing.GroupLayout layout =
new javax.swing.GroupLayout(
this);
1090 this.setLayout(layout);
1091 layout.setHorizontalGroup(
1092 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
1093 .addComponent(tableContainerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 1000, Short.MAX_VALUE)
1095 layout.setVerticalGroup(
1096 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
1097 .addGroup(layout.createSequentialGroup()
1098 .addComponent(tableContainerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 64, Short.MAX_VALUE)
1104 boolean enableCentralRepoActions =
false;
1106 int rowIndex = filesTable.getSelectedRow();
1107 List<OtherOccurrenceNodeData> selectedFile = filesTableModel.getListOfNodesForFile(rowIndex);
1108 if (!selectedFile.isEmpty() && selectedFile.get(0) instanceof OtherOccurrenceNodeInstanceData) {
1109 OtherOccurrenceNodeInstanceData instanceData = (OtherOccurrenceNodeInstanceData) selectedFile.get(0);
1110 enableCentralRepoActions = instanceData.isCentralRepoNode();
1113 showCaseDetailsMenuItem.setVisible(enableCentralRepoActions);
1114 showCommonalityMenuItem.setVisible(enableCentralRepoActions);
1152 dataSourceID = nodeData.getDeviceID();
1153 if (nodeData.getFilePath() != null) {
1154 filePath = nodeData.getFilePath().toLowerCase();
1158 type = nodeData.getType();
1159 String tempCaseUUID;
1161 tempCaseUUID = nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID();
1167 }
catch (NoCurrentCaseException ex) {
1168 LOGGER.log(Level.WARNING,
"Unable to get current case", ex);
1169 tempCaseUUID = UUID_PLACEHOLDER_STRING;
1172 caseUUID = tempCaseUUID;
1178 UniquePathKey otherKey = (UniquePathKey) (other);
1179 return (Objects.equals(otherKey.getDataSourceID(), this.getDataSourceID())
1180 && Objects.equals(otherKey.getFilePath(), this.getFilePath())
1181 && Objects.equals(otherKey.getType(), this.getType())
1182 && Objects.equals(otherKey.getCaseUUID(), this.getCaseUUID()));
1189 return Objects.hash(getDataSourceID(), getFilePath(), getType(), getCaseUUID());
1206 String getFilePath() {
1215 String getDataSourceID() {
1216 return dataSourceID;
1224 String getCaseUUID() {
Object getValueAt(int rowIdx, int colIdx)
final Collection< CorrelationAttributeInstance > correlationAttributes
void updateOnFileSelection()
void rightClickPopupMenuPopupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent evt)
final OtherOccurrencesFilesTableModel filesTableModel
boolean equals(Object other)
List< CorrelationCase > getCases()
String makeDataSourceString(String caseUUID, String deviceId, String dataSourceName)
int isPreferred(Node node)
javax.swing.JLabel earliestCaseLabel
javax.swing.JMenuItem showCommonalityMenuItem
void updateOnDataSourceSelection()
List< CorrelationAttributeInstance > getArtifactInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String value)
static CorrelationDataSource fromTSKDataSource(CorrelationCase correlationCase, Content dataSource)
javax.swing.JPanel tableContainerPanel
void setEarliestCaseDate()
javax.swing.JSplitPane caseDatasourceFileSplitPane
AbstractFile getAbstractFileFromNode(Node node)
CorrelationCase getCase(Case autopsyCase)
static List< CorrelationAttributeInstance.Type > getDefaultCorrelationTypes()
CorrelationCase getCaseByUUID(String caseUUID)
javax.swing.JTable dataSourcesTable
Collection< CorrelationAttributeInstance > getCorrelationAttributesFromNode(Node node)
String getCorrelationValue()
final String dataSourceID
javax.swing.JScrollPane detailsPanelScrollPane
javax.swing.JSplitPane tablesViewerSplitPane
javax.swing.JScrollPane filesTableScrollPane
void writeOtherOccurrencesToFileAsCSV(File destFile)
List< CorrelationAttributeInstance.Type > getDefinedCorrelationTypes()
static List< CorrelationAttributeInstance > makeCorrAttrsForCorrelation(BlackboardArtifact artifact)
Type getCorrelationType()
void populateTable(Node node)
javax.swing.JPopupMenu rightClickPopupMenu
javax.swing.JSplitPane caseDatasourceSplitPane
javax.swing.JScrollPane dataSourceScrollPane
javax.swing.JScrollPane caseScrollPane
BlackboardArtifact getBlackboardArtifactFromNode(Node node)
void updateOnCaseSelection()
boolean isSupported(Node node)
String getCaseDetailsOptionsPaneDialog()
void showCaseDetails(int selectedRowViewIdx)
javax.swing.JMenuItem exportToCSVMenuItem
SleuthkitCase getSleuthkitCase()
void addOrUpdateNodeData(final Case autopsyCase, Map< UniquePathKey, OtherOccurrenceNodeInstanceData > nodeDataMap, AbstractFile newFile)
void showCommonalityDetails()
OccurrencePanel occurrencePanel
DataContentViewerOtherCases()
int getFrequencyPercentage(CorrelationAttributeInstance corAttr)
javax.swing.JFileChooser CSVFileChooser
javax.swing.JLabel earliestCaseDate
static Case getCurrentCase()
synchronized static Logger getLogger(String name)
final OtherOccurrencesCasesTableModel casesTableModel
static Case getCurrentCaseThrows()
javax.swing.JLabel foundInLabel
String getExportDirectory()
javax.swing.JTable filesTable
DataContentViewer createInstance()
void customizeComponents()
List< AbstractFile > getCaseDbMatches(CorrelationAttributeInstance corAttr, Case openCase)
Map< UniquePathKey, OtherOccurrenceNodeInstanceData > getCorrelatedInstances(CorrelationAttributeInstance corAttr, String dataSourceName, String deviceId)
String getCaseCreatedDate(int caseTableRowIdx)
static CentralRepository getInstance()
static boolean isCaseOpen()
javax.swing.JTable casesTable
final OtherOccurrencesDataSourcesTableModel dataSourcesTableModel
static final int FILES_TYPE_ID
javax.swing.JMenuItem showCaseDetailsMenuItem
static boolean isEnabled()