diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/IngestJobInfoPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/IngestJobInfoPanel.java index 9faa17f51c..4dcdc5260f 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/IngestJobInfoPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/IngestJobInfoPanel.java @@ -89,8 +89,15 @@ public final class IngestJobInfoPanel extends javax.swing.JPanel { return; } - if (CURRENT_CASE == Case.Events.valueOf(evt.getPropertyName())) { - refresh(); + // Check whether we have a case open or case close event. + if ((CURRENT_CASE == Case.Events.valueOf(evt.getPropertyName()))) { + if (evt.getNewValue() != null) { + // Case open + refresh(); + } else { + // Case close + reset(); + } } }); } @@ -124,7 +131,7 @@ public final class IngestJobInfoPanel extends javax.swing.JPanel { */ private void refresh() { try { - if (Case.isCaseOpen()) { + if (Case.isCaseOpen()) { // Note - this will generally return true when handling a case close event SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase(); this.ingestJobs = skCase.getIngestJobs(); setDataSource(selectedDataSource); @@ -138,6 +145,14 @@ public final class IngestJobInfoPanel extends javax.swing.JPanel { JOptionPane.showMessageDialog(this, Bundle.IngestJobInfoPanel_loadIngestJob_error_text(), Bundle.IngestJobInfoPanel_loadIngestJob_error_title(), JOptionPane.ERROR_MESSAGE); } } + + /** + * Reset the panel. + */ + private void reset() { + this.ingestJobs = new ArrayList<>(); + setDataSource(null); + } @Messages({"IngestJobInfoPanel.IngestJobTableModel.StartTime.header=Start Time", "IngestJobInfoPanel.IngestJobTableModel.EndTime.header=End Time", diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java index 70198bc678..56922c7bfb 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java @@ -52,11 +52,9 @@ import javax.swing.JPanel; import javax.swing.filechooser.FileNameExtensionFilter; import javax.swing.table.TableModel; import javax.swing.table.TableRowSorter; -import org.apache.commons.lang.StringUtils; import org.joda.time.DateTimeZone; import org.joda.time.LocalDateTime; import org.openide.nodes.Node; -import org.openide.util.Exceptions; import org.openide.util.NbBundle.Messages; import org.openide.util.lookup.ServiceProvider; import org.sleuthkit.autopsy.casemodule.Case; @@ -78,7 +76,6 @@ import org.sleuthkit.datamodel.TskException; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskData; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; -import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode; /** * View correlation results from other cases @@ -469,16 +466,11 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi if (bbArtifact != null && CentralRepository.isEnabled()) { ret.addAll(CorrelationAttributeUtil.makeCorrAttrsForCorrelation(bbArtifact)); } - boolean isSupported = false; - try { - isSupported = this.file != null && this.file.getSize() > 0 && isDownloadParentSupported(node); - } catch (TskCoreException ex) { - LOGGER.log(Level.WARNING, ex.getMessage(), ex); - } // we can correlate based on the MD5 if it is enabled - if (isSupported && CentralRepository.isEnabled()) { + if (this.file != null && CentralRepository.isEnabled() && this.file.getSize() > 0) { try { + List artifactTypes = CentralRepository.getInstance().getDefinedCorrelationTypes(); String md5 = this.file.getMd5Hash(); if (md5 != null && !md5.isEmpty() && null != artifactTypes && !artifactTypes.isEmpty()) { @@ -506,7 +498,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi LOGGER.log(Level.SEVERE, "Error connecting to DB", ex); // NON-NLS } // If EamDb not enabled, get the Files default correlation type to allow Other Occurances to be enabled. - } else if (isSupported) { + } else if (this.file != null && this.file.getSize() > 0) { String md5 = this.file.getMd5Hash(); if (md5 != null && !md5.isEmpty()) { try { @@ -525,37 +517,8 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi } } } - return ret; - } - /** - * Private helper method to check if the node is an TSK_WEB_DOWNLOAD or - * TSK_WEB_CACHE artifact and if it is, if the file reflects the parent file - * or the downloaded file. - * - * @param node The node to check support for. - * - * @return False if the node is for a Web Cache or a Web Download artifact, - * and that artifact's content file is it's parent. - * - * @throws TskCoreException Unable to retrieve the parent of the artifact in - * this node. - */ - private boolean isDownloadParentSupported(Node node) throws TskCoreException { - if (node instanceof BlackboardArtifactNode) { - BlackboardArtifact theArtifact = ((BlackboardArtifactNode) node).getArtifact(); - try { - //disable the content viewer when a download or cached file does not exist instead of displaying its parent - if ((theArtifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID() - || theArtifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE.getTypeID()) - && this.file.getId() == theArtifact.getParent().getId()) { - return false; - } - } catch (TskCoreException ex) { - throw new TskCoreException(String.format("Error getting parent of artifact with type %s and objID = %d can not confirm content with name %s and objId = %d is not the parent. Other occurences will not correlate on the file.", theArtifact.getArtifactTypeName(), theArtifact.getObjectID(), this.file.getName(), this.file.getId()), ex); - } - } - return true; + return ret; } @Messages({"DataContentViewerOtherCases.earliestCaseNotAvailable= Not Enabled."}) @@ -738,16 +701,11 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi this.file = this.getAbstractFileFromNode(node); if (CentralRepository.isEnabled()) { return !getCorrelationAttributesFromNode(node).isEmpty(); - } else if (this.file == null || this.file.getSize() <= 0 || StringUtils.isBlank(file.getMd5Hash())) { - return false; + } else { + return this.file != null + && this.file.getSize() > 0 + && ((this.file.getMd5Hash() != null) && (!this.file.getMd5Hash().isEmpty())); } - boolean isSupported = false; - try { - isSupported = isDownloadParentSupported(node); - } catch (TskCoreException ex) { - LOGGER.log(Level.WARNING, ex.getMessage(), ex); - } - return isSupported; } @Override diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoAccount.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoAccount.java index 88c74a4fe8..8d62629363 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoAccount.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoAccount.java @@ -336,7 +336,7 @@ public final class CentralRepoAccount { normalizedAccountIdentifier = accountIdentifier.toLowerCase(); } } catch (CorrelationAttributeNormalizationException ex) { - throw new InvalidAccountIDException("Invalid account identifier", ex); + throw new InvalidAccountIDException(String.format("Account id normaization failed, invalid account identifier %s", accountIdentifier), ex); } return normalizedAccountIdentifier; diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/Bundle.properties b/Core/src/org/sleuthkit/autopsy/communications/relationships/Bundle.properties index 6ecb170c10..32f2bf4849 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/Bundle.properties @@ -28,3 +28,9 @@ SummaryViewer.contactsLabel.text=Book Entries: SummaryViewer.accountCountry.text= SummaryViewer.fileRefPane.border.title=File References in Current Case SummaryViewer.selectAccountFileRefLabel.text= SummaryViewer_FileRefNameColumn_Title=Path +SummaryViewer_Persona_Message= +SummaryViewer_Select_account_for_persona= +SummaryViewer.personaPanel.border.title=Personas +PersonaPanel.personaIDLabel.text=jLabel1 +SummaryPersonaPane.noPersonaLabel.text=No personas found +SummaryPersonaPane.messageLabel.text= +SummaryPersonaPane.createButton.text=Create +PersonaPanel.viewButton.text=View diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/PersonaPanel.form b/Core/src/org/sleuthkit/autopsy/communications/relationships/PersonaPanel.form new file mode 100755 index 0000000000..e76f4fe702 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/PersonaPanel.form @@ -0,0 +1,47 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/PersonaPanel.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/PersonaPanel.java new file mode 100755 index 0000000000..b6968f9cd2 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/PersonaPanel.java @@ -0,0 +1,115 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2020 Basis Technology Corp. + * Contact: carrier sleuthkit 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 obt ain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.communications.relationships; + +import java.awt.Dimension; +import javax.swing.JButton; +import org.sleuthkit.autopsy.centralrepository.datamodel.Persona; + +/** + * + * Panel to show a single persona with a button for viewing persona details. + */ +public class PersonaPanel extends javax.swing.JPanel { + + private static final long serialVersionUID = 1L; + private final Persona persona; + + /** + * Creates new form PersonaPanel + */ + PersonaPanel(Persona persona) { + initComponents(); + this.persona = persona; + personaIDLabel.setText(persona.getName()); + } + + /** + * Returns the persona displayed by this panel. + * + * @return + */ + Persona getPersona() { + return persona; + } + + /** + * Returns the preferred width for the given persona label. + * + * @return + */ + int getPersonaLabelPreferedWidth() { + return personaIDLabel.getPreferredSize().width; + } + + /** + * Sets the preferred width for the persona name label. + * + * @param width + */ + void setPersonalLabelPreferredWidth(int width) { + Dimension currentDim = personaIDLabel.getPreferredSize(); + personaIDLabel.setPreferredSize(new Dimension(Math.max(currentDim.width, width), currentDim.height)); + } + + /** + * Returns the View button for this panel. + * + * @return + */ + JButton getViewButton() { + return viewButton; + } + + /** + * 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") + // //GEN-BEGIN:initComponents + private void initComponents() { + java.awt.GridBagConstraints gridBagConstraints; + + personaIDLabel = new javax.swing.JLabel(); + viewButton = new javax.swing.JButton(); + + setLayout(new java.awt.GridBagLayout()); + + org.openide.awt.Mnemonics.setLocalizedText(personaIDLabel, org.openide.util.NbBundle.getMessage(PersonaPanel.class, "PersonaPanel.personaIDLabel.text")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.insets = new java.awt.Insets(0, 5, 0, 0); + add(personaIDLabel, gridBagConstraints); + + org.openide.awt.Mnemonics.setLocalizedText(viewButton, org.openide.util.NbBundle.getMessage(PersonaPanel.class, "PersonaPanel.viewButton.text")); // NOI18N + viewButton.setMargin(new java.awt.Insets(0, 5, 0, 5)); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(0, 5, 0, 0); + add(viewButton, gridBagConstraints); + }// //GEN-END:initComponents + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel personaIDLabel; + private javax.swing.JButton viewButton; + // End of variables declaration//GEN-END:variables +} diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/SummaryPanelWorker.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/SummaryPanelWorker.java new file mode 100755 index 0000000000..bc6157f4cf --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/SummaryPanelWorker.java @@ -0,0 +1,146 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2020 Basis Technology Corp. + * Contact: carrier sleuthkit 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 obt ain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.communications.relationships; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.logging.Level; +import javax.swing.SwingWorker; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoAccount; +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.coreutils.Logger; +import org.sleuthkit.datamodel.Account; +import org.sleuthkit.datamodel.AccountFileInstance; +import org.sleuthkit.datamodel.InvalidAccountIDException; + +/** + * Runnable SwingWorker for gather the data that the Summary panel needs. + */ +class SummaryPanelWorker extends SwingWorker { + + private final static Logger logger = Logger.getLogger(SummaryPanelWorker.class.getName()); + + private final Account account; + + // Construct a instance + SummaryPanelWorker(Account account) { + this.account = account; + } + + /** + * Returns the account the worker is gathering data for. + * + * @return + */ + Account getAccount() { + return account; + } + + @Override + protected SummaryWorkerResults doInBackground() throws Exception { + CentralRepoAccount crAccount = null; + List stringList = new ArrayList<>(); + List accountFileInstanceList = Case.getCurrentCase().getSleuthkitCase().getCommunicationsManager().getAccountFileInstances(account); + for (AccountFileInstance instance : accountFileInstanceList) { + stringList.add(instance.getFile().getUniquePath()); + } + + List personaList = new ArrayList<>(); + if (CentralRepository.isEnabled()) { + Collection personaAccountList = PersonaAccount.getPersonaAccountsForAccount(account); + PersonaAccount.getPersonaAccountsForAccount(account); + + for (PersonaAccount pAccount : personaAccountList) { + personaList.add(pAccount.getPersona()); + } + + try { + crAccount = CentralRepository.getInstance().getAccount(CentralRepository.getInstance().getAccountTypeByName(account.getAccountType().getTypeName()), account.getTypeSpecificID()); + } catch (InvalidAccountIDException unused) { + // This was probably caused to a phone number not making + // threw the normalization. + logger.log(Level.WARNING, String.format("Exception thrown from CR getAccount for account %s (%d)", account.getTypeSpecificID(), account.getAccountID())); + } + } + + return new SummaryWorkerResults(stringList, personaList, crAccount); + } + + /** + * Wraps the results of the worker for easy of returning and usage by the + * SummaryViewer. + */ + final static class SummaryWorkerResults { + + private final List accountFileInstancePaths; + private final List personaList; + private final CentralRepoAccount centralRepoAccount; + + /** + * Constructor. + * + * @param accountFileInstancePaths List of instance paths. + * @param personaList List of personas for the account + * @param centralRepoAccount CentralRepoAccount for the given + * account, maybe null if CR is not + * enabled. + */ + SummaryWorkerResults(List accountFileInstancePaths, List personaList, CentralRepoAccount centralRepoAccount) { + this.accountFileInstancePaths = accountFileInstancePaths; + this.personaList = personaList; + this.centralRepoAccount = centralRepoAccount; + } + + /** + * Returns the list of instance paths for the account given to the + * worker. + * + * @return + */ + List getPaths() { + return accountFileInstancePaths; + } + + /** + * Returns the list of personas found for the account given to the + * worker. This list maybe empty if none were found or cr is not + * enabled. + * + * @return + */ + List getPersonaList() { + return personaList; + } + + /** + * Return the cr account for the account given to the worker. This maybe + * null if the cr was not enabled. + * + * @return + */ + CentralRepoAccount getCRAccount() { + return centralRepoAccount; + } + } + +} diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/SummaryPersonaPane.form b/Core/src/org/sleuthkit/autopsy/communications/relationships/SummaryPersonaPane.form new file mode 100755 index 0000000000..2fd6f636be --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/SummaryPersonaPane.form @@ -0,0 +1,104 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/SummaryPersonaPane.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/SummaryPersonaPane.java new file mode 100755 index 0000000000..9c07a050ea --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/SummaryPersonaPane.java @@ -0,0 +1,295 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2020 Basis Technology Corp. + * Contact: carrier sleuthkit 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 obt ain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.communications.relationships; + +import java.awt.CardLayout; +import java.awt.Component; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; +import javax.swing.Box; +import javax.swing.JButton; +import javax.swing.JPanel; +import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoAccount; +import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException; +import org.sleuthkit.autopsy.centralrepository.datamodel.Persona; +import org.sleuthkit.autopsy.centralrepository.datamodel.PersonaAccount; +import org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsDialog; +import org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsDialogCallback; +import org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsMode; +import org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsPanel; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.datamodel.Account; + +/** + * Panel to show the Personas for a given account. That is apart SummaryViewer. + */ +public final class SummaryPersonaPane extends javax.swing.JPanel { + + private static final long serialVersionUID = 1L; + + private final static Logger logger = Logger.getLogger(SummaryPersonaPane.class.getName()); + + private final Map personaMap; + private final ViewButtonHandler viewButtonHandler = new ViewButtonHandler(); + private CentralRepoAccount currentCRAccount = null; + private Account currentAccount = null; + + /** + * Creates new form SummaryPersonaPane + */ + SummaryPersonaPane() { + initComponents(); + personaScrollPane.setViewportView(new JPanel()); + + personaMap = new HashMap<>(); + } + + /** + * Clear the persona list. + */ + void clearList() { + personaScrollPane.setViewportView(new JPanel()); + personaMap.clear(); + } + + /** + * Show the message panel. + */ + void showMessagePanel() { + CardLayout layout = (CardLayout) getLayout(); + layout.show(this, "message"); + } + + /** + * Set the message that appears when the message panel is visible. + * + * @param message Message to show. + */ + void setMessage(String message) { + messageLabel.setText(message); + } + + /** + * Update the list of personas to the new given list. + * + * @param personaList New list of personas to show + */ + void updatePersonaList(Account account, CentralRepoAccount crAccount, List personaList) { + JPanel panel = new JPanel(); + currentCRAccount = crAccount; + currentAccount = account; + + CardLayout layout = (CardLayout) getLayout(); + if (personaList.isEmpty()) { + layout.show(this, "create"); + } else { + panel.setLayout(new GridLayout(personaList.size() + 1, 1)); + int maxWidth = 0; + List panelList = new ArrayList<>(); + for (Persona persona : personaList) { + PersonaPanel personaPanel = new PersonaPanel(persona); + JButton viewButton = personaPanel.getViewButton(); + panel.add(personaPanel); + + personaMap.put(viewButton, persona); + viewButton.addActionListener(viewButtonHandler); + + panelList.add(personaPanel); + maxWidth = Math.max(personaPanel.getPersonaLabelPreferedWidth(), maxWidth); + } + + //Set the preferred width of the labeles to the buttons line up. + if (panelList.size() > 1) { + for (PersonaPanel ppanel : panelList) { + ppanel.setPersonalLabelPreferredWidth(maxWidth); + } + } + + panel.add(Box.createVerticalGlue()); + personaScrollPane.setViewportView(panel); + layout.show(this, "persona"); + } + + } + + /** + * ActionListener to handle the launching of the view dialog for the given + * persona. + */ + final private class ViewButtonHandler implements ActionListener { + + @Override + public void actionPerformed(ActionEvent e) { + Persona persona = personaMap.get((Component) e.getSource()); + new PersonaDetailsDialog(SummaryPersonaPane.this, + PersonaDetailsMode.VIEW, persona, new PersonaViewCallbackImpl()); + } + } + + /** + * Callback method for the view mode of the PersonaDetailsDialog + */ + private final class PersonaViewCallbackImpl implements PersonaDetailsDialogCallback { + + @Override + public void callback(Persona persona) { + // nothing to do + } + } + + /** + * Callback class to handle the creation of a new person for the given + * account + */ + private final class PersonaCreateCallbackImpl implements PersonaDetailsDialogCallback { + + @Override + public void callback(Persona persona) { + if (persona != null) { + List list = new ArrayList<>(); + list.add(persona); + + CentralRepoAccount crAccount = null; + Collection personaAccounts = null; + try { + personaAccounts = persona.getPersonaAccounts(); + } catch (CentralRepoException ex) { + logger.log(Level.WARNING, String.format("Failed to get cr account from person %s (%d)", persona.getName(), persona.getId()), ex); + } + + if (personaAccounts != null) { + Iterator iterator = personaAccounts.iterator(); + if (iterator.hasNext()) { + crAccount = iterator.next().getAccount(); + } + } + + updatePersonaList(currentAccount, crAccount, list); + } + } + } + + /** + * 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") + // //GEN-BEGIN:initComponents + private void initComponents() { + java.awt.GridBagConstraints gridBagConstraints; + + personaScrollPane = new javax.swing.JScrollPane(); + messagePane = new javax.swing.JPanel(); + messageLabel = new javax.swing.JLabel(); + createPersonaPanel = new javax.swing.JPanel(); + noPersonaLabel = new javax.swing.JLabel(); + createButton = new javax.swing.JButton(); + + setLayout(new java.awt.CardLayout()); + + personaScrollPane.setBorder(null); + add(personaScrollPane, "persona"); + + messagePane.setLayout(new java.awt.GridBagLayout()); + + org.openide.awt.Mnemonics.setLocalizedText(messageLabel, org.openide.util.NbBundle.getMessage(SummaryPersonaPane.class, "SummaryPersonaPane.messageLabel.text")); // NOI18N + messageLabel.setEnabled(false); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.weighty = 1.0; + messagePane.add(messageLabel, gridBagConstraints); + + add(messagePane, "message"); + + createPersonaPanel.setPreferredSize(new java.awt.Dimension(200, 100)); + createPersonaPanel.setLayout(new java.awt.GridBagLayout()); + + org.openide.awt.Mnemonics.setLocalizedText(noPersonaLabel, org.openide.util.NbBundle.getMessage(SummaryPersonaPane.class, "SummaryPersonaPane.noPersonaLabel.text")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weighty = 1.0; + gridBagConstraints.insets = new java.awt.Insets(7, 5, 0, 0); + createPersonaPanel.add(noPersonaLabel, gridBagConstraints); + + org.openide.awt.Mnemonics.setLocalizedText(createButton, org.openide.util.NbBundle.getMessage(SummaryPersonaPane.class, "SummaryPersonaPane.createButton.text")); // NOI18N + createButton.setMargin(new java.awt.Insets(0, 5, 0, 5)); + createButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + createButtonActionPerformed(evt); + } + }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 0; + gridBagConstraints.gridheight = 2; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + gridBagConstraints.insets = new java.awt.Insets(5, 5, 0, 0); + createPersonaPanel.add(createButton, gridBagConstraints); + + add(createPersonaPanel, "create"); + }// //GEN-END:initComponents + + @NbBundle.Messages({ + "# {0} - accountIdentifer", + "SummaryPersonaPane_not_account_in_cr=Unable to find an account with identifier {0} in the Central Repository." + }) + + private void createButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_createButtonActionPerformed + PersonaDetailsDialog createPersonaDialog = new PersonaDetailsDialog(SummaryPersonaPane.this, + PersonaDetailsMode.CREATE, null, new PersonaCreateCallbackImpl(), false); + + // Pre populate the persona name and accounts if we have them. + PersonaDetailsPanel personaPanel = createPersonaDialog.getDetailsPanel(); + if (currentCRAccount != null) { + personaPanel.addAccount(currentCRAccount, "", Persona.Confidence.HIGH); + + } else { + createPersonaDialog.setStartupPopupMessage(Bundle.SummaryPersonaPane_not_account_in_cr(currentAccount.getTypeSpecificID())); + } + personaPanel.setPersonaName(currentAccount.getTypeSpecificID()); + // display the dialog now + createPersonaDialog.display(); + }//GEN-LAST:event_createButtonActionPerformed + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton createButton; + private javax.swing.JPanel createPersonaPanel; + private javax.swing.JLabel messageLabel; + private javax.swing.JPanel messagePane; + private javax.swing.JLabel noPersonaLabel; + private javax.swing.JScrollPane personaScrollPane; + // End of variables declaration//GEN-END:variables +} diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/SummaryViewer.form b/Core/src/org/sleuthkit/autopsy/communications/relationships/SummaryViewer.form index ec718e9bd1..271f9ab901 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/SummaryViewer.form +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/SummaryViewer.form @@ -265,7 +265,7 @@ - + @@ -281,7 +281,7 @@ - + @@ -363,5 +363,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/SummaryViewer.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/SummaryViewer.java index 94fb1bca86..4cf917eac1 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/SummaryViewer.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/SummaryViewer.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2019 Basis Technology Corp. + * Copyright 2019-2020 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,13 +19,11 @@ package org.sleuthkit.autopsy.communications.relationships; import java.awt.CardLayout; -import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.logging.Level; import javax.swing.DefaultListModel; import javax.swing.JPanel; -import javax.swing.SwingWorker; import org.netbeans.swing.outline.DefaultOutlineModel; import org.netbeans.swing.outline.Outline; import org.openide.explorer.view.OutlineView; @@ -33,11 +31,10 @@ import org.openide.nodes.AbstractNode; import org.openide.nodes.Children; import org.openide.util.Lookup; import org.openide.util.NbBundle.Messages; -import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.datamodel.Account; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; +import org.sleuthkit.autopsy.centralrepository.datamodel.Persona; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.datamodel.AccountFileInstance; /** * Account Summary View Panel. This panel shows a list of various counts related @@ -47,6 +44,8 @@ import org.sleuthkit.datamodel.AccountFileInstance; */ public class SummaryViewer extends javax.swing.JPanel implements RelationshipsViewer { + private static final long serialVersionUID = 1L; + private final Lookup lookup; private final DefaultListModel fileRefListModel; @@ -62,7 +61,8 @@ public class SummaryViewer extends javax.swing.JPanel implements RelationshipsVi "SummaryViewer_Device_Account_Description=This account was referenced by a device in the case.", "SummaryViewer_Account_Description=This account represents a device in the case.", "SummaryViewer_Account_Description_MuliSelect=Summary information is not available when multiple accounts are selected.", - "SummaryViewer_Country_Code=Country: " + "SummaryViewer_Country_Code=Country: ", + "SummaryViewer_Select_account_for_persona=