mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-17 18:17:43 +00:00
Merge pull request #3310 from sleuthkit/accounts_relationships
Accounts relationships
This commit is contained in:
commit
28d97c6598
@ -12,3 +12,5 @@ FiltersPanel.dateRangeLabel.text=Date Range:
|
||||
FiltersPanel.startCheckBox.text=Start:
|
||||
FiltersPanel.endCheckBox.text=End:
|
||||
FiltersPanel.refreshButton.text=Refresh
|
||||
FiltersPanel.deviceRequiredLabel.text=Select at least one.
|
||||
FiltersPanel.accountTypeRequiredLabel.text=Select at least one.
|
||||
|
@ -87,9 +87,10 @@
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<Group type="103" groupAlignment="1" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="accountTypesLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="accountTypeRequiredLabel" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
@ -111,7 +112,10 @@
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="accountTypesLabel" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="accountTypesLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="accountTypeRequiredLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jScrollPane3" pref="245" max="32767" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
@ -166,6 +170,20 @@
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JLabel" name="accountTypeRequiredLabel">
|
||||
<Properties>
|
||||
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="0" green="0" red="ff" type="rgb"/>
|
||||
</Property>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/images/error-icon-16.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.accountTypeRequiredLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="horizontalTextPosition" type="int" value="2"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JPanel" name="jPanel3">
|
||||
@ -176,6 +194,7 @@
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="devicesLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="deviceRequiredLabel" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
@ -194,7 +213,10 @@
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="devicesLabel" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="devicesLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="deviceRequiredLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jScrollPane2" pref="96" max="32767" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
@ -261,6 +283,20 @@
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JLabel" name="deviceRequiredLabel">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/images/error-icon-16.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/communications/Bundle.properties" key="FiltersPanel.deviceRequiredLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="0" green="0" red="ff" type="rgb"/>
|
||||
</Property>
|
||||
<Property name="horizontalTextPosition" type="int" value="2"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JPanel" name="jPanel4">
|
||||
|
@ -19,6 +19,7 @@
|
||||
package org.sleuthkit.autopsy.communications;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.awt.event.ItemListener;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.time.LocalDate;
|
||||
import java.time.ZoneId;
|
||||
@ -68,12 +69,25 @@ final public class FiltersPanel extends javax.swing.JPanel {
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||
private final Map<String, JCheckBox> devicesMap = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Listens to ingest events to enable refresh button
|
||||
*/
|
||||
private final PropertyChangeListener ingestListener;
|
||||
private boolean needsRefresh;
|
||||
|
||||
/**
|
||||
* Listen to check box state changes and validates that at least one box is
|
||||
* selected for device and account type ( other wise there will be no
|
||||
* results)
|
||||
*/
|
||||
private final ItemListener validationListener;
|
||||
|
||||
@NbBundle.Messages({"refreshText=Refresh Results",
|
||||
"applyText=Apply"})
|
||||
public FiltersPanel() {
|
||||
initComponents();
|
||||
deviceRequiredLabel.setVisible(false);
|
||||
accountTypeRequiredLabel.setVisible(false);
|
||||
startDatePicker.setDate(LocalDate.now().minusWeeks(3));
|
||||
endDatePicker.setDateToToday();
|
||||
startDatePicker.getSettings().setVetoPolicy(
|
||||
@ -88,7 +102,10 @@ final public class FiltersPanel extends javax.swing.JPanel {
|
||||
);
|
||||
|
||||
updateTimeZone();
|
||||
validationListener = itemEvent -> validateFilters();
|
||||
|
||||
updateFilters();
|
||||
setAllDevicesSelected(true);
|
||||
UserPreferences.addChangeListener(preferenceChangeEvent -> {
|
||||
if (preferenceChangeEvent.getKey().equals(UserPreferences.DISPLAY_TIMES_IN_LOCAL_TIME)) {
|
||||
updateTimeZone();
|
||||
@ -99,7 +116,8 @@ final public class FiltersPanel extends javax.swing.JPanel {
|
||||
String eventType = pce.getPropertyName();
|
||||
if (eventType.equals(DATA_ADDED.toString())) {
|
||||
updateFilters();
|
||||
refreshButton.setEnabled(true);
|
||||
needsRefresh = true;
|
||||
validateFilters();
|
||||
}
|
||||
};
|
||||
|
||||
@ -107,6 +125,24 @@ final public class FiltersPanel extends javax.swing.JPanel {
|
||||
refreshButton.addActionListener(e -> applyFilters());
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that filters are in a consistent state and will result in some
|
||||
* results. Checks that at least one device and at least one account type is
|
||||
* selected. Disables the apply and refresh button and shows warnings if the
|
||||
* filters are not valid.
|
||||
*/
|
||||
private void validateFilters() {
|
||||
boolean someDevice = devicesMap.values().stream().anyMatch(JCheckBox::isSelected);
|
||||
boolean someAccountType = accountTypeMap.values().stream().anyMatch(JCheckBox::isSelected);
|
||||
|
||||
deviceRequiredLabel.setVisible(someDevice == false);
|
||||
accountTypeRequiredLabel.setVisible(someAccountType == false);
|
||||
|
||||
applyFiltersButton.setEnabled(someDevice && someAccountType);
|
||||
refreshButton.setEnabled(someDevice && someAccountType && needsRefresh);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the filter widgets, and apply them.
|
||||
*/
|
||||
@ -171,6 +207,7 @@ final public class FiltersPanel extends javax.swing.JPanel {
|
||||
+ "\"/></td><td width=" + 3 + "><td>" + type.getDisplayName() + "</td></tr></table></html>",
|
||||
true
|
||||
);
|
||||
jCheckBox.addItemListener(validationListener);
|
||||
accountTypePane.add(jCheckBox);
|
||||
return jCheckBox;
|
||||
});
|
||||
@ -191,6 +228,7 @@ final public class FiltersPanel extends javax.swing.JPanel {
|
||||
//store the device id in the map, but display a datasource name in the UI.
|
||||
devicesMap.computeIfAbsent(dataSource.getDeviceId(), ds -> {
|
||||
final JCheckBox jCheckBox = new JCheckBox(dsName, false);
|
||||
jCheckBox.addItemListener(validationListener);
|
||||
devicesPane.add(jCheckBox);
|
||||
return jCheckBox;
|
||||
});
|
||||
@ -203,7 +241,6 @@ final public class FiltersPanel extends javax.swing.JPanel {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -217,9 +254,9 @@ final public class FiltersPanel extends javax.swing.JPanel {
|
||||
applyFiltersButton.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.applyFiltersButton.text")); // NOI18N
|
||||
applyFiltersButton.setPreferredSize(null);
|
||||
|
||||
filtersTitleLabel.setFont(new java.awt.Font("Tahoma", 0, 16)); // NOI18N
|
||||
filtersTitleLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/funnel.png"))); // NOI18N
|
||||
filtersTitleLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.filtersTitleLabel.text")); // NOI18N
|
||||
filtersTitleLabel.setFont(new java.awt.Font("Tahoma", 0, 16)); // NOI18N
|
||||
|
||||
unCheckAllAccountTypesButton.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.unCheckAllAccountTypesButton.text")); // NOI18N
|
||||
unCheckAllAccountTypesButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
@ -241,15 +278,21 @@ final public class FiltersPanel extends javax.swing.JPanel {
|
||||
accountTypePane.setLayout(new javax.swing.BoxLayout(accountTypePane, javax.swing.BoxLayout.Y_AXIS));
|
||||
jScrollPane3.setViewportView(accountTypePane);
|
||||
|
||||
accountTypeRequiredLabel.setForeground(new java.awt.Color(255, 0, 0));
|
||||
accountTypeRequiredLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/error-icon-16.png"))); // NOI18N
|
||||
accountTypeRequiredLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.accountTypeRequiredLabel.text")); // NOI18N
|
||||
accountTypeRequiredLabel.setHorizontalTextPosition(javax.swing.SwingConstants.LEFT);
|
||||
|
||||
javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
|
||||
jPanel2.setLayout(jPanel2Layout);
|
||||
jPanel2Layout.setHorizontalGroup(
|
||||
jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup()
|
||||
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel2Layout.createSequentialGroup()
|
||||
.addGroup(jPanel2Layout.createSequentialGroup()
|
||||
.addComponent(accountTypesLabel)
|
||||
.addGap(0, 0, Short.MAX_VALUE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(accountTypeRequiredLabel))
|
||||
.addGroup(jPanel2Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
@ -264,7 +307,9 @@ final public class FiltersPanel extends javax.swing.JPanel {
|
||||
jPanel2Layout.setVerticalGroup(
|
||||
jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel2Layout.createSequentialGroup()
|
||||
.addComponent(accountTypesLabel)
|
||||
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(accountTypesLabel)
|
||||
.addComponent(accountTypeRequiredLabel))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 245, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
@ -297,13 +342,19 @@ final public class FiltersPanel extends javax.swing.JPanel {
|
||||
devicesPane.setLayout(new javax.swing.BoxLayout(devicesPane, javax.swing.BoxLayout.Y_AXIS));
|
||||
jScrollPane2.setViewportView(devicesPane);
|
||||
|
||||
deviceRequiredLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/error-icon-16.png"))); // NOI18N
|
||||
deviceRequiredLabel.setText(org.openide.util.NbBundle.getMessage(FiltersPanel.class, "FiltersPanel.deviceRequiredLabel.text")); // NOI18N
|
||||
deviceRequiredLabel.setForeground(new java.awt.Color(255, 0, 0));
|
||||
deviceRequiredLabel.setHorizontalTextPosition(javax.swing.SwingConstants.LEFT);
|
||||
|
||||
javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
|
||||
jPanel3.setLayout(jPanel3Layout);
|
||||
jPanel3Layout.setHorizontalGroup(
|
||||
jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel3Layout.createSequentialGroup()
|
||||
.addComponent(devicesLabel)
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(deviceRequiredLabel))
|
||||
.addGroup(jPanel3Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
@ -317,7 +368,9 @@ final public class FiltersPanel extends javax.swing.JPanel {
|
||||
jPanel3Layout.setVerticalGroup(
|
||||
jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel3Layout.createSequentialGroup()
|
||||
.addComponent(devicesLabel)
|
||||
.addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(devicesLabel)
|
||||
.addComponent(deviceRequiredLabel))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 96, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
@ -430,7 +483,7 @@ final public class FiltersPanel extends javax.swing.JPanel {
|
||||
commsFilter.addAndFilter(getDateRangeFilter());
|
||||
commsFilter.addAndFilter(new CommunicationsFilter.RelationshipTypeFilter(
|
||||
ImmutableSet.of(CALL_LOG, MESSAGE)));
|
||||
|
||||
|
||||
try {
|
||||
final CommunicationsManager commsManager = Case.getCurrentCase().getSleuthkitCase().getCommunicationsManager();
|
||||
em.setRootContext(new AbstractNode(Children.create(new AccountsRootChildren(commsManager, commsFilter), true)));
|
||||
@ -438,7 +491,8 @@ final public class FiltersPanel extends javax.swing.JPanel {
|
||||
logger.log(Level.SEVERE, "There was an error getting the CommunicationsManager for the current case.", ex);
|
||||
}
|
||||
|
||||
refreshButton.setEnabled(false);
|
||||
needsRefresh = false;
|
||||
validateFilters();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -449,9 +503,9 @@ final public class FiltersPanel extends javax.swing.JPanel {
|
||||
private DeviceFilter getDeviceFilter() {
|
||||
DeviceFilter deviceFilter = new DeviceFilter(
|
||||
devicesMap.entrySet().stream()
|
||||
.filter(entry -> entry.getValue().isSelected())
|
||||
.map(Entry::getKey)
|
||||
.collect(Collectors.toSet()));
|
||||
.filter(entry -> entry.getValue().isSelected())
|
||||
.map(Entry::getKey)
|
||||
.collect(Collectors.toSet()));
|
||||
return deviceFilter;
|
||||
}
|
||||
|
||||
@ -461,9 +515,11 @@ final public class FiltersPanel extends javax.swing.JPanel {
|
||||
* @return an AccountTypeFilter
|
||||
*/
|
||||
private AccountTypeFilter getAccountTypeFilter() {
|
||||
AccountTypeFilter accountTypeFilter = new AccountTypeFilter(accountTypeMap.entrySet().stream()
|
||||
.filter(entry -> entry.getValue().isSelected())
|
||||
.map(entry -> entry.getKey()).collect(Collectors.toSet()));
|
||||
AccountTypeFilter accountTypeFilter = new AccountTypeFilter(
|
||||
accountTypeMap.entrySet().stream()
|
||||
.filter(entry -> entry.getValue().isSelected())
|
||||
.map(entry -> entry.getKey())
|
||||
.collect(Collectors.toSet()));
|
||||
return accountTypeFilter;
|
||||
}
|
||||
|
||||
@ -532,11 +588,13 @@ final public class FiltersPanel extends javax.swing.JPanel {
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private final javax.swing.JPanel accountTypePane = new javax.swing.JPanel();
|
||||
private final javax.swing.JLabel accountTypeRequiredLabel = new javax.swing.JLabel();
|
||||
private final javax.swing.JLabel accountTypesLabel = new javax.swing.JLabel();
|
||||
private final javax.swing.JButton applyFiltersButton = new javax.swing.JButton();
|
||||
private final javax.swing.JButton checkAllAccountTypesButton = new javax.swing.JButton();
|
||||
private final javax.swing.JButton checkAllDevicesButton = new javax.swing.JButton();
|
||||
private final javax.swing.JLabel dateRangeLabel = new javax.swing.JLabel();
|
||||
private final javax.swing.JLabel deviceRequiredLabel = new javax.swing.JLabel();
|
||||
private final javax.swing.JLabel devicesLabel = new javax.swing.JLabel();
|
||||
private final javax.swing.JPanel devicesPane = new javax.swing.JPanel();
|
||||
private final javax.swing.JCheckBox endCheckBox = new javax.swing.JCheckBox();
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Copyright 2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -47,8 +47,10 @@ import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT;
|
||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME;
|
||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_RCVD;
|
||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION;
|
||||
@ -73,6 +75,7 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger LOGGER = Logger.getLogger(MessageContentViewer.class.getName());
|
||||
private static final BlackboardAttribute.Type TSK_ASSOCIATED_TYPE = new BlackboardAttribute.Type(TSK_ASSOCIATED_ARTIFACT);
|
||||
|
||||
private static final int HDR_TAB_INDEX = 0;
|
||||
private static final int TEXT_TAB_INDEX = 1;
|
||||
@ -92,9 +95,10 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont
|
||||
/**
|
||||
* Creates new MessageContentViewer
|
||||
*/
|
||||
@NbBundle.Messages("MessageContentViewer.AtrachmentsPanel.title=Attachments")
|
||||
public MessageContentViewer() {
|
||||
initComponents();
|
||||
drp = DataResultPanel.createInstanceUninitialized("Attachments", "", Node.EMPTY, 0, null);
|
||||
drp = DataResultPanel.createInstanceUninitialized(Bundle.MessageContentViewer_AtrachmentsPanel_title(), "", Node.EMPTY, 0, null);
|
||||
attachmentsScrollPane.setViewportView(drp);
|
||||
msgbodyTabbedPane.setEnabledAt(ATTM_TAB_INDEX, true);
|
||||
|
||||
@ -106,8 +110,8 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont
|
||||
|
||||
drp.open();
|
||||
drpExplorerManager = drp.getExplorerManager();
|
||||
drpExplorerManager.addPropertyChangeListener(evt
|
||||
-> viewInNewWindowButton.setEnabled(drpExplorerManager.getSelectedNodes().length == 1));
|
||||
drpExplorerManager.addPropertyChangeListener(evt ->
|
||||
viewInNewWindowButton.setEnabled(drpExplorerManager.getSelectedNodes().length == 1));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -406,6 +410,20 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the artifact is a keyword hit, use the associated artifact as the
|
||||
* one to show in this viewer
|
||||
*/
|
||||
if (artifact.getArtifactTypeID() == TSK_KEYWORD_HIT.getTypeID()) {
|
||||
try {
|
||||
getAssociatedArtifact(artifact).ifPresent(associatedArtifact -> {
|
||||
artifact = associatedArtifact;
|
||||
});
|
||||
} catch (TskCoreException ex) {
|
||||
LOGGER.log(Level.SEVERE, "error getting associated artifact", ex);
|
||||
}
|
||||
}
|
||||
|
||||
if (artifact.getArtifactTypeID() == TSK_MESSAGE.getTypeID()) {
|
||||
displayMsg();
|
||||
} else if (artifact.getArtifactTypeID() == TSK_EMAIL_MSG.getTypeID()) {
|
||||
@ -415,6 +433,24 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the artifact associated with the given artifact, if there is one.
|
||||
*
|
||||
* @param artifact The artifact to get the associated artifact from. Must
|
||||
* not be null
|
||||
*
|
||||
* @throws TskCoreException If there is a critical error querying the DB.
|
||||
* @return An optional containing the artifact associated with the given
|
||||
* artifact, if there is one.
|
||||
*/
|
||||
private static Optional<BlackboardArtifact> getAssociatedArtifact(final BlackboardArtifact artifact) throws TskCoreException {
|
||||
BlackboardAttribute attribute = artifact.getAttribute(TSK_ASSOCIATED_TYPE);
|
||||
if (attribute != null) {
|
||||
return Optional.of(artifact.getSleuthkitCase().getArtifactByArtifactId(attribute.getValueLong()));
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NbBundle.Messages("MessageContentViewer.title=Message")
|
||||
public String getTitle() {
|
||||
@ -463,10 +499,37 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont
|
||||
|
||||
@Override
|
||||
public boolean isSupported(Node node) {
|
||||
BlackboardArtifact artifact = node.getLookup().lookup(BlackboardArtifact.class);
|
||||
return ((artifact != null)
|
||||
&& ((artifact.getArtifactTypeID() == TSK_EMAIL_MSG.getTypeID())
|
||||
|| (artifact.getArtifactTypeID() == TSK_MESSAGE.getTypeID())));
|
||||
BlackboardArtifact nodeArtifact = node.getLookup().lookup(BlackboardArtifact.class);
|
||||
|
||||
if (nodeArtifact == null) {
|
||||
return false;
|
||||
}
|
||||
//if the artifact is a keyword hit, check if its associated artifact is a message or email.
|
||||
if (nodeArtifact.getArtifactTypeID() == TSK_KEYWORD_HIT.getTypeID()) {
|
||||
try {
|
||||
if (getAssociatedArtifact(nodeArtifact).map(MessageContentViewer::isMessageArtifact).orElse(false)) {
|
||||
return true;
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
LOGGER.log(Level.SEVERE, "error getting associated artifact", ex);
|
||||
}
|
||||
}
|
||||
return isMessageArtifact(nodeArtifact);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the given artifact one that can be shown in this viewer?
|
||||
*
|
||||
* @param nodeArtifact An artifact that might be a message. Must not be
|
||||
* null.
|
||||
*
|
||||
* @return True if the given artifact can be shown as a message in this
|
||||
* viewer.
|
||||
*/
|
||||
private static boolean isMessageArtifact(BlackboardArtifact nodeArtifact) {
|
||||
final int artifactTypeID = nodeArtifact.getArtifactTypeID();
|
||||
return artifactTypeID == TSK_EMAIL_MSG.getTypeID()
|
||||
|| artifactTypeID == TSK_MESSAGE.getTypeID();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -34,6 +34,7 @@ import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.Account;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT;
|
||||
@ -53,6 +54,7 @@ public class ExtractedContentViewer implements DataContentViewer {
|
||||
|
||||
private static final long INVALID_DOCUMENT_ID = 0L;
|
||||
private static final BlackboardAttribute.Type TSK_ASSOCIATED_ARTIFACT_TYPE = new BlackboardAttribute.Type(TSK_ASSOCIATED_ARTIFACT);
|
||||
public static final BlackboardAttribute.Type TSK_ACCOUNT_TYPE = new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE);
|
||||
|
||||
private ExtractedContentPanel panel;
|
||||
private volatile Node currentNode = null;
|
||||
@ -173,14 +175,13 @@ public class ExtractedContentViewer implements DataContentViewer {
|
||||
}
|
||||
}
|
||||
panel.updateControls(currentSource);
|
||||
|
||||
|
||||
String contentName = "";
|
||||
if (content != null) {
|
||||
contentName = content.getName();
|
||||
}
|
||||
setPanel(contentName, sources);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
static private IndexedText getRawArtifactText(Lookup nodeLookup) throws TskCoreException {
|
||||
@ -261,7 +262,7 @@ public class ExtractedContentViewer implements DataContentViewer {
|
||||
|
||||
@Override
|
||||
public void resetComponent() {
|
||||
|
||||
|
||||
panel.resetDisplay();
|
||||
currentNode = null;
|
||||
currentSource = null;
|
||||
@ -274,14 +275,22 @@ public class ExtractedContentViewer implements DataContentViewer {
|
||||
}
|
||||
|
||||
/*
|
||||
* Is there a credit card artifact in the lookup
|
||||
* Is there a credit card or keyword hit artifact in the lookup
|
||||
*/
|
||||
Collection<? extends BlackboardArtifact> artifacts = node.getLookup().lookupAll(BlackboardArtifact.class);
|
||||
if (artifacts != null) {
|
||||
for (BlackboardArtifact art : artifacts) {
|
||||
final int artifactTypeID = art.getArtifactTypeID();
|
||||
if (artifactTypeID == TSK_ACCOUNT.getTypeID()
|
||||
|| artifactTypeID == TSK_KEYWORD_HIT.getTypeID()) {
|
||||
if (artifactTypeID == TSK_ACCOUNT.getTypeID()) {
|
||||
try {
|
||||
BlackboardAttribute attribute = art.getAttribute(TSK_ACCOUNT_TYPE);
|
||||
if (attribute != null && Account.Type.CREDIT_CARD.getTypeName().equals(attribute.getValueString())) {
|
||||
return true;
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error getting TSK_ACCOUNT_TYPE attribute from artifact " + art.getArtifactID(), ex);
|
||||
}
|
||||
} else if (artifactTypeID == TSK_KEYWORD_HIT.getTypeID()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user