mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-17 10:17:41 +00:00
Merge branch 'cvt-contacts-view' of https://github.com/sleuthkit/autopsy into cvt-contacts-view
This commit is contained in:
commit
18e8b1e90a
@ -20,7 +20,6 @@ package org.sleuthkit.autopsy.communications;
|
||||
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import java.awt.Component;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
@ -36,11 +35,11 @@ import org.openide.nodes.AbstractNode;
|
||||
import org.openide.nodes.Children;
|
||||
import org.openide.nodes.Node;
|
||||
import org.openide.util.Lookup;
|
||||
import org.openide.util.lookup.ProxyLookup;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.datamodel.AccountDeviceInstance;
|
||||
import org.sleuthkit.datamodel.CommunicationsFilter;
|
||||
import org.sleuthkit.datamodel.CommunicationsManager;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
@ -70,7 +69,7 @@ public final class AccountsBrowser extends JPanel implements ExplorerManager.Pro
|
||||
* This lookup proxies the selection lookup of both he accounts table and
|
||||
* the messages table.
|
||||
*/
|
||||
private final ProxyLookup proxyLookup;
|
||||
private final Lookup lookup;
|
||||
|
||||
public AccountsBrowser() {
|
||||
initComponents();
|
||||
@ -95,16 +94,19 @@ public final class AccountsBrowser extends JPanel implements ExplorerManager.Pro
|
||||
} else if (ExplorerManager.PROP_EXPLORED_CONTEXT.equals(evt.getPropertyName())) {
|
||||
SwingUtilities.invokeLater(this::setColumnWidths);
|
||||
} else if (evt.getPropertyName().equals(ExplorerManager.PROP_SELECTED_NODES)) {
|
||||
relationshipBrowser.setSelectionInfo(new SelectionInfo());
|
||||
final Node[] selectedNodes = accountsTableEM.getSelectedNodes();
|
||||
final Set<AccountDeviceInstance> accountDeviceInstances = new HashSet<>();
|
||||
|
||||
CommunicationsFilter filter = null;
|
||||
for (final Node node : selectedNodes) {
|
||||
accountDeviceInstances.add(((AccountDeviceInstanceNode) node).getAccountDeviceInstance());
|
||||
filter = ((AccountDeviceInstanceNode)node).getFilter();
|
||||
}
|
||||
relationshipBrowser.setSelectionInfo(new SelectionInfo(accountDeviceInstances, filter));
|
||||
}
|
||||
});
|
||||
final MessageBrowser messageBrowser = new MessageBrowser(accountsTableEM, messageBrowserEM);
|
||||
|
||||
// jSplitPane1.setRightComponent(messageBrowser);
|
||||
|
||||
proxyLookup = new ProxyLookup(
|
||||
messageBrowser.getLookup(),
|
||||
ExplorerUtils.createLookup(accountsTableEM, getActionMap()));
|
||||
lookup = ExplorerUtils.createLookup(accountsTableEM, getActionMap());
|
||||
}
|
||||
|
||||
private void setColumnWidths() {
|
||||
@ -176,6 +178,6 @@ public final class AccountsBrowser extends JPanel implements ExplorerManager.Pro
|
||||
|
||||
@Override
|
||||
public Lookup getLookup() {
|
||||
return proxyLookup;
|
||||
return lookup;
|
||||
}
|
||||
}
|
||||
|
@ -39,5 +39,4 @@ VisualizationPanel.fastOrganicLayoutButton.text=Fast Organic
|
||||
VisualizationPanel.hierarchyLayoutButton.text=Hierarchical
|
||||
VisualizationPanel.clearVizButton.text_1=Clear Viz.
|
||||
VisualizationPanel.snapshotButton.text_1=Snapshot Report
|
||||
ContactsViewer.testLabel.text=No Value Set
|
||||
MessagesViewer.testLabel.text=No Value Set
|
||||
ContactDetailsPane.nameLabel.text=jLabel1
|
||||
|
@ -3,6 +3,17 @@ AccountNode.accountType=Type
|
||||
AccountNode.device=Device
|
||||
AccountNode.messageCount=Msgs
|
||||
applyText=Apply
|
||||
ContactNode_Email=Email Address
|
||||
ContactNode_Home_Number=Home Number
|
||||
ContactNode_Mobile_Number=Mobile Number
|
||||
ContactNode_Name=Name
|
||||
ContactNode_Office_Number=Office Number
|
||||
ContactNode_Phone=Phone Number
|
||||
ContactNode_URL=URL
|
||||
ContactsViewer_columnHeader_Email=Email
|
||||
ContactsViewer_columnHeader_Name=Name
|
||||
ContactsViewer_columnHeader_Phone=Phone
|
||||
ContactsViewer_tabTitle=Contacts
|
||||
CTL_OpenCVTAction=Communications
|
||||
CVTTopComponent.name=\ Communications Visualization
|
||||
CVTTopComponent.TabConstraints.tabTitle=Visualize
|
||||
@ -22,7 +33,18 @@ FiltersPanel.refreshButton.text=Refresh
|
||||
FiltersPanel.deviceRequiredLabel.text=Select at least one.
|
||||
FiltersPanel.accountTypeRequiredLabel.text=Select at least one.
|
||||
FiltersPanel.needsRefreshLabel.text=Displayed data is out of date. Press Refresh.
|
||||
MessageBrowser.DataResultViewerTable.title=Messages
|
||||
MessageNode_Node_Property_Attms=Attachments
|
||||
MessageNode_Node_Property_Date=Date
|
||||
MessageNode_Node_Property_From=From
|
||||
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_From=From
|
||||
MessageViewer_columnHeader_Subject=Subject
|
||||
MessageViewer_columnHeader_To=To
|
||||
MessageViewer_tabTitle=Messages
|
||||
OpenCVTAction.displayName=Communications
|
||||
PinAccountsAction.pluralText=Add Selected Accounts to Visualization
|
||||
PinAccountsAction.singularText=Add Selected Account to Visualization
|
||||
@ -83,8 +105,7 @@ VisualizationPanel.fastOrganicLayoutButton.text=Fast Organic
|
||||
VisualizationPanel.hierarchyLayoutButton.text=Hierarchical
|
||||
VisualizationPanel.clearVizButton.text_1=Clear Viz.
|
||||
VisualizationPanel.snapshotButton.text_1=Snapshot Report
|
||||
ContactsViewer.testLabel.text=No Value Set
|
||||
MessagesViewer.testLabel.text=No Value Set
|
||||
ContactDetailsPane.nameLabel.text=jLabel1
|
||||
VisualizationPanel_action_dialogs_title=Communications
|
||||
VisualizationPanel_action_name_text=Snapshot Report
|
||||
VisualizationPanel_module_name=Communications
|
||||
|
61
Core/src/org/sleuthkit/autopsy/communications/ContactDetailsPane.form
Executable file
61
Core/src/org/sleuthkit/autopsy/communications/ContactDetailsPane.form
Executable file
@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<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>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="nameLabel">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Tahoma" size="24" style="0"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="ContactDetailsPane.nameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="org.openide.explorer.propertysheet.PropertySheet" name="propertySheet">
|
||||
<Properties>
|
||||
<Property name="descriptionAreaVisible" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
112
Core/src/org/sleuthkit/autopsy/communications/ContactDetailsPane.java
Executable file
112
Core/src/org/sleuthkit/autopsy/communications/ContactDetailsPane.java
Executable file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import org.openide.explorer.ExplorerManager;
|
||||
import org.openide.nodes.Node;
|
||||
|
||||
/**
|
||||
* Displays the propertied of a ContactNode in a PropertySheet.
|
||||
*/
|
||||
public final class ContactDetailsPane extends javax.swing.JPanel implements ExplorerManager.Provider {
|
||||
|
||||
final private ExplorerManager explorerManager = new ExplorerManager();
|
||||
|
||||
/**
|
||||
* Displays the propertied of a ContactNode in a PropertySheet.
|
||||
*/
|
||||
public ContactDetailsPane() {
|
||||
initComponents();
|
||||
this.setEnabled(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the list of nodes for the property sheet.
|
||||
*
|
||||
* @param nodes List of nodes to set
|
||||
*/
|
||||
public void setNode(Node[] nodes) {
|
||||
if (nodes != null) {
|
||||
nameLabel.setText(nodes[0].getDisplayName());
|
||||
} else {
|
||||
nameLabel.setText("");
|
||||
}
|
||||
|
||||
propertySheet.setNodes(nodes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExplorerManager getExplorerManager() {
|
||||
return explorerManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnabled(boolean enabled) {
|
||||
super.setEnabled(enabled);
|
||||
nameLabel.setEnabled(enabled);
|
||||
propertySheet.setEnabled(enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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() {
|
||||
|
||||
nameLabel = new javax.swing.JLabel();
|
||||
propertySheet = new org.openide.explorer.propertysheet.PropertySheet();
|
||||
|
||||
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
|
||||
|
||||
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())
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JLabel nameLabel;
|
||||
private org.openide.explorer.propertysheet.PropertySheet propertySheet;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
}
|
123
Core/src/org/sleuthkit/autopsy/communications/ContactNode.java
Executable file
123
Core/src/org/sleuthkit/autopsy/communications/ContactNode.java
Executable file
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.TimeZone;
|
||||
import java.util.logging.Level;
|
||||
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 static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL;
|
||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME;
|
||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER;
|
||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_HOME;
|
||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_MOBILE;
|
||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_OFFICE;
|
||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL;
|
||||
import static org.sleuthkit.datamodel.BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME;
|
||||
import org.sleuthkit.datamodel.TimeUtilities;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
* Extends BlackboardArtifactNode to override createSheet to create a contact
|
||||
* artifact specific sheet.
|
||||
*/
|
||||
final class ContactNode extends BlackboardArtifactNode {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(RelationshipNode.class.getName());
|
||||
|
||||
@Messages({
|
||||
"ContactNode_Name=Name",
|
||||
"ContactNode_Phone=Phone Number",
|
||||
"ContactNode_Email=Email Address",
|
||||
"ContactNode_Mobile_Number=Mobile Number",
|
||||
"ContactNode_Office_Number=Office Number",
|
||||
"ContactNode_URL=URL",
|
||||
"ContactNode_Home_Number=Home Number",})
|
||||
|
||||
ContactNode(BlackboardArtifact artifact) {
|
||||
super(artifact);
|
||||
|
||||
setDisplayName(getAttributeDisplayString(artifact, TSK_NAME));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Sheet createSheet() {
|
||||
final BlackboardArtifact artifact = getArtifact();
|
||||
BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(artifact.getArtifactTypeID());
|
||||
if (fromID != TSK_CONTACT) {
|
||||
return super.createSheet();
|
||||
}
|
||||
|
||||
Sheet sheet = new Sheet();
|
||||
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
|
||||
if (sheetSet == null) {
|
||||
sheetSet = Sheet.createPropertiesSet();
|
||||
sheet.put(sheetSet);
|
||||
}
|
||||
|
||||
sheetSet.put(new NodeProperty<>("email", Bundle.ContactNode_Email(), "",
|
||||
getAttributeDisplayString(artifact, TSK_EMAIL))); //NON-NLS
|
||||
sheetSet.put(new NodeProperty<>("phone", Bundle.ContactNode_Phone(), "",
|
||||
getAttributeDisplayString(artifact, TSK_PHONE_NUMBER))); //NON-NLS
|
||||
sheetSet.put(new NodeProperty<>("mobile", Bundle.ContactNode_Mobile_Number(), "",
|
||||
getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_MOBILE))); //NON-NLS
|
||||
sheetSet.put(new NodeProperty<>("home", Bundle.ContactNode_Home_Number(), "",
|
||||
getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_HOME))); //NON-NLS
|
||||
sheetSet.put(new NodeProperty<>("office", Bundle.ContactNode_Office_Number(), "",
|
||||
getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_OFFICE))); //NON-NLS
|
||||
sheetSet.put(new NodeProperty<>("url", Bundle.ContactNode_URL(), "",
|
||||
getAttributeDisplayString(artifact, TSK_URL))); //NON-NLS
|
||||
|
||||
return sheet;
|
||||
}
|
||||
|
||||
private static String getAttributeDisplayString(final BlackboardArtifact artifact, final BlackboardAttribute.ATTRIBUTE_TYPE attributeType) {
|
||||
try {
|
||||
BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.fromID(attributeType.getTypeID())));
|
||||
if (attribute == null) {
|
||||
return "";
|
||||
} else if (attributeType.getValueType() == DATETIME) {
|
||||
return TimeUtilities.epochToTime(attribute.getValueLong(),
|
||||
TimeZone.getTimeZone(Utils.getUserPreferredZoneId()));
|
||||
} else {
|
||||
return attribute.getDisplayString();
|
||||
}
|
||||
} catch (TskCoreException tskCoreException) {
|
||||
logger.log(Level.WARNING, "Error getting attribute value.", tskCoreException); //NON-NLS
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Circumvent DataResultFilterNode's slightly odd delegation to
|
||||
* BlackboardArtifactNode.getSourceName().
|
||||
*
|
||||
* @return the displayName of this Node, which is the type.
|
||||
*/
|
||||
@Override
|
||||
public String getSourceName() {
|
||||
return getDisplayName();
|
||||
}
|
||||
}
|
109
Core/src/org/sleuthkit/autopsy/communications/ContactsChildNodeFactory.java
Executable file
109
Core/src/org/sleuthkit/autopsy/communications/ContactsChildNodeFactory.java
Executable file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import org.openide.nodes.ChildFactory;
|
||||
import org.openide.nodes.Node;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT;
|
||||
import org.sleuthkit.datamodel.CommunicationsManager;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
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 SelectionInfo selectionInfo;
|
||||
|
||||
/**
|
||||
* Construct a new ContactsChildNodeFactory from the currently selectionInfo
|
||||
*
|
||||
* @param selectionInfo SelectionInfo object for the currently selected
|
||||
* accounts
|
||||
*/
|
||||
ContactsChildNodeFactory(SelectionInfo selectionInfo) {
|
||||
this.selectionInfo = selectionInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 contacts of 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());
|
||||
|
||||
relationshipSources.stream().filter((content) -> (content instanceof BlackboardArtifact)).forEachOrdered((content) -> {
|
||||
|
||||
BlackboardArtifact bba = (BlackboardArtifact) content;
|
||||
BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(bba.getArtifactTypeID());
|
||||
|
||||
if (fromID == TSK_CONTACT) {
|
||||
list.add(bba);
|
||||
}
|
||||
});
|
||||
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Failed to get relationship sources.", ex); //NON-NLS
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node createNodeForKey(BlackboardArtifact key) {
|
||||
return new ContactNode(key);
|
||||
}
|
||||
}
|
@ -16,30 +16,27 @@
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="testLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace pref="294" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="outlineView" max="32767" attributes="0"/>
|
||||
<Component id="contactPane" alignment="0" max="32767" attributes="0"/>
|
||||
</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="testLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace pref="264" max="32767" attributes="0"/>
|
||||
<Component id="outlineView" max="32767" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="contactPane" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="testLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="ContactsViewer.testLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Component class="org.openide.explorer.view.OutlineView" name="outlineView">
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new org.openide.explorer.view.OutlineView()"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="org.sleuthkit.autopsy.communications.ContactDetailsPane" name="contactPane">
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
@ -18,26 +18,101 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.communications;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.KeyboardFocusManager;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.ListSelectionModel;
|
||||
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.util.Lookup;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.lookup.ServiceProvider;
|
||||
import org.sleuthkit.autopsy.corecomponents.TableFilterNode;
|
||||
import org.sleuthkit.autopsy.directorytree.DataResultFilterNode;
|
||||
|
||||
/**
|
||||
* Visualization for contacts
|
||||
* Visualization for contact nodes.
|
||||
*
|
||||
*/
|
||||
@ServiceProvider(service=RelationshipsViewer.class)
|
||||
public class ContactsViewer extends JPanel implements RelationshipsViewer{
|
||||
@ServiceProvider(service = RelationshipsViewer.class)
|
||||
public final class ContactsViewer extends JPanel implements RelationshipsViewer, ExplorerManager.Provider, Lookup.Provider {
|
||||
|
||||
private final ExplorerManager tableEM;
|
||||
private final Outline outline;
|
||||
private final ModifiableProxyLookup proxyLookup;
|
||||
private final PropertyChangeListener focusPropertyListener;
|
||||
private final ContactsChildNodeFactory nodeFactory;
|
||||
|
||||
@NbBundle.Messages({
|
||||
"ContactsViewer_tabTitle=Contacts",
|
||||
"ContactsViewer_columnHeader_Name=Name",
|
||||
"ContactsViewer_columnHeader_Phone=Phone",
|
||||
"ContactsViewer_columnHeader_Email=Email",})
|
||||
|
||||
/**
|
||||
* Creates new form ContactsViewer
|
||||
* Visualization for contact nodes.
|
||||
*/
|
||||
public ContactsViewer() {
|
||||
tableEM = new ExplorerManager();
|
||||
proxyLookup = new ModifiableProxyLookup(createLookup(tableEM, getActionMap()));
|
||||
nodeFactory = new ContactsChildNodeFactory(null);
|
||||
|
||||
// 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, contactPane)) {
|
||||
//if the focus owner is within the MessageContentViewer (the attachments table)
|
||||
proxyLookup.setNewLookups(createLookup(contactPane.getExplorerManager(), getActionMap()));
|
||||
} else if (isDescendingFrom(newFocusOwner, ContactsViewer.this)) {
|
||||
//... or if it is within the Results table.
|
||||
proxyLookup.setNewLookups(createLookup(tableEM, getActionMap()));
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
initComponents();
|
||||
|
||||
outline = outlineView.getOutline();
|
||||
outlineView.setPropertyColumns(
|
||||
"email", Bundle.ContactsViewer_columnHeader_Email(),
|
||||
"phone", Bundle.ContactsViewer_columnHeader_Phone()
|
||||
);
|
||||
outline.setRootVisible(false);
|
||||
outline.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
((DefaultOutlineModel) outline.getOutlineModel()).setNodesColumnLabel(Bundle.ContactsViewer_columnHeader_Name());
|
||||
|
||||
tableEM.addPropertyChangeListener((PropertyChangeEvent evt) -> {
|
||||
if (evt.getPropertyName().equals(ExplorerManager.PROP_SELECTED_NODES)) {
|
||||
final Node[] nodes = tableEM.getSelectedNodes();
|
||||
|
||||
if (nodes != null && nodes.length > 0) {
|
||||
contactPane.setEnabled(true);
|
||||
contactPane.setNode(nodes);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
tableEM.setRootContext(new TableFilterNode(new DataResultFilterNode(new AbstractNode(Children.create(nodeFactory, true)), getExplorerManager()), true));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return "Contacts";
|
||||
return Bundle.ContactsViewer_tabTitle();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -47,7 +122,35 @@ public class ContactsViewer extends JPanel implements RelationshipsViewer{
|
||||
|
||||
@Override
|
||||
public void setSelectionInfo(SelectionInfo info) {
|
||||
testLabel.setText(info.getString());
|
||||
contactPane.setNode(new Node[]{new AbstractNode(Children.LEAF)});
|
||||
contactPane.setEnabled(false);
|
||||
|
||||
nodeFactory.refresh(info);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExplorerManager getExplorerManager() {
|
||||
return tableEM;
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -59,30 +162,28 @@ public class ContactsViewer extends JPanel implements RelationshipsViewer{
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
|
||||
testLabel = new javax.swing.JLabel();
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(testLabel, org.openide.util.NbBundle.getMessage(ContactsViewer.class, "ContactsViewer.testLabel.text")); // NOI18N
|
||||
outlineView = new org.openide.explorer.view.OutlineView();
|
||||
contactPane = new org.sleuthkit.autopsy.communications.ContactDetailsPane();
|
||||
|
||||
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()
|
||||
.addComponent(testLabel)
|
||||
.addContainerGap(294, Short.MAX_VALUE))
|
||||
.addComponent(outlineView, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(contactPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(testLabel)
|
||||
.addContainerGap(264, Short.MAX_VALUE))
|
||||
.addComponent(outlineView, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(contactPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JLabel testLabel;
|
||||
private org.sleuthkit.autopsy.communications.ContactDetailsPane contactPane;
|
||||
private org.openide.explorer.view.OutlineView outlineView;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
}
|
||||
|
@ -49,6 +49,7 @@ import org.sleuthkit.datamodel.CommunicationsFilter.DateRangeFilter;
|
||||
import org.sleuthkit.datamodel.CommunicationsFilter.DeviceFilter;
|
||||
import org.sleuthkit.datamodel.DataSource;
|
||||
import static org.sleuthkit.datamodel.Relationship.Type.CALL_LOG;
|
||||
import static org.sleuthkit.datamodel.Relationship.Type.CONTACT;
|
||||
import static org.sleuthkit.datamodel.Relationship.Type.MESSAGE;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
@ -514,7 +515,7 @@ final public class FiltersPanel extends JPanel {
|
||||
commsFilter.addAndFilter(getAccountTypeFilter());
|
||||
commsFilter.addAndFilter(getDateRangeFilter());
|
||||
commsFilter.addAndFilter(new CommunicationsFilter.RelationshipTypeFilter(
|
||||
ImmutableSet.of(CALL_LOG, MESSAGE)));
|
||||
ImmutableSet.of(CALL_LOG, MESSAGE, CONTACT)));
|
||||
return commsFilter;
|
||||
}
|
||||
|
||||
|
@ -18,23 +18,168 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.communications;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.TimeZone;
|
||||
import java.util.logging.Level;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openide.nodes.Sheet;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
|
||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||
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;
|
||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME;
|
||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_SENT;
|
||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START;
|
||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL_FROM;
|
||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL_TO;
|
||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM;
|
||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO;
|
||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SUBJECT;
|
||||
import static org.sleuthkit.datamodel.BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME;
|
||||
import org.sleuthkit.datamodel.Tag;
|
||||
import org.sleuthkit.datamodel.TimeUtilities;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Wraps a BlackboardArtifact as an AbstractNode for use in an OutlookView
|
||||
*/
|
||||
final class MessageNode extends BlackboardArtifactNode {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(RelationshipNode.class.getName());
|
||||
|
||||
MessageNode(BlackboardArtifact artifact) {
|
||||
super(artifact);
|
||||
// Grabbed this from RelationshipNode, does always work even with internalization?
|
||||
|
||||
final String stripEnd = StringUtils.stripEnd(artifact.getDisplayName(), "s"); // NON-NLS
|
||||
String removeEndIgnoreCase = StringUtils.removeEndIgnoreCase(stripEnd, "message"); // NON-NLS
|
||||
setDisplayName(removeEndIgnoreCase.isEmpty() ? stripEnd : removeEndIgnoreCase);
|
||||
}
|
||||
|
||||
@Messages({
|
||||
"MessageNode_Node_Property_Type=Type",
|
||||
"MessageNode_Node_Property_From=From",
|
||||
"MessageNode_Node_Property_To=To",
|
||||
"MessageNode_Node_Property_Date=Date",
|
||||
"MessageNode_Node_Property_Subject=Subject",
|
||||
"MessageNode_Node_Property_Attms=Attachments"
|
||||
})
|
||||
|
||||
@Override
|
||||
protected Sheet createSheet() {
|
||||
Sheet sheet = new Sheet();
|
||||
List<Tag> tags = getAllTagsFromDatabase();
|
||||
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
|
||||
if (sheetSet == null) {
|
||||
sheetSet = Sheet.createPropertiesSet();
|
||||
sheet.put(sheetSet);
|
||||
}
|
||||
|
||||
sheetSet.put(new NodeProperty<>("Type", Bundle.MessageNode_Node_Property_Type(), "", getDisplayName())); //NON-NLS
|
||||
|
||||
addScoreProperty(sheetSet, tags);
|
||||
|
||||
CorrelationAttributeInstance correlationAttribute = null;
|
||||
if (UserPreferences.hideCentralRepoCommentsAndOccurrences() == false) {
|
||||
correlationAttribute = getCorrelationAttributeInstance();
|
||||
}
|
||||
addCommentProperty(sheetSet, tags, correlationAttribute);
|
||||
|
||||
if (UserPreferences.hideCentralRepoCommentsAndOccurrences() == false) {
|
||||
addCountProperty(sheetSet, correlationAttribute);
|
||||
}
|
||||
final BlackboardArtifact artifact = getArtifact();
|
||||
|
||||
BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(artifact.getArtifactTypeID());
|
||||
if (null != fromID) {
|
||||
//Consider refactoring this to reduce boilerplate
|
||||
switch (fromID) {
|
||||
case TSK_EMAIL_MSG:
|
||||
sheetSet.put(new NodeProperty<>("From", Bundle.MessageNode_Node_Property_From(), "",
|
||||
StringUtils.strip(getAttributeDisplayString(artifact, TSK_EMAIL_FROM), " \t\n;"))); //NON-NLS
|
||||
sheetSet.put(new NodeProperty<>("To", Bundle.MessageNode_Node_Property_To(), "",
|
||||
StringUtils.strip(getAttributeDisplayString(artifact, TSK_EMAIL_TO), " \t\n;"))); //NON-NLS
|
||||
sheetSet.put(new NodeProperty<>("Date", Bundle.MessageNode_Node_Property_Date(), "",
|
||||
getAttributeDisplayString(artifact, TSK_DATETIME_SENT))); //NON-NLS
|
||||
sheetSet.put(new NodeProperty<>("Subject", Bundle.MessageNode_Node_Property_Subject(), "",
|
||||
getAttributeDisplayString(artifact, TSK_SUBJECT))); //NON-NLS
|
||||
try {
|
||||
sheetSet.put(new NodeProperty<>("Attms", Bundle.MessageNode_Node_Property_Attms(), "", artifact.getChildrenCount())); //NON-NLS
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, "Error loading attachment count for " + artifact, ex); //NON-NLS
|
||||
}
|
||||
|
||||
break;
|
||||
case TSK_MESSAGE:
|
||||
sheetSet.put(new NodeProperty<>("From", Bundle.MessageNode_Node_Property_From(), "",
|
||||
getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_FROM))); //NON-NLS
|
||||
sheetSet.put(new NodeProperty<>("To", Bundle.MessageNode_Node_Property_To(), "",
|
||||
getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_TO))); //NON-NLS
|
||||
sheetSet.put(new NodeProperty<>("Date", Bundle.MessageNode_Node_Property_Date(), "",
|
||||
getAttributeDisplayString(artifact, TSK_DATETIME))); //NON-NLS
|
||||
sheetSet.put(new NodeProperty<>("Subject", Bundle.MessageNode_Node_Property_Subject(), "",
|
||||
getAttributeDisplayString(artifact, TSK_SUBJECT))); //NON-NLS
|
||||
try {
|
||||
sheetSet.put(new NodeProperty<>("Attms", Bundle.MessageNode_Node_Property_Attms(), "", artifact.getChildrenCount())); //NON-NLS
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, "Error loading attachment count for " + artifact, ex); //NON-NLS
|
||||
}
|
||||
break;
|
||||
case TSK_CALLLOG:
|
||||
sheetSet.put(new NodeProperty<>("From", Bundle.MessageNode_Node_Property_From(), "",
|
||||
getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_FROM))); //NON-NLS
|
||||
sheetSet.put(new NodeProperty<>("To", Bundle.MessageNode_Node_Property_To(), "",
|
||||
getAttributeDisplayString(artifact, TSK_PHONE_NUMBER_TO))); //NON-NLS
|
||||
sheetSet.put(new NodeProperty<>("Date", Bundle.MessageNode_Node_Property_Date(), "",
|
||||
getAttributeDisplayString(artifact, TSK_DATETIME_START))); //NON-NLS
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return sheet;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Get the display string for the attribute of the given type from the given
|
||||
* artifact.
|
||||
*
|
||||
* @param artifact the value of artifact
|
||||
* @param attributeType the value of TSK_SUBJECT1
|
||||
*
|
||||
* @return The display string, or an empty string if there is no such
|
||||
* attribute or an an error.
|
||||
*/
|
||||
private static String getAttributeDisplayString(final BlackboardArtifact artifact, final BlackboardAttribute.ATTRIBUTE_TYPE attributeType) {
|
||||
try {
|
||||
BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.fromID(attributeType.getTypeID())));
|
||||
if (attribute == null) {
|
||||
return "";
|
||||
} else if (attributeType.getValueType() == DATETIME) {
|
||||
return TimeUtilities.epochToTime(attribute.getValueLong(),
|
||||
TimeZone.getTimeZone(Utils.getUserPreferredZoneId()));
|
||||
} else {
|
||||
return attribute.getDisplayString();
|
||||
}
|
||||
} catch (TskCoreException tskCoreException) {
|
||||
logger.log(Level.WARNING, "Error getting attribute value.", tskCoreException); //NON-NLS
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Circumvent DataResultFilterNode's slightly odd delegation to
|
||||
* BlackboardArtifactNode.getSourceName().
|
||||
*
|
||||
* @return the displayName of this Node, which is the type.
|
||||
*/
|
||||
@Override
|
||||
public String getSourceName() {
|
||||
return getDisplayName();
|
||||
}
|
||||
}
|
||||
|
@ -1,48 +0,0 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import org.openide.nodes.ChildFactory;
|
||||
import org.openide.nodes.Node;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class MessageNodeFactory extends ChildFactory<BlackboardArtifact> {
|
||||
private final Collection<BlackboardArtifact> artifacts;
|
||||
|
||||
MessageNodeFactory(Collection<BlackboardArtifact> artifacts) {
|
||||
this.artifacts = artifacts;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean createKeys(List<BlackboardArtifact> list) {
|
||||
list.addAll(artifacts);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node createNodeForKey(BlackboardArtifact key) {
|
||||
return new MessageNode(key);
|
||||
}
|
||||
}
|
115
Core/src/org/sleuthkit/autopsy/communications/MessagesChildNodeFactory.java
Executable file
115
Core/src/org/sleuthkit/autopsy/communications/MessagesChildNodeFactory.java
Executable file
@ -0,0 +1,115 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import org.openide.nodes.ChildFactory;
|
||||
import org.openide.nodes.Node;
|
||||
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.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 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) {
|
||||
this.selectionInfo = selectionInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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());
|
||||
|
||||
relationshipSources.stream().filter((content) -> (content instanceof BlackboardArtifact)).forEachOrdered((content) -> {
|
||||
|
||||
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) {
|
||||
list.add(bba);
|
||||
}
|
||||
});
|
||||
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Failed to get relationship sources.", ex); //NON-NLS
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node createNodeForKey(BlackboardArtifact key) {
|
||||
return new MessageNode(key);
|
||||
}
|
||||
}
|
@ -16,30 +16,27 @@
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="testLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace pref="294" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="outlineView" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="contentViewer" alignment="1" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="outlineView" min="-2" pref="190" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="testLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace pref="264" max="32767" attributes="0"/>
|
||||
<Component id="contentViewer" pref="778" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="testLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="MessagesViewer.testLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Component class="org.openide.explorer.view.OutlineView" name="outlineView">
|
||||
</Component>
|
||||
<Component class="org.sleuthkit.autopsy.contentviewers.MessageContentViewer" name="contentViewer">
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new MessageDataContent()"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
@ -18,26 +18,106 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.communications;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.KeyboardFocusManager;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.ListSelectionModel;
|
||||
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.util.Lookup;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.openide.util.lookup.ServiceProvider;
|
||||
import org.sleuthkit.autopsy.corecomponents.TableFilterNode;
|
||||
import org.sleuthkit.autopsy.directorytree.DataResultFilterNode;
|
||||
|
||||
/**
|
||||
* Visualation for Contacts
|
||||
*
|
||||
* Visualation for the messages of the currently selected accounts.
|
||||
*/
|
||||
@ServiceProvider(service=RelationshipsViewer.class)
|
||||
public class MessagesViewer extends JPanel implements RelationshipsViewer{
|
||||
@ServiceProvider(service = RelationshipsViewer.class)
|
||||
public final class MessagesViewer extends JPanel implements RelationshipsViewer, ExplorerManager.Provider, Lookup.Provider {
|
||||
|
||||
private final ExplorerManager tableEM;
|
||||
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"
|
||||
})
|
||||
|
||||
/**
|
||||
* Creates new form MessagesViewer
|
||||
* Visualation for the messages of the currently selected accounts.
|
||||
*/
|
||||
public MessagesViewer() {
|
||||
tableEM = new ExplorerManager();
|
||||
proxyLookup = new ModifiableProxyLookup(createLookup(tableEM, getActionMap()));
|
||||
nodeFactory = new MessagesChildNodeFactory(null);
|
||||
|
||||
// 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, contentViewer)) {
|
||||
//if the focus owner is within the MessageContentViewer (the attachments table)
|
||||
proxyLookup.setNewLookups(createLookup(((MessageDataContent) contentViewer).getExplorerManager(), getActionMap()));
|
||||
} else if (isDescendingFrom(newFocusOwner, MessagesViewer.this)) {
|
||||
//... or if it is within the Results table.
|
||||
proxyLookup.setNewLookups(createLookup(tableEM, getActionMap()));
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
initComponents();
|
||||
|
||||
outline = outlineView.getOutline();
|
||||
outlineView.setPropertyColumns(
|
||||
"From", Bundle.MessageViewer_columnHeader_From(),
|
||||
"To", Bundle.MessageViewer_columnHeader_To(),
|
||||
"Date", Bundle.MessageViewer_columnHeader_Date(),
|
||||
"Subject", Bundle.MessageViewer_columnHeader_Subject(),
|
||||
"Attms", Bundle.MessageViewer_columnHeader_Attms(),
|
||||
"Type", "Type"
|
||||
);
|
||||
outline.setRootVisible(false);
|
||||
outline.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
((DefaultOutlineModel) outline.getOutlineModel()).setNodesColumnLabel("Type");
|
||||
|
||||
tableEM.addPropertyChangeListener((PropertyChangeEvent evt) -> {
|
||||
if (evt.getPropertyName().equals(ExplorerManager.PROP_SELECTED_NODES)) {
|
||||
final Node[] nodes = tableEM.getSelectedNodes();
|
||||
|
||||
if (nodes != null && nodes.length > 0) {
|
||||
contentViewer.setNode(nodes[0]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
tableEM.setRootContext(new TableFilterNode(new DataResultFilterNode(new AbstractNode(Children.create(nodeFactory, true)), getExplorerManager()), true));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return "Messages";
|
||||
return Bundle.MessageViewer_tabTitle();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -47,7 +127,33 @@ public class MessagesViewer extends JPanel implements RelationshipsViewer{
|
||||
|
||||
@Override
|
||||
public void setSelectionInfo(SelectionInfo info) {
|
||||
testLabel.setText(info.getString());
|
||||
// tableEM.setRootContext(new TableFilterNode(new DataResultFilterNode(new AbstractNode(Children.create(new MessagesChildNodeFactory(info), true)), getExplorerManager()), true));
|
||||
nodeFactory.refresh(info);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExplorerManager getExplorerManager() {
|
||||
return tableEM;
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -59,30 +165,28 @@ public class MessagesViewer extends JPanel implements RelationshipsViewer{
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
|
||||
testLabel = new javax.swing.JLabel();
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(testLabel, org.openide.util.NbBundle.getMessage(MessagesViewer.class, "MessagesViewer.testLabel.text")); // NOI18N
|
||||
outlineView = new org.openide.explorer.view.OutlineView();
|
||||
contentViewer = new MessageDataContent();
|
||||
|
||||
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()
|
||||
.addComponent(testLabel)
|
||||
.addContainerGap(294, Short.MAX_VALUE))
|
||||
.addComponent(outlineView, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(contentViewer, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(testLabel)
|
||||
.addContainerGap(264, Short.MAX_VALUE))
|
||||
.addComponent(outlineView, javax.swing.GroupLayout.PREFERRED_SIZE, 190, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(contentViewer, javax.swing.GroupLayout.DEFAULT_SIZE, 778, Short.MAX_VALUE))
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JLabel testLabel;
|
||||
private org.sleuthkit.autopsy.contentviewers.MessageContentViewer contentViewer;
|
||||
private org.openide.explorer.view.OutlineView outlineView;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
}
|
||||
|
@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2017-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;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import org.openide.nodes.ChildFactory;
|
||||
import org.openide.nodes.Node;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class RelaionshipSetNodeFactory extends ChildFactory<BlackboardArtifact> {
|
||||
|
||||
private final Collection<BlackboardArtifact> artifacts;
|
||||
|
||||
public RelaionshipSetNodeFactory(Collection<BlackboardArtifact> artifacts) {
|
||||
this.artifacts = artifacts;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean createKeys(List<BlackboardArtifact> list) {
|
||||
list.addAll(artifacts);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node createNodeForKey(BlackboardArtifact key) {
|
||||
return new RelationshipNode(key);
|
||||
}
|
||||
}
|
@ -27,6 +27,9 @@
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JTabbedPane" name="tabPane">
|
||||
<Events>
|
||||
<EventHandler event="stateChanged" listener="javax.swing.event.ChangeListener" parameters="javax.swing.event.ChangeEvent" handler="tabPaneStateChanged"/>
|
||||
</Events>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout"/>
|
||||
</Container>
|
||||
|
@ -25,7 +25,9 @@ import org.openide.util.Lookup;
|
||||
* Displays the Relationship information for the currently selected accounts.
|
||||
*
|
||||
*/
|
||||
public class RelationshipBrowser extends JPanel {
|
||||
final class RelationshipBrowser extends JPanel {
|
||||
|
||||
private SelectionInfo currentSelection;
|
||||
|
||||
/**
|
||||
* Creates new form RelationshipBrowser
|
||||
@ -38,11 +40,15 @@ public class RelationshipBrowser extends JPanel {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of currentSelection and passes the SelectionInfo onto the
|
||||
* currently selected\visible tab.
|
||||
*
|
||||
* @param info Currently selected account nodes
|
||||
*/
|
||||
public void setSelectionInfo(SelectionInfo info) {
|
||||
((RelationshipsViewer)tabPane.getSelectedComponent()).setSelectionInfo(info);
|
||||
|
||||
// TODO If we only pass the info to the currently selected tab, we
|
||||
// need to do something when the tab changes
|
||||
currentSelection = info;
|
||||
((RelationshipsViewer) tabPane.getSelectedComponent()).setSelectionInfo(info);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -56,6 +62,12 @@ public class RelationshipBrowser extends JPanel {
|
||||
|
||||
tabPane = new javax.swing.JTabbedPane();
|
||||
|
||||
tabPane.addChangeListener(new javax.swing.event.ChangeListener() {
|
||||
public void stateChanged(javax.swing.event.ChangeEvent evt) {
|
||||
tabPaneStateChanged(evt);
|
||||
}
|
||||
});
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
@ -68,6 +80,10 @@ public class RelationshipBrowser extends JPanel {
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
private void tabPaneStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_tabPaneStateChanged
|
||||
((RelationshipsViewer) tabPane.getSelectedComponent()).setSelectionInfo(currentSelection);
|
||||
}//GEN-LAST:event_tabPaneStateChanged
|
||||
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JTabbedPane tabPane;
|
||||
|
@ -18,29 +18,46 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.communications;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import java.util.Set;
|
||||
import org.sleuthkit.datamodel.AccountDeviceInstance;
|
||||
import org.sleuthkit.datamodel.CommunicationsFilter;
|
||||
|
||||
/**
|
||||
* Class to wrap the details of the current selection from the AccountBrowser or
|
||||
* VisualizationPane
|
||||
*
|
||||
*/
|
||||
public class SelectionInfo {
|
||||
public final class SelectionInfo {
|
||||
|
||||
private final String displayString;
|
||||
private final Set<AccountDeviceInstance> accountDeviceInstances;
|
||||
private final CommunicationsFilter communicationFilter;
|
||||
|
||||
SelectionInfo() {
|
||||
displayString = (new Date()).toString();
|
||||
/**
|
||||
* Wraps the details of the currently selected accounts.
|
||||
*
|
||||
* @param accountDeviceInstances Selected accountDecivedInstances
|
||||
* @param communicationFilter Currently selected communications filters
|
||||
*/
|
||||
SelectionInfo(Set<AccountDeviceInstance> accountDeviceInstances, CommunicationsFilter communicationFilter) {
|
||||
this.accountDeviceInstances = accountDeviceInstances;
|
||||
this.communicationFilter = communicationFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Temporary function for testing data flow
|
||||
* Returns the currently selected accountDeviceInstances
|
||||
*
|
||||
* @return A String representing the time the object was created
|
||||
* @return Set of AccountDeviceInstance
|
||||
*/
|
||||
public String getString() {
|
||||
return displayString;
|
||||
public Set<AccountDeviceInstance> getAccountDevicesInstances() {
|
||||
return accountDeviceInstances;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently selected communications filters.
|
||||
*
|
||||
* @return Instance of CommunicationsFilter
|
||||
*/
|
||||
public CommunicationsFilter getCommunicationsFilter() {
|
||||
return communicationFilter;
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user