diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/ContextViewer.form b/Core/src/org/sleuthkit/autopsy/contentviewers/ContextViewer.form
new file mode 100644
index 0000000000..c7f826dc9e
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/contentviewers/ContextViewer.form
@@ -0,0 +1,95 @@
+
+
+
diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/ContextViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/ContextViewer.java
new file mode 100644
index 0000000000..3c2e4e526f
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/contentviewers/ContextViewer.java
@@ -0,0 +1,357 @@
+/*
+ * Autopsy Forensic Browser
+ *
+ * Copyright 2019 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.contentviewers;
+
+import java.awt.Component;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import org.apache.commons.lang.StringUtils;
+import org.openide.nodes.Node;
+import org.openide.util.NbBundle;
+import org.openide.util.lookup.ServiceProvider;
+import org.sleuthkit.autopsy.casemodule.Case;
+import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
+import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer;
+import org.sleuthkit.autopsy.coreutils.Logger;
+import org.sleuthkit.autopsy.directorytree.DirectoryTreeTopComponent;
+import org.sleuthkit.datamodel.AbstractFile;
+import org.sleuthkit.datamodel.BlackboardArtifact;
+import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT;
+import org.sleuthkit.datamodel.BlackboardAttribute;
+import org.sleuthkit.datamodel.SleuthkitCase;
+import org.sleuthkit.datamodel.TskCoreException;
+
+/**
+ * Displays additional context for the selected file, such as its source, and
+ * usage, if known.
+ *
+ */
+@ServiceProvider(service = DataContentViewer.class, position = 7)
+@NbBundle.Messages({
+ "ContextViewer.title=Context Viewer",
+ "ContextViewer.toolTip=Displays context for selected file."
+})
+public final class ContextViewer extends javax.swing.JPanel implements DataContentViewer {
+
+ private static final long serialVersionUID = 1L;
+ private static final Logger logger = Logger.getLogger(ContextViewer.class.getName());
+
+ // defines a list of artifacts that provide context for a file
+ private static final List SOURCE_CONTEXT_ARTIFACTS = new ArrayList<>();
+
+ static {
+ SOURCE_CONTEXT_ARTIFACTS.add(TSK_ASSOCIATED_OBJECT);
+ }
+
+ private BlackboardArtifact sourceContextArtifact;
+
+ /**
+ * Creates new form ContextViewer
+ */
+ public ContextViewer() {
+
+ initComponents();
+ }
+
+ /**
+ * 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
+ * regenerated by the Form Editor.
+ */
+ @SuppressWarnings("unchecked")
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ jSourceGoToResultButton = new javax.swing.JButton();
+ jLabel1 = new javax.swing.JLabel();
+ jSourceNameLabel = new javax.swing.JLabel();
+ jSourceTextLabel = new javax.swing.JLabel();
+
+ org.openide.awt.Mnemonics.setLocalizedText(jSourceGoToResultButton, org.openide.util.NbBundle.getMessage(ContextViewer.class, "ContextViewer.jSourceGoToResultButton.text")); // NOI18N
+ jSourceGoToResultButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ jSourceGoToResultButtonActionPerformed(evt);
+ }
+ });
+
+ jLabel1.setFont(new java.awt.Font("Dialog", 1, 14)); // NOI18N
+ org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(ContextViewer.class, "ContextViewer.jLabel1.text")); // NOI18N
+
+ org.openide.awt.Mnemonics.setLocalizedText(jSourceNameLabel, org.openide.util.NbBundle.getMessage(ContextViewer.class, "ContextViewer.jSourceNameLabel.text")); // NOI18N
+
+ org.openide.awt.Mnemonics.setLocalizedText(jSourceTextLabel, org.openide.util.NbBundle.getMessage(ContextViewer.class, "ContextViewer.jSourceTextLabel.text")); // NOI18N
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+ this.setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jLabel1)
+ .addGroup(layout.createSequentialGroup()
+ .addGap(6, 6, 6)
+ .addComponent(jSourceNameLabel)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(jSourceTextLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 192, Short.MAX_VALUE)))
+ .addGap(36, 36, 36))
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(jSourceGoToResultButton)
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(jLabel1)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(jSourceNameLabel)
+ .addComponent(jSourceTextLabel))
+ .addGap(18, 18, 18)
+ .addComponent(jSourceGoToResultButton)
+ .addGap(0, 203, Short.MAX_VALUE))
+ );
+ }// //GEN-END:initComponents
+
+ private void jSourceGoToResultButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jSourceGoToResultButtonActionPerformed
+
+ final DirectoryTreeTopComponent dtc = DirectoryTreeTopComponent.findInstance();
+
+ // Navigate to the source context artifact.
+ if (sourceContextArtifact != null) {
+ dtc.viewArtifact(sourceContextArtifact);
+ }
+
+ }//GEN-LAST:event_jSourceGoToResultButtonActionPerformed
+
+ @Override
+ public void setNode(Node selectedNode) {
+ if ((selectedNode == null) || (!isSupported(selectedNode))) {
+ resetComponent();
+ return;
+ }
+
+ AbstractFile file = selectedNode.getLookup().lookup(AbstractFile.class);
+ try {
+ populateSourceContextData(file);
+ } catch (NoCurrentCaseException | TskCoreException ex) {
+ logger.log(Level.SEVERE, "Exception displaying context for file {0}", file); //NON-NLS
+ }
+ }
+
+ @Override
+ public String getTitle() {
+ return Bundle.ContextViewer_title();
+ }
+
+ @Override
+ public String getToolTip() {
+ return Bundle.ContextViewer_toolTip();
+ }
+
+ @Override
+ public DataContentViewer createInstance() {
+ return new ContextViewer();
+ }
+
+ @Override
+ public Component getComponent() {
+ return this;
+ }
+
+ @Override
+ public void resetComponent() {
+ setSourceName("");
+ setSourceText("");
+ }
+
+ @Override
+ public boolean isSupported(Node node) {
+
+ // check if the node has an abstract file and the file has any context defining artifacts.
+ if (node.getLookup().lookup(AbstractFile.class) != null) {
+ AbstractFile abstractFile = node.getLookup().lookup(AbstractFile.class);
+ for (BlackboardArtifact.ARTIFACT_TYPE artifactType : SOURCE_CONTEXT_ARTIFACTS) {
+ List artifactsList;
+ try {
+ artifactsList = abstractFile.getArtifacts(artifactType);
+ if (!artifactsList.isEmpty()) {
+ return true;
+ }
+ } catch (TskCoreException ex) {
+ logger.log(Level.SEVERE, "Exception while looking up context artifacts for file {0}", abstractFile); //NON-NLS
+ }
+ }
+
+ }
+
+ return false;
+ }
+
+ @Override
+ public int isPreferred(Node node) {
+ return 1;
+ }
+
+ private void populateSourceContextData(AbstractFile sourceFile) throws NoCurrentCaseException, TskCoreException {
+
+ SleuthkitCase tskCase = Case.getCurrentCaseThrows().getSleuthkitCase();
+
+ // Check for all context artifacts
+ boolean foundASource = false;
+ for (BlackboardArtifact.ARTIFACT_TYPE artifactType : SOURCE_CONTEXT_ARTIFACTS) {
+ List artifactsList = tskCase.getBlackboardArtifacts(artifactType, sourceFile.getId());
+ if (!artifactsList.isEmpty()) {
+ foundASource = true;
+ }
+ for (BlackboardArtifact contextArtifact : artifactsList) {
+ addSourceEntry(contextArtifact);
+ }
+ }
+ if (foundASource == false) {
+ setSourceName("Unknown");
+ showSourceText(false);
+ }
+ }
+
+ @NbBundle.Messages({
+ "ContextViewer.attachmentSource=Attached to: ",
+ "ContextViewer.downloadSource=Downloaded from: "
+ })
+ private void addSourceEntry(BlackboardArtifact artifact) throws TskCoreException {
+
+ if (BlackboardArtifact.ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT.getTypeID() == artifact.getArtifactTypeID()) {
+ BlackboardAttribute associatedArtifactAttribute = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT));
+ if (associatedArtifactAttribute != null) {
+ long artifactId = associatedArtifactAttribute.getValueLong();
+ BlackboardArtifact associatedArtifact = artifact.getSleuthkitCase().getBlackboardArtifact(artifactId);
+
+ //save the artifact id for "Go to Result" button
+ sourceContextArtifact = associatedArtifact;
+
+ if (BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE.getTypeID() == associatedArtifact.getArtifactTypeID()
+ || BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID() == associatedArtifact.getArtifactTypeID()) {
+
+ setSourceName(Bundle.ContextViewer_attachmentSource());
+ setSourceText(msgArtifactToAbbreiviatedString(associatedArtifact));
+
+ } else if (BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID() == associatedArtifact.getArtifactTypeID()
+ || BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE.getTypeID() == associatedArtifact.getArtifactTypeID()) {
+
+ setSourceName(Bundle.ContextViewer_downloadSource());
+ setSourceText(webDownloadArtifactToString(associatedArtifact));
+ }
+ }
+ }
+
+ }
+
+ private void setSourceName(String nameLabel) {
+ jSourceNameLabel.setText(nameLabel);
+ }
+
+ private void setSourceText(String text) {
+ jSourceTextLabel.setText(text);
+ showSourceText(true);
+ }
+
+ private void showSourceText(boolean isVisible) {
+ jSourceTextLabel.setVisible(isVisible);
+ }
+
+ private String webDownloadArtifactToString(BlackboardArtifact artifact) throws TskCoreException {
+ StringBuilder sb = new StringBuilder(1024);
+ Map attributesMap = getAttributesMap(artifact);
+
+ if (BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID() == artifact.getArtifactTypeID()
+ || BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE.getTypeID() == artifact.getArtifactTypeID()) {
+ appendAttributeString(sb, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL, attributesMap, "URL");
+ appendAttributeString(sb, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED, attributesMap, "On");
+ }
+ return sb.toString();
+ }
+
+ private String msgArtifactToAbbreiviatedString(BlackboardArtifact artifact) throws TskCoreException {
+
+ StringBuilder sb = new StringBuilder(1024);
+ Map attributesMap = getAttributesMap(artifact);
+
+ if (BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE.getTypeID() == artifact.getArtifactTypeID()) {
+ sb.append("Message ");
+ appendAttributeString(sb, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM, attributesMap, "From");
+ appendAttributeString(sb, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO, attributesMap, "To");
+ appendAttributeString(sb, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, attributesMap, "On");
+ } else if (BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID() == artifact.getArtifactTypeID()) {
+ sb.append("Email ");
+ appendAttributeString(sb, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL_FROM, attributesMap, "From");
+ appendAttributeString(sb, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL_TO, attributesMap, "To");
+ appendAttributeString(sb, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_SENT, attributesMap, "On");
+ }
+ return sb.toString();
+ }
+
+ private void appendAttributeString(StringBuilder sb, BlackboardAttribute.ATTRIBUTE_TYPE attribType,
+ Map attributesMap, String prependStr) {
+
+ BlackboardAttribute attribute = attributesMap.get(attribType);
+ if (attribute != null) {
+ String attrVal = attribute.getDisplayString();
+ if (!StringUtils.isEmpty(attrVal)) {
+ if (!StringUtils.isEmpty(prependStr)) {
+ sb.append(prependStr).append(" ");
+ }
+ sb.append(StringUtils.abbreviate(attrVal, 200)).append(" ");
+ }
+ }
+ }
+
+ private String getAttribNameValue(BlackboardAttribute.ATTRIBUTE_TYPE attribType, Map attributesMap) {
+ BlackboardAttribute attribute = attributesMap.get(attribType);
+ if (attribute != null) {
+ return String.format("%s : %s", attribType.getDisplayName(), attribute.getDisplayString());
+ }
+ return null;
+ }
+
+ private Map getAttributesMap(BlackboardArtifact artifact) throws TskCoreException {
+ Map attributeMap = new HashMap<>();
+
+ List attributeList = artifact.getAttributes();
+ for (BlackboardAttribute attribute : attributeList) {
+ BlackboardAttribute.ATTRIBUTE_TYPE type = BlackboardAttribute.ATTRIBUTE_TYPE.fromID(attribute.getAttributeType().getTypeID());
+ attributeMap.put(type, attribute);
+ }
+
+ return attributeMap;
+ }
+
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JLabel jLabel1;
+ private javax.swing.JButton jSourceGoToResultButton;
+ private javax.swing.JLabel jSourceNameLabel;
+ private javax.swing.JLabel jSourceTextLabel;
+ // End of variables declaration//GEN-END:variables
+}
diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/Metadata.java b/Core/src/org/sleuthkit/autopsy/contentviewers/Metadata.java
index 126299f120..5f6c3eac9b 100644
--- a/Core/src/org/sleuthkit/autopsy/contentviewers/Metadata.java
+++ b/Core/src/org/sleuthkit/autopsy/contentviewers/Metadata.java
@@ -191,12 +191,21 @@ public class Metadata extends javax.swing.JPanel implements DataContentViewer {
}
try {
- List sourceArtifacts = file.getArtifacts(ARTIFACT_TYPE.TSK_DOWNLOAD_SOURCE);
- if (!sourceArtifacts.isEmpty()) {
- BlackboardArtifact artifact = sourceArtifacts.get(0);
- BlackboardAttribute urlAttr = artifact.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_URL));
- if (urlAttr != null) {
- addRow(sb, NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.downloadSource"), urlAttr.getValueString());
+ List associatedObjectArtifacts = file.getArtifacts(ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT);
+ if (!associatedObjectArtifacts.isEmpty()) {
+ BlackboardArtifact artifact = associatedObjectArtifacts.get(0);
+ BlackboardAttribute associatedArtifactAttribute = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT));
+ if (associatedArtifactAttribute != null) {
+ long artifactId = associatedArtifactAttribute.getValueLong();
+ BlackboardArtifact associatedArtifact = artifact.getSleuthkitCase().getBlackboardArtifact(artifactId);
+ if (associatedArtifact != null &&
+ ((associatedArtifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID()) ||
+ (associatedArtifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_WEB_CACHE.getTypeID())) ) {
+ BlackboardAttribute urlAttr = associatedArtifact.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_URL));
+ if (urlAttr != null) {
+ addRow(sb, NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.downloadSource"), urlAttr.getValueString());
+ }
+ }
}
}
} catch (TskCoreException ex) {
diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ExtractedContent.java b/Core/src/org/sleuthkit/autopsy/datamodel/ExtractedContent.java
index e52e50c31c..ada8d91b36 100644
--- a/Core/src/org/sleuthkit/autopsy/datamodel/ExtractedContent.java
+++ b/Core/src/org/sleuthkit/autopsy/datamodel/ExtractedContent.java
@@ -238,8 +238,8 @@ public class ExtractedContent implements AutopsyVisitableItem {
doNotShow.add(new BlackboardArtifact.Type(TSK_INTERESTING_ARTIFACT_HIT));
doNotShow.add(new BlackboardArtifact.Type(TSK_ACCOUNT));
doNotShow.add(new BlackboardArtifact.Type(TSK_DATA_SOURCE_USAGE));
- doNotShow.add(new BlackboardArtifact.Type(TSK_DOWNLOAD_SOURCE));
- doNotShow.add(new BlackboardArtifact.Type(TSK_ASSOCIATED_OBJECT));
+ //doNotShow.add(new BlackboardArtifact.Type(TSK_DOWNLOAD_SOURCE));
+ //doNotShow.add(new BlackboardArtifact.Type(TSK_ASSOCIATED_OBJECT));
}
private final PropertyChangeListener pcl = (PropertyChangeEvent evt) -> {
diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chrome.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chrome.java
index f75132c610..49ac9911fe 100644
--- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chrome.java
+++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chrome.java
@@ -554,22 +554,24 @@ class Chrome extends Extract {
RecentActivityExtracterModuleFactory.getModuleName(),
NbBundle.getMessage(this.getClass(), "Chrome.moduleName")));
- BlackboardArtifact bbart = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, downloadFile, bbattributes);
- if (bbart != null) {
- bbartifacts.add(bbart);
- }
-
- // find the downloaded file and create a TSK_DOWNLOAD_SOURCE for it..
- try {
- for (AbstractFile downloadedFile : fileManager.findFiles(dataSource, FilenameUtils.getName(fullPath), FilenameUtils.getPath(fullPath))) {
- BlackboardArtifact downloadSourceArt = downloadedFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_DOWNLOAD_SOURCE);
- downloadSourceArt.addAttributes(createDownloadSourceAttributes(result.get("url").toString()));
-
- bbartifacts.add(downloadSourceArt);
- break;
+ BlackboardArtifact webDownloadArtifact = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, downloadFile, bbattributes);
+ if (webDownloadArtifact != null) {
+ bbartifacts.add(webDownloadArtifact);
+
+ // find the downloaded file and create a TSK_ASSOCIATED_OBJECT for it, associating it with the TSK_WEB_DOWNLOAD artifact.
+ try {
+ for (AbstractFile downloadedFile : fileManager.findFiles(dataSource, FilenameUtils.getName(fullPath), FilenameUtils.getPath(fullPath))) {
+ BlackboardArtifact associatedObjectArtifact = downloadedFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT);
+ associatedObjectArtifact.addAttribute(
+ new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT,
+ RecentActivityExtracterModuleFactory.getModuleName(), webDownloadArtifact.getArtifactID()));
+
+ bbartifacts.add(associatedObjectArtifact);
+ break;
+ }
+ } catch (TskCoreException ex) {
+ logger.log(Level.SEVERE, String.format("Error creating associated object artifact for file '%s'", fullPath), ex); //NON-NLS
}
- } catch (TskCoreException ex) {
- logger.log(Level.SEVERE, String.format("Error creating download source artifact for file '%s'", fullPath), ex); //NON-NLS
}
}
diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ChromeCacheExtractor.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ChromeCacheExtractor.java
index efaf8934b2..4e1b5c3931 100644
--- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ChromeCacheExtractor.java
+++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ChromeCacheExtractor.java
@@ -380,12 +380,12 @@ final class ChromeCacheExtractor {
* Extracts the files if needed and adds as derived files, creates artifacts
*
* @param cacheEntryAddress cache entry address
- * @param sourceArtifacts any source artifacts created are added to this collection
+ * @param associatedObjectArtifacts any associated object artifacts created are added to this collection
* @param webCacheArtifacts any web cache artifacts created are added to this collection
*
* @return Optional derived file, is a derived file is added for the given entry
*/
- private List processCacheEntry(CacheAddress cacheEntryAddress, Collection sourceArtifacts, Collection webCacheArtifacts ) throws TskCoreException, IngestModuleException {
+ private List processCacheEntry(CacheAddress cacheEntryAddress, Collection associatedObjectArtifacts, Collection webCacheArtifacts ) throws TskCoreException, IngestModuleException {
List derivedFiles = new ArrayList<>();
@@ -437,10 +437,6 @@ final class ChromeCacheExtractor {
moduleName,
cacheEntry.getHTTPHeaders());
- Collection sourceArtifactAttributes = new ArrayList<>();
- sourceArtifactAttributes.add(urlAttr);
- sourceArtifactAttributes.add(createTimeAttr);
-
Collection webCacheAttributes = new ArrayList<>();
webCacheAttributes.add(urlAttr);
webCacheAttributes.add(createTimeAttr);
@@ -450,12 +446,7 @@ final class ChromeCacheExtractor {
// add artifacts to the f_XXX file
if (dataSegment.isInExternalFile() ) {
try {
- BlackboardArtifact sourceArtifact = cachedFileAbstractFile.get().newArtifact(ARTIFACT_TYPE.TSK_DOWNLOAD_SOURCE);
- if (sourceArtifact != null) {
- sourceArtifact.addAttributes(sourceArtifactAttributes);
- sourceArtifacts.add(sourceArtifact);
- }
-
+
BlackboardArtifact webCacheArtifact = cacheEntryFile.get().getAbstractFile().newArtifact(ARTIFACT_TYPE.TSK_WEB_CACHE);
if (webCacheArtifact != null) {
webCacheArtifact.addAttributes(webCacheAttributes);
@@ -469,6 +460,14 @@ final class ChromeCacheExtractor {
moduleName, cachedFileAbstractFile.get().getId()));
webCacheArtifacts.add(webCacheArtifact);
+
+ BlackboardArtifact associatedObjectArtifact = cachedFileAbstractFile.get().newArtifact(ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT);
+ if (associatedObjectArtifact != null) {
+ associatedObjectArtifact.addAttribute(
+ new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT,
+ moduleName, webCacheArtifact.getArtifactID()));
+ associatedObjectArtifacts.add(associatedObjectArtifact);
+ }
}
if (isBrotliCompressed) {
@@ -497,12 +496,7 @@ final class ChromeCacheExtractor {
"",
TskData.EncodingType.NONE);
- BlackboardArtifact sourceArtifact = derivedFile.newArtifact(ARTIFACT_TYPE.TSK_DOWNLOAD_SOURCE);
- if (sourceArtifact != null) {
- sourceArtifact.addAttributes(sourceArtifactAttributes);
- sourceArtifacts.add(sourceArtifact);
- }
-
+
BlackboardArtifact webCacheArtifact = cacheEntryFile.get().getAbstractFile().newArtifact(ARTIFACT_TYPE.TSK_WEB_CACHE);
if (webCacheArtifact != null) {
webCacheArtifact.addAttributes(webCacheAttributes);
@@ -516,6 +510,14 @@ final class ChromeCacheExtractor {
moduleName, derivedFile.getId()));
webCacheArtifacts.add(webCacheArtifact);
+
+ BlackboardArtifact associatedObjectArtifact = derivedFile.newArtifact(ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT);
+ if (associatedObjectArtifact != null) {
+ associatedObjectArtifact.addAttribute(
+ new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT,
+ moduleName, webCacheArtifact.getArtifactID()));
+ associatedObjectArtifacts.add(associatedObjectArtifact);
+ }
}
if (isBrotliCompressed) {
diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractSafari.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractSafari.java
index 704826047f..c11e4fde22 100755
--- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractSafari.java
+++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractSafari.java
@@ -50,6 +50,7 @@ import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
import org.sleuthkit.autopsy.recentactivity.BinaryCookieReader.Cookie;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact;
+import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskCoreException;
import org.xml.sax.SAXException;
@@ -637,15 +638,17 @@ final class ExtractSafari extends Extract {
time = date.getDate().getTime();
}
- BlackboardArtifact bbart = origFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD);
- bbart.addAttributes(this.createDownloadAttributes(path, pathID, url, time, NetworkUtils.extractDomain(url), getName()));
- bbartifacts.add(bbart);
+ BlackboardArtifact webDownloadArtifact = origFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD);
+ webDownloadArtifact.addAttributes(this.createDownloadAttributes(path, pathID, url, time, NetworkUtils.extractDomain(url), getName()));
+ bbartifacts.add(webDownloadArtifact);
- // find the downloaded file and create a TSK_DOWNLOAD_SOURCE for it.
+ // find the downloaded file and create a TSK_ASSOCIATED_OBJECT for it, associating it with the TSK_WEB_DOWNLOAD artifact.
for (AbstractFile downloadedFile : fileManager.findFiles(dataSource, FilenameUtils.getName(path), FilenameUtils.getPath(path))) {
- BlackboardArtifact downloadSourceArt = downloadedFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_DOWNLOAD_SOURCE);
- downloadSourceArt.addAttributes(createDownloadSourceAttributes(url));
- bbartifacts.add(downloadSourceArt);
+ BlackboardArtifact associatedObjectArtifact = downloadedFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT);
+ associatedObjectArtifact.addAttribute(
+ new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT,
+ RecentActivityExtracterModuleFactory.getModuleName(), webDownloadArtifact.getArtifactID()));
+ bbartifacts.add(associatedObjectArtifact);
break;
}
diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractZoneIdentifier.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractZoneIdentifier.java
index 250c55fa6e..51e3a8eff9 100755
--- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractZoneIdentifier.java
+++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractZoneIdentifier.java
@@ -36,9 +36,11 @@ import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProgress;
import org.sleuthkit.autopsy.ingest.IngestJobContext;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact;
+import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT;
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_DOWNLOAD_SOURCE;
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD;
import org.sleuthkit.datamodel.BlackboardAttribute;
+import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_LOCATION;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID;
@@ -94,7 +96,7 @@ final class ExtractZoneIdentifier extends Extract {
return;
}
- Collection sourceArtifacts = new ArrayList<>();
+ Collection associatedObjectArtifacts = new ArrayList<>();
Collection downloadArtifacts = new ArrayList<>();
for (AbstractFile zoneFile : zoneFiles) {
@@ -104,7 +106,7 @@ final class ExtractZoneIdentifier extends Extract {
}
try {
- processZoneFile(context, dataSource, zoneFile, sourceArtifacts, downloadArtifacts, knownPathIDs);
+ processZoneFile(context, dataSource, zoneFile, associatedObjectArtifacts, downloadArtifacts, knownPathIDs);
} catch (TskCoreException ex) {
addErrorMessage(Bundle.ExtractZone_process_errMsg());
String message = String.format("Failed to process zone identifier file %s", zoneFile.getName()); //NON-NLS
@@ -112,23 +114,23 @@ final class ExtractZoneIdentifier extends Extract {
}
}
- postArtifacts(sourceArtifacts);
+ postArtifacts(associatedObjectArtifacts);
postArtifacts(downloadArtifacts);
}
/**
* Process a single Zone Identifier file.
*
- * @param context IngetJobContext
- * @param dataSource Content
- * @param zoneFile Zone Indentifier file
- * @param sourceArtifacts List for TSK_DOWNLOAD_SOURCE artifacts
- * @param downloadArtifacts List for TSK_WEB_DOWNLOAD aritfacts
- *
+ * @param context IngetJobContext
+ * @param dataSource Content
+ * @param zoneFile Zone Indentifier file
+ * @param associatedObjectArtifacts List for TSK_ASSOCIATED_OBJECT artifacts
+ * @param downloadArtifacts List for TSK_WEB_DOWNLOAD artifacts
+ *
* @throws TskCoreException
*/
private void processZoneFile(IngestJobContext context, Content dataSource,
- AbstractFile zoneFile, Collection sourceArtifacts,
+ AbstractFile zoneFile, Collection associatedObjectArtifacts,
Collection downloadArtifacts,
Set knownPathIDs) throws TskCoreException {
@@ -155,16 +157,16 @@ final class ExtractZoneIdentifier extends Extract {
BlackboardArtifact downloadBba = createDownloadArtifact(zoneFile, zoneInfo);
if (downloadBba != null) {
downloadArtifacts.add(downloadBba);
+ // create a TSK_ASSOCIATED_OBJECT for the downloaded file, associating it with the TSK_WEB_DOWNLOAD artifact.
+ if (downloadFile.getArtifactsCount(TSK_ASSOCIATED_OBJECT) == 0) {
+ BlackboardArtifact associatedObjectBba = createAssociatedObjectArtifact(downloadFile, downloadBba);
+ if (associatedObjectBba != null) {
+ associatedObjectArtifacts.add(associatedObjectBba);
+ }
+ }
}
}
- // check if download has a child TSK_DOWNLOAD_SOURCE artifact, if not create one
- if (downloadFile.getArtifactsCount(TSK_DOWNLOAD_SOURCE) == 0) {
- BlackboardArtifact sourceBba = createDownloadSourceArtifact(downloadFile, zoneInfo);
- if (sourceBba != null) {
- sourceArtifacts.add(sourceBba);
- }
- }
}
}
@@ -203,33 +205,26 @@ final class ExtractZoneIdentifier extends Extract {
}
/**
- * Create a Download Source Artifact for the given ZoneIdentifierInfo
+ * Create a Associated Object Artifact for the given ZoneIdentifierInfo
* object.
*
* @param downloadFile AbstractFile representing the file downloaded, not
- * the zone identifier file.
- * @param zoneInfo Zone identifier file wrapper object
+ * the zone identifier file.
+ * @param downloadBba TSK_WEB_DOWNLOAD artifact to associate with.
*
- * @return TSK_DOWNLOAD_SOURCE object for given parameters
+ * @return TSK_ASSOCIATED_OBJECT artifact.
*/
- private BlackboardArtifact createDownloadSourceArtifact(AbstractFile downloadFile, ZoneIdentifierInfo zoneInfo) {
+ private BlackboardArtifact createAssociatedObjectArtifact(AbstractFile downloadFile, BlackboardArtifact downloadBba) {
Collection bbattributes = new ArrayList<>();
bbattributes.addAll(Arrays.asList(
- new BlackboardAttribute(TSK_URL,
- RecentActivityExtracterModuleFactory.getModuleName(),
- StringUtils.defaultString(zoneInfo.getURL(), "")),
-
- new BlackboardAttribute(TSK_DOMAIN,
- RecentActivityExtracterModuleFactory.getModuleName(),
- (zoneInfo.getURL() != null) ? NetworkUtils.extractDomain(zoneInfo.getURL()) : ""),
-
- new BlackboardAttribute(TSK_LOCATION,
- RecentActivityExtracterModuleFactory.getModuleName(),
- StringUtils.defaultString(zoneInfo.getZoneIdAsString(), "")))); //NON-NLS
+ new BlackboardAttribute(TSK_ASSOCIATED_ARTIFACT,
+ RecentActivityExtracterModuleFactory.getModuleName(),
+ downloadBba.getArtifactID())
+ ));
- return createArtifactWithAttributes(TSK_DOWNLOAD_SOURCE, downloadFile, bbattributes);
+ return createArtifactWithAttributes(TSK_ASSOCIATED_OBJECT, downloadFile, bbattributes);
}
/**
diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Firefox.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Firefox.java
index dd4e70ee06..7fddeb0aa8 100644
--- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Firefox.java
+++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Firefox.java
@@ -544,22 +544,25 @@ class Firefox extends Extract {
domain)); //NON-NLS
}
- BlackboardArtifact bbart = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, downloadsFile, bbattributes);
- if (bbart != null) {
- bbartifacts.add(bbart);
- }
-
- // find the downloaded file and create a TSK_DOWNLOAD_SOURCE for it.
- try {
- for (AbstractFile downloadedFile : fileManager.findFiles(dataSource, FilenameUtils.getName(downloadedFilePath), FilenameUtils.getPath(downloadedFilePath))) {
- BlackboardArtifact downloadSourceArt = downloadedFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_DOWNLOAD_SOURCE);
- downloadSourceArt.addAttributes(createDownloadSourceAttributes(source));
- bbartifacts.add(downloadSourceArt);
- break;
+ BlackboardArtifact webDownloadArtifact = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, downloadsFile, bbattributes);
+ if (webDownloadArtifact != null) {
+ bbartifacts.add(webDownloadArtifact);
+
+ // find the downloaded file and create a TSK_ASSOCIATED_OBJECT for it, associating it with the TSK_WEB_DOWNLOAD artifact.
+ try {
+ for (AbstractFile downloadedFile : fileManager.findFiles(dataSource, FilenameUtils.getName(downloadedFilePath), FilenameUtils.getPath(downloadedFilePath))) {
+ BlackboardArtifact associatedObjectArtifact = downloadedFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT);
+ associatedObjectArtifact.addAttribute(
+ new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT,
+ RecentActivityExtracterModuleFactory.getModuleName(), webDownloadArtifact.getArtifactID()));
+
+ bbartifacts.add(associatedObjectArtifact);
+ break;
+ }
+ } catch (TskCoreException ex) {
+ logger.log(Level.SEVERE, String.format("Error creating associated object artifact for file '%s'",
+ downloadedFilePath), ex); //NON-NLS
}
- } catch (TskCoreException ex) {
- logger.log(Level.SEVERE, String.format("Error creating download source artifact for file '%s'",
- downloadedFilePath), ex); //NON-NLS
}
}
if (errors > 0) {
@@ -681,22 +684,24 @@ class Firefox extends Extract {
RecentActivityExtracterModuleFactory.getModuleName(), domain)); //NON-NLS
}
- BlackboardArtifact bbart = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, downloadsFile, bbattributes);
- if (bbart != null) {
- bbartifacts.add(bbart);
- }
+ BlackboardArtifact webDownloadArtifact = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, downloadsFile, bbattributes);
+ if (webDownloadArtifact != null) {
+ bbartifacts.add(webDownloadArtifact);
- // find the downloaded file and create a TSK_DOWNLOAD_SOURCE for it.
- try {
- for (AbstractFile downloadedFile : fileManager.findFiles(dataSource, FilenameUtils.getName(downloadedFilePath), FilenameUtils.getPath(downloadedFilePath))) {
- BlackboardArtifact downloadSourceArt = downloadedFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_DOWNLOAD_SOURCE);
- downloadSourceArt.addAttributes(createDownloadSourceAttributes(url));
- bbartifacts.add(downloadSourceArt);
- break;
+ // find the downloaded file and create a TSK_ASSOCIATED_OBJECT for it, associating it with the TSK_WEB_DOWNLOAD artifact.
+ try {
+ for (AbstractFile downloadedFile : fileManager.findFiles(dataSource, FilenameUtils.getName(downloadedFilePath), FilenameUtils.getPath(downloadedFilePath))) {
+ BlackboardArtifact associatedObjectArtifact = downloadedFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT);
+ associatedObjectArtifact.addAttribute(
+ new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT,
+ RecentActivityExtracterModuleFactory.getModuleName(), webDownloadArtifact.getArtifactID()));
+ bbartifacts.add(associatedObjectArtifact);
+ break;
+ }
+ } catch (TskCoreException ex) {
+ logger.log(Level.SEVERE, String.format("Error creating associated object artifact for file '%s'",
+ downloadedFilePath), ex); //NON-NLS
}
- } catch (TskCoreException ex) {
- logger.log(Level.SEVERE, String.format("Error creating download source artifact for file '%s'",
- downloadedFilePath), ex); //NON-NLS
}
}
if (errors > 0) {