working through the 3 panel dao and data artifact node

This commit is contained in:
Greg DiCristofaro 2021-10-04 15:31:42 -04:00
parent 1bf360f2cc
commit 258aaaddfa
2 changed files with 290 additions and 466 deletions

View File

@ -18,26 +18,18 @@
*/
package org.sleuthkit.autopsy.datamodel;
import org.sleuthkit.autopsy.actions.ViewArtifactAction;
import org.sleuthkit.autopsy.actions.ViewOsAccountAction;
import com.google.common.annotations.Beta;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import org.sleuthkit.autopsy.actions.ViewArtifactAction;
import org.sleuthkit.autopsy.actions.ViewOsAccountAction;
import java.lang.ref.WeakReference;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@ -51,7 +43,6 @@ import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
import org.openide.util.Utilities;
import org.openide.util.WeakListeners;
import org.openide.util.lookup.Lookups;
import org.sleuthkit.autopsy.actions.AddBlackboardArtifactTagAction;
import org.sleuthkit.autopsy.actions.AddContentTagAction;
@ -65,14 +56,9 @@ import org.sleuthkit.autopsy.casemodule.events.CommentChangedEvent;
import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent;
import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent;
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoDbUtil;
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeNormalizationException;
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException;
import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.autopsy.corecomponents.DataResultViewerTable;
import org.sleuthkit.autopsy.coreutils.Logger;
import static org.sleuthkit.autopsy.datamodel.DisplayableItemNode.findLinked;
import org.sleuthkit.autopsy.corecomponents.DataResultViewerTable.HasCommentStatus;
import static org.sleuthkit.autopsy.datamodel.AbstractContentNode.backgroundTasksPool;
import org.sleuthkit.autopsy.timeline.actions.ViewArtifactInTimelineAction;
import org.sleuthkit.autopsy.timeline.actions.ViewFileInTimelineAction;
@ -82,13 +68,17 @@ import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.Tag;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.autopsy.datamodel.utils.IconsUtil;
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeNormalizationException;
import org.sleuthkit.autopsy.corecomponents.DataResultViewerTable;
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
import org.sleuthkit.autopsy.coreutils.TimeZoneUtils;
import static org.sleuthkit.autopsy.datamodel.AbstractContentNode.NO_DESCR;
import org.sleuthkit.autopsy.datamodel.ThreePanelDAO.DataArtifactRow;
import org.sleuthkit.autopsy.datamodel.ThreePanelDAO.DataArtifactTableDTO;
import org.sleuthkit.autopsy.texttranslation.TextTranslationService;
import org.sleuthkit.autopsy.datamodel.utils.FileNameTransTask;
import org.sleuthkit.autopsy.directorytree.ExportCSVAction;
@ -97,11 +87,6 @@ import org.sleuthkit.autopsy.directorytree.ExternalViewerShortcutAction;
import org.sleuthkit.autopsy.directorytree.ExtractAction;
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
import org.sleuthkit.autopsy.directorytree.ViewContextAction;
import org.sleuthkit.autopsy.modules.embeddedfileextractor.ExtractArchiveWithPasswordAction;
import org.sleuthkit.datamodel.AnalysisResult;
import org.sleuthkit.datamodel.BlackboardArtifact.Category;
import org.sleuthkit.datamodel.HostAddress;
import org.sleuthkit.datamodel.Pool;
import org.sleuthkit.datamodel.DataArtifact;
import org.sleuthkit.datamodel.DerivedFile;
import org.sleuthkit.datamodel.Directory;
@ -111,13 +96,9 @@ import org.sleuthkit.datamodel.LocalDirectory;
import org.sleuthkit.datamodel.LocalFile;
import org.sleuthkit.datamodel.OsAccount;
import org.sleuthkit.datamodel.Report;
import org.sleuthkit.datamodel.Score;
import org.sleuthkit.datamodel.SlackFile;
import org.sleuthkit.datamodel.VirtualDirectory;
import org.sleuthkit.datamodel.TskData;
import org.sleuthkit.datamodel.Volume;
import org.sleuthkit.datamodel.VolumeSystem;
import org.sleuthkit.datamodel.Image;
import org.sleuthkit.datamodel.Tag;
/**
* An AbstractNode implementation that can be used to represent an data artifact
@ -127,36 +108,71 @@ public class DataArtifactNodev2 extends AbstractContentNode<BlackboardArtifact>
private static final Logger logger = Logger.getLogger(DataArtifactNodev2.class.getName());
/**
* Constructs an AbstractNode implementation that can be used to represent a
* data artifact or analysis result of any type. The Lookup of the Node will
* contain the data artifact or analysis result and its parent content as
* its source content.
*
* @param artifact The data artifact or analysis result.
* @param iconPath The path to the icon for the data artifact or analysis
* result type.
*/
public DataArtifactNodev2(BlackboardArtifact artifact, String iconPath) {
super(artifact, createLookup(artifact, false));
...
private static Lookup createLookup(DataArtifactRow row) {
DataArtifactItem artifactItem = new DataArtifactItem(row.getDataArtifact(), row.getSrcContent());
if (row.getSrcContent() == null) {
return Lookups.fixed(row.getDataArtifact(), artifactItem);
} else {
return Lookups.fixed(row.getDataArtifact(), artifactItem, row.getSrcContent());
}
}
private final BlackboardArtifact.Type artifactType;
private final List<BlackboardAttribute.Type> attributeTypes;
private final DataArtifactRow artifactRow;
private final boolean hasSupportedTimeStamp;
private String translatedSourceName = null;
/**
* Constructs an AbstractNode implementation that can be used to represent a
* data artifact or analysis result of any type. The Lookup of the Node will
* contain the data artifact or analysis result and its parent content as
* its source content.
*
* @param artifact The data artifact or analysis result.
private final PropertyChangeListener fileNameTranslationListener = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
String eventType = evt.getPropertyName();
if (eventType.equals(FileNameTransTask.getPropertyName())) {
/*
* Replace the value of the Source File property with the
* translated name via setDisplayName (see note in createSheet),
* and put the untranslated name in the Original Name property
* and in the tooltip.
*/
public DataArtifactNodev2(BlackboardArtifact artifact) {
this(artifact, IconsUtil.getIconFilePath(artifact.getArtifactTypeID()));
String originalName = evt.getOldValue().toString();
translatedSourceName = evt.getNewValue().toString();
setDisplayName(translatedSourceName);
setShortDescription(originalName);
updateSheet(new NodeProperty<>(
Bundle.BlackboardArtifactNode_createSheet_srcFile_origName(),
Bundle.BlackboardArtifactNode_createSheet_srcFile_origDisplayName(),
NO_DESCR,
originalName));
}
}
};
public DataArtifactNodev2(DataArtifactTableDTO tableData, DataArtifactRow artifactRow) {
this(tableData, artifactRow, IconsUtil.getIconFilePath(tableData.getArtifactType().getTypeID()));
}
public DataArtifactNodev2(DataArtifactTableDTO tableData, DataArtifactRow artifactRow, String iconPath) {
super(artifactRow.getDataArtifact(), createLookup(artifactRow));
setDisplayName(artifactRow.getSrcContent().getName());
setShortDescription(getDisplayName());
setName(Long.toString(artifactRow.getDataArtifact().getArtifactID()));
setIconBaseWithExtension(iconPath != null && iconPath.charAt(0) == '/' ? iconPath.substring(1) : iconPath);
this.artifactRow = artifactRow;
this.artifactType = tableData.getArtifactType();
this.attributeTypes = tableData.getAttributeTypes();
this.hasSupportedTimeStamp = supportedTimeStamp(this.attributeTypes, this.artifactRow.getAttributeValues());
}
private boolean supportedTimeStamp(List<BlackboardAttribute.Type> attributeTypes, Map<String, Object> attributeValues) {
return attributeTypes.stream()
.anyMatch(tp -> {
return BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME.equals(tp.getValueType())
&& attributeValues.containsKey(tp.getTypeName());
});
}
/**
* Returns a list of non null actions from the given possibly null options.
@ -176,28 +192,26 @@ public class DataArtifactNodev2 extends AbstractContentNode<BlackboardArtifact>
// groupings of actions where each group will be separated by a divider
List<List<Action>> actionsLists = new ArrayList<>();
DataArtifact artifact = this.artifactRow.getDataArtifact();
Content srcContent = this.artifactRow.getSrcContent();
// view artifact in timeline
actionsLists.add(getNonNull(
getTimelineArtifactAction(this.artifact)
getTimelineArtifactAction(artifact, this.hasSupportedTimeStamp)
));
// view associated file (TSK_PATH_ID attr) in directory and timeline
actionsLists.add(getAssociatedFileActions(this.artifact, this.artifactType));
actionsLists.add(getAssociatedFileActions(artifact, this.artifactType));
// view source content in directory and timeline
actionsLists.add(getNonNull(
getViewSrcContentAction(this.artifact, this.srcContent),
getTimelineSrcContentAction(this.srcContent)
));
// extract with password from encrypted file
actionsLists.add(getNonNull(
getExtractWithPasswordAction(this.srcContent)
getViewSrcContentAction(artifact, srcContent),
getTimelineSrcContentAction(srcContent)
));
// menu options for artifact with report parent
if (this.srcContent instanceof Report) {
actionsLists.add(DataModelActionsFactory.getActions(this.srcContent, false));
if (srcContent instanceof Report) {
actionsLists.add(DataModelActionsFactory.getActions(srcContent, false));
}
Node parentFileNode = getParentFileNode(srcContent);
@ -213,7 +227,7 @@ public class DataArtifactNodev2 extends AbstractContentNode<BlackboardArtifact>
}
// file and result tagging
actionsLists.add(getTagActions(parentFileNode != null, this.artifact, selectedFileCount, selectedArtifactCount));
actionsLists.add(getTagActions(parentFileNode != null, artifact, selectedFileCount, selectedArtifactCount));
// menu extension items (i.e. add to central repository)
actionsLists.add(ContextMenuExtensionPoint.getActions());
@ -240,16 +254,16 @@ public class DataArtifactNodev2 extends AbstractContentNode<BlackboardArtifact>
* @return The artifact type name.
*/
@Messages({
"BlackboardArtifactNode_getAssociatedTypeStr_webCache=Cached File",
"BlackboardArtifactNode_getAssociatedTypeStr_webDownload=Downloaded File",
"BlackboardArtifactNode_getAssociatedTypeStr_associated=Associated File",})
"DataArtifactNodev2_getAssociatedTypeStr_webCache=Cached File",
"DataArtifactNodev2_getAssociatedTypeStr_webDownload=Downloaded File",
"DataArtifactNodev2_getAssociatedTypeStr_associated=Associated File",})
private String getAssociatedTypeStr(BlackboardArtifact.Type artifactType) {
if (BlackboardArtifact.Type.TSK_WEB_CACHE.equals(artifactType)) {
return Bundle.BlackboardArtifactNode_getAssociatedTypeStr_webCache();
return Bundle.DataArtifactNodev2_getAssociatedTypeStr_webCache();
} else if (BlackboardArtifact.Type.TSK_WEB_DOWNLOAD.equals(artifactType)) {
return Bundle.BlackboardArtifactNode_getAssociatedTypeStr_webDownload();
return Bundle.DataArtifactNodev2_getAssociatedTypeStr_webDownload();
} else {
return Bundle.BlackboardArtifactNode_getAssociatedTypeStr_associated();
return Bundle.DataArtifactNodev2_getAssociatedTypeStr_associated();
}
}
@ -262,20 +276,20 @@ public class DataArtifactNodev2 extends AbstractContentNode<BlackboardArtifact>
* @return The name of the type of content.
*/
@Messages({
"BlackboardArtifactNode_getViewSrcContentAction_type_File=File",
"BlackboardArtifactNode_getViewSrcContentAction_type_DataArtifact=Data Artifact",
"BlackboardArtifactNode_getViewSrcContentAction_type_OSAccount=OS Account",
"BlackboardArtifactNode_getViewSrcContentAction_type_unknown=Item"
"DataArtifactNodev2_getViewSrcContentAction_type_File=File",
"DataArtifactNodev2_getViewSrcContentAction_type_DataArtifact=Data Artifact",
"DataArtifactNodev2_getViewSrcContentAction_type_OSAccount=OS Account",
"DataArtifactNodev2_getViewSrcContentAction_type_unknown=Item"
})
private String getContentTypeStr(Content content) {
if (content instanceof AbstractFile) {
return Bundle.BlackboardArtifactNode_getViewSrcContentAction_type_File();
return Bundle.DataArtifactNodev2_getViewSrcContentAction_type_File();
} else if (content instanceof DataArtifact) {
return Bundle.BlackboardArtifactNode_getViewSrcContentAction_type_DataArtifact();
return Bundle.DataArtifactNodev2_getViewSrcContentAction_type_DataArtifact();
} else if (content instanceof OsAccount) {
return Bundle.BlackboardArtifactNode_getViewSrcContentAction_type_OSAccount();
return Bundle.DataArtifactNodev2_getViewSrcContentAction_type_OSAccount();
} else {
return Bundle.BlackboardArtifactNode_getViewSrcContentAction_type_unknown();
return Bundle.DataArtifactNodev2_getViewSrcContentAction_type_unknown();
}
}
@ -291,9 +305,9 @@ public class DataArtifactNodev2 extends AbstractContentNode<BlackboardArtifact>
*/
@Messages({
"# {0} - type",
"BlackboardArtifactNode_getAssociatedFileActions_viewAssociatedFileAction=View {0} in Directory",
"DataArtifactNodev2_getAssociatedFileActions_viewAssociatedFileAction=View {0} in Directory",
"# {0} - type",
"BlackboardArtifactNode_getAssociatedFileActions_viewAssociatedFileInTimelineAction=View {0} in Timeline..."
"DataArtifactNodev2_getAssociatedFileActions_viewAssociatedFileInTimelineAction=View {0} in Timeline..."
})
private List<Action> getAssociatedFileActions(BlackboardArtifact artifact, BlackboardArtifact.Type artifactType) {
try {
@ -301,11 +315,11 @@ public class DataArtifactNodev2 extends AbstractContentNode<BlackboardArtifact>
if (associatedFile != null) {
return Arrays.asList(
new ViewContextAction(
Bundle.BlackboardArtifactNode_getAssociatedFileActions_viewAssociatedFileAction(
Bundle.DataArtifactNodev2_getAssociatedFileActions_viewAssociatedFileAction(
getAssociatedTypeStr(artifactType)),
associatedFile),
new ViewFileInTimelineAction(associatedFile,
Bundle.BlackboardArtifactNode_getAssociatedFileActions_viewAssociatedFileInTimelineAction(
Bundle.DataArtifactNodev2_getAssociatedFileActions_viewAssociatedFileInTimelineAction(
getAssociatedTypeStr(artifactType)))
);
}
@ -326,22 +340,22 @@ public class DataArtifactNodev2 extends AbstractContentNode<BlackboardArtifact>
*/
@Messages({
"# {0} - contentType",
"BlackboardArtifactNode_getSrcContentAction_actionDisplayName=View Source {0} in Directory"
"DataArtifactNodev2_getSrcContentAction_actionDisplayName=View Source {0} in Directory"
})
private Action getViewSrcContentAction(BlackboardArtifact artifact, Content content) {
if (content instanceof DataArtifact) {
return new ViewArtifactAction(
(BlackboardArtifact) content,
Bundle.BlackboardArtifactNode_getSrcContentAction_actionDisplayName(
Bundle.DataArtifactNodev2_getSrcContentAction_actionDisplayName(
getContentTypeStr(content)));
} else if (content instanceof OsAccount) {
return new ViewOsAccountAction(
(OsAccount) content,
Bundle.BlackboardArtifactNode_getSrcContentAction_actionDisplayName(
Bundle.DataArtifactNodev2_getSrcContentAction_actionDisplayName(
getContentTypeStr(content)));
} else if (content instanceof AbstractFile || artifact instanceof DataArtifact) {
return new ViewContextAction(
Bundle.BlackboardArtifactNode_getSrcContentAction_actionDisplayName(
Bundle.DataArtifactNodev2_getSrcContentAction_actionDisplayName(
getContentTypeStr(content)),
content);
} else {
@ -377,29 +391,6 @@ public class DataArtifactNodev2 extends AbstractContentNode<BlackboardArtifact>
}
}
/**
* Returns actions for extracting content from file or null if not possible.
*
* @param srcContent The source content.
*
* @return The action or null if not appropriate source content.
*/
private Action getExtractWithPasswordAction(Content srcContent) {
if ((srcContent instanceof AbstractFile)
&& FileTypeExtensions.getArchiveExtensions()
.contains("." + ((AbstractFile) srcContent).getNameExtension().toLowerCase())) {
try {
if (srcContent.getArtifacts(BlackboardArtifact.Type.TSK_ENCRYPTION_DETECTED.getTypeID()).size() > 0) {
return new ExtractArchiveWithPasswordAction((AbstractFile) srcContent);
}
} catch (TskCoreException ex) {
logger.log(Level.WARNING, "Unable to add unzip with password action to context menus", ex);
}
}
return null;
}
/**
* Returns tag actions.
*
@ -442,15 +433,15 @@ public class DataArtifactNodev2 extends AbstractContentNode<BlackboardArtifact>
* @return The list of actions or an empty list.
*/
@Messages({
"BlackboardArtifactNode_getSrcContentViewerActions_viewInNewWin=View Item in New Window",
"BlackboardArtifactNode_getSrcContentViewerActions_openInExtViewer=Open in External Viewer Ctrl+E"
"DataArtifactNodev2_getSrcContentViewerActions_viewInNewWin=View Item in New Window",
"DataArtifactNodev2_getSrcContentViewerActions_openInExtViewer=Open in External Viewer Ctrl+E"
})
private List<Action> getSrcContentViewerActions(Node srcFileNode, int selectedFileCount) {
List<Action> actionsList = new ArrayList<>();
if (srcFileNode != null) {
actionsList.add(new NewWindowViewAction(Bundle.BlackboardArtifactNode_getSrcContentViewerActions_viewInNewWin(), srcFileNode));
actionsList.add(new NewWindowViewAction(Bundle.DataArtifactNodev2_getSrcContentViewerActions_viewInNewWin(), srcFileNode));
if (selectedFileCount == 1) {
actionsList.add(new ExternalViewerAction(Bundle.BlackboardArtifactNode_getSrcContentViewerActions_openInExtViewer(), srcFileNode));
actionsList.add(new ExternalViewerAction(Bundle.DataArtifactNodev2_getSrcContentViewerActions_openInExtViewer(), srcFileNode));
} else {
actionsList.add(ExternalViewerShortcutAction.getInstance());
}
@ -468,25 +459,26 @@ public class DataArtifactNodev2 extends AbstractContentNode<BlackboardArtifact>
*/
@NbBundle.Messages({
"# {0} - contentType",
"BlackboardArtifactNode_getTimelineSrcContentAction_actionDisplayName=View Source {0} in Timeline... "
"DataArtifactNodev2_getTimelineSrcContentAction_actionDisplayName=View Source {0} in Timeline... "
})
private Action getTimelineSrcContentAction(Content srcContent) {
if (srcContent instanceof AbstractFile) {
return new ViewFileInTimelineAction((AbstractFile) srcContent,
Bundle.BlackboardArtifactNode_getTimelineSrcContentAction_actionDisplayName(
Bundle.DataArtifactNodev2_getTimelineSrcContentAction_actionDisplayName(
getContentTypeStr(srcContent)));
} else if (srcContent instanceof DataArtifact) {
try {
if (ViewArtifactInTimelineAction.hasSupportedTimeStamp((BlackboardArtifact) srcContent)) {
return new ViewArtifactInTimelineAction((BlackboardArtifact) srcContent,
Bundle.BlackboardArtifactNode_getTimelineSrcContentAction_actionDisplayName(
getContentTypeStr(srcContent)));
}
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, MessageFormat.format("Error getting source data artifact timestamp (artifact objID={0})", srcContent.getId()), ex); //NON-NLS
}
}
// else if (srcContent instanceof DataArtifact) {
// try {
// if (hasSupportedTimeStamp((BlackboardArtifact) srcContent)) {
// return new ViewArtifactInTimelineAction((BlackboardArtifact) srcContent,
// Bundle.DataArtifactNodev2_getTimelineSrcContentAction_actionDisplayName(
// getContentTypeStr(srcContent)));
// }
// } catch (TskCoreException ex) {
// logger.log(Level.SEVERE, MessageFormat.format("Error getting source data artifact timestamp (artifact objID={0})", srcContent.getId()), ex); //NON-NLS
// }
// }
return null;
}
@ -495,53 +487,41 @@ public class DataArtifactNodev2 extends AbstractContentNode<BlackboardArtifact>
* view it in the timeline.
*
* @param art The artifact for timeline navigation action.
* @param hasSupportedTimeStamp This artifact has a supported time stamp.
*
* @return The action or null if no action should exist.
*/
@Messages({
"BlackboardArtifactNode_getTimelineArtifactAction_displayName=View Selected Item in Timeline... "
"DataArtifactNodev2_getTimelineArtifactAction_displayName=View Selected Item in Timeline... "
})
private Action getTimelineArtifactAction(BlackboardArtifact art) {
try {
// don't show ViewArtifactInTimelineAction for AnalysisResults.
if (!(art instanceof AnalysisResult) && ViewArtifactInTimelineAction.hasSupportedTimeStamp(art)) {
return new ViewArtifactInTimelineAction(art, Bundle.BlackboardArtifactNode_getTimelineArtifactAction_displayName());
}
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, MessageFormat.format("Error getting artifact timestamp (artifact objID={0})", art.getId()), ex); //NON-NLS
}
private Action getTimelineArtifactAction(BlackboardArtifact art, boolean hasSupportedTimeStamp) {
if (hasSupportedTimeStamp) {
return new ViewArtifactInTimelineAction(art, Bundle.DataArtifactNodev2_getTimelineArtifactAction_displayName());
} else {
return null;
}
/**
* Gets the name of the source content of the artifact represented by this
* node.
*
* @return The source content name.
*/
public String getSourceName() {
return srcContent.getName();
}
@NbBundle.Messages({
"BlackboardArtifactNode.createSheet.srcFile.name=Source Name",
"BlackboardArtifactNode.createSheet.srcFile.displayName=Source Name",
"BlackboardArtifactNode.createSheet.srcFile.origName=Original Name",
"BlackboardArtifactNode.createSheet.srcFile.origDisplayName=Original Name",
"BlackboardArtifactNode.createSheet.artifactType.displayName=Result Type",
"BlackboardArtifactNode.createSheet.artifactType.name=Result Type",
"BlackboardArtifactNode.createSheet.artifactDetails.displayName=Result Details",
"BlackboardArtifactNode.createSheet.artifactDetails.name=Result Details",
"BlackboardArtifactNode.createSheet.artifactMD5.displayName=MD5 Hash",
"BlackboardArtifactNode.createSheet.artifactMD5.name=MD5 Hash",
"BlackboardArtifactNode.createSheet.fileSize.name=Size",
"BlackboardArtifactNode.createSheet.fileSize.displayName=Size",
"BlackboardArtifactNode.createSheet.path.displayName=Path",
"BlackboardArtifactNode.createSheet.path.name=Path"
"DataArtifactNodev2.createSheet.srcFile.name=Source Name",
"DataArtifactNodev2.createSheet.srcFile.displayName=Source Name",
"DataArtifactNodev2.createSheet.srcFile.origName=Original Name",
"DataArtifactNodev2.createSheet.srcFile.origDisplayName=Original Name",
"DataArtifactNodev2.createSheet.artifactType.displayName=Result Type",
"DataArtifactNodev2.createSheet.artifactType.name=Result Type",
"DataArtifactNodev2.createSheet.artifactDetails.displayName=Result Details",
"DataArtifactNodev2.createSheet.artifactDetails.name=Result Details",
"DataArtifactNodev2.createSheet.artifactMD5.displayName=MD5 Hash",
"DataArtifactNodev2.createSheet.artifactMD5.name=MD5 Hash",
"DataArtifactNodev2.createSheet.fileSize.name=Size",
"DataArtifactNodev2.createSheet.fileSize.displayName=Size",
"DataArtifactNodev2.createSheet.path.displayName=Path",
"DataArtifactNodev2.createSheet.path.name=Path"
})
@Override
protected Sheet createSheet() {
Content srcContent = this.artifactRow.getSrcContent();
/*
* Create an empty property sheet.
*/
@ -559,19 +539,12 @@ public class DataArtifactNodev2 extends AbstractContentNode<BlackboardArtifact>
* the node's icon as well as the display name.
*/
sheetSet.put(new NodeProperty<>(
Bundle.BlackboardArtifactNode_createSheet_srcFile_name(),
Bundle.BlackboardArtifactNode_createSheet_srcFile_displayName(),
Bundle.DataArtifactNodev2_createSheet_srcFile_name(),
Bundle.DataArtifactNodev2_createSheet_srcFile_displayName(),
NO_DESCR,
getDisplayName()));
GetSCOTask scoTask;
if (artifact instanceof AnalysisResult
&& !(artifactType.getTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID()
|| artifactType.getTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID())) {
scoTask = updateSheetForAnalysisResult((AnalysisResult) artifact, sheetSet);
} else {
scoTask = addSCOColumns(sheetSet);
}
GetSCOTask scoTask = addSCOColumns(sheetSet);
if (TextTranslationService.getInstance().hasProvider() && UserPreferences.displayTranslatedFileNames()) {
/*
@ -580,45 +553,15 @@ public class DataArtifactNodev2 extends AbstractContentNode<BlackboardArtifact>
* node to the sheet.
*/
sheetSet.put(new NodeProperty<>(
Bundle.BlackboardArtifactNode_createSheet_srcFile_origName(),
Bundle.BlackboardArtifactNode_createSheet_srcFile_origDisplayName(),
Bundle.DataArtifactNodev2_createSheet_srcFile_origName(),
Bundle.DataArtifactNodev2_createSheet_srcFile_origDisplayName(),
NO_DESCR,
translatedSourceName != null ? srcContent.getName() : ""));
if (translatedSourceName == null) {
/*
* NOTE: The task makes its own weak reference to the listener.
*/
new FileNameTransTask(srcContent.getName(), this, listener).submit();
}
}
/*
* If the artifact represented by this node is an interesting artifact
* hit, add the type and description of the interesting artifact to the
* sheet.
*/
if (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID()) {
try {
BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT));
if (attribute != null) {
BlackboardArtifact associatedArtifact = Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboardArtifact(attribute.getValueLong());
sheetSet.put(new NodeProperty<>(
NbBundle.getMessage(DataArtifactNodev2.class,
"BlackboardArtifactNode.createSheet.artifactType.name"),
NbBundle.getMessage(DataArtifactNodev2.class,
"BlackboardArtifactNode.createSheet.artifactType.displayName"),
NO_DESCR,
associatedArtifact.getDisplayName()));
sheetSet.put(new NodeProperty<>(
NbBundle.getMessage(DataArtifactNodev2.class,
"BlackboardArtifactNode.createSheet.artifactDetails.name"),
NbBundle.getMessage(DataArtifactNodev2.class,
"BlackboardArtifactNode.createSheet.artifactDetails.displayName"),
NO_DESCR,
associatedArtifact.getShortDescription()));
}
} catch (TskCoreException | NoCurrentCaseException ex) {
logger.log(Level.SEVERE, MessageFormat.format("Error getting associated artifact of TSK_INTERESTING_ARTIFACT_HIT artifact (objID={0}))", artifact.getId()), ex); //NON-NLS
new FileNameTransTask(srcContent.getName(), this, fileNameTranslationListener).submit();
}
}
@ -635,178 +578,17 @@ public class DataArtifactNodev2 extends AbstractContentNode<BlackboardArtifact>
entry.getValue()));
}
/*
* Add any "custom properties" for the node to the sheet.
*/
if (customProperties != null) {
for (NodeProperty<? extends Object> np : customProperties) {
sheetSet.put(np);
}
}
/*
* If the artifact represented by this node is a file extension mismatch
* artifact, add the extension and type of the artifact's source file to
* the sheet.
*/
final int artifactTypeId = artifact.getArtifactTypeID();
if (artifactTypeId == BlackboardArtifact.ARTIFACT_TYPE.TSK_EXT_MISMATCH_DETECTED.getTypeID()) {
String ext = ""; //NON-NLS
String actualMimeType = ""; //NON-NLS
if (srcContent instanceof AbstractFile) {
AbstractFile file = (AbstractFile) srcContent;
ext = file.getNameExtension();
actualMimeType = file.getMIMEType();
if (actualMimeType == null) {
actualMimeType = ""; //NON-NLS
}
}
sheetSet.put(new NodeProperty<>(
NbBundle.getMessage(DataArtifactNodev2.class,
"BlackboardArtifactNode.createSheet.ext.name"),
NbBundle.getMessage(DataArtifactNodev2.class,
"BlackboardArtifactNode.createSheet.ext.displayName"),
NO_DESCR,
ext));
sheetSet.put(new NodeProperty<>(
NbBundle.getMessage(DataArtifactNodev2.class,
"BlackboardArtifactNode.createSheet.mimeType.name"),
NbBundle.getMessage(DataArtifactNodev2.class,
"BlackboardArtifactNode.createSheet.mimeType.displayName"),
NO_DESCR,
actualMimeType));
}
/*
* If the type of the artifact represented by this node dictates the
* addition of the source content's unique path, add it to the sheet.
*/
if (artifactType != null && artifactType.getCategory() == Category.ANALYSIS_RESULT) {
String sourcePath = ""; //NON-NLS
try {
sourcePath = srcContent.getUniquePath();
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, MessageFormat.format("Error getting unique path of source content (artifact objID={0})", artifact.getId()), ex); //NON-NLS
}
if (sourcePath.isEmpty() == false) {
sheetSet.put(new NodeProperty<>(
NbBundle.getMessage(DataArtifactNodev2.class,
"BlackboardArtifactNode.createSheet.filePath.name"),
NbBundle.getMessage(DataArtifactNodev2.class,
"BlackboardArtifactNode.createSheet.filePath.displayName"),
NO_DESCR,
sourcePath));
}
/*
* If the type of the artifact represented by this node dictates the
* addition of the source content's file metadata, add it to the
* sheet. Otherwise, add the data source to the sheet.
*/
if (Arrays.asList(SHOW_FILE_METADATA).contains(artifactTypeId)) {
AbstractFile file = srcContent instanceof AbstractFile ? (AbstractFile) srcContent : null;
sheetSet.put(new NodeProperty<>(
NbBundle.getMessage(DataArtifactNodev2.class,
"ContentTagNode.createSheet.fileModifiedTime.name"),
NbBundle.getMessage(DataArtifactNodev2.class,
"ContentTagNode.createSheet.fileModifiedTime.displayName"),
"",
file == null ? "" : TimeZoneUtils.getFormattedTime(file.getMtime())));
sheetSet.put(new NodeProperty<>(
NbBundle.getMessage(DataArtifactNodev2.class,
"ContentTagNode.createSheet.fileChangedTime.name"),
NbBundle.getMessage(DataArtifactNodev2.class,
"ContentTagNode.createSheet.fileChangedTime.displayName"),
"",
file == null ? "" : TimeZoneUtils.getFormattedTime(file.getCtime())));
sheetSet.put(new NodeProperty<>(
NbBundle.getMessage(DataArtifactNodev2.class,
"ContentTagNode.createSheet.fileAccessedTime.name"),
NbBundle.getMessage(DataArtifactNodev2.class,
"ContentTagNode.createSheet.fileAccessedTime.displayName"),
"",
file == null ? "" : TimeZoneUtils.getFormattedTime(file.getAtime())));
sheetSet.put(new NodeProperty<>(
NbBundle.getMessage(DataArtifactNodev2.class,
"ContentTagNode.createSheet.fileCreatedTime.name"),
NbBundle.getMessage(DataArtifactNodev2.class,
"ContentTagNode.createSheet.fileCreatedTime.displayName"),
"",
file == null ? "" : TimeZoneUtils.getFormattedTime(file.getCrtime())));
sheetSet.put(new NodeProperty<>(
NbBundle.getMessage(DataArtifactNodev2.class,
"ContentTagNode.createSheet.fileSize.name"),
NbBundle.getMessage(DataArtifactNodev2.class,
"ContentTagNode.createSheet.fileSize.displayName"),
"",
file == null ? "" : file.getSize()));
sheetSet.put(new NodeProperty<>(
Bundle.BlackboardArtifactNode_createSheet_artifactMD5_name(),
Bundle.BlackboardArtifactNode_createSheet_artifactMD5_displayName(),
"",
file == null ? "" : StringUtils.defaultString(file.getMd5Hash())));
}
} else {
String dataSourceStr = "";
try {
Content dataSource = srcContent.getDataSource();
if (dataSource != null) {
dataSourceStr = dataSource.getName();
} else {
dataSourceStr = getRootAncestorName();
}
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, MessageFormat.format("Error getting source data source name (artifact objID={0})", artifact.getId()), ex); //NON-NLS
}
String dataSourceStr = this.artifactRow.getDataSourceName();
if (dataSourceStr.isEmpty() == false) {
sheetSet.put(new NodeProperty<>(
NbBundle.getMessage(DataArtifactNodev2.class,
"BlackboardArtifactNode.createSheet.dataSrc.name"),
"DataArtifactNodev2.createSheet.dataSrc.name"),
NbBundle.getMessage(DataArtifactNodev2.class,
"BlackboardArtifactNode.createSheet.dataSrc.displayName"),
"DataArtifactNodev2.createSheet.dataSrc.displayName"),
NO_DESCR,
dataSourceStr));
}
}
/*
* If the artifact represented by this node is an EXIF artifact, add the
* source file size and path to the sheet.
*/
if (artifactTypeId == BlackboardArtifact.ARTIFACT_TYPE.TSK_METADATA_EXIF.getTypeID()) {
long size = 0;
String path = ""; //NON-NLS
if (srcContent instanceof AbstractFile) {
AbstractFile af = (AbstractFile) srcContent;
size = af.getSize();
try {
path = af.getUniquePath();
} catch (TskCoreException ex) {
path = af.getParentPath();
}
}
sheetSet.put(new NodeProperty<>(
NbBundle.getMessage(DataArtifactNodev2.class,
"BlackboardArtifactNode.createSheet.fileSize.name"),
NbBundle.getMessage(DataArtifactNodev2.class,
"BlackboardArtifactNode.createSheet.fileSize.displayName"),
NO_DESCR,
size));
sheetSet
.put(new NodeProperty<>(
NbBundle.getMessage(DataArtifactNodev2.class,
"BlackboardArtifactNode.createSheet.path.name"),
NbBundle.getMessage(DataArtifactNodev2.class,
"BlackboardArtifactNode.createSheet.path.displayName"),
NO_DESCR,
path));
}
if (scoTask != null) {
backgroundTasksPool.submit(scoTask);
@ -815,7 +597,6 @@ public class DataArtifactNodev2 extends AbstractContentNode<BlackboardArtifact>
return sheet;
}
/**
* Adds a "custom" property to the property sheet of this node, independent
* of the artifact this node represents or its source content.
@ -926,11 +707,6 @@ public class DataArtifactNodev2 extends AbstractContentNode<BlackboardArtifact>
}
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
public boolean isLeafTypeNode() {
return true;
@ -941,21 +717,6 @@ public class DataArtifactNodev2 extends AbstractContentNode<BlackboardArtifact>
return getClass().getName();
}
@Override
public <T> T accept(ContentNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Messages({
"BlackboardArtifactNode_analysisSheet_sourceType_name=Source Type",
"BlackboardArtifactNode_analysisSheet_soureName_name=Source Name",
"BlackboardArtifactNode_analysisSheet_score_name=Score",
"BlackboardArtifactNode_analysisSheet_conclusion_name=Conclusion",
"BlackboardArtifactNode_analysisSheet_configuration_name=Configuration",
"BlackboardArtifactNode_analysisSheet_justifaction_name=Justification"
})
private GetSCOTask addSCOColumns(Sheet.Set sheetSet) {
if (!UserPreferences.getHideSCOColumns()) {
/*
@ -966,19 +727,19 @@ public class DataArtifactNodev2 extends AbstractContentNode<BlackboardArtifact>
* and this node's PropertyChangeListener will update the sheet.
*/
sheetSet.put(new NodeProperty<>(
Bundle.BlackboardArtifactNode_createSheet_score_name(),
Bundle.BlackboardArtifactNode_createSheet_score_displayName(),
Bundle.DataArtifactNodev2_createSheet_score_name(),
Bundle.DataArtifactNodev2_createSheet_score_displayName(),
VALUE_LOADING,
""));
sheetSet.put(new NodeProperty<>(
Bundle.BlackboardArtifactNode_createSheet_comment_name(),
Bundle.BlackboardArtifactNode_createSheet_comment_displayName(),
Bundle.DataArtifactNodev2_createSheet_comment_name(),
Bundle.DataArtifactNodev2_createSheet_comment_displayName(),
VALUE_LOADING,
""));
if (CentralRepository.isEnabled()) {
sheetSet.put(new NodeProperty<>(
Bundle.BlackboardArtifactNode_createSheet_count_name(),
Bundle.BlackboardArtifactNode_createSheet_count_displayName(),
Bundle.DataArtifactNodev2_createSheet_count_name(),
Bundle.DataArtifactNodev2_createSheet_count_displayName(),
VALUE_LOADING,
""));
}
@ -987,42 +748,6 @@ public class DataArtifactNodev2 extends AbstractContentNode<BlackboardArtifact>
return null;
}
/**
* Returns a displayable type string for the given content object.
*
* If the content object is a artifact of a custom type then this method may
* cause a DB call BlackboardArtifact.getType
*
* @param source The object to determine the type of.
*
* @return A string representing the content type.
*/
private String getSourceObjType(Content source) {
if (source instanceof BlackboardArtifact) {
BlackboardArtifact srcArtifact = (BlackboardArtifact) source;
try {
return srcArtifact.getType().getDisplayName();
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Failed to get custom artifact type id=" + source.getId(), ex);
}
} else if (srcContent instanceof Volume) {
return TskData.ObjectType.VOL.toString();
} else if (srcContent instanceof AbstractFile) {
return TskData.ObjectType.ABSTRACTFILE.toString();
} else if (srcContent instanceof Image) {
return TskData.ObjectType.IMG.toString();
} else if (srcContent instanceof VolumeSystem) {
return TskData.ObjectType.VS.toString();
} else if (srcContent instanceof OsAccount) {
return TskData.ObjectType.OS_ACCOUNT.toString();
} else if (srcContent instanceof HostAddress) {
return TskData.ObjectType.HOST_ADDRESS.toString();
} else if (srcContent instanceof Pool) {
return TskData.ObjectType.POOL.toString();
}
return "";
}
/**
* Update the SCO columns with the data retrieved in the background thread.
*
@ -1035,21 +760,21 @@ public class DataArtifactNodev2 extends AbstractContentNode<BlackboardArtifact>
public void run() {
if (scoData.getScoreAndDescription() != null) {
updateSheet(new NodeProperty<>(
Bundle.BlackboardArtifactNode_createSheet_score_name(),
Bundle.BlackboardArtifactNode_createSheet_score_displayName(),
Bundle.DataArtifactNodev2_createSheet_score_name(),
Bundle.DataArtifactNodev2_createSheet_score_displayName(),
scoData.getScoreAndDescription().getRight(),
scoData.getScoreAndDescription().getLeft()));
}
if (scoData.getComment() != null) {
updateSheet(new NodeProperty<>(
Bundle.BlackboardArtifactNode_createSheet_comment_name(),
Bundle.BlackboardArtifactNode_createSheet_comment_displayName(),
Bundle.DataArtifactNodev2_createSheet_comment_name(),
Bundle.DataArtifactNodev2_createSheet_comment_displayName(),
NO_DESCR, scoData.getComment()));
}
if (scoData.getCountAndDescription() != null) {
updateSheet(new NodeProperty<>(
Bundle.BlackboardArtifactNode_createSheet_count_name(),
Bundle.BlackboardArtifactNode_createSheet_count_displayName(),
Bundle.DataArtifactNodev2_createSheet_count_name(),
Bundle.DataArtifactNodev2_createSheet_count_displayName(),
scoData.getCountAndDescription().getRight(),
scoData.getCountAndDescription().getLeft()));
}
@ -1058,25 +783,96 @@ public class DataArtifactNodev2 extends AbstractContentNode<BlackboardArtifact>
}
/**
* Sets the displayName of the node based on the source content.
* Gets all of the tags applied to the artifact represented by this node and
* its source content.
*
* @return The tags.
*/
private void setDisplayNameBySourceContent() {
if (srcContent instanceof BlackboardArtifact) {
@Override
protected final List<Tag> getAllTagsFromDatabase() {
List<Tag> tags = new ArrayList<>();
try {
setDisplayName(((BlackboardArtifact) srcContent).getShortDescription());
} catch (TskCoreException ex) {
// Log the error, but set the display name to
// Content.getName so there is something visible to the user.
logger.log(Level.WARNING, "Failed to get short description for artifact id = " + srcContent.getId(), ex);
setDisplayName(srcContent.getName());
tags.addAll(Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsByArtifact(artifact));
tags.addAll(Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsByContent(srcContent));
} catch (TskCoreException | NoCurrentCaseException ex) {
logger.log(Level.SEVERE, MessageFormat.format("Error getting tags for artifact and its source content (artifact objID={0})", artifact.getId()), ex);
}
} else if (srcContent instanceof OsAccount) {
setDisplayName(((OsAccount) srcContent).getAddr().orElse(srcContent.getName()));
return tags;
}
/**
* Computes the value of the comment property ("C" in S, C, O) for the
* artifact represented by this node.
*
* An icon is displayed in the property sheet if a commented tag has been
* applied to the artifact or its source content, or if there is a
* corresponding commented correlation attribute instance in the central
* repository.
*
* @param tags The tags applied to the artifact and its source
* content.
* @param attributes A correlation attribute instance for the central
* repository lookup.
*
* @return The value of the comment property.
*/
@Override
protected DataResultViewerTable.HasCommentStatus getCommentProperty(List<Tag> tags, List<CorrelationAttributeInstance> attributes) {
/*
* Has a tag with a comment been applied to the artifact or its source
* content?
*/
DataResultViewerTable.HasCommentStatus status = tags.size() > 0 ? DataResultViewerTable.HasCommentStatus.TAG_NO_COMMENT : DataResultViewerTable.HasCommentStatus.NO_COMMENT;
for (Tag tag : tags) {
if (!StringUtils.isBlank(tag.getComment())) {
status = DataResultViewerTable.HasCommentStatus.TAG_COMMENT;
break;
}
}
/*
* Is there a comment in the CR for anything that matches the value and
* type of the specified attributes.
*/
try {
if (CentralRepoDbUtil.commentExistsOnAttributes(attributes)) {
if (status == DataResultViewerTable.HasCommentStatus.TAG_COMMENT) {
status = DataResultViewerTable.HasCommentStatus.CR_AND_TAG_COMMENTS;
} else {
setDisplayName(srcContent.getName());
status = DataResultViewerTable.HasCommentStatus.CR_COMMENT;
}
}
} catch (CentralRepoException ex) {
logger.log(Level.SEVERE, "Attempted to Query CR for presence of comments in a Blackboard Artifact node and was unable to perform query, comment column will only reflect caseDB", ex);
}
return status;
}
setShortDescription(getDisplayName());
@Override
protected Pair<Long, String> getCountPropertyAndDescription(CorrelationAttributeInstance attribute, String defaultDescription) {
Long count = -1L;
String description = defaultDescription;
try {
if (attribute != null && StringUtils.isNotBlank(attribute.getCorrelationValue())) {
count = CentralRepository.getInstance().getCountCasesWithOtherInstances(attribute);
description = Bundle.DataArtifactNodev2_createSheet_count_description(count, attribute.getCorrelationType().getDisplayName());
} else if (attribute != null) {
description = Bundle.DataArtifactNodev2_createSheet_count_noCorrelationValues_description();
}
} catch (CentralRepoException ex) {
logger.log(Level.SEVERE, MessageFormat.format("Error querying central repository for other occurences count (artifact objID={0}, corrAttrType={1}, corrAttrValue={2})", artifact.getId(), attribute.getCorrelationType(), attribute.getCorrelationValue()), ex);
} catch (CorrelationAttributeNormalizationException ex) {
logger.log(Level.SEVERE, MessageFormat.format("Error normalizing correlation attribute for central repository query (artifact objID={0}, corrAttrType={2}, corrAttrValue={3})", artifact.getId(), attribute.getCorrelationType(), attribute.getCorrelationValue()), ex);
}
return Pair.of(count, description);
}
@Override
public <T> T accept(ContentNodeVisitor<T> visitor) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
}

View File

@ -88,8 +88,8 @@ public class ThreePanelDAO {
: null;
Content srcContent = artifact.getParent();
String srcContentTypeName = getSourceObjType(srcContent);
rows.add(new DataArtifactRow(id, attributeValues, srcContent, srcContentTypeName, linkedFile));
String dataSourceName = getDataSourceName(srcContent);
rows.add(new DataArtifactRow(id, attributeValues, artifact, srcContent, linkedFile, dataSourceName));
}
List<BlackboardAttribute.Type> attributeTypeSortedList = attributeTypes.stream()
@ -99,6 +99,33 @@ public class ThreePanelDAO {
return new DataArtifactTableDTO(artType, attributeTypeSortedList, rows);
}
private String getDataSourceName(Content srcContent) throws TskCoreException {
Content dataSource = srcContent.getDataSource();
if (dataSource != null) {
return dataSource.getName();
} else {
return getRootAncestorName(srcContent);
}
}
/**
* Gets the name of the root ancestor of the source content for the artifact
* represented by this node.
*
* @param srcContent The source content.
*
* @return The root ancestor name or the empty string if an error occurs.
*/
private String getRootAncestorName(Content srcContent) throws TskCoreException {
String parentName = srcContent.getName();
Content parent = srcContent;
while ((parent = parent.getParent()) != null) {
parentName = parent.getName();
}
return parentName;
}
/**
* Returns a displayable type string for the given content object.
*
@ -226,17 +253,18 @@ public class ThreePanelDAO {
private final Map<String, Object> attributeValues;
private final DataArtifact dataArtifact;
private final Content srcContent;
private final String srcContentTypeName;
private final Content linkedFile;
private String dataSourceName;
public DataArtifactRow(long id, Map<String, Object> attributeValues, Content srcContent, String srcContentTypeName, Content linkedFile) {
public DataArtifactRow(long id, Map<String, Object> attributeValues, DataArtifact dataArtifact, Content srcContent, Content linkedFile, String dataSourceName) {
this.id = id;
this.attributeValues = attributeValues;
this.dataArtifact = dataArtifact;
this.srcContent = srcContent;
this.srcContentTypeName = srcContentTypeName;
this.linkedFile = linkedFile;
this.dataSourceName = dataSourceName;
}
public long getId() {
@ -247,12 +275,12 @@ public class ThreePanelDAO {
return attributeValues;
}
public Content getSrcContent() {
return srcContent;
public DataArtifact getDataArtifact() {
return dataArtifact;
}
public String getSrcContentTypeName() {
return srcContentTypeName;
public Content getSrcContent() {
return srcContent;
}
public Content getLinkedFile() {