mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-12 16:06:15 +00:00
Merge remote-tracking branch 'upstream/develop' into remove-tsk-jfx-dependency
This commit is contained in:
commit
a63a0a26dd
@ -93,3 +93,7 @@ MediaPlayerPanel.playButton.text=\u25ba
|
|||||||
MediaPlayerPanel.infoLabel.text=No Errors
|
MediaPlayerPanel.infoLabel.text=No Errors
|
||||||
MediaPlayerPanel.VolumeIcon.text=Volume
|
MediaPlayerPanel.VolumeIcon.text=Volume
|
||||||
MediaPlayerPanel.playBackSpeedLabel.text=Speed:
|
MediaPlayerPanel.playBackSpeedLabel.text=Speed:
|
||||||
|
ContextViewer.jSourceGoToResultButton.text=Go to Result
|
||||||
|
ContextViewer.jSourceNameLabel.text=jSourceNameLabel
|
||||||
|
ContextViewer.jSourceTextLabel.text=jLabel2
|
||||||
|
ContextViewer.jSourceLabel.text=Source
|
||||||
|
@ -10,6 +10,17 @@ AnnotationsContentViewer.title=Annotations
|
|||||||
AnnotationsContentViewer.toolTip=Displays tags and comments associated with the selected content.
|
AnnotationsContentViewer.toolTip=Displays tags and comments associated with the selected content.
|
||||||
ApplicationContentViewer.title=Application
|
ApplicationContentViewer.title=Application
|
||||||
ApplicationContentViewer.toolTip=Displays file contents.
|
ApplicationContentViewer.toolTip=Displays file contents.
|
||||||
|
ContextViewer.attachmentSource=Attached to:
|
||||||
|
ContextViewer.downloadedOn=On
|
||||||
|
ContextViewer.downloadSource=Downloaded from:
|
||||||
|
ContextViewer.downloadURL=URL
|
||||||
|
ContextViewer.email=Email
|
||||||
|
ContextViewer.message=Message
|
||||||
|
ContextViewer.messageFrom=From
|
||||||
|
ContextViewer.messageOn=On
|
||||||
|
ContextViewer.messageTo=From
|
||||||
|
ContextViewer.title=Context Viewer
|
||||||
|
ContextViewer.toolTip=Displays context for selected file.
|
||||||
FXVideoPanel.pauseButton.infoLabel.playbackErr=Unable to play video.
|
FXVideoPanel.pauseButton.infoLabel.playbackErr=Unable to play video.
|
||||||
FXVideoPanel.progress.bufferingCancelled=media buffering was canceled
|
FXVideoPanel.progress.bufferingCancelled=media buffering was canceled
|
||||||
FXVideoPanel.progress.bufferingInterrupted=media buffering was interrupted
|
FXVideoPanel.progress.bufferingInterrupted=media buffering was interrupted
|
||||||
@ -164,6 +175,10 @@ MediaPlayerPanel.playButton.text=\u25ba
|
|||||||
MediaPlayerPanel.infoLabel.text=No Errors
|
MediaPlayerPanel.infoLabel.text=No Errors
|
||||||
MediaPlayerPanel.VolumeIcon.text=Volume
|
MediaPlayerPanel.VolumeIcon.text=Volume
|
||||||
MediaPlayerPanel.playBackSpeedLabel.text=Speed:
|
MediaPlayerPanel.playBackSpeedLabel.text=Speed:
|
||||||
|
ContextViewer.jSourceGoToResultButton.text=Go to Result
|
||||||
|
ContextViewer.jSourceNameLabel.text=jSourceNameLabel
|
||||||
|
ContextViewer.jSourceTextLabel.text=jLabel2
|
||||||
|
ContextViewer.jSourceLabel.text=Source
|
||||||
# {0} - tableName
|
# {0} - tableName
|
||||||
SQLiteViewer.readTable.errorText=Error getting rows for table: {0}
|
SQLiteViewer.readTable.errorText=Error getting rows for table: {0}
|
||||||
# {0} - tableName
|
# {0} - tableName
|
||||||
|
103
Core/src/org/sleuthkit/autopsy/contentviewers/ContextViewer.form
Normal file
103
Core/src/org/sleuthkit/autopsy/contentviewers/ContextViewer.form
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
|
||||||
|
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||||
|
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||||
|
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||||
|
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||||
|
</AuxValues>
|
||||||
|
|
||||||
|
<Layout>
|
||||||
|
<DimensionLayout dim="0">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Group type="102" attributes="0">
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Group type="102" alignment="0" attributes="0">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Component id="jSourceLabel" min="-2" max="-2" attributes="0"/>
|
||||||
|
<Group type="102" alignment="0" attributes="0">
|
||||||
|
<EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
|
||||||
|
<Component id="jSourceNameLabel" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Component id="jSourceTextLabel" pref="192" max="32767" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
<EmptySpace min="-2" pref="36" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
<Group type="102" alignment="0" attributes="0">
|
||||||
|
<Component id="jSourceGoToResultButton" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace max="32767" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
</DimensionLayout>
|
||||||
|
<DimensionLayout dim="1">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Group type="102" alignment="0" attributes="0">
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Component id="jSourceLabel" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Group type="103" groupAlignment="3" attributes="0">
|
||||||
|
<Component id="jSourceNameLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
|
<Component id="jSourceTextLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||||
|
<Component id="jSourceGoToResultButton" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace min="0" pref="203" max="32767" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
</DimensionLayout>
|
||||||
|
</Layout>
|
||||||
|
<SubComponents>
|
||||||
|
<Component class="javax.swing.JButton" name="jSourceGoToResultButton">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/contentviewers/Bundle.properties" key="ContextViewer.jSourceGoToResultButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<Events>
|
||||||
|
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jSourceGoToResultButtonActionPerformed"/>
|
||||||
|
</Events>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
|
</AuxValues>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JLabel" name="jSourceLabel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||||
|
<Font name="Dialog" size="14" style="1"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/contentviewers/Bundle.properties" key="ContextViewer.jSourceLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
|
</AuxValues>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JLabel" name="jSourceNameLabel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/contentviewers/Bundle.properties" key="ContextViewer.jSourceNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JLabel" name="jSourceTextLabel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/contentviewers/Bundle.properties" key="ContextViewer.jSourceTextLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
|
</SubComponents>
|
||||||
|
</Form>
|
440
Core/src/org/sleuthkit/autopsy/contentviewers/ContextViewer.java
Normal file
440
Core/src/org/sleuthkit/autopsy/contentviewers/ContextViewer.java
Normal file
@ -0,0 +1,440 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2019 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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)
|
||||||
|
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());
|
||||||
|
private static final int ARTIFACT_STR_MAX_LEN = 1024;
|
||||||
|
private static final int ATTRIBUTE_STR_MAX_LEN = 200;
|
||||||
|
|
||||||
|
// defines a list of artifacts that provide context for a file
|
||||||
|
private static final List<BlackboardArtifact.ARTIFACT_TYPE> 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")
|
||||||
|
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||||
|
private void initComponents() {
|
||||||
|
|
||||||
|
javax.swing.JButton jSourceGoToResultButton = new javax.swing.JButton();
|
||||||
|
javax.swing.JLabel jSourceLabel = 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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
jSourceLabel.setFont(new java.awt.Font("Dialog", 1, 14)); // NOI18N
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(jSourceLabel, org.openide.util.NbBundle.getMessage(ContextViewer.class, "ContextViewer.jSourceLabel.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(jSourceLabel)
|
||||||
|
.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(jSourceLabel)
|
||||||
|
.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))
|
||||||
|
);
|
||||||
|
}// </editor-fold>//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, String.format("Exception displaying context for file %s", file.getName()), ex); //NON-NLS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NbBundle.Messages({
|
||||||
|
"ContextViewer.title=Context Viewer",
|
||||||
|
"ContextViewer.toolTip=Displays context for selected file."
|
||||||
|
})
|
||||||
|
|
||||||
|
@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<BlackboardArtifact> artifactsList;
|
||||||
|
try {
|
||||||
|
artifactsList = abstractFile.getArtifacts(artifactType);
|
||||||
|
if (!artifactsList.isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (TskCoreException ex) {
|
||||||
|
logger.log(Level.SEVERE, String.format("Exception while looking up context artifacts for file %s", abstractFile), ex); //NON-NLS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int isPreferred(Node node) {
|
||||||
|
// this is a low preference viewer.
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Looks for context providing artifacts for the given file and populates
|
||||||
|
* the source context.
|
||||||
|
*
|
||||||
|
* @param sourceFile File for which to show the context.
|
||||||
|
*
|
||||||
|
* @throws NoCurrentCaseException
|
||||||
|
* @throws TskCoreException
|
||||||
|
*/
|
||||||
|
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<BlackboardArtifact> artifactsList = tskCase.getBlackboardArtifacts(artifactType, sourceFile.getId());
|
||||||
|
|
||||||
|
foundASource = !artifactsList.isEmpty();
|
||||||
|
for (BlackboardArtifact contextArtifact : artifactsList) {
|
||||||
|
addSourceEntry(contextArtifact);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (foundASource == false) {
|
||||||
|
setSourceName("Unknown");
|
||||||
|
showSourceText(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a source context entry for the selected file based on the given context
|
||||||
|
* providing artifact.
|
||||||
|
*
|
||||||
|
* @param artifact Artifact that may provide context.
|
||||||
|
*
|
||||||
|
* @throws NoCurrentCaseException
|
||||||
|
* @throws TskCoreException
|
||||||
|
*/
|
||||||
|
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 for "Go to Result" button
|
||||||
|
sourceContextArtifact = associatedArtifact;
|
||||||
|
|
||||||
|
setSourceFields(associatedArtifact);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the source label and text fields based on the given associated
|
||||||
|
* artifact.
|
||||||
|
*
|
||||||
|
* @param associatedArtifact - associated artifact
|
||||||
|
*
|
||||||
|
* @throws TskCoreException
|
||||||
|
*/
|
||||||
|
@NbBundle.Messages({
|
||||||
|
"ContextViewer.attachmentSource=Attached to: ",
|
||||||
|
"ContextViewer.downloadSource=Downloaded from: "
|
||||||
|
})
|
||||||
|
private void setSourceFields(BlackboardArtifact associatedArtifact) throws TskCoreException {
|
||||||
|
if (BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE.getTypeID() == associatedArtifact.getArtifactTypeID()
|
||||||
|
|| BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID() == associatedArtifact.getArtifactTypeID()) {
|
||||||
|
|
||||||
|
setSourceName(Bundle.ContextViewer_attachmentSource());
|
||||||
|
setSourceText(msgArtifactToAbbreviatedString(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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the source label string.
|
||||||
|
*
|
||||||
|
* @param nameLabel String value for source label.
|
||||||
|
*/
|
||||||
|
private void setSourceName(String nameLabel) {
|
||||||
|
jSourceNameLabel.setText(nameLabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the source text string.
|
||||||
|
*
|
||||||
|
* @param nameLabel String value for source text.
|
||||||
|
*/
|
||||||
|
private void setSourceText(String text) {
|
||||||
|
jSourceTextLabel.setText(text);
|
||||||
|
showSourceText(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showSourceText(boolean isVisible) {
|
||||||
|
jSourceTextLabel.setVisible(isVisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a display string with download source URL from the given
|
||||||
|
* artifact.
|
||||||
|
*
|
||||||
|
* @param artifact artifact to get download source URL from.
|
||||||
|
*
|
||||||
|
* @return Display string with download URL and date/time.
|
||||||
|
*
|
||||||
|
* @throws TskCoreException
|
||||||
|
*/
|
||||||
|
@NbBundle.Messages({
|
||||||
|
"ContextViewer.downloadURL=URL",
|
||||||
|
"ContextViewer.downloadedOn=On"
|
||||||
|
})
|
||||||
|
private String webDownloadArtifactToString(BlackboardArtifact artifact) throws TskCoreException {
|
||||||
|
StringBuilder sb = new StringBuilder(ARTIFACT_STR_MAX_LEN);
|
||||||
|
Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> 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, Bundle.ContextViewer_downloadURL());
|
||||||
|
appendAttributeString(sb, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED, attributesMap, Bundle.ContextViewer_downloadedOn());
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a abbreviated display string for a message artifact.
|
||||||
|
*
|
||||||
|
* @param artifact artifact to get download source URL from.
|
||||||
|
*
|
||||||
|
* @return Display string for message artifact.
|
||||||
|
*
|
||||||
|
* @throws TskCoreException
|
||||||
|
*/
|
||||||
|
@NbBundle.Messages({
|
||||||
|
"ContextViewer.message=Message",
|
||||||
|
"ContextViewer.email=Email",
|
||||||
|
"ContextViewer.messageFrom=From",
|
||||||
|
"ContextViewer.messageTo=From",
|
||||||
|
"ContextViewer.messageOn=On",
|
||||||
|
})
|
||||||
|
private String msgArtifactToAbbreviatedString(BlackboardArtifact artifact) throws TskCoreException {
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder(ARTIFACT_STR_MAX_LEN);
|
||||||
|
Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> attributesMap = getAttributesMap(artifact);
|
||||||
|
|
||||||
|
if (BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE.getTypeID() == artifact.getArtifactTypeID()) {
|
||||||
|
sb.append(Bundle.ContextViewer_message()).append(' ');
|
||||||
|
appendAttributeString(sb, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM, attributesMap, Bundle.ContextViewer_messageFrom());
|
||||||
|
appendAttributeString(sb, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO, attributesMap, Bundle.ContextViewer_messageTo());
|
||||||
|
appendAttributeString(sb, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, attributesMap, Bundle.ContextViewer_messageOn());
|
||||||
|
} else if (BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID() == artifact.getArtifactTypeID()) {
|
||||||
|
sb.append(Bundle.ContextViewer_email()).append(' ');
|
||||||
|
appendAttributeString(sb, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL_FROM, attributesMap, Bundle.ContextViewer_messageFrom());
|
||||||
|
appendAttributeString(sb, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL_TO, attributesMap, Bundle.ContextViewer_messageTo());
|
||||||
|
appendAttributeString(sb, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_SENT, attributesMap, Bundle.ContextViewer_messageOn());
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Looks up specified attribute in the given map and, if found, appends its
|
||||||
|
* value to the given string builder.
|
||||||
|
*
|
||||||
|
* @param sb String builder to append to.
|
||||||
|
* @param attribType Attribute type to look for.
|
||||||
|
* @param attributesMap Attributes map.
|
||||||
|
* @param prependStr Optional string that is prepended before the attribute
|
||||||
|
* value.
|
||||||
|
*/
|
||||||
|
private void appendAttributeString(StringBuilder sb, BlackboardAttribute.ATTRIBUTE_TYPE attribType,
|
||||||
|
Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> 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, ATTRIBUTE_STR_MAX_LEN)).append(' ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all attributes for the given artifact, and returns a map of
|
||||||
|
* attributes keyed by attribute type.
|
||||||
|
*
|
||||||
|
* @param artifact Artifact for which to get the attributes.
|
||||||
|
*
|
||||||
|
* @return Map of attribute type and value.
|
||||||
|
*
|
||||||
|
* @throws TskCoreException
|
||||||
|
*/
|
||||||
|
private Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> getAttributesMap(BlackboardArtifact artifact) throws TskCoreException {
|
||||||
|
Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> attributeMap = new HashMap<>();
|
||||||
|
|
||||||
|
List<BlackboardAttribute> 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 jSourceNameLabel;
|
||||||
|
private javax.swing.JLabel jSourceTextLabel;
|
||||||
|
// End of variables declaration//GEN-END:variables
|
||||||
|
}
|
@ -191,12 +191,14 @@ public class Metadata extends javax.swing.JPanel implements DataContentViewer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
List<BlackboardArtifact> sourceArtifacts = file.getArtifacts(ARTIFACT_TYPE.TSK_DOWNLOAD_SOURCE);
|
List<BlackboardArtifact> associatedObjectArtifacts = file.getArtifacts(ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT);
|
||||||
if (!sourceArtifacts.isEmpty()) {
|
if (!associatedObjectArtifacts.isEmpty()) {
|
||||||
BlackboardArtifact artifact = sourceArtifacts.get(0);
|
BlackboardArtifact artifact = associatedObjectArtifacts.get(0);
|
||||||
BlackboardAttribute urlAttr = artifact.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_URL));
|
BlackboardAttribute associatedArtifactAttribute = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT));
|
||||||
if (urlAttr != null) {
|
if (associatedArtifactAttribute != null) {
|
||||||
addRow(sb, NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.downloadSource"), urlAttr.getValueString());
|
long artifactId = associatedArtifactAttribute.getValueLong();
|
||||||
|
BlackboardArtifact associatedArtifact = artifact.getSleuthkitCase().getBlackboardArtifact(artifactId);
|
||||||
|
addDownloadSourceRow(sb, associatedArtifact);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
@ -292,6 +294,26 @@ public class Metadata extends javax.swing.JPanel implements DataContentViewer {
|
|||||||
this.setCursor(null);
|
this.setCursor(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a row for download source from the given associated artifact,
|
||||||
|
* if the associated artifacts specifies a source.
|
||||||
|
*
|
||||||
|
* @param sb string builder.
|
||||||
|
* @param associatedArtifact
|
||||||
|
*
|
||||||
|
* @throws TskCoreException if there is an error
|
||||||
|
*/
|
||||||
|
private void addDownloadSourceRow(StringBuilder sb, BlackboardArtifact associatedArtifact ) throws TskCoreException {
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add the acquisition details to the results (if applicable)
|
* Add the acquisition details to the results (if applicable)
|
||||||
*
|
*
|
||||||
|
@ -52,7 +52,11 @@ final class XRYFileReader implements AutoCloseable {
|
|||||||
//Assume UTF_16LE
|
//Assume UTF_16LE
|
||||||
private static final Charset CHARSET = StandardCharsets.UTF_16LE;
|
private static final Charset CHARSET = StandardCharsets.UTF_16LE;
|
||||||
|
|
||||||
//Assume all XRY reports have the type on the 3rd line.
|
//Assume the header begins with 'xry export'.
|
||||||
|
private static final String START_OF_HEADER = "xry export";
|
||||||
|
|
||||||
|
//Assume all XRY reports have the type on the 3rd line
|
||||||
|
//relative to the start of the header.
|
||||||
private static final int LINE_WITH_REPORT_TYPE = 3;
|
private static final int LINE_WITH_REPORT_TYPE = 3;
|
||||||
|
|
||||||
//Assume all headers are 5 lines in length.
|
//Assume all headers are 5 lines in length.
|
||||||
@ -91,8 +95,12 @@ final class XRYFileReader implements AutoCloseable {
|
|||||||
reader = Files.newBufferedReader(xryFile, CHARSET);
|
reader = Files.newBufferedReader(xryFile, CHARSET);
|
||||||
xryFilePath = xryFile;
|
xryFilePath = xryFile;
|
||||||
|
|
||||||
//Advance the reader to the start of the first XRY entity.
|
//Advance the reader to the start of the header.
|
||||||
for (int i = 0; i < HEADER_LENGTH_IN_LINES; i++) {
|
advanceToHeader(reader);
|
||||||
|
|
||||||
|
//Advance the reader past the header to the start
|
||||||
|
//of the first XRY entity.
|
||||||
|
for (int i = 1; i < HEADER_LENGTH_IN_LINES; i++) {
|
||||||
reader.readLine();
|
reader.readLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -298,8 +306,11 @@ final class XRYFileReader implements AutoCloseable {
|
|||||||
*/
|
*/
|
||||||
private static Optional<String> getType(Path file) throws IOException {
|
private static Optional<String> getType(Path file) throws IOException {
|
||||||
try (BufferedReader reader = Files.newBufferedReader(file, CHARSET)) {
|
try (BufferedReader reader = Files.newBufferedReader(file, CHARSET)) {
|
||||||
|
//Header may not start at the beginning of the file.
|
||||||
|
advanceToHeader(reader);
|
||||||
|
|
||||||
//Advance the reader to the line before the report type.
|
//Advance the reader to the line before the report type.
|
||||||
for (int i = 0; i < LINE_WITH_REPORT_TYPE - 1; i++) {
|
for (int i = 1; i < LINE_WITH_REPORT_TYPE - 1; i++) {
|
||||||
reader.readLine();
|
reader.readLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -310,4 +321,51 @@ final class XRYFileReader implements AutoCloseable {
|
|||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Advances the reader to the start of the header. The XRY Export header may
|
||||||
|
* not be the first n lines of the file. It may be preceded by new lines or
|
||||||
|
* white space.
|
||||||
|
*
|
||||||
|
* This function will consume the first line of the header, which will be
|
||||||
|
* 'XRY Export'.
|
||||||
|
*
|
||||||
|
* @param reader BufferedReader pointing to the xry file
|
||||||
|
* @throws IOException if an I/O error occurs
|
||||||
|
*/
|
||||||
|
private static void advanceToHeader(BufferedReader reader) throws IOException {
|
||||||
|
String line;
|
||||||
|
if((line = reader.readLine()) == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String normalizedLine = line.trim().toLowerCase();
|
||||||
|
if (normalizedLine.equals(START_OF_HEADER)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The first line may have 0xFFFE BOM prepended to it, which will cause
|
||||||
|
* the equality check to fail. This bit a logic will try to remove those
|
||||||
|
* bytes and attempt another check.
|
||||||
|
*/
|
||||||
|
byte[] normalizedBytes = normalizedLine.getBytes(CHARSET);
|
||||||
|
if (normalizedBytes.length > 2) {
|
||||||
|
normalizedLine = new String(normalizedBytes, 2,
|
||||||
|
normalizedBytes.length - 2, CHARSET);
|
||||||
|
if (normalizedLine.equals(START_OF_HEADER)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All other lines will need to match completely.
|
||||||
|
*/
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
normalizedLine = line.trim().toLowerCase();
|
||||||
|
if (normalizedLine.equals(START_OF_HEADER)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,6 +103,7 @@ final class CheckBoxJList<T extends CheckBoxJList.CheckboxListItem> extends JLis
|
|||||||
setBackground(list.getBackground());
|
setBackground(list.getBackground());
|
||||||
setSelected(value.isChecked());
|
setSelected(value.isChecked());
|
||||||
setText(value.getDisplayName());
|
setText(value.getDisplayName());
|
||||||
|
setEnabled(list.isEnabled());
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,10 +37,6 @@
|
|||||||
<Events>
|
<Events>
|
||||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="uncheckButtonActionPerformed"/>
|
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="uncheckButtonActionPerformed"/>
|
||||||
</Events>
|
</Events>
|
||||||
<AuxValues>
|
|
||||||
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
|
||||||
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
|
||||||
</AuxValues>
|
|
||||||
<Constraints>
|
<Constraints>
|
||||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||||
<GridBagConstraints gridX="1" gridY="2" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="9" anchor="12" weightX="1.0" weightY="0.0"/>
|
<GridBagConstraints gridX="1" gridY="2" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="9" anchor="12" weightX="1.0" weightY="0.0"/>
|
||||||
@ -56,10 +52,6 @@
|
|||||||
<Events>
|
<Events>
|
||||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="checkButtonActionPerformed"/>
|
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="checkButtonActionPerformed"/>
|
||||||
</Events>
|
</Events>
|
||||||
<AuxValues>
|
|
||||||
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
|
||||||
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
|
||||||
</AuxValues>
|
|
||||||
<Constraints>
|
<Constraints>
|
||||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||||
<GridBagConstraints gridX="2" gridY="2" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="12" weightX="0.0" weightY="0.0"/>
|
<GridBagConstraints gridX="2" gridY="2" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="12" weightX="0.0" weightY="0.0"/>
|
||||||
|
@ -62,6 +62,14 @@ final class CheckBoxListPanel<T> extends javax.swing.JPanel {
|
|||||||
model.removeAllElements();
|
model.removeAllElements();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setEnabled(boolean enabled) {
|
||||||
|
checkboxList.setEnabled(enabled);
|
||||||
|
checkButton.setEnabled(enabled);
|
||||||
|
uncheckButton.setEnabled(enabled);
|
||||||
|
checkboxList.setEnabled(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list of all of the selected elements.
|
* Returns a list of all of the selected elements.
|
||||||
*
|
*
|
||||||
@ -126,8 +134,8 @@ final class CheckBoxListPanel<T> extends javax.swing.JPanel {
|
|||||||
java.awt.GridBagConstraints gridBagConstraints;
|
java.awt.GridBagConstraints gridBagConstraints;
|
||||||
|
|
||||||
titleLabel = new javax.swing.JLabel();
|
titleLabel = new javax.swing.JLabel();
|
||||||
javax.swing.JButton uncheckButton = new javax.swing.JButton();
|
uncheckButton = new javax.swing.JButton();
|
||||||
javax.swing.JButton checkButton = new javax.swing.JButton();
|
checkButton = new javax.swing.JButton();
|
||||||
scrollPane = new javax.swing.JScrollPane();
|
scrollPane = new javax.swing.JScrollPane();
|
||||||
|
|
||||||
setLayout(new java.awt.GridBagLayout());
|
setLayout(new java.awt.GridBagLayout());
|
||||||
@ -186,8 +194,10 @@ final class CheckBoxListPanel<T> extends javax.swing.JPanel {
|
|||||||
|
|
||||||
|
|
||||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
|
private javax.swing.JButton checkButton;
|
||||||
private javax.swing.JScrollPane scrollPane;
|
private javax.swing.JScrollPane scrollPane;
|
||||||
private javax.swing.JLabel titleLabel;
|
private javax.swing.JLabel titleLabel;
|
||||||
|
private javax.swing.JButton uncheckButton;
|
||||||
// End of variables declaration//GEN-END:variables
|
// End of variables declaration//GEN-END:variables
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -115,10 +115,6 @@
|
|||||||
<ResourceString bundle="org/sleuthkit/autopsy/geolocation/Bundle.properties" key="GeoFilterPanel.daysLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
<ResourceString bundle="org/sleuthkit/autopsy/geolocation/Bundle.properties" key="GeoFilterPanel.daysLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
<AuxValues>
|
|
||||||
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
|
||||||
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
|
||||||
</AuxValues>
|
|
||||||
<Constraints>
|
<Constraints>
|
||||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||||
<GridBagConstraints gridX="3" gridY="1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="9" insetsLeft="5" insetsBottom="0" insetsRight="0" anchor="17" weightX="1.0" weightY="0.0"/>
|
<GridBagConstraints gridX="3" gridY="1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="9" insetsLeft="5" insetsBottom="0" insetsRight="0" anchor="17" weightX="1.0" weightY="0.0"/>
|
||||||
|
@ -74,6 +74,20 @@ class GeoFilterPanel extends javax.swing.JPanel {
|
|||||||
add(checkboxPanel, gridBagConstraints);
|
add(checkboxPanel, gridBagConstraints);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setEnabled(boolean enabled) {
|
||||||
|
applyButton.setEnabled(enabled);
|
||||||
|
mostRecentButton.setEnabled(enabled);
|
||||||
|
allButton.setEnabled(enabled);
|
||||||
|
showWaypointsWOTSCheckBox.setEnabled(enabled && mostRecentButton.isSelected());
|
||||||
|
checkboxPanel.setEnabled(enabled);
|
||||||
|
daysLabel.setEnabled(enabled);
|
||||||
|
daysSpinner.setEnabled(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the data source list with the current data sources
|
||||||
|
*/
|
||||||
void updateDataSourceList() {
|
void updateDataSourceList() {
|
||||||
try {
|
try {
|
||||||
initCheckboxList();
|
initCheckboxList();
|
||||||
@ -155,7 +169,7 @@ class GeoFilterPanel extends javax.swing.JPanel {
|
|||||||
mostRecentButton = new javax.swing.JRadioButton();
|
mostRecentButton = new javax.swing.JRadioButton();
|
||||||
showWaypointsWOTSCheckBox = new javax.swing.JCheckBox();
|
showWaypointsWOTSCheckBox = new javax.swing.JCheckBox();
|
||||||
daysSpinner = new javax.swing.JSpinner(numberModel);
|
daysSpinner = new javax.swing.JSpinner(numberModel);
|
||||||
javax.swing.JLabel daysLabel = new javax.swing.JLabel();
|
daysLabel = new javax.swing.JLabel();
|
||||||
javax.swing.JPanel buttonPanel = new javax.swing.JPanel();
|
javax.swing.JPanel buttonPanel = new javax.swing.JPanel();
|
||||||
applyButton = new javax.swing.JButton();
|
applyButton = new javax.swing.JButton();
|
||||||
javax.swing.JLabel optionsLabel = new javax.swing.JLabel();
|
javax.swing.JLabel optionsLabel = new javax.swing.JLabel();
|
||||||
@ -272,6 +286,7 @@ class GeoFilterPanel extends javax.swing.JPanel {
|
|||||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
private javax.swing.JRadioButton allButton;
|
private javax.swing.JRadioButton allButton;
|
||||||
private javax.swing.JButton applyButton;
|
private javax.swing.JButton applyButton;
|
||||||
|
private javax.swing.JLabel daysLabel;
|
||||||
private javax.swing.JSpinner daysSpinner;
|
private javax.swing.JSpinner daysSpinner;
|
||||||
private javax.swing.JRadioButton mostRecentButton;
|
private javax.swing.JRadioButton mostRecentButton;
|
||||||
private javax.swing.JCheckBox showWaypointsWOTSCheckBox;
|
private javax.swing.JCheckBox showWaypointsWOTSCheckBox;
|
||||||
|
@ -22,6 +22,7 @@ import java.awt.BorderLayout;
|
|||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -171,6 +172,7 @@ public final class GeolocationTopComponent extends TopComponent {
|
|||||||
logger.log(Level.SEVERE, ex.getMessage(), ex);
|
logger.log(Level.SEVERE, ex.getMessage(), ex);
|
||||||
return; // Doen't set the waypoints.
|
return; // Doen't set the waypoints.
|
||||||
}
|
}
|
||||||
|
mapPanel.setWaypoints(new ArrayList<>());
|
||||||
updateWaypoints();
|
updateWaypoints();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,35 +216,11 @@ public final class GeolocationTopComponent extends TopComponent {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SwingUtilities.invokeLater(new Runnable() {
|
mapPanel.setWaypointLoading(true);
|
||||||
public void run() {
|
geoFilterPanel.setEnabled(false);
|
||||||
Case currentCase = Case.getCurrentCase();
|
|
||||||
try {
|
|
||||||
WaypointBuilder.getAllWaypoints(currentCase.getSleuthkitCase(), filters.getDataSources(), filters.showAllWaypoints(), filters.getMostRecentNumDays(), filters.showWaypointsWithoutTimeStamp(), new WaypointFilterQueryCallBack() {
|
|
||||||
@Override
|
|
||||||
public void process(List<Waypoint> waypoints) {
|
|
||||||
// If the list is empty, tell the user and do not change
|
|
||||||
// the visible waypoints.
|
|
||||||
if (waypoints == null || waypoints.isEmpty()) {
|
|
||||||
JOptionPane.showMessageDialog(GeolocationTopComponent.this,
|
|
||||||
Bundle.GeoTopComponent_no_waypoints_returned_Title(),
|
|
||||||
Bundle.GeoTopComponent_no_waypoints_returned_mgs(),
|
|
||||||
JOptionPane.INFORMATION_MESSAGE);
|
|
||||||
|
|
||||||
return;
|
Thread thread = new Thread(new WaypointRunner(filters));
|
||||||
}
|
thread.start();
|
||||||
mapPanel.setWaypoints(MapWaypoint.getWaypoints(waypoints));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (GeoLocationDataException ex) {
|
|
||||||
logger.log(Level.SEVERE, "Failed to filter waypoints.", ex);
|
|
||||||
JOptionPane.showMessageDialog(GeolocationTopComponent.this,
|
|
||||||
Bundle.GeoTopComponent_filter_exception_Title(),
|
|
||||||
Bundle.GeoTopComponent_filter_exception_msg(),
|
|
||||||
JOptionPane.ERROR_MESSAGE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -269,4 +247,76 @@ public final class GeolocationTopComponent extends TopComponent {
|
|||||||
private org.sleuthkit.autopsy.geolocation.HidingPane filterPane;
|
private org.sleuthkit.autopsy.geolocation.HidingPane filterPane;
|
||||||
private org.sleuthkit.autopsy.geolocation.MapPanel mapPanel;
|
private org.sleuthkit.autopsy.geolocation.MapPanel mapPanel;
|
||||||
// End of variables declaration//GEN-END:variables
|
// End of variables declaration//GEN-END:variables
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A runnable class for getting waypoints based on the current filters.
|
||||||
|
*/
|
||||||
|
private class WaypointRunner implements Runnable {
|
||||||
|
|
||||||
|
private final GeoFilter filters;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs the Waypoint Runner
|
||||||
|
*
|
||||||
|
* @param filters
|
||||||
|
*/
|
||||||
|
WaypointRunner(GeoFilter filters) {
|
||||||
|
this.filters = filters;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
Case currentCase = Case.getCurrentCase();
|
||||||
|
try {
|
||||||
|
WaypointBuilder.getAllWaypoints(currentCase.getSleuthkitCase(),
|
||||||
|
filters.getDataSources(),
|
||||||
|
filters.showAllWaypoints(),
|
||||||
|
filters.getMostRecentNumDays(),
|
||||||
|
filters.showWaypointsWithoutTimeStamp(),
|
||||||
|
new WaypointCallBack());
|
||||||
|
|
||||||
|
} catch (GeoLocationDataException ex) {
|
||||||
|
logger.log(Level.SEVERE, "Failed to filter waypoints.", ex);
|
||||||
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
JOptionPane.showMessageDialog(GeolocationTopComponent.this,
|
||||||
|
Bundle.GeoTopComponent_filter_exception_Title(),
|
||||||
|
Bundle.GeoTopComponent_filter_exception_msg(),
|
||||||
|
JOptionPane.ERROR_MESSAGE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback for getting waypoints.
|
||||||
|
*/
|
||||||
|
private class WaypointCallBack implements WaypointFilterQueryCallBack {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process(List<Waypoint> waypoints) {
|
||||||
|
// Make sure that the waypoints are added to the map panel in
|
||||||
|
// the correct thread.
|
||||||
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
// If the list is empty, tell the user and do not change
|
||||||
|
// the visible waypoints.
|
||||||
|
if (waypoints == null || waypoints.isEmpty()) {
|
||||||
|
JOptionPane.showMessageDialog(GeolocationTopComponent.this,
|
||||||
|
Bundle.GeoTopComponent_no_waypoints_returned_Title(),
|
||||||
|
Bundle.GeoTopComponent_no_waypoints_returned_mgs(),
|
||||||
|
JOptionPane.INFORMATION_MESSAGE);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mapPanel.setWaypoints(MapWaypoint.getWaypoints(waypoints));
|
||||||
|
geoFilterPanel.setEnabled(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,7 +98,7 @@
|
|||||||
</Constraint>
|
</Constraint>
|
||||||
</Constraints>
|
</Constraints>
|
||||||
|
|
||||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
|
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||||
<SubComponents>
|
<SubComponents>
|
||||||
<Component class="javax.swing.JLabel" name="cordLabel">
|
<Component class="javax.swing.JLabel" name="cordLabel">
|
||||||
<Properties>
|
<Properties>
|
||||||
@ -107,8 +107,19 @@
|
|||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
<Constraints>
|
<Constraints>
|
||||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||||
<BorderConstraints direction="East"/>
|
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="5" insetsBottom="0" insetsRight="5" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||||
|
</Constraint>
|
||||||
|
</Constraints>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JProgressBar" name="progressBar">
|
||||||
|
<Properties>
|
||||||
|
<Property name="indeterminate" type="boolean" value="true"/>
|
||||||
|
<Property name="stringPainted" type="boolean" value="true"/>
|
||||||
|
</Properties>
|
||||||
|
<Constraints>
|
||||||
|
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||||
|
<GridBagConstraints gridX="1" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="12" weightX="0.0" weightY="0.0"/>
|
||||||
</Constraint>
|
</Constraint>
|
||||||
</Constraints>
|
</Constraints>
|
||||||
</Component>
|
</Component>
|
||||||
|
@ -179,6 +179,17 @@ final public class MapPanel extends javax.swing.JPanel {
|
|||||||
mapViewer.setOverlayPainter(waypointPainter);
|
mapViewer.setOverlayPainter(waypointPainter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show or hide the waypoint loading progress bar.
|
||||||
|
*
|
||||||
|
* @param loading
|
||||||
|
*/
|
||||||
|
void setWaypointLoading(boolean loading) {
|
||||||
|
progressBar.setEnabled(true);
|
||||||
|
progressBar.setVisible(loading);
|
||||||
|
progressBar.setString("Loading Waypoints");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup the zoom slider based on the current tileFactory.
|
* Setup the zoom slider based on the current tileFactory.
|
||||||
*/
|
*/
|
||||||
@ -265,6 +276,7 @@ final public class MapPanel extends javax.swing.JPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mapViewer.repaint();
|
mapViewer.repaint();
|
||||||
|
setWaypointLoading(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -486,6 +498,7 @@ final public class MapPanel extends javax.swing.JPanel {
|
|||||||
zoomSlider = new javax.swing.JSlider();
|
zoomSlider = new javax.swing.JSlider();
|
||||||
infoPanel = new javax.swing.JPanel();
|
infoPanel = new javax.swing.JPanel();
|
||||||
cordLabel = new javax.swing.JLabel();
|
cordLabel = new javax.swing.JLabel();
|
||||||
|
progressBar = new javax.swing.JProgressBar();
|
||||||
|
|
||||||
setFocusable(false);
|
setFocusable(false);
|
||||||
setLayout(new java.awt.BorderLayout());
|
setLayout(new java.awt.BorderLayout());
|
||||||
@ -553,10 +566,24 @@ final public class MapPanel extends javax.swing.JPanel {
|
|||||||
|
|
||||||
add(mapViewer, java.awt.BorderLayout.CENTER);
|
add(mapViewer, java.awt.BorderLayout.CENTER);
|
||||||
|
|
||||||
infoPanel.setLayout(new java.awt.BorderLayout());
|
infoPanel.setLayout(new java.awt.GridBagLayout());
|
||||||
|
|
||||||
org.openide.awt.Mnemonics.setLocalizedText(cordLabel, org.openide.util.NbBundle.getMessage(MapPanel.class, "MapPanel.cordLabel.text")); // NOI18N
|
org.openide.awt.Mnemonics.setLocalizedText(cordLabel, org.openide.util.NbBundle.getMessage(MapPanel.class, "MapPanel.cordLabel.text")); // NOI18N
|
||||||
infoPanel.add(cordLabel, java.awt.BorderLayout.EAST);
|
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||||
|
gridBagConstraints.gridx = 0;
|
||||||
|
gridBagConstraints.gridy = 0;
|
||||||
|
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||||
|
gridBagConstraints.weightx = 1.0;
|
||||||
|
gridBagConstraints.insets = new java.awt.Insets(0, 5, 0, 5);
|
||||||
|
infoPanel.add(cordLabel, gridBagConstraints);
|
||||||
|
|
||||||
|
progressBar.setIndeterminate(true);
|
||||||
|
progressBar.setStringPainted(true);
|
||||||
|
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||||
|
gridBagConstraints.gridx = 1;
|
||||||
|
gridBagConstraints.gridy = 0;
|
||||||
|
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST;
|
||||||
|
infoPanel.add(progressBar, gridBagConstraints);
|
||||||
|
|
||||||
add(infoPanel, java.awt.BorderLayout.SOUTH);
|
add(infoPanel, java.awt.BorderLayout.SOUTH);
|
||||||
}// </editor-fold>//GEN-END:initComponents
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
@ -594,6 +621,7 @@ final public class MapPanel extends javax.swing.JPanel {
|
|||||||
private javax.swing.JLabel cordLabel;
|
private javax.swing.JLabel cordLabel;
|
||||||
private javax.swing.JPanel infoPanel;
|
private javax.swing.JPanel infoPanel;
|
||||||
private org.jxmapviewer.JXMapViewer mapViewer;
|
private org.jxmapviewer.JXMapViewer mapViewer;
|
||||||
|
private javax.swing.JProgressBar progressBar;
|
||||||
private javax.swing.JPanel zoomPanel;
|
private javax.swing.JPanel zoomPanel;
|
||||||
private javax.swing.JSlider zoomSlider;
|
private javax.swing.JSlider zoomSlider;
|
||||||
// End of variables declaration//GEN-END:variables
|
// End of variables declaration//GEN-END:variables
|
||||||
|
@ -103,8 +103,7 @@ public class PlasoIngestModule implements DataSourceIngestModule {
|
|||||||
|
|
||||||
@NbBundle.Messages({
|
@NbBundle.Messages({
|
||||||
"PlasoIngestModule.executable.not.found=Plaso Executable Not Found.",
|
"PlasoIngestModule.executable.not.found=Plaso Executable Not Found.",
|
||||||
"PlasoIngestModule.requires.windows=Plaso module requires windows.",
|
"PlasoIngestModule.requires.windows=Plaso module requires windows."})
|
||||||
"PlasoIngestModule.dataSource.not.an.image=Datasource is not an Image."})
|
|
||||||
@Override
|
@Override
|
||||||
public void startUp(IngestJobContext context) throws IngestModuleException {
|
public void startUp(IngestJobContext context) throws IngestModuleException {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
@ -121,11 +120,6 @@ public class PlasoIngestModule implements DataSourceIngestModule {
|
|||||||
throw new IngestModuleException(Bundle.PlasoIngestModule_executable_not_found(), exception);
|
throw new IngestModuleException(Bundle.PlasoIngestModule_executable_not_found(), exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
Content dataSource = context.getDataSource();
|
|
||||||
if (!(dataSource instanceof Image)) {
|
|
||||||
throw new IngestModuleException(Bundle.PlasoIngestModule_dataSource_not_an_image());
|
|
||||||
}
|
|
||||||
image = (Image) dataSource;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NbBundle.Messages({
|
@NbBundle.Messages({
|
||||||
@ -138,11 +132,20 @@ public class PlasoIngestModule implements DataSourceIngestModule {
|
|||||||
"PlasoIngestModule.psort.cancelled=psort run was canceled",
|
"PlasoIngestModule.psort.cancelled=psort run was canceled",
|
||||||
"PlasoIngestModule.bad.imageFile=Cannot find image file name and path",
|
"PlasoIngestModule.bad.imageFile=Cannot find image file name and path",
|
||||||
"PlasoIngestModule.completed=Plaso Processing Completed",
|
"PlasoIngestModule.completed=Plaso Processing Completed",
|
||||||
"PlasoIngestModule.has.run=Plaso Plugin has been run.",
|
"PlasoIngestModule.has.run=Plaso",
|
||||||
"PlasoIngestModule.psort.fail=Plaso returned an error when sorting events. Results are not complete."})
|
"PlasoIngestModule.psort.fail=Plaso returned an error when sorting events. Results are not complete.",
|
||||||
|
"PlasoIngestModule.dataSource.not.an.image=Skipping non-disk image datasource"})
|
||||||
@Override
|
@Override
|
||||||
public ProcessResult process(Content dataSource, DataSourceIngestModuleProgress statusHelper) {
|
public ProcessResult process(Content dataSource, DataSourceIngestModuleProgress statusHelper) {
|
||||||
assert dataSource.equals(image);
|
|
||||||
|
if (!(dataSource instanceof Image)) {
|
||||||
|
IngestMessage message = IngestMessage.createMessage(IngestMessage.MessageType.DATA,
|
||||||
|
Bundle.PlasoIngestModule_has_run(),
|
||||||
|
Bundle.PlasoIngestModule_dataSource_not_an_image());
|
||||||
|
IngestServices.getInstance().postMessage(message);
|
||||||
|
return ProcessResult.OK;
|
||||||
|
} else {
|
||||||
|
image = (Image) dataSource;
|
||||||
|
|
||||||
statusHelper.switchToDeterminate(100);
|
statusHelper.switchToDeterminate(100);
|
||||||
currentCase = Case.getCurrentCase();
|
currentCase = Case.getCurrentCase();
|
||||||
@ -213,6 +216,7 @@ public class PlasoIngestModule implements DataSourceIngestModule {
|
|||||||
IngestServices.getInstance().postMessage(message);
|
IngestServices.getInstance().postMessage(message);
|
||||||
return ProcessResult.OK;
|
return ProcessResult.OK;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private ProcessBuilder buildLog2TimeLineCommand(Path moduleOutputPath, Image image) {
|
private ProcessBuilder buildLog2TimeLineCommand(Path moduleOutputPath, Image image) {
|
||||||
//make a csv list of disabled parsers.
|
//make a csv list of disabled parsers.
|
||||||
@ -240,8 +244,10 @@ public class PlasoIngestModule implements DataSourceIngestModule {
|
|||||||
|
|
||||||
static private ProcessBuilder buildProcessWithRunAsInvoker(String... commandLine) {
|
static private ProcessBuilder buildProcessWithRunAsInvoker(String... commandLine) {
|
||||||
ProcessBuilder processBuilder = new ProcessBuilder(commandLine);
|
ProcessBuilder processBuilder = new ProcessBuilder(commandLine);
|
||||||
/* Add an environment variable to force log2timeline/psort to run with
|
/*
|
||||||
* the same permissions Autopsy uses. */
|
* Add an environment variable to force log2timeline/psort to run with
|
||||||
|
* the same permissions Autopsy uses.
|
||||||
|
*/
|
||||||
processBuilder.environment().put("__COMPAT_LAYER", "RunAsInvoker"); //NON-NLS
|
processBuilder.environment().put("__COMPAT_LAYER", "RunAsInvoker"); //NON-NLS
|
||||||
return processBuilder;
|
return processBuilder;
|
||||||
}
|
}
|
||||||
@ -277,8 +283,7 @@ public class PlasoIngestModule implements DataSourceIngestModule {
|
|||||||
"PlasoIngestModule.create.artifacts.cancelled=Cancelled Plaso Artifact Creation ",
|
"PlasoIngestModule.create.artifacts.cancelled=Cancelled Plaso Artifact Creation ",
|
||||||
"# {0} - file that events are from",
|
"# {0} - file that events are from",
|
||||||
"PlasoIngestModule.artifact.progress=Adding events to case: {0}",
|
"PlasoIngestModule.artifact.progress=Adding events to case: {0}",
|
||||||
"PlasoIngestModule.info.empty.database=Plaso database was empty.",
|
"PlasoIngestModule.info.empty.database=Plaso database was empty.",})
|
||||||
})
|
|
||||||
private void createPlasoArtifacts(String plasoDb, DataSourceIngestModuleProgress statusHelper) {
|
private void createPlasoArtifacts(String plasoDb, DataSourceIngestModuleProgress statusHelper) {
|
||||||
Blackboard blackboard = currentCase.getSleuthkitCase().getBlackboard();
|
Blackboard blackboard = currentCase.getSleuthkitCase().getBlackboard();
|
||||||
|
|
||||||
@ -343,9 +348,11 @@ public class PlasoIngestModule implements DataSourceIngestModule {
|
|||||||
BlackboardArtifact bbart = resolvedFile.newArtifact(TSK_TL_EVENT);
|
BlackboardArtifact bbart = resolvedFile.newArtifact(TSK_TL_EVENT);
|
||||||
bbart.addAttributes(bbattributes);
|
bbart.addAttributes(bbattributes);
|
||||||
try {
|
try {
|
||||||
/* Post the artifact which will index the artifact for
|
/*
|
||||||
|
* Post the artifact which will index the artifact for
|
||||||
* keyword search, and fire an event to notify UI of
|
* keyword search, and fire an event to notify UI of
|
||||||
* this new artifact */
|
* this new artifact
|
||||||
|
*/
|
||||||
blackboard.postArtifact(bbart, MODULE_NAME);
|
blackboard.postArtifact(bbart, MODULE_NAME);
|
||||||
} catch (BlackboardException ex) {
|
} catch (BlackboardException ex) {
|
||||||
logger.log(Level.SEVERE, "Error Posting Artifact.", ex);//NON-NLS
|
logger.log(Level.SEVERE, "Error Posting Artifact.", ex);//NON-NLS
|
||||||
|
@ -46,6 +46,8 @@ from org.sleuthkit.datamodel import Account
|
|||||||
from org.sleuthkit.datamodel.blackboardutils import CommunicationArtifactsHelper
|
from org.sleuthkit.datamodel.blackboardutils import CommunicationArtifactsHelper
|
||||||
from org.sleuthkit.datamodel.blackboardutils.CommunicationArtifactsHelper import MessageReadStatus
|
from org.sleuthkit.datamodel.blackboardutils.CommunicationArtifactsHelper import MessageReadStatus
|
||||||
from org.sleuthkit.datamodel.blackboardutils.CommunicationArtifactsHelper import CommunicationDirection
|
from org.sleuthkit.datamodel.blackboardutils.CommunicationArtifactsHelper import CommunicationDirection
|
||||||
|
from org.sleuthkit.datamodel.blackboardutils import FileAttachment
|
||||||
|
from org.sleuthkit.datamodel.blackboardutils import MessageAttachments
|
||||||
from TskMessagesParser import TskMessagesParser
|
from TskMessagesParser import TskMessagesParser
|
||||||
from TskContactsParser import TskContactsParser
|
from TskContactsParser import TskContactsParser
|
||||||
from TskCallLogsParser import TskCallLogsParser
|
from TskCallLogsParser import TskCallLogsParser
|
||||||
@ -137,7 +139,7 @@ class SkypeAnalyzer(general.AndroidComponentAnalyzer):
|
|||||||
)
|
)
|
||||||
self.parse_contacts(skype_db, helper)
|
self.parse_contacts(skype_db, helper)
|
||||||
self.parse_calllogs(skype_db, helper)
|
self.parse_calllogs(skype_db, helper)
|
||||||
self.parse_messages(skype_db, helper)
|
self.parse_messages(skype_db, helper, current_case)
|
||||||
except NoCurrentCaseException as ex:
|
except NoCurrentCaseException as ex:
|
||||||
self._logger.log(Level.WARNING, "No case currently open.", ex)
|
self._logger.log(Level.WARNING, "No case currently open.", ex)
|
||||||
self._logger.log(Level.WARNING, traceback.format_exc())
|
self._logger.log(Level.WARNING, traceback.format_exc())
|
||||||
@ -209,13 +211,13 @@ class SkypeAnalyzer(general.AndroidComponentAnalyzer):
|
|||||||
"Failed to post call log artifact to the blackboard", ex)
|
"Failed to post call log artifact to the blackboard", ex)
|
||||||
self._logger.log(Level.WARNING, traceback.format_exc())
|
self._logger.log(Level.WARNING, traceback.format_exc())
|
||||||
|
|
||||||
def parse_messages(self, skype_db, helper):
|
def parse_messages(self, skype_db, helper, current_case):
|
||||||
#Query for messages and iterate row by row adding
|
#Query for messages and iterate row by row adding
|
||||||
#each message artifact
|
#each message artifact
|
||||||
try:
|
try:
|
||||||
messages_parser = SkypeMessagesParser(skype_db)
|
messages_parser = SkypeMessagesParser(skype_db)
|
||||||
while messages_parser.next():
|
while messages_parser.next():
|
||||||
helper.addMessage(
|
message_artifact = helper.addMessage(
|
||||||
messages_parser.get_message_type(),
|
messages_parser.get_message_type(),
|
||||||
messages_parser.get_message_direction(),
|
messages_parser.get_message_direction(),
|
||||||
messages_parser.get_phone_number_from(),
|
messages_parser.get_phone_number_from(),
|
||||||
@ -226,6 +228,13 @@ class SkypeAnalyzer(general.AndroidComponentAnalyzer):
|
|||||||
messages_parser.get_message_text(),
|
messages_parser.get_message_text(),
|
||||||
messages_parser.get_thread_id()
|
messages_parser.get_thread_id()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (messages_parser.get_file_attachment() is not None):
|
||||||
|
file_attachments = ArrayList()
|
||||||
|
file_attachments.add(FileAttachment(current_case.getSleuthkitCase(), skype_db.getDBFile().getDataSource(), messages_parser.get_file_attachment()))
|
||||||
|
message_attachments = MessageAttachments(file_attachments, [])
|
||||||
|
helper.addAttachments(message_artifact, message_attachments)
|
||||||
|
|
||||||
messages_parser.close()
|
messages_parser.close()
|
||||||
except SQLException as ex:
|
except SQLException as ex:
|
||||||
#Error parsing Skype db
|
#Error parsing Skype db
|
||||||
@ -425,12 +434,6 @@ class SkypeMessagesParser(TskMessagesParser):
|
|||||||
content = self.result_set.getString("content")
|
content = self.result_set.getString("content")
|
||||||
|
|
||||||
if content is not None:
|
if content is not None:
|
||||||
file_path = self.result_set.getString("device_gallery_path")
|
|
||||||
|
|
||||||
#if a file name and file path are associated with a message, append it
|
|
||||||
if file_path is not None:
|
|
||||||
return general.appendAttachmentList(content, [file_path])
|
|
||||||
|
|
||||||
return content
|
return content
|
||||||
|
|
||||||
return super(SkypeMessagesParser, self).get_message_text()
|
return super(SkypeMessagesParser, self).get_message_text()
|
||||||
@ -440,3 +443,11 @@ class SkypeMessagesParser(TskMessagesParser):
|
|||||||
if group_ids is not None:
|
if group_ids is not None:
|
||||||
return self.result_set.getString("conversation_id")
|
return self.result_set.getString("conversation_id")
|
||||||
return super(SkypeMessagesParser, self).get_thread_id()
|
return super(SkypeMessagesParser, self).get_thread_id()
|
||||||
|
|
||||||
|
|
||||||
|
def get_file_attachment(self):
|
||||||
|
if (self.result_set.getString("device_gallery_path") is None):
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
return self.result_set.getString("device_gallery_path")
|
||||||
|
|
||||||
|
@ -45,6 +45,9 @@ from org.sleuthkit.datamodel import Account
|
|||||||
from org.sleuthkit.datamodel.blackboardutils import CommunicationArtifactsHelper
|
from org.sleuthkit.datamodel.blackboardutils import CommunicationArtifactsHelper
|
||||||
from org.sleuthkit.datamodel.blackboardutils.CommunicationArtifactsHelper import MessageReadStatus
|
from org.sleuthkit.datamodel.blackboardutils.CommunicationArtifactsHelper import MessageReadStatus
|
||||||
from org.sleuthkit.datamodel.blackboardutils.CommunicationArtifactsHelper import CommunicationDirection
|
from org.sleuthkit.datamodel.blackboardutils.CommunicationArtifactsHelper import CommunicationDirection
|
||||||
|
from org.sleuthkit.datamodel.blackboardutils import FileAttachment
|
||||||
|
from org.sleuthkit.datamodel.blackboardutils import URLAttachment
|
||||||
|
from org.sleuthkit.datamodel.blackboardutils import MessageAttachments
|
||||||
from TskMessagesParser import TskMessagesParser
|
from TskMessagesParser import TskMessagesParser
|
||||||
from TskContactsParser import TskContactsParser
|
from TskContactsParser import TskContactsParser
|
||||||
from TskCallLogsParser import TskCallLogsParser
|
from TskCallLogsParser import TskCallLogsParser
|
||||||
@ -151,7 +154,7 @@ class WhatsAppAnalyzer(general.AndroidComponentAnalyzer):
|
|||||||
current_case.getSleuthkitCase(), self._PARSER_NAME,
|
current_case.getSleuthkitCase(), self._PARSER_NAME,
|
||||||
calllog_and_message_db.getDBFile(), Account.Type.WHATSAPP)
|
calllog_and_message_db.getDBFile(), Account.Type.WHATSAPP)
|
||||||
self.parse_calllogs(calllog_and_message_db, helper)
|
self.parse_calllogs(calllog_and_message_db, helper)
|
||||||
self.parse_messages(dataSource, calllog_and_message_db, helper)
|
self.parse_messages(dataSource, calllog_and_message_db, helper, current_case)
|
||||||
|
|
||||||
except NoCurrentCaseException as ex:
|
except NoCurrentCaseException as ex:
|
||||||
#If there is no current case, bail out immediately.
|
#If there is no current case, bail out immediately.
|
||||||
@ -227,14 +230,14 @@ class WhatsAppAnalyzer(general.AndroidComponentAnalyzer):
|
|||||||
"Error posting calllog artifact to the blackboard.", ex)
|
"Error posting calllog artifact to the blackboard.", ex)
|
||||||
self._logger.log(Level.WARNING, traceback.format_exc())
|
self._logger.log(Level.WARNING, traceback.format_exc())
|
||||||
|
|
||||||
def parse_messages(self, dataSource, messages_db, helper):
|
def parse_messages(self, dataSource, messages_db, helper, current_case):
|
||||||
try:
|
try:
|
||||||
messages_db.attachDatabase(dataSource, "wa.db",
|
messages_db.attachDatabase(dataSource, "wa.db",
|
||||||
messages_db.getDBFile().getParentPath(), "wadb")
|
messages_db.getDBFile().getParentPath(), "wadb")
|
||||||
|
|
||||||
messages_parser = WhatsAppMessagesParser(messages_db)
|
messages_parser = WhatsAppMessagesParser(messages_db)
|
||||||
while messages_parser.next():
|
while messages_parser.next():
|
||||||
helper.addMessage(
|
message_artifact = helper.addMessage(
|
||||||
messages_parser.get_message_type(),
|
messages_parser.get_message_type(),
|
||||||
messages_parser.get_message_direction(),
|
messages_parser.get_message_direction(),
|
||||||
messages_parser.get_phone_number_from(),
|
messages_parser.get_phone_number_from(),
|
||||||
@ -245,6 +248,14 @@ class WhatsAppAnalyzer(general.AndroidComponentAnalyzer):
|
|||||||
messages_parser.get_message_text(),
|
messages_parser.get_message_text(),
|
||||||
messages_parser.get_thread_id()
|
messages_parser.get_thread_id()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# add attachments, if any
|
||||||
|
if (messages_parser.get_url_attachment() is not None):
|
||||||
|
url_attachments = ArrayList()
|
||||||
|
url_attachments.add(URLAttachment(messages_parser.get_url_attachment()))
|
||||||
|
message_attachments = MessageAttachments([], url_attachments)
|
||||||
|
helper.addAttachments(message_artifact, message_attachments)
|
||||||
|
|
||||||
messages_parser.close()
|
messages_parser.close()
|
||||||
except SQLException as ex:
|
except SQLException as ex:
|
||||||
self._logger.log(Level.WARNING, "Error querying the whatsapp database for contacts.", ex)
|
self._logger.log(Level.WARNING, "Error querying the whatsapp database for contacts.", ex)
|
||||||
@ -502,9 +513,6 @@ class WhatsAppMessagesParser(TskMessagesParser):
|
|||||||
message = self.result_set.getString("content")
|
message = self.result_set.getString("content")
|
||||||
if message is None:
|
if message is None:
|
||||||
message = super(WhatsAppMessagesParser, self).get_message_text()
|
message = super(WhatsAppMessagesParser, self).get_message_text()
|
||||||
attachment = self.result_set.getString("attachment")
|
|
||||||
if attachment is not None:
|
|
||||||
return general.appendAttachmentList(message, [attachment])
|
|
||||||
return message
|
return message
|
||||||
|
|
||||||
def get_thread_id(self):
|
def get_thread_id(self):
|
||||||
@ -512,3 +520,14 @@ class WhatsAppMessagesParser(TskMessagesParser):
|
|||||||
if group is not None:
|
if group is not None:
|
||||||
return self.result_set.getString("id")
|
return self.result_set.getString("id")
|
||||||
return super(WhatsAppMessagesParser, self).get_thread_id()
|
return super(WhatsAppMessagesParser, self).get_thread_id()
|
||||||
|
|
||||||
|
|
||||||
|
def get_url_attachment(self):
|
||||||
|
attachment = self.result_set.getString("attachment")
|
||||||
|
if (attachment is None):
|
||||||
|
return None
|
||||||
|
elif (str(attachment).startswith("http:") or str(attachment).startswith("https:") ):
|
||||||
|
return attachment
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
@ -554,22 +554,24 @@ class Chrome extends Extract {
|
|||||||
RecentActivityExtracterModuleFactory.getModuleName(),
|
RecentActivityExtracterModuleFactory.getModuleName(),
|
||||||
NbBundle.getMessage(this.getClass(), "Chrome.moduleName")));
|
NbBundle.getMessage(this.getClass(), "Chrome.moduleName")));
|
||||||
|
|
||||||
BlackboardArtifact bbart = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, downloadFile, bbattributes);
|
BlackboardArtifact webDownloadArtifact = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, downloadFile, bbattributes);
|
||||||
if (bbart != null) {
|
if (webDownloadArtifact != null) {
|
||||||
bbartifacts.add(bbart);
|
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.
|
||||||
try {
|
try {
|
||||||
for (AbstractFile downloadedFile : fileManager.findFiles(dataSource, FilenameUtils.getName(fullPath), FilenameUtils.getPath(fullPath))) {
|
for (AbstractFile downloadedFile : fileManager.findFiles(dataSource, FilenameUtils.getName(fullPath), FilenameUtils.getPath(fullPath))) {
|
||||||
BlackboardArtifact downloadSourceArt = downloadedFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_DOWNLOAD_SOURCE);
|
BlackboardArtifact associatedObjectArtifact = downloadedFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT);
|
||||||
downloadSourceArt.addAttributes(createDownloadSourceAttributes(result.get("url").toString()));
|
associatedObjectArtifact.addAttribute(
|
||||||
|
new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT,
|
||||||
|
RecentActivityExtracterModuleFactory.getModuleName(), webDownloadArtifact.getArtifactID()));
|
||||||
|
|
||||||
bbartifacts.add(downloadSourceArt);
|
bbartifacts.add(associatedObjectArtifact);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
logger.log(Level.SEVERE, String.format("Error creating download source artifact for file '%s'", fullPath), ex); //NON-NLS
|
logger.log(Level.SEVERE, String.format("Error creating associated object artifact for file '%s'", fullPath), ex); //NON-NLS
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,12 +380,12 @@ final class ChromeCacheExtractor {
|
|||||||
* Extracts the files if needed and adds as derived files, creates artifacts
|
* Extracts the files if needed and adds as derived files, creates artifacts
|
||||||
*
|
*
|
||||||
* @param cacheEntryAddress cache entry address
|
* @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
|
* @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
|
* @return Optional derived file, is a derived file is added for the given entry
|
||||||
*/
|
*/
|
||||||
private List<DerivedFile> processCacheEntry(CacheAddress cacheEntryAddress, Collection<BlackboardArtifact> sourceArtifacts, Collection<BlackboardArtifact> webCacheArtifacts ) throws TskCoreException, IngestModuleException {
|
private List<DerivedFile> processCacheEntry(CacheAddress cacheEntryAddress, Collection<BlackboardArtifact> associatedObjectArtifacts, Collection<BlackboardArtifact> webCacheArtifacts ) throws TskCoreException, IngestModuleException {
|
||||||
|
|
||||||
List<DerivedFile> derivedFiles = new ArrayList<>();
|
List<DerivedFile> derivedFiles = new ArrayList<>();
|
||||||
|
|
||||||
@ -437,10 +437,6 @@ final class ChromeCacheExtractor {
|
|||||||
moduleName,
|
moduleName,
|
||||||
cacheEntry.getHTTPHeaders());
|
cacheEntry.getHTTPHeaders());
|
||||||
|
|
||||||
Collection<BlackboardAttribute> sourceArtifactAttributes = new ArrayList<>();
|
|
||||||
sourceArtifactAttributes.add(urlAttr);
|
|
||||||
sourceArtifactAttributes.add(createTimeAttr);
|
|
||||||
|
|
||||||
Collection<BlackboardAttribute> webCacheAttributes = new ArrayList<>();
|
Collection<BlackboardAttribute> webCacheAttributes = new ArrayList<>();
|
||||||
webCacheAttributes.add(urlAttr);
|
webCacheAttributes.add(urlAttr);
|
||||||
webCacheAttributes.add(createTimeAttr);
|
webCacheAttributes.add(createTimeAttr);
|
||||||
@ -450,11 +446,6 @@ final class ChromeCacheExtractor {
|
|||||||
// add artifacts to the f_XXX file
|
// add artifacts to the f_XXX file
|
||||||
if (dataSegment.isInExternalFile() ) {
|
if (dataSegment.isInExternalFile() ) {
|
||||||
try {
|
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);
|
BlackboardArtifact webCacheArtifact = cacheEntryFile.get().getAbstractFile().newArtifact(ARTIFACT_TYPE.TSK_WEB_CACHE);
|
||||||
if (webCacheArtifact != null) {
|
if (webCacheArtifact != null) {
|
||||||
@ -469,6 +460,14 @@ final class ChromeCacheExtractor {
|
|||||||
moduleName, cachedFileAbstractFile.get().getId()));
|
moduleName, cachedFileAbstractFile.get().getId()));
|
||||||
|
|
||||||
webCacheArtifacts.add(webCacheArtifact);
|
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) {
|
if (isBrotliCompressed) {
|
||||||
@ -497,11 +496,6 @@ final class ChromeCacheExtractor {
|
|||||||
"",
|
"",
|
||||||
TskData.EncodingType.NONE);
|
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);
|
BlackboardArtifact webCacheArtifact = cacheEntryFile.get().getAbstractFile().newArtifact(ARTIFACT_TYPE.TSK_WEB_CACHE);
|
||||||
if (webCacheArtifact != null) {
|
if (webCacheArtifact != null) {
|
||||||
@ -516,6 +510,14 @@ final class ChromeCacheExtractor {
|
|||||||
moduleName, derivedFile.getId()));
|
moduleName, derivedFile.getId()));
|
||||||
|
|
||||||
webCacheArtifacts.add(webCacheArtifact);
|
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) {
|
if (isBrotliCompressed) {
|
||||||
|
@ -50,6 +50,7 @@ import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
|
|||||||
import org.sleuthkit.autopsy.recentactivity.BinaryCookieReader.Cookie;
|
import org.sleuthkit.autopsy.recentactivity.BinaryCookieReader.Cookie;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
|
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||||
import org.sleuthkit.datamodel.Content;
|
import org.sleuthkit.datamodel.Content;
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
import org.xml.sax.SAXException;
|
import org.xml.sax.SAXException;
|
||||||
@ -637,15 +638,17 @@ final class ExtractSafari extends Extract {
|
|||||||
time = date.getDate().getTime();
|
time = date.getDate().getTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
BlackboardArtifact bbart = origFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD);
|
BlackboardArtifact webDownloadArtifact = origFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD);
|
||||||
bbart.addAttributes(this.createDownloadAttributes(path, pathID, url, time, NetworkUtils.extractDomain(url), getName()));
|
webDownloadArtifact.addAttributes(this.createDownloadAttributes(path, pathID, url, time, NetworkUtils.extractDomain(url), getName()));
|
||||||
bbartifacts.add(bbart);
|
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))) {
|
for (AbstractFile downloadedFile : fileManager.findFiles(dataSource, FilenameUtils.getName(path), FilenameUtils.getPath(path))) {
|
||||||
BlackboardArtifact downloadSourceArt = downloadedFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_DOWNLOAD_SOURCE);
|
BlackboardArtifact associatedObjectArtifact = downloadedFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT);
|
||||||
downloadSourceArt.addAttributes(createDownloadSourceAttributes(url));
|
associatedObjectArtifact.addAttribute(
|
||||||
bbartifacts.add(downloadSourceArt);
|
new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT,
|
||||||
|
RecentActivityExtracterModuleFactory.getModuleName(), webDownloadArtifact.getArtifactID()));
|
||||||
|
bbartifacts.add(associatedObjectArtifact);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +28,6 @@ import java.util.List;
|
|||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.openide.util.NbBundle.Messages;
|
import org.openide.util.NbBundle.Messages;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.coreutils.NetworkUtils;
|
import org.sleuthkit.autopsy.coreutils.NetworkUtils;
|
||||||
@ -36,13 +35,11 @@ import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProgress;
|
|||||||
import org.sleuthkit.autopsy.ingest.IngestJobContext;
|
import org.sleuthkit.autopsy.ingest.IngestJobContext;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_DOWNLOAD_SOURCE;
|
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT;
|
||||||
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD;
|
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD;
|
||||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN;
|
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT;
|
||||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_LOCATION;
|
|
||||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID;
|
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID;
|
||||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL;
|
|
||||||
import org.sleuthkit.datamodel.Content;
|
import org.sleuthkit.datamodel.Content;
|
||||||
import org.sleuthkit.datamodel.ReadContentInputStream;
|
import org.sleuthkit.datamodel.ReadContentInputStream;
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
@ -94,7 +91,7 @@ final class ExtractZoneIdentifier extends Extract {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Collection<BlackboardArtifact> sourceArtifacts = new ArrayList<>();
|
Collection<BlackboardArtifact> associatedObjectArtifacts = new ArrayList<>();
|
||||||
Collection<BlackboardArtifact> downloadArtifacts = new ArrayList<>();
|
Collection<BlackboardArtifact> downloadArtifacts = new ArrayList<>();
|
||||||
|
|
||||||
for (AbstractFile zoneFile : zoneFiles) {
|
for (AbstractFile zoneFile : zoneFiles) {
|
||||||
@ -104,7 +101,7 @@ final class ExtractZoneIdentifier extends Extract {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
processZoneFile(context, dataSource, zoneFile, sourceArtifacts, downloadArtifacts, knownPathIDs);
|
processZoneFile(context, dataSource, zoneFile, associatedObjectArtifacts, downloadArtifacts, knownPathIDs);
|
||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
addErrorMessage(Bundle.ExtractZone_process_errMsg());
|
addErrorMessage(Bundle.ExtractZone_process_errMsg());
|
||||||
String message = String.format("Failed to process zone identifier file %s", zoneFile.getName()); //NON-NLS
|
String message = String.format("Failed to process zone identifier file %s", zoneFile.getName()); //NON-NLS
|
||||||
@ -112,7 +109,7 @@ final class ExtractZoneIdentifier extends Extract {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
postArtifacts(sourceArtifacts);
|
postArtifacts(associatedObjectArtifacts);
|
||||||
postArtifacts(downloadArtifacts);
|
postArtifacts(downloadArtifacts);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,13 +119,13 @@ final class ExtractZoneIdentifier extends Extract {
|
|||||||
* @param context IngetJobContext
|
* @param context IngetJobContext
|
||||||
* @param dataSource Content
|
* @param dataSource Content
|
||||||
* @param zoneFile Zone Indentifier file
|
* @param zoneFile Zone Indentifier file
|
||||||
* @param sourceArtifacts List for TSK_DOWNLOAD_SOURCE artifacts
|
* @param associatedObjectArtifacts List for TSK_ASSOCIATED_OBJECT artifacts
|
||||||
* @param downloadArtifacts List for TSK_WEB_DOWNLOAD aritfacts
|
* @param downloadArtifacts List for TSK_WEB_DOWNLOAD artifacts
|
||||||
*
|
*
|
||||||
* @throws TskCoreException
|
* @throws TskCoreException
|
||||||
*/
|
*/
|
||||||
private void processZoneFile(IngestJobContext context, Content dataSource,
|
private void processZoneFile(IngestJobContext context, Content dataSource,
|
||||||
AbstractFile zoneFile, Collection<BlackboardArtifact> sourceArtifacts,
|
AbstractFile zoneFile, Collection<BlackboardArtifact> associatedObjectArtifacts,
|
||||||
Collection<BlackboardArtifact> downloadArtifacts,
|
Collection<BlackboardArtifact> downloadArtifacts,
|
||||||
Set<Long> knownPathIDs) throws TskCoreException {
|
Set<Long> knownPathIDs) throws TskCoreException {
|
||||||
|
|
||||||
@ -155,16 +152,16 @@ final class ExtractZoneIdentifier extends Extract {
|
|||||||
BlackboardArtifact downloadBba = createDownloadArtifact(zoneFile, zoneInfo);
|
BlackboardArtifact downloadBba = createDownloadArtifact(zoneFile, zoneInfo);
|
||||||
if (downloadBba != null) {
|
if (downloadBba != null) {
|
||||||
downloadArtifacts.add(downloadBba);
|
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 +200,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.
|
* object.
|
||||||
*
|
*
|
||||||
* @param downloadFile AbstractFile representing the file downloaded, not
|
* @param downloadFile AbstractFile representing the file downloaded, not
|
||||||
* the zone identifier file.
|
* the zone identifier file.
|
||||||
* @param zoneInfo Zone identifier file wrapper object
|
* @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<BlackboardAttribute> bbattributes = new ArrayList<>();
|
Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
|
||||||
|
|
||||||
bbattributes.addAll(Arrays.asList(
|
bbattributes.addAll(Arrays.asList(
|
||||||
new BlackboardAttribute(TSK_URL,
|
new BlackboardAttribute(TSK_ASSOCIATED_ARTIFACT,
|
||||||
RecentActivityExtracterModuleFactory.getModuleName(),
|
RecentActivityExtracterModuleFactory.getModuleName(),
|
||||||
StringUtils.defaultString(zoneInfo.getURL(), "")),
|
downloadBba.getArtifactID())
|
||||||
|
));
|
||||||
|
|
||||||
new BlackboardAttribute(TSK_DOMAIN,
|
return createArtifactWithAttributes(TSK_ASSOCIATED_OBJECT, downloadFile, bbattributes);
|
||||||
RecentActivityExtracterModuleFactory.getModuleName(),
|
|
||||||
(zoneInfo.getURL() != null) ? NetworkUtils.extractDomain(zoneInfo.getURL()) : ""),
|
|
||||||
|
|
||||||
new BlackboardAttribute(TSK_LOCATION,
|
|
||||||
RecentActivityExtracterModuleFactory.getModuleName(),
|
|
||||||
StringUtils.defaultString(zoneInfo.getZoneIdAsString(), "")))); //NON-NLS
|
|
||||||
|
|
||||||
return createArtifactWithAttributes(TSK_DOWNLOAD_SOURCE, downloadFile, bbattributes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -544,24 +544,27 @@ class Firefox extends Extract {
|
|||||||
domain)); //NON-NLS
|
domain)); //NON-NLS
|
||||||
}
|
}
|
||||||
|
|
||||||
BlackboardArtifact bbart = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, downloadsFile, bbattributes);
|
BlackboardArtifact webDownloadArtifact = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, downloadsFile, bbattributes);
|
||||||
if (bbart != null) {
|
if (webDownloadArtifact != null) {
|
||||||
bbartifacts.add(bbart);
|
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.
|
||||||
try {
|
try {
|
||||||
for (AbstractFile downloadedFile : fileManager.findFiles(dataSource, FilenameUtils.getName(downloadedFilePath), FilenameUtils.getPath(downloadedFilePath))) {
|
for (AbstractFile downloadedFile : fileManager.findFiles(dataSource, FilenameUtils.getName(downloadedFilePath), FilenameUtils.getPath(downloadedFilePath))) {
|
||||||
BlackboardArtifact downloadSourceArt = downloadedFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_DOWNLOAD_SOURCE);
|
BlackboardArtifact associatedObjectArtifact = downloadedFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT);
|
||||||
downloadSourceArt.addAttributes(createDownloadSourceAttributes(source));
|
associatedObjectArtifact.addAttribute(
|
||||||
bbartifacts.add(downloadSourceArt);
|
new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT,
|
||||||
|
RecentActivityExtracterModuleFactory.getModuleName(), webDownloadArtifact.getArtifactID()));
|
||||||
|
|
||||||
|
bbartifacts.add(associatedObjectArtifact);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
logger.log(Level.SEVERE, String.format("Error creating download source artifact for file '%s'",
|
logger.log(Level.SEVERE, String.format("Error creating associated object artifact for file '%s'",
|
||||||
downloadedFilePath), ex); //NON-NLS
|
downloadedFilePath), ex); //NON-NLS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (errors > 0) {
|
if (errors > 0) {
|
||||||
this.addErrorMessage(
|
this.addErrorMessage(
|
||||||
NbBundle.getMessage(this.getClass(), "Firefox.getDlPre24.errMsg.errParsingArtifacts",
|
NbBundle.getMessage(this.getClass(), "Firefox.getDlPre24.errMsg.errParsingArtifacts",
|
||||||
@ -681,24 +684,26 @@ class Firefox extends Extract {
|
|||||||
RecentActivityExtracterModuleFactory.getModuleName(), domain)); //NON-NLS
|
RecentActivityExtracterModuleFactory.getModuleName(), domain)); //NON-NLS
|
||||||
}
|
}
|
||||||
|
|
||||||
BlackboardArtifact bbart = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, downloadsFile, bbattributes);
|
BlackboardArtifact webDownloadArtifact = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, downloadsFile, bbattributes);
|
||||||
if (bbart != null) {
|
if (webDownloadArtifact != null) {
|
||||||
bbartifacts.add(bbart);
|
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.
|
||||||
try {
|
try {
|
||||||
for (AbstractFile downloadedFile : fileManager.findFiles(dataSource, FilenameUtils.getName(downloadedFilePath), FilenameUtils.getPath(downloadedFilePath))) {
|
for (AbstractFile downloadedFile : fileManager.findFiles(dataSource, FilenameUtils.getName(downloadedFilePath), FilenameUtils.getPath(downloadedFilePath))) {
|
||||||
BlackboardArtifact downloadSourceArt = downloadedFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_DOWNLOAD_SOURCE);
|
BlackboardArtifact associatedObjectArtifact = downloadedFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT);
|
||||||
downloadSourceArt.addAttributes(createDownloadSourceAttributes(url));
|
associatedObjectArtifact.addAttribute(
|
||||||
bbartifacts.add(downloadSourceArt);
|
new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT,
|
||||||
|
RecentActivityExtracterModuleFactory.getModuleName(), webDownloadArtifact.getArtifactID()));
|
||||||
|
bbartifacts.add(associatedObjectArtifact);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
logger.log(Level.SEVERE, String.format("Error creating download source artifact for file '%s'",
|
logger.log(Level.SEVERE, String.format("Error creating associated object artifact for file '%s'",
|
||||||
downloadedFilePath), ex); //NON-NLS
|
downloadedFilePath), ex); //NON-NLS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (errors > 0) {
|
if (errors > 0) {
|
||||||
this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Firefox.getDlV24.errMsg.errParsingArtifacts",
|
this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Firefox.getDlV24.errMsg.errParsingArtifacts",
|
||||||
this.getName(), errors));
|
this.getName(), errors));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user