From 1dc55ba7e8b65a3c86cbdcc6ac5e20dcbe9117f0 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Fri, 6 Jul 2018 10:59:38 -0400 Subject: [PATCH 01/21] Implemented message node to handle 'No results found' message. --- .../DataContentViewerOtherCases.form | 4 +- .../DataContentViewerOtherCases.java | 33 +-- ...DataContentViewerOtherCasesTableModel.java | 46 ++-- .../OtherOccurrenceNodeData.java | 213 +--------------- .../OtherOccurrenceNodeInstanceData.java | 233 ++++++++++++++++++ .../OtherOccurrenceNodeMessageData.java | 34 +++ 6 files changed, 319 insertions(+), 244 deletions(-) mode change 100644 => 100755 Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/OtherOccurrenceNodeData.java create mode 100644 Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/OtherOccurrenceNodeInstanceData.java create mode 100755 Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/OtherOccurrenceNodeMessageData.java diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.form b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.form index 60667bae46..7b9e47c236 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.form +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.form @@ -80,7 +80,7 @@ - + @@ -106,7 +106,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java index 8ead475d95..c3558a106b 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java @@ -126,7 +126,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi showCommonalityDetails(); } else if (jmi.equals(addCommentMenuItem)) { try { - OtherOccurrenceNodeData selectedNode = (OtherOccurrenceNodeData) tableModel.getRow(otherCasesTable.getSelectedRow()); + OtherOccurrenceNodeInstanceData selectedNode = (OtherOccurrenceNodeInstanceData) tableModel.getRow(otherCasesTable.getSelectedRow()); AddEditCentralRepoCommentAction action = AddEditCentralRepoCommentAction.createAddEditCommentAction(selectedNode.createCorrelationAttribute()); String currentComment = action.addEditCentralRepoComment(); selectedNode.updateComment(currentComment); @@ -205,7 +205,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi if (-1 != selectedRowViewIdx) { EamDb dbManager = EamDb.getInstance(); int selectedRowModelIdx = otherCasesTable.convertRowIndexToModel(selectedRowViewIdx); - OtherOccurrenceNodeData nodeData = (OtherOccurrenceNodeData) tableModel.getRow(selectedRowModelIdx); + OtherOccurrenceNodeInstanceData nodeData = (OtherOccurrenceNodeInstanceData) tableModel.getRow(selectedRowModelIdx); CorrelationCase eamCasePartial = nodeData.getCorrelationAttributeInstance().getCorrelationCase(); if (eamCasePartial == null) { JOptionPane.showConfirmDialog(showCaseDetailsMenuItem, @@ -504,13 +504,13 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi * * @return A collection of correlated artifact instances */ - private Map getCorrelatedInstances(CorrelationAttribute corAttr, String dataSourceName, String deviceId) { + private Map getCorrelatedInstances(CorrelationAttribute corAttr, String dataSourceName, String deviceId) { // @@@ Check exception try { final Case openCase = Case.getCurrentCase(); String caseUUID = openCase.getName(); - HashMap nodeDataMap = new HashMap<>(); + HashMap nodeDataMap = new HashMap<>(); if (EamDb.isEnabled()) { List instances = EamDb.getInstance().getArtifactInstancesByTypeValue(corAttr.getCorrelationType(), corAttr.getCorrelationValue()); @@ -528,7 +528,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi || !artifactInstance.getCorrelationDataSource().getDeviceID().equals(deviceId) || !artifactInstance.getFilePath().equalsIgnoreCase(file.getParentPath() + file.getName())) { - OtherOccurrenceNodeData newNode = new OtherOccurrenceNodeData(artifactInstance, corAttr.getCorrelationType(), corAttr.getCorrelationValue()); + OtherOccurrenceNodeInstanceData newNode = new OtherOccurrenceNodeInstanceData(artifactInstance, corAttr.getCorrelationType(), corAttr.getCorrelationValue()); UniquePathKey uniquePathKey = new UniquePathKey(newNode); nodeDataMap.put(uniquePathKey, newNode); } @@ -592,9 +592,9 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi * @throws TskCoreException * @throws EamDbException */ - private void addOrUpdateNodeData(final Case autopsyCase, Map nodeDataMap, AbstractFile newFile) throws TskCoreException, EamDbException { + private void addOrUpdateNodeData(final Case autopsyCase, Map nodeDataMap, AbstractFile newFile) throws TskCoreException, EamDbException { - OtherOccurrenceNodeData newNode = new OtherOccurrenceNodeData(newFile, autopsyCase); + OtherOccurrenceNodeInstanceData newNode = new OtherOccurrenceNodeInstanceData(newFile, autopsyCase); // If the caseDB object has a notable tag associated with it, update // the known status to BAD @@ -617,7 +617,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi // Otherwise this is a new node so add the new node to the map. if (nodeDataMap.containsKey(uniquePathKey)) { if (newNode.getKnown() == TskData.FileKnown.BAD) { - OtherOccurrenceNodeData prevInstance = nodeDataMap.get(uniquePathKey); + OtherOccurrenceNodeInstanceData prevInstance = nodeDataMap.get(uniquePathKey); prevInstance.updateKnown(newNode.getKnown()); } } else { @@ -663,8 +663,10 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi * * @param node The node being viewed. */ - @Messages({"DataContentViewerOtherCases.table.isempty=There are no associated artifacts or files from other occurrences to display.", - "DataContentViewerOtherCases.table.noArtifacts=Correlation cannot be performed on the selected file."}) + @Messages({ + "DataContentViewerOtherCases.table.noResultsFound=No results found.", + "DataContentViewerOtherCases.table.noArtifacts=Correlation cannot be performed on the selected file." + }) private void populateTable(Node node) { String dataSourceName = ""; String deviceId = ""; @@ -682,7 +684,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi // get the attributes we can correlate on correlationAttributes.addAll(getCorrelationAttributesFromNode(node)); for (CorrelationAttribute corAttr : correlationAttributes) { - Map correlatedNodeDataMap = new HashMap<>(0); + Map correlatedNodeDataMap = new HashMap<>(0); // get correlation and reference set instances from DB correlatedNodeDataMap.putAll(getCorrelatedInstances(corAttr, dataSourceName, deviceId)); @@ -697,7 +699,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi // @@@ BC: We should have a more descriptive message than this. Mention that the file didn't have a MD5, etc. displayMessageOnTableStatusPanel(Bundle.DataContentViewerOtherCases_table_noArtifacts()); } else if (0 == tableModel.getRowCount()) { - displayMessageOnTableStatusPanel(Bundle.DataContentViewerOtherCases_table_isempty()); + tableModel.addNodeData(new OtherOccurrenceNodeMessageData(Bundle.DataContentViewerOtherCases_table_noResultsFound())); } else { clearMessageOnTableStatusPanel(); setColumnWidths(); @@ -877,8 +879,9 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi if (EamDbUtil.useCentralRepo() && otherCasesTable.getSelectedRowCount() == 1) { int rowIndex = otherCasesTable.getSelectedRow(); OtherOccurrenceNodeData selectedNode = (OtherOccurrenceNodeData) tableModel.getRow(rowIndex); - if (selectedNode.isCentralRepoNode()) { - enableCentralRepoActions = true; + if (selectedNode instanceof OtherOccurrenceNodeInstanceData) { + OtherOccurrenceNodeInstanceData instanceData = (OtherOccurrenceNodeInstanceData) selectedNode; + enableCentralRepoActions = instanceData.isCentralRepoNode(); } } @@ -915,7 +918,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi private final String filePath; private final String type; - UniquePathKey(OtherOccurrenceNodeData nodeData) { + UniquePathKey(OtherOccurrenceNodeInstanceData nodeData) { super(); dataSourceID = nodeData.getDeviceID(); if (nodeData.getFilePath() != null) { diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCasesTableModel.java b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCasesTableModel.java index 5febf88dc3..0d7018885c 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCasesTableModel.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCasesTableModel.java @@ -1,7 +1,7 @@ /* * Central Repository * - * Copyright 2015-2017 Basis Technology Corp. + * Copyright 2015-2018 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,8 +22,6 @@ import java.util.ArrayList; import java.util.List; import javax.swing.table.AbstractTableModel; import org.openide.util.NbBundle.Messages; -import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttribute; -import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance; /** * Model for cells in data content viewer table @@ -34,7 +32,7 @@ public class DataContentViewerOtherCasesTableModel extends AbstractTableModel { "DataContentViewerOtherCasesTableModel.device=Device", "DataContentViewerOtherCasesTableModel.dataSource=Data Source", "DataContentViewerOtherCasesTableModel.path=Path", - "DataContentViewerOtherCasesTableModel.type=Correlation Type", + "DataContentViewerOtherCasesTableModel.property=Correlation Property", "DataContentViewerOtherCasesTableModel.value=Correlation Value", "DataContentViewerOtherCasesTableModel.known=Known", "DataContentViewerOtherCasesTableModel.comment=Comment", @@ -44,7 +42,7 @@ public class DataContentViewerOtherCasesTableModel extends AbstractTableModel { // If order is changed, update the CellRenderer to ensure correct row coloring. CASE_NAME(Bundle.DataContentViewerOtherCasesTableModel_case(), 100), DATA_SOURCE(Bundle.DataContentViewerOtherCasesTableModel_dataSource(), 100), - TYPE(Bundle.DataContentViewerOtherCasesTableModel_type(), 100), + PROPERTY(Bundle.DataContentViewerOtherCasesTableModel_property(), 125), VALUE(Bundle.DataContentViewerOtherCasesTableModel_value(), 200), KNOWN(Bundle.DataContentViewerOtherCasesTableModel_known(), 50), FILE_PATH(Bundle.DataContentViewerOtherCasesTableModel_path(), 450), @@ -126,38 +124,49 @@ public class DataContentViewerOtherCasesTableModel extends AbstractTableModel { */ private Object mapValueById(int rowIdx, TableColumns colId) { OtherOccurrenceNodeData nodeData = nodeDataList.get(rowIdx); + + if (nodeData instanceof OtherOccurrenceNodeMessageData) { + if (colId == TableColumns.CASE_NAME) { + OtherOccurrenceNodeMessageData messageData = (OtherOccurrenceNodeMessageData) nodeData; + return messageData.getDisplayMessage(); + } else { + return ""; + } + } + + OtherOccurrenceNodeInstanceData instanceData = (OtherOccurrenceNodeInstanceData) nodeData; String value = Bundle.DataContentViewerOtherCasesTableModel_noData(); switch (colId) { case CASE_NAME: - if (null != nodeData.getCaseName()) { - value = nodeData.getCaseName(); + if (null != instanceData.getCaseName()) { + value = instanceData.getCaseName(); } break; case DEVICE: - if (null != nodeData.getDeviceID()) { - value = nodeData.getDeviceID(); + if (null != instanceData.getDeviceID()) { + value = instanceData.getDeviceID(); } break; case DATA_SOURCE: - if (null != nodeData.getDataSourceName()) { - value = nodeData.getDataSourceName(); + if (null != instanceData.getDataSourceName()) { + value = instanceData.getDataSourceName(); } break; case FILE_PATH: - value = nodeData.getFilePath(); + value = instanceData.getFilePath(); break; - case TYPE: - value = nodeData.getType(); + case PROPERTY: + value = instanceData.getType(); break; case VALUE: - value = nodeData.getValue(); + value = instanceData.getValue(); break; case KNOWN: - value = nodeData.getKnown().getName(); + value = instanceData.getKnown().getName(); break; case COMMENT: - value = nodeData.getComment(); + value = instanceData.getComment(); break; } return value; @@ -178,6 +187,9 @@ public class DataContentViewerOtherCasesTableModel extends AbstractTableModel { fireTableDataChanged(); } + /** + * Clear the node data table. + */ void clearTable() { nodeDataList.clear(); fireTableDataChanged(); diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/OtherOccurrenceNodeData.java b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/OtherOccurrenceNodeData.java old mode 100644 new mode 100755 index 958068fb14..c10f078313 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/OtherOccurrenceNodeData.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/OtherOccurrenceNodeData.java @@ -1,5 +1,5 @@ /* - * Central Repository + * Autopsy Forensic Browser * * Copyright 2018 Basis Technology Corp. * Contact: carrier sleuthkit org @@ -18,216 +18,9 @@ */ package org.sleuthkit.autopsy.centralrepository.contentviewer; -import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttribute; -import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance; -import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException; -import org.sleuthkit.datamodel.AbstractFile; -import org.sleuthkit.datamodel.DataSource; -import org.sleuthkit.datamodel.TskCoreException; -import org.sleuthkit.datamodel.TskData; -import org.sleuthkit.datamodel.TskDataException; - /** - * Class for populating the Other Occurrences tab + * Marker interface for Other Occurrences nodes. */ -class OtherOccurrenceNodeData { +interface OtherOccurrenceNodeData { - // For now hard code the string for the central repo files type, since - // getting it dynamically can fail. - private static final String FILE_TYPE_STR = "Files"; - - private final String caseName; - private String deviceID; - private String dataSourceName; - private final String filePath; - private final String typeStr; - private final CorrelationAttribute.Type type; - private final String value; - private TskData.FileKnown known; - private String comment; - - private AbstractFile originalAbstractFile = null; - private CorrelationAttributeInstance originalCorrelationInstance = null; - - /** - * Create a node from a central repo instance. - * @param instance The central repo instance - * @param type The type of the instance - * @param value The value of the instance - */ - OtherOccurrenceNodeData(CorrelationAttributeInstance instance, CorrelationAttribute.Type type, String value) { - caseName = instance.getCorrelationCase().getDisplayName(); - deviceID = instance.getCorrelationDataSource().getDeviceID(); - dataSourceName = instance.getCorrelationDataSource().getName(); - filePath = instance.getFilePath(); - this.typeStr = type.getDisplayName(); - this.type = type; - this.value = value; - known = instance.getKnownStatus(); - comment = instance.getComment(); - - originalCorrelationInstance = instance; - } - - /** - * Create a node from an abstract file. - * @param newFile The abstract file - * @param autopsyCase The current case - * @throws EamDbException - */ - OtherOccurrenceNodeData(AbstractFile newFile, Case autopsyCase) throws EamDbException { - caseName = autopsyCase.getDisplayName(); - try { - DataSource dataSource = autopsyCase.getSleuthkitCase().getDataSource(newFile.getDataSource().getId()); - deviceID = dataSource.getDeviceId(); - dataSourceName = dataSource.getName(); - } catch (TskDataException | TskCoreException ex) { - throw new EamDbException("Error loading data source for abstract file ID " + newFile.getId(), ex); - } - - filePath = newFile.getParentPath() + newFile.getName(); - typeStr = FILE_TYPE_STR; - this.type = null; - value = newFile.getMd5Hash(); - known = newFile.getKnown(); - comment = ""; - - originalAbstractFile = newFile; - } - - /** - * Check if this node is a "file" type - * @return true if it is a file type - */ - boolean isFileType() { - return FILE_TYPE_STR.equals(typeStr); - } - - /** - * Update the known status for this node - * @param newKnownStatus The new known status - */ - void updateKnown(TskData.FileKnown newKnownStatus) { - known = newKnownStatus; - } - - /** - * Update the comment for this node - * @param newComment The new comment - */ - void updateComment(String newComment) { - comment = newComment; - } - - /** - * Check if this is a central repo node. - * @return true if this node was created from a central repo instance, false otherwise - */ - boolean isCentralRepoNode() { - return (originalCorrelationInstance != null); - } - - /** - * Uses the saved instance plus type and value to make a new CorrelationAttribute. - * Should only be called if isCentralRepoNode() is true. - * @return the newly created CorrelationAttribute - */ - CorrelationAttribute createCorrelationAttribute() throws EamDbException { - if (! isCentralRepoNode() ) { - throw new EamDbException("Can not create CorrelationAttribute for non central repo node"); - } - CorrelationAttribute attr = new CorrelationAttribute(type, value); - attr.addInstance(originalCorrelationInstance); - return attr; - } - - /** - * Get the case name - * @return the case name - */ - String getCaseName() { - return caseName; - } - - /** - * Get the device ID - * @return the device ID - */ - String getDeviceID() { - return deviceID; - } - - /** - * Get the data source name - * @return the data source name - */ - String getDataSourceName() { - return dataSourceName; - } - - /** - * Get the file path - * @return the file path - */ - String getFilePath() { - return filePath; - } - - /** - * Get the type (as a string) - * @return the type - */ - String getType() { - return typeStr; - } - - /** - * Get the value (MD5 hash for files) - * @return the value - */ - String getValue() { - return value; - } - - /** - * Get the known status - * @return the known status - */ - TskData.FileKnown getKnown() { - return known; - } - - /** - * Get the comment - * @return the comment - */ - String getComment() { - return comment; - } - - /** - * Get the backing abstract file. - * Should only be called if isCentralRepoNode() is false - * @return the original abstract file - */ - AbstractFile getAbstractFile() throws EamDbException { - if (originalCorrelationInstance == null) { - throw new EamDbException("AbstractFile is null"); - } - return originalAbstractFile; - } - - /** - * Get the backing CorrelationAttributeInstance. - * Should only be called if isCentralRepoNode() is true - * @return the original CorrelationAttributeInstance - * @throws EamDbException - */ - CorrelationAttributeInstance getCorrelationAttributeInstance() throws EamDbException { - if (originalCorrelationInstance == null) { - throw new EamDbException("CorrelationAttributeInstance is null"); - } - return originalCorrelationInstance; - } } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/OtherOccurrenceNodeInstanceData.java b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/OtherOccurrenceNodeInstanceData.java new file mode 100644 index 0000000000..7eb907aba8 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/OtherOccurrenceNodeInstanceData.java @@ -0,0 +1,233 @@ +/* + * Central Repository + * + * Copyright 2018 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.centralrepository.contentviewer; + +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttribute; +import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException; +import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.DataSource; +import org.sleuthkit.datamodel.TskCoreException; +import org.sleuthkit.datamodel.TskData; +import org.sleuthkit.datamodel.TskDataException; + +/** + * Class for populating the Other Occurrences tab + */ +class OtherOccurrenceNodeInstanceData implements OtherOccurrenceNodeData { + + // For now hard code the string for the central repo files type, since + // getting it dynamically can fail. + private static final String FILE_TYPE_STR = "Files"; + + private final String caseName; + private String deviceID; + private String dataSourceName; + private final String filePath; + private final String typeStr; + private final CorrelationAttribute.Type type; + private final String value; + private TskData.FileKnown known; + private String comment; + + private AbstractFile originalAbstractFile = null; + private CorrelationAttributeInstance originalCorrelationInstance = null; + + /** + * Create a node from a central repo instance. + * @param instance The central repo instance + * @param type The type of the instance + * @param value The value of the instance + */ + OtherOccurrenceNodeInstanceData(CorrelationAttributeInstance instance, CorrelationAttribute.Type type, String value) { + caseName = instance.getCorrelationCase().getDisplayName(); + deviceID = instance.getCorrelationDataSource().getDeviceID(); + dataSourceName = instance.getCorrelationDataSource().getName(); + filePath = instance.getFilePath(); + this.typeStr = type.getDisplayName(); + this.type = type; + this.value = value; + known = instance.getKnownStatus(); + comment = instance.getComment(); + + originalCorrelationInstance = instance; + } + + /** + * Create a node from an abstract file. + * @param newFile The abstract file + * @param autopsyCase The current case + * @throws EamDbException + */ + OtherOccurrenceNodeInstanceData(AbstractFile newFile, Case autopsyCase) throws EamDbException { + caseName = autopsyCase.getDisplayName(); + try { + DataSource dataSource = autopsyCase.getSleuthkitCase().getDataSource(newFile.getDataSource().getId()); + deviceID = dataSource.getDeviceId(); + dataSourceName = dataSource.getName(); + } catch (TskDataException | TskCoreException ex) { + throw new EamDbException("Error loading data source for abstract file ID " + newFile.getId(), ex); + } + + filePath = newFile.getParentPath() + newFile.getName(); + typeStr = FILE_TYPE_STR; + this.type = null; + value = newFile.getMd5Hash(); + known = newFile.getKnown(); + comment = ""; + + originalAbstractFile = newFile; + } + + /** + * Check if this node is a "file" type + * @return true if it is a file type + */ + boolean isFileType() { + return FILE_TYPE_STR.equals(typeStr); + } + + /** + * Update the known status for this node + * @param newKnownStatus The new known status + */ + void updateKnown(TskData.FileKnown newKnownStatus) { + known = newKnownStatus; + } + + /** + * Update the comment for this node + * @param newComment The new comment + */ + void updateComment(String newComment) { + comment = newComment; + } + + /** + * Check if this is a central repo node. + * @return true if this node was created from a central repo instance, false otherwise + */ + boolean isCentralRepoNode() { + return (originalCorrelationInstance != null); + } + + /** + * Uses the saved instance plus type and value to make a new CorrelationAttribute. + * Should only be called if isCentralRepoNode() is true. + * @return the newly created CorrelationAttribute + */ + CorrelationAttribute createCorrelationAttribute() throws EamDbException { + if (! isCentralRepoNode() ) { + throw new EamDbException("Can not create CorrelationAttribute for non central repo node"); + } + CorrelationAttribute attr = new CorrelationAttribute(type, value); + attr.addInstance(originalCorrelationInstance); + return attr; + } + + /** + * Get the case name + * @return the case name + */ + String getCaseName() { + return caseName; + } + + /** + * Get the device ID + * @return the device ID + */ + String getDeviceID() { + return deviceID; + } + + /** + * Get the data source name + * @return the data source name + */ + String getDataSourceName() { + return dataSourceName; + } + + /** + * Get the file path + * @return the file path + */ + String getFilePath() { + return filePath; + } + + /** + * Get the type (as a string) + * @return the type + */ + String getType() { + return typeStr; + } + + /** + * Get the value (MD5 hash for files) + * @return the value + */ + String getValue() { + return value; + } + + /** + * Get the known status + * @return the known status + */ + TskData.FileKnown getKnown() { + return known; + } + + /** + * Get the comment + * @return the comment + */ + String getComment() { + return comment; + } + + /** + * Get the backing abstract file. + * Should only be called if isCentralRepoNode() is false + * @return the original abstract file + */ + AbstractFile getAbstractFile() throws EamDbException { + if (originalCorrelationInstance == null) { + throw new EamDbException("AbstractFile is null"); + } + return originalAbstractFile; + } + + /** + * Get the backing CorrelationAttributeInstance. + * Should only be called if isCentralRepoNode() is true + * @return the original CorrelationAttributeInstance + * @throws EamDbException + */ + CorrelationAttributeInstance getCorrelationAttributeInstance() throws EamDbException { + if (originalCorrelationInstance == null) { + throw new EamDbException("CorrelationAttributeInstance is null"); + } + return originalCorrelationInstance; + } +} diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/OtherOccurrenceNodeMessageData.java b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/OtherOccurrenceNodeMessageData.java new file mode 100755 index 0000000000..99e530349a --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/OtherOccurrenceNodeMessageData.java @@ -0,0 +1,34 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2018 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.centralrepository.contentviewer; + +/** + * Class for populating the Other Occurrences tab with a single message. + */ +final class OtherOccurrenceNodeMessageData implements OtherOccurrenceNodeData { + private final String displayMessage; + + OtherOccurrenceNodeMessageData(String displayMessage) { + this.displayMessage = displayMessage; + } + + String getDisplayMessage() { + return displayMessage; + } +} From 5aec70fbaf03c09630ddba81185a59a5fa13c1fb Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Fri, 6 Jul 2018 16:43:56 -0400 Subject: [PATCH 02/21] Partial handling of 'noArtifacts' message. --- .../DataContentViewerOtherCases.java | 25 +++++++------------ ...DataContentViewerOtherCasesTableModel.java | 8 +++--- 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java index c3558a106b..ebc5b7c375 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java @@ -38,7 +38,6 @@ import java.util.Map; import java.util.Objects; import java.util.logging.Level; import org.sleuthkit.autopsy.coreutils.Logger; -import java.util.stream.Collectors; import javax.swing.JFileChooser; import javax.swing.JMenuItem; import javax.swing.JOptionPane; @@ -49,6 +48,7 @@ import javax.swing.JPanel; import javax.swing.filechooser.FileNameExtensionFilter; import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumn; +import javax.swing.table.TableColumnModel; import org.joda.time.DateTimeZone; import org.joda.time.LocalDateTime; import org.openide.nodes.Node; @@ -147,7 +147,6 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi // Set background of every nth row as light grey. TableCellRenderer renderer = new DataContentViewerOtherCasesTableCellRenderer(); otherCasesTable.setDefaultRenderer(Object.class, renderer); - tableStatusPanelLabel.setVisible(false); } @@ -664,8 +663,8 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi * @param node The node being viewed. */ @Messages({ - "DataContentViewerOtherCases.table.noResultsFound=No results found.", - "DataContentViewerOtherCases.table.noArtifacts=Correlation cannot be performed on the selected file." + "DataContentViewerOtherCases.table.noArtifacts=Item has no attributes with which to search.", + "DataContentViewerOtherCases.table.noResultsFound=No results found." }) private void populateTable(Node node) { String dataSourceName = ""; @@ -696,17 +695,20 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi } if (correlationAttributes.isEmpty()) { - // @@@ BC: We should have a more descriptive message than this. Mention that the file didn't have a MD5, etc. - displayMessageOnTableStatusPanel(Bundle.DataContentViewerOtherCases_table_noArtifacts()); + tableModel.addNodeData(new OtherOccurrenceNodeMessageData(Bundle.DataContentViewerOtherCases_table_noArtifacts())); + //DLG: Removing columns causes problems. Look into resizing columns. } else if (0 == tableModel.getRowCount()) { tableModel.addNodeData(new OtherOccurrenceNodeMessageData(Bundle.DataContentViewerOtherCases_table_noResultsFound())); + //DLG: Removing columns causes problems. Look into resizing columns. } else { - clearMessageOnTableStatusPanel(); setColumnWidths(); } setEarliestCaseDate(); } + /** + * Adjust column widths to their preferred values. + */ private void setColumnWidths() { for (int idx = 0; idx < tableModel.getColumnCount(); idx++) { TableColumn column = otherCasesTable.getColumnModel().getColumn(idx); @@ -717,15 +719,6 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi } } - private void displayMessageOnTableStatusPanel(String message) { - tableStatusPanelLabel.setText(message); - tableStatusPanelLabel.setVisible(true); - } - - private void clearMessageOnTableStatusPanel() { - tableStatusPanelLabel.setVisible(false); - } - /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCasesTableModel.java b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCasesTableModel.java index 0d7018885c..de528e2d42 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCasesTableModel.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCasesTableModel.java @@ -32,8 +32,8 @@ public class DataContentViewerOtherCasesTableModel extends AbstractTableModel { "DataContentViewerOtherCasesTableModel.device=Device", "DataContentViewerOtherCasesTableModel.dataSource=Data Source", "DataContentViewerOtherCasesTableModel.path=Path", - "DataContentViewerOtherCasesTableModel.property=Correlation Property", - "DataContentViewerOtherCasesTableModel.value=Correlation Value", + "DataContentViewerOtherCasesTableModel.attribute=Matched Attribute", + "DataContentViewerOtherCasesTableModel.value=Attribute Value", "DataContentViewerOtherCasesTableModel.known=Known", "DataContentViewerOtherCasesTableModel.comment=Comment", "DataContentViewerOtherCasesTableModel.noData=No Data.",}) @@ -42,7 +42,7 @@ public class DataContentViewerOtherCasesTableModel extends AbstractTableModel { // If order is changed, update the CellRenderer to ensure correct row coloring. CASE_NAME(Bundle.DataContentViewerOtherCasesTableModel_case(), 100), DATA_SOURCE(Bundle.DataContentViewerOtherCasesTableModel_dataSource(), 100), - PROPERTY(Bundle.DataContentViewerOtherCasesTableModel_property(), 125), + ATTRIBUTE(Bundle.DataContentViewerOtherCasesTableModel_attribute(), 125), VALUE(Bundle.DataContentViewerOtherCasesTableModel_value(), 200), KNOWN(Bundle.DataContentViewerOtherCasesTableModel_known(), 50), FILE_PATH(Bundle.DataContentViewerOtherCasesTableModel_path(), 450), @@ -156,7 +156,7 @@ public class DataContentViewerOtherCasesTableModel extends AbstractTableModel { case FILE_PATH: value = instanceData.getFilePath(); break; - case PROPERTY: + case ATTRIBUTE: value = instanceData.getType(); break; case VALUE: From 75fbb309b9ad390b5ce9261ec5e228d994a01be8 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Wed, 11 Jul 2018 01:35:06 -0400 Subject: [PATCH 03/21] Column width adjustments handled. --- .../DataContentViewerOtherCases.form | 24 +--- .../DataContentViewerOtherCases.java | 123 +++++++++-------- ...DataContentViewerOtherCasesTableModel.java | 126 ++++++++++-------- 3 files changed, 142 insertions(+), 131 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.form b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.form index 7b9e47c236..9c42be16a8 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.form +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.form @@ -133,23 +133,18 @@ - - - + - - - - - - - - + + + + + @@ -230,13 +225,6 @@ - - - - - - - diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java index ebc5b7c375..1c69671b05 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java @@ -19,6 +19,7 @@ package org.sleuthkit.autopsy.centralrepository.contentviewer; import java.awt.Component; +import java.awt.FontMetrics; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.BufferedWriter; @@ -86,7 +87,10 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi private static final long serialVersionUID = -1L; - private final static Logger logger = Logger.getLogger(DataContentViewerOtherCases.class.getName()); + private static final Logger logger = Logger.getLogger(DataContentViewerOtherCases.class.getName()); + + private static final int DEFAULT_MIN_CELL_WIDTH = 15; + private static final int CELL_TEXT_WIDTH_PADDING = 5; private final DataContentViewerOtherCasesTableModel tableModel; private final Collection correlationAttributes; @@ -459,12 +463,12 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi @Messages({"DataContentViewerOtherCases.earliestCaseNotAvailable= Not Enabled."}) /** - * Gets the list of Eam Cases and determines the earliest case creation date. - * Sets the label to display the earliest date string to the user. + * Gets the list of Eam Cases and determines the earliest case creation + * date. Sets the label to display the earliest date string to the user. */ - private void setEarliestCaseDate() { - String dateStringDisplay = Bundle.DataContentViewerOtherCases_earliestCaseNotAvailable(); - + private void setEarliestCaseDate() { + String dateStringDisplay = Bundle.DataContentViewerOtherCases_earliestCaseNotAvailable(); + if (EamDb.isEnabled()) { LocalDateTime earliestDate = LocalDateTime.now(DateTimeZone.UTC); DateFormat datetimeFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss", Locale.US); @@ -472,15 +476,15 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi EamDb dbManager = EamDb.getInstance(); List cases = dbManager.getCases(); for (CorrelationCase aCase : cases) { - LocalDateTime caseDate = LocalDateTime.fromDateFields(datetimeFormat.parse(aCase.getCreationDate())); - - if (caseDate.isBefore(earliestDate)) { + LocalDateTime caseDate = LocalDateTime.fromDateFields(datetimeFormat.parse(aCase.getCreationDate())); + + if (caseDate.isBefore(earliestDate)) { earliestDate = caseDate; dateStringDisplay = aCase.getCreationDate(); - } + } } - + } catch (EamDbException ex) { logger.log(Level.SEVERE, "Error getting list of cases from database.", ex); // NON-NLS } catch (ParseException ex) { @@ -492,10 +496,10 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi } /** - * Query the central repo database (if enabled) and the case database to find all - * artifact instances correlated to the given central repository artifact. If the - * central repo is not enabled, this will only return files from the current case - * with matching MD5 hashes. + * Query the central repo database (if enabled) and the case database to + * find all artifact instances correlated to the given central repository + * artifact. If the central repo is not enabled, this will only return files + * from the current case with matching MD5 hashes. * * @param corAttr CorrelationAttribute to query for * @param dataSourceName Data source to filter results @@ -503,19 +507,19 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi * * @return A collection of correlated artifact instances */ - private Map getCorrelatedInstances(CorrelationAttribute corAttr, String dataSourceName, String deviceId) { + private Map getCorrelatedInstances(CorrelationAttribute corAttr, String dataSourceName, String deviceId) { // @@@ Check exception try { final Case openCase = Case.getCurrentCase(); String caseUUID = openCase.getName(); - HashMap nodeDataMap = new HashMap<>(); + HashMap nodeDataMap = new HashMap<>(); if (EamDb.isEnabled()) { List instances = EamDb.getInstance().getArtifactInstancesByTypeValue(corAttr.getCorrelationType(), corAttr.getCorrelationValue()); - for (CorrelationAttributeInstance artifactInstance:instances) { - + for (CorrelationAttributeInstance artifactInstance : instances) { + // Only add the attribute if it isn't the object the user selected. // We consider it to be a different object if at least one of the following is true: // - the case UUID is different @@ -534,7 +538,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi } } - if (corAttr.getCorrelationType().getDisplayName().equals("Files")) { + if (corAttr.getCorrelationType().getDisplayName().equals("Files")) { List caseDbFiles = getCaseDbMatches(corAttr, openCase); for (AbstractFile caseDbFile : caseDbFiles) { @@ -557,13 +561,17 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi } /** - * Get all other abstract files in the current case with the same MD5 as the selected node. + * Get all other abstract files in the current case with the same MD5 as the + * selected node. + * * @param corAttr The CorrelationAttribute containing the MD5 to search for * @param openCase The current case + * * @return List of matching AbstractFile objects + * * @throws NoCurrentCaseException * @throws TskCoreException - * @throws EamDbException + * @throws EamDbException */ private List getCaseDbMatches(CorrelationAttribute corAttr, Case openCase) throws NoCurrentCaseException, TskCoreException, EamDbException { String md5 = corAttr.getCorrelationValue(); @@ -583,18 +591,18 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi /** * Adds the file to the nodeDataMap map if it does not already exist - * - * @param autopsyCase + * + * @param autopsyCase * @param nodeDataMap * @param newFile * * @throws TskCoreException * @throws EamDbException */ - private void addOrUpdateNodeData(final Case autopsyCase, Map nodeDataMap, AbstractFile newFile) throws TskCoreException, EamDbException { - + private void addOrUpdateNodeData(final Case autopsyCase, Map nodeDataMap, AbstractFile newFile) throws TskCoreException, EamDbException { + OtherOccurrenceNodeInstanceData newNode = new OtherOccurrenceNodeInstanceData(newFile, autopsyCase); - + // If the caseDB object has a notable tag associated with it, update // the known status to BAD if (newNode.getKnown() != TskData.FileKnown.BAD) { @@ -610,7 +618,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi // Make a key to see if the file is already in the map UniquePathKey uniquePathKey = new UniquePathKey(newNode); - + // If this node is already in the list, the only thing we need to do is // update the known status to BAD if the caseDB version had known status BAD. // Otherwise this is a new node so add the new node to the map. @@ -639,7 +647,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi } else { return this.file != null && this.file.getSize() > 0 - && ((this.file.getMd5Hash() != null) && ( ! this.file.getMd5Hash().isEmpty())); + && ((this.file.getMd5Hash() != null) && (!this.file.getMd5Hash().isEmpty())); } } @@ -683,7 +691,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi // get the attributes we can correlate on correlationAttributes.addAll(getCorrelationAttributesFromNode(node)); for (CorrelationAttribute corAttr : correlationAttributes) { - Map correlatedNodeDataMap = new HashMap<>(0); + Map correlatedNodeDataMap = new HashMap<>(0); // get correlation and reference set instances from DB correlatedNodeDataMap.putAll(getCorrelatedInstances(corAttr, dataSourceName, deviceId)); @@ -696,25 +704,40 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi if (correlationAttributes.isEmpty()) { tableModel.addNodeData(new OtherOccurrenceNodeMessageData(Bundle.DataContentViewerOtherCases_table_noArtifacts())); - //DLG: Removing columns causes problems. Look into resizing columns. + setColumnWidthToText(0, Bundle.DataContentViewerOtherCases_table_noArtifacts()); } else if (0 == tableModel.getRowCount()) { tableModel.addNodeData(new OtherOccurrenceNodeMessageData(Bundle.DataContentViewerOtherCases_table_noResultsFound())); - //DLG: Removing columns causes problems. Look into resizing columns. + setColumnWidthToText(0, Bundle.DataContentViewerOtherCases_table_noResultsFound()); } else { setColumnWidths(); } setEarliestCaseDate(); } + /** + * Adjust a given column for the text provided. + * + * @param columnIndex The index of the column to adjust. + * @param text The text whose length will be used to adjust the + * column width. + */ + private void setColumnWidthToText(int columnIndex, String text) { + TableColumn column = otherCasesTable.getColumnModel().getColumn(columnIndex); + FontMetrics fontMetrics = otherCasesTable.getFontMetrics(otherCasesTable.getFont()); + int stringWidth = fontMetrics.stringWidth(text); + column.setMinWidth(stringWidth + CELL_TEXT_WIDTH_PADDING); + } + /** * Adjust column widths to their preferred values. */ private void setColumnWidths() { for (int idx = 0; idx < tableModel.getColumnCount(); idx++) { TableColumn column = otherCasesTable.getColumnModel().getColumn(idx); - int colWidth = tableModel.getColumnPreferredWidth(idx); - if (0 < colWidth) { - column.setPreferredWidth(colWidth); + column.setMinWidth(DEFAULT_MIN_CELL_WIDTH); + int columnWidth = tableModel.getColumnPreferredWidth(idx); + if (columnWidth > 0) { + column.setPreferredWidth(columnWidth); } } } @@ -742,7 +765,6 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi earliestCaseLabel = new javax.swing.JLabel(); earliestCaseDate = new javax.swing.JLabel(); tableStatusPanel = new javax.swing.JPanel(); - tableStatusPanelLabel = new javax.swing.JLabel(); rightClickPopupMenu.addPopupMenuListener(new javax.swing.event.PopupMenuListener() { public void popupMenuCanceled(javax.swing.event.PopupMenuEvent evt) { @@ -804,8 +826,6 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi .addGap(0, 16, Short.MAX_VALUE) ); - tableStatusPanelLabel.setForeground(new java.awt.Color(255, 0, 51)); - javax.swing.GroupLayout tableContainerPanelLayout = new javax.swing.GroupLayout(tableContainerPanel); tableContainerPanel.setLayout(tableContainerPanelLayout); tableContainerPanelLayout.setHorizontalGroup( @@ -818,20 +838,16 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi .addComponent(earliestCaseLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(earliestCaseDate) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(tableStatusPanelLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addContainerGap()) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); tableContainerPanelLayout.setVerticalGroup( tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, tableContainerPanelLayout.createSequentialGroup() - .addComponent(tableScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 176, Short.MAX_VALUE) - .addGap(0, 0, 0) - .addGroup(tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addGroup(tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(earliestCaseLabel) - .addComponent(earliestCaseDate)) - .addComponent(tableStatusPanelLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(tableScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 27, Short.MAX_VALUE) + .addGap(2, 2, 2) + .addGroup(tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(earliestCaseLabel) + .addComponent(earliestCaseDate)) .addGap(0, 0, 0) .addComponent(tableStatusPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(0, 0, 0)) @@ -850,7 +866,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi .addGap(0, 483, Short.MAX_VALUE) .addGroup(otherCasesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(otherCasesPanelLayout.createSequentialGroup() - .addComponent(tableContainerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 483, Short.MAX_VALUE) + .addComponent(tableContainerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 59, Short.MAX_VALUE) .addGap(0, 0, 0))) ); @@ -862,7 +878,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(otherCasesPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 483, Short.MAX_VALUE) + .addComponent(otherCasesPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 59, Short.MAX_VALUE) ); }// //GEN-END:initComponents @@ -898,7 +914,6 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi private javax.swing.JPanel tableContainerPanel; private javax.swing.JScrollPane tableScrollPane; private javax.swing.JPanel tableStatusPanel; - private javax.swing.JLabel tableStatusPanelLabel; // End of variables declaration//GEN-END:variables /** @@ -925,9 +940,9 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi @Override public boolean equals(Object other) { if (other instanceof UniquePathKey) { - UniquePathKey otherKey = (UniquePathKey)(other); - return ( Objects.equals(otherKey.dataSourceID, this.dataSourceID) - && Objects.equals(otherKey.filePath, this.filePath) + UniquePathKey otherKey = (UniquePathKey) (other); + return (Objects.equals(otherKey.dataSourceID, this.dataSourceID) + && Objects.equals(otherKey.filePath, this.filePath) && Objects.equals(otherKey.type, this.type)); } return false; diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCasesTableModel.java b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCasesTableModel.java index de528e2d42..9ae79259c2 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCasesTableModel.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCasesTableModel.java @@ -107,71 +107,79 @@ public class DataContentViewerOtherCasesTableModel extends AbstractTableModel { return Bundle.DataContentViewerOtherCasesTableModel_noData(); } - return mapValueById(rowIdx, TableColumns.values()[colIdx]); + OtherOccurrenceNodeData nodeData = nodeDataList.get(rowIdx); + TableColumns columnId = TableColumns.values()[colIdx]; + if (nodeData instanceof OtherOccurrenceNodeMessageData) { + return mapNodeMessageData((OtherOccurrenceNodeMessageData) nodeData, columnId); + } + return mapNodeInstanceData((OtherOccurrenceNodeInstanceData) nodeData, columnId); + } + + /** + * Map a column ID to the value in that cell for node message data. + * + * @param nodeData The node message data. + * @param columnId The ID of the cell column. + * + * @return The value in the cell. + */ + private Object mapNodeMessageData(OtherOccurrenceNodeMessageData nodeData, TableColumns columnId) { + if (columnId == TableColumns.CASE_NAME) { + return nodeData.getDisplayMessage(); + } + return ""; + } + + /** + * Map a column ID to the value in that cell for node instance data. + * + * @param nodeData The node instance data. + * @param columnId The ID of the cell column. + * + * @return The value in the cell. + */ + private Object mapNodeInstanceData(OtherOccurrenceNodeInstanceData nodeData, TableColumns columnId) { + String value = Bundle.DataContentViewerOtherCasesTableModel_noData(); + + switch (columnId) { + case CASE_NAME: + if (null != nodeData.getCaseName()) { + value = nodeData.getCaseName(); + } + break; + case DEVICE: + if (null != nodeData.getDeviceID()) { + value = nodeData.getDeviceID(); + } + break; + case DATA_SOURCE: + if (null != nodeData.getDataSourceName()) { + value = nodeData.getDataSourceName(); + } + break; + case FILE_PATH: + value = nodeData.getFilePath(); + break; + case ATTRIBUTE: + value = nodeData.getType(); + break; + case VALUE: + value = nodeData.getValue(); + break; + case KNOWN: + value = nodeData.getKnown().getName(); + break; + case COMMENT: + value = nodeData.getComment(); + break; + } + return value; } Object getRow(int rowIdx) { return nodeDataList.get(rowIdx); } - /** - * Map a rowIdx and colId to the value in that cell. - * - * @param rowIdx Index of row to search - * @param colId ID of column to search - * - * @return value in the cell - */ - private Object mapValueById(int rowIdx, TableColumns colId) { - OtherOccurrenceNodeData nodeData = nodeDataList.get(rowIdx); - - if (nodeData instanceof OtherOccurrenceNodeMessageData) { - if (colId == TableColumns.CASE_NAME) { - OtherOccurrenceNodeMessageData messageData = (OtherOccurrenceNodeMessageData) nodeData; - return messageData.getDisplayMessage(); - } else { - return ""; - } - } - - OtherOccurrenceNodeInstanceData instanceData = (OtherOccurrenceNodeInstanceData) nodeData; - String value = Bundle.DataContentViewerOtherCasesTableModel_noData(); - - switch (colId) { - case CASE_NAME: - if (null != instanceData.getCaseName()) { - value = instanceData.getCaseName(); - } - break; - case DEVICE: - if (null != instanceData.getDeviceID()) { - value = instanceData.getDeviceID(); - } - break; - case DATA_SOURCE: - if (null != instanceData.getDataSourceName()) { - value = instanceData.getDataSourceName(); - } - break; - case FILE_PATH: - value = instanceData.getFilePath(); - break; - case ATTRIBUTE: - value = instanceData.getType(); - break; - case VALUE: - value = instanceData.getValue(); - break; - case KNOWN: - value = instanceData.getKnown().getName(); - break; - case COMMENT: - value = instanceData.getComment(); - break; - } - return value; - } - @Override public Class getColumnClass(int colIdx) { return String.class; From a1c4db14bd55b1c9567f2886a7698a5b7707c1d2 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Thu, 2 Aug 2018 10:22:08 -0400 Subject: [PATCH 04/21] Codacy issues resolved. --- .../contentviewer/DataContentViewerOtherCases.java | 1 - .../contentviewer/DataContentViewerOtherCasesTableModel.java | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java index 635605a904..6579b15e08 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java @@ -49,7 +49,6 @@ import javax.swing.JPanel; import javax.swing.filechooser.FileNameExtensionFilter; import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumn; -import javax.swing.table.TableColumnModel; import org.joda.time.DateTimeZone; import org.joda.time.LocalDateTime; import org.openide.nodes.Node; diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCasesTableModel.java b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCasesTableModel.java index 9ae79259c2..1f04f1f478 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCasesTableModel.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCasesTableModel.java @@ -172,6 +172,8 @@ public class DataContentViewerOtherCasesTableModel extends AbstractTableModel { case COMMENT: value = nodeData.getComment(); break; + default: // This shouldn't occur! Use default "No data" value. + break; } return value; } From 74bf4bd272c5cb2d85aa589fd48510853fc4aee6 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Thu, 2 Aug 2018 14:14:24 -0400 Subject: [PATCH 05/21] 3964 - change name of new image to reflect naming schema in 3771 --- Core/build.xml | 2 +- .../src/org/sleuthkit/autopsy/ingest/EmbeddedFileTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/build.xml b/Core/build.xml index 322fe961ff..aa654b0f36 100644 --- a/Core/build.xml +++ b/Core/build.xml @@ -86,7 +86,7 @@ - + diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/ingest/EmbeddedFileTest.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/ingest/EmbeddedFileTest.java index 0bb8144527..7af0a429d8 100755 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/ingest/EmbeddedFileTest.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/ingest/EmbeddedFileTest.java @@ -47,7 +47,7 @@ import org.sleuthkit.datamodel.TskCoreException; public class EmbeddedFileTest extends NbTestCase { private static final String CASE_NAME = "EmbeddedFileTest"; - private final Path IMAGE_PATH = Paths.get(this.getDataDir().toString(), "EmbeddedIM_img2_v1.vhd"); + private final Path IMAGE_PATH = Paths.get(this.getDataDir().toString(), "EmbeddedIM_img1_v2.vhd"); public static final String HASH_VALUE = "098f6bcd4621d373cade4e832627b4f6"; private static final int DEEP_FOLDER_COUNT = 25; private Case openCase; From 0c571ab20ece0fb87b29e7ca7539f7ea59bd2e14 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Thu, 2 Aug 2018 15:27:27 -0400 Subject: [PATCH 06/21] Added user-defined path for extraction. --- .../autopsy/directorytree/ExtractAction.java | 66 ++++++++++++++++--- .../directorytree/ExtractUnallocAction.java | 44 ++++++++++++- 2 files changed, 99 insertions(+), 11 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ExtractAction.java b/Core/src/org/sleuthkit/autopsy/directorytree/ExtractAction.java index 2f45e44331..b0b847d1a6 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/ExtractAction.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/ExtractAction.java @@ -33,7 +33,6 @@ import javax.swing.JOptionPane; import javax.swing.SwingWorker; import org.netbeans.api.progress.ProgressHandle; import org.openide.util.Cancellable; -import org.openide.util.Exceptions; import org.openide.util.NbBundle; import org.openide.util.Utilities; import org.sleuthkit.autopsy.casemodule.Case; @@ -54,6 +53,8 @@ public final class ExtractAction extends AbstractAction { private Logger logger = Logger.getLogger(ExtractAction.class.getName()); + private String userDefinedExportPath; + // This class is a singleton to support multi-selection of nodes, since // org.openide.nodes.NodeOp.findActions(Node[] nodes) will only pick up an Action if every // node in the array returns a reference to the same action object from Node.getActions(boolean). @@ -97,7 +98,7 @@ public final class ExtractAction extends AbstractAction { * @param e * @param selectedFile Selected file */ - @NbBundle.Messages ({"ExtractAction.noOpenCase.errMsg=No open case available."}) + @NbBundle.Messages({"ExtractAction.noOpenCase.errMsg=No open case available."}) private void extractFile(ActionEvent e, AbstractFile selectedFile) { Case openCase; try { @@ -108,10 +109,12 @@ public final class ExtractAction extends AbstractAction { return; } JFileChooser fileChooser = new JFileChooser(); - fileChooser.setCurrentDirectory(new File(openCase.getExportDirectory())); + fileChooser.setCurrentDirectory(new File(getExportDirectory(openCase))); // If there is an attribute name, change the ":". Otherwise the extracted file will be hidden fileChooser.setSelectedFile(new File(FileUtil.escapeFileName(selectedFile.getName()))); if (fileChooser.showSaveDialog((Component) e.getSource()) == JFileChooser.APPROVE_OPTION) { + updateExportDirectory(fileChooser.getSelectedFile().getParent(), openCase); + ArrayList fileExtractionTasks = new ArrayList<>(); fileExtractionTasks.add(new FileExtractionTask(selectedFile, fileChooser.getSelectedFile())); runExtractionTasks(e, fileExtractionTasks); @@ -135,7 +138,7 @@ public final class ExtractAction extends AbstractAction { } JFileChooser folderChooser = new JFileChooser(); folderChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); - folderChooser.setCurrentDirectory(new File(openCase.getExportDirectory())); + folderChooser.setCurrentDirectory(new File(getExportDirectory(openCase))); if (folderChooser.showSaveDialog((Component) e.getSource()) == JFileChooser.APPROVE_OPTION) { File destinationFolder = folderChooser.getSelectedFile(); if (!destinationFolder.exists()) { @@ -148,12 +151,16 @@ public final class ExtractAction extends AbstractAction { return; } } + updateExportDirectory(destinationFolder.getPath(), openCase); - /* get the unique set of files from the list. A user once reported extraction taking - * days because it was extracting the same PST file 20k times. They selected 20k - * email messages in the tree and chose to extract them. */ + /* + * get the unique set of files from the list. A user once reported + * extraction taking days because it was extracting the same PST + * file 20k times. They selected 20k email messages in the tree and + * chose to extract them. + */ Set uniqueFiles = new HashSet<>(selectedFiles); - + // make a task for each file ArrayList fileExtractionTasks = new ArrayList<>(); for (AbstractFile source : uniqueFiles) { @@ -164,6 +171,45 @@ public final class ExtractAction extends AbstractAction { } } + /** + * Get the export directory path. + * + * @param openCase The current case. + * + * @return The export directory path. + */ + private String getExportDirectory(Case openCase) { + String caseExportPath = openCase.getExportDirectory(); + + if (userDefinedExportPath == null) { + return caseExportPath; + } + + File file = new File(userDefinedExportPath); + if (file.exists() == false || file.isDirectory() == false) { + return caseExportPath; + } + + return userDefinedExportPath; + } + + /** + * Update the default export directory. If the directory path matches the + * case export directory, then the directory used will always match the + * export directory of any given case. Otherwise, the path last used will be + * saved. + * + * @param exportPath The export path. + * @param openCase The current case. + */ + private void updateExportDirectory(String exportPath, Case openCase) { + if (exportPath.equalsIgnoreCase(openCase.getExportDirectory())) { + userDefinedExportPath = null; + } else { + userDefinedExportPath = exportPath; + } + } + private void runExtractionTasks(ActionEvent e, ArrayList fileExtractionTasks) { // verify all of the sources and destinations are OK @@ -177,8 +223,8 @@ public final class ExtractAction extends AbstractAction { } /* - * This code assumes that each destination is unique. We previously satisfied - * that by adding the unique ID. + * This code assumes that each destination is unique. We previously + * satisfied that by adding the unique ID. */ if (task.destination.exists()) { if (JOptionPane.showConfirmDialog((Component) e.getSource(), diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ExtractUnallocAction.java b/Core/src/org/sleuthkit/autopsy/directorytree/ExtractUnallocAction.java index b0729d24c6..83fe882e45 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/ExtractUnallocAction.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/ExtractUnallocAction.java @@ -66,6 +66,7 @@ final class ExtractUnallocAction extends AbstractAction { private final List filesToExtract = new ArrayList<>(); private static final Set volumesInProgress = new HashSet<>(); private static final Set imagesInProgress = new HashSet<>(); + private static String userDefinedExportPath; private long currentImage = 0L; private final boolean isImage; @@ -145,7 +146,7 @@ final class ExtractUnallocAction extends AbstractAction { } }; - fileChooser.setCurrentDirectory(new File(openCase.getExportDirectory())); + fileChooser.setCurrentDirectory(new File(getExportDirectory(openCase))); fileChooser.setDialogTitle( NbBundle.getMessage(this.getClass(), "ExtractUnallocAction.dlgTitle.selectDirToSaveTo.msg")); fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); @@ -153,6 +154,9 @@ final class ExtractUnallocAction extends AbstractAction { int returnValue = fileChooser.showSaveDialog((Component) e.getSource()); if (returnValue == JFileChooser.APPROVE_OPTION) { String destination = fileChooser.getSelectedFile().getPath(); + + updateExportDirectory(destination, openCase); + for (OutputFileData outputFileData : filesToExtract) { outputFileData.setPath(destination); @@ -214,7 +218,45 @@ final class ExtractUnallocAction extends AbstractAction { } } } + } + + /** + * Get the export directory path. + * + * @param openCase The current case. + * + * @return The export directory path. + */ + private String getExportDirectory(Case openCase) { + String caseExportPath = openCase.getExportDirectory(); + if (userDefinedExportPath == null) { + return caseExportPath; + } + + File file = new File(userDefinedExportPath); + if (file.exists() == false || file.isDirectory() == false) { + return caseExportPath; + } + + return userDefinedExportPath; + } + + /** + * Update the default export directory. If the directory path matches the + * case export directory, then the directory used will always match the + * export directory of any given case. Otherwise, the path last used will be + * saved. + * + * @param exportPath The export path. + * @param openCase The current case. + */ + private void updateExportDirectory(String exportPath, Case openCase) { + if (exportPath.equalsIgnoreCase(openCase.getExportDirectory())) { + userDefinedExportPath = null; + } else { + userDefinedExportPath = exportPath; + } } /** From 21fc9a67a952300e4b2bd556ce42b175540da706 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Thu, 2 Aug 2018 16:08:21 -0400 Subject: [PATCH 07/21] 3964 adjust failure messages for zip bomb test to give more context --- .../autopsy/ingest/EmbeddedFileTest.java | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/ingest/EmbeddedFileTest.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/ingest/EmbeddedFileTest.java index 7af0a429d8..995aac1818 100755 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/ingest/EmbeddedFileTest.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/ingest/EmbeddedFileTest.java @@ -96,43 +96,45 @@ public class EmbeddedFileTest extends NbTestCase { public void testEncryptionAndZipBomb() { try { - List results = openCase.getSleuthkitCase().findAllFilesWhere("name LIKE '%%'"); - String protectedName1 = "password_protected.zip"; - String protectedName2 = "level1_protected.zip"; - String protectedName3 = "42.zip"; - String depthZipBomb = "DepthTriggerZipBomb.zip"; - String ratioZipBomb = "RatioTriggerZipBomb.zip"; + List results = openCase.getSleuthkitCase().findAllFilesWhere("name LIKE '%%'"); + final String zipBombSetName = "Possible Zip Bomb"; + final String protectedName1 = "password_protected.zip"; + final String protectedName2 = "level1_protected.zip"; + final String protectedName3 = "42.zip"; + final String depthZipBomb = "DepthTriggerZipBomb.zip"; + final String ratioZipBomb = "RatioTriggerZipBomb.zip"; int zipBombs = 0; - assertEquals(2221, results.size()); + assertEquals("The number of files in the test image has changed", 2221, results.size()); int passwdProtectedZips = 0; for (AbstractFile file : results) { //.zip file has artifact TSK_ENCRYPTION_DETECTED if (file.getName().equalsIgnoreCase(protectedName1) || file.getName().equalsIgnoreCase(protectedName2) || file.getName().equalsIgnoreCase(protectedName3)){ ArrayList artifacts = file.getAllArtifacts(); - assertEquals(1, artifacts.size()); + assertEquals("Password protected zip file " + file.getName() + " has incorrect number of artifacts", 1, artifacts.size()); for (BlackboardArtifact artifact : artifacts) { - assertEquals(artifact.getArtifactTypeID(), BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_DETECTED.getTypeID()); + assertEquals("Artifact for password protected zip file " + file.getName() + " has incorrect type ID", artifact.getArtifactTypeID(), BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_DETECTED.getTypeID()); passwdProtectedZips++; } } else if (file.getName().equalsIgnoreCase(depthZipBomb) || file.getName().equalsIgnoreCase(ratioZipBomb)){ ArrayList artifacts = file.getAllArtifacts(); - assertEquals(1, artifacts.size()); + assertEquals("Zip bomb " + file.getName() + " has incorrect number of artifacts", 1, artifacts.size()); for (BlackboardArtifact artifact : artifacts) { - assertEquals(artifact.getArtifactTypeID(), BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID()); + assertEquals("Artifact for Zip bomb " + file.getName() + " has incorrect type ID", artifact.getArtifactTypeID(), BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID()); BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME)); - assertNotNull("Possible Zip Bomb", attribute); + assertNotNull("No attribute found for artifact on zip bomb " + file.getName(), attribute); + assertEquals("Interesting artifact on file, " + file.getName() + ", does not reflect it being a zip bomb", zipBombSetName, attribute.getDisplayString()); zipBombs++; } } else {//No other files have artifact defined - assertEquals(0, file.getAllArtifacts().size()); + assertEquals("Unexpected file, " + file.getName() + ", has artifacts", 0, file.getAllArtifacts().size()); } } //Make sure 3 password protected zip files have been tested: password_protected.zip, level1_protected.zip and 42.zip that we download for bomb testing. - assertEquals(3, passwdProtectedZips); + assertEquals("Unexpected number of artifacts reflecting password protected zip files found", 3, passwdProtectedZips); //Make sure 2 zip bomb files have been tested: DepthTriggerZipBomb.zip and RatioTriggerZipBomb.zip. - assertEquals(2, zipBombs); + assertEquals("Unexpected number of artifacts reflecting zip bombs found", 2, zipBombs); } catch (TskCoreException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex); From 5238b6b5dd2527e7cf172cad06abba91084905d3 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Thu, 2 Aug 2018 17:50:26 -0400 Subject: [PATCH 08/21] Fixed dialog size. --- .../centralrepository/Bundle.properties | 2 - .../CentralRepoCommentDialog.form | 42 ++++--------------- .../CentralRepoCommentDialog.java | 26 ++---------- 3 files changed, 12 insertions(+), 58 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/Bundle.properties b/Core/src/org/sleuthkit/autopsy/centralrepository/Bundle.properties index 3223583037..1c7e6c2d7e 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/Bundle.properties @@ -5,8 +5,6 @@ OpenIDE-Module-Long-Description=\ Correlation Engine ingest module and central database. \n\n\ The Correlation Engine ingest module stores attributes of artifacts matching selected correlation types into a central database.\n\ Stored attributes are used in future cases to correlate and analyzes files and artifacts during ingest. -CentralRepoCommentDialog.fileLabel.text=File: CentralRepoCommentDialog.commentLabel.text=Comment: -CentralRepoCommentDialog.pathLabel.text= CentralRepoCommentDialog.okButton.text=&OK CentralRepoCommentDialog.cancelButton.text=C&ancel diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/CentralRepoCommentDialog.form b/Core/src/org/sleuthkit/autopsy/centralrepository/CentralRepoCommentDialog.form index 5a9882d4cf..8f471230d0 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/CentralRepoCommentDialog.form +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/CentralRepoCommentDialog.form @@ -31,14 +31,7 @@ - - - - - - - - + @@ -55,21 +48,16 @@ - - - - - - + - + - - - - + + + + - + @@ -113,20 +101,6 @@ - - - - - - - - - - - - - - diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/CentralRepoCommentDialog.java b/Core/src/org/sleuthkit/autopsy/centralrepository/CentralRepoCommentDialog.java index 529ffb8529..5325c0fc2f 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/CentralRepoCommentDialog.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/CentralRepoCommentDialog.java @@ -52,7 +52,6 @@ final class CentralRepoCommentDialog extends javax.swing.JDialog { currentComment = instance.getComment(); } - pathLabel.setText(instance.getFilePath()); commentTextArea.setText(instance.getComment()); this.correlationAttribute = correlationAttribute; @@ -103,8 +102,6 @@ final class CentralRepoCommentDialog extends javax.swing.JDialog { commentTextArea = new javax.swing.JTextArea(); okButton = new javax.swing.JButton(); cancelButton = new javax.swing.JButton(); - fileLabel = new javax.swing.JLabel(); - pathLabel = new javax.swing.JLabel(); commentLabel = new javax.swing.JLabel(); setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); @@ -131,10 +128,6 @@ final class CentralRepoCommentDialog extends javax.swing.JDialog { } }); - org.openide.awt.Mnemonics.setLocalizedText(fileLabel, org.openide.util.NbBundle.getMessage(CentralRepoCommentDialog.class, "CentralRepoCommentDialog.fileLabel.text")); // NOI18N - - org.openide.awt.Mnemonics.setLocalizedText(pathLabel, org.openide.util.NbBundle.getMessage(CentralRepoCommentDialog.class, "CentralRepoCommentDialog.pathLabel.text")); // NOI18N - org.openide.awt.Mnemonics.setLocalizedText(commentLabel, org.openide.util.NbBundle.getMessage(CentralRepoCommentDialog.class, "CentralRepoCommentDialog.commentLabel.text")); // NOI18N javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); @@ -146,12 +139,7 @@ final class CentralRepoCommentDialog extends javax.swing.JDialog { .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 500, Short.MAX_VALUE) .addGroup(layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addComponent(fileLabel) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(pathLabel)) - .addComponent(commentLabel)) + .addComponent(commentLabel) .addGap(0, 451, Short.MAX_VALUE)) .addGroup(layout.createSequentialGroup() .addGap(0, 0, Short.MAX_VALUE) @@ -164,17 +152,13 @@ final class CentralRepoCommentDialog extends javax.swing.JDialog { layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(fileLabel) - .addComponent(pathLabel)) - .addGap(19, 19, 19) .addComponent(commentLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jScrollPane1) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(okButton) - .addComponent(cancelButton)) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(cancelButton) + .addComponent(okButton)) .addContainerGap()) ); @@ -197,9 +181,7 @@ final class CentralRepoCommentDialog extends javax.swing.JDialog { private javax.swing.JButton cancelButton; private javax.swing.JLabel commentLabel; private javax.swing.JTextArea commentTextArea; - private javax.swing.JLabel fileLabel; private javax.swing.JScrollPane jScrollPane1; private javax.swing.JButton okButton; - private javax.swing.JLabel pathLabel; // End of variables declaration//GEN-END:variables } From 372ca76864d6d1fac73d3fa1f6e43fd9e26eacad Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 24 Jul 2018 14:52:53 -0400 Subject: [PATCH 09/21] 4065 initial implementation without refresh - minimal public api changes --- .../casemodule/services/TagsManager.java | 112 ++++++++++++++---- .../autopsy/core/UserPreferences.java | 17 ++- .../org/sleuthkit/autopsy/datamodel/Tags.java | 94 +++++++++------ .../autopsy/directorytree/Bundle.properties | 3 +- .../DirectoryTreeTopComponent.form | 19 ++- .../DirectoryTreeTopComponent.java | 22 +++- 6 files changed, 199 insertions(+), 68 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java index d80feed87a..786e461619 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java @@ -30,6 +30,7 @@ import java.util.logging.Level; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; +import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifactTag; @@ -71,13 +72,14 @@ public class TagsManager implements Closeable { || tagDisplayName.contains(";")); } + @NbBundle.Messages({"TagsManager.notableTagEnding.text= (Notable)"}) /** - * Get String of text which is used to label tags as notable to the user. - * + * Get String of text which is used to label tags as notable to the user. + * * @return Bundle message TagsManager.notableTagEnding.text */ - public static String getNotableTagLabel(){ + public static String getNotableTagLabel() { return Bundle.TagsManager_notableTagEnding_text(); } @@ -123,13 +125,13 @@ public class TagsManager implements Closeable { /** * Returns a list of names of standard/predefined tags - * + * * @return list of predefined tag names */ public static List getStandardTagNames() { return TagNameDefinition.getStandardTagNames(); } - + /** * Constructs a per case Autopsy service that manages the addition of * content and artifact tags to the case database. @@ -163,7 +165,26 @@ public class TagsManager implements Closeable { * @throws TskCoreException If there is an error querying the case database. */ public List getTagNamesInUse() throws TskCoreException { - return caseDb.getTagNamesInUse(); + if (UserPreferences.showOnlyCurrentUserTags()) { +// return caseDb.getTagNamesInUse(System.getProperty("user.name")); + Set tagNameSet = new HashSet<>(); + String userName = System.getProperty("user.name"); + List artifactTags = caseDb.getAllBlackboardArtifactTags(); + for (BlackboardArtifactTag tag : artifactTags) { + if (tag.getUserName().equals(userName)) { + tagNameSet.add(tag.getName()); + } + } + List contentTags = caseDb.getAllContentTags(); + for (ContentTag tag : contentTags) { + if (tag.getUserName().equals(userName)) { + tagNameSet.add(tag.getName()); + } + } + return new ArrayList(tagNameSet); + } else { + return caseDb.getTagNamesInUse(); + } } /** @@ -172,15 +193,35 @@ public class TagsManager implements Closeable { * blackboard_artifact_tags tables, for the given data source object id. * * @param dsObjId data source object id - * + * * @return A list, possibly empty, of TagName data transfer objects (DTOs) - * for the rows. + * for the rows. * * @throws TskCoreException */ public List getTagNamesInUse(long dsObjId) throws TskCoreException { - return caseDb.getTagNamesInUse(dsObjId); + if (UserPreferences.showOnlyCurrentUserTags()) { +// return caseDb.getTagNamesInUse(dsObjId, System.getProperty("user.name")); + Set tagNameSet = new HashSet<>(); + String userName = System.getProperty("user.name"); + List artifactTags = caseDb.getAllBlackboardArtifactTags(); + for (BlackboardArtifactTag tag : artifactTags) { + if (tag.getUserName().equals(userName) && tag.getArtifact().getDataSource().getId() == dsObjId) { + tagNameSet.add(tag.getName()); + } + } + List contentTags = caseDb.getAllContentTags(); + for (ContentTag tag : contentTags) { + if (tag.getUserName().equals(userName) && tag.getContent().getDataSource().getId() == dsObjId) { + tagNameSet.add(tag.getName()); + } + } + return new ArrayList(tagNameSet); + } else { + return caseDb.getTagNamesInUse(dsObjId); + } } + /** * Gets a map of tag display names to tag name entries in the case database. * It has keys for the display names of the standard tag types, the current @@ -413,27 +454,52 @@ public class TagsManager implements Closeable { * the case database. */ public long getContentTagsCountByTagName(TagName tagName) throws TskCoreException { - return caseDb.getContentTagsCountByTagName(tagName); + if (UserPreferences.showOnlyCurrentUserTags()) { + String userName = System.getProperty("user.name"); + long count = 0; + List contentTags = getContentTagsByTagName(tagName); + for (ContentTag tag : contentTags) { + if (userName.equals(tag.getUserName())) { + count++; + } + } + return count; + } else { + return caseDb.getContentTagsCountByTagName(tagName); + } } /** * Gets content tags count by tag name, for the given data source * * @param tagName The representation of the desired tag type in the case - * database, which can be obtained by calling getTagNames and/or addTagName. - * + * database, which can be obtained by calling getTagNames + * and/or addTagName. + * * @param dsObjId data source object id * * @return A count of the content tags with the specified tag name, and for - * the given data source + * the given data source * * @throws TskCoreException If there is an error getting the tags count from - * the case database. + * the case database. */ public long getContentTagsCountByTagName(TagName tagName, long dsObjId) throws TskCoreException { - return caseDb.getContentTagsCountByTagName(tagName, dsObjId); + if (UserPreferences.showOnlyCurrentUserTags()) { + String userName = System.getProperty("user.name"); + long count = 0; + List contentTags = getContentTagsByTagName(tagName, dsObjId); + for (ContentTag tag : contentTags) { + if (userName.equals(tag.getUserName())) { + count++; + } + } + return count; + } else { + return caseDb.getContentTagsCountByTagName(tagName, dsObjId); + } } - + /** * Gets a content tag by tag id. * @@ -463,11 +529,11 @@ public class TagsManager implements Closeable { return caseDb.getContentTagsByTagName(tagName); } - /** + /** * Gets content tags by tag name, for the given data source. * * @param tagName The tag name of interest. - * + * * @param dsObjId data source object id * * @return A list, possibly empty, of the content tags with the specified @@ -479,7 +545,7 @@ public class TagsManager implements Closeable { public List getContentTagsByTagName(TagName tagName, long dsObjId) throws TskCoreException { return caseDb.getContentTagsByTagName(tagName, dsObjId); } - + /** * Gets content tags count by content. * @@ -589,8 +655,8 @@ public class TagsManager implements Closeable { * and/or addTagName. * @param dsObjId data source object id * - * @return A count of the artifact tags with the specified tag name, - * for the given data source. + * @return A count of the artifact tags with the specified tag name, for the + * given data source. * * @throws TskCoreException If there is an error getting the tags count from * the case database. @@ -598,7 +664,7 @@ public class TagsManager implements Closeable { public long getBlackboardArtifactTagsCountByTagName(TagName tagName, long dsObjId) throws TskCoreException { return caseDb.getBlackboardArtifactTagsCountByTagName(tagName, dsObjId); } - + /** * Gets an artifact tag by tag id. * @@ -647,7 +713,7 @@ public class TagsManager implements Closeable { public List getBlackboardArtifactTagsByTagName(TagName tagName, long dsObjId) throws TskCoreException { return caseDb.getBlackboardArtifactTagsByTagName(tagName, dsObjId); } - + /** * Gets artifact tags for a particular artifact. * diff --git a/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java b/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java index 22fa2b7135..9869001067 100644 --- a/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java +++ b/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java @@ -70,7 +70,8 @@ public final class UserPreferences { private static final String MAX_NUM_OF_LOG_FILE = "MaximumNumberOfLogFiles"; private static final int LOG_FILE_NUM_INT = 10; public static final String GROUP_ITEMS_IN_TREE_BY_DATASOURCE = "GroupItemsInTreeByDataSource"; //NON-NLS - + private static final String SHOW_ONLY_CURRENT_USER_TAGS = "ShowOnlyCurrentUserTags"; + // Prevent instantiation. private UserPreferences() { } @@ -196,6 +197,14 @@ public final class UserPreferences { preferences.putBoolean(GROUP_ITEMS_IN_TREE_BY_DATASOURCE, value); } + public static boolean showOnlyCurrentUserTags() { + return preferences.getBoolean(SHOW_ONLY_CURRENT_USER_TAGS, false); + } + + public static void setShowOnlyCurrentUserTags(boolean value) { + preferences.putBoolean(SHOW_ONLY_CURRENT_USER_TAGS, value); + } + /** * Reads persisted case database connection info. * @@ -379,21 +388,25 @@ public final class UserPreferences { /** * get the maximum number of log files to save + * * @return Number of log files */ public static int getLogFileCount() { return preferences.getInt(MAX_NUM_OF_LOG_FILE, LOG_FILE_NUM_INT); } - + /** * get the default number of log files to save + * * @return LOG_FILE_COUNT */ public static int getDefaultLogFileCount() { return LOG_FILE_NUM_INT; } + /** * Set the maximum number of log files to save + * * @param count number of log files */ public static void setLogFileCount(int count) { diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java index c41a750f7e..643f3ecda6 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java @@ -1,15 +1,15 @@ /* * Autopsy Forensic Browser - * + * * Copyright 2011-2018 Basis Technology Corp. * Contact: carrier sleuthkit org - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -59,19 +59,19 @@ public class Tags implements AutopsyVisitableItem { private final String ICON_PATH = "org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png"; //NON-NLS private final long datasourceObjId; - + Tags() { - this(0); + this(0); } - + Tags(long dsObjId) { this.datasourceObjId = dsObjId; } - + long filteringDataSourceObjId() { return this.datasourceObjId; } - + @Override public T accept(AutopsyItemVisitor visitor) { return visitor.visit(this); @@ -98,13 +98,12 @@ public class Tags implements AutopsyVisitableItem { */ public class RootNode extends DisplayableItemNode { - public RootNode(long objId) { super(Children.create(new TagNameNodeFactory(objId), true), Lookups.singleton(DISPLAY_NAME)); super.setName(DISPLAY_NAME); super.setDisplayName(DISPLAY_NAME); this.setIconBaseWithExtension(ICON_PATH); - + } @Override @@ -139,7 +138,7 @@ public class Tags implements AutopsyVisitableItem { private class TagNameNodeFactory extends ChildFactory.Detachable implements Observer { private final long datasourceObjId; - + private final Set CASE_EVENTS_OF_INTEREST = EnumSet.of(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED, Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED, Case.Events.CONTENT_TAG_ADDED, @@ -197,13 +196,14 @@ public class Tags implements AutopsyVisitableItem { /** * Constructor + * * @param objId data source object id */ TagNameNodeFactory(long objId) { this.datasourceObjId = objId; - + } - + @Override protected void addNotify() { IngestManager.getInstance().addIngestJobEventListener(pcl); @@ -224,11 +224,10 @@ public class Tags implements AutopsyVisitableItem { @Override protected boolean createKeys(List keys) { try { - - List tagNamesInUse = UserPreferences.groupItemsInTreeByDatasource() ? - Case.getCurrentCaseThrows().getServices().getTagsManager().getTagNamesInUse(datasourceObjId) : - Case.getCurrentCaseThrows().getServices().getTagsManager().getTagNamesInUse() - ; + + List tagNamesInUse = UserPreferences.groupItemsInTreeByDatasource() + ? Case.getCurrentCaseThrows().getServices().getTagsManager().getTagNamesInUse(datasourceObjId) + : Case.getCurrentCaseThrows().getServices().getTagsManager().getTagNamesInUse(); Collections.sort(tagNamesInUse); keys.addAll(tagNamesInUse); } catch (TskCoreException | NoCurrentCaseException ex) { @@ -277,14 +276,13 @@ public class Tags implements AutopsyVisitableItem { try { TagsManager tm = Case.getCurrentCaseThrows().getServices().getTagsManager(); if (UserPreferences.groupItemsInTreeByDatasource()) { - tagsCount = tm.getContentTagsCountByTagName(tagName, datasourceObjId); + tagsCount = tm.getContentTagsCountByTagName(tagName, datasourceObjId); tagsCount += tm.getBlackboardArtifactTagsCountByTagName(tagName, datasourceObjId); - } - else { + } else { tagsCount = tm.getContentTagsCountByTagName(tagName); tagsCount += tm.getBlackboardArtifactTagsCountByTagName(tagName); } - + } catch (TskCoreException | NoCurrentCaseException ex) { Logger.getLogger(TagNameNode.class.getName()).log(Level.SEVERE, "Failed to get tags count for " + tagName.getDisplayName() + " tag name", ex); //NON-NLS } @@ -387,9 +385,9 @@ public class Tags implements AutopsyVisitableItem { private void updateDisplayName() { long tagsCount = 0; try { - tagsCount = UserPreferences.groupItemsInTreeByDatasource() ? - Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsCountByTagName(tagName, datasourceObjId) : - Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsCountByTagName(tagName); + tagsCount = UserPreferences.groupItemsInTreeByDatasource() + ? Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsCountByTagName(tagName, datasourceObjId) + : Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsCountByTagName(tagName); } catch (TskCoreException | NoCurrentCaseException ex) { Logger.getLogger(ContentTagTypeNode.class.getName()).log(Level.SEVERE, "Failed to get content tags count for " + tagName.getDisplayName() + " tag name", ex); //NON-NLS } @@ -444,11 +442,20 @@ public class Tags implements AutopsyVisitableItem { protected boolean createKeys(List keys) { // Use the content tags bearing the specified tag name as the keys. try { - List contentTags = UserPreferences.groupItemsInTreeByDatasource() ? - Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsByTagName(tagName, datasourceObjId) : - Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsByTagName(tagName); - - keys.addAll(contentTags); + List contentTags = UserPreferences.groupItemsInTreeByDatasource() + ? Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsByTagName(tagName, datasourceObjId) + : Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsByTagName(tagName); + if (UserPreferences.showOnlyCurrentUserTags()) { + String userName = System.getProperty("user.name"); + for (ContentTag tag : contentTags){ + if (userName.equals(tag.getUserName())){ + keys.add(tag); + } + } + } + else { + keys.addAll(contentTags); + } } catch (TskCoreException | NoCurrentCaseException ex) { Logger.getLogger(ContentTagNodeFactory.class.getName()).log(Level.SEVERE, "Failed to get tag names", ex); //NON-NLS } @@ -479,6 +486,7 @@ public class Tags implements AutopsyVisitableItem { private final TagName tagName; private final String ICON_PATH = "org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png"; //NON-NLS + private int displayCount = 0; public BlackboardArtifactTagTypeNode(TagName tagName) { super(Children.create(new BlackboardArtifactTagNodeFactory(tagName), true), Lookups.singleton(tagName.getDisplayName() + " " + ARTIFACT_DISPLAY_NAME)); @@ -492,9 +500,9 @@ public class Tags implements AutopsyVisitableItem { private void updateDisplayName() { long tagsCount = 0; try { - tagsCount = UserPreferences.groupItemsInTreeByDatasource() ? - Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsCountByTagName(tagName, datasourceObjId) : - Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsCountByTagName(tagName); + tagsCount = UserPreferences.groupItemsInTreeByDatasource() + ? Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsCountByTagName(tagName, datasourceObjId) + : Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsCountByTagName(tagName); } catch (TskCoreException | NoCurrentCaseException ex) { Logger.getLogger(BlackboardArtifactTagTypeNode.class.getName()).log(Level.SEVERE, "Failed to get blackboard artifact tags count for " + tagName.getDisplayName() + " tag name", ex); //NON-NLS } @@ -549,10 +557,20 @@ public class Tags implements AutopsyVisitableItem { protected boolean createKeys(List keys) { try { // Use the blackboard artifact tags bearing the specified tag name as the keys. - List artifactTags = UserPreferences.groupItemsInTreeByDatasource() ? - Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsByTagName(tagName, datasourceObjId) : - Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsByTagName(tagName); - keys.addAll(artifactTags); + List artifactTags = UserPreferences.groupItemsInTreeByDatasource() + ? Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsByTagName(tagName, datasourceObjId) + : Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsByTagName(tagName); + if (UserPreferences.showOnlyCurrentUserTags()) { + String userName = System.getProperty("user.name"); + for (BlackboardArtifactTag tag : artifactTags){ + if (userName.equals(tag.getUserName())){ + keys.add(tag); + } + } + } + else { + keys.addAll(artifactTags); + } } catch (TskCoreException | NoCurrentCaseException ex) { Logger.getLogger(BlackboardArtifactTagNodeFactory.class.getName()).log(Level.SEVERE, "Failed to get tag names", ex); //NON-NLS } diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/Bundle.properties b/Core/src/org/sleuthkit/autopsy/directorytree/Bundle.properties index 926c4b4626..24818139af 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/directorytree/Bundle.properties @@ -124,4 +124,5 @@ GroupDataSourcesDialog.dataSourceCountLabel.text=jLabel1 GroupDataSourcesDialog.queryLabel.text=Would you like to group by data source for faster loading? GroupDataSourcesDialog.yesButton.text=Yes GroupDataSourcesDialog.noButton.text=No -GroupDataSourcesDialog.title=Group by Data Source? \ No newline at end of file +GroupDataSourcesDialog.title=Group by Data Source? +DirectoryTreeTopComponent.showOnlyCurrentUserTagsCheckbox.text=X diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.form b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.form index 732e34c20b..6ca508789c 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.form +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.form @@ -21,7 +21,9 @@ - + + + @@ -36,7 +38,10 @@ - + + + + @@ -151,5 +156,15 @@ + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java index fb9ded33e2..b20a71db5c 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java @@ -137,6 +137,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat forwardButton.setEnabled(false); groupByDatasourceCheckBox.setSelected(UserPreferences.groupItemsInTreeByDatasource()); + showOnlyCurrentUserTagsCheckbox.setSelected(UserPreferences.showOnlyCurrentUserTags()); } /** @@ -191,6 +192,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat forwardButton = new javax.swing.JButton(); showRejectedCheckBox = new javax.swing.JCheckBox(); groupByDatasourceCheckBox = new javax.swing.JCheckBox(); + showOnlyCurrentUserTagsCheckbox = new javax.swing.JCheckBox(); treeView.setBorder(null); @@ -235,6 +237,13 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat } }); + org.openide.awt.Mnemonics.setLocalizedText(showOnlyCurrentUserTagsCheckbox, org.openide.util.NbBundle.getMessage(DirectoryTreeTopComponent.class, "DirectoryTreeTopComponent.showOnlyCurrentUserTagsCheckbox.text")); // NOI18N + showOnlyCurrentUserTagsCheckbox.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + showOnlyCurrentUserTagsCheckboxActionPerformed(evt); + } + }); + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( @@ -244,7 +253,9 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat .addComponent(backButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(forwardButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 51, Short.MAX_VALUE) + .addGap(18, 18, 18) + .addComponent(showOnlyCurrentUserTagsCheckbox, javax.swing.GroupLayout.DEFAULT_SIZE, 33, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(showRejectedCheckBox) .addComponent(groupByDatasourceCheckBox)) @@ -256,7 +267,9 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addGap(5, 5, 5) - .addComponent(showRejectedCheckBox) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(showRejectedCheckBox) + .addComponent(showOnlyCurrentUserTagsCheckbox)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(groupByDatasourceCheckBox)) .addGroup(layout.createSequentialGroup() @@ -323,10 +336,15 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat UserPreferences.setGroupItemsInTreeByDatasource(this.groupByDatasourceCheckBox.isSelected()); }//GEN-LAST:event_groupByDatasourceCheckBoxActionPerformed + private void showOnlyCurrentUserTagsCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_showOnlyCurrentUserTagsCheckboxActionPerformed + UserPreferences.setShowOnlyCurrentUserTags(this.showOnlyCurrentUserTagsCheckbox.isSelected()); + }//GEN-LAST:event_showOnlyCurrentUserTagsCheckboxActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton backButton; private javax.swing.JButton forwardButton; private javax.swing.JCheckBox groupByDatasourceCheckBox; + private javax.swing.JCheckBox showOnlyCurrentUserTagsCheckbox; private javax.swing.JCheckBox showRejectedCheckBox; private javax.swing.JScrollPane treeView; // End of variables declaration//GEN-END:variables From 75fed47b97b0d910fa96d051b193eea557acda93 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 24 Jul 2018 16:49:34 -0400 Subject: [PATCH 10/21] 4065 resolve conflict in DirectorTreeTopComponent with develop --- Core/src/org/sleuthkit/autopsy/core/UserPreferences.java | 2 +- Core/src/org/sleuthkit/autopsy/datamodel/Tags.java | 6 +++++- .../autopsy/directorytree/DirectoryTreeTopComponent.java | 8 ++++++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java b/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java index 9869001067..970ca9f0b0 100644 --- a/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java +++ b/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java @@ -70,7 +70,7 @@ public final class UserPreferences { private static final String MAX_NUM_OF_LOG_FILE = "MaximumNumberOfLogFiles"; private static final int LOG_FILE_NUM_INT = 10; public static final String GROUP_ITEMS_IN_TREE_BY_DATASOURCE = "GroupItemsInTreeByDataSource"; //NON-NLS - private static final String SHOW_ONLY_CURRENT_USER_TAGS = "ShowOnlyCurrentUserTags"; + public static final String SHOW_ONLY_CURRENT_USER_TAGS = "ShowOnlyCurrentUserTags"; // Prevent instantiation. private UserPreferences() { diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java index 643f3ecda6..b70e88957b 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java @@ -103,7 +103,6 @@ public class Tags implements AutopsyVisitableItem { super.setName(DISPLAY_NAME); super.setDisplayName(DISPLAY_NAME); this.setIconBaseWithExtension(ICON_PATH); - } @Override @@ -133,6 +132,11 @@ public class Tags implements AutopsyVisitableItem { public String getItemType() { return getClass().getName(); } + + public void refresh(){ + tagResults.update(); + } + } private class TagNameNodeFactory extends ChildFactory.Detachable implements Observer { diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java index b20a71db5c..83038c5421 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java @@ -81,6 +81,7 @@ import org.sleuthkit.autopsy.datamodel.InterestingHits; import org.sleuthkit.autopsy.datamodel.KeywordHits; import org.sleuthkit.autopsy.datamodel.ResultsNode; import org.sleuthkit.autopsy.datamodel.AutopsyTreeChildFactory; +import org.sleuthkit.autopsy.datamodel.Tags; import org.sleuthkit.autopsy.datamodel.ViewsNode; import org.sleuthkit.autopsy.datamodel.accounts.Accounts; import org.sleuthkit.autopsy.datamodel.accounts.BINRange; @@ -153,6 +154,9 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat case UserPreferences.GROUP_ITEMS_IN_TREE_BY_DATASOURCE: refreshContentTreeSafe(); break; + case UserPreferences.SHOW_ONLY_CURRENT_USER_TAGS: + refreshTagsTree(); + break; case UserPreferences.HIDE_KNOWN_FILES_IN_VIEWS_TREE: case UserPreferences.HIDE_SLACK_FILES_IN_VIEWS_TREE: // TODO: Need a way to refresh the Views subtree @@ -908,6 +912,10 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat SwingUtilities.invokeLater(this::rebuildTree); } + private void refreshTagsTree() { + ((Tags.RootNode)autopsyTreeChildren.findChild("Tags")).refresh(); + } + /** * Rebuilds the autopsy tree. * From b86307de6044b9704b97351ba0ccbce1b1bbd3bd Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 24 Jul 2018 18:24:27 -0400 Subject: [PATCH 11/21] 4065 continued conflict resolution while cherry-picking --- .../sleuthkit/autopsy/casemodule/Case.java | 9 ++++- .../events/TagTreeRefreshEvent.java | 27 +++++++++++++++ .../casemodule/services/TagsManager.java | 28 +++++++++++++-- .../org/sleuthkit/autopsy/datamodel/Tags.java | 34 ++++++++----------- .../DirectoryTreeTopComponent.java | 14 +++++++- 5 files changed, 89 insertions(+), 23 deletions(-) create mode 100644 Core/src/org/sleuthkit/autopsy/casemodule/events/TagTreeRefreshEvent.java diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index 9019ae162d..92789c6998 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -75,6 +75,7 @@ import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent; import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent; import org.sleuthkit.autopsy.casemodule.events.DataSourceAddedEvent; import org.sleuthkit.autopsy.casemodule.events.ReportAddedEvent; +import org.sleuthkit.autopsy.casemodule.events.TagTreeRefreshEvent; import org.sleuthkit.autopsy.casemodule.services.Services; import org.sleuthkit.autopsy.commonfilesearch.CommonFilesSearchAction; import org.sleuthkit.autopsy.communications.OpenCommVisualizationToolAction; @@ -372,7 +373,9 @@ public class Case { * old value of the PropertyChangeEvent is the display name of the tag * definition that has changed. */ - TAG_DEFINITION_CHANGED; + TAG_DEFINITION_CHANGED, + + REFRESH_TAG_TREE; }; @@ -1510,6 +1513,10 @@ public class Case { eventPublisher.publish(new ContentTagAddedEvent(newTag)); } + public void notifyTagsTreeRefresh(){ + eventPublisher.publish(new TagTreeRefreshEvent()); + } + /** * Notifies case event subscribers that a content tag has been deleted. * diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/events/TagTreeRefreshEvent.java b/Core/src/org/sleuthkit/autopsy/casemodule/events/TagTreeRefreshEvent.java new file mode 100644 index 0000000000..ce3640d267 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/events/TagTreeRefreshEvent.java @@ -0,0 +1,27 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.sleuthkit.autopsy.casemodule.events; + +import java.io.Serializable; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.events.AutopsyEvent; + +/** + * + * @author wschaefer + */ +public class TagTreeRefreshEvent extends AutopsyEvent implements Serializable{ + + private static final long serialVersionUID = 1L; + + public TagTreeRefreshEvent(){ + this(Case.Events.REFRESH_TAG_TREE.toString(), true, false); + } + private TagTreeRefreshEvent(String eventName, Object oldValue, Object newValue) { + super(eventName, oldValue, newValue); + } + +} diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java index 786e461619..772dd8afe2 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java @@ -644,7 +644,19 @@ public class TagsManager implements Closeable { * the case database. */ public long getBlackboardArtifactTagsCountByTagName(TagName tagName) throws TskCoreException { - return caseDb.getBlackboardArtifactTagsCountByTagName(tagName); + if (UserPreferences.showOnlyCurrentUserTags()) { + String userName = System.getProperty("user.name"); + long count = 0; + List artifactTags = getBlackboardArtifactTagsByTagName(tagName); + for (BlackboardArtifactTag tag : artifactTags) { + if (userName.equals(tag.getUserName())) { + count++; + } + } + return count; + } else { + return caseDb.getBlackboardArtifactTagsCountByTagName(tagName); + } } /** @@ -662,7 +674,19 @@ public class TagsManager implements Closeable { * the case database. */ public long getBlackboardArtifactTagsCountByTagName(TagName tagName, long dsObjId) throws TskCoreException { - return caseDb.getBlackboardArtifactTagsCountByTagName(tagName, dsObjId); + if (UserPreferences.showOnlyCurrentUserTags()) { + String userName = System.getProperty("user.name"); + long count = 0; + List artifactTags = getBlackboardArtifactTagsByTagName(tagName, dsObjId); + for (BlackboardArtifactTag tag : artifactTags) { + if (userName.equals(tag.getUserName())) { + count++; + } + } + return count; + } else { + return caseDb.getBlackboardArtifactTagsCountByTagName(tagName, dsObjId); + } } /** diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java index b70e88957b..0bb3eedde3 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java @@ -132,11 +132,7 @@ public class Tags implements AutopsyVisitableItem { public String getItemType() { return getClass().getName(); } - - public void refresh(){ - tagResults.update(); - } - + } private class TagNameNodeFactory extends ChildFactory.Detachable implements Observer { @@ -147,7 +143,8 @@ public class Tags implements AutopsyVisitableItem { Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED, Case.Events.CONTENT_TAG_ADDED, Case.Events.CONTENT_TAG_DELETED, - Case.Events.CURRENT_CASE); + Case.Events.CURRENT_CASE, + Case.Events.REFRESH_TAG_TREE); private final PropertyChangeListener pcl = new PropertyChangeListener() { @Override @@ -156,7 +153,8 @@ public class Tags implements AutopsyVisitableItem { if (eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED.toString()) || eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED.toString()) || eventType.equals(Case.Events.CONTENT_TAG_ADDED.toString()) - || eventType.equals(Case.Events.CONTENT_TAG_DELETED.toString())) { + || eventType.equals(Case.Events.CONTENT_TAG_DELETED.toString()) + || eventType.equals(Case.Events.REFRESH_TAG_TREE.toString())) { /** * Checking for a current case is a stop gap measure until a * different way of handling the closing of cases is worked @@ -451,14 +449,13 @@ public class Tags implements AutopsyVisitableItem { : Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsByTagName(tagName); if (UserPreferences.showOnlyCurrentUserTags()) { String userName = System.getProperty("user.name"); - for (ContentTag tag : contentTags){ - if (userName.equals(tag.getUserName())){ + for (ContentTag tag : contentTags) { + if (userName.equals(tag.getUserName())) { keys.add(tag); - } + } } - } - else { - keys.addAll(contentTags); + } else { + keys.addAll(contentTags); } } catch (TskCoreException | NoCurrentCaseException ex) { Logger.getLogger(ContentTagNodeFactory.class.getName()).log(Level.SEVERE, "Failed to get tag names", ex); //NON-NLS @@ -566,14 +563,13 @@ public class Tags implements AutopsyVisitableItem { : Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsByTagName(tagName); if (UserPreferences.showOnlyCurrentUserTags()) { String userName = System.getProperty("user.name"); - for (BlackboardArtifactTag tag : artifactTags){ - if (userName.equals(tag.getUserName())){ + for (BlackboardArtifactTag tag : artifactTags) { + if (userName.equals(tag.getUserName())) { keys.add(tag); - } + } } - } - else { - keys.addAll(artifactTags); + } else { + keys.addAll(artifactTags); } } catch (TskCoreException | NoCurrentCaseException ex) { Logger.getLogger(BlackboardArtifactTagNodeFactory.class.getName()).log(Level.SEVERE, "Failed to get tag names", ex); //NON-NLS diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java index 83038c5421..4305278446 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java @@ -913,7 +913,19 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat } private void refreshTagsTree() { - ((Tags.RootNode)autopsyTreeChildren.findChild("Tags")).refresh(); + SwingUtilities.invokeLater(() -> { + // if no open case or has no data then there is no tree to rebuild + Case currentCase; + try { + currentCase = Case.getCurrentCaseThrows(); + } catch (NoCurrentCaseException ex) { + return; + } + if (null == currentCase || currentCase.hasData() == false) { + return; + } + currentCase.notifyTagsTreeRefresh(); + }); } /** From 5a50721b3331f4419ba7ae1ff5edd6b105ffd174 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 25 Jul 2018 12:57:35 -0400 Subject: [PATCH 12/21] 4065 continued conflict resolution while cherry-picking --- .../sleuthkit/autopsy/casemodule/Case.java | 4 +-- .../events/TagTreeRefreshEvent.java | 27 ------------------- .../org/sleuthkit/autopsy/datamodel/Tags.java | 10 ++++--- .../autopsy/directorytree/Bundle.properties | 2 +- .../DirectoryTreeTopComponent.form | 2 +- .../DirectoryTreeTopComponent.java | 15 +++-------- 6 files changed, 12 insertions(+), 48 deletions(-) delete mode 100644 Core/src/org/sleuthkit/autopsy/casemodule/events/TagTreeRefreshEvent.java diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index 92789c6998..f40fed2143 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -373,9 +373,7 @@ public class Case { * old value of the PropertyChangeEvent is the display name of the tag * definition that has changed. */ - TAG_DEFINITION_CHANGED, - - REFRESH_TAG_TREE; + TAG_DEFINITION_CHANGED; }; diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/events/TagTreeRefreshEvent.java b/Core/src/org/sleuthkit/autopsy/casemodule/events/TagTreeRefreshEvent.java deleted file mode 100644 index ce3640d267..0000000000 --- a/Core/src/org/sleuthkit/autopsy/casemodule/events/TagTreeRefreshEvent.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.sleuthkit.autopsy.casemodule.events; - -import java.io.Serializable; -import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.events.AutopsyEvent; - -/** - * - * @author wschaefer - */ -public class TagTreeRefreshEvent extends AutopsyEvent implements Serializable{ - - private static final long serialVersionUID = 1L; - - public TagTreeRefreshEvent(){ - this(Case.Events.REFRESH_TAG_TREE.toString(), true, false); - } - private TagTreeRefreshEvent(String eventName, Object oldValue, Object newValue) { - super(eventName, oldValue, newValue); - } - -} diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java index 0bb3eedde3..cac9306a14 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java @@ -132,6 +132,10 @@ public class Tags implements AutopsyVisitableItem { public String getItemType() { return getClass().getName(); } + + public void refresh(){ + tagResults.update(); + } } @@ -143,8 +147,7 @@ public class Tags implements AutopsyVisitableItem { Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED, Case.Events.CONTENT_TAG_ADDED, Case.Events.CONTENT_TAG_DELETED, - Case.Events.CURRENT_CASE, - Case.Events.REFRESH_TAG_TREE); + Case.Events.CURRENT_CASE); private final PropertyChangeListener pcl = new PropertyChangeListener() { @Override @@ -153,8 +156,7 @@ public class Tags implements AutopsyVisitableItem { if (eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED.toString()) || eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED.toString()) || eventType.equals(Case.Events.CONTENT_TAG_ADDED.toString()) - || eventType.equals(Case.Events.CONTENT_TAG_DELETED.toString()) - || eventType.equals(Case.Events.REFRESH_TAG_TREE.toString())) { + || eventType.equals(Case.Events.CONTENT_TAG_DELETED.toString())) { /** * Checking for a current case is a stop gap measure until a * different way of handling the closing of cases is worked diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/Bundle.properties b/Core/src/org/sleuthkit/autopsy/directorytree/Bundle.properties index 24818139af..b90711b8d9 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/directorytree/Bundle.properties @@ -125,4 +125,4 @@ GroupDataSourcesDialog.queryLabel.text=Would you like to group by data source fo GroupDataSourcesDialog.yesButton.text=Yes GroupDataSourcesDialog.noButton.text=No GroupDataSourcesDialog.title=Group by Data Source? -DirectoryTreeTopComponent.showOnlyCurrentUserTagsCheckbox.text=X +DirectoryTreeTopComponent.showOnlyCurrentUserTagsCheckbox.text=Hide Other User's Tags diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.form b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.form index 6ca508789c..8fa8265e06 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.form +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.form @@ -22,7 +22,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java index 4305278446..71fd0c5a2d 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java @@ -258,7 +258,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(forwardButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(18, 18, 18) - .addComponent(showOnlyCurrentUserTagsCheckbox, javax.swing.GroupLayout.DEFAULT_SIZE, 33, Short.MAX_VALUE) + .addComponent(showOnlyCurrentUserTagsCheckbox, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(showRejectedCheckBox) @@ -914,17 +914,8 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat private void refreshTagsTree() { SwingUtilities.invokeLater(() -> { - // if no open case or has no data then there is no tree to rebuild - Case currentCase; - try { - currentCase = Case.getCurrentCaseThrows(); - } catch (NoCurrentCaseException ex) { - return; - } - if (null == currentCase || currentCase.hasData() == false) { - return; - } - currentCase.notifyTagsTreeRefresh(); + // if no open case or has no data then there is no tree to rebuild + ((Tags.RootNode) autopsyTreeChildren.findChild("Tags")).refresh(); }); } From 764c3e4a06b49056b1e1952654f22afcadae003d Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 25 Jul 2018 13:21:01 -0400 Subject: [PATCH 13/21] 4065 finish removal of tag refresh event --- Core/src/org/sleuthkit/autopsy/casemodule/Case.java | 7 +------ .../sleuthkit/autopsy/casemodule/services/TagsManager.java | 4 ++-- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index f40fed2143..0d2556c438 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -75,7 +75,6 @@ import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent; import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent; import org.sleuthkit.autopsy.casemodule.events.DataSourceAddedEvent; import org.sleuthkit.autopsy.casemodule.events.ReportAddedEvent; -import org.sleuthkit.autopsy.casemodule.events.TagTreeRefreshEvent; import org.sleuthkit.autopsy.casemodule.services.Services; import org.sleuthkit.autopsy.commonfilesearch.CommonFilesSearchAction; import org.sleuthkit.autopsy.communications.OpenCommVisualizationToolAction; @@ -1510,11 +1509,7 @@ public class Case { public void notifyContentTagAdded(ContentTag newTag) { eventPublisher.publish(new ContentTagAddedEvent(newTag)); } - - public void notifyTagsTreeRefresh(){ - eventPublisher.publish(new TagTreeRefreshEvent()); - } - + /** * Notifies case event subscribers that a content tag has been deleted. * diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java index 772dd8afe2..cae9aa0308 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java @@ -181,7 +181,7 @@ public class TagsManager implements Closeable { tagNameSet.add(tag.getName()); } } - return new ArrayList(tagNameSet); + return new ArrayList(tagNameSet); } else { return caseDb.getTagNamesInUse(); } @@ -216,7 +216,7 @@ public class TagsManager implements Closeable { tagNameSet.add(tag.getName()); } } - return new ArrayList(tagNameSet); + return new ArrayList(tagNameSet); } else { return caseDb.getTagNamesInUse(dsObjId); } From f772010fc2b3eea3d720c7762c8f318e3b57447d Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 25 Jul 2018 14:46:40 -0400 Subject: [PATCH 14/21] 4065 fix non event refresh for group by data source --- .../casemodule/services/TagsManager.java | 4 ++-- .../DirectoryTreeTopComponent.java | 17 +++++++++++++++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java index cae9aa0308..aacad1ce7a 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java @@ -181,7 +181,7 @@ public class TagsManager implements Closeable { tagNameSet.add(tag.getName()); } } - return new ArrayList(tagNameSet); + return new ArrayList<>(tagNameSet); } else { return caseDb.getTagNamesInUse(); } @@ -216,7 +216,7 @@ public class TagsManager implements Closeable { tagNameSet.add(tag.getName()); } } - return new ArrayList(tagNameSet); + return new ArrayList<>(tagNameSet); } else { return caseDb.getTagNamesInUse(dsObjId); } diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java index 71fd0c5a2d..51133e76b3 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java @@ -914,8 +914,21 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat private void refreshTagsTree() { SwingUtilities.invokeLater(() -> { - // if no open case or has no data then there is no tree to rebuild - ((Tags.RootNode) autopsyTreeChildren.findChild("Tags")).refresh(); + // if no open case or has no data then there is no tree to rebuild + if (UserPreferences.groupItemsInTreeByDatasource()) { + for (Node dataSource : autopsyTreeChildren.getNodes()) { + Node tagsNode = dataSource.getChildren().findChild("Tags"); + if (tagsNode != null) { + //Reports is at the same level as the data sources so we want to ignore it + ((Tags.RootNode)tagsNode).refresh(); + } + } + } else { + Node tagsNode = autopsyTreeChildren.findChild("Tags"); + if (tagsNode != null) { + ((Tags.RootNode)tagsNode).refresh(); + } + } }); } From efbd58fd34bb273351ebe9fbaa44dfeb6f366781 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 25 Jul 2018 15:05:36 -0400 Subject: [PATCH 15/21] 4065 replace static text with text from bundle message --- Core/src/org/sleuthkit/autopsy/datamodel/Tags.java | 6 +++++- .../autopsy/directorytree/DirectoryTreeTopComponent.java | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java index cac9306a14..97af746282 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java @@ -55,7 +55,7 @@ public class Tags implements AutopsyVisitableItem { // override of Children.Keys.createNodes(). private final TagResults tagResults = new TagResults(); - private final String DISPLAY_NAME = NbBundle.getMessage(RootNode.class, "TagsNode.displayName.text"); + private final static String DISPLAY_NAME = NbBundle.getMessage(RootNode.class, "TagsNode.displayName.text"); private final String ICON_PATH = "org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png"; //NON-NLS private final long datasourceObjId; @@ -68,6 +68,10 @@ public class Tags implements AutopsyVisitableItem { this.datasourceObjId = dsObjId; } + public static String getTagsDisplayName(){ + return DISPLAY_NAME; + } + long filteringDataSourceObjId() { return this.datasourceObjId; } diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java index 51133e76b3..469a3c62dd 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java @@ -917,14 +917,14 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat // if no open case or has no data then there is no tree to rebuild if (UserPreferences.groupItemsInTreeByDatasource()) { for (Node dataSource : autopsyTreeChildren.getNodes()) { - Node tagsNode = dataSource.getChildren().findChild("Tags"); + Node tagsNode = dataSource.getChildren().findChild(Tags.getTagsDisplayName()); if (tagsNode != null) { //Reports is at the same level as the data sources so we want to ignore it ((Tags.RootNode)tagsNode).refresh(); } } } else { - Node tagsNode = autopsyTreeChildren.findChild("Tags"); + Node tagsNode = autopsyTreeChildren.findChild(Tags.getTagsDisplayName()); if (tagsNode != null) { ((Tags.RootNode)tagsNode).refresh(); } From 6baf076f98212aaba22f1da01ba467e7a22f7709 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Thu, 26 Jul 2018 17:27:41 -0400 Subject: [PATCH 16/21] 4065 clean up and comments for hiding tags other than the current users --- .../org/sleuthkit/autopsy/casemodule/Case.java | 2 +- .../casemodule/services/TagsManager.java | 16 +++++++--------- .../autopsy/core/UserPreferences.java | 13 +++++++++++++ .../org/sleuthkit/autopsy/datamodel/Tags.java | 18 +++++++++++++----- .../DirectoryTreeTopComponent.java | 3 +++ 5 files changed, 37 insertions(+), 15 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index 0d2556c438..9019ae162d 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -1509,7 +1509,7 @@ public class Case { public void notifyContentTagAdded(ContentTag newTag) { eventPublisher.publish(new ContentTagAddedEvent(newTag)); } - + /** * Notifies case event subscribers that a content tag has been deleted. * diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java index aacad1ce7a..d2b0b041cf 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java @@ -48,7 +48,7 @@ import org.sleuthkit.datamodel.TskData; public class TagsManager implements Closeable { private static final Logger LOGGER = Logger.getLogger(TagsManager.class.getName()); - + private static final String USER_NAME_PROPERTY = "user.name"; private final SleuthkitCase caseDb; /** @@ -166,9 +166,8 @@ public class TagsManager implements Closeable { */ public List getTagNamesInUse() throws TskCoreException { if (UserPreferences.showOnlyCurrentUserTags()) { -// return caseDb.getTagNamesInUse(System.getProperty("user.name")); Set tagNameSet = new HashSet<>(); - String userName = System.getProperty("user.name"); + String userName = System.getProperty(USER_NAME_PROPERTY); List artifactTags = caseDb.getAllBlackboardArtifactTags(); for (BlackboardArtifactTag tag : artifactTags) { if (tag.getUserName().equals(userName)) { @@ -201,9 +200,8 @@ public class TagsManager implements Closeable { */ public List getTagNamesInUse(long dsObjId) throws TskCoreException { if (UserPreferences.showOnlyCurrentUserTags()) { -// return caseDb.getTagNamesInUse(dsObjId, System.getProperty("user.name")); Set tagNameSet = new HashSet<>(); - String userName = System.getProperty("user.name"); + String userName = System.getProperty(USER_NAME_PROPERTY); List artifactTags = caseDb.getAllBlackboardArtifactTags(); for (BlackboardArtifactTag tag : artifactTags) { if (tag.getUserName().equals(userName) && tag.getArtifact().getDataSource().getId() == dsObjId) { @@ -455,7 +453,7 @@ public class TagsManager implements Closeable { */ public long getContentTagsCountByTagName(TagName tagName) throws TskCoreException { if (UserPreferences.showOnlyCurrentUserTags()) { - String userName = System.getProperty("user.name"); + String userName = System.getProperty(USER_NAME_PROPERTY); long count = 0; List contentTags = getContentTagsByTagName(tagName); for (ContentTag tag : contentTags) { @@ -486,7 +484,7 @@ public class TagsManager implements Closeable { */ public long getContentTagsCountByTagName(TagName tagName, long dsObjId) throws TskCoreException { if (UserPreferences.showOnlyCurrentUserTags()) { - String userName = System.getProperty("user.name"); + String userName = System.getProperty(USER_NAME_PROPERTY); long count = 0; List contentTags = getContentTagsByTagName(tagName, dsObjId); for (ContentTag tag : contentTags) { @@ -645,7 +643,7 @@ public class TagsManager implements Closeable { */ public long getBlackboardArtifactTagsCountByTagName(TagName tagName) throws TskCoreException { if (UserPreferences.showOnlyCurrentUserTags()) { - String userName = System.getProperty("user.name"); + String userName = System.getProperty(USER_NAME_PROPERTY); long count = 0; List artifactTags = getBlackboardArtifactTagsByTagName(tagName); for (BlackboardArtifactTag tag : artifactTags) { @@ -675,7 +673,7 @@ public class TagsManager implements Closeable { */ public long getBlackboardArtifactTagsCountByTagName(TagName tagName, long dsObjId) throws TskCoreException { if (UserPreferences.showOnlyCurrentUserTags()) { - String userName = System.getProperty("user.name"); + String userName = System.getProperty(USER_NAME_PROPERTY); long count = 0; List artifactTags = getBlackboardArtifactTagsByTagName(tagName, dsObjId); for (BlackboardArtifactTag tag : artifactTags) { diff --git a/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java b/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java index 970ca9f0b0..78b726111e 100644 --- a/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java +++ b/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java @@ -197,10 +197,23 @@ public final class UserPreferences { preferences.putBoolean(GROUP_ITEMS_IN_TREE_BY_DATASOURCE, value); } + /** + * Get the user preference which identifies whether tags should be shown for + * only the current user or all users. + * + * @return true for just the current user, false for all users + */ public static boolean showOnlyCurrentUserTags() { return preferences.getBoolean(SHOW_ONLY_CURRENT_USER_TAGS, false); } + + /** + * Set the user preference which identifies whether tags should be shown for + * only the current user or all users. + * + * @param value - true for just the current user, false for all users + */ public static void setShowOnlyCurrentUserTags(boolean value) { preferences.putBoolean(SHOW_ONLY_CURRENT_USER_TAGS, value); } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java index 97af746282..d11bcf49a3 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java @@ -68,10 +68,15 @@ public class Tags implements AutopsyVisitableItem { this.datasourceObjId = dsObjId; } - public static String getTagsDisplayName(){ + /** + * Return the display name used by the tags node in the tree. + * + * @return - DISPLAY_NAME + */ + public static String getTagsDisplayName() { return DISPLAY_NAME; } - + long filteringDataSourceObjId() { return this.datasourceObjId; } @@ -136,9 +141,12 @@ public class Tags implements AutopsyVisitableItem { public String getItemType() { return getClass().getName(); } - - public void refresh(){ - tagResults.update(); + + /** + * Cause the contents of the RootNode and its children to be updated. + */ + public void refresh() { + tagResults.update(); } } diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java index 469a3c62dd..17cac06732 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java @@ -912,6 +912,9 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat SwingUtilities.invokeLater(this::rebuildTree); } + /** + * Refresh only the tags subtree(s) of the tree view. + */ private void refreshTagsTree() { SwingUtilities.invokeLater(() -> { // if no open case or has no data then there is no tree to rebuild From 215f76ad9990d1b5985776e1952b8ec90347bd6a Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 27 Jul 2018 11:12:06 -0400 Subject: [PATCH 17/21] 4065 move use of userName filter setting to Tags tree out of Tags Manager --- .../casemodule/services/TagsManager.java | 234 ++++++++++++------ .../org/sleuthkit/autopsy/datamodel/Tags.java | 70 ++++-- 2 files changed, 206 insertions(+), 98 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java index d2b0b041cf..058f7accdf 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java @@ -48,7 +48,6 @@ import org.sleuthkit.datamodel.TskData; public class TagsManager implements Closeable { private static final Logger LOGGER = Logger.getLogger(TagsManager.class.getName()); - private static final String USER_NAME_PROPERTY = "user.name"; private final SleuthkitCase caseDb; /** @@ -165,25 +164,34 @@ public class TagsManager implements Closeable { * @throws TskCoreException If there is an error querying the case database. */ public List getTagNamesInUse() throws TskCoreException { - if (UserPreferences.showOnlyCurrentUserTags()) { - Set tagNameSet = new HashSet<>(); - String userName = System.getProperty(USER_NAME_PROPERTY); - List artifactTags = caseDb.getAllBlackboardArtifactTags(); - for (BlackboardArtifactTag tag : artifactTags) { - if (tag.getUserName().equals(userName)) { - tagNameSet.add(tag.getName()); - } + return caseDb.getTagNamesInUse(); + } + + /** + * Gets a list of all tag names currently in use in the case database for + * tagging content or artifacts by the specified user. + * + * @param userName - the user name that you want to get tags for + * + * @return A list, possibly empty, of TagName objects. + * + * @throws TskCoreException If there is an error querying the case database. + */ + public List getTagNamesInUseForUser(String userName) throws TskCoreException { + Set tagNameSet = new HashSet<>(); + List artifactTags = caseDb.getAllBlackboardArtifactTags(); + for (BlackboardArtifactTag tag : artifactTags) { + if (tag.getUserName().equals(userName)) { + tagNameSet.add(tag.getName()); } - List contentTags = caseDb.getAllContentTags(); - for (ContentTag tag : contentTags) { - if (tag.getUserName().equals(userName)) { - tagNameSet.add(tag.getName()); - } - } - return new ArrayList<>(tagNameSet); - } else { - return caseDb.getTagNamesInUse(); } + List contentTags = caseDb.getAllContentTags(); + for (ContentTag tag : contentTags) { + if (tag.getUserName().equals(userName)) { + tagNameSet.add(tag.getName()); + } + } + return new ArrayList<>(tagNameSet); } /** @@ -199,25 +207,37 @@ public class TagsManager implements Closeable { * @throws TskCoreException */ public List getTagNamesInUse(long dsObjId) throws TskCoreException { - if (UserPreferences.showOnlyCurrentUserTags()) { - Set tagNameSet = new HashSet<>(); - String userName = System.getProperty(USER_NAME_PROPERTY); - List artifactTags = caseDb.getAllBlackboardArtifactTags(); - for (BlackboardArtifactTag tag : artifactTags) { - if (tag.getUserName().equals(userName) && tag.getArtifact().getDataSource().getId() == dsObjId) { - tagNameSet.add(tag.getName()); - } + return caseDb.getTagNamesInUse(dsObjId); + } + + /** + * Selects all of the rows from the tag_names table in the case database for + * which there is at least one matching row in the content_tags or + * blackboard_artifact_tags tables, for the given data source object id and user. + * + * @param dsObjId data source object id + * @param userName - the user name that you want to get tags for + * + * @return A list, possibly empty, of TagName data transfer objects (DTOs) + * for the rows. + * + * @throws TskCoreException + */ + public List getTagNamesInUseForUser(long dsObjId, String userName) throws TskCoreException { + Set tagNameSet = new HashSet<>(); + List artifactTags = caseDb.getAllBlackboardArtifactTags(); + for (BlackboardArtifactTag tag : artifactTags) { + if (tag.getUserName().equals(userName) && tag.getArtifact().getDataSource().getId() == dsObjId) { + tagNameSet.add(tag.getName()); } - List contentTags = caseDb.getAllContentTags(); - for (ContentTag tag : contentTags) { - if (tag.getUserName().equals(userName) && tag.getContent().getDataSource().getId() == dsObjId) { - tagNameSet.add(tag.getName()); - } - } - return new ArrayList<>(tagNameSet); - } else { - return caseDb.getTagNamesInUse(dsObjId); } + List contentTags = caseDb.getAllContentTags(); + for (ContentTag tag : contentTags) { + if (tag.getUserName().equals(userName) && tag.getContent().getDataSource().getId() == dsObjId) { + tagNameSet.add(tag.getName()); + } + } + return new ArrayList<>(tagNameSet); } /** @@ -452,19 +472,32 @@ public class TagsManager implements Closeable { * the case database. */ public long getContentTagsCountByTagName(TagName tagName) throws TskCoreException { - if (UserPreferences.showOnlyCurrentUserTags()) { - String userName = System.getProperty(USER_NAME_PROPERTY); - long count = 0; - List contentTags = getContentTagsByTagName(tagName); - for (ContentTag tag : contentTags) { - if (userName.equals(tag.getUserName())) { - count++; - } + return caseDb.getContentTagsCountByTagName(tagName); + } + + /** + * Gets content tags count by tag name for the specified user. + * + * @param tagName The representation of the desired tag type in the case + * database, which can be obtained by calling getTagNames + * and/or addTagName. + * @param userName - the user name that you want to get tags for + * + * @return A count of the content tags with the specified tag name for the + * specified user. + * + * @throws TskCoreException If there is an error getting the tags count from + * the case database. + */ + public long getContentTagsCountByTagNameForUser(TagName tagName, String userName) throws TskCoreException { + long count = 0; + List contentTags = getContentTagsByTagName(tagName); + for (ContentTag tag : contentTags) { + if (userName.equals(tag.getUserName())) { + count++; } - return count; - } else { - return caseDb.getContentTagsCountByTagName(tagName); } + return count; } /** @@ -483,19 +516,34 @@ public class TagsManager implements Closeable { * the case database. */ public long getContentTagsCountByTagName(TagName tagName, long dsObjId) throws TskCoreException { - if (UserPreferences.showOnlyCurrentUserTags()) { - String userName = System.getProperty(USER_NAME_PROPERTY); - long count = 0; - List contentTags = getContentTagsByTagName(tagName, dsObjId); - for (ContentTag tag : contentTags) { - if (userName.equals(tag.getUserName())) { - count++; - } + return caseDb.getContentTagsCountByTagName(tagName, dsObjId); + } + + /** + * Gets content tags count by tag name, for the given data source and user + * + * @param tagName The representation of the desired tag type in the case + * database, which can be obtained by calling getTagNames + * and/or addTagName. + * + * @param dsObjId data source object id + * @param userName - the user name that you want to get tags for + * + * @return A count of the content tags with the specified tag name, and for + * the given data source and user + * + * @throws TskCoreException If there is an error getting the tags count from + * the case database. + */ + public long getContentTagsCountByTagNameForUser(TagName tagName, long dsObjId, String userName) throws TskCoreException { + long count = 0; + List contentTags = getContentTagsByTagName(tagName, dsObjId); + for (ContentTag tag : contentTags) { + if (userName.equals(tag.getUserName())) { + count++; } - return count; - } else { - return caseDb.getContentTagsCountByTagName(tagName, dsObjId); } + return count; } /** @@ -642,19 +690,32 @@ public class TagsManager implements Closeable { * the case database. */ public long getBlackboardArtifactTagsCountByTagName(TagName tagName) throws TskCoreException { - if (UserPreferences.showOnlyCurrentUserTags()) { - String userName = System.getProperty(USER_NAME_PROPERTY); - long count = 0; - List artifactTags = getBlackboardArtifactTagsByTagName(tagName); - for (BlackboardArtifactTag tag : artifactTags) { - if (userName.equals(tag.getUserName())) { - count++; - } + return caseDb.getBlackboardArtifactTagsCountByTagName(tagName); + } + + /** + * Gets an artifact tags count by tag name for a specific user. + * + * @param tagName The representation of the desired tag type in the case + * database, which can be obtained by calling getTagNames + * and/or addTagName. + * @param userName - the user name that you want to get tags for + * + * @return A count of the artifact tags with the specified tag name for the + * specified user. + * + * @throws TskCoreException If there is an error getting the tags count from + * the case database. + */ + public long getBlackboardArtifactTagsCountByTagNameForUser(TagName tagName, String userName) throws TskCoreException { + long count = 0; + List artifactTags = getBlackboardArtifactTagsByTagName(tagName); + for (BlackboardArtifactTag tag : artifactTags) { + if (userName.equals(tag.getUserName())) { + count++; } - return count; - } else { - return caseDb.getBlackboardArtifactTagsCountByTagName(tagName); } + return count; } /** @@ -672,19 +733,34 @@ public class TagsManager implements Closeable { * the case database. */ public long getBlackboardArtifactTagsCountByTagName(TagName tagName, long dsObjId) throws TskCoreException { - if (UserPreferences.showOnlyCurrentUserTags()) { - String userName = System.getProperty(USER_NAME_PROPERTY); - long count = 0; - List artifactTags = getBlackboardArtifactTagsByTagName(tagName, dsObjId); - for (BlackboardArtifactTag tag : artifactTags) { - if (userName.equals(tag.getUserName())) { - count++; - } + return caseDb.getBlackboardArtifactTagsCountByTagName(tagName, dsObjId); + } + + /** + * Gets an artifact tags count by tag name, for the given data source and + * user. + * + * @param tagName The representation of the desired tag type in the case + * database, which can be obtained by calling getTagNames + * and/or addTagName. + * @param dsObjId data source object id + * @param userName - the user name that you want to get tags for + * + * @return A count of the artifact tags with the specified tag name, for the + * given data source and user. + * + * @throws TskCoreException If there is an error getting the tags count from + * the case database. + */ + public long getBlackboardArtifactTagsCountByTagNameForUser(TagName tagName, long dsObjId, String userName) throws TskCoreException { + long count = 0; + List artifactTags = getBlackboardArtifactTagsByTagName(tagName, dsObjId); + for (BlackboardArtifactTag tag : artifactTags) { + if (userName.equals(tag.getUserName())) { + count++; } - return count; - } else { - return caseDb.getBlackboardArtifactTagsCountByTagName(tagName, dsObjId); } + return count; } /** diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java index d11bcf49a3..b5f8ecff39 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java @@ -56,6 +56,7 @@ public class Tags implements AutopsyVisitableItem { private final TagResults tagResults = new TagResults(); private final static String DISPLAY_NAME = NbBundle.getMessage(RootNode.class, "TagsNode.displayName.text"); + private static final String USER_NAME_PROPERTY = "user.name"; //NON-NLS private final String ICON_PATH = "org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png"; //NON-NLS private final long datasourceObjId; @@ -240,10 +241,17 @@ public class Tags implements AutopsyVisitableItem { @Override protected boolean createKeys(List keys) { try { - - List tagNamesInUse = UserPreferences.groupItemsInTreeByDatasource() - ? Case.getCurrentCaseThrows().getServices().getTagsManager().getTagNamesInUse(datasourceObjId) - : Case.getCurrentCaseThrows().getServices().getTagsManager().getTagNamesInUse(); + List tagNamesInUse; + if (UserPreferences.showOnlyCurrentUserTags()) { + String userName = System.getProperty(USER_NAME_PROPERTY); + tagNamesInUse = UserPreferences.groupItemsInTreeByDatasource() + ? Case.getCurrentCaseThrows().getServices().getTagsManager().getTagNamesInUseForUser(datasourceObjId, userName) + : Case.getCurrentCaseThrows().getServices().getTagsManager().getTagNamesInUseForUser(userName); + } else { + tagNamesInUse = UserPreferences.groupItemsInTreeByDatasource() + ? Case.getCurrentCaseThrows().getServices().getTagsManager().getTagNamesInUse(datasourceObjId) + : Case.getCurrentCaseThrows().getServices().getTagsManager().getTagNamesInUse(); + } Collections.sort(tagNamesInUse); keys.addAll(tagNamesInUse); } catch (TskCoreException | NoCurrentCaseException ex) { @@ -291,14 +299,24 @@ public class Tags implements AutopsyVisitableItem { long tagsCount = 0; try { TagsManager tm = Case.getCurrentCaseThrows().getServices().getTagsManager(); - if (UserPreferences.groupItemsInTreeByDatasource()) { - tagsCount = tm.getContentTagsCountByTagName(tagName, datasourceObjId); - tagsCount += tm.getBlackboardArtifactTagsCountByTagName(tagName, datasourceObjId); + if (UserPreferences.showOnlyCurrentUserTags()) { + String userName = System.getProperty(USER_NAME_PROPERTY); + if (UserPreferences.groupItemsInTreeByDatasource()) { + tagsCount = tm.getContentTagsCountByTagNameForUser(tagName, datasourceObjId, userName); + tagsCount += tm.getBlackboardArtifactTagsCountByTagNameForUser(tagName, datasourceObjId, userName); + } else { + tagsCount = tm.getContentTagsCountByTagNameForUser(tagName, userName); + tagsCount += tm.getBlackboardArtifactTagsCountByTagNameForUser(tagName, userName); + } } else { - tagsCount = tm.getContentTagsCountByTagName(tagName); - tagsCount += tm.getBlackboardArtifactTagsCountByTagName(tagName); + if (UserPreferences.groupItemsInTreeByDatasource()) { + tagsCount = tm.getContentTagsCountByTagName(tagName, datasourceObjId); + tagsCount += tm.getBlackboardArtifactTagsCountByTagName(tagName, datasourceObjId); + } else { + tagsCount = tm.getContentTagsCountByTagName(tagName); + tagsCount += tm.getBlackboardArtifactTagsCountByTagName(tagName); + } } - } catch (TskCoreException | NoCurrentCaseException ex) { Logger.getLogger(TagNameNode.class.getName()).log(Level.SEVERE, "Failed to get tags count for " + tagName.getDisplayName() + " tag name", ex); //NON-NLS } @@ -401,9 +419,17 @@ public class Tags implements AutopsyVisitableItem { private void updateDisplayName() { long tagsCount = 0; try { - tagsCount = UserPreferences.groupItemsInTreeByDatasource() - ? Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsCountByTagName(tagName, datasourceObjId) - : Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsCountByTagName(tagName); + + if (UserPreferences.showOnlyCurrentUserTags()) { + String userName = System.getProperty(USER_NAME_PROPERTY); + tagsCount = UserPreferences.groupItemsInTreeByDatasource() + ? Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsCountByTagNameForUser(tagName, datasourceObjId, userName) + : Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsCountByTagNameForUser(tagName, userName); + } else { + tagsCount = UserPreferences.groupItemsInTreeByDatasource() + ? Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsCountByTagName(tagName, datasourceObjId) + : Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsCountByTagName(tagName); + } } catch (TskCoreException | NoCurrentCaseException ex) { Logger.getLogger(ContentTagTypeNode.class.getName()).log(Level.SEVERE, "Failed to get content tags count for " + tagName.getDisplayName() + " tag name", ex); //NON-NLS } @@ -462,7 +488,7 @@ public class Tags implements AutopsyVisitableItem { ? Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsByTagName(tagName, datasourceObjId) : Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsByTagName(tagName); if (UserPreferences.showOnlyCurrentUserTags()) { - String userName = System.getProperty("user.name"); + String userName = System.getProperty(USER_NAME_PROPERTY); for (ContentTag tag : contentTags) { if (userName.equals(tag.getUserName())) { keys.add(tag); @@ -501,7 +527,6 @@ public class Tags implements AutopsyVisitableItem { private final TagName tagName; private final String ICON_PATH = "org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png"; //NON-NLS - private int displayCount = 0; public BlackboardArtifactTagTypeNode(TagName tagName) { super(Children.create(new BlackboardArtifactTagNodeFactory(tagName), true), Lookups.singleton(tagName.getDisplayName() + " " + ARTIFACT_DISPLAY_NAME)); @@ -515,9 +540,16 @@ public class Tags implements AutopsyVisitableItem { private void updateDisplayName() { long tagsCount = 0; try { - tagsCount = UserPreferences.groupItemsInTreeByDatasource() - ? Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsCountByTagName(tagName, datasourceObjId) - : Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsCountByTagName(tagName); + if (UserPreferences.showOnlyCurrentUserTags()) { + String userName = System.getProperty(USER_NAME_PROPERTY); + tagsCount = UserPreferences.groupItemsInTreeByDatasource() + ? Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsCountByTagNameForUser(tagName, datasourceObjId, userName) + : Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsCountByTagNameForUser(tagName, userName); + } else { + tagsCount = UserPreferences.groupItemsInTreeByDatasource() + ? Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsCountByTagName(tagName, datasourceObjId) + : Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsCountByTagName(tagName); + } } catch (TskCoreException | NoCurrentCaseException ex) { Logger.getLogger(BlackboardArtifactTagTypeNode.class.getName()).log(Level.SEVERE, "Failed to get blackboard artifact tags count for " + tagName.getDisplayName() + " tag name", ex); //NON-NLS } @@ -576,7 +608,7 @@ public class Tags implements AutopsyVisitableItem { ? Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsByTagName(tagName, datasourceObjId) : Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsByTagName(tagName); if (UserPreferences.showOnlyCurrentUserTags()) { - String userName = System.getProperty("user.name"); + String userName = System.getProperty(USER_NAME_PROPERTY); for (BlackboardArtifactTag tag : artifactTags) { if (userName.equals(tag.getUserName())) { keys.add(tag); From 2367bd5766cf78ce9ca2afe8fdf53ebbc28b5c4b Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Thu, 2 Aug 2018 16:31:46 -0400 Subject: [PATCH 18/21] 4065 fix codacy issue and formating issue found in review --- .../org/sleuthkit/autopsy/casemodule/services/TagsManager.java | 1 - Core/src/org/sleuthkit/autopsy/datamodel/ContentTagNode.java | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java index 058f7accdf..896298c2bd 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java @@ -30,7 +30,6 @@ import java.util.logging.Level; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; -import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifactTag; diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ContentTagNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/ContentTagNode.java index e213e460cb..acbfcac758 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ContentTagNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/ContentTagNode.java @@ -128,8 +128,7 @@ class ContentTagNode extends DisplayableItemNode { List actions = new ArrayList<>(); actions.addAll(Arrays.asList(super.getActions(context))); - AbstractFile file = getLookup().lookup(AbstractFile.class - ); + AbstractFile file = getLookup().lookup(AbstractFile.class); if (file != null) { actions.add(ViewFileInTimelineAction.createViewFileAction(file)); } From 9c4f2b24385f03f84ec0d652c0b717d45523f698 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Fri, 3 Aug 2018 14:23:11 -0400 Subject: [PATCH 19/21] Normalize path. --- .../sleuthkit/autopsy/report/ReportHTML.java | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java b/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java index b2d388bedc..81c4c9ac72 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java @@ -784,8 +784,14 @@ class ReportHTML implements TableReportModule { localFileFolder.mkdirs(); } - // Construct a file tagName for the local file that incorporates the file id to ensure uniqueness. - String fileName = file.getName(); + /* + * Construct a file tagName for the local file that incorporates the + * file ID to ensure uniqueness. + * + * Note: File name is normalized to account for possible attribute name + * which will be separated by a ':' character. + */ + String fileName = org.sleuthkit.autopsy.coreutils.FileUtil.escapeFileName(file.getName()); String objectIdSuffix = "_" + file.getId(); int lastDotIndex = fileName.lastIndexOf("."); if (lastDotIndex != -1 && lastDotIndex != 0) { @@ -1294,9 +1300,24 @@ class ReportHTML implements TableReportModule { return summary; } + /** + * Create a thumbnail of a given file. + * + * @param file The file from which to create the thumbnail. + * + * @return The path to the thumbnail file, or null if a thumbnail couldn't + * be created. + */ private String prepareThumbnail(AbstractFile file) { BufferedImage bufferedThumb = ImageUtils.getThumbnail(file, ImageUtils.ICON_SIZE_MEDIUM); - File thumbFile = Paths.get(thumbsPath, file.getName() + ".png").toFile(); + + /* + * File name is normalized to account for possible attribute name which + * will be separated by a ':' character. + */ + String fileName = org.sleuthkit.autopsy.coreutils.FileUtil.escapeFileName(file.getName()); + + File thumbFile = Paths.get(thumbsPath, fileName + ".png").toFile(); if (bufferedThumb == null) { return null; } From 19b7ba19c0b3a160fcaca535af0a1a052ceac264 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 3 Aug 2018 16:15:27 -0400 Subject: [PATCH 20/21] 4103 added icons back to AID 2.0 as part of figuring out how to do 4095 --- .../guiutils/StatusIconCellRenderer.java | 32 ++++++++++++----- .../autoingest/AutoIngestJobsNode.java | 2 +- .../autoingest/AutoIngestJobsPanel.java | 3 ++ .../PrioritizedIconCellRenderer.java | 35 +++++++++++++------ 4 files changed, 51 insertions(+), 21 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/guiutils/StatusIconCellRenderer.java b/Core/src/org/sleuthkit/autopsy/guiutils/StatusIconCellRenderer.java index 15c1e0adf4..02874440f7 100644 --- a/Core/src/org/sleuthkit/autopsy/guiutils/StatusIconCellRenderer.java +++ b/Core/src/org/sleuthkit/autopsy/guiutils/StatusIconCellRenderer.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2015-2017 Basis Technology Corp. + * Copyright 2015-2018 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,16 +19,19 @@ package org.sleuthkit.autopsy.guiutils; import java.awt.Component; +import java.lang.reflect.InvocationTargetException; import javax.swing.ImageIcon; import javax.swing.JTable; import static javax.swing.SwingConstants.CENTER; +import org.openide.nodes.Node; import org.openide.util.ImageUtilities; import org.openide.util.NbBundle.Messages; +import org.sleuthkit.autopsy.datamodel.NodeProperty; /** - * A JTable cell renderer that represents a status as a center-aligned icon, and - * grays out the cell if the table is disabled. The statuses represented are OK, - * WARNING, and ERROR. + * A JTable and outline view cell renderer that represents a status as a + * center-aligned icon, and grays out the cell if the table is disabled. The + * statuses represented are OK, WARNING, and ERROR. */ public class StatusIconCellRenderer extends GrayableCellRenderer { @@ -45,8 +48,20 @@ public class StatusIconCellRenderer extends GrayableCellRenderer { @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { setHorizontalAlignment(CENTER); - if ((value instanceof Status)) { - switch((Status) value) { + Object switchValue = null; + if ((value instanceof NodeProperty)) { + //The Outline view has properties in the cell, the value contained in the property is what we want + try { + switchValue = ((Node.Property) value).getValue(); + } catch (IllegalAccessException | InvocationTargetException ex) { + //Unable to get the value from the NodeProperty no Icon will be displayed + } + } else { + //JTables contain the value we want directly in the cell + switchValue = value; + } + if ((switchValue instanceof Status)) { + switch ((Status) switchValue) { case OK: setIcon(OK_ICON); setToolTipText(org.openide.util.NbBundle.getMessage(StatusIconCellRenderer.class, "StatusIconCellRenderer.tooltiptext.ok")); @@ -60,8 +75,7 @@ public class StatusIconCellRenderer extends GrayableCellRenderer { setToolTipText(org.openide.util.NbBundle.getMessage(StatusIconCellRenderer.class, "StatusIconCellRenderer.tooltiptext.error")); break; } - } - else { + } else { setIcon(null); setText(""); } @@ -69,7 +83,7 @@ public class StatusIconCellRenderer extends GrayableCellRenderer { return this; } - + public enum Status { OK, WARNING, diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java index d5bfbd13d8..00a2bc4d37 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java @@ -326,7 +326,7 @@ final class AutoIngestJobsNode extends AbstractNode { ss.put(new NodeProperty<>(Bundle.AutoIngestJobsNode_jobCreated_text(), Bundle.AutoIngestJobsNode_jobCreated_text(), Bundle.AutoIngestJobsNode_jobCreated_text(), jobWrapper.getManifest().getDateFileCreated())); ss.put(new NodeProperty<>(Bundle.AutoIngestJobsNode_priority_text(), Bundle.AutoIngestJobsNode_priority_text(), Bundle.AutoIngestJobsNode_priority_text(), - jobWrapper.getPriority() > 0 ? Bundle.AutoIngestJobsNode_prioritized_true() : Bundle.AutoIngestJobsNode_prioritized_false())); + jobWrapper.getPriority())); break; case RUNNING_JOB: AutoIngestJob.StageDetails status = jobWrapper.getProcessingStageDetails(); diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsPanel.java index fb6f79ab0c..18fb8171b2 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsPanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsPanel.java @@ -31,6 +31,7 @@ import org.sleuthkit.autopsy.datamodel.EmptyNode; import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestJobsNode.AutoIngestJobStatus; import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestJobsNode.JobNode; import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestNodeRefreshEvents.AutoIngestRefreshEvent; +import org.sleuthkit.autopsy.guiutils.StatusIconCellRenderer; /** * A panel which displays an outline view with all jobs for a specified status. @@ -84,6 +85,7 @@ final class AutoIngestJobsPanel extends javax.swing.JPanel implements ExplorerMa indexOfColumn = getColumnIndexByName(Bundle.AutoIngestJobsNode_priority_text()); if (indexOfColumn != INVALID_INDEX) { outline.getColumnModel().getColumn(indexOfColumn).setPreferredWidth(INITIAL_PRIORITIZED_WIDTH); + outline.getColumnModel().getColumn(indexOfColumn).setCellRenderer(new PrioritizedIconCellRenderer()); } break; case RUNNING_JOB: @@ -108,6 +110,7 @@ final class AutoIngestJobsPanel extends javax.swing.JPanel implements ExplorerMa indexOfColumn = getColumnIndexByName(Bundle.AutoIngestJobsNode_status_text()); if (indexOfColumn != INVALID_INDEX) { outline.getColumnModel().getColumn(indexOfColumn).setPreferredWidth(INITIAL_STATUS_WIDTH); + outline.getColumnModel().getColumn(indexOfColumn).setCellRenderer(new StatusIconCellRenderer()); } break; default: diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PrioritizedIconCellRenderer.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PrioritizedIconCellRenderer.java index a4066e6c15..a41e3c0d6d 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PrioritizedIconCellRenderer.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PrioritizedIconCellRenderer.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2017 Basis Technology Corp. + * Copyright 2017-2018 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,21 +19,22 @@ package org.sleuthkit.autopsy.experimental.autoingest; import java.awt.Component; +import java.lang.reflect.InvocationTargetException; import javax.swing.ImageIcon; import javax.swing.JTable; import static javax.swing.SwingConstants.CENTER; +import org.openide.nodes.Node; import org.openide.util.ImageUtilities; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.guiutils.GrayableCellRenderer; -import org.sleuthkit.autopsy.guiutils.StatusIconCellRenderer; +import org.sleuthkit.autopsy.datamodel.NodeProperty; /** - * A JTable cell renderer that represents whether the priority value of a job - * has ever been increased, tick if prioritized nothing if not. + * A JTable and Outline view cell renderer that represents whether the priority + * value of a job has ever been increased, tick if prioritized nothing if not. */ class PrioritizedIconCellRenderer extends GrayableCellRenderer { - @Messages({ "PrioritizedIconCellRenderer.prioritized.tooltiptext=This job has been prioritized. The most recently prioritized job should be processed next.", "PrioritizedIconCellRenderer.notPrioritized.tooltiptext=This job has not been prioritized." @@ -44,13 +45,25 @@ class PrioritizedIconCellRenderer extends GrayableCellRenderer { @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { setHorizontalAlignment(CENTER); - if ((value instanceof Integer)) { - if ((int) value == 0) { - setIcon(null); + Object switchValue = null; + if ((value instanceof NodeProperty)) { + //The Outline view has properties in the cell, the value contained in the property is what we want + try { + switchValue = ((Node.Property) value).getValue(); + } catch (IllegalAccessException | InvocationTargetException ignored) { + //Unable to get the value from the NodeProperty no Icon will be displayed + } + } else { + //JTables contain the value we want directly in the cell + switchValue = value; + } + if (switchValue instanceof Integer && (int) switchValue != 0) { + setIcon(checkedIcon); + setToolTipText(org.openide.util.NbBundle.getMessage(PrioritizedIconCellRenderer.class, "PrioritizedIconCellRenderer.prioritized.tooltiptext")); + } else { + setIcon(null); + if (switchValue instanceof Integer) { setToolTipText(org.openide.util.NbBundle.getMessage(PrioritizedIconCellRenderer.class, "PrioritizedIconCellRenderer.notPrioritized.tooltiptext")); - } else { - setIcon(checkedIcon); - setToolTipText(org.openide.util.NbBundle.getMessage(PrioritizedIconCellRenderer.class, "PrioritizedIconCellRenderer.prioritized.tooltiptext")); } } grayCellIfTableNotEnabled(table, isSelected); From 833da054843bc6595543cf710615c91f9f39a85c Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 3 Aug 2018 17:27:46 -0400 Subject: [PATCH 21/21] 3964 update url for new version of Emedded test file --- Core/build.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/build.xml b/Core/build.xml index aa654b0f36..2efe03ecea 100644 --- a/Core/build.xml +++ b/Core/build.xml @@ -86,7 +86,7 @@ - +