mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-12 16:06:15 +00:00
Added contact information to cvt tooltips and MessageContentViewer
This commit is contained in:
parent
972f736a9d
commit
c151a58974
@ -61,6 +61,7 @@ DefaultArtifactContentViewer.copyMenuItem.text=Copy
|
||||
DefaultArtifactContentViewer.selectAllMenuItem.text=Select All
|
||||
MessageAccountPanel_button_create_label=Create
|
||||
MessageAccountPanel_button_view_label=View
|
||||
MessageAccountPanel_contact_label=Contact:
|
||||
MessageAccountPanel_no_matches=No matches found.
|
||||
MessageAccountPanel_persona_label=Persona:
|
||||
MessageAccountPanel_unknown_label=Unknown
|
||||
|
@ -16,7 +16,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.sleuthkit.autopsy.contentviewers.artifactviewers;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
@ -39,6 +38,7 @@ import javax.swing.SwingUtilities;
|
||||
import javax.swing.SwingWorker;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.Persona;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.PersonaAccount;
|
||||
import org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsDialog;
|
||||
@ -46,8 +46,10 @@ import org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsDialogCallb
|
||||
import org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsMode;
|
||||
import org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsPanel;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.guiutils.ContactCache;
|
||||
import org.sleuthkit.datamodel.Account;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.CommunicationsManager;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
@ -113,13 +115,24 @@ final class MessageAccountPanel extends JPanel {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
Collection<PersonaAccount> personAccounts = PersonaAccount.getPersonaAccountsForAccount(account);
|
||||
if (personAccounts != null && !personAccounts.isEmpty()) {
|
||||
for (PersonaAccount personaAccount : PersonaAccount.getPersonaAccountsForAccount(account)) {
|
||||
dataList.add(new AccountContainer(account, personaAccount));
|
||||
List<BlackboardArtifact> contactList = ContactCache.getContacts(account);
|
||||
BlackboardArtifact contact = null;
|
||||
|
||||
if (contactList != null && !contactList.isEmpty()) {
|
||||
contact = contactList.get(0);
|
||||
}
|
||||
|
||||
if (CentralRepository.isEnabled()) {
|
||||
Collection<PersonaAccount> personAccounts = PersonaAccount.getPersonaAccountsForAccount(account);
|
||||
if (personAccounts != null && !personAccounts.isEmpty()) {
|
||||
for (PersonaAccount personaAccount : PersonaAccount.getPersonaAccountsForAccount(account)) {
|
||||
dataList.add(new AccountContainer(account, personaAccount, contact));
|
||||
}
|
||||
} else {
|
||||
dataList.add(new AccountContainer(account, null, contact));
|
||||
}
|
||||
} else {
|
||||
dataList.add(new AccountContainer(account, null));
|
||||
dataList.add(new AccountContainer(account, null, contact));
|
||||
}
|
||||
}
|
||||
|
||||
@ -127,8 +140,7 @@ final class MessageAccountPanel extends JPanel {
|
||||
}
|
||||
|
||||
@Messages({
|
||||
"MessageAccountPanel_no_matches=No matches found.",
|
||||
})
|
||||
"MessageAccountPanel_no_matches=No matches found.",})
|
||||
@Override
|
||||
protected void done() {
|
||||
try {
|
||||
@ -199,6 +211,7 @@ final class MessageAccountPanel extends JPanel {
|
||||
for (AccountContainer o : data) {
|
||||
group.addGap(5)
|
||||
.addComponent(o.getAccountLabel())
|
||||
.addGroup(o.getContactLineVerticalGroup(layout))
|
||||
.addGroup(o.getPersonLineVerticalGroup(layout));
|
||||
}
|
||||
|
||||
@ -234,6 +247,7 @@ final class MessageAccountPanel extends JPanel {
|
||||
group.addGap(10);
|
||||
for (AccountContainer o : data) {
|
||||
pgroup.addGroup(o.getPersonaSequentialGroup(layout));
|
||||
pgroup.addGroup(o.getContactSequentialGroup(layout));
|
||||
}
|
||||
group.addGap(10)
|
||||
.addGroup(pgroup)
|
||||
@ -253,10 +267,13 @@ final class MessageAccountPanel extends JPanel {
|
||||
|
||||
private final Account account;
|
||||
private Persona persona = null;
|
||||
private final String contactName;
|
||||
|
||||
private JLabel accountLabel;
|
||||
private JLabel personaHeader;
|
||||
private JLabel personaDisplayName;
|
||||
private JLabel contactHeader;
|
||||
private JLabel contactDisplayName;
|
||||
private JButton button;
|
||||
|
||||
/**
|
||||
@ -265,16 +282,22 @@ final class MessageAccountPanel extends JPanel {
|
||||
* @param account
|
||||
* @param personaAccount
|
||||
*/
|
||||
AccountContainer(Account account, PersonaAccount personaAccount) {
|
||||
AccountContainer(Account account, PersonaAccount personaAccount, BlackboardArtifact contactArtifact) throws TskCoreException {
|
||||
if (contactArtifact != null && contactArtifact.getArtifactTypeID() != BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT.getTypeID()) {
|
||||
throw new IllegalArgumentException("Failed to create AccountContainer object, passed in artifact was not a TSK_CONTACT");
|
||||
}
|
||||
|
||||
this.account = account;
|
||||
this.persona = personaAccount != null ? personaAccount.getPersona() : null;
|
||||
this.contactName = getNameFromContactArtifact(contactArtifact);
|
||||
}
|
||||
|
||||
@Messages({
|
||||
"MessageAccountPanel_persona_label=Persona:",
|
||||
"MessageAccountPanel_unknown_label=Unknown",
|
||||
"MessageAccountPanel_button_view_label=View",
|
||||
"MessageAccountPanel_button_create_label=Create"
|
||||
"MessageAccountPanel_button_create_label=Create",
|
||||
"MessageAccountPanel_contact_label=Contact:"
|
||||
})
|
||||
/**
|
||||
* Swing components will not be initialized until this method is called.
|
||||
@ -282,16 +305,29 @@ final class MessageAccountPanel extends JPanel {
|
||||
private void initalizeSwingControls() {
|
||||
accountLabel = new JLabel();
|
||||
personaHeader = new JLabel(Bundle.MessageAccountPanel_persona_label());
|
||||
contactHeader = new JLabel(Bundle.MessageAccountPanel_contact_label());
|
||||
personaDisplayName = new JLabel();
|
||||
contactDisplayName = new JLabel();
|
||||
button = new JButton();
|
||||
button.addActionListener(new PersonaButtonListener(this));
|
||||
|
||||
accountLabel.setText(account.getTypeSpecificID());
|
||||
|
||||
contactDisplayName.setText(contactName);
|
||||
personaDisplayName.setText(persona != null ? persona.getName() : Bundle.MessageAccountPanel_unknown_label());
|
||||
button.setText(persona != null ? Bundle.MessageAccountPanel_button_view_label() : Bundle.MessageAccountPanel_button_create_label());
|
||||
}
|
||||
|
||||
private String getNameFromContactArtifact(BlackboardArtifact contactArtifact) throws TskCoreException {
|
||||
if (contactArtifact != null) {
|
||||
BlackboardAttribute attribute = contactArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME));
|
||||
if (attribute != null) {
|
||||
return attribute.getValueString();
|
||||
}
|
||||
}
|
||||
|
||||
return Bundle.MessageAccountPanel_unknown_label();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new persona for this object and update the controls.
|
||||
*
|
||||
@ -366,6 +402,17 @@ final class MessageAccountPanel extends JPanel {
|
||||
return group;
|
||||
}
|
||||
|
||||
private SequentialGroup getContactSequentialGroup(GroupLayout layout) {
|
||||
SequentialGroup group = layout.createSequentialGroup();
|
||||
|
||||
group
|
||||
.addComponent(contactHeader)
|
||||
.addPreferredGap(ComponentPlacement.RELATED)
|
||||
.addComponent(contactDisplayName);
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the vertical layout code for the persona line.
|
||||
*
|
||||
@ -379,6 +426,12 @@ final class MessageAccountPanel extends JPanel {
|
||||
.addComponent(personaDisplayName)
|
||||
.addComponent(button);
|
||||
}
|
||||
|
||||
private ParallelGroup getContactLineVerticalGroup(GroupLayout layout) {
|
||||
return layout.createParallelGroup(Alignment.BASELINE)
|
||||
.addComponent(contactHeader)
|
||||
.addComponent(contactDisplayName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -447,10 +447,8 @@ public class MessageArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
resetComponent();
|
||||
}
|
||||
|
||||
msgbodyTabbedPane.setEnabledAt(ACCT_TAB_INDEX, CentralRepository.isEnabled());
|
||||
if(CentralRepository.isEnabled()) {
|
||||
accountsPanel.setArtifact(artifact);
|
||||
}
|
||||
msgbodyTabbedPane.setEnabledAt(ACCT_TAB_INDEX, true);
|
||||
accountsPanel.setArtifact(artifact);
|
||||
}
|
||||
|
||||
/**
|
||||
|
160
Core/src/org/sleuthkit/autopsy/guiutils/ContactCache.java
Executable file
160
Core/src/org/sleuthkit/autopsy/guiutils/ContactCache.java
Executable file
@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2020 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.guiutils;
|
||||
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
import static org.sleuthkit.autopsy.ingest.IngestManager.IngestModuleEvent.DATA_ADDED;
|
||||
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
|
||||
import org.sleuthkit.datamodel.Account;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
* A singleton cache of the Contact artifacts for accounts. The map of account
|
||||
* unique ids to list of contact artifacts is stored in a LoadingCache which
|
||||
* expires after 10 of non-use.
|
||||
*
|
||||
*/
|
||||
public final class ContactCache {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(ContactCache.class.getName());
|
||||
|
||||
private static ContactCache instance;
|
||||
|
||||
private final LoadingCache<String, Map<String, List<BlackboardArtifact>>> accountMap;
|
||||
|
||||
/**
|
||||
* Returns the list of Contacts for the given Account.
|
||||
*
|
||||
* @param account Account instance.
|
||||
*
|
||||
* @return List of TSK_CONTACT artifacts that references the given Account.
|
||||
* An empty list is returned if no contacts are found.
|
||||
*
|
||||
* @throws ExecutionException
|
||||
*/
|
||||
public static synchronized List<BlackboardArtifact> getContacts(Account account) throws ExecutionException {
|
||||
return getInstance().accountMap.get("realMap").get(account.getTypeSpecificID());
|
||||
}
|
||||
|
||||
/**
|
||||
* Force the cache to invalidate all entries.
|
||||
*/
|
||||
static synchronized void invalidateCache() {
|
||||
getInstance().accountMap.invalidateAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new instance.
|
||||
*/
|
||||
private ContactCache() {
|
||||
|
||||
accountMap = CacheBuilder.newBuilder().expireAfterAccess(10, TimeUnit.MINUTES).build(
|
||||
new CacheLoader<String, Map<String, List<BlackboardArtifact>>>() {
|
||||
@Override
|
||||
public Map<String, List<BlackboardArtifact>> load(String key) {
|
||||
try {
|
||||
return buildMap();
|
||||
} catch (SQLException | TskCoreException ex) {
|
||||
logger.log(Level.WARNING, "Failed to build account to contact map", ex);
|
||||
}
|
||||
return new HashMap<>(); // Return an empty map if there is an exception to avoid NPE and continual trying.
|
||||
}
|
||||
});
|
||||
|
||||
PropertyChangeListener ingestListener = pce -> {
|
||||
String eventType = pce.getPropertyName();
|
||||
if (eventType.equals(DATA_ADDED.toString())) {
|
||||
ModuleDataEvent eventData = (ModuleDataEvent) pce.getOldValue();
|
||||
if (eventData.getBlackboardArtifactType().getTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT.getTypeID()) {
|
||||
invalidateCache();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
IngestManager.getInstance().addIngestModuleEventListener(EnumSet.of(DATA_ADDED), ingestListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the singleton instance of the cache object.
|
||||
*
|
||||
* @return AccountCache instance.
|
||||
*/
|
||||
private static synchronized ContactCache getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new ContactCache();
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the map of account IDs to contacts that reference them.
|
||||
*
|
||||
* @return A map of account IDs to contact artifacts.
|
||||
*
|
||||
* @throws TskCoreException
|
||||
* @throws SQLException
|
||||
*/
|
||||
private Map<String, List<BlackboardArtifact>> buildMap() throws TskCoreException, SQLException {
|
||||
Map<String, List<BlackboardArtifact>> acctMap = new HashMap<>();
|
||||
List<BlackboardArtifact> contactList = Case.getCurrentCase().getSleuthkitCase().getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT);
|
||||
|
||||
for(BlackboardArtifact contactArtifact: contactList) {
|
||||
List<BlackboardAttribute> contactAttributes = contactArtifact.getAttributes();
|
||||
for(BlackboardAttribute attribute: contactAttributes) {
|
||||
String typeName = attribute.getAttributeType().getTypeName();
|
||||
|
||||
if(typeName.startsWith("TSK_EMAIL")
|
||||
|| typeName.startsWith("TSK_PHONE")
|
||||
|| typeName.startsWith("TSK_NAME")
|
||||
|| typeName.startsWith("TSK_ID")) {
|
||||
String accountID = attribute.getValueString();
|
||||
List<BlackboardArtifact> artifactList = acctMap.get(accountID);
|
||||
if(artifactList == null) {
|
||||
artifactList = new ArrayList<>();
|
||||
acctMap.put(accountID, artifactList);
|
||||
}
|
||||
if(!artifactList.contains(contactArtifact)) {
|
||||
artifactList.add(contactArtifact);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return acctMap;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user