mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-12 16:06:15 +00:00
Merge branch 'release-4.12.0' of https://github.com/sleuthkit/autopsy into 5187-LogicalImagerGUITweaks
This commit is contained in:
commit
78e8ecfbb3
@ -75,7 +75,7 @@ file.reference.javax.ws.rs-api-2.0.1.jar=release/modules/ext/javax.ws.rs-api-2.0
|
||||
file.reference.cxf-core-3.0.16.jar=release/modules/ext/cxf-core-3.0.16.jar
|
||||
file.reference.cxf-rt-frontend-jaxrs-3.0.16.jar=release/modules/ext/cxf-rt-frontend-jaxrs-3.0.16.jar
|
||||
file.reference.cxf-rt-transports-http-3.0.16.jar=release/modules/ext/cxf-rt-transports-http-3.0.16.jar
|
||||
file.reference.sleuthkit-postgresql-4.6.6.jar=release/modules/ext/sleuthkit-postgresql-4.6.6.jar
|
||||
file.reference.sleuthkit-postgresql-4.6.7.jar=release/modules/ext/sleuthkit-postgresql-4.6.7.jar
|
||||
file.reference.curator-client-2.8.0.jar=release/modules/ext/curator-client-2.8.0.jar
|
||||
file.reference.curator-framework-2.8.0.jar=release/modules/ext/curator-framework-2.8.0.jar
|
||||
file.reference.curator-recipes-2.8.0.jar=release/modules/ext/curator-recipes-2.8.0.jar
|
||||
|
@ -482,8 +482,8 @@
|
||||
<binary-origin>release\modules\ext\jmatio-1.5.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/sleuthkit-postgresql-4.6.6.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/sleuthkit-postgresql-4.6.6.jar</binary-origin>
|
||||
<runtime-relative-path>ext/sleuthkit-postgresql-4.6.7.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/sleuthkit-postgresql-4.6.7.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/tika-parsers-1.20.jar</runtime-relative-path>
|
||||
|
BIN
Core/src/org/sleuthkit/autopsy/communications/images/nail.png
Executable file
BIN
Core/src/org/sleuthkit/autopsy/communications/images/nail.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 202 B |
BIN
Core/src/org/sleuthkit/autopsy/communications/images/screw.png
Executable file
BIN
Core/src/org/sleuthkit/autopsy/communications/images/screw.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 217 B |
BIN
Core/src/org/sleuthkit/autopsy/communications/images/threaded.png
Executable file
BIN
Core/src/org/sleuthkit/autopsy/communications/images/threaded.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 263 B |
BIN
Core/src/org/sleuthkit/autopsy/communications/images/unthreaded.png
Executable file
BIN
Core/src/org/sleuthkit/autopsy/communications/images/unthreaded.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 199 B |
@ -11,5 +11,13 @@ SummaryViewer.emailDataLabel.text=emails
|
||||
SummaryViewer.attachmentsDataLabel.text=attachments
|
||||
SummaryViewer.messagesLabel.text=Messages:
|
||||
SummaryViewer.callLogsLabel.text=Call Logs:
|
||||
ThreadRootMessagePanel.showAllCheckBox.text=Show All Messages
|
||||
ThreadPane.backButton.text=<---
|
||||
SummaryViewer.caseReferencesPanel.border.title=Other Occurrences
|
||||
SummaryViewer.fileReferencesPanel.border.title=File References in Current Case
|
||||
MessageViewer.threadsLabel.text=Select a Thread to View
|
||||
MessageViewer.threadNameLabel.text=<threadName>
|
||||
MessageViewer.showingMessagesLabel.text=Showing Messages for Thread:
|
||||
MessageViewer.backButton.AccessibleContext.accessibleDescription=
|
||||
MessageViewer.backButton.text=Threads
|
||||
MessageViewer.showAllButton.text=All Messages
|
||||
|
@ -19,12 +19,16 @@ MessageNode_Node_Property_Subject=Subject
|
||||
MessageNode_Node_Property_To=To
|
||||
MessageNode_Node_Property_Type=Type
|
||||
MessageViewer_columnHeader_Attms=Attachments
|
||||
MessageViewer_columnHeader_Date=Date
|
||||
MessageViewer_columnHeader_Date=Data
|
||||
MessageViewer_columnHeader_EarlyDate=Earliest Message
|
||||
MessageViewer_columnHeader_From=From
|
||||
MessageViewer_columnHeader_Subject=Subject
|
||||
MessageViewer_columnHeader_To=To
|
||||
MessageViewer_no_messages=<No messages found for selected account>
|
||||
MessageViewer_tabTitle=Messages
|
||||
MessageViewer_viewMessage_all=All
|
||||
MessageViewer_viewMessage_selected=Selected
|
||||
MessageViewer_viewMessage_unthreaded=Unthreaded
|
||||
SummaryViewer.countsPanel.border.title=Counts
|
||||
SummaryViewer.emailLabel.text=Emails:
|
||||
SummaryViewer.contactsLabel.text=Contacts:
|
||||
@ -37,11 +41,19 @@ SummaryViewer.emailDataLabel.text=emails
|
||||
SummaryViewer.attachmentsDataLabel.text=attachments
|
||||
SummaryViewer.messagesLabel.text=Messages:
|
||||
SummaryViewer.callLogsLabel.text=Call Logs:
|
||||
SummaryViewer.caseReferencesPanel.border.title=Other Occurrences
|
||||
SummaryViewer.fileReferencesPanel.border.title=File References in Current Case
|
||||
SummaryViewer_CaseRefNameColumn_Title=Case Name
|
||||
SummaryViewer_CentralRepository_Message=<Enable Central Resposity to see Other Occurrences>
|
||||
SummaryViewer_Creation_Date_Title=Creation Date
|
||||
SummaryViewer_FileRefNameColumn_Title=Path
|
||||
SummaryViewer_TabTitle=Summary
|
||||
SummeryViewer_FileRef_Message=<Select one Accout to see File References>
|
||||
ThreadRootMessagePanel.showAllCheckBox.text=Show All Messages
|
||||
ThreadPane.backButton.text=<---
|
||||
SummaryViewer.caseReferencesPanel.border.title=Other Occurrences
|
||||
SummaryViewer.fileReferencesPanel.border.title=File References in Current Case
|
||||
MessageViewer.threadsLabel.text=Select a Thread to View
|
||||
MessageViewer.threadNameLabel.text=<threadName>
|
||||
MessageViewer.showingMessagesLabel.text=Showing Messages for Thread:
|
||||
MessageViewer.backButton.AccessibleContext.accessibleDescription=
|
||||
MessageViewer.backButton.text=Threads
|
||||
MessageViewer.showAllButton.text=All Messages
|
||||
|
@ -17,34 +17,7 @@
|
||||
<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">
|
||||
<Component id="propertySheet" max="32767" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="nameLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</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="nameLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="propertySheet" pref="283" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="nameLabel">
|
||||
<Properties>
|
||||
@ -55,11 +28,21 @@
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="ContactDetailsPane.nameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="16" insetsLeft="15" insetsBottom="15" insetsRight="15" anchor="23" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="org.openide.explorer.propertysheet.PropertySheet" name="propertySheet">
|
||||
<Properties>
|
||||
<Property name="descriptionAreaVisible" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="1" gridWidth="2" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="9" insetsLeft="15" insetsBottom="16" insetsRight="15" anchor="18" weightX="1.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
@ -73,38 +73,36 @@ public final class ContactDetailsPane extends javax.swing.JPanel implements Expl
|
||||
@SuppressWarnings("unchecked")
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
java.awt.GridBagConstraints gridBagConstraints;
|
||||
|
||||
messageContentViewer1 = new org.sleuthkit.autopsy.contentviewers.MessageContentViewer();
|
||||
nameLabel = new javax.swing.JLabel();
|
||||
propertySheet = new org.openide.explorer.propertysheet.PropertySheet();
|
||||
|
||||
setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
nameLabel.setFont(new java.awt.Font("Tahoma", 0, 24)); // NOI18N
|
||||
org.openide.awt.Mnemonics.setLocalizedText(nameLabel, org.openide.util.NbBundle.getMessage(ContactDetailsPane.class, "ContactDetailsPane.nameLabel.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.FIRST_LINE_START;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(16, 15, 15, 15);
|
||||
add(nameLabel, gridBagConstraints);
|
||||
|
||||
propertySheet.setDescriptionAreaVisible(false);
|
||||
|
||||
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)
|
||||
.addComponent(propertySheet, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(nameLabel)
|
||||
.addGap(0, 0, Short.MAX_VALUE)))
|
||||
.addContainerGap())
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(nameLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(propertySheet, javax.swing.GroupLayout.DEFAULT_SIZE, 283, Short.MAX_VALUE)
|
||||
.addContainerGap())
|
||||
);
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 1;
|
||||
gridBagConstraints.gridwidth = 2;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.weighty = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(9, 15, 16, 15);
|
||||
add(propertySheet, gridBagConstraints);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
|
||||
|
@ -36,7 +36,7 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
* ChildFactory for ContactNodes.
|
||||
*/
|
||||
final class ContactsChildNodeFactory extends ChildFactory<BlackboardArtifact>{
|
||||
private static final Logger logger = Logger.getLogger(MessagesChildNodeFactory.class.getName());
|
||||
private static final Logger logger = Logger.getLogger(ContactsChildNodeFactory.class.getName());
|
||||
|
||||
private SelectionInfo selectionInfo;
|
||||
|
||||
|
@ -20,11 +20,11 @@ package org.sleuthkit.autopsy.communications.relationships;
|
||||
|
||||
import java.util.TimeZone;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.Action;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openide.nodes.Sheet;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
|
||||
import org.sleuthkit.autopsy.datamodel.NodeProperty;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
@ -40,20 +40,31 @@ import static org.sleuthkit.datamodel.BlackboardAttribute.TSK_BLACKBOARD_ATTRIBU
|
||||
import org.sleuthkit.datamodel.TimeUtilities;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.autopsy.communications.Utils;
|
||||
import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
|
||||
|
||||
/**
|
||||
* Wraps a BlackboardArtifact as an AbstractNode for use in an OutlookView
|
||||
*/
|
||||
final class MessageNode extends BlackboardArtifactNode {
|
||||
class MessageNode extends BlackboardArtifactNode {
|
||||
|
||||
public static final String UNTHREADED_ID = "<UNTHREADED>";
|
||||
|
||||
private static final Logger logger = Logger.getLogger(MessageNode.class.getName());
|
||||
|
||||
MessageNode(BlackboardArtifact artifact) {
|
||||
private final String threadID;
|
||||
|
||||
private final Action preferredAction;
|
||||
|
||||
MessageNode(BlackboardArtifact artifact, String threadID, Action preferredAction) {
|
||||
super(artifact);
|
||||
|
||||
this.preferredAction = preferredAction;
|
||||
|
||||
final String stripEnd = StringUtils.stripEnd(artifact.getDisplayName(), "s"); // NON-NLS
|
||||
String removeEndIgnoreCase = StringUtils.removeEndIgnoreCase(stripEnd, "message"); // NON-NLS
|
||||
setDisplayName(removeEndIgnoreCase.isEmpty() ? stripEnd : removeEndIgnoreCase);
|
||||
|
||||
this.threadID = threadID;
|
||||
}
|
||||
|
||||
@Messages({
|
||||
@ -76,6 +87,8 @@ final class MessageNode extends BlackboardArtifactNode {
|
||||
|
||||
sheetSet.put(new NodeProperty<>("Type", Bundle.MessageNode_Node_Property_Type(), "", getDisplayName())); //NON-NLS
|
||||
|
||||
sheetSet.put(new NodeProperty<>("ThreadID", "ThreadID","",threadID == null ? UNTHREADED_ID : threadID)); //NON-NLS
|
||||
|
||||
final BlackboardArtifact artifact = getArtifact();
|
||||
|
||||
BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(artifact.getArtifactTypeID());
|
||||
@ -167,4 +180,13 @@ final class MessageNode extends BlackboardArtifactNode {
|
||||
public String getSourceName() {
|
||||
return getDisplayName();
|
||||
}
|
||||
|
||||
String getThreadID() {
|
||||
return threadID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Action getPreferredAction() {
|
||||
return preferredAction;
|
||||
}
|
||||
}
|
||||
|
140
Core/src/org/sleuthkit/autopsy/communications/relationships/MessageViewer.form
Executable file
140
Core/src/org/sleuthkit/autopsy/communications/relationships/MessageViewer.form
Executable file
@ -0,0 +1,140 @@
|
||||
<?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"/>
|
||||
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,3,-126,0,0,2,-76"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignCardLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JPanel" name="rootMessagesPane">
|
||||
<Properties>
|
||||
<Property name="opaque" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignCardLayout" value="org.netbeans.modules.form.compat2.layouts.DesignCardLayout$CardConstraintsDescription">
|
||||
<CardConstraints cardName="threads"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="threadsLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/relationships/Bundle.properties" key="MessageViewer.threadsLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="15" insetsLeft="15" insetsBottom="9" insetsRight="0" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="showAllButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/relationships/Bundle.properties" key="MessageViewer.showAllButton.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="showAllButtonActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="2" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="15" insetsBottom="15" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel" name="rootTablePane">
|
||||
<Properties>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.LineBorderInfo">
|
||||
<LineBorder/>
|
||||
</Border>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="1" gridWidth="2" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="15" insetsBottom="9" insetsRight="15" anchor="18" weightX="1.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JPanel" name="messagePanel">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignCardLayout" value="org.netbeans.modules.form.compat2.layouts.DesignCardLayout$CardConstraintsDescription">
|
||||
<CardConstraints cardName="messages"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="org.sleuthkit.autopsy.communications.relationships.MessagesPanel" name="threadMessagesPanel">
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new MessagesPanel()"/>
|
||||
</AuxValues>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="3" gridWidth="3" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="15" insetsBottom="0" insetsRight="15" anchor="18" weightX="1.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="backButton">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/relationships/Bundle.properties" key="MessageViewer.backButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AccessibilityProperties>
|
||||
<Property name="AccessibleContext.accessibleDescription" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/relationships/Bundle.properties" key="MessageViewer.backButton.AccessibleContext.accessibleDescription" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</AccessibilityProperties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="backButtonActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="2" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="9" insetsLeft="0" insetsBottom="9" insetsRight="15" anchor="13" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="showingMessagesLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/relationships/Bundle.properties" key="MessageViewer.showingMessagesLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="9" insetsLeft="15" insetsBottom="5" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="threadNameLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/relationships/Bundle.properties" key="MessageViewer.threadNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</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="9" insetsLeft="5" insetsBottom="5" insetsRight="15" anchor="17" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Form>
|
439
Core/src/org/sleuthkit/autopsy/communications/relationships/MessageViewer.java
Executable file
439
Core/src/org/sleuthkit/autopsy/communications/relationships/MessageViewer.java
Executable file
@ -0,0 +1,439 @@
|
||||
/*
|
||||
* 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.communications.relationships;
|
||||
|
||||
import java.awt.CardLayout;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Image;
|
||||
import java.awt.KeyboardFocusManager;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyVetoException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.ListSelectionModel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import static javax.swing.SwingUtilities.isDescendingFrom;
|
||||
import org.netbeans.swing.outline.DefaultOutlineModel;
|
||||
import org.netbeans.swing.outline.Outline;
|
||||
import org.openide.explorer.ExplorerManager;
|
||||
import static org.openide.explorer.ExplorerUtils.createLookup;
|
||||
import org.openide.nodes.AbstractNode;
|
||||
import org.openide.nodes.Children;
|
||||
import org.openide.nodes.Node;
|
||||
import org.openide.nodes.Node.Property;
|
||||
import org.openide.nodes.Node.PropertySet;
|
||||
import org.openide.util.Exceptions;
|
||||
import org.openide.util.Lookup;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.sleuthkit.autopsy.communications.ModifiableProxyLookup;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
/**
|
||||
* The main panel for the messages tab of the RelationshipViewer
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||
public class MessageViewer extends JPanel implements RelationshipsViewer {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(MessageViewer.class.getName());
|
||||
|
||||
private final ModifiableProxyLookup proxyLookup;
|
||||
private final PropertyChangeListener focusPropertyListener;
|
||||
private final ThreadChildNodeFactory rootMessageFactory;
|
||||
private final MessagesChildNodeFactory threadMessageNodeFactory;
|
||||
|
||||
private SelectionInfo currentSelectionInfo = null;
|
||||
|
||||
OutlineViewPanel currentPanel;
|
||||
|
||||
@Messages({
|
||||
"MessageViewer_tabTitle=Messages",
|
||||
"MessageViewer_columnHeader_From=From",
|
||||
"MessageViewer_columnHeader_Date=Data",
|
||||
"MessageViewer_columnHeader_To=To",
|
||||
"MessageViewer_columnHeader_EarlyDate=Earliest Message",
|
||||
"MessageViewer_columnHeader_Subject=Subject",
|
||||
"MessageViewer_columnHeader_Attms=Attachments",
|
||||
"MessageViewer_no_messages=<No messages found for selected account>",
|
||||
"MessageViewer_viewMessage_all=All",
|
||||
"MessageViewer_viewMessage_selected=Selected",
|
||||
"MessageViewer_viewMessage_unthreaded=Unthreaded",})
|
||||
|
||||
/**
|
||||
* Creates new form MessageViewer
|
||||
*/
|
||||
public MessageViewer() {
|
||||
|
||||
initComponents();
|
||||
currentPanel = rootTablePane;
|
||||
proxyLookup = new ModifiableProxyLookup(createLookup(rootTablePane.getExplorerManager(), getActionMap()));
|
||||
rootMessageFactory = new ThreadChildNodeFactory(new ShowThreadMessagesAction());
|
||||
threadMessageNodeFactory = new MessagesChildNodeFactory();
|
||||
|
||||
// See org.sleuthkit.autopsy.timeline.TimeLineTopComponent for a detailed
|
||||
// explaination of focusPropertyListener
|
||||
focusPropertyListener = (final PropertyChangeEvent focusEvent) -> {
|
||||
if (focusEvent.getPropertyName().equalsIgnoreCase("focusOwner")) {
|
||||
final Component newFocusOwner = (Component) focusEvent.getNewValue();
|
||||
|
||||
if (newFocusOwner == null) {
|
||||
return;
|
||||
}
|
||||
if (isDescendingFrom(newFocusOwner, rootTablePane)) {
|
||||
proxyLookup.setNewLookups(createLookup(rootTablePane.getExplorerManager(), getActionMap()));
|
||||
} else if (isDescendingFrom(newFocusOwner, MessageViewer.this)) {
|
||||
proxyLookup.setNewLookups(createLookup(currentPanel.getExplorerManager(), getActionMap()));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
rootTablePane.getExplorerManager().setRootContext(
|
||||
new AbstractNode(Children.create(rootMessageFactory, true)));
|
||||
|
||||
rootTablePane.getOutlineView().setPopupAllowed(false);
|
||||
|
||||
Outline outline = rootTablePane.getOutlineView().getOutline();
|
||||
rootTablePane.getOutlineView().setPropertyColumns(
|
||||
"Date", Bundle.MessageViewer_columnHeader_EarlyDate(),
|
||||
"Subject", Bundle.MessageViewer_columnHeader_Subject()
|
||||
);
|
||||
outline.setRootVisible(false);
|
||||
((DefaultOutlineModel) outline.getOutlineModel()).setNodesColumnLabel("Type");
|
||||
outline.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
|
||||
|
||||
rootTablePane.getExplorerManager().addPropertyChangeListener((PropertyChangeEvent evt) -> {
|
||||
if (evt.getPropertyName().equals(ExplorerManager.PROP_SELECTED_NODES)) {
|
||||
showSelectedThread();
|
||||
}
|
||||
});
|
||||
|
||||
threadMessagesPanel.setChildFactory(threadMessageNodeFactory);
|
||||
|
||||
rootTablePane.setTableColumnsWidth(10, 20, 70);
|
||||
|
||||
Image image = getScaledImage((new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/timeline/images/arrow-180.png"))).getImage(), 16, 16);
|
||||
backButton.setIcon(new ImageIcon(image) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return Bundle.MessageViewer_tabTitle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JPanel getPanel() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelectionInfo(SelectionInfo info) {
|
||||
currentSelectionInfo = info;
|
||||
|
||||
currentPanel = rootTablePane;
|
||||
|
||||
CardLayout layout = (CardLayout) this.getLayout();
|
||||
layout.show(this, "threads");
|
||||
|
||||
rootMessageFactory.refresh(info);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Lookup getLookup() {
|
||||
return proxyLookup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addNotify() {
|
||||
super.addNotify();
|
||||
//add listener that maintains correct selection in the Global Actions Context
|
||||
KeyboardFocusManager.getCurrentKeyboardFocusManager()
|
||||
.addPropertyChangeListener("focusOwner", focusPropertyListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeNotify() {
|
||||
super.removeNotify();
|
||||
KeyboardFocusManager.getCurrentKeyboardFocusManager()
|
||||
.removePropertyChangeListener("focusOwner", focusPropertyListener);
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private void showSelectedThread() {
|
||||
final Node[] nodes = rootTablePane.getExplorerManager().getSelectedNodes();
|
||||
|
||||
if (nodes == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (nodes.length == 0 || nodes.length > 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
ArrayList<String> threadIDList = new ArrayList<>();
|
||||
String subject = "";
|
||||
|
||||
PropertySet[] propertySets = nodes[0].getPropertySets();
|
||||
for (PropertySet pset : propertySets) {
|
||||
Property[] properties = pset.getProperties();
|
||||
for (Property prop : properties) {
|
||||
if (prop.getName().equalsIgnoreCase("threadid")) {
|
||||
try {
|
||||
String threadID = prop.getValue().toString();
|
||||
if (!threadIDList.contains(threadID)) {
|
||||
threadIDList.add(threadID);
|
||||
}
|
||||
} catch (IllegalAccessException | InvocationTargetException ex) {
|
||||
logger.log(Level.WARNING, String.format("Unable to get threadid for node: %s", nodes[0].getDisplayName()), ex);
|
||||
}
|
||||
} else if (prop.getName().equalsIgnoreCase("subject")) {
|
||||
try {
|
||||
subject = prop.getValue().toString();
|
||||
} catch (IllegalAccessException | InvocationTargetException ex) {
|
||||
logger.log(Level.WARNING, String.format("Unable to get subject for node: %s", nodes[0].getDisplayName()), ex);
|
||||
subject = "<unavailable>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!threadIDList.isEmpty()) {
|
||||
threadMessageNodeFactory.refresh(currentSelectionInfo, threadIDList);
|
||||
|
||||
if (!subject.isEmpty()) {
|
||||
threadNameLabel.setText(subject);
|
||||
} else {
|
||||
threadNameLabel.setText(Bundle.MessageViewer_viewMessage_unthreaded());
|
||||
}
|
||||
|
||||
showMessagesPane();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the threads pane visible.
|
||||
*/
|
||||
private void showThreadsPane() {
|
||||
switchCard("threads");
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the message pane visible.
|
||||
*/
|
||||
private void showMessagesPane() {
|
||||
switchCard("messages");
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the visible panel (card).
|
||||
*
|
||||
* @param cardName Name of card to show
|
||||
*/
|
||||
private void switchCard(String cardName) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
CardLayout layout = (CardLayout)getLayout();
|
||||
layout.show(MessageViewer.this, cardName);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Scales the given image to the given width and height.
|
||||
*
|
||||
* @param srcImg Image to scale
|
||||
* @param w Image width
|
||||
* @param h Image height
|
||||
*
|
||||
* @return Scaled version of srcImg
|
||||
*/
|
||||
private Image getScaledImage(Image srcImg, int w, int h){
|
||||
BufferedImage resizedImg = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
|
||||
Graphics2D g2 = resizedImg.createGraphics();
|
||||
|
||||
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
|
||||
g2.drawImage(srcImg, 0, 0, w, h, null);
|
||||
g2.dispose();
|
||||
|
||||
return resizedImg;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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() {
|
||||
java.awt.GridBagConstraints gridBagConstraints;
|
||||
|
||||
rootMessagesPane = new javax.swing.JPanel();
|
||||
threadsLabel = new javax.swing.JLabel();
|
||||
showAllButton = new javax.swing.JButton();
|
||||
rootTablePane = new org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel();
|
||||
messagePanel = new javax.swing.JPanel();
|
||||
threadMessagesPanel = new MessagesPanel();
|
||||
backButton = new javax.swing.JButton();
|
||||
showingMessagesLabel = new javax.swing.JLabel();
|
||||
threadNameLabel = new javax.swing.JLabel();
|
||||
|
||||
setLayout(new java.awt.CardLayout());
|
||||
|
||||
rootMessagesPane.setOpaque(false);
|
||||
rootMessagesPane.setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(threadsLabel, org.openide.util.NbBundle.getMessage(MessageViewer.class, "MessageViewer.threadsLabel.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(15, 15, 9, 0);
|
||||
rootMessagesPane.add(threadsLabel, gridBagConstraints);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(showAllButton, org.openide.util.NbBundle.getMessage(MessageViewer.class, "MessageViewer.showAllButton.text")); // NOI18N
|
||||
showAllButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
showAllButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 2;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 15, 15, 0);
|
||||
rootMessagesPane.add(showAllButton, gridBagConstraints);
|
||||
|
||||
rootTablePane.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 1;
|
||||
gridBagConstraints.gridwidth = 2;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.weighty = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 15, 9, 15);
|
||||
rootMessagesPane.add(rootTablePane, gridBagConstraints);
|
||||
|
||||
add(rootMessagesPane, "threads");
|
||||
|
||||
messagePanel.setLayout(new java.awt.GridBagLayout());
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 3;
|
||||
gridBagConstraints.gridwidth = 3;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.weighty = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(0, 15, 0, 15);
|
||||
messagePanel.add(threadMessagesPanel, gridBagConstraints);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(backButton, org.openide.util.NbBundle.getMessage(MessageViewer.class, "MessageViewer.backButton.text")); // NOI18N
|
||||
backButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
backButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 2;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(9, 0, 9, 15);
|
||||
messagePanel.add(backButton, gridBagConstraints);
|
||||
backButton.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(MessageViewer.class, "MessageViewer.backButton.AccessibleContext.accessibleDescription")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(showingMessagesLabel, org.openide.util.NbBundle.getMessage(MessageViewer.class, "MessageViewer.showingMessagesLabel.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(9, 15, 5, 0);
|
||||
messagePanel.add(showingMessagesLabel, gridBagConstraints);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(threadNameLabel, org.openide.util.NbBundle.getMessage(MessageViewer.class, "MessageViewer.threadNameLabel.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 1;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(9, 5, 5, 15);
|
||||
messagePanel.add(threadNameLabel, gridBagConstraints);
|
||||
|
||||
add(messagePanel, "messages");
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
private void backButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_backButtonActionPerformed
|
||||
try {
|
||||
rootTablePane.getExplorerManager().setSelectedNodes(new Node[0]);
|
||||
} catch (PropertyVetoException ex) {
|
||||
Exceptions.printStackTrace(ex);
|
||||
}
|
||||
showThreadsPane();
|
||||
}//GEN-LAST:event_backButtonActionPerformed
|
||||
|
||||
private void showAllButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_showAllButtonActionPerformed
|
||||
threadMessageNodeFactory.refresh(currentSelectionInfo, null);
|
||||
threadNameLabel.setText("All Messages");
|
||||
|
||||
showMessagesPane();
|
||||
}//GEN-LAST:event_showAllButtonActionPerformed
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JButton backButton;
|
||||
private javax.swing.JPanel messagePanel;
|
||||
private javax.swing.JPanel rootMessagesPane;
|
||||
private org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel rootTablePane;
|
||||
private javax.swing.JButton showAllButton;
|
||||
private javax.swing.JLabel showingMessagesLabel;
|
||||
private org.sleuthkit.autopsy.communications.relationships.MessagesPanel threadMessagesPanel;
|
||||
private javax.swing.JLabel threadNameLabel;
|
||||
private javax.swing.JLabel threadsLabel;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
/**
|
||||
* The preferred action of the table nodes.
|
||||
*/
|
||||
class ShowThreadMessagesAction extends AbstractAction {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
showSelectedThread();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -27,52 +27,51 @@ import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.CommunicationsManager;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
* ChildFactory that creates createKeys and nodes from a given selectionInfo for
|
||||
* only emails, call logs and messages.
|
||||
* A ChildFactory subclass for creating MessageNodes from a set of
|
||||
* BlackboardArtifact objects.
|
||||
*
|
||||
*/
|
||||
final class MessagesChildNodeFactory extends ChildFactory<BlackboardArtifact> {
|
||||
public class MessagesChildNodeFactory extends ChildFactory<BlackboardArtifact>{
|
||||
|
||||
private static final Logger logger = Logger.getLogger(MessagesChildNodeFactory.class.getName());
|
||||
|
||||
private SelectionInfo selectionInfo;
|
||||
|
||||
/**
|
||||
* Construct a new MessageChildNodeFactory from the currently selectionInfo
|
||||
*
|
||||
* @param selectionInfo SelectionInfo object for the currently selected
|
||||
* accounts
|
||||
*/
|
||||
MessagesChildNodeFactory(SelectionInfo selectionInfo) {
|
||||
private List<String> threadIDs;
|
||||
|
||||
MessagesChildNodeFactory(SelectionInfo selectionInfo, List<String> threadIDs) {
|
||||
this.selectionInfo = selectionInfo;
|
||||
this.threadIDs = threadIDs;
|
||||
}
|
||||
|
||||
MessagesChildNodeFactory() {
|
||||
this(null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the current instance of selectionInfo and calls the refresh method.
|
||||
*
|
||||
* @param selectionInfo New instance of the currently selected accounts
|
||||
* @param threadIDs A list of threadIDs to filter the keys by, null will
|
||||
* return all keys for the selected accounts.
|
||||
*/
|
||||
public void refresh(SelectionInfo selectionInfo) {
|
||||
public void refresh(SelectionInfo selectionInfo, List<String> threadIDs) {
|
||||
this.threadIDs = threadIDs;
|
||||
this.selectionInfo = selectionInfo;
|
||||
refresh(true);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a list of Keys (BlackboardArtifact) for only messages for the
|
||||
* currently selected accounts
|
||||
*
|
||||
* @param list List of BlackboardArtifact to populate
|
||||
*
|
||||
* @return True on success
|
||||
*/
|
||||
@Override
|
||||
protected boolean createKeys(List<BlackboardArtifact> list) {
|
||||
CommunicationsManager communicationManager;
|
||||
|
||||
try {
|
||||
communicationManager = Case.getCurrentCaseThrows().getSleuthkitCase().getCommunicationsManager();
|
||||
} catch (NoCurrentCaseException | TskCoreException ex) {
|
||||
@ -87,19 +86,37 @@ final class MessagesChildNodeFactory extends ChildFactory<BlackboardArtifact> {
|
||||
final Set<Content> relationshipSources;
|
||||
|
||||
try {
|
||||
relationshipSources = communicationManager.getRelationshipSources(selectionInfo.getAccountDevicesInstances(), selectionInfo.getCommunicationsFilter());
|
||||
|
||||
relationshipSources.stream().filter((content) -> (content instanceof BlackboardArtifact)).forEachOrdered((content) -> {
|
||||
relationshipSources = communicationManager.getRelationshipSources(selectionInfo.getAccountDevicesInstances(), selectionInfo.getCommunicationsFilter());
|
||||
for(Content content: relationshipSources) {
|
||||
if( !(content instanceof BlackboardArtifact)){
|
||||
continue;
|
||||
}
|
||||
|
||||
BlackboardArtifact bba = (BlackboardArtifact) content;
|
||||
BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(bba.getArtifactTypeID());
|
||||
|
||||
if (fromID == BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG
|
||||
|| fromID == BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG
|
||||
|| fromID == BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE) {
|
||||
if (fromID != BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG
|
||||
&& fromID != BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG
|
||||
&& fromID != BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// We want all artifacts that do not have "threadIDs" to appear as one thread in the UI
|
||||
// To achive this assign any artifact that does not have a threadID
|
||||
// the "UNTHREADED_ID"
|
||||
String artifactThreadID = MessageNode.UNTHREADED_ID;
|
||||
BlackboardAttribute attribute = bba.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_THREAD_ID));
|
||||
|
||||
if(attribute != null) {
|
||||
artifactThreadID = attribute.getValueString();
|
||||
}
|
||||
|
||||
if(threadIDs == null || threadIDs.contains(artifactThreadID)) {
|
||||
list.add(bba);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Failed to get relationship sources.", ex); //NON-NLS
|
||||
@ -110,6 +127,7 @@ final class MessagesChildNodeFactory extends ChildFactory<BlackboardArtifact> {
|
||||
|
||||
@Override
|
||||
protected Node createNodeForKey(BlackboardArtifact key) {
|
||||
return new MessageNode(key);
|
||||
return new MessageNode(key, null, null);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.4" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||
<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"/>
|
||||
@ -11,33 +11,23 @@
|
||||
<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"/>
|
||||
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,3,13,0,0,2,103"/>
|
||||
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,1,-112"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JSplitPane" name="splitPane">
|
||||
<Properties>
|
||||
<Property name="orientation" type="int" value="0"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="1.0"/>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
|
||||
<BorderConstraints direction="Center"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="org.sleuthkit.autopsy.contentviewers.MessageContentViewer" name="contentViewer">
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new MessageDataContent()"/>
|
||||
</AuxValues>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
||||
<JSplitPaneConstraints position="bottom"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel" name="outlineViewPanel">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
||||
@ -45,6 +35,16 @@
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="org.sleuthkit.autopsy.contentviewers.MessageContentViewer" name="messageContentViewer">
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new MessageDataContent()"/>
|
||||
</AuxValues>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
|
||||
<JSplitPaneConstraints position="right"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
@ -6,7 +6,7 @@
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obt ain a copy of the License at
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
@ -22,57 +22,38 @@ import java.awt.Component;
|
||||
import java.awt.KeyboardFocusManager;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import javax.swing.JPanel;
|
||||
import static javax.swing.SwingUtilities.isDescendingFrom;
|
||||
import org.netbeans.swing.outline.DefaultOutlineModel;
|
||||
import org.netbeans.swing.outline.Outline;
|
||||
import org.openide.explorer.ExplorerManager;
|
||||
import static org.openide.explorer.ExplorerUtils.createLookup;
|
||||
import org.openide.nodes.AbstractNode;
|
||||
import org.openide.nodes.ChildFactory;
|
||||
import org.openide.nodes.Children;
|
||||
import org.openide.nodes.Node;
|
||||
import org.openide.nodes.NodeAdapter;
|
||||
import org.openide.nodes.NodeMemberEvent;
|
||||
import org.openide.util.Lookup;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.openide.util.lookup.ServiceProvider;
|
||||
import org.sleuthkit.autopsy.communications.ModifiableProxyLookup;
|
||||
import org.sleuthkit.autopsy.corecomponents.TableFilterNode;
|
||||
import org.sleuthkit.autopsy.directorytree.DataResultFilterNode;
|
||||
|
||||
/**
|
||||
* Visualation for the messages of the currently selected accounts.
|
||||
*
|
||||
* General Purpose class for panels that need OutlineView of message nodes at
|
||||
* the top with a MessageContentViewer at the bottom.
|
||||
*/
|
||||
@ServiceProvider(service = RelationshipsViewer.class)
|
||||
public final class MessagesViewer extends JPanel implements RelationshipsViewer {
|
||||
public class MessagesPanel extends javax.swing.JPanel implements Lookup.Provider {
|
||||
|
||||
private final Outline outline;
|
||||
private final ModifiableProxyLookup proxyLookup;
|
||||
private final PropertyChangeListener focusPropertyListener;
|
||||
private final MessagesChildNodeFactory nodeFactory;
|
||||
|
||||
@Messages({
|
||||
"MessageViewer_tabTitle=Messages",
|
||||
"MessageViewer_columnHeader_From=From",
|
||||
"MessageViewer_columnHeader_To=To",
|
||||
"MessageViewer_columnHeader_Date=Date",
|
||||
"MessageViewer_columnHeader_Subject=Subject",
|
||||
"MessageViewer_columnHeader_Attms=Attachments",
|
||||
"MessageViewer_no_messages=<No messages found for selected account>"
|
||||
})
|
||||
|
||||
/**
|
||||
* Visualation for the messages of the currently selected accounts.
|
||||
* Creates new form MessagesPanel
|
||||
*/
|
||||
public MessagesViewer() {
|
||||
public MessagesPanel() {
|
||||
initComponents();
|
||||
|
||||
splitPane.setResizeWeight(0.5);
|
||||
|
||||
outlineViewPanel.hideOutlineView(Bundle.MessageViewer_no_messages());
|
||||
|
||||
proxyLookup = new ModifiableProxyLookup(createLookup(outlineViewPanel.getExplorerManager(), getActionMap()));
|
||||
nodeFactory = new MessagesChildNodeFactory(null);
|
||||
|
||||
// See org.sleuthkit.autopsy.timeline.TimeLineTopComponent for a detailed
|
||||
// explaination of focusPropertyListener
|
||||
@ -83,10 +64,10 @@ public final class MessagesViewer extends JPanel implements RelationshipsViewer
|
||||
if (newFocusOwner == null) {
|
||||
return;
|
||||
}
|
||||
if (isDescendingFrom(newFocusOwner, contentViewer)) {
|
||||
if (isDescendingFrom(newFocusOwner, messageContentViewer)) {
|
||||
//if the focus owner is within the MessageContentViewer (the attachments table)
|
||||
proxyLookup.setNewLookups(createLookup(((MessageDataContent) contentViewer).getExplorerManager(), getActionMap()));
|
||||
} else if (isDescendingFrom(newFocusOwner, MessagesViewer.this)) {
|
||||
proxyLookup.setNewLookups(createLookup(((MessageDataContent) messageContentViewer).getExplorerManager(), getActionMap()));
|
||||
} else if (isDescendingFrom(newFocusOwner, MessagesPanel.this)) {
|
||||
//... or if it is within the Results table.
|
||||
proxyLookup.setNewLookups(createLookup(outlineViewPanel.getExplorerManager(), getActionMap()));
|
||||
|
||||
@ -110,52 +91,22 @@ public final class MessagesViewer extends JPanel implements RelationshipsViewer
|
||||
final Node[] nodes = outlineViewPanel.getExplorerManager().getSelectedNodes();
|
||||
|
||||
if (nodes != null && nodes.length == 1) {
|
||||
contentViewer.setNode(nodes[0]);
|
||||
messageContentViewer.setNode(nodes[0]);
|
||||
}
|
||||
else {
|
||||
contentViewer.setNode(null);
|
||||
messageContentViewer.setNode(null);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
outlineViewPanel.getExplorerManager().setRootContext(
|
||||
new TableFilterNode(
|
||||
new DataResultFilterNode(
|
||||
new AbstractNode(
|
||||
Children.create(nodeFactory, true)),
|
||||
outlineViewPanel.getExplorerManager()),
|
||||
true));
|
||||
|
||||
// When a new set of nodes are added to the OutlineView the childrenAdded
|
||||
// seems to be fired before the childrenRemoved.
|
||||
outlineViewPanel.getExplorerManager().getRootContext().addNodeListener(new NodeAdapter() {
|
||||
@Override
|
||||
public void childrenAdded(NodeMemberEvent nme) {
|
||||
updateOutlineViewPanel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void childrenRemoved(NodeMemberEvent nme) {
|
||||
updateOutlineViewPanel();
|
||||
}
|
||||
});
|
||||
|
||||
splitPane.setResizeWeight(0.5);
|
||||
splitPane.setDividerLocation(0.5);
|
||||
outlineViewPanel.setTableColumnsWidth(5,10,10,15,50,10);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return Bundle.MessageViewer_tabTitle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JPanel getPanel() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelectionInfo(SelectionInfo info) {
|
||||
nodeFactory.refresh(info);
|
||||
public MessagesPanel(ChildFactory<?> nodeFactory) {
|
||||
this();
|
||||
setChildFactory(nodeFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -178,13 +129,13 @@ public final class MessagesViewer extends JPanel implements RelationshipsViewer
|
||||
.removePropertyChangeListener("focusOwner", focusPropertyListener);
|
||||
}
|
||||
|
||||
private void updateOutlineViewPanel() {
|
||||
int nodeCount = outlineViewPanel.getExplorerManager().getRootContext().getChildren().getNodesCount();
|
||||
if(nodeCount == 0) {
|
||||
outlineViewPanel.hideOutlineView(Bundle.MessageViewer_no_messages());
|
||||
} else {
|
||||
outlineViewPanel.showOutlineView();
|
||||
}
|
||||
final void setChildFactory(ChildFactory<?> nodeFactory) {
|
||||
outlineViewPanel.getExplorerManager().setRootContext(
|
||||
new TableFilterNode(
|
||||
new DataResultFilterNode(
|
||||
new AbstractNode(
|
||||
Children.create(nodeFactory, true)),
|
||||
outlineViewPanel.getExplorerManager()),true));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -195,31 +146,23 @@ public final class MessagesViewer extends JPanel implements RelationshipsViewer
|
||||
@SuppressWarnings("unchecked")
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
java.awt.GridBagConstraints gridBagConstraints;
|
||||
|
||||
splitPane = new javax.swing.JSplitPane();
|
||||
contentViewer = new MessageDataContent();
|
||||
outlineViewPanel = new org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel();
|
||||
messageContentViewer = new MessageDataContent();
|
||||
|
||||
setLayout(new java.awt.GridBagLayout());
|
||||
setLayout(new java.awt.BorderLayout());
|
||||
|
||||
splitPane.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
|
||||
splitPane.setBottomComponent(contentViewer);
|
||||
splitPane.setLeftComponent(outlineViewPanel);
|
||||
splitPane.setRightComponent(messageContentViewer);
|
||||
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.weighty = 1.0;
|
||||
add(splitPane, gridBagConstraints);
|
||||
add(splitPane, java.awt.BorderLayout.CENTER);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private org.sleuthkit.autopsy.contentviewers.MessageContentViewer contentViewer;
|
||||
private org.sleuthkit.autopsy.contentviewers.MessageContentViewer messageContentViewer;
|
||||
private org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel outlineViewPanel;
|
||||
private javax.swing.JSplitPane splitPane;
|
||||
// End of variables declaration//GEN-END:variables
|
@ -1,9 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||
<Properties>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||
@ -23,12 +20,6 @@
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="org.openide.explorer.view.OutlineView" name="outlineView">
|
||||
<Properties>
|
||||
<Property name="horizontalScrollBarPolicy" type="int" value="32"/>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[300, 400]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignCardLayout" value="org.netbeans.modules.form.compat2.layouts.DesignCardLayout$CardConstraintsDescription">
|
||||
<CardConstraints cardName="outlineCard"/>
|
||||
|
@ -101,6 +101,15 @@ public class OutlineViewPanel extends javax.swing.JPanel implements ExplorerMana
|
||||
outlineView.setEnabled(enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the width of the columns of the OutlineView based on the passed in
|
||||
* list of percentages. There should be on double value for each column
|
||||
* in the OutlineView.
|
||||
*
|
||||
* @param percentages A series of double percentages values representing
|
||||
* what percent of the total width of the table each
|
||||
* column should have.
|
||||
*/
|
||||
public void setTableColumnsWidth(double... percentages) {
|
||||
JTable table = outlineView.getOutline();
|
||||
double total = 0;
|
||||
@ -127,11 +136,7 @@ public class OutlineViewPanel extends javax.swing.JPanel implements ExplorerMana
|
||||
messagePanel = new javax.swing.JPanel();
|
||||
messageLabel = new javax.swing.JLabel();
|
||||
|
||||
setEnabled(false);
|
||||
setLayout(new java.awt.CardLayout(5, 5));
|
||||
|
||||
outlineView.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
|
||||
outlineView.setPreferredSize(new java.awt.Dimension(300, 400));
|
||||
add(outlineView, "outlineCard");
|
||||
|
||||
messagePanel.setLayout(new java.awt.BorderLayout());
|
||||
|
@ -11,7 +11,6 @@
|
||||
<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"/>
|
||||
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,1,-112"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
@ -22,7 +21,7 @@
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="1" insetsLeft="1" insetsBottom="1" insetsRight="1" anchor="18" weightX="1.0" weightY="1.0"/>
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
|
@ -31,7 +31,7 @@ public final class RelationshipBrowser extends JPanel implements Lookup.Provider
|
||||
|
||||
private SelectionInfo currentSelection;
|
||||
|
||||
private final MessagesViewer messagesViewer;
|
||||
private final MessageViewer messagesViewer;
|
||||
private final ContactsViewer contactsViewer;
|
||||
private final SummaryViewer summaryViewer;
|
||||
private final MediaViewer mediaViewer;
|
||||
@ -42,15 +42,14 @@ public final class RelationshipBrowser extends JPanel implements Lookup.Provider
|
||||
* Creates new form RelationshipBrowser
|
||||
*/
|
||||
public RelationshipBrowser() {
|
||||
messagesViewer = new MessagesViewer();
|
||||
initComponents();
|
||||
messagesViewer = new MessageViewer();
|
||||
contactsViewer = new ContactsViewer();
|
||||
summaryViewer = new SummaryViewer();
|
||||
mediaViewer = new MediaViewer();
|
||||
|
||||
proxyLookup = new ModifiableProxyLookup(messagesViewer.getLookup());
|
||||
|
||||
initComponents();
|
||||
|
||||
tabPane.add(summaryViewer.getDisplayName(), summaryViewer);
|
||||
tabPane.add(messagesViewer.getDisplayName(), messagesViewer);
|
||||
tabPane.add(contactsViewer.getDisplayName(), contactsViewer);
|
||||
@ -59,7 +58,7 @@ public final class RelationshipBrowser extends JPanel implements Lookup.Provider
|
||||
|
||||
/**
|
||||
* Sets the value of currentSelection and passes the SelectionInfo onto the
|
||||
* currently selected or visible tab.
|
||||
* currently selected\visible tab.
|
||||
*
|
||||
* @param info Currently selected account nodes
|
||||
*/
|
||||
@ -94,7 +93,6 @@ public final class RelationshipBrowser extends JPanel implements Lookup.Provider
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.weighty = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(1, 1, 1, 1);
|
||||
add(tabPane, gridBagConstraints);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
|
@ -0,0 +1,216 @@
|
||||
/*
|
||||
* 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.communications.relationships;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.Action;
|
||||
import org.openide.nodes.AbstractNode;
|
||||
import org.openide.nodes.ChildFactory;
|
||||
import org.openide.nodes.Children;
|
||||
import org.openide.nodes.Node;
|
||||
import org.openide.nodes.Sheet;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.datamodel.NodeProperty;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.CommunicationsManager;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
* ChildFactory that creates createKeys and nodes from a given selectionInfo for
|
||||
* only emails, call logs and messages.
|
||||
*
|
||||
*/
|
||||
final class ThreadChildNodeFactory extends ChildFactory<BlackboardArtifact> {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(ThreadChildNodeFactory.class.getName());
|
||||
|
||||
private SelectionInfo selectionInfo;
|
||||
|
||||
private final Action preferredAction;
|
||||
|
||||
/**
|
||||
* Construct a new ThreadChildNodeFactory from the currently selectionInfo
|
||||
*
|
||||
* @param preferredAction SelectionInfo object for the currently selected
|
||||
* accounts
|
||||
*/
|
||||
|
||||
ThreadChildNodeFactory(Action preferredAction) {
|
||||
this.preferredAction = preferredAction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the current instance of selectionInfo and calls the refresh method.
|
||||
*
|
||||
* @param selectionInfo New instance of the currently selected accounts
|
||||
*/
|
||||
public void refresh(SelectionInfo selectionInfo) {
|
||||
this.selectionInfo = selectionInfo;
|
||||
refresh(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a list of Keys (BlackboardArtifact) for only messages for the
|
||||
* currently selected accounts.
|
||||
*
|
||||
* @param list List of BlackboardArtifact to populate
|
||||
*
|
||||
* @return True on success
|
||||
*/
|
||||
@Override
|
||||
protected boolean createKeys(List<BlackboardArtifact> list) {
|
||||
CommunicationsManager communicationManager;
|
||||
try {
|
||||
communicationManager = Case.getCurrentCaseThrows().getSleuthkitCase().getCommunicationsManager();
|
||||
} catch (NoCurrentCaseException | TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Failed to get communications manager from case.", ex); //NON-NLS
|
||||
return false;
|
||||
}
|
||||
|
||||
if(selectionInfo == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final Set<Content> relationshipSources;
|
||||
|
||||
try {
|
||||
relationshipSources = communicationManager.getRelationshipSources(selectionInfo.getAccountDevicesInstances(), selectionInfo.getCommunicationsFilter());
|
||||
|
||||
createRootMessageKeys(list, relationshipSources) ;
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Failed to get relationship sources.", ex); //NON-NLS
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds only BlackboardArtifact objects to the list where are the earliest
|
||||
* message in a message thread (based on threadID). If there are "unthreaded"
|
||||
* messages (messages that do not have a threadID) one representitive artifact
|
||||
* will be added to the list and dealt with a node creation time.
|
||||
*
|
||||
* @param list List to populate with BlackboardArtifact keys
|
||||
* @param relationshipSources Set of Content objects
|
||||
* @return True on success
|
||||
* @throws TskCoreException
|
||||
*/
|
||||
private boolean createRootMessageKeys(List<BlackboardArtifact> list, Set<Content> relationshipSources) throws TskCoreException{
|
||||
Map<String, BlackboardArtifact> rootMessageMap = new HashMap<>();
|
||||
for(Content content: relationshipSources) {
|
||||
if(!(content instanceof BlackboardArtifact)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BlackboardArtifact bba = (BlackboardArtifact) content;
|
||||
BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(bba.getArtifactTypeID());
|
||||
|
||||
if (fromID == BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG
|
||||
|| fromID == BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG
|
||||
|| fromID == BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE) {
|
||||
|
||||
// We want all artifacts that do not have "threadIDs" to appear as one thread in the UI
|
||||
// To achive this assign any artifact that does not have a threadID
|
||||
// the "UNTHREADED_ID"
|
||||
String threadID = MessageNode.UNTHREADED_ID;
|
||||
BlackboardAttribute attribute = bba.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_THREAD_ID));
|
||||
|
||||
if(attribute != null) {
|
||||
threadID = attribute.getValueString();
|
||||
}
|
||||
|
||||
BlackboardArtifact tableArtifact = rootMessageMap.get(threadID);
|
||||
if(tableArtifact == null) {
|
||||
rootMessageMap.put(threadID, bba);
|
||||
} else {
|
||||
// Get the date of the message
|
||||
BlackboardAttribute tableAttribute = tableArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_SENT));
|
||||
attribute = bba.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_SENT));
|
||||
|
||||
// put the earliest message into the table
|
||||
if(tableAttribute != null
|
||||
&& attribute != null
|
||||
&& tableAttribute.getValueLong() > attribute.getValueLong()) {
|
||||
rootMessageMap.put(threadID, bba);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(BlackboardArtifact bba: rootMessageMap.values()) {
|
||||
list.add(bba);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node createNodeForKey(BlackboardArtifact bba) {
|
||||
BlackboardAttribute attribute = null;
|
||||
try {
|
||||
attribute = bba.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_THREAD_ID));
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, String.format("Unable to get threadID for artifact: %s", bba.getName()), ex);
|
||||
}
|
||||
|
||||
if (attribute != null) {
|
||||
return new ThreadNode(bba, attribute.getValueString(), preferredAction);
|
||||
} else {
|
||||
// Only one of these should occur.
|
||||
return new UnthreadedNode();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An this node represents the "unthreaded" thread.
|
||||
*/
|
||||
final class UnthreadedNode extends AbstractNode {
|
||||
/**
|
||||
* Construct an instance of UnthreadNode.
|
||||
*/
|
||||
UnthreadedNode() {
|
||||
super(Children.LEAF);
|
||||
setDisplayName("Unthreaded");
|
||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/communications/images/unthreaded.png" );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Sheet createSheet() {
|
||||
Sheet sheet = super.createSheet();
|
||||
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
|
||||
if (sheetSet == null) {
|
||||
sheetSet = Sheet.createPropertiesSet();
|
||||
sheet.put(sheetSet);
|
||||
}
|
||||
|
||||
// Give this node a threadID of "UNTHEADED_ID"
|
||||
sheetSet.put(new NodeProperty<>("ThreadID", "ThreadID","",MessageNode.UNTHREADED_ID));
|
||||
|
||||
return sheet;
|
||||
}
|
||||
}
|
||||
}
|
60
Core/src/org/sleuthkit/autopsy/communications/relationships/ThreadNode.java
Executable file
60
Core/src/org/sleuthkit/autopsy/communications/relationships/ThreadNode.java
Executable file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.communications.relationships;
|
||||
|
||||
import javax.swing.Action;
|
||||
import org.openide.nodes.AbstractNode;
|
||||
import org.openide.nodes.Children;
|
||||
import org.openide.nodes.Sheet;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
|
||||
/**
|
||||
* An AbstractNode subclass which wraps a MessagNode object. Doing this allows
|
||||
* for the reuse of the createSheet and other function from MessageNode, but
|
||||
* also some customizing of how a ThreadNode is shown.
|
||||
*/
|
||||
final class ThreadNode extends AbstractNode{
|
||||
|
||||
final private MessageNode messageNode;
|
||||
|
||||
ThreadNode(BlackboardArtifact artifact, String threadID, Action preferredAction) {
|
||||
super(Children.LEAF);
|
||||
messageNode = new MessageNode(artifact, threadID, preferredAction);
|
||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/communications/images/threaded.png" );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Sheet createSheet() {
|
||||
return messageNode.createSheet();
|
||||
}
|
||||
|
||||
String getThreadID() {
|
||||
return messageNode.getThreadID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Action getPreferredAction() {
|
||||
return messageNode.getPreferredAction();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return messageNode.getDisplayName();
|
||||
}
|
||||
}
|
@ -302,6 +302,8 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
try {
|
||||
if (rootNode != null) {
|
||||
this.rootNode = rootNode;
|
||||
|
||||
/**
|
||||
* Check to see if we have previously created a paging support
|
||||
* class for this node.
|
||||
@ -364,8 +366,6 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
* case database round trips.
|
||||
*/
|
||||
if (rootNode != null && rootNode.getChildren().getNodesCount() > 0) {
|
||||
this.rootNode = rootNode;
|
||||
|
||||
this.getExplorerManager().setRootContext(this.rootNode);
|
||||
setupTable();
|
||||
} else {
|
||||
|
@ -490,6 +490,12 @@ public class DataResultFilterNode extends FilterNode {
|
||||
|
||||
@Override
|
||||
public AbstractAction visit(BlackboardArtifactNode ban) {
|
||||
|
||||
Action preferredAction = ban.getPreferredAction();
|
||||
if(preferredAction instanceof AbstractAction) {
|
||||
return (AbstractAction) preferredAction;
|
||||
}
|
||||
|
||||
BlackboardArtifact artifact = ban.getArtifact();
|
||||
try {
|
||||
if ((artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID())
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2014-2018 Basis Technology Corp.
|
||||
* Copyright 2014-2019 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -286,7 +286,7 @@ public final class DataSourceIngestJob {
|
||||
this.addIngestModules(fileIngestModuleTemplates, IngestModuleType.FILE_LEVEL, skCase);
|
||||
this.addIngestModules(secondStageDataSourceModuleTemplates, IngestModuleType.DATA_SOURCE_LEVEL, skCase);
|
||||
} catch (TskCoreException | NoCurrentCaseException ex) {
|
||||
logger.log(Level.SEVERE, "Failed to add ingest modules to database.", ex);
|
||||
logErrorMessage(Level.WARNING, "Failed to add ingest modules listing to case database", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@ -421,13 +421,13 @@ public final class DataSourceIngestJob {
|
||||
try {
|
||||
this.ingestJob = Case.getCurrentCaseThrows().getSleuthkitCase().addIngestJob(dataSource, NetworkUtils.getLocalHostName(), ingestModules, new Date(this.createTime), new Date(0), IngestJobStatusType.STARTED, "");
|
||||
} catch (TskCoreException | NoCurrentCaseException ex) {
|
||||
logger.log(Level.SEVERE, "Failed to add ingest job to database.", ex);
|
||||
logErrorMessage(Level.WARNING, "Failed to add ingest job info to case database", ex); //NON-NLS
|
||||
}
|
||||
if (this.hasFirstStageDataSourceIngestPipeline() || this.hasFileIngestPipeline()) {
|
||||
logger.log(Level.INFO, "Starting first stage analysis for {0} (jobId={1})", new Object[]{dataSource.getName(), this.id}); //NON-NLS
|
||||
logInfoMessage("Starting first stage analysis"); //NON-NLS
|
||||
this.startFirstStage();
|
||||
} else if (this.hasSecondStageDataSourceIngestPipeline()) {
|
||||
logger.log(Level.INFO, "Starting second stage analysis for {0} (jobId={1}), no first stage configured", new Object[]{dataSource.getName(), this.id}); //NON-NLS
|
||||
logInfoMessage("Starting second stage analysis"); //NON-NLS
|
||||
this.startSecondStage();
|
||||
}
|
||||
}
|
||||
@ -521,13 +521,13 @@ public final class DataSourceIngestJob {
|
||||
* Schedule the first stage tasks.
|
||||
*/
|
||||
if (this.hasFirstStageDataSourceIngestPipeline() && this.hasFileIngestPipeline()) {
|
||||
logger.log(Level.INFO, "Scheduling first stage data source and file level analysis tasks for {0} (jobId={1})", new Object[]{dataSource.getName(), this.id}); //NON-NLS
|
||||
logInfoMessage("Scheduling first stage data source and file level analysis tasks"); //NON-NLS
|
||||
DataSourceIngestJob.taskScheduler.scheduleIngestTasks(this);
|
||||
} else if (this.hasFirstStageDataSourceIngestPipeline()) {
|
||||
logger.log(Level.INFO, "Scheduling first stage data source level analysis tasks for {0} (jobId={1}), no file level analysis configured", new Object[]{dataSource.getName(), this.id}); //NON-NLS
|
||||
logInfoMessage("Scheduling first stage data source level analysis tasks"); //NON-NLS
|
||||
DataSourceIngestJob.taskScheduler.scheduleDataSourceIngestTask(this);
|
||||
} else {
|
||||
logger.log(Level.INFO, "Scheduling file level analysis tasks for {0} (jobId={1}), no first stage data source level analysis configured", new Object[]{dataSource.getName(), this.id}); //NON-NLS
|
||||
logInfoMessage("Scheduling file level analysis tasks, no first stage data source level analysis configured"); //NON-NLS
|
||||
DataSourceIngestJob.taskScheduler.scheduleFileIngestTasks(this, this.files);
|
||||
|
||||
/**
|
||||
@ -546,7 +546,7 @@ public final class DataSourceIngestJob {
|
||||
* Starts the second stage of this ingest job.
|
||||
*/
|
||||
private void startSecondStage() {
|
||||
logger.log(Level.INFO, "Starting second stage analysis for {0} (jobId={1})", new Object[]{dataSource.getName(), this.id}); //NON-NLS
|
||||
logInfoMessage("Starting second stage analysis"); //NON-NLS
|
||||
this.stage = DataSourceIngestJob.Stages.SECOND;
|
||||
if (this.doUI) {
|
||||
this.startDataSourceIngestProgressBar();
|
||||
@ -554,7 +554,7 @@ public final class DataSourceIngestJob {
|
||||
synchronized (this.dataSourceIngestPipelineLock) {
|
||||
this.currentDataSourceIngestPipeline = this.secondStageDataSourceIngestPipeline;
|
||||
}
|
||||
logger.log(Level.INFO, "Scheduling second stage data source level analysis tasks for {0} (jobId={1})", new Object[]{dataSource.getName(), this.id}); //NON-NLS
|
||||
logInfoMessage("Scheduling second stage data source level analysis tasks"); //NON-NLS
|
||||
DataSourceIngestJob.taskScheduler.scheduleDataSourceIngestTask(this);
|
||||
}
|
||||
|
||||
@ -643,7 +643,7 @@ public final class DataSourceIngestJob {
|
||||
* job and starts the second stage, if appropriate.
|
||||
*/
|
||||
private void finishFirstStage() {
|
||||
logger.log(Level.INFO, "Finished first stage analysis for {0} (jobId={1})", new Object[]{dataSource.getName(), this.id}); //NON-NLS
|
||||
logInfoMessage("Finished first stage analysis"); //NON-NLS
|
||||
|
||||
// Shut down the file ingest pipelines. Note that no shut down is
|
||||
// required for the data source ingest pipeline because data source
|
||||
@ -693,7 +693,7 @@ public final class DataSourceIngestJob {
|
||||
* Shuts down the ingest pipelines and progress bars for this job.
|
||||
*/
|
||||
private void finish() {
|
||||
logger.log(Level.INFO, "Finished analysis for {0} (jobId={1})", new Object[]{dataSource.getName(), this.id}); //NON-NLS
|
||||
logInfoMessage("Finished analysis"); //NON-NLS
|
||||
this.stage = DataSourceIngestJob.Stages.FINALIZATION;
|
||||
|
||||
if (this.doUI) {
|
||||
@ -711,19 +711,19 @@ public final class DataSourceIngestJob {
|
||||
try {
|
||||
ingestJob.setIngestJobStatus(IngestJobStatusType.CANCELLED);
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Failed to set ingest status for ingest job in database.", ex);
|
||||
logErrorMessage(Level.WARNING, "Failed to update ingest job status in case database", ex);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
ingestJob.setIngestJobStatus(IngestJobStatusType.COMPLETED);
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Failed to set ingest status for ingest job in database.", ex);
|
||||
logErrorMessage(Level.WARNING, "Failed to update ingest job status in case database", ex);
|
||||
}
|
||||
}
|
||||
try {
|
||||
this.ingestJob.setEndDateTime(new Date());
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Failed to set end date for ingest job in database.", ex);
|
||||
logErrorMessage(Level.WARNING, "Failed to set job end date in case database", ex);
|
||||
}
|
||||
}
|
||||
this.parentJob.dataSourceJobFinished(this);
|
||||
@ -842,7 +842,7 @@ public final class DataSourceIngestJob {
|
||||
if (DataSourceIngestJob.Stages.FIRST == this.stage) {
|
||||
DataSourceIngestJob.taskScheduler.fastTrackFileIngestTasks(this, files);
|
||||
} else {
|
||||
DataSourceIngestJob.logger.log(Level.SEVERE, "Adding files during second stage not supported"); //NON-NLS
|
||||
logErrorMessage(Level.SEVERE, "Adding files to job during second stage analysis not supported");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1066,6 +1066,39 @@ public final class DataSourceIngestJob {
|
||||
return this.cancellationReason;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes an info message to the application log that includes the data
|
||||
* source name, data source object id, and the job id.
|
||||
*
|
||||
* @param message The message.
|
||||
*/
|
||||
private void logInfoMessage(String message) {
|
||||
logger.log(Level.INFO, String.format("%s (data source = %s, objId = %d, jobId = %d)", message, dataSource.getName(), dataSource.getId(), id)); //NON-NLS
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes an error message to the application log that includes the data
|
||||
* source name, data source object id, and the job id.
|
||||
*
|
||||
* @param level The logging level for the message.
|
||||
* @param message The message.
|
||||
* @param throwable The throwable associated with the error.
|
||||
*/
|
||||
private void logErrorMessage(Level level, String message, Throwable throwable) {
|
||||
logger.log(level, String.format("%s (data source = %s, objId = %d, jobId = %d)", message, dataSource.getName(), dataSource.getId(), id), throwable); //NON-NLS
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes an error message to the application log that includes the data
|
||||
* source name, data source object id, and the job id.
|
||||
*
|
||||
* @param level The logging level for the message.
|
||||
* @param message The message.
|
||||
*/
|
||||
private void logErrorMessage(Level level, String message) {
|
||||
logger.log(level, String.format("%s (data source = %s, objId = %d, jobId = %d)", message, dataSource.getName(), dataSource.getId(), id)); //NON-NLS
|
||||
}
|
||||
|
||||
/**
|
||||
* Write ingest module errors to the log.
|
||||
*
|
||||
@ -1073,7 +1106,7 @@ public final class DataSourceIngestJob {
|
||||
*/
|
||||
private void logIngestModuleErrors(List<IngestModuleError> errors) {
|
||||
for (IngestModuleError error : errors) {
|
||||
DataSourceIngestJob.logger.log(Level.SEVERE, String.format("%s experienced an error analyzing %s (jobId=%d)", error.getModuleDisplayName(), dataSource.getName(), this.id), error.getThrowable()); //NON-NLS
|
||||
logErrorMessage(Level.SEVERE, String.format("%s experienced an error during analysis", error.getModuleDisplayName()), error.getThrowable()); //NON-NLS
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2012-2018 Basis Technology Corp.
|
||||
* Copyright 2012-2019 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -403,10 +403,10 @@ public class IngestManager implements IngestProgressSnapshotProvider {
|
||||
synchronized (ingestJobsById) {
|
||||
ingestJobsById.put(job.getId(), job);
|
||||
}
|
||||
IngestManager.logger.log(Level.INFO, "Starting ingest job {0}", job.getId()); //NON-NLS
|
||||
errors = job.start();
|
||||
if (errors.isEmpty()) {
|
||||
this.fireIngestJobStarted(job.getId());
|
||||
IngestManager.logger.log(Level.INFO, "Ingest job {0} started", job.getId()); //NON-NLS
|
||||
} else {
|
||||
synchronized (ingestJobsById) {
|
||||
this.ingestJobsById.remove(job.getId());
|
||||
|
@ -41,6 +41,9 @@ public final class OpenCvLoader {
|
||||
* Return whether or not the OpenCV library has been loaded.
|
||||
*
|
||||
* @return - true if the opencv library is loaded or false if it is not
|
||||
* @throws UnsatisfiedLinkError - A COPY of the exception that prevented OpenCV from loading.
|
||||
* Note that the stack trace in the exception can be confusing because it refers to a
|
||||
* past invocation.
|
||||
*/
|
||||
public static boolean isOpenCvLoaded() throws UnsatisfiedLinkError {
|
||||
if (!OPEN_CV_LOADED) {
|
||||
|
@ -99,13 +99,14 @@ class TextMessageAnalyzer(general.AndroidComponentAnalyzer):
|
||||
resultSet = None
|
||||
try:
|
||||
resultSet = statement.executeQuery(
|
||||
"SELECT address, date, read, type, subject, body FROM sms;")
|
||||
"SELECT address, date, read, type, subject, body, thread_id FROM sms;")
|
||||
while resultSet.next():
|
||||
address = resultSet.getString("address") # may be phone number, or other addresses
|
||||
date = Long.valueOf(resultSet.getString("date")) / 1000
|
||||
read = resultSet.getInt("read") # may be unread = 0, read = 1
|
||||
subject = resultSet.getString("subject") # message subject
|
||||
body = resultSet.getString("body") # message body
|
||||
thread_id = "{0}_{1}".format(abstractFile.getId(), resultSet.getInt("thread_id"))
|
||||
attributes = ArrayList()
|
||||
artifact = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE); #create Message artifact and then add attributes from result set.
|
||||
if resultSet.getString("type") == "1":
|
||||
@ -119,6 +120,7 @@ class TextMessageAnalyzer(general.AndroidComponentAnalyzer):
|
||||
attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SUBJECT, general.MODULE_NAME, subject))
|
||||
attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT, general.MODULE_NAME, body))
|
||||
attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE, general.MODULE_NAME, "SMS Message"))
|
||||
attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_THREAD_ID, general.MODULE_NAME, thread_id))
|
||||
|
||||
artifact.addAttributes(attributes)
|
||||
|
||||
|
@ -1,3 +1,3 @@
|
||||
<project name="TSK_VERSION">
|
||||
<property name="TSK_VERSION" value="4.6.6"/>
|
||||
<property name="TSK_VERSION" value="4.6.7"/>
|
||||
</project>
|
||||
|
@ -38,7 +38,7 @@ PROJECT_NAME = "Autopsy User Documentation"
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
# control system is used.
|
||||
|
||||
PROJECT_NUMBER = 4.11.0
|
||||
PROJECT_NUMBER = 4.12.0
|
||||
|
||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||
# for a project that appears at the top of each page and should give viewer a
|
||||
@ -1025,7 +1025,7 @@ GENERATE_HTML = YES
|
||||
# The default directory is: html.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_OUTPUT = 4.11.0
|
||||
HTML_OUTPUT = 4.12.0
|
||||
|
||||
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
|
||||
# generated HTML page (for example: .htm, .php, .asp).
|
||||
|
@ -38,7 +38,7 @@ PROJECT_NAME = "Autopsy"
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
# control system is used.
|
||||
|
||||
PROJECT_NUMBER = 4.11.0
|
||||
PROJECT_NUMBER = 4.12.0
|
||||
|
||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||
# for a project that appears a the top of each page and should give viewer a
|
||||
@ -1063,7 +1063,7 @@ GENERATE_HTML = YES
|
||||
# The default directory is: html.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_OUTPUT = api-docs/4.11.0/
|
||||
HTML_OUTPUT = api-docs/4.12.0/
|
||||
|
||||
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
|
||||
# generated HTML page (for example: .htm, .php, .asp).
|
||||
|
@ -4,10 +4,10 @@ app.title=Autopsy
|
||||
### lowercase version of above
|
||||
app.name=${branding.token}
|
||||
### if left unset, version will default to today's date
|
||||
app.version=4.11.0
|
||||
app.version=4.12.0
|
||||
### build.type must be one of: DEVELOPMENT, RELEASE
|
||||
#build.type=RELEASE
|
||||
build.type=DEVELOPMENT
|
||||
build.type=RELEASE
|
||||
#build.type=DEVELOPMENT
|
||||
|
||||
project.org.netbeans.progress=org-netbeans-api-progress
|
||||
project.org.sleuthkit.autopsy.experimental=Experimental
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
# NOTE: update_sleuthkit_version.pl updates this value and relies
|
||||
# on it keeping the same name and whitespace. Don't change it.
|
||||
TSK_VERSION=4.6.6
|
||||
TSK_VERSION=4.6.7
|
||||
|
||||
|
||||
# In the beginning...
|
||||
|
Loading…
x
Reference in New Issue
Block a user