mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-19 11:07:43 +00:00
Merge branch 'develop' of github.com:sleuthkit/autopsy into 6412-updatedDialogs
This commit is contained in:
commit
2b144413c6
@ -53,7 +53,7 @@ public interface CentralRepository {
|
||||
case SQLITE:
|
||||
return SqliteCentralRepo.getInstance();
|
||||
default:
|
||||
return null;
|
||||
throw new CentralRepoException("Failed to get CentralRepository instance, Central Repositiory is not enabled.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -329,7 +329,7 @@ public class Persona {
|
||||
String deleteSQL = "UPDATE personas SET status_id = " + PersonaStatus.DELETED.status_id + " WHERE id = " + this.id;
|
||||
CentralRepository cr = CentralRepository.getInstance();
|
||||
if (cr != null) {
|
||||
cr.executeDeleteSQL(deleteSQL);
|
||||
cr.executeUpdateSQL(deleteSQL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -127,16 +127,12 @@ public class PersonaAccount {
|
||||
* @param confidence Confidence level.
|
||||
*
|
||||
* @return PersonaAccount
|
||||
*
|
||||
* @throws CentralRepoException If there is an error in creating the
|
||||
* account.
|
||||
*/
|
||||
static PersonaAccount addPersonaAccount(Persona persona, CentralRepoAccount account, String justification, Persona.Confidence confidence) throws CentralRepoException {
|
||||
CentralRepository cr = CentralRepository.getInstance();
|
||||
|
||||
if(cr == null) {
|
||||
throw new CentralRepoException("Failed to add Persona, Central Repository is not enable");
|
||||
}
|
||||
|
||||
CentralRepoExaminer currentExaminer = cr.getOrInsertExaminer(System.getProperty("user.name"));
|
||||
|
||||
Instant instant = Instant.now();
|
||||
@ -151,7 +147,7 @@ public class PersonaAccount {
|
||||
+ currentExaminer.getId()
|
||||
+ ")";
|
||||
|
||||
CentralRepository.getInstance().executeInsertSQL(insertClause);
|
||||
cr.executeInsertSQL(insertClause);
|
||||
|
||||
String queryClause = PERSONA_ACCOUNTS_QUERY_CLAUSE
|
||||
+ "WHERE persona_id = " + persona.getId()
|
||||
@ -249,21 +245,15 @@ public class PersonaAccount {
|
||||
* persona_account.
|
||||
*/
|
||||
static Collection<PersonaAccount> getPersonaAccountsForPersona(long personaId) throws CentralRepoException {
|
||||
CentralRepository cr = CentralRepository.getInstance();
|
||||
|
||||
if (cr != null) {
|
||||
String queryClause = PERSONA_ACCOUNTS_QUERY_CLAUSE
|
||||
+ " WHERE persona_accounts.persona_id = " + personaId;
|
||||
|
||||
PersonaAccountsQueryCallback queryCallback = new PersonaAccountsQueryCallback();
|
||||
cr.executeSelectSQL(queryClause, queryCallback);
|
||||
CentralRepository.getInstance().executeSelectSQL(queryClause, queryCallback);
|
||||
|
||||
return queryCallback.getPersonaAccountsList();
|
||||
}
|
||||
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all the Persona for the specified Account.
|
||||
*
|
||||
@ -279,18 +269,12 @@ public class PersonaAccount {
|
||||
+ " WHERE persona_accounts.account_id = " + accountId
|
||||
+ " AND personas.status_id != " + Persona.PersonaStatus.DELETED.getStatusId();
|
||||
|
||||
CentralRepository cr = CentralRepository.getInstance();
|
||||
|
||||
if (cr != null) {
|
||||
PersonaAccountsQueryCallback queryCallback = new PersonaAccountsQueryCallback();
|
||||
cr.executeSelectSQL(queryClause, queryCallback);
|
||||
CentralRepository.getInstance().executeSelectSQL(queryClause, queryCallback);
|
||||
|
||||
return queryCallback.getPersonaAccountsList();
|
||||
}
|
||||
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all the Persona associated with all the accounts matching the given
|
||||
* account identifier substring.
|
||||
@ -308,17 +292,12 @@ public class PersonaAccount {
|
||||
+ " WHERE LOWER(accounts.account_unique_identifier) LIKE LOWER('%" + accountIdentifierSubstring + "%')"
|
||||
+ " AND personas.status_id != " + Persona.PersonaStatus.DELETED.getStatusId();
|
||||
|
||||
CentralRepository cr = CentralRepository.getInstance();
|
||||
if (cr != null) {
|
||||
PersonaAccountsQueryCallback queryCallback = new PersonaAccountsQueryCallback();
|
||||
cr.executeSelectSQL(queryClause, queryCallback);
|
||||
CentralRepository.getInstance().executeSelectSQL(queryClause, queryCallback);
|
||||
|
||||
return queryCallback.getPersonaAccountsList();
|
||||
}
|
||||
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all the Persona associated with the given account.
|
||||
*
|
||||
@ -335,14 +314,10 @@ public class PersonaAccount {
|
||||
+ " AND type_name = '" + account.getAccountType().getTypeName() + "' "
|
||||
+ " AND personas.status_id != " + Persona.PersonaStatus.DELETED.getStatusId();
|
||||
|
||||
CentralRepository cr = CentralRepository.getInstance();
|
||||
if (cr != null) {
|
||||
PersonaAccountsQueryCallback queryCallback = new PersonaAccountsQueryCallback();
|
||||
cr.executeSelectSQL(queryClause, queryCallback);
|
||||
CentralRepository.getInstance().executeSelectSQL(queryClause, queryCallback);
|
||||
return queryCallback.getPersonaAccountsList();
|
||||
}
|
||||
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -354,14 +329,8 @@ public class PersonaAccount {
|
||||
* account.
|
||||
*/
|
||||
static void removePersonaAccount(long id) throws CentralRepoException {
|
||||
CentralRepository cr = CentralRepository.getInstance();
|
||||
|
||||
if(cr == null) {
|
||||
throw new CentralRepoException("Failed to remove persona account, Central Repo is not enabled");
|
||||
}
|
||||
|
||||
String deleteClause = " DELETE FROM persona_accounts WHERE id = " + id;
|
||||
cr.executeDeleteSQL(deleteClause);
|
||||
CentralRepository.getInstance().executeDeleteSQL(deleteClause);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -373,14 +342,8 @@ public class PersonaAccount {
|
||||
* account.
|
||||
*/
|
||||
static void modifyPersonaAccount(long id, Persona.Confidence confidence, String justification) throws CentralRepoException {
|
||||
CentralRepository cr = CentralRepository.getInstance();
|
||||
|
||||
if (cr == null) {
|
||||
throw new CentralRepoException("Failed to modify persona account, Central Repo is not enabled");
|
||||
}
|
||||
|
||||
String updateClause = "UPDATE persona_accounts SET confidence_id = " + confidence.getLevelId() + ", justification = \"" + justification + "\" WHERE id = " + id;
|
||||
cr.executeUpdateSQL(updateClause);
|
||||
CentralRepository.getInstance().executeUpdateSQL(updateClause);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -419,13 +382,12 @@ public class PersonaAccount {
|
||||
*
|
||||
* @return Collection of all accounts associated with the given persona, may
|
||||
* be empty.
|
||||
*
|
||||
* @throws CentralRepoException If there is an error in getting the
|
||||
* accounts.
|
||||
*/
|
||||
static Collection<CentralRepoAccount> getAccountsForPersona(long personaId) throws CentralRepoException {
|
||||
CentralRepository cr = CentralRepository.getInstance();
|
||||
|
||||
if (cr != null) {
|
||||
String queryClause = "SELECT account_id, "
|
||||
+ " accounts.account_type_id as account_type_id, accounts.account_unique_identifier as account_unique_identifier,"
|
||||
+ " account_types.type_name as type_name "
|
||||
@ -435,11 +397,9 @@ public class PersonaAccount {
|
||||
+ " WHERE persona_accounts.persona_id = " + personaId;
|
||||
|
||||
AccountsForPersonaQueryCallback queryCallback = new AccountsForPersonaQueryCallback();
|
||||
cr.executeSelectSQL(queryClause, queryCallback);
|
||||
CentralRepository.getInstance().executeSelectSQL(queryClause, queryCallback);
|
||||
|
||||
return queryCallback.getAccountsList();
|
||||
}
|
||||
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,6 @@
|
||||
CTL_OpenPersonaManager=Persona Manager
|
||||
CTL_PersonaManagerTopComponentAction=Persona Manager
|
||||
CTL_OpenPersonas=Personas
|
||||
CTL_PersonasTopComponentAction=Personas
|
||||
CTL_PersonaDetailsTopComponent=Persona Details
|
||||
PersonaManagerTopComponent.createBtn.text=New Persona
|
||||
PersonaManagerTopComponent.searchBtn.text=Search
|
||||
PersonaManagerTopComponent.resultsTable.columnModel.title1=Name
|
||||
PersonaManagerTopComponent.resultsTable.columnModel.title0=ID
|
||||
PersonaManagerTopComponent.resultsTable.toolTipText=
|
||||
PersonaManagerTopComponent.searchAccountRadio.text=Account
|
||||
PersonaManagerTopComponent.searchNameRadio.text=Name
|
||||
PersonaManagerTopComponent.searchField.text=
|
||||
PersonaManagerTopComponent.editBtn.text=Edit Persona
|
||||
PersonaDetailsDialog.cancelBtn.text=Cancel
|
||||
PersonaDetailsDialog.okBtn.text=OK
|
||||
PersonaDetailsPanel.casesLbl.text=Cases found in:
|
||||
@ -27,7 +18,6 @@ PersonaDetailsPanel.nameLbl.text=Name:
|
||||
AddAliasDialog.accountsLbl.text=Account:
|
||||
AddAliasDialog.okBtn.text=OK
|
||||
AddAliasDialog.cancelBtn.text=Cancel
|
||||
PersonaManagerTopComponent.deleteBtn.text=Delete Persona
|
||||
PersonaDetailsPanel.casesLbl.text=Cases found in:
|
||||
PersonaDetailsPanel.deleteAliasBtn.text=Delete
|
||||
PersonaDetailsPanel.addAliasBtn.text=Add
|
||||
@ -73,3 +63,19 @@ PersonaMetadataDialog.cancelBtn.text=Cancel
|
||||
PersonaDetailsPanel.editAccountBtn.text=Edit
|
||||
PersonaDetailsPanel.editMetadataBtn.text=Edit
|
||||
PersonaDetailsPanel.editAliasBtn.text=Edit
|
||||
PersonasTopComponent.searchAccountRadio.text=Account
|
||||
PersonasTopComponent.searchNameRadio.text=Name
|
||||
PersonasTopComponent.searchField.text=
|
||||
PersonasTopComponent.deleteBtn.text=Delete Persona
|
||||
PersonasTopComponent.editBtn.text=Edit Persona
|
||||
PersonasTopComponent.createBtn.text=New Persona
|
||||
PersonasTopComponent.createAccountBtn.text=Create Account
|
||||
PersonasTopComponent.searchBtn.text=Search
|
||||
PersonasTopComponent.resultsTable.columnModel.title1=Name
|
||||
PersonasTopComponent.resultsTable.columnModel.title0=ID
|
||||
PersonasTopComponent.resultsTable.toolTipText=
|
||||
CreatePersonaAccountDialog.cancelBtn.text=Cancel
|
||||
CreatePersonaAccountDialog.typeLbl.text=Type:
|
||||
CreatePersonaAccountDialog.identifierTextField.text=
|
||||
CreatePersonaAccountDialog.identiferLbl.text=Identifier:
|
||||
CreatePersonaAccountDialog.okBtn.text=OK
|
||||
|
@ -3,10 +3,13 @@ AddMetadataDialog_dup_msg=A metadata entry with this name has already been added
|
||||
AddMetadataDialog_dup_Title=Metadata add failure
|
||||
AddMetadataDialog_empty_name_msg=A metadata entry cannot have an empty name or value.
|
||||
AddMetadataDialog_empty_name_Title=Missing field(s)
|
||||
CTL_OpenPersonaManager=Persona Manager
|
||||
CTL_PersonaManagerTopComponentAction=Persona Manager
|
||||
CreatePersonaAccountDialog.title.text=Create Account
|
||||
CreatePersonaAccountDialog_dup_msg=An account with this identifier and type already exists.
|
||||
CreatePersonaAccountDialog_dup_Title=Account creation failure
|
||||
CTL_OpenPersonas=Personas
|
||||
CTL_PersonasTopComponentAction=Personas
|
||||
CTL_PersonaDetailsTopComponent=Persona Details
|
||||
OpenPersonasAction.displayName=Persona Manager
|
||||
OpenPersonasAction.displayName=Personas
|
||||
PersonaAccountDialog.title.text=Add Account
|
||||
PersonaAccountDialog_dup_msg=This account is already added to the persona.
|
||||
PersonaAccountDialog_dup_Title=Account add failure
|
||||
@ -23,32 +26,11 @@ PersonaAliasDialog_dup_msg=This alias has already been added to this persona.
|
||||
PersonaAliasDialog_dup_Title=Alias add failure
|
||||
PersonaAliasDialog_empty_msg=An alias cannot be empty.
|
||||
PersonaAliasDialog_empty_Title=Empty alias
|
||||
PersonaDetailsDialog.cancelBtn.text=Cancel
|
||||
PersonaDetailsDialog.okBtn.text=OK
|
||||
PersonaDetailsDialogCreateTitle=Create Persona
|
||||
PersonaDetailsDialogEditTitle=Edit Persona
|
||||
PersonaDetailsDialogViewTitle=View Persona
|
||||
PersonaDetailsPanel_CentralRepoErr_msg=Failure to write to Central Repository.
|
||||
PersonaDetailsPanel_CentralRepoErr_Title=Central Repository failure
|
||||
PersonaDetailsPanel_empty_justification_msg=The justification field cannot be empty
|
||||
PersonaDetailsPanel_empty_justification_Title=Empty justification
|
||||
PersonaDetailsPanel_EmptyComment_msg=Persona comment cannot be empty.
|
||||
PersonaDetailsPanel_EmptyComment_Title=Empty persona comment
|
||||
PersonaDetailsPanel_EmptyName_msg=Persona name cannot be empty.
|
||||
PersonaDetailsPanel_EmptyName_Title=Empty persona name
|
||||
PersonaDetailsPanel_load_exception_msg=Failed to load persona.
|
||||
PersonaDetailsPanel_load_exception_Title=Initialization failure
|
||||
PersonaDetailsPanel_NotEnoughAccounts_msg=A persona needs at least one account.
|
||||
PersonaDetailsPanel_NotEnoughAccounts_Title=Missing account
|
||||
PersonaManagerTopComponent.createBtn.text=New Persona
|
||||
PersonaManagerTopComponent.searchBtn.text=Search
|
||||
PersonaManagerTopComponent.resultsTable.columnModel.title1=Name
|
||||
PersonaManagerTopComponent.resultsTable.columnModel.title0=ID
|
||||
PersonaManagerTopComponent.resultsTable.toolTipText=
|
||||
PersonaManagerTopComponent.searchAccountRadio.text=Account
|
||||
PersonaManagerTopComponent.searchNameRadio.text=Name
|
||||
PersonaManagerTopComponent.searchField.text=
|
||||
PersonaManagerTopComponent.editBtn.text=Edit Persona
|
||||
PersonaDetailsDialog.cancelBtn.text=Cancel
|
||||
PersonaDetailsDialog.okBtn.text=OK
|
||||
PersonaDetailsPanel.casesLbl.text=Cases found in:
|
||||
PersonaDetailsPanel.deleteAliasBtn.text=Delete
|
||||
PersonaDetailsPanel.addAliasBtn.text=Add
|
||||
@ -64,7 +46,6 @@ PersonaDetailsPanel.nameLbl.text=Name:
|
||||
AddAliasDialog.accountsLbl.text=Account:
|
||||
AddAliasDialog.okBtn.text=OK
|
||||
AddAliasDialog.cancelBtn.text=Cancel
|
||||
PersonaManagerTopComponent.deleteBtn.text=Delete Persona
|
||||
PersonaDetailsPanel.casesLbl.text=Cases found in:
|
||||
PersonaDetailsPanel.deleteAliasBtn.text=Delete
|
||||
PersonaDetailsPanel.addAliasBtn.text=Add
|
||||
@ -98,6 +79,18 @@ PersonaAliasDialog.justificationLbl.text=Justification:
|
||||
PersonaAliasDialog.aliasTextField.text=
|
||||
PersonaAliasDialog.aliasLbl.text=Alias:
|
||||
PersonaAliasDialog.okBtn.text_1=OK
|
||||
PersonaDetailsPanel_CentralRepoErr_msg=Failure to write to Central Repository.
|
||||
PersonaDetailsPanel_CentralRepoErr_Title=Central Repository failure
|
||||
PersonaDetailsPanel_empty_justification_msg=The justification field cannot be empty
|
||||
PersonaDetailsPanel_empty_justification_Title=Empty justification
|
||||
PersonaDetailsPanel_EmptyComment_msg=Persona comment cannot be empty.
|
||||
PersonaDetailsPanel_EmptyComment_Title=Empty persona comment
|
||||
PersonaDetailsPanel_EmptyName_msg=Persona name cannot be empty.
|
||||
PersonaDetailsPanel_EmptyName_Title=Empty persona name
|
||||
PersonaDetailsPanel_load_exception_msg=Failed to load persona.
|
||||
PersonaDetailsPanel_load_exception_Title=Initialization failure
|
||||
PersonaDetailsPanel_NotEnoughAccounts_msg=A persona needs at least one account.
|
||||
PersonaDetailsPanel_NotEnoughAccounts_Title=Missing account
|
||||
PersonaMetadataDialog.confidenceLbl.text=Confidence:
|
||||
PersonaMetadataDialog.justificationTextField.text=
|
||||
PersonaMetadataDialog.justificationLbl.text=Justification:
|
||||
@ -110,10 +103,26 @@ PersonaMetadataDialog.cancelBtn.text=Cancel
|
||||
PersonaDetailsPanel.editAccountBtn.text=Edit
|
||||
PersonaDetailsPanel.editMetadataBtn.text=Edit
|
||||
PersonaDetailsPanel.editAliasBtn.text=Edit
|
||||
PMTopComponent_delete_confirmation_msg=Are you sure you want to delete this persona?
|
||||
PMTopComponent_delete_confirmation_Title=Are you sure?
|
||||
PMTopComponent_delete_exception_msg=Failed to delete persona.
|
||||
PMTopComponent_delete_exception_Title=Delete failure
|
||||
PMTopComponent_Name=Persona Manager
|
||||
PMTopComponent_search_exception_msg=Failed to search personas.
|
||||
PMTopComponent_search_exception_Title=Search failure
|
||||
PersonasTopComponent.searchAccountRadio.text=Account
|
||||
PersonasTopComponent.searchNameRadio.text=Name
|
||||
PersonasTopComponent.searchField.text=
|
||||
PersonasTopComponent.deleteBtn.text=Delete Persona
|
||||
PersonasTopComponent.editBtn.text=Edit Persona
|
||||
PersonasTopComponent.createBtn.text=New Persona
|
||||
PersonasTopComponent.createAccountBtn.text=Create Account
|
||||
PersonasTopComponent.searchBtn.text=Search
|
||||
PersonasTopComponent.resultsTable.columnModel.title1=Name
|
||||
PersonasTopComponent.resultsTable.columnModel.title0=ID
|
||||
PersonasTopComponent.resultsTable.toolTipText=
|
||||
CreatePersonaAccountDialog.cancelBtn.text=Cancel
|
||||
CreatePersonaAccountDialog.typeLbl.text=Type:
|
||||
CreatePersonaAccountDialog.identifierTextField.text=
|
||||
CreatePersonaAccountDialog.identiferLbl.text=Identifier:
|
||||
CreatePersonaAccountDialog.okBtn.text=OK
|
||||
PersonasTopComponent_delete_confirmation_msg=Are you sure you want to delete this persona?
|
||||
PersonasTopComponent_delete_confirmation_Title=Are you sure?
|
||||
PersonasTopComponent_delete_exception_msg=Failed to delete persona.
|
||||
PersonasTopComponent_delete_exception_Title=Delete failure
|
||||
PersonasTopComponent_Name=Personas
|
||||
PersonasTopComponent_search_exception_msg=Failed to search personas.
|
||||
PersonasTopComponent_search_exception_Title=Search failure
|
||||
|
@ -8,3 +8,5 @@ PersonaAliasDialog.cancelBtn.text_1=\u53d6\u308a\u6d88\u3057
|
||||
PersonaAliasDialog.okBtn.text_1=OK
|
||||
PersonaMetadataDialog.okBtn.text=OK
|
||||
PersonaMetadataDialog.cancelBtn.text=\u53d6\u308a\u6d88\u3057
|
||||
CreatePersonaAccountDialog.okBtn.text=OK
|
||||
CreatePersonaAccountDialog.cancelBtn.text=\u53d6\u308a\u6d88\u3057
|
||||
|
@ -0,0 +1,168 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JDialogFormInfo">
|
||||
<Properties>
|
||||
<Property name="defaultCloseOperation" type="int" value="2"/>
|
||||
<Property name="resizable" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<SyntheticProperties>
|
||||
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
|
||||
<SyntheticProperty name="generateCenter" type="boolean" value="false"/>
|
||||
</SyntheticProperties>
|
||||
<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 pref="194" max="32767" attributes="0"/>
|
||||
<Component id="okBtn" linkSize="2" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="cancelBtn" linkSize="2" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="settingsPanel" 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="settingsPanel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="okBtn" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="cancelBtn" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JPanel" name="settingsPanel">
|
||||
<Properties>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
|
||||
<EtchetBorder/>
|
||||
</Border>
|
||||
</Property>
|
||||
</Properties>
|
||||
|
||||
<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">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="typeLbl" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="typeComboBox" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="identiferLbl" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="identifierTextField" pref="281" 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"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="identiferLbl" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="identifierTextField" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="typeComboBox" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="typeLbl" alignment="3" min="-2" pref="9" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="identiferLbl">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/persona/Bundle.properties" key="CreatePersonaAccountDialog.identiferLbl.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="identifierTextField">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/persona/Bundle.properties" key="CreatePersonaAccountDialog.identifierTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="identifierTextFieldActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="typeLbl">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/persona/Bundle.properties" key="CreatePersonaAccountDialog.typeLbl.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JComboBox" name="typeComboBox">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
|
||||
<Connection code="new javax.swing.DefaultComboBoxModel<>(getAllAccountTypes())" type="code"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoAccount.CentralRepoAccountType>"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JButton" name="cancelBtn">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/persona/Bundle.properties" key="CreatePersonaAccountDialog.cancelBtn.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[79, 23]"/>
|
||||
</Property>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[79, 23]"/>
|
||||
</Property>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[79, 23]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cancelBtnActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="okBtn">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/persona/Bundle.properties" key="CreatePersonaAccountDialog.okBtn.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="okBtnActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
@ -0,0 +1,270 @@
|
||||
/*
|
||||
* Central Repository
|
||||
*
|
||||
* 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.centralrepository.persona;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.ListCellRenderer;
|
||||
import javax.swing.SwingUtilities;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.openide.windows.WindowManager;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoAccount;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoAccount.CentralRepoAccountType;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
/**
|
||||
* Configuration dialog for creating an account.
|
||||
*/
|
||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||
public class CreatePersonaAccountDialog extends JDialog {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(CreatePersonaAccountDialog.class.getName());
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final TypeChoiceRenderer TYPE_CHOICE_RENDERER = new TypeChoiceRenderer();
|
||||
|
||||
/**
|
||||
* Creates new create account dialog.
|
||||
*/
|
||||
@Messages({"CreatePersonaAccountDialog.title.text=Create Account",})
|
||||
public CreatePersonaAccountDialog(PersonaDetailsPanel pdp) {
|
||||
super(SwingUtilities.windowForComponent(pdp),
|
||||
Bundle.PersonaAccountDialog_title_text(),
|
||||
ModalityType.APPLICATION_MODAL);
|
||||
|
||||
initComponents();
|
||||
typeComboBox.setRenderer(TYPE_CHOICE_RENDERER);
|
||||
display();
|
||||
}
|
||||
|
||||
/**
|
||||
* This class handles displaying and rendering drop down menu for account
|
||||
* choices.
|
||||
*/
|
||||
private class TypeChoiceRenderer extends JLabel implements ListCellRenderer<CentralRepoAccountType>, Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
public Component getListCellRendererComponent(
|
||||
JList<? extends CentralRepoAccountType> list, CentralRepoAccountType value,
|
||||
int index, boolean isSelected, boolean cellHasFocus) {
|
||||
setText(value.getAcctType().getDisplayName());
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
private CentralRepoAccountType[] getAllAccountTypes() {
|
||||
Collection<CentralRepoAccountType> allAccountTypes;
|
||||
try {
|
||||
allAccountTypes = CentralRepository.getInstance().getAllAccountTypes();
|
||||
} catch (CentralRepoException e) {
|
||||
logger.log(Level.SEVERE, "Failed to access central repository", e);
|
||||
JOptionPane.showMessageDialog(this,
|
||||
Bundle.PersonaAccountDialog_get_types_exception_Title(),
|
||||
Bundle.PersonaAccountDialog_get_types_exception_msg(),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
return new CentralRepoAccountType[0];
|
||||
}
|
||||
return allAccountTypes.toArray(new CentralRepoAccountType[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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() {
|
||||
|
||||
settingsPanel = new javax.swing.JPanel();
|
||||
identiferLbl = new javax.swing.JLabel();
|
||||
identifierTextField = new javax.swing.JTextField();
|
||||
typeLbl = new javax.swing.JLabel();
|
||||
typeComboBox = new javax.swing.JComboBox<>();
|
||||
cancelBtn = new javax.swing.JButton();
|
||||
okBtn = new javax.swing.JButton();
|
||||
|
||||
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
|
||||
setResizable(false);
|
||||
|
||||
settingsPanel.setBorder(javax.swing.BorderFactory.createEtchedBorder());
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(identiferLbl, org.openide.util.NbBundle.getMessage(CreatePersonaAccountDialog.class, "CreatePersonaAccountDialog.identiferLbl.text")); // NOI18N
|
||||
|
||||
identifierTextField.setText(org.openide.util.NbBundle.getMessage(CreatePersonaAccountDialog.class, "CreatePersonaAccountDialog.identifierTextField.text")); // NOI18N
|
||||
identifierTextField.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
identifierTextFieldActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(typeLbl, org.openide.util.NbBundle.getMessage(CreatePersonaAccountDialog.class, "CreatePersonaAccountDialog.typeLbl.text")); // NOI18N
|
||||
|
||||
typeComboBox.setModel(new javax.swing.DefaultComboBoxModel<>(getAllAccountTypes()));
|
||||
|
||||
javax.swing.GroupLayout settingsPanelLayout = new javax.swing.GroupLayout(settingsPanel);
|
||||
settingsPanel.setLayout(settingsPanelLayout);
|
||||
settingsPanelLayout.setHorizontalGroup(
|
||||
settingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(settingsPanelLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(settingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(settingsPanelLayout.createSequentialGroup()
|
||||
.addComponent(typeLbl)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(typeComboBox, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addGroup(settingsPanelLayout.createSequentialGroup()
|
||||
.addComponent(identiferLbl)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(identifierTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 281, Short.MAX_VALUE)))
|
||||
.addContainerGap())
|
||||
);
|
||||
settingsPanelLayout.setVerticalGroup(
|
||||
settingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(settingsPanelLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(settingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(identiferLbl)
|
||||
.addComponent(identifierTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(settingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(typeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(typeLbl, javax.swing.GroupLayout.PREFERRED_SIZE, 9, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(cancelBtn, org.openide.util.NbBundle.getMessage(CreatePersonaAccountDialog.class, "CreatePersonaAccountDialog.cancelBtn.text")); // NOI18N
|
||||
cancelBtn.setMaximumSize(new java.awt.Dimension(79, 23));
|
||||
cancelBtn.setMinimumSize(new java.awt.Dimension(79, 23));
|
||||
cancelBtn.setPreferredSize(new java.awt.Dimension(79, 23));
|
||||
cancelBtn.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
cancelBtnActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(okBtn, org.openide.util.NbBundle.getMessage(CreatePersonaAccountDialog.class, "CreatePersonaAccountDialog.okBtn.text")); // NOI18N
|
||||
okBtn.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
okBtnActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
|
||||
getContentPane().setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap(194, Short.MAX_VALUE)
|
||||
.addComponent(okBtn)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(cancelBtn, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap())
|
||||
.addComponent(settingsPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
);
|
||||
|
||||
layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {cancelBtn, okBtn});
|
||||
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(settingsPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(okBtn)
|
||||
.addComponent(cancelBtn, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
);
|
||||
|
||||
pack();
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
private void display() {
|
||||
this.setLocationRelativeTo(WindowManager.getDefault().getMainWindow());
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
private CentralRepoAccount createAccount(CentralRepoAccount.CentralRepoAccountType type, String identifier) {
|
||||
CentralRepoAccount ret = null;
|
||||
try {
|
||||
CentralRepository cr = CentralRepository.getInstance();
|
||||
if (cr != null) {
|
||||
ret = cr.getOrCreateAccount(type, identifier);
|
||||
}
|
||||
} catch (CentralRepoException e) {
|
||||
logger.log(Level.SEVERE, "Failed to access central repository", e);
|
||||
JOptionPane.showMessageDialog(this,
|
||||
Bundle.PersonaAccountDialog_get_types_exception_Title(),
|
||||
Bundle.PersonaAccountDialog_get_types_exception_msg(),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Messages({
|
||||
"CreatePersonaAccountDialog_dup_Title=Account creation failure",
|
||||
"CreatePersonaAccountDialog_dup_msg=An account with this identifier and type already exists.",})
|
||||
private void okBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okBtnActionPerformed
|
||||
if (identifierTextField.getText().isEmpty()) {
|
||||
JOptionPane.showMessageDialog(this,
|
||||
Bundle.PersonaAccountDialog_identifier_empty_msg(),
|
||||
Bundle.PersonaAccountDialog_identifier_empty_Title(),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
return;
|
||||
}
|
||||
|
||||
CentralRepoAccount.CentralRepoAccountType type =
|
||||
(CentralRepoAccount.CentralRepoAccountType) typeComboBox.getSelectedItem();
|
||||
String identifier = identifierTextField.getText();
|
||||
|
||||
if (createAccount(type, identifier) != null) {
|
||||
dispose();
|
||||
}
|
||||
}//GEN-LAST:event_okBtnActionPerformed
|
||||
|
||||
private void cancelBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelBtnActionPerformed
|
||||
dispose();
|
||||
}//GEN-LAST:event_cancelBtnActionPerformed
|
||||
|
||||
private void identifierTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_identifierTextFieldActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_identifierTextFieldActionPerformed
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JButton cancelBtn;
|
||||
private javax.swing.JLabel identiferLbl;
|
||||
private javax.swing.JTextField identifierTextField;
|
||||
private javax.swing.JButton okBtn;
|
||||
private javax.swing.JPanel settingsPanel;
|
||||
private javax.swing.JComboBox<org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoAccount.CentralRepoAccountType> typeComboBox;
|
||||
private javax.swing.JLabel typeLbl;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
}
|
@ -35,18 +35,18 @@ import org.sleuthkit.autopsy.coreutils.ThreadConfined;
|
||||
* An Action that opens the Persona Search window.
|
||||
*/
|
||||
|
||||
@ActionID(category = "Tools", id = "org.sleuthkit.autopsy.centralrepository.persona.OpenPersonaManagerAction")
|
||||
@ActionRegistration(displayName = "#CTL_OpenPersonaManager", lazy = false)
|
||||
@ActionID(category = "Tools", id = "org.sleuthkit.autopsy.centralrepository.persona.OpenPersonasAction")
|
||||
@ActionRegistration(displayName = "#CTL_OpenPersonas", lazy = false)
|
||||
@ActionReferences(value = {
|
||||
@ActionReference(path = "Menu/Tools", position = 105)
|
||||
})
|
||||
public final class OpenPersonaManagerAction extends CallableSystemAction {
|
||||
public final class OpenPersonasAction extends CallableSystemAction {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final JMenuItem menuItem;
|
||||
|
||||
public OpenPersonaManagerAction() {
|
||||
public OpenPersonasAction() {
|
||||
menuItem = super.getMenuPresenter();
|
||||
this.setEnabled(CentralRepository.isEnabled());
|
||||
}
|
||||
@ -54,7 +54,7 @@ public final class OpenPersonaManagerAction extends CallableSystemAction {
|
||||
@Override
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||
public void performAction() {
|
||||
final TopComponent topComponent = WindowManager.getDefault().findTopComponent("PersonaManagerTopComponent");
|
||||
final TopComponent topComponent = WindowManager.getDefault().findTopComponent("PersonasTopComponent");
|
||||
if (topComponent != null) {
|
||||
if (topComponent.isOpened() == false) {
|
||||
topComponent.open();
|
||||
@ -65,7 +65,7 @@ public final class OpenPersonaManagerAction extends CallableSystemAction {
|
||||
}
|
||||
|
||||
@Override
|
||||
@NbBundle.Messages("OpenPersonasAction.displayName=Persona Manager")
|
||||
@NbBundle.Messages("OpenPersonasAction.displayName=Personas")
|
||||
public String getName() {
|
||||
return Bundle.OpenPersonasAction_displayName();
|
||||
}
|
@ -27,9 +27,7 @@
|
||||
</Component>
|
||||
</NonVisualComponents>
|
||||
<Properties>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[400, 400]"/>
|
||||
</Property>
|
||||
<Property name="name" type="java.lang.String" value="" noResource="true"/>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||
@ -46,7 +44,7 @@
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="jSplitPane1" alignment="0" pref="692" max="32767" attributes="0"/>
|
||||
<Component id="jSplitPane1" alignment="0" pref="794" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
@ -70,9 +68,10 @@
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="jSeparator1" max="32767" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="createBtn" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
@ -89,6 +88,10 @@
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="searchBtn" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="createAccountBtn" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
@ -106,7 +109,7 @@
|
||||
<Component id="searchBtn" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="resultsPane" pref="528" max="32767" attributes="0"/>
|
||||
<Component id="resultsPane" pref="457" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="editBtn" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
@ -114,6 +117,10 @@
|
||||
<Component id="deleteBtn" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jSeparator1" min="-2" pref="4" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="createAccountBtn" min="-2" pref="32" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
@ -122,7 +129,7 @@
|
||||
<Component class="javax.swing.JTextField" name="searchField">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/persona/Bundle.properties" key="PersonaManagerTopComponent.searchField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/persona/Bundle.properties" key="PersonasTopComponent.searchField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
@ -133,7 +140,7 @@
|
||||
</Property>
|
||||
<Property name="selected" type="boolean" value="true"/>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/persona/Bundle.properties" key="PersonaManagerTopComponent.searchNameRadio.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/persona/Bundle.properties" key="PersonasTopComponent.searchNameRadio.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
@ -143,7 +150,7 @@
|
||||
<ComponentRef name="searchButtonGroup"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/persona/Bundle.properties" key="PersonaManagerTopComponent.searchAccountRadio.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/persona/Bundle.properties" key="PersonasTopComponent.searchAccountRadio.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
@ -157,20 +164,20 @@
|
||||
<Component class="javax.swing.JTable" name="resultsTable">
|
||||
<Properties>
|
||||
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/persona/Bundle.properties" key="PersonaManagerTopComponent.resultsTable.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/persona/Bundle.properties" key="PersonasTopComponent.resultsTable.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="columnModel" type="javax.swing.table.TableColumnModel" editor="org.netbeans.modules.form.editors2.TableColumnModelEditor">
|
||||
<TableColumnModel selectionModel="0">
|
||||
<Column maxWidth="25" minWidth="-1" prefWidth="-1" resizable="true">
|
||||
<Title editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/persona/Bundle.properties" key="PersonaManagerTopComponent.resultsTable.columnModel.title0" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/persona/Bundle.properties" key="PersonasTopComponent.resultsTable.columnModel.title0" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Title>
|
||||
<Editor/>
|
||||
<Renderer/>
|
||||
</Column>
|
||||
<Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true">
|
||||
<Title editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/persona/Bundle.properties" key="PersonaManagerTopComponent.resultsTable.columnModel.title1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/persona/Bundle.properties" key="PersonasTopComponent.resultsTable.columnModel.title1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Title>
|
||||
<Editor/>
|
||||
<Renderer/>
|
||||
@ -187,36 +194,48 @@
|
||||
<Component class="javax.swing.JButton" name="searchBtn">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/persona/Bundle.properties" key="PersonaManagerTopComponent.searchBtn.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/persona/Bundle.properties" key="PersonasTopComponent.searchBtn.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="editBtn">
|
||||
<Component class="javax.swing.JButton" name="createAccountBtn">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/persona/Bundle.properties" key="PersonaManagerTopComponent.editBtn.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="createBtn">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/persona/Bundle.properties" key="PersonaManagerTopComponent.createBtn.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/persona/Bundle.properties" key="PersonasTopComponent.createAccountBtn.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="deleteBtn">
|
||||
<Component class="javax.swing.JButton" name="createBtn">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/persona/Bundle.properties" key="PersonaManagerTopComponent.deleteBtn.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/persona/Bundle.properties" key="PersonasTopComponent.createBtn.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="editBtn">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/persona/Bundle.properties" key="PersonasTopComponent.editBtn.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="deleteBtn">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/persona/Bundle.properties" key="PersonasTopComponent.deleteBtn.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JSeparator" name="jSeparator1">
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsPanel" name="detailsPanel">
|
@ -44,27 +44,29 @@ import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
* Top component for the Personas tool
|
||||
*
|
||||
*/
|
||||
@TopComponent.Description(preferredID = "PersonaManagerTopComponent", persistenceType = TopComponent.PERSISTENCE_NEVER)
|
||||
@TopComponent.Registration(mode = "personamanager", openAtStartup = false)
|
||||
@RetainLocation("personamanager")
|
||||
@TopComponent.Description(preferredID = "PersonasTopComponent", persistenceType = TopComponent.PERSISTENCE_NEVER)
|
||||
@TopComponent.Registration(mode = "personas", openAtStartup = false)
|
||||
@RetainLocation("personas")
|
||||
@SuppressWarnings("PMD.SingularField")
|
||||
public final class PersonaManagerTopComponent extends TopComponent {
|
||||
public final class PersonasTopComponent extends TopComponent {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(PersonaManagerTopComponent.class.getName());
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final Logger logger = Logger.getLogger(PersonasTopComponent.class.getName());
|
||||
|
||||
private List<Persona> currentResults = null;
|
||||
private Persona selectedPersona = null;
|
||||
|
||||
@Messages({
|
||||
"PMTopComponent_Name=Persona Manager",
|
||||
"PMTopComponent_delete_exception_Title=Delete failure",
|
||||
"PMTopComponent_delete_exception_msg=Failed to delete persona.",
|
||||
"PMTopComponent_delete_confirmation_Title=Are you sure?",
|
||||
"PMTopComponent_delete_confirmation_msg=Are you sure you want to delete this persona?",
|
||||
"PersonasTopComponent_Name=Personas",
|
||||
"PersonasTopComponent_delete_exception_Title=Delete failure",
|
||||
"PersonasTopComponent_delete_exception_msg=Failed to delete persona.",
|
||||
"PersonasTopComponent_delete_confirmation_Title=Are you sure?",
|
||||
"PersonasTopComponent_delete_confirmation_msg=Are you sure you want to delete this persona?",
|
||||
})
|
||||
public PersonaManagerTopComponent() {
|
||||
public PersonasTopComponent() {
|
||||
initComponents();
|
||||
setName(Bundle.PMTopComponent_Name());
|
||||
setName(Bundle.PersonasTopComponent_Name());
|
||||
executeSearch();
|
||||
|
||||
searchBtn.addActionListener(new ActionListener() {
|
||||
@ -77,7 +79,7 @@ public final class PersonaManagerTopComponent extends TopComponent {
|
||||
editBtn.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
new PersonaDetailsDialog(PersonaManagerTopComponent.this,
|
||||
new PersonaDetailsDialog(PersonasTopComponent.this,
|
||||
PersonaDetailsMode.EDIT, selectedPersona, new CreateEditCallbackImpl());
|
||||
}
|
||||
});
|
||||
@ -85,7 +87,7 @@ public final class PersonaManagerTopComponent extends TopComponent {
|
||||
createBtn.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
new PersonaDetailsDialog(PersonaManagerTopComponent.this,
|
||||
new PersonaDetailsDialog(PersonasTopComponent.this,
|
||||
PersonaDetailsMode.CREATE, selectedPersona, new CreateEditCallbackImpl());
|
||||
}
|
||||
});
|
||||
@ -94,8 +96,8 @@ public final class PersonaManagerTopComponent extends TopComponent {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
NotifyDescriptor confirm = new NotifyDescriptor.Confirmation(
|
||||
Bundle.PMTopComponent_delete_confirmation_msg(),
|
||||
Bundle.PMTopComponent_delete_confirmation_Title(),
|
||||
Bundle.PersonasTopComponent_delete_confirmation_msg(),
|
||||
Bundle.PersonasTopComponent_delete_confirmation_Title(),
|
||||
NotifyDescriptor.YES_NO_OPTION);
|
||||
DialogDisplayer.getDefault().notify(confirm);
|
||||
if (confirm.getValue().equals(NotifyDescriptor.YES_OPTION)) {
|
||||
@ -105,9 +107,9 @@ public final class PersonaManagerTopComponent extends TopComponent {
|
||||
}
|
||||
} catch (CentralRepoException ex) {
|
||||
logger.log(Level.SEVERE, "Failed to delete persona: " + selectedPersona.getName(), ex);
|
||||
JOptionPane.showMessageDialog(PersonaManagerTopComponent.this,
|
||||
Bundle.PMTopComponent_delete_exception_msg(),
|
||||
Bundle.PMTopComponent_delete_exception_Title(),
|
||||
JOptionPane.showMessageDialog(PersonasTopComponent.this,
|
||||
Bundle.PersonasTopComponent_delete_exception_msg(),
|
||||
Bundle.PersonasTopComponent_delete_exception_Title(),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
return;
|
||||
}
|
||||
@ -132,6 +134,13 @@ public final class PersonaManagerTopComponent extends TopComponent {
|
||||
searchAccountRadio.addActionListener((ActionEvent e) -> {
|
||||
searchField.setText("");
|
||||
});
|
||||
|
||||
createAccountBtn.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
new CreatePersonaAccountDialog(detailsPanel);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -214,8 +223,8 @@ public final class PersonaManagerTopComponent extends TopComponent {
|
||||
}
|
||||
|
||||
@Messages({
|
||||
"PMTopComponent_search_exception_Title=Search failure",
|
||||
"PMTopComponent_search_exception_msg=Failed to search personas.",})
|
||||
"PersonasTopComponent_search_exception_Title=Search failure",
|
||||
"PersonasTopComponent_search_exception_msg=Failed to search personas.",})
|
||||
private void executeSearch() {
|
||||
Collection<Persona> results;
|
||||
try {
|
||||
@ -227,8 +236,8 @@ public final class PersonaManagerTopComponent extends TopComponent {
|
||||
} catch (CentralRepoException ex) {
|
||||
logger.log(Level.SEVERE, "Failed to search personas", ex);
|
||||
JOptionPane.showMessageDialog(this,
|
||||
Bundle.PMTopComponent_search_exception_Title(),
|
||||
Bundle.PMTopComponent_search_exception_msg(),
|
||||
Bundle.PersonasTopComponent_search_exception_Title(),
|
||||
Bundle.PersonasTopComponent_search_exception_msg(),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
return;
|
||||
}
|
||||
@ -262,39 +271,43 @@ public final class PersonaManagerTopComponent extends TopComponent {
|
||||
resultsPane = new javax.swing.JScrollPane();
|
||||
resultsTable = new javax.swing.JTable();
|
||||
searchBtn = new javax.swing.JButton();
|
||||
editBtn = new javax.swing.JButton();
|
||||
createAccountBtn = new javax.swing.JButton();
|
||||
createBtn = new javax.swing.JButton();
|
||||
editBtn = new javax.swing.JButton();
|
||||
deleteBtn = new javax.swing.JButton();
|
||||
jSeparator1 = new javax.swing.JSeparator();
|
||||
detailsPanel = new org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsPanel();
|
||||
|
||||
setMinimumSize(new java.awt.Dimension(400, 400));
|
||||
setName(""); // NOI18N
|
||||
|
||||
searchField.setText(org.openide.util.NbBundle.getMessage(PersonaManagerTopComponent.class, "PersonaManagerTopComponent.searchField.text")); // NOI18N
|
||||
searchField.setText(org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.searchField.text")); // NOI18N
|
||||
|
||||
searchButtonGroup.add(searchNameRadio);
|
||||
searchNameRadio.setSelected(true);
|
||||
org.openide.awt.Mnemonics.setLocalizedText(searchNameRadio, org.openide.util.NbBundle.getMessage(PersonaManagerTopComponent.class, "PersonaManagerTopComponent.searchNameRadio.text")); // NOI18N
|
||||
org.openide.awt.Mnemonics.setLocalizedText(searchNameRadio, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.searchNameRadio.text")); // NOI18N
|
||||
|
||||
searchButtonGroup.add(searchAccountRadio);
|
||||
org.openide.awt.Mnemonics.setLocalizedText(searchAccountRadio, org.openide.util.NbBundle.getMessage(PersonaManagerTopComponent.class, "PersonaManagerTopComponent.searchAccountRadio.text")); // NOI18N
|
||||
org.openide.awt.Mnemonics.setLocalizedText(searchAccountRadio, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.searchAccountRadio.text")); // NOI18N
|
||||
|
||||
resultsTable.setToolTipText(org.openide.util.NbBundle.getMessage(PersonaManagerTopComponent.class, "PersonaManagerTopComponent.resultsTable.toolTipText")); // NOI18N
|
||||
resultsTable.setToolTipText(org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.resultsTable.toolTipText")); // NOI18N
|
||||
resultsTable.getTableHeader().setReorderingAllowed(false);
|
||||
resultsPane.setViewportView(resultsTable);
|
||||
if (resultsTable.getColumnModel().getColumnCount() > 0) {
|
||||
resultsTable.getColumnModel().getColumn(0).setMaxWidth(25);
|
||||
resultsTable.getColumnModel().getColumn(0).setHeaderValue(org.openide.util.NbBundle.getMessage(PersonaManagerTopComponent.class, "PersonaManagerTopComponent.resultsTable.columnModel.title0")); // NOI18N
|
||||
resultsTable.getColumnModel().getColumn(1).setHeaderValue(org.openide.util.NbBundle.getMessage(PersonaManagerTopComponent.class, "PersonaManagerTopComponent.resultsTable.columnModel.title1")); // NOI18N
|
||||
resultsTable.getColumnModel().getColumn(0).setHeaderValue(org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.resultsTable.columnModel.title0")); // NOI18N
|
||||
resultsTable.getColumnModel().getColumn(1).setHeaderValue(org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.resultsTable.columnModel.title1")); // NOI18N
|
||||
}
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(searchBtn, org.openide.util.NbBundle.getMessage(PersonaManagerTopComponent.class, "PersonaManagerTopComponent.searchBtn.text")); // NOI18N
|
||||
org.openide.awt.Mnemonics.setLocalizedText(searchBtn, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.searchBtn.text")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(editBtn, org.openide.util.NbBundle.getMessage(PersonaManagerTopComponent.class, "PersonaManagerTopComponent.editBtn.text")); // NOI18N
|
||||
org.openide.awt.Mnemonics.setLocalizedText(createAccountBtn, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.createAccountBtn.text")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(createBtn, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.createBtn.text")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(editBtn, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.editBtn.text")); // NOI18N
|
||||
editBtn.setEnabled(false);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(createBtn, org.openide.util.NbBundle.getMessage(PersonaManagerTopComponent.class, "PersonaManagerTopComponent.createBtn.text")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(deleteBtn, org.openide.util.NbBundle.getMessage(PersonaManagerTopComponent.class, "PersonaManagerTopComponent.deleteBtn.text")); // NOI18N
|
||||
org.openide.awt.Mnemonics.setLocalizedText(deleteBtn, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.deleteBtn.text")); // NOI18N
|
||||
deleteBtn.setEnabled(false);
|
||||
|
||||
javax.swing.GroupLayout searchPanelLayout = new javax.swing.GroupLayout(searchPanel);
|
||||
@ -304,6 +317,7 @@ public final class PersonaManagerTopComponent extends TopComponent {
|
||||
.addGroup(searchPanelLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jSeparator1)
|
||||
.addGroup(searchPanelLayout.createSequentialGroup()
|
||||
.addComponent(createBtn)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
@ -317,7 +331,10 @@ public final class PersonaManagerTopComponent extends TopComponent {
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(searchAccountRadio)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(searchBtn)))
|
||||
.addComponent(searchBtn))
|
||||
.addGroup(searchPanelLayout.createSequentialGroup()
|
||||
.addComponent(createAccountBtn)
|
||||
.addGap(0, 0, Short.MAX_VALUE)))
|
||||
.addContainerGap())
|
||||
);
|
||||
searchPanelLayout.setVerticalGroup(
|
||||
@ -331,12 +348,16 @@ public final class PersonaManagerTopComponent extends TopComponent {
|
||||
.addComponent(searchAccountRadio)
|
||||
.addComponent(searchBtn))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(resultsPane, javax.swing.GroupLayout.DEFAULT_SIZE, 528, Short.MAX_VALUE)
|
||||
.addComponent(resultsPane, javax.swing.GroupLayout.DEFAULT_SIZE, 457, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(editBtn)
|
||||
.addComponent(createBtn)
|
||||
.addComponent(deleteBtn))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 4, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(createAccountBtn, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
@ -347,7 +368,7 @@ public final class PersonaManagerTopComponent extends TopComponent {
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 692, Short.MAX_VALUE)
|
||||
.addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 794, Short.MAX_VALUE)
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
@ -356,10 +377,12 @@ public final class PersonaManagerTopComponent extends TopComponent {
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JButton createAccountBtn;
|
||||
private javax.swing.JButton createBtn;
|
||||
private javax.swing.JButton deleteBtn;
|
||||
private org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsPanel detailsPanel;
|
||||
private javax.swing.JButton editBtn;
|
||||
private javax.swing.JSeparator jSeparator1;
|
||||
private javax.swing.JSplitPane jSplitPane1;
|
||||
private javax.swing.JScrollPane resultsPane;
|
||||
private javax.swing.JTable resultsTable;
|
@ -981,4 +981,3 @@ CallLogArtifactViewer.localAccountPersonaNameLabel.text=jLabel1
|
||||
CallLogArtifactViewer.localAccountPersonaButton.text=jButton1
|
||||
ContactArtifactViewer.personasLabel.text=Personas
|
||||
MessageArtifactViewer.accountsTab.TabConstraints.tabTitle=Accounts
|
||||
ContactArtifactViewer.contactImage.text=
|
||||
|
@ -35,15 +35,23 @@ AnnotationsContentViewer.title=Annotations
|
||||
AnnotationsContentViewer.toolTip=Displays tags and comments associated with the selected content.
|
||||
ApplicationContentViewer.title=Application
|
||||
ApplicationContentViewer.toolTip=Displays file contents.
|
||||
CallLogArtifactViewer_crdisbaled_persona_button_text=Create
|
||||
CallLogArtifactViewer_crdisbaled_persona_label=Unknown
|
||||
CallLogArtifactViewer_number_from=From
|
||||
CallLogArtifactViewer_number_to=To
|
||||
CallLogArtifactViewer_persona_button_new=Create
|
||||
CallLogArtifactViewer_persona_button_view=View
|
||||
CallLogArtifactViewer_persona_label=\ Persona
|
||||
CallLogArtifactViewer_persona_searching=Searching...
|
||||
CallLogArtifactViewer_persona_text_none=None Found
|
||||
CallLogArtifactViewer_heading_metadata=Metadata
|
||||
CallLogArtifactViewer_heading_parties=Parties
|
||||
CallLogArtifactViewer_heading_Source=Source
|
||||
CallLogArtifactViewer_label_datasource=Data Source
|
||||
CallLogArtifactViewer_label_date=Date
|
||||
CallLogArtifactViewer_label_direction=Direction
|
||||
CallLogArtifactViewer_label_duration=Duration
|
||||
CallLogArtifactViewer_label_from=From
|
||||
CallLogArtifactViewer_label_to=To
|
||||
CallLogArtifactViewer_suffix_local=(Local)
|
||||
CallLogArtifactViewer_value_unknown=Unknown
|
||||
CommunicationArtifactViewerHelper_menuitem_copy=Copy
|
||||
CommunicationArtifactViewerHelper_persona_button_create=Create
|
||||
CommunicationArtifactViewerHelper_persona_button_view=View
|
||||
CommunicationArtifactViewerHelper_persona_label=Persona:
|
||||
CommunicationArtifactViewerHelper_persona_searching=Searching...
|
||||
CommunicationArtifactViewerHelper_persona_unknown=Unknown
|
||||
ContactArtifactViewer_missing_account_label=Missing Account:
|
||||
ContactArtifactViewer_persona_account_justification=Account found in Contact artifact
|
||||
ContactArtifactViewer_persona_button_new=Create
|
||||
|
@ -35,6 +35,7 @@ import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.lookup.ServiceProvider;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
@ -67,7 +68,7 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
private GridBagLayout m_gridBagLayout = new GridBagLayout();
|
||||
private GridBagConstraints m_constraints = new GridBagConstraints();
|
||||
|
||||
private final List<PersonaSearchAndDisplayTask> personaSearchtasks = new ArrayList<>();
|
||||
private PersonaAccountFetcher currentAccountFetcher = null;
|
||||
|
||||
/**
|
||||
* Creates new form CallLogArtifactViewer.
|
||||
@ -92,6 +93,10 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
public void setArtifact(BlackboardArtifact artifact) {
|
||||
resetComponent();
|
||||
|
||||
if (artifact == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
CallLogViewData callLogViewData = null;
|
||||
try {
|
||||
callLogViewData = getCallLogViewData(artifact);
|
||||
@ -101,11 +106,16 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
|
||||
// update the view with the call log data
|
||||
if (callLogViewData != null) {
|
||||
updateView(callLogViewData);
|
||||
List<AccountPersonaSearcherData> personaSearchDataList = updateView(callLogViewData);
|
||||
if(!personaSearchDataList.isEmpty()) {
|
||||
currentAccountFetcher = new PersonaAccountFetcher(artifact, personaSearchDataList, this);
|
||||
currentAccountFetcher.execute();
|
||||
} else {
|
||||
currentAccountFetcher = null;
|
||||
}
|
||||
}
|
||||
// repaint
|
||||
this.revalidate();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -281,6 +291,8 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
* Update the viewer with the call log data.
|
||||
*
|
||||
* @param callLogViewData Call log data to update the view with.
|
||||
*
|
||||
* @return List of AccountPersonaSearcherData objects.
|
||||
*/
|
||||
@NbBundle.Messages({
|
||||
"CallLogArtifactViewer_heading_parties=Parties",
|
||||
@ -288,10 +300,11 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
"CallLogArtifactViewer_label_from=From",
|
||||
"CallLogArtifactViewer_label_to=To"
|
||||
})
|
||||
private void updateView(CallLogViewData callLogViewData) {
|
||||
private List<AccountPersonaSearcherData> updateView(CallLogViewData callLogViewData) {
|
||||
|
||||
CommunicationArtifactViewerHelper.addHeader(this, m_gridBagLayout, this.m_constraints, Bundle.CallLogArtifactViewer_heading_parties());
|
||||
|
||||
List<AccountPersonaSearcherData> dataList = new ArrayList<>();
|
||||
// Display From address
|
||||
CommunicationArtifactViewerHelper.addKey(this, m_gridBagLayout, this.m_constraints, Bundle.CallLogArtifactViewer_label_from());
|
||||
|
||||
@ -301,10 +314,7 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
CommunicationArtifactViewerHelper.addValue(this, m_gridBagLayout, this.m_constraints, accountDisplayString);
|
||||
|
||||
// show persona
|
||||
Optional<PersonaSearchAndDisplayTask> task = CommunicationArtifactViewerHelper.addPersonaRow(this, m_gridBagLayout, this.m_constraints, callLogViewData.getFromAccount());
|
||||
if (task.isPresent()) {
|
||||
personaSearchtasks.add(task.get());
|
||||
}
|
||||
dataList.addAll( CommunicationArtifactViewerHelper.addPersonaRow(this, m_gridBagLayout, this.m_constraints, callLogViewData.getFromAccount()));
|
||||
} else {
|
||||
CommunicationArtifactViewerHelper.addValue(this, m_gridBagLayout, this.m_constraints, Bundle.CallLogArtifactViewer_value_unknown());
|
||||
}
|
||||
@ -315,10 +325,8 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
String accountDisplayString = getAccountDisplayString(callLogViewData.getToAccount(), callLogViewData);
|
||||
CommunicationArtifactViewerHelper.addValue(this, m_gridBagLayout, this.m_constraints, accountDisplayString);
|
||||
|
||||
Optional<PersonaSearchAndDisplayTask> task = CommunicationArtifactViewerHelper.addPersonaRow(this, m_gridBagLayout, this.m_constraints, callLogViewData.getToAccount());
|
||||
if (task.isPresent()) {
|
||||
personaSearchtasks.add(task.get());
|
||||
}
|
||||
dataList.addAll( CommunicationArtifactViewerHelper.addPersonaRow(this, m_gridBagLayout, this.m_constraints, callLogViewData.getToAccount()));
|
||||
|
||||
} else {
|
||||
CommunicationArtifactViewerHelper.addValue(this, m_gridBagLayout, this.m_constraints, Bundle.CallLogArtifactViewer_value_unknown());
|
||||
}
|
||||
@ -328,20 +336,26 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
CommunicationArtifactViewerHelper.addKey(this, m_gridBagLayout, this.m_constraints, Bundle.CallLogArtifactViewer_label_to());
|
||||
CommunicationArtifactViewerHelper.addValue(this, m_gridBagLayout, this.m_constraints, otherParty);
|
||||
|
||||
Optional<PersonaSearchAndDisplayTask> task = CommunicationArtifactViewerHelper.addPersonaRow(this, m_gridBagLayout, this.m_constraints, otherParty);
|
||||
if (task.isPresent()) {
|
||||
personaSearchtasks.add(task.get());
|
||||
}
|
||||
dataList.addAll( CommunicationArtifactViewerHelper.addPersonaRow(this, m_gridBagLayout, this.m_constraints, otherParty));
|
||||
}
|
||||
|
||||
updateMetadataView(callLogViewData);
|
||||
|
||||
updateOtherAttributesView(callLogViewData);
|
||||
|
||||
updateSourceView(callLogViewData);
|
||||
|
||||
if (CentralRepository.isEnabled() == false) {
|
||||
showCRDisabledMessage();
|
||||
}
|
||||
|
||||
CommunicationArtifactViewerHelper.addPageEndGlue(this, m_gridBagLayout, this.m_constraints);
|
||||
|
||||
this.setLayout(m_gridBagLayout);
|
||||
this.revalidate();
|
||||
this.repaint();
|
||||
|
||||
return dataList;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -392,6 +406,37 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
CommunicationArtifactViewerHelper.addValue(this, m_gridBagLayout, this.m_constraints, callLogViewData.getDataSourceName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the other attributes section.
|
||||
*
|
||||
* @param callLogViewData Call log data.
|
||||
*/
|
||||
@NbBundle.Messages({
|
||||
"CallLogArtifactViewer_heading_others=Other Attributes"
|
||||
})
|
||||
private void updateOtherAttributesView(CallLogViewData callLogViewData) {
|
||||
|
||||
if (callLogViewData.getOtherAttributes().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
CommunicationArtifactViewerHelper.addHeader(this, m_gridBagLayout, this.m_constraints, Bundle.CallLogArtifactViewer_heading_others());
|
||||
|
||||
for (Map.Entry<String, String> entry : callLogViewData.getOtherAttributes().entrySet()) {
|
||||
CommunicationArtifactViewerHelper.addKey(this, m_gridBagLayout, this.m_constraints, entry.getKey());
|
||||
CommunicationArtifactViewerHelper.addValue(this, m_gridBagLayout, this.m_constraints, entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@NbBundle.Messages({
|
||||
"CalllogArtifactViewer_cr_disabled_message=Enable Central Repository to view, create and edit personas."
|
||||
})
|
||||
private void showCRDisabledMessage() {
|
||||
CommunicationArtifactViewerHelper.addBlankLine(this, m_gridBagLayout, m_constraints);
|
||||
m_constraints.gridy++;
|
||||
CommunicationArtifactViewerHelper.addMessageRow(this, m_gridBagLayout, m_constraints, Bundle.ContactArtifactViewer_cr_disabled_message());
|
||||
m_constraints.gridy++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns display string for a account. Checks if the given account is the
|
||||
* local account, if it is known. If it is, it appends a "(Local)" suffix to
|
||||
@ -419,7 +464,9 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
|
||||
@Override
|
||||
public boolean isSupported(BlackboardArtifact artifact) {
|
||||
return artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG.getTypeID();
|
||||
|
||||
return (artifact != null)
|
||||
&& (artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG.getTypeID());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -428,8 +475,10 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
private void resetComponent() {
|
||||
|
||||
// cancel any outstanding persona searching threads.
|
||||
personaSearchtasks.forEach(task -> task.cancel(Boolean.TRUE));
|
||||
personaSearchtasks.clear();
|
||||
if(currentAccountFetcher != null && !currentAccountFetcher.isDone()) {
|
||||
currentAccountFetcher.cancel(true);
|
||||
currentAccountFetcher = null;
|
||||
}
|
||||
|
||||
// clear the panel
|
||||
this.removeAll();
|
||||
@ -441,9 +490,9 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
m_constraints.anchor = GridBagConstraints.FIRST_LINE_START;
|
||||
m_constraints.gridy = 0;
|
||||
m_constraints.gridx = 0;
|
||||
m_constraints.weighty = 0.05;
|
||||
m_constraints.weightx = 0.05;
|
||||
m_constraints.insets = new java.awt.Insets(0, 0, 0, 0);
|
||||
m_constraints.weighty = 0.0;
|
||||
m_constraints.weightx = 0.0; // keep components fixed horizontally.
|
||||
m_constraints.insets = new java.awt.Insets(0, CommunicationArtifactViewerHelper.LEFT_INSET, 0, 0);
|
||||
m_constraints.fill = GridBagConstraints.NONE;
|
||||
|
||||
}
|
||||
|
@ -27,12 +27,14 @@ import java.awt.Toolkit;
|
||||
import java.awt.datatransfer.StringSelection;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.SwingUtilities;
|
||||
import java.util.Optional;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
|
||||
|
||||
@ -41,12 +43,12 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
|
||||
* A class to help display a communication artifact in a panel using a
|
||||
* gridbaglayout.
|
||||
*/
|
||||
public final class CommunicationArtifactViewerHelper {
|
||||
final class CommunicationArtifactViewerHelper {
|
||||
|
||||
// Number of columns in the gridbag layout.
|
||||
private final static int MAX_COLS = 4;
|
||||
|
||||
private final static int LEFT_INDENT = 12;
|
||||
final static int LEFT_INSET = 12;
|
||||
|
||||
/**
|
||||
* Empty private constructor
|
||||
@ -62,8 +64,15 @@ public final class CommunicationArtifactViewerHelper {
|
||||
* @param gridbagLayout Layout to use.
|
||||
* @param constraints Constrains to use.
|
||||
* @param headerString Heading string to display.
|
||||
*
|
||||
* @return JLabel Heading label added.
|
||||
*/
|
||||
static void addHeader(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints, String headerString) {
|
||||
static JLabel addHeader(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints, String headerString) {
|
||||
|
||||
Insets savedInsets = constraints.insets;
|
||||
|
||||
// create label for heading
|
||||
javax.swing.JLabel headingLabel = new javax.swing.JLabel();
|
||||
|
||||
// add a blank line before the start of new section, unless it's
|
||||
// the first section
|
||||
@ -75,9 +84,9 @@ public final class CommunicationArtifactViewerHelper {
|
||||
|
||||
// let the header span all of the row
|
||||
constraints.gridwidth = MAX_COLS;
|
||||
constraints.insets = new Insets(0, 0, 0, 0); // No inset for header
|
||||
|
||||
// create label for heading
|
||||
javax.swing.JLabel headingLabel = new javax.swing.JLabel();
|
||||
// set text
|
||||
headingLabel.setText(headerString);
|
||||
|
||||
// make it large and bold
|
||||
@ -92,6 +101,28 @@ public final class CommunicationArtifactViewerHelper {
|
||||
|
||||
// add line end glue
|
||||
addLineEndGlue(panel, gridbagLayout, constraints);
|
||||
|
||||
//restore insets
|
||||
constraints.insets = savedInsets;
|
||||
|
||||
return headingLabel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given component to the panel.
|
||||
*
|
||||
* Caller must know what it's doing and set up all the constraints properly.
|
||||
*
|
||||
* @param panel Panel to update.
|
||||
* @param gridbagLayout Layout to use.
|
||||
* @param constraints Constrains to use.
|
||||
* @param component Component to add.
|
||||
*/
|
||||
static void addComponent(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints, JComponent component) {
|
||||
|
||||
// add to panel
|
||||
gridbagLayout.setConstraints(component, constraints);
|
||||
panel.add(component);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -102,7 +133,7 @@ public final class CommunicationArtifactViewerHelper {
|
||||
* @param gridbagLayout Layout to use.
|
||||
* @param constraints Constrains to use.
|
||||
*/
|
||||
private static void addLineEndGlue(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints) {
|
||||
static void addLineEndGlue(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints) {
|
||||
// Place the filler just past the last column.
|
||||
constraints.gridx = MAX_COLS;
|
||||
|
||||
@ -155,7 +186,7 @@ public final class CommunicationArtifactViewerHelper {
|
||||
* @param gridbagLayout Layout to use.
|
||||
* @param constraints Constrains to use.
|
||||
*/
|
||||
private static void addBlankLine(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints) {
|
||||
static void addBlankLine(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints) {
|
||||
constraints.gridy++;
|
||||
constraints.gridx = 0;
|
||||
|
||||
@ -167,54 +198,85 @@ public final class CommunicationArtifactViewerHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a label/key to the panel.
|
||||
* Adds a label/key to the panel at col 0.
|
||||
*
|
||||
* @param panel Panel to update.
|
||||
* @param gridbagLayout Layout to use.
|
||||
* @param constraints Constrains to use.
|
||||
* @param keyString Key name to display.
|
||||
*
|
||||
* @return Label added.
|
||||
*/
|
||||
static void addKey(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints, String keyString) {
|
||||
static JLabel addKey(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints, String keyString) {
|
||||
return addKeyAtCol(panel, gridbagLayout, constraints, keyString, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a label/key to the panel at specified column.
|
||||
*
|
||||
* @param panel Panel to update.
|
||||
* @param gridbagLayout Layout to use.
|
||||
* @param constraints Constrains to use.
|
||||
* @param keyString Key name to display.
|
||||
* @param gridx column index, must be less than MAX_COLS - 1.
|
||||
*
|
||||
* @return Label added.
|
||||
*/
|
||||
static JLabel addKeyAtCol(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints, String keyString, int gridx) {
|
||||
|
||||
// create label
|
||||
javax.swing.JLabel keyLabel = new javax.swing.JLabel();
|
||||
|
||||
constraints.gridy++;
|
||||
constraints.gridx = 0;
|
||||
constraints.gridx = gridx < MAX_COLS - 1 ? gridx : MAX_COLS - 2;
|
||||
|
||||
Insets savedInsets = constraints.insets;
|
||||
|
||||
// Set inset to indent in
|
||||
constraints.insets = new java.awt.Insets(0, LEFT_INDENT, 0, 0);
|
||||
|
||||
// create label,
|
||||
javax.swing.JLabel keyLabel = new javax.swing.JLabel();
|
||||
// set text
|
||||
keyLabel.setText(keyString + ": ");
|
||||
|
||||
// add to panel
|
||||
gridbagLayout.setConstraints(keyLabel, constraints);
|
||||
panel.add(keyLabel);
|
||||
|
||||
// restore inset
|
||||
constraints.insets = savedInsets;
|
||||
return keyLabel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a value string to the panel.
|
||||
* Adds a value string to the panel at col 1.
|
||||
*
|
||||
* @param panel Panel to update.
|
||||
* @param gridbagLayout Layout to use.
|
||||
* @param constraints Constrains to use.
|
||||
* @param keyString Value string to display.
|
||||
*
|
||||
* @return Label added.
|
||||
*/
|
||||
static void addValue(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints, String valueString) {
|
||||
static JLabel addValue(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints, String valueString) {
|
||||
return addValueAtCol(panel, gridbagLayout, constraints, valueString, 1);
|
||||
}
|
||||
|
||||
constraints.gridx = 1;
|
||||
/**
|
||||
* Adds a value string to the panel at specified column.
|
||||
*
|
||||
* @param panel Panel to update.
|
||||
* @param gridbagLayout Layout to use.
|
||||
* @param constraints Constrains to use.
|
||||
* @param keyString Value string to display.
|
||||
* @param gridx Column index, must be less than MAX_COLS;
|
||||
*
|
||||
* @return Label added.
|
||||
*/
|
||||
static JLabel addValueAtCol(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints, String valueString, int gridx) {
|
||||
// create label,
|
||||
javax.swing.JLabel valueField = new javax.swing.JLabel();
|
||||
|
||||
constraints.gridx = gridx < MAX_COLS ? gridx : MAX_COLS - 1;
|
||||
|
||||
int savedGridwidth = constraints.gridwidth;
|
||||
|
||||
// let the value span 2 cols
|
||||
constraints.gridwidth = 2;
|
||||
|
||||
// create label,
|
||||
javax.swing.JLabel valueField = new javax.swing.JLabel();
|
||||
// set text
|
||||
valueField.setText(valueString);
|
||||
|
||||
// attach a right click menu with Copy option
|
||||
@ -234,6 +296,63 @@ public final class CommunicationArtifactViewerHelper {
|
||||
|
||||
// end the line
|
||||
addLineEndGlue(panel, gridbagLayout, constraints);
|
||||
|
||||
return valueField;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a message string, starting at column 0, and spanning the entire
|
||||
* row.
|
||||
*
|
||||
* @param panel Panel to show.
|
||||
* @param gridbagLayout Layout to use.
|
||||
* @param constraints Constraints to use.
|
||||
*
|
||||
* @param messageString Message to display.
|
||||
*
|
||||
* @return Label for message added.
|
||||
*/
|
||||
static JLabel addMessageRow(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints, String messageString) {
|
||||
return addMessageRow(panel, gridbagLayout, constraints, messageString, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a message string, starting at specified column, and spanning the
|
||||
* entire row.
|
||||
*
|
||||
* @param panel Panel to show.
|
||||
* @param gridbagLayout Layout to use.
|
||||
* @param constraints Constraints to use.
|
||||
*
|
||||
* @param messageString Message to display.
|
||||
*
|
||||
* @return Label for message added.
|
||||
*/
|
||||
static JLabel addMessageRow(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints, String messageString, int gridx) {
|
||||
|
||||
// create label
|
||||
javax.swing.JLabel messageLabel = new javax.swing.JLabel();
|
||||
|
||||
constraints.gridy++;
|
||||
constraints.gridx = gridx < MAX_COLS - 1 ? gridx : MAX_COLS - 2;
|
||||
|
||||
int savedGridwidth = constraints.gridwidth;
|
||||
|
||||
constraints.gridwidth = 3;
|
||||
|
||||
// set text
|
||||
messageLabel.setText(messageString);
|
||||
|
||||
// add to panel
|
||||
gridbagLayout.setConstraints(messageLabel, constraints);
|
||||
panel.add(messageLabel);
|
||||
|
||||
addLineEndGlue(panel, gridbagLayout, constraints);
|
||||
|
||||
// restore constraints
|
||||
constraints.gridwidth = savedGridwidth;
|
||||
|
||||
return messageLabel;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -250,8 +369,7 @@ public final class CommunicationArtifactViewerHelper {
|
||||
* @param constraints Constrains to use.
|
||||
* @param accountIdentifier Account identifier to search the persona.
|
||||
*
|
||||
* @return Optional PersonaSearchAndDisplayTask started to search for
|
||||
* persona.
|
||||
* @return List of AccountPersonaSearcherData objects.
|
||||
*/
|
||||
@NbBundle.Messages({
|
||||
"CommunicationArtifactViewerHelper_persona_label=Persona: ",
|
||||
@ -260,17 +378,17 @@ public final class CommunicationArtifactViewerHelper {
|
||||
"CommunicationArtifactViewerHelper_persona_button_view=View",
|
||||
"CommunicationArtifactViewerHelper_persona_button_create=Create"
|
||||
})
|
||||
static Optional<PersonaSearchAndDisplayTask> addPersonaRow(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints, String accountIdentifier) {
|
||||
|
||||
PersonaSearchAndDisplayTask personaTask = null;
|
||||
static List<AccountPersonaSearcherData> addPersonaRow(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints, String accountIdentifier) {
|
||||
List<AccountPersonaSearcherData> dataList = new ArrayList<>();
|
||||
|
||||
constraints.gridy++;
|
||||
constraints.gridx = 1;
|
||||
|
||||
Insets savedInsets = constraints.insets;
|
||||
|
||||
// Indent in
|
||||
constraints.insets = new java.awt.Insets(0, LEFT_INDENT, 0, 0);
|
||||
// extra Indent in
|
||||
constraints.insets = new java.awt.Insets(0, 2 * LEFT_INSET, 0, 0);
|
||||
|
||||
// create label
|
||||
javax.swing.JLabel personaLabel = new javax.swing.JLabel();
|
||||
@ -293,23 +411,22 @@ public final class CommunicationArtifactViewerHelper {
|
||||
// Place a button as place holder. It will be enabled when persona is available.
|
||||
javax.swing.JButton personaButton = new javax.swing.JButton();
|
||||
personaButton.setText(Bundle.CommunicationArtifactViewerHelper_persona_button_view());
|
||||
personaButton.setMargin(new Insets(0, 5, 0, 5));
|
||||
personaButton.setEnabled(false);
|
||||
|
||||
|
||||
gridbagLayout.setConstraints(personaButton, constraints);
|
||||
panel.add(personaButton);
|
||||
|
||||
if (CentralRepository.isEnabled()) {
|
||||
// kick off a task to find the persona for this account
|
||||
personaTask = new PersonaSearchAndDisplayTask(panel, new AccountPersonaSearcherData(accountIdentifier, personaLabel, personaButton));
|
||||
personaTask.execute();
|
||||
dataList.add(new AccountPersonaSearcherData(accountIdentifier, personaLabel, personaButton));
|
||||
} else {
|
||||
personaLabel.setEnabled(false);
|
||||
}
|
||||
|
||||
addLineEndGlue(panel, gridbagLayout, constraints);
|
||||
|
||||
return Optional.ofNullable(personaTask);
|
||||
return dataList;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,6 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||
<Form version="1.4" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||
<Properties>
|
||||
<Property name="toolTipText" type="java.lang.String" value="" noResource="true"/>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||
@ -11,217 +14,8 @@
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,-57,0,0,2,31"/>
|
||||
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,1,-112"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JPanel" name="namePanel">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="1" gridWidth="5" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="6" insetsLeft="19" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="contactNameLabel">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
|
||||
<FontInfo relative="true">
|
||||
<Font bold="true" component="contactNameLabel" italic="true" property="font" relativeSize="true" size="6"/>
|
||||
</FontInfo>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/contentviewers/Bundle.properties" key="ContactArtifactViewer.contactNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="2" ipadX="111" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JLabel" name="phonesLabel">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
|
||||
<FontInfo relative="true">
|
||||
<Font bold="true" component="phonesLabel" property="font" relativeSize="true" size="2"/>
|
||||
</FontInfo>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/contentviewers/Bundle.properties" key="ContactArtifactViewer.phonesLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="2" gridWidth="3" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="6" insetsLeft="19" insetsBottom="0" insetsRight="0" anchor="18" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Container class="javax.swing.JPanel" name="phoneNumbersPanel">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="3" gridWidth="4" gridHeight="1" fill="3" ipadX="0" ipadY="0" insetsTop="6" insetsLeft="19" insetsBottom="0" insetsRight="0" anchor="18" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
</Container>
|
||||
<Component class="javax.swing.JLabel" name="emailsLabel">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
|
||||
<FontInfo relative="true">
|
||||
<Font bold="true" component="emailsLabel" property="font" relativeSize="true" size="2"/>
|
||||
</FontInfo>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/contentviewers/Bundle.properties" key="ContactArtifactViewer.emailsLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="4" gridWidth="2" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="6" insetsLeft="19" insetsBottom="0" insetsRight="0" anchor="18" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Container class="javax.swing.JPanel" name="emailsPanel">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="5" gridWidth="4" gridHeight="1" fill="3" ipadX="0" ipadY="0" insetsTop="6" insetsLeft="19" insetsBottom="0" insetsRight="0" anchor="18" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
</Container>
|
||||
<Component class="javax.swing.JLabel" name="othersLabel">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
|
||||
<FontInfo relative="true">
|
||||
<Font bold="true" component="othersLabel" property="font" relativeSize="true" size="2"/>
|
||||
</FontInfo>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/contentviewers/Bundle.properties" key="ContactArtifactViewer.othersLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="6" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="6" insetsLeft="19" insetsBottom="0" insetsRight="0" anchor="18" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Container class="javax.swing.JPanel" name="otherAttrsPanel">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="7" gridWidth="4" gridHeight="1" fill="3" ipadX="0" ipadY="0" insetsTop="6" insetsLeft="19" insetsBottom="0" insetsRight="0" anchor="18" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
</Container>
|
||||
<Component class="javax.swing.Box$Filler" name="interPanelfiller">
|
||||
<Properties>
|
||||
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[0, 32767]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="classDetails" type="java.lang.String" value="Box.Filler.VerticalGlue"/>
|
||||
</AuxValues>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="8" gridWidth="1" gridHeight="2" fill="3" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.1"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="personasLabel">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
|
||||
<FontInfo relative="true">
|
||||
<Font bold="true" component="personasLabel" property="font" relativeSize="true" size="2"/>
|
||||
</FontInfo>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/contentviewers/Bundle.properties" key="ContactArtifactViewer.personasLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[90, 19]"/>
|
||||
</Property>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[90, 19]"/>
|
||||
</Property>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[90, 19]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="9" gridWidth="3" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="6" insetsLeft="19" insetsBottom="0" insetsRight="0" anchor="18" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Container class="javax.swing.JPanel" name="personasPanel">
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="10" gridWidth="4" gridHeight="1" fill="3" ipadX="0" ipadY="0" insetsTop="6" insetsLeft="19" insetsBottom="0" insetsRight="0" anchor="18" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
|
||||
</Container>
|
||||
<Component class="javax.swing.Box$Filler" name="bottomFiller">
|
||||
<Properties>
|
||||
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[0, 32767]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="classDetails" type="java.lang.String" value="Box.Filler.VerticalGlue"/>
|
||||
</AuxValues>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="11" gridWidth="4" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="1.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.Box$Filler" name="rightFiller">
|
||||
<Properties>
|
||||
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[32767, 0]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="classDetails" type="java.lang.String" value="Box.Filler.HorizontalGlue"/>
|
||||
</AuxValues>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="4" gridY="3" gridWidth="1" gridHeight="8" fill="1" ipadX="2" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="1.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="contactImage">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/images/defaultContact.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/contentviewers/Bundle.properties" key="ContactArtifactViewer.contactImage.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
|
||||
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="6" insetsLeft="19" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
@ -19,9 +19,9 @@
|
||||
package org.sleuthkit.autopsy.contentviewers;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Font;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Insets;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
@ -40,11 +40,11 @@ import javax.imageio.ImageIO;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import org.openide.util.lookup.ServiceProvider;
|
||||
import javax.swing.SwingWorker;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.lookup.ServiceProvider;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoAccount;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
|
||||
@ -70,11 +70,23 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
private final static Logger logger = Logger.getLogger(ContactArtifactViewer.class.getName());
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final int TOP_INSET = 4;
|
||||
private static final int LEFT_INSET = 12;
|
||||
private GridBagLayout m_gridBagLayout = new GridBagLayout();
|
||||
private GridBagConstraints m_constraints = new GridBagConstraints();
|
||||
|
||||
// contact name, if available.
|
||||
private JLabel personaSearchStatusLabel;
|
||||
|
||||
private BlackboardArtifact contactArtifact;
|
||||
private String contactName;
|
||||
private String datasourceName;
|
||||
|
||||
private List<BlackboardAttribute> phoneNumList = new ArrayList<>();
|
||||
private List<BlackboardAttribute> emailList = new ArrayList<>();
|
||||
private List<BlackboardAttribute> nameList = new ArrayList<>();
|
||||
private List<BlackboardAttribute> otherList = new ArrayList<>();
|
||||
private List<BlackboardAttribute> accountAttributesList = new ArrayList<>();
|
||||
|
||||
private final static String DEFAULT_IMAGE_PATH = "/org/sleuthkit/autopsy/images/defaultContact.png";
|
||||
private final ImageIcon defaultImage;
|
||||
|
||||
// A list of unique accounts matching the attributes of the contact artifact.
|
||||
private final List<CentralRepoAccount> contactUniqueAccountsList = new ArrayList<>();
|
||||
@ -83,11 +95,10 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
// account identifier attributes of the Contact artifact.
|
||||
private final Map<Persona, ArrayList<CentralRepoAccount>> contactUniquePersonasMap = new HashMap<>();
|
||||
|
||||
private final static String DEFAULT_IMAGE_PATH = "/org/sleuthkit/autopsy/images/defaultContact.png";
|
||||
private final ImageIcon defaultImage;
|
||||
private ContactPersonaSearcherTask personaSearchTask;
|
||||
|
||||
/**
|
||||
* Creates new form for ContactArtifactViewer
|
||||
* Creates new form ContactArtifactViewer
|
||||
*/
|
||||
public ContactArtifactViewer() {
|
||||
initComponents();
|
||||
@ -103,164 +114,13 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
@SuppressWarnings("unchecked")
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
java.awt.GridBagConstraints gridBagConstraints;
|
||||
|
||||
namePanel = new javax.swing.JPanel();
|
||||
contactNameLabel = new javax.swing.JLabel();
|
||||
phonesLabel = new javax.swing.JLabel();
|
||||
phoneNumbersPanel = new javax.swing.JPanel();
|
||||
emailsLabel = new javax.swing.JLabel();
|
||||
emailsPanel = new javax.swing.JPanel();
|
||||
othersLabel = new javax.swing.JLabel();
|
||||
otherAttrsPanel = new javax.swing.JPanel();
|
||||
javax.swing.Box.Filler interPanelfiller = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 32767));
|
||||
personasLabel = new javax.swing.JLabel();
|
||||
personasPanel = new javax.swing.JPanel();
|
||||
javax.swing.Box.Filler bottomFiller = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 32767));
|
||||
javax.swing.Box.Filler rightFiller = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(32767, 0));
|
||||
contactImage = new javax.swing.JLabel();
|
||||
|
||||
setToolTipText(""); // NOI18N
|
||||
setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
namePanel.setLayout(new java.awt.GridBagLayout());
|
||||
|
||||
contactNameLabel.setFont(contactNameLabel.getFont().deriveFont((contactNameLabel.getFont().getStyle() | java.awt.Font.ITALIC) | java.awt.Font.BOLD, contactNameLabel.getFont().getSize()+6));
|
||||
org.openide.awt.Mnemonics.setLocalizedText(contactNameLabel, org.openide.util.NbBundle.getMessage(ContactArtifactViewer.class, "ContactArtifactViewer.contactNameLabel.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.ipadx = 111;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
namePanel.add(contactNameLabel, gridBagConstraints);
|
||||
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 1;
|
||||
gridBagConstraints.gridwidth = 5;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(6, 19, 0, 0);
|
||||
add(namePanel, gridBagConstraints);
|
||||
|
||||
phonesLabel.setFont(phonesLabel.getFont().deriveFont(phonesLabel.getFont().getStyle() | java.awt.Font.BOLD, phonesLabel.getFont().getSize()+2));
|
||||
org.openide.awt.Mnemonics.setLocalizedText(phonesLabel, org.openide.util.NbBundle.getMessage(ContactArtifactViewer.class, "ContactArtifactViewer.phonesLabel.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 2;
|
||||
gridBagConstraints.gridwidth = 3;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(6, 19, 0, 0);
|
||||
add(phonesLabel, gridBagConstraints);
|
||||
|
||||
phoneNumbersPanel.setLayout(new java.awt.GridBagLayout());
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 3;
|
||||
gridBagConstraints.gridwidth = 4;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(6, 19, 0, 0);
|
||||
add(phoneNumbersPanel, gridBagConstraints);
|
||||
|
||||
emailsLabel.setFont(emailsLabel.getFont().deriveFont(emailsLabel.getFont().getStyle() | java.awt.Font.BOLD, emailsLabel.getFont().getSize()+2));
|
||||
org.openide.awt.Mnemonics.setLocalizedText(emailsLabel, org.openide.util.NbBundle.getMessage(ContactArtifactViewer.class, "ContactArtifactViewer.emailsLabel.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 4;
|
||||
gridBagConstraints.gridwidth = 2;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(6, 19, 0, 0);
|
||||
add(emailsLabel, gridBagConstraints);
|
||||
|
||||
emailsPanel.setLayout(new java.awt.GridBagLayout());
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 5;
|
||||
gridBagConstraints.gridwidth = 4;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(6, 19, 0, 0);
|
||||
add(emailsPanel, gridBagConstraints);
|
||||
|
||||
othersLabel.setFont(othersLabel.getFont().deriveFont(othersLabel.getFont().getStyle() | java.awt.Font.BOLD, othersLabel.getFont().getSize()+2));
|
||||
org.openide.awt.Mnemonics.setLocalizedText(othersLabel, org.openide.util.NbBundle.getMessage(ContactArtifactViewer.class, "ContactArtifactViewer.othersLabel.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 6;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(6, 19, 0, 0);
|
||||
add(othersLabel, gridBagConstraints);
|
||||
|
||||
otherAttrsPanel.setLayout(new java.awt.GridBagLayout());
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 7;
|
||||
gridBagConstraints.gridwidth = 4;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(6, 19, 0, 0);
|
||||
add(otherAttrsPanel, gridBagConstraints);
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 8;
|
||||
gridBagConstraints.gridheight = 2;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL;
|
||||
gridBagConstraints.weighty = 0.1;
|
||||
add(interPanelfiller, gridBagConstraints);
|
||||
|
||||
personasLabel.setFont(personasLabel.getFont().deriveFont(personasLabel.getFont().getStyle() | java.awt.Font.BOLD, personasLabel.getFont().getSize()+2));
|
||||
org.openide.awt.Mnemonics.setLocalizedText(personasLabel, org.openide.util.NbBundle.getMessage(ContactArtifactViewer.class, "ContactArtifactViewer.personasLabel.text")); // NOI18N
|
||||
personasLabel.setMaximumSize(new java.awt.Dimension(90, 19));
|
||||
personasLabel.setMinimumSize(new java.awt.Dimension(90, 19));
|
||||
personasLabel.setPreferredSize(new java.awt.Dimension(90, 19));
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 9;
|
||||
gridBagConstraints.gridwidth = 3;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(6, 19, 0, 0);
|
||||
add(personasLabel, gridBagConstraints);
|
||||
|
||||
personasPanel.setLayout(new java.awt.GridBagLayout());
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 10;
|
||||
gridBagConstraints.gridwidth = 4;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL;
|
||||
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
|
||||
gridBagConstraints.insets = new java.awt.Insets(6, 19, 0, 0);
|
||||
add(personasPanel, gridBagConstraints);
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 11;
|
||||
gridBagConstraints.gridwidth = 4;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
|
||||
gridBagConstraints.weighty = 1.0;
|
||||
add(bottomFiller, gridBagConstraints);
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 4;
|
||||
gridBagConstraints.gridy = 3;
|
||||
gridBagConstraints.gridheight = 8;
|
||||
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
|
||||
gridBagConstraints.ipadx = 2;
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
add(rightFiller, gridBagConstraints);
|
||||
|
||||
contactImage.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/defaultContact.png"))); // NOI18N
|
||||
org.openide.awt.Mnemonics.setLocalizedText(contactImage, org.openide.util.NbBundle.getMessage(ContactArtifactViewer.class, "ContactArtifactViewer.contactImage.text")); // NOI18N
|
||||
gridBagConstraints = new java.awt.GridBagConstraints();
|
||||
gridBagConstraints.gridx = 0;
|
||||
gridBagConstraints.gridy = 0;
|
||||
gridBagConstraints.insets = new java.awt.Insets(6, 19, 0, 0);
|
||||
add(contactImage, gridBagConstraints);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
@Override
|
||||
public void setArtifact(BlackboardArtifact artifact) {
|
||||
|
||||
// Reset the panel.
|
||||
resetComponent();
|
||||
|
||||
@ -268,15 +128,50 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
return;
|
||||
}
|
||||
|
||||
List<BlackboardAttribute> phoneNumList = new ArrayList<>();
|
||||
List<BlackboardAttribute> emailList = new ArrayList<>();
|
||||
List<BlackboardAttribute> nameList = new ArrayList<>();
|
||||
List<BlackboardAttribute> otherList = new ArrayList<>();
|
||||
List<BlackboardAttribute> accountAttributesList = new ArrayList<>();
|
||||
|
||||
try {
|
||||
extractArtifactData(artifact);
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, String.format("Error getting attributes for artifact (artifact_id=%d, obj_id=%d)", artifact.getArtifactID(), artifact.getObjectID()), ex);
|
||||
return;
|
||||
}
|
||||
|
||||
updateView();
|
||||
|
||||
this.setLayout(this.m_gridBagLayout);
|
||||
this.revalidate();
|
||||
this.repaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getComponent() {
|
||||
// Slap a vertical scrollbar on the panel.
|
||||
return new JScrollPane(this, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupported(BlackboardArtifact artifact) {
|
||||
return (artifact != null)
|
||||
&& (artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT.getTypeID());
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts data from the artifact to be displayed in the panel.
|
||||
*
|
||||
* @param artifact Artifact to show.
|
||||
* @throws TskCoreException
|
||||
*/
|
||||
private void extractArtifactData(BlackboardArtifact artifact) throws TskCoreException {
|
||||
|
||||
this.contactArtifact = artifact;
|
||||
|
||||
phoneNumList = new ArrayList<>();
|
||||
emailList = new ArrayList<>();
|
||||
nameList = new ArrayList<>();
|
||||
otherList = new ArrayList<>();
|
||||
accountAttributesList = new ArrayList<>();
|
||||
|
||||
// Get all the attributes and group them by the section panels they go in
|
||||
for (BlackboardAttribute bba : artifact.getAttributes()) {
|
||||
for (BlackboardAttribute bba : contactArtifact.getAttributes()) {
|
||||
if (bba.getAttributeType().getTypeName().startsWith("TSK_PHONE")) {
|
||||
phoneNumList.add(bba);
|
||||
accountAttributesList.add(bba);
|
||||
@ -292,234 +187,215 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, String.format("Error getting attributes for artifact (artifact_id=%d, obj_id=%d)", artifact.getArtifactID(), artifact.getObjectID()), ex);
|
||||
|
||||
datasourceName = contactArtifact.getDataSource().getName();
|
||||
}
|
||||
// update name section
|
||||
updateNamePanel(nameList);
|
||||
|
||||
/**
|
||||
* Updates the view with the data extracted from the artifact.
|
||||
*/
|
||||
private void updateView() {
|
||||
|
||||
// Update contact name, image, phone numbers
|
||||
updateContactDetails();
|
||||
|
||||
// update artifact source panel
|
||||
updateSource();
|
||||
|
||||
// show a empty Personas panel and kick off a serch for personas
|
||||
initiatePersonasSearch();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the view with contact's details.
|
||||
*/
|
||||
@NbBundle.Messages({
|
||||
"ContactArtifactViewer_phones_header=Phone",
|
||||
"ContactArtifactViewer_emails_header=Email",
|
||||
"ContactArtifactViewer_others_header=Other",})
|
||||
private void updateContactDetails() {
|
||||
|
||||
// update image and name.
|
||||
updateContactImage(m_gridBagLayout, m_constraints);
|
||||
updateContactName(m_gridBagLayout, m_constraints);
|
||||
|
||||
// update contact attributes sections
|
||||
updateSection(phoneNumList, this.phonesLabel, this.phoneNumbersPanel);
|
||||
updateSection(emailList, this.emailsLabel, this.emailsPanel);
|
||||
updateSection(otherList, this.othersLabel, this.otherAttrsPanel);
|
||||
|
||||
try {
|
||||
initiatePersonasSearch(accountAttributesList);
|
||||
} catch (CentralRepoException ex) {
|
||||
logger.log(Level.SEVERE, String.format("Error getting Personas for Contact artifact (artifact_id=%d, obj_id=%d)", artifact.getArtifactID(), artifact.getObjectID()), ex);
|
||||
}
|
||||
|
||||
contactImage.setIcon(getImageFromArtifact(artifact));
|
||||
|
||||
// repaint
|
||||
this.revalidate();
|
||||
this.repaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getComponent() {
|
||||
// Slap a vertical scrollbar on the panel.
|
||||
return new JScrollPane(this, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
updateContactMethodSection(phoneNumList, Bundle.ContactArtifactViewer_phones_header(), m_gridBagLayout, m_constraints);
|
||||
updateContactMethodSection(emailList, Bundle.ContactArtifactViewer_emails_header(), m_gridBagLayout, m_constraints);
|
||||
updateContactMethodSection(otherList, Bundle.ContactArtifactViewer_others_header(), m_gridBagLayout, m_constraints);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given artifact is supported by this viewer. This viewer
|
||||
* supports TSK_CONTACT artifacts.
|
||||
* Updates the contact image in the view.
|
||||
*
|
||||
* @param artifact artifact to check.
|
||||
* @param contactPanelLayout Panel layout.
|
||||
* @param contactPanelConstraints Layout constraints.
|
||||
*
|
||||
* @return True if the artifact is supported, false otherwise.
|
||||
*/
|
||||
@Override
|
||||
public boolean isSupported(BlackboardArtifact artifact) {
|
||||
return artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT.getTypeID();
|
||||
}
|
||||
@NbBundle.Messages({
|
||||
"ContactArtifactViewer.contactImage.text=",})
|
||||
private void updateContactImage(GridBagLayout contactPanelLayout, GridBagConstraints contactPanelConstraints) {
|
||||
// place the image on the top right corner
|
||||
Insets savedInsets = contactPanelConstraints.insets;
|
||||
contactPanelConstraints.gridy = 0;
|
||||
contactPanelConstraints.gridx = 0;
|
||||
contactPanelConstraints.insets = new Insets(0, 0, 0, 0);
|
||||
|
||||
/**
|
||||
* Clears all artifact specific state.
|
||||
*/
|
||||
private void resetComponent() {
|
||||
contactNameLabel.setVisible(false);
|
||||
emailsLabel.setVisible(false);
|
||||
emailsPanel.removeAll();
|
||||
//namePanel.removeAll(); // this is not dynamically populated, do not remove.
|
||||
otherAttrsPanel.removeAll();
|
||||
othersLabel.setVisible(false);
|
||||
personasLabel.setVisible(false);
|
||||
personasPanel.removeAll();
|
||||
phoneNumbersPanel.removeAll();
|
||||
phonesLabel.setVisible(false);
|
||||
javax.swing.JLabel contactImage = new javax.swing.JLabel();
|
||||
contactImage.setIcon(getImageFromArtifact(contactArtifact));
|
||||
contactImage.setText(Bundle.ContactArtifactViewer_contactImage_text());
|
||||
|
||||
contactName = null;
|
||||
contactUniqueAccountsList.clear();
|
||||
contactUniquePersonasMap.clear();
|
||||
contactImage.setIcon(defaultImage);
|
||||
// add image to top left corner of the page.
|
||||
CommunicationArtifactViewerHelper.addComponent(this, contactPanelLayout, contactPanelConstraints, contactImage);
|
||||
CommunicationArtifactViewerHelper.addLineEndGlue(this, contactPanelLayout, contactPanelConstraints);
|
||||
contactPanelConstraints.gridy++;
|
||||
|
||||
contactPanelConstraints.insets = savedInsets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the contact name in the view.
|
||||
*
|
||||
* @param attributesList
|
||||
* @param contactPanelLayout Panel layout.
|
||||
* @param contactPanelConstraints Layout constraints.
|
||||
*
|
||||
*/
|
||||
private void updateNamePanel(List<BlackboardAttribute> attributesList) {
|
||||
for (BlackboardAttribute bba : attributesList) {
|
||||
if (bba.getAttributeType().getTypeName().startsWith("TSK_NAME")) {
|
||||
@NbBundle.Messages({
|
||||
"ContactArtifactViewer_contactname_unknown=Unknown",})
|
||||
private void updateContactName(GridBagLayout contactPanelLayout, GridBagConstraints contactPanelConstraints) {
|
||||
|
||||
boolean foundName = false;
|
||||
for (BlackboardAttribute bba : this.nameList) {
|
||||
if (StringUtils.isEmpty(bba.getValueString()) == false) {
|
||||
contactName = bba.getDisplayString();
|
||||
contactNameLabel.setText(contactName);
|
||||
contactNameLabel.setVisible(true);
|
||||
|
||||
CommunicationArtifactViewerHelper.addHeader(this, contactPanelLayout, contactPanelConstraints, contactName);
|
||||
foundName = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
contactNameLabel.revalidate();
|
||||
if (foundName == false) {
|
||||
CommunicationArtifactViewerHelper.addHeader(this, contactPanelLayout, contactPanelConstraints, Bundle.ContactArtifactViewer_contactname_unknown());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the view by displaying the given list of attributes in the given
|
||||
* section panel.
|
||||
*
|
||||
* @param sectionAttributesList list of attributes to display.
|
||||
* @param sectionLabel section name label.
|
||||
* @param sectionPanel section panel to display the attributes in.
|
||||
* @param sectionAttributesList List of attributes to display.
|
||||
* @param sectionLabel Section name label.
|
||||
* @param contactPanelLayout Panel layout.
|
||||
* @param contactPanelConstraints Layout constraints.
|
||||
*
|
||||
*/
|
||||
private void updateSection(List<BlackboardAttribute> sectionAttributesList, JLabel sectionLabel, JPanel sectionPanel) {
|
||||
@NbBundle.Messages({
|
||||
"ContactArtifactViewer_plural_suffix=s",})
|
||||
private void updateContactMethodSection(List<BlackboardAttribute> sectionAttributesList, String sectionHeader, GridBagLayout contactPanelLayout, GridBagConstraints contactPanelConstraints) {
|
||||
|
||||
// If there are no attributes for tis section, hide the section panel and the section label
|
||||
// If there are no attributes for this section, do nothing
|
||||
if (sectionAttributesList.isEmpty()) {
|
||||
sectionLabel.setVisible(false);
|
||||
sectionPanel.setVisible(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// create a gridbag layout to show each attribute on one line
|
||||
GridBagLayout gridBagLayout = new GridBagLayout();
|
||||
GridBagConstraints constraints = new GridBagConstraints();
|
||||
constraints.anchor = GridBagConstraints.FIRST_LINE_START;
|
||||
constraints.gridy = 0;
|
||||
constraints.insets = new java.awt.Insets(TOP_INSET, LEFT_INSET, 0, 0);
|
||||
for (BlackboardAttribute bba : sectionAttributesList) {
|
||||
constraints.fill = GridBagConstraints.NONE;
|
||||
constraints.weightx = 0;
|
||||
|
||||
constraints.gridx = 0;
|
||||
|
||||
// Add a label for attribute type
|
||||
javax.swing.JLabel attrTypeLabel = new javax.swing.JLabel();
|
||||
String attrLabel = bba.getAttributeType().getDisplayName();
|
||||
attrTypeLabel.setText(attrLabel);
|
||||
|
||||
// make type label bold - uncomment if needed.
|
||||
//attrTypeLabel.setFont(attrTypeLabel.getFont().deriveFont(Font.BOLD, attrTypeLabel.getFont().getSize() ));
|
||||
gridBagLayout.setConstraints(attrTypeLabel, constraints);
|
||||
sectionPanel.add(attrTypeLabel);
|
||||
|
||||
// Add the attribute value
|
||||
constraints.gridx++;
|
||||
javax.swing.JLabel attrValueLabel = new javax.swing.JLabel();
|
||||
attrValueLabel.setText(bba.getValueString());
|
||||
gridBagLayout.setConstraints(attrValueLabel, constraints);
|
||||
sectionPanel.add(attrValueLabel);
|
||||
|
||||
// add a filler to take up rest of the space
|
||||
constraints.gridx++;
|
||||
constraints.weightx = 1.0;
|
||||
constraints.fill = GridBagConstraints.HORIZONTAL;
|
||||
sectionPanel.add(new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(32767, 0)));
|
||||
|
||||
constraints.gridy++;
|
||||
String sectionHeaderString = sectionHeader;
|
||||
if (sectionAttributesList.size() > 1) {
|
||||
sectionHeaderString = sectionHeaderString.concat(Bundle.ContactArtifactViewer_plural_suffix());
|
||||
}
|
||||
CommunicationArtifactViewerHelper.addHeader(this, contactPanelLayout, contactPanelConstraints, sectionHeaderString);
|
||||
for (BlackboardAttribute bba : sectionAttributesList) {
|
||||
CommunicationArtifactViewerHelper.addKey(this, contactPanelLayout, contactPanelConstraints, bba.getAttributeType().getDisplayName());
|
||||
CommunicationArtifactViewerHelper.addValue(this, contactPanelLayout, contactPanelConstraints, bba.getDisplayString());
|
||||
}
|
||||
|
||||
sectionLabel.setVisible(true);
|
||||
sectionPanel.setVisible(true);
|
||||
|
||||
sectionPanel.setLayout(gridBagLayout);
|
||||
sectionPanel.revalidate();
|
||||
sectionPanel.repaint();
|
||||
}
|
||||
|
||||
/**
|
||||
* Kicks off a search for personas, based in the list of attributes.
|
||||
* Updates the source section.
|
||||
*/
|
||||
@NbBundle.Messages({
|
||||
"ContactArtifactViewer_heading_Source=Source",
|
||||
"ContactArtifactViewer_label_datasource=Data Source",})
|
||||
private void updateSource() {
|
||||
CommunicationArtifactViewerHelper.addHeader(this, this.m_gridBagLayout, m_constraints, Bundle.ContactArtifactViewer_heading_Source());
|
||||
CommunicationArtifactViewerHelper.addKey(this, m_gridBagLayout, m_constraints, Bundle.ContactArtifactViewer_label_datasource());
|
||||
CommunicationArtifactViewerHelper.addValue(this, m_gridBagLayout, m_constraints, datasourceName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Kicks off a search for personas, based in the given list of attributes.
|
||||
*
|
||||
* @param accountAttributesList a list of account identifying attributes.
|
||||
*
|
||||
* @throws CentralRepoException
|
||||
*/
|
||||
@NbBundle.Messages({
|
||||
"ContactArtifactViewer_persona_searching= Searching...",
|
||||
"ContactArtifactViewer_persona_header=Persona",
|
||||
"ContactArtifactViewer_persona_searching=Searching...",
|
||||
"ContactArtifactViewer_cr_disabled_message=Enable Central Repository to view, create and edit personas.",
|
||||
"ContactArtifactViewer_persona_unknown=Unknown"
|
||||
})
|
||||
private void initiatePersonasSearch(List<BlackboardAttribute> accountAttributesList) throws CentralRepoException {
|
||||
|
||||
personasLabel.setVisible(true);
|
||||
/**
|
||||
* Initiates a search for Personas for the accounts associated with the
|
||||
* Contact.
|
||||
*
|
||||
*/
|
||||
private void initiatePersonasSearch() {
|
||||
|
||||
// add a section header
|
||||
JLabel personaHeader = CommunicationArtifactViewerHelper.addHeader(this, m_gridBagLayout, m_constraints, Bundle.ContactArtifactViewer_persona_header());
|
||||
|
||||
m_constraints.gridy++;
|
||||
|
||||
// add a status label
|
||||
String personaStatusLabelText = CentralRepository.isEnabled()
|
||||
? Bundle.ContactArtifactViewer_persona_searching()
|
||||
: Bundle.ContactArtifactViewer_persona_unknown();
|
||||
|
||||
// create a gridbag layout to show each participant on one line
|
||||
GridBagLayout gridBagLayout = new GridBagLayout();
|
||||
GridBagConstraints constraints = new GridBagConstraints();
|
||||
constraints.anchor = GridBagConstraints.FIRST_LINE_START;
|
||||
constraints.gridx = 0;
|
||||
constraints.gridy = 0;
|
||||
constraints.insets = new java.awt.Insets(TOP_INSET, LEFT_INSET, 0, 0);
|
||||
this.personaSearchStatusLabel = new javax.swing.JLabel();
|
||||
personaSearchStatusLabel.setText(personaStatusLabelText);
|
||||
|
||||
// Add a Persona Name label
|
||||
constraints.fill = GridBagConstraints.NONE;
|
||||
constraints.weightx = 0;
|
||||
m_constraints.gridx = 0;
|
||||
|
||||
//javax.swing.Box.Filler filler1 = this.createFiller(5, 0);
|
||||
//personasPanel.add(filler1, constraints);
|
||||
javax.swing.JLabel personaLabel = new javax.swing.JLabel();
|
||||
personaLabel.setText(Bundle.ContactArtifactViewer_persona_label());
|
||||
personaLabel.setFont(personaLabel.getFont().deriveFont(Font.BOLD, personaLabel.getFont().getSize()));
|
||||
gridBagLayout.setConstraints(personaLabel, constraints);
|
||||
personasPanel.add(personaLabel);
|
||||
|
||||
constraints.gridy++;
|
||||
javax.swing.JLabel personaStatusLabel = new javax.swing.JLabel();
|
||||
personaStatusLabel.setText(personaStatusLabelText);
|
||||
gridBagLayout.setConstraints(personaStatusLabel, constraints);
|
||||
personasPanel.add(personaStatusLabel);
|
||||
|
||||
|
||||
if (CentralRepository.isEnabled() ) {
|
||||
personasLabel.setEnabled(true);
|
||||
CommunicationArtifactViewerHelper.addComponent(this, m_gridBagLayout, m_constraints, personaSearchStatusLabel);
|
||||
|
||||
if (CentralRepository.isEnabled()) {
|
||||
// Kick off a background task to serach for personas for the contact
|
||||
ContactPersonaSearcherTask personaSearchTask = new ContactPersonaSearcherTask(accountAttributesList);
|
||||
personaSearchTask = new ContactPersonaSearcherTask(accountAttributesList);
|
||||
personaSearchTask.execute();
|
||||
} else {
|
||||
personasLabel.setEnabled(false);
|
||||
personaLabel.setEnabled(false);
|
||||
personaStatusLabel.setEnabled(false);
|
||||
personaHeader.setEnabled(false);
|
||||
personaSearchStatusLabel.setEnabled(false);
|
||||
|
||||
CommunicationArtifactViewerHelper.addBlankLine(this, m_gridBagLayout, m_constraints);
|
||||
m_constraints.gridy++;
|
||||
CommunicationArtifactViewerHelper.addMessageRow(this, m_gridBagLayout, m_constraints, Bundle.ContactArtifactViewer_cr_disabled_message());
|
||||
m_constraints.gridy++;
|
||||
|
||||
CommunicationArtifactViewerHelper.addPageEndGlue(this, m_gridBagLayout, this.m_constraints);
|
||||
}
|
||||
|
||||
personasPanel.setLayout(gridBagLayout);
|
||||
personasPanel.revalidate();
|
||||
personasPanel.repaint();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the Persona panel with the gathered persona information.
|
||||
*/
|
||||
private void updatePersonasPanel() {
|
||||
// Clear out the panel
|
||||
personasPanel.removeAll();
|
||||
private void updatePersonas() {
|
||||
|
||||
GridBagLayout gridBagLayout = new GridBagLayout();
|
||||
GridBagConstraints constraints = new GridBagConstraints();
|
||||
constraints.anchor = GridBagConstraints.FIRST_LINE_START;
|
||||
constraints.gridx = 0;
|
||||
constraints.gridy = 0;
|
||||
constraints.insets = new java.awt.Insets(TOP_INSET, LEFT_INSET, 0, 0);
|
||||
// Remove the "Searching....." label
|
||||
this.remove(personaSearchStatusLabel);
|
||||
|
||||
m_constraints.gridx = 0;
|
||||
if (contactUniquePersonasMap.isEmpty()) {
|
||||
showPersona(null, Collections.emptyList(), gridBagLayout, constraints);
|
||||
// No persona found - show a button to create one.
|
||||
showPersona(null, 0, Collections.emptyList(), this.m_gridBagLayout, this.m_constraints);
|
||||
} else {
|
||||
int matchCounter = 0;
|
||||
for (Map.Entry<Persona, ArrayList<CentralRepoAccount>> entry : contactUniquePersonasMap.entrySet()) {
|
||||
List<CentralRepoAccount> missingAccounts = new ArrayList<>();
|
||||
ArrayList<CentralRepoAccount> personaAccounts = entry.getValue();
|
||||
matchCounter++;
|
||||
|
||||
// create a list of accounts missing from this persona
|
||||
for (CentralRepoAccount account : contactUniqueAccountsList) {
|
||||
@ -528,52 +404,51 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
}
|
||||
}
|
||||
|
||||
showPersona(entry.getKey(), missingAccounts, gridBagLayout, constraints);
|
||||
|
||||
constraints.gridy += 2;
|
||||
showPersona(entry.getKey(), matchCounter, missingAccounts, m_gridBagLayout, m_constraints);
|
||||
m_constraints.gridy += 2;
|
||||
}
|
||||
}
|
||||
|
||||
personasPanel.setLayout(gridBagLayout);
|
||||
personasPanel.setSize(personasPanel.getPreferredSize());
|
||||
personasPanel.revalidate();
|
||||
personasPanel.repaint();
|
||||
}
|
||||
// add veritcal glue at the end
|
||||
CommunicationArtifactViewerHelper.addPageEndGlue(this, m_gridBagLayout, this.m_constraints);
|
||||
|
||||
@NbBundle.Messages({
|
||||
"ContactArtifactViewer_persona_label=Persona ",
|
||||
"ContactArtifactViewer_persona_text_none=None found",
|
||||
"ContactArtifactViewer_persona_button_view=View",
|
||||
"ContactArtifactViewer_persona_button_new=Create",
|
||||
"ContactArtifactViewer_missing_account_label=Missing Account: "
|
||||
})
|
||||
// redraw the panel
|
||||
this.setLayout(this.m_gridBagLayout);
|
||||
this.revalidate();
|
||||
this.repaint();
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the given persona in the persona panel.
|
||||
*
|
||||
* @param persona Persona to display.
|
||||
* @param missingAccountsList List of accounts this persona may be missing.
|
||||
* @param missingAccountsList List of contact accounts this persona may be
|
||||
* missing.
|
||||
* @param gridBagLayout Layout to use.
|
||||
* @param constraints layout constraints.
|
||||
*
|
||||
* @throws CentralRepoException
|
||||
*/
|
||||
private void showPersona(Persona persona, List<CentralRepoAccount> missingAccountsList, GridBagLayout gridBagLayout, GridBagConstraints constraints) {
|
||||
@NbBundle.Messages({
|
||||
"ContactArtifactViewer_persona_label=Persona ",
|
||||
"ContactArtifactViewer_persona_no_match=No matches found",
|
||||
"ContactArtifactViewer_persona_button_view=View",
|
||||
"ContactArtifactViewer_persona_button_new=Create",
|
||||
"ContactArtifactViewer_persona_match_num=Match ",
|
||||
"ContactArtifactViewer_missing_account_label=Missing contact account",
|
||||
"ContactArtifactViewer_found_all_accounts_label=All accounts found."
|
||||
})
|
||||
private void showPersona(Persona persona, int matchNumber, List<CentralRepoAccount> missingAccountsList, GridBagLayout gridBagLayout, GridBagConstraints constraints) {
|
||||
|
||||
constraints.fill = GridBagConstraints.NONE;
|
||||
constraints.weightx = 0;
|
||||
// save the original insets
|
||||
Insets savedInsets = constraints.insets;
|
||||
|
||||
// some label are indented 2x to appear indented w.r.t column above
|
||||
Insets extraIndentInsets = new java.awt.Insets(0, 2 * CommunicationArtifactViewerHelper.LEFT_INSET, 0, 0);
|
||||
|
||||
// Add a Match X label in col 0.
|
||||
constraints.gridx = 0;
|
||||
|
||||
//javax.swing.Box.Filler filler1 = createFiller(5, 0);
|
||||
// gridBagLayout.setConstraints(filler1, constraints);
|
||||
//personasPanel.add(filler1);
|
||||
// Add a "Persona" label
|
||||
//constraints.gridx++;
|
||||
javax.swing.JLabel personaLabel = new javax.swing.JLabel();
|
||||
personaLabel.setText(Bundle.ContactArtifactViewer_persona_label());
|
||||
personaLabel.setFont(personaLabel.getFont().deriveFont(Font.BOLD, personaLabel.getFont().getSize()));
|
||||
gridBagLayout.setConstraints(personaLabel, constraints);
|
||||
personasPanel.add(personaLabel);
|
||||
javax.swing.JLabel matchNumberLabel = CommunicationArtifactViewerHelper.addKey(this, gridBagLayout, constraints, String.format("%s %d", Bundle.ContactArtifactViewer_persona_match_num(), matchNumber));
|
||||
|
||||
javax.swing.JLabel personaNameLabel = new javax.swing.JLabel();
|
||||
javax.swing.JButton personaButton = new javax.swing.JButton();
|
||||
@ -581,60 +456,111 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
String personaName;
|
||||
String personaButtonText;
|
||||
ActionListener personaButtonListener;
|
||||
|
||||
if (persona != null) {
|
||||
personaName = persona.getName();
|
||||
personaButtonText = Bundle.ContactArtifactViewer_persona_button_view();
|
||||
personaButtonListener = new ViewPersonaButtonListener(persona);
|
||||
personaButtonListener = new ViewPersonaButtonListener(this, persona);
|
||||
} else {
|
||||
personaName = Bundle.ContactArtifactViewer_persona_text_none();
|
||||
matchNumberLabel.setVisible(false);
|
||||
personaName = Bundle.ContactArtifactViewer_persona_no_match();
|
||||
personaButtonText = Bundle.ContactArtifactViewer_persona_button_new();
|
||||
personaButtonListener = new CreatePersonaButtonListener(new PersonaUIComponents(personaNameLabel, personaButton));
|
||||
personaButtonListener = new CreatePersonaButtonListener(this, new PersonaUIComponents(personaNameLabel, personaButton));
|
||||
}
|
||||
|
||||
// Add the label for persona name,
|
||||
constraints.gridy++;
|
||||
constraints.gridx = 0;
|
||||
//constraints.gridwidth = 1; // TBD: this may not be needed if we use single panel
|
||||
constraints.gridx++;
|
||||
personaNameLabel.setText(personaName);
|
||||
gridBagLayout.setConstraints(personaNameLabel, constraints);
|
||||
personasPanel.add(personaNameLabel);
|
||||
CommunicationArtifactViewerHelper.addComponent(this, gridBagLayout, constraints, personaNameLabel);
|
||||
//personasPanel.add(personaNameLabel);
|
||||
|
||||
//constraints.gridx++;
|
||||
//personasPanel.add(createFiller(5, 0), constraints);
|
||||
// Add a Persona action button
|
||||
constraints.gridx++;
|
||||
//constraints.gridwidth = 1;
|
||||
personaButton.setText(personaButtonText);
|
||||
personaButton.addActionListener(personaButtonListener);
|
||||
|
||||
// no top inset of the button, in order to center align with the labels.
|
||||
constraints.insets = new java.awt.Insets(0, LEFT_INSET, 0, 0);
|
||||
// Shirnk the button height.
|
||||
personaButton.setMargin(new Insets(0, 5, 0, 5));
|
||||
gridBagLayout.setConstraints(personaButton, constraints);
|
||||
personasPanel.add(personaButton);
|
||||
CommunicationArtifactViewerHelper.addComponent(this, gridBagLayout, constraints, personaButton);
|
||||
CommunicationArtifactViewerHelper.addLineEndGlue(this, gridBagLayout, constraints);
|
||||
|
||||
// restore normal inset
|
||||
constraints.insets = new java.awt.Insets(TOP_INSET, LEFT_INSET, 0, 0);
|
||||
constraints.insets = savedInsets;
|
||||
|
||||
// if we have a persona, indicate if any of the contact's accounts are missing from it.
|
||||
if (persona != null) {
|
||||
if (missingAccountsList.isEmpty()) {
|
||||
constraints.gridy++;
|
||||
constraints.gridx = 1;
|
||||
//constraints.insets = labelInsets;
|
||||
|
||||
javax.swing.JLabel accountsStatus = new javax.swing.JLabel(Bundle.ContactArtifactViewer_found_all_accounts_label());
|
||||
constraints.insets = extraIndentInsets;
|
||||
CommunicationArtifactViewerHelper.addComponent(this, gridBagLayout, constraints, accountsStatus);
|
||||
constraints.insets = savedInsets;
|
||||
|
||||
CommunicationArtifactViewerHelper.addLineEndGlue(this, gridBagLayout, constraints);
|
||||
} else {
|
||||
// show missing accounts.
|
||||
for (CentralRepoAccount missingAccount : missingAccountsList) {
|
||||
constraints.weightx = 0;
|
||||
//constraints.weightx = 0;
|
||||
constraints.gridx = 0;
|
||||
constraints.gridy++;
|
||||
|
||||
// Add a "Missing Account: " label
|
||||
constraints.gridx++; // Ident
|
||||
javax.swing.JLabel missingAccountLabel = new javax.swing.JLabel();
|
||||
missingAccountLabel.setText(Bundle.ContactArtifactViewer_missing_account_label());
|
||||
gridBagLayout.setConstraints(missingAccountLabel, constraints);
|
||||
personasPanel.add(missingAccountLabel);
|
||||
// this needs an extra indent
|
||||
constraints.insets = extraIndentInsets;
|
||||
CommunicationArtifactViewerHelper.addKeyAtCol(this, gridBagLayout, constraints, Bundle.ContactArtifactViewer_missing_account_label(), 1);
|
||||
constraints.insets = savedInsets;
|
||||
|
||||
// Add the label for account id,
|
||||
constraints.gridx++;
|
||||
javax.swing.JLabel missingAccountIdentifierLabel = new javax.swing.JLabel();
|
||||
missingAccountIdentifierLabel.setText(missingAccount.getIdentifier());
|
||||
gridBagLayout.setConstraints(missingAccountIdentifierLabel, constraints);
|
||||
personasPanel.add(missingAccountIdentifierLabel);
|
||||
CommunicationArtifactViewerHelper.addValueAtCol(this, gridBagLayout, constraints, missingAccount.getIdentifier(), 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// restore insets
|
||||
constraints.insets = savedInsets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets all artifact specific state.
|
||||
*/
|
||||
private void resetComponent() {
|
||||
|
||||
contactArtifact = null;
|
||||
contactName = null;
|
||||
datasourceName = null;
|
||||
|
||||
contactUniqueAccountsList.clear();
|
||||
contactUniquePersonasMap.clear();
|
||||
|
||||
phoneNumList.clear();
|
||||
emailList.clear();
|
||||
nameList.clear();
|
||||
otherList.clear();
|
||||
accountAttributesList.clear();
|
||||
|
||||
if (personaSearchTask != null) {
|
||||
personaSearchTask.cancel(Boolean.TRUE);
|
||||
personaSearchTask = null;
|
||||
}
|
||||
|
||||
// clear the panel
|
||||
this.removeAll();
|
||||
this.setLayout(null);
|
||||
|
||||
m_gridBagLayout = new GridBagLayout();
|
||||
m_constraints = new GridBagConstraints();
|
||||
|
||||
m_constraints.anchor = GridBagConstraints.FIRST_LINE_START;
|
||||
m_constraints.gridy = 0;
|
||||
m_constraints.gridx = 0;
|
||||
m_constraints.weighty = 0.0;
|
||||
m_constraints.weightx = 0.0; // keep components fixed horizontally.
|
||||
m_constraints.insets = new java.awt.Insets(0, CommunicationArtifactViewerHelper.LEFT_INSET, 0, 0);
|
||||
m_constraints.fill = GridBagConstraints.NONE;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an image from a TSK_CONTACT artifact.
|
||||
@ -666,7 +592,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
imageIcon = new ImageIcon(image);
|
||||
break;
|
||||
} catch (IOException ex) {
|
||||
// ImageIO.read will through an IOException if file is not an image
|
||||
// ImageIO.read will throw an IOException if file is not an image
|
||||
// therefore we don't need to report this exception just try
|
||||
// the next file.
|
||||
}
|
||||
@ -703,6 +629,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
|
||||
Map<Persona, ArrayList<CentralRepoAccount>> uniquePersonas = new HashMap<>();
|
||||
|
||||
// TBD: this search needs to change to use the new method CommunicationsManager.getAccountsRelatedToArtifact
|
||||
for (BlackboardAttribute bba : accountAttributesList) {
|
||||
|
||||
// Get account, add to accounts list
|
||||
@ -736,7 +663,6 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return uniquePersonas;
|
||||
@ -758,7 +684,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
contactUniqueAccountsList.clear();
|
||||
contactUniqueAccountsList.addAll(uniqueAccountsList);
|
||||
|
||||
updatePersonasPanel();
|
||||
updatePersonas();
|
||||
|
||||
} catch (CancellationException ex) {
|
||||
logger.log(Level.INFO, "Persona searching was canceled."); //NON-NLS
|
||||
@ -815,6 +741,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
*/
|
||||
private class CreatePersonaButtonListener implements ActionListener {
|
||||
|
||||
private final Component parentComponent;
|
||||
private final PersonaUIComponents personaUIComponents;
|
||||
|
||||
/**
|
||||
@ -822,8 +749,9 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
*
|
||||
* @param personaUIComponents UI components.
|
||||
*/
|
||||
CreatePersonaButtonListener(PersonaUIComponents personaUIComponents) {
|
||||
CreatePersonaButtonListener(Component parentComponent, PersonaUIComponents personaUIComponents) {
|
||||
this.personaUIComponents = personaUIComponents;
|
||||
this.parentComponent = parentComponent;
|
||||
}
|
||||
|
||||
@NbBundle.Messages({
|
||||
@ -833,8 +761,8 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
@Override
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
// Launch the Persona Create dialog - do not display immediately
|
||||
PersonaDetailsDialog createPersonaDialog = new PersonaDetailsDialog(ContactArtifactViewer.this,
|
||||
PersonaDetailsMode.CREATE, null, new PersonaCreateCallbackImpl(personaUIComponents), false);
|
||||
PersonaDetailsDialog createPersonaDialog = new PersonaDetailsDialog(parentComponent,
|
||||
PersonaDetailsMode.CREATE, null, new PersonaCreateCallbackImpl(parentComponent, personaUIComponents), false);
|
||||
|
||||
// Pre populate the persona name and accounts if we have them.
|
||||
PersonaDetailsPanel personaPanel = createPersonaDialog.getDetailsPanel();
|
||||
@ -859,19 +787,21 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
private class ViewPersonaButtonListener implements ActionListener {
|
||||
|
||||
private final Persona persona;
|
||||
private final Component parentComponent;
|
||||
|
||||
/**
|
||||
* Creates listener for View persona button.
|
||||
*
|
||||
* @param persona
|
||||
*/
|
||||
ViewPersonaButtonListener(Persona persona) {
|
||||
ViewPersonaButtonListener(Component parentComponent, Persona persona) {
|
||||
this.persona = persona;
|
||||
this.parentComponent = parentComponent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
new PersonaDetailsDialog(ContactArtifactViewer.this,
|
||||
new PersonaDetailsDialog(parentComponent,
|
||||
PersonaDetailsMode.VIEW, persona, new PersonaViewCallbackImpl());
|
||||
}
|
||||
}
|
||||
@ -881,6 +811,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
*/
|
||||
class PersonaCreateCallbackImpl implements PersonaDetailsDialogCallback {
|
||||
|
||||
private final Component parentComponent;
|
||||
private final PersonaUIComponents personaUIComponents;
|
||||
|
||||
/**
|
||||
@ -888,7 +819,8 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
*
|
||||
* @param personaUIComponents UI Components.
|
||||
*/
|
||||
PersonaCreateCallbackImpl(PersonaUIComponents personaUIComponents) {
|
||||
PersonaCreateCallbackImpl(Component parentComponent, PersonaUIComponents personaUIComponents) {
|
||||
this.parentComponent = parentComponent;
|
||||
this.personaUIComponents = personaUIComponents;
|
||||
}
|
||||
|
||||
@ -905,7 +837,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
for (ActionListener act : personaButton.getActionListeners()) {
|
||||
personaButton.removeActionListener(act);
|
||||
}
|
||||
personaButton.addActionListener(new ViewPersonaButtonListener(persona));
|
||||
personaButton.addActionListener(new ViewPersonaButtonListener(parentComponent, persona));
|
||||
|
||||
}
|
||||
|
||||
@ -925,18 +857,6 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JLabel contactImage;
|
||||
private javax.swing.JLabel contactNameLabel;
|
||||
private javax.swing.JLabel emailsLabel;
|
||||
private javax.swing.JPanel emailsPanel;
|
||||
private javax.swing.JPanel namePanel;
|
||||
private javax.swing.JPanel otherAttrsPanel;
|
||||
private javax.swing.JLabel othersLabel;
|
||||
private javax.swing.JLabel personasLabel;
|
||||
private javax.swing.JPanel personasPanel;
|
||||
private javax.swing.JPanel phoneNumbersPanel;
|
||||
private javax.swing.JLabel phonesLabel;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/**
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2020 Basis Technology Corp.
|
||||
@ -22,83 +22,113 @@ import java.awt.Component;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.SwingWorker;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoAccount;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
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.coreutils.Logger;
|
||||
import org.sleuthkit.datamodel.Account;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.CommunicationsManager;
|
||||
|
||||
/**
|
||||
* Background task to search for a persona for a given account.
|
||||
*
|
||||
* When the search is complete, it updates the UI components
|
||||
* for the persona appropriately.
|
||||
*
|
||||
* SwingWorker for fetching and updating Persona controls.
|
||||
*/
|
||||
class PersonaAccountFetcher extends SwingWorker<Map<String, Collection<Persona>>, Void> {
|
||||
|
||||
@NbBundle.Messages({
|
||||
"# {0} - Persona count",
|
||||
"PersonaDisplayTask_persona_count_suffix=(1 of {0})"
|
||||
})
|
||||
class PersonaSearchAndDisplayTask extends SwingWorker<Collection<Persona>, Void> {
|
||||
|
||||
private final static Logger logger = Logger.getLogger(PersonaSearchAndDisplayTask.class.getName());
|
||||
private final static Logger logger = Logger.getLogger(PersonaAccountFetcher.class.getName());
|
||||
|
||||
private final BlackboardArtifact artifact;
|
||||
private final List<AccountPersonaSearcherData> personaSearchDataList;
|
||||
private final Component parentComponent;
|
||||
private final AccountPersonaSearcherData personaSearcherData;
|
||||
|
||||
PersonaSearchAndDisplayTask(Component parentComponent, AccountPersonaSearcherData personaSearcherData) {
|
||||
/**
|
||||
* Construct the SwingWorker.
|
||||
*
|
||||
* @param artifact The artifact to search account for.
|
||||
* @param personaSearchDataList List of PersonaSerarcherData objects.
|
||||
* @param parentComponent The parent panel.
|
||||
*/
|
||||
PersonaAccountFetcher(BlackboardArtifact artifact, List<AccountPersonaSearcherData> personaSearchDataList, Component parentComponent) {
|
||||
this.artifact = artifact;
|
||||
this.personaSearchDataList = personaSearchDataList;
|
||||
this.parentComponent = parentComponent;
|
||||
this.personaSearcherData = personaSearcherData;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<Persona> doInBackground() throws Exception {
|
||||
protected Map<String, Collection<Persona>> doInBackground() throws Exception {
|
||||
Map<String, Collection<Persona>> accountMap = new HashMap<>();
|
||||
|
||||
Collection<Persona> personas = new ArrayList<>();
|
||||
CommunicationsManager commManager = Case.getCurrentCase().getSleuthkitCase().getCommunicationsManager();
|
||||
|
||||
if (CentralRepository.isEnabled()) {
|
||||
Collection<CentralRepoAccount> accountCandidates
|
||||
= CentralRepoAccount.getAccountsWithIdentifier(personaSearcherData.getAccountIdentifer());
|
||||
List<Account> relatedAccountList = commManager.getAccountsRelatedToArtifact(artifact);
|
||||
|
||||
if (accountCandidates.isEmpty() == false) {
|
||||
CentralRepoAccount account = accountCandidates.iterator().next();
|
||||
for (Account account : relatedAccountList) {
|
||||
|
||||
// get personas for the account
|
||||
Collection<PersonaAccount> personaAccountsList = PersonaAccount.getPersonaAccountsForAccount(account.getId());
|
||||
personas = personaAccountsList.stream().map(PersonaAccount::getPersona)
|
||||
.collect(Collectors.toList());
|
||||
if (isCancelled()) {
|
||||
return new HashMap<>();
|
||||
}
|
||||
|
||||
Collection<PersonaAccount> personaAccountList = PersonaAccount.getPersonaAccountsForAccount(account);
|
||||
Collection<Persona> personaList = new ArrayList<>();
|
||||
for (PersonaAccount pAccount : personaAccountList) {
|
||||
personaList.add(pAccount.getPersona());
|
||||
}
|
||||
return personas;
|
||||
|
||||
accountMap.put(account.getTypeSpecificID(), personaList);
|
||||
}
|
||||
|
||||
return accountMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done() {
|
||||
Collection<Persona> personas;
|
||||
try {
|
||||
personas = super.get();
|
||||
|
||||
if (this.isCancelled()) {
|
||||
if (isCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Map<String, Collection<Persona>> accountMap = get();
|
||||
|
||||
for (AccountPersonaSearcherData searcherData : personaSearchDataList) {
|
||||
Collection<Persona> persona = accountMap.get(searcherData.getAccountIdentifer());
|
||||
updatePersonaControls(searcherData, persona);
|
||||
}
|
||||
|
||||
} catch (CancellationException ex) {
|
||||
logger.log(Level.INFO, "Persona searching was canceled."); //NON-NLS
|
||||
} catch (InterruptedException ex) {
|
||||
logger.log(Level.INFO, "Persona searching was interrupted."); //NON-NLS
|
||||
} catch (ExecutionException ex) {
|
||||
logger.log(Level.SEVERE, "Fatal error during Persona search.", ex); //NON-NLS
|
||||
}
|
||||
|
||||
parentComponent.repaint();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the Persona gui controls.
|
||||
*
|
||||
* @param personaSearcherData The data objects with persona controls
|
||||
* @param personas Collection of persona objects
|
||||
*/
|
||||
private void updatePersonaControls(AccountPersonaSearcherData personaSearcherData, Collection<Persona> personas) {
|
||||
//Update the Persona label and button based on the search result
|
||||
String personaLabelText = Bundle.CommunicationArtifactViewerHelper_persona_label();
|
||||
String personaButtonText;
|
||||
ActionListener buttonActionListener;
|
||||
|
||||
if (personas.isEmpty()) {
|
||||
if (personas == null || personas.isEmpty()) {
|
||||
// No persona found
|
||||
personaLabelText += Bundle.CommunicationArtifactViewerHelper_persona_unknown();
|
||||
|
||||
@ -122,14 +152,6 @@ class PersonaSearchAndDisplayTask extends SwingWorker<Collection<Persona>, Void>
|
||||
|
||||
// set button action
|
||||
personaSearcherData.getPersonaActionButton().addActionListener(buttonActionListener);
|
||||
} catch (CancellationException ex) {
|
||||
logger.log(Level.INFO, "Persona searching was canceled."); //NON-NLS
|
||||
} catch (InterruptedException ex) {
|
||||
logger.log(Level.INFO, "Persona searching was interrupted."); //NON-NLS
|
||||
} catch (ExecutionException ex) {
|
||||
logger.log(Level.SEVERE, "Fatal error during Persona search.", ex); //NON-NLS
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -217,4 +239,5 @@ class PersonaSearchAndDisplayTask extends SwingWorker<Collection<Persona>, Void>
|
||||
// nothing to do
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -290,6 +290,62 @@ public final class ContentUtils {
|
||||
return totalRead;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads all the data from any content object and writes (extracts) it to a
|
||||
* file, using a cancellation check instead of a Future object method.
|
||||
*
|
||||
* @param content Any content object.
|
||||
* @param outputFile Will be created if it doesn't exist, and overwritten
|
||||
* if it does
|
||||
* @param cancelCheck A function used to check if the file write process
|
||||
* should be terminated.
|
||||
* @param startingOffset the starting offset to start reading the file
|
||||
* @param endingOffset the ending offset to read of the file to write
|
||||
*
|
||||
* @return number of bytes extracted
|
||||
*
|
||||
* @throws IOException if file could not be written
|
||||
*/
|
||||
public static long writeToFile(Content content, java.io.File outputFile,
|
||||
Supplier<Boolean> cancelCheck, long startingOffset, long endingOffset) throws IOException {
|
||||
|
||||
InputStream in = new ReadContentInputStream(content);
|
||||
long totalRead = 0;
|
||||
try (FileOutputStream out = new FileOutputStream(outputFile, false)) {
|
||||
long offsetSkipped = in.skip(startingOffset);
|
||||
if (offsetSkipped != startingOffset) {
|
||||
in.close();
|
||||
throw new IOException(String.format("Skipping file to starting offset {0} was not successful only skipped to offset {1}.", startingOffset, offsetSkipped));
|
||||
}
|
||||
byte[] buffer = new byte[TO_FILE_BUFFER_SIZE];
|
||||
int len = in.read(buffer);
|
||||
long writeFileLength = endingOffset - startingOffset;
|
||||
writeFileLength = writeFileLength - TO_FILE_BUFFER_SIZE;
|
||||
while (len != -1 && writeFileLength != 0) {
|
||||
out.write(buffer, 0, len);
|
||||
totalRead += len;
|
||||
if (cancelCheck.get()) {
|
||||
break;
|
||||
}
|
||||
if (writeFileLength > TO_FILE_BUFFER_SIZE) {
|
||||
len = in.read(buffer);
|
||||
writeFileLength = writeFileLength - TO_FILE_BUFFER_SIZE;
|
||||
} else {
|
||||
int writeLength = (int)writeFileLength;
|
||||
byte[] lastBuffer = new byte[writeLength];
|
||||
len = in.read(lastBuffer);
|
||||
out.write(lastBuffer, 0, len);
|
||||
totalRead += len;
|
||||
writeFileLength = 0;
|
||||
}
|
||||
}
|
||||
|
||||
} finally {
|
||||
in.close();
|
||||
}
|
||||
return totalRead;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to ignore the '.' and '..' directories
|
||||
*
|
||||
|
@ -777,10 +777,6 @@ public class TimeLineController {
|
||||
case CONTENT_TAG_DELETED:
|
||||
future = executor.submit(() -> filteredEvents.handleContentTagDeleted((ContentTagDeletedEvent) evt));
|
||||
break;
|
||||
case CURRENT_CASE:
|
||||
//close timeline on case changes.
|
||||
SwingUtilities.invokeLater(TimeLineController.this::shutDownTimeLine);
|
||||
break;
|
||||
case DATA_SOURCE_ADDED:
|
||||
future = executor.submit(() -> {
|
||||
filteredEvents.handleDataSourceAdded();
|
||||
|
@ -86,19 +86,13 @@ public class TimeLineModule {
|
||||
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
try {
|
||||
getController().handleCaseEvent(evt);
|
||||
} catch (NoCurrentCaseException ex) {
|
||||
// ignore
|
||||
return;
|
||||
} catch (TskCoreException ex) {
|
||||
MessageNotifyUtil.Message.error("Error creating timeline controller.");
|
||||
logger.log(Level.SEVERE, "Error creating timeline controller", ex);
|
||||
}
|
||||
|
||||
if (Case.Events.valueOf(evt.getPropertyName()).equals(CURRENT_CASE)) {
|
||||
// we care only about case closing here
|
||||
if (evt.getNewValue() == null) {
|
||||
/*
|
||||
* Current case is closing, shut down the timeline top
|
||||
* component and set the pre case singleton controller
|
||||
* reference to null.
|
||||
*/
|
||||
synchronized (controllerLock) {
|
||||
if (controller != null) {
|
||||
SwingUtilities.invokeLater(controller::shutDownTimeLine);
|
||||
@ -106,6 +100,13 @@ public class TimeLineModule {
|
||||
controller = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
getController().handleCaseEvent(evt);
|
||||
} catch (NoCurrentCaseException ignored) {
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error handling application event", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -55,6 +55,7 @@ ExtractOs.windowsVolume.label=OS Drive (Windows)
|
||||
ExtractOs.yellowDogLinuxOs.label=Linux (Yellow Dog)
|
||||
ExtractOs.yellowDogLinuxVolume.label=OS Drive (Linux Yellow Dog)
|
||||
ExtractOS_progressMessage=Checking for OS
|
||||
ExtractPrefetch_module_name=Windows Prefetch Extractor
|
||||
ExtractRecycleBin_module_name=Recycle Bin
|
||||
ExtractSafari_Error_Getting_History=An error occurred while processing Safari history files.
|
||||
ExtractSafari_Error_Parsing_Bookmark=An error occured while processing Safari Bookmark files
|
||||
|
@ -0,0 +1,388 @@
|
||||
/*
|
||||
*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2020 Basis Technology Corp.
|
||||
*
|
||||
*
|
||||
* 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.recentactivity;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import org.openide.modules.InstalledFileLocator;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.services.FileManager;
|
||||
import org.sleuthkit.autopsy.coreutils.ExecUtil;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
|
||||
import org.sleuthkit.autopsy.coreutils.SQLiteDBConnect;
|
||||
import org.sleuthkit.autopsy.datamodel.ContentUtils;
|
||||
import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProcessTerminator;
|
||||
import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProgress;
|
||||
import org.sleuthkit.autopsy.ingest.IngestJobContext;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.Blackboard;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
* Extract the Prefetch Files and process them thru an External program. The data will then be added to the
|
||||
* TSK_PROG_RUN artifact. Associated artifacts will be created if possible.
|
||||
*/
|
||||
final class ExtractPrefetch extends Extract {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(ExtractPrefetch.class.getName());
|
||||
|
||||
private IngestJobContext context;
|
||||
|
||||
|
||||
private static final String MODULE_NAME = "extractPREFETCH"; //NON-NLS
|
||||
|
||||
private static final String PREFETCH_TSK_COMMENT = "Prefetch File";
|
||||
private static final String PREFETCH_FILE_LOCATION = "/Windows/Prefetch";
|
||||
private static final String PREFETCH_TOOL_FOLDER = "markmckinnon"; //NON-NLS
|
||||
private static final String PREFETCH_TOOL_NAME_WINDOWS_64 = "parse_prefetch_x64.exe"; //NON-NLS
|
||||
private static final String PREFETCH_TOOL_NAME_WINDOWS_32 = "parse_prefetch_x32.exe"; //NON-NLS
|
||||
private static final String PREFETCH_TOOL_NAME_MACOS = "parse_prefetch_macos"; //NON-NLS
|
||||
private static final String PREFETCH_TOOL_NAME_LINUX = "parse_prefetch_linux"; //NON-NLS
|
||||
private static final String PREFETCH_OUTPUT_FILE_NAME = "Output.txt"; //NON-NLS
|
||||
private static final String PREFETCH_ERROR_FILE_NAME = "Error.txt"; //NON-NLS
|
||||
private static final String PREFETCH_PARSER_DB_FILE = "Autopsy_PF_DB.db3"; //NON-NLS
|
||||
private static final String PREFETCH_DIR_NAME = "prefetch"; //NON-NLS
|
||||
|
||||
@Messages({
|
||||
"ExtractPrefetch_module_name=Windows Prefetch Extractor"
|
||||
})
|
||||
ExtractPrefetch() {
|
||||
this.moduleName = Bundle.ExtractPrefetch_module_name();
|
||||
}
|
||||
|
||||
@Override
|
||||
void process(Content dataSource, IngestJobContext context, DataSourceIngestModuleProgress progressBar) {
|
||||
|
||||
this.context = context;
|
||||
|
||||
String modOutPath = Case.getCurrentCase().getModuleDirectory() + File.separator + PREFETCH_DIR_NAME;
|
||||
File dir = new File(modOutPath);
|
||||
if (dir.exists() == false) {
|
||||
boolean dirMade = dir.mkdirs();
|
||||
if (!dirMade) {
|
||||
logger.log(Level.SEVERE, "Error creating directory to store prefetch output database"); //NON-NLS
|
||||
return; //If we cannot create the directory then we need to exit
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
extractPrefetchFiles(dataSource);
|
||||
|
||||
final String prefetchDumper = getPathForPrefetchDumper();
|
||||
if (prefetchDumper == null) {
|
||||
logger.log(Level.SEVERE, "Error finding parse_prefetch program"); //NON-NLS
|
||||
return; //If we cannot find the parse_prefetch program we cannot proceed
|
||||
}
|
||||
|
||||
if (context.dataSourceIngestIsCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String modOutFile = modOutPath + File.separator + PREFETCH_PARSER_DB_FILE;
|
||||
try {
|
||||
String tempDirPath = RAImageIngestModule.getRATempPath(Case.getCurrentCase(), PREFETCH_DIR_NAME );
|
||||
parsePrefetchFiles(prefetchDumper, tempDirPath, modOutFile, modOutPath);
|
||||
createAppExecArtifacts(modOutFile, dataSource);
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.WARNING, "Error runing parse_prefetch or creating artifacts.", ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract prefetch file to temp directory to process. Checks to make sure that the prefetch files only
|
||||
* come from the /Windows/Prefetch directory
|
||||
*
|
||||
* @param dataSource - datasource to search for prefetch files
|
||||
*
|
||||
*/
|
||||
|
||||
void extractPrefetchFiles(Content dataSource) {
|
||||
List<AbstractFile> pFiles;
|
||||
|
||||
FileManager fileManager = Case.getCurrentCase().getServices().getFileManager();
|
||||
|
||||
try {
|
||||
pFiles = fileManager.findFiles(dataSource, "%.pf"); //NON-NLS
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, "Unable to find prefetch files.", ex); //NON-NLS
|
||||
return; // No need to continue
|
||||
}
|
||||
|
||||
for (AbstractFile pFile : pFiles) {
|
||||
|
||||
if (context.dataSourceIngestIsCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String prefetchFile = RAImageIngestModule.getRATempPath(Case.getCurrentCase(), PREFETCH_DIR_NAME) + File.separator + pFile.getName();
|
||||
if (pFile.getParentPath().contains(PREFETCH_FILE_LOCATION)) {
|
||||
try {
|
||||
ContentUtils.writeToFile(pFile, new File(prefetchFile));
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.WARNING, String.format("Unable to write %s to temp directory. File name: %s", pFile.getName(), prefetchFile), ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the export parse_prefetch program against the prefetch files
|
||||
*
|
||||
* @param prefetchExePath - Path to the Executable to run
|
||||
* @param prefetchDir - Directory where the prefetch files reside to be processed.
|
||||
* @param tempOutFile - Output database file name and path.
|
||||
* @param tempOutPath - Directory to store the output and error files.
|
||||
*
|
||||
* @throws FileNotFoundException
|
||||
* @throws IOException
|
||||
*/
|
||||
void parsePrefetchFiles(String prefetchExePath, String prefetchDir, String tempOutFile, String tempOutPath) throws FileNotFoundException, IOException {
|
||||
final Path outputFilePath = Paths.get(tempOutPath, PREFETCH_OUTPUT_FILE_NAME);
|
||||
final Path errFilePath = Paths.get(tempOutPath, PREFETCH_ERROR_FILE_NAME);
|
||||
|
||||
List<String> commandLine = new ArrayList<>();
|
||||
commandLine.add(prefetchExePath);
|
||||
commandLine.add(prefetchDir); //NON-NLS
|
||||
commandLine.add(tempOutFile);
|
||||
|
||||
ProcessBuilder processBuilder = new ProcessBuilder(commandLine);
|
||||
processBuilder.redirectOutput(outputFilePath.toFile());
|
||||
processBuilder.redirectError(errFilePath.toFile());
|
||||
|
||||
ExecUtil.execute(processBuilder, new DataSourceIngestModuleProcessTerminator(context));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the path and executable for the parse_prefetch program. Checks for specific version of OS to
|
||||
* get proper executable.
|
||||
*
|
||||
* @return - path and executable to run.
|
||||
*
|
||||
*/
|
||||
|
||||
private String getPathForPrefetchDumper() {
|
||||
Path path = null;
|
||||
if (PlatformUtil.isWindowsOS()) {
|
||||
if (PlatformUtil.is64BitOS()) {
|
||||
path = Paths.get(PREFETCH_TOOL_FOLDER, PREFETCH_TOOL_NAME_WINDOWS_64);
|
||||
} else {
|
||||
path = Paths.get(PREFETCH_TOOL_FOLDER, PREFETCH_TOOL_NAME_WINDOWS_32);
|
||||
}
|
||||
} else {
|
||||
if ("Linux".equals(PlatformUtil.getOSName())) {
|
||||
path = Paths.get(PREFETCH_TOOL_FOLDER, PREFETCH_TOOL_NAME_LINUX);
|
||||
} else {
|
||||
path = Paths.get(PREFETCH_TOOL_FOLDER, PREFETCH_TOOL_NAME_MACOS);
|
||||
}
|
||||
}
|
||||
File prefetchToolFile = InstalledFileLocator.getDefault().locate(path.toString(),
|
||||
ExtractPrefetch.class.getPackage().getName(), false);
|
||||
if (prefetchToolFile != null) {
|
||||
return prefetchToolFile.getAbsolutePath();
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the artifacts from external run of the parse_prefetch program
|
||||
*
|
||||
* @param prefetchDb - Database file to read from running the parse_prefetch program.
|
||||
* @param dataSource - The datasource to search in
|
||||
*
|
||||
*/
|
||||
|
||||
private void createAppExecArtifacts(String prefetchDb, Content dataSource) {
|
||||
List<BlackboardArtifact> blkBrdArtList = new ArrayList<>();
|
||||
|
||||
String sqlStatement = "SELECT prefetch_File_Name, actual_File_Name, file_path, Number_time_file_run, Embeded_date_Time_Unix_1, " +
|
||||
" Embeded_date_Time_Unix_2, Embeded_date_Time_Unix_3, Embeded_date_Time_Unix_4, Embeded_date_Time_Unix_5," +
|
||||
" Embeded_date_Time_Unix_6, Embeded_date_Time_Unix_7, Embeded_date_Time_Unix_8 " +
|
||||
" FROM prefetch_file_info;"; //NON-NLS
|
||||
|
||||
try (SQLiteDBConnect tempdbconnect = new SQLiteDBConnect("org.sqlite.JDBC", "jdbc:sqlite:" + prefetchDb); //NON-NLS
|
||||
ResultSet resultSet = tempdbconnect.executeQry(sqlStatement)) {
|
||||
|
||||
while (resultSet.next()) {
|
||||
|
||||
if (context.dataSourceIngestIsCancelled()) {
|
||||
logger.log(Level.INFO, "Cancelled Prefetch Artifact Creation."); //NON-NLS
|
||||
return;
|
||||
}
|
||||
|
||||
String prefetchFileName = resultSet.getString("prefetch_File_Name");
|
||||
String applicationName = resultSet.getString("actual_File_Name"); //NON-NLS
|
||||
List<Long> executionTimes = new ArrayList<>();
|
||||
executionTimes.add(Long.valueOf(resultSet.getInt("Embeded_date_Time_Unix_1")));
|
||||
executionTimes.add(Long.valueOf(resultSet.getInt("Embeded_date_Time_Unix_2")));
|
||||
executionTimes.add(Long.valueOf(resultSet.getInt("Embeded_date_Time_Unix_3")));
|
||||
executionTimes.add(Long.valueOf(resultSet.getInt("Embeded_date_Time_Unix_4")));
|
||||
executionTimes.add(Long.valueOf(resultSet.getInt("Embeded_date_Time_Unix_5")));
|
||||
executionTimes.add(Long.valueOf(resultSet.getInt("Embeded_date_Time_Unix_6")));
|
||||
executionTimes.add(Long.valueOf(resultSet.getInt("Embeded_date_Time_Unix_7")));
|
||||
executionTimes.add(Long.valueOf(resultSet.getInt("Embeded_date_Time_Unix_8")));
|
||||
String timesProgramRun = resultSet.getString("Number_time_file_run");
|
||||
String filePath = resultSet.getString("file_path");
|
||||
|
||||
AbstractFile pfAbstractFile = getAbstractFile(prefetchFileName, PREFETCH_FILE_LOCATION, dataSource);
|
||||
|
||||
List<Long> prefetchExecutionTimes = findNonZeroExecutionTimes(executionTimes);
|
||||
|
||||
if (pfAbstractFile != null) {
|
||||
for (Long executionTime : prefetchExecutionTimes) {
|
||||
|
||||
// only add prefetch file entries that have an actual date associated with them
|
||||
Collection<BlackboardAttribute> blkBrdAttributes = Arrays.asList(
|
||||
new BlackboardAttribute(
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME, getName(),
|
||||
applicationName),//NON-NLS
|
||||
new BlackboardAttribute(
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, getName(),
|
||||
executionTime),
|
||||
new BlackboardAttribute(
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COUNT, getName(), Integer.valueOf(timesProgramRun)),
|
||||
new BlackboardAttribute(
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT, getName(), PREFETCH_TSK_COMMENT));
|
||||
|
||||
try {
|
||||
BlackboardArtifact blkBrdArt = pfAbstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_PROG_RUN);
|
||||
blkBrdArt.addAttributes(blkBrdAttributes);
|
||||
blkBrdArtList.add(blkBrdArt);
|
||||
BlackboardArtifact associatedBbArtifact = createAssociatedArtifact(applicationName.toLowerCase(), filePath, blkBrdArt, dataSource);
|
||||
if (associatedBbArtifact != null) {
|
||||
blkBrdArtList.add(associatedBbArtifact);
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Exception Adding Artifact.", ex);//NON-NLS
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logger.log(Level.SEVERE, "File has a null value " + prefetchFileName);//NON-NLS
|
||||
}
|
||||
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
logger.log(Level.SEVERE, "Error while trying to read into a sqlite db.", ex);//NON-NLS
|
||||
}
|
||||
|
||||
if (!blkBrdArtList.isEmpty()) {
|
||||
try {
|
||||
blackboard.postArtifacts(blkBrdArtList, MODULE_NAME);
|
||||
} catch (Blackboard.BlackboardException ex) {
|
||||
logger.log(Level.SEVERE, "Error Posting Artifact.", ex);//NON-NLS
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cycle thru the execution times list and only return a new list of times that are greater than zero.
|
||||
*
|
||||
* @param executionTimes - list of prefetch execution times 8 possible timestamps
|
||||
*
|
||||
* @return List of timestamps that are greater than zero
|
||||
*/
|
||||
|
||||
private List<Long> findNonZeroExecutionTimes(List<Long> executionTimes) {
|
||||
List<Long> prefetchExecutionTimes = new ArrayList<>();
|
||||
for (Long executionTime : executionTimes) { // only add prefetch file entries that have an actual date associated with them
|
||||
if (executionTime > 0) {
|
||||
prefetchExecutionTimes.add(executionTime);
|
||||
}
|
||||
}
|
||||
return prefetchExecutionTimes;
|
||||
}
|
||||
/**
|
||||
* Create associated artifacts using file path name and the artifact it associates with
|
||||
*
|
||||
* @param fileName the filename to search for
|
||||
* @param filePathName file and path of object being associated with
|
||||
* @param bba blackboard artifact to associate with
|
||||
* @param dataSource - The datasource to search in
|
||||
*
|
||||
* @returnv BlackboardArtifact or a null value
|
||||
*/
|
||||
private BlackboardArtifact createAssociatedArtifact(String fileName, String filePathName, BlackboardArtifact bba, Content dataSource) {
|
||||
AbstractFile sourceFile = getAbstractFile(fileName, filePathName, dataSource);
|
||||
if (sourceFile != null) {
|
||||
Collection<BlackboardAttribute> bbattributes2 = new ArrayList<>();
|
||||
bbattributes2.addAll(Arrays.asList(
|
||||
new BlackboardAttribute(TSK_ASSOCIATED_ARTIFACT, this.getName(),
|
||||
bba.getArtifactID())));
|
||||
|
||||
BlackboardArtifact associatedObjectBba = createArtifactWithAttributes(TSK_ASSOCIATED_OBJECT, sourceFile, bbattributes2);
|
||||
if (associatedObjectBba != null) {
|
||||
return associatedObjectBba;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the abstract file for the prefetch file.
|
||||
*
|
||||
* @param fileName - File name of the prefetch file to find.
|
||||
* @param filePath - Path where the prefetch file is located.
|
||||
* @param dataSource - The datasource to search in
|
||||
*
|
||||
* @return Abstract file of the prefetch file.
|
||||
*
|
||||
*/
|
||||
|
||||
AbstractFile getAbstractFile(String fileName, String filePath, Content dataSource) {
|
||||
List<AbstractFile> files;
|
||||
|
||||
FileManager fileManager = Case.getCurrentCase().getServices().getFileManager();
|
||||
|
||||
try {
|
||||
files = fileManager.findFiles(dataSource, fileName, filePath); //NON-NLS
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, "Unable to find prefetch files.", ex); //NON-NLS
|
||||
return null; // No need to continue
|
||||
}
|
||||
|
||||
if (!files.isEmpty()) {
|
||||
return files.get(0);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -79,6 +79,7 @@ public final class RAImageIngestModule implements DataSourceIngestModule {
|
||||
Extract zoneInfo = new ExtractZoneIdentifier();
|
||||
Extract recycleBin = new ExtractRecycleBin();
|
||||
Extract sru = new ExtractSru();
|
||||
Extract prefetch = new ExtractPrefetch();
|
||||
|
||||
extractors.add(chrome);
|
||||
extractors.add(firefox);
|
||||
@ -93,6 +94,7 @@ public final class RAImageIngestModule implements DataSourceIngestModule {
|
||||
extractors.add(zoneInfo); // this needs to run after the web browser modules
|
||||
extractors.add(recycleBin); // this needs to run after ExtractRegistry and ExtractOS
|
||||
extractors.add(sru);
|
||||
extractors.add(prefetch);
|
||||
|
||||
browserExtractors.add(chrome);
|
||||
browserExtractors.add(firefox);
|
||||
|
@ -1,5 +1,5 @@
|
||||
#Updated by build script
|
||||
#Fri, 12 Jun 2020 14:50:38 -0400
|
||||
#Fri, 19 Jun 2020 10:14:47 -0400
|
||||
LBL_splash_window_title=Starting Autopsy
|
||||
SPLASH_HEIGHT=314
|
||||
SPLASH_WIDTH=538
|
||||
|
@ -1,4 +1,4 @@
|
||||
#Updated by build script
|
||||
#Fri, 12 Jun 2020 14:50:38 -0400
|
||||
#Fri, 19 Jun 2020 10:14:47 -0400
|
||||
CTL_MainWindow_Title=Autopsy 4.15.0
|
||||
CTL_MainWindow_Title_No_Project=Autopsy 4.15.0
|
||||
|
BIN
thirdparty/markmckinnon/parse_prefetch_linux
vendored
Normal file
BIN
thirdparty/markmckinnon/parse_prefetch_linux
vendored
Normal file
Binary file not shown.
BIN
thirdparty/markmckinnon/parse_prefetch_macos
vendored
Normal file
BIN
thirdparty/markmckinnon/parse_prefetch_macos
vendored
Normal file
Binary file not shown.
BIN
thirdparty/markmckinnon/parse_prefetch_x64.exe
vendored
Normal file
BIN
thirdparty/markmckinnon/parse_prefetch_x64.exe
vendored
Normal file
Binary file not shown.
BIN
thirdparty/markmckinnon/parse_prefetch_x86.exe
vendored
Normal file
BIN
thirdparty/markmckinnon/parse_prefetch_x86.exe
vendored
Normal file
Binary file not shown.
@ -6,6 +6,15 @@
|
||||
<code-name-base>org.sleuthkit.autopsy.thunderbirdparser</code-name-base>
|
||||
<suite-component/>
|
||||
<module-dependencies>
|
||||
<dependency>
|
||||
<code-name-base>org.netbeans.api.progress</code-name-base>
|
||||
<build-prerequisite/>
|
||||
<compile-dependency/>
|
||||
<run-dependency>
|
||||
<release-version>1</release-version>
|
||||
<specification-version>1.47.1</specification-version>
|
||||
</run-dependency>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<code-name-base>org.openide.util</code-name-base>
|
||||
<build-prerequisite/>
|
||||
|
@ -54,6 +54,7 @@ import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
|
||||
import org.sleuthkit.datamodel.DerivedFile;
|
||||
import org.sleuthkit.datamodel.ReadContentInputStream;
|
||||
import org.sleuthkit.datamodel.Relationship;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
@ -76,6 +77,7 @@ public final class ThunderbirdMboxFileIngestModule implements FileIngestModule {
|
||||
private Blackboard blackboard;
|
||||
private CommunicationArtifactsHelper communicationArtifactsHelper;
|
||||
|
||||
private static final int MBOX_SIZE_TO_SPLIT = 1048576000;
|
||||
private Case currentCase;
|
||||
|
||||
/**
|
||||
@ -309,6 +311,8 @@ public final class ThunderbirdMboxFileIngestModule implements FileIngestModule {
|
||||
return ProcessResult.OK;
|
||||
}
|
||||
|
||||
if (abstractFile.getSize() < MBOX_SIZE_TO_SPLIT) {
|
||||
|
||||
try {
|
||||
ContentUtils.writeToFile(abstractFile, file, context::fileIngestIsCancelled);
|
||||
} catch (IOException ex) {
|
||||
@ -316,6 +320,67 @@ public final class ThunderbirdMboxFileIngestModule implements FileIngestModule {
|
||||
return ProcessResult.OK;
|
||||
}
|
||||
|
||||
processMboxFile(file, abstractFile, emailFolder);
|
||||
|
||||
if (file.delete() == false) {
|
||||
logger.log(Level.INFO, "Failed to delete temp file: {0}", file.getName()); //NON-NLS
|
||||
}
|
||||
} else {
|
||||
|
||||
List<Long> mboxSplitOffsets = new ArrayList<>();
|
||||
try{
|
||||
mboxSplitOffsets = findMboxSplitOffset(abstractFile, file);
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.WARNING, String.format("Failed finding split offsets for mbox file {0}.", fileName), ex); //NON-NLS
|
||||
return ProcessResult.OK;
|
||||
}
|
||||
|
||||
long startingOffset = 0;
|
||||
for (Long mboxSplitOffset : mboxSplitOffsets) {
|
||||
File splitFile = new File(fileName + "-" + mboxSplitOffset);
|
||||
try {
|
||||
ContentUtils.writeToFile(abstractFile, splitFile, context::fileIngestIsCancelled, startingOffset, mboxSplitOffset);
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.WARNING, "Failed writing split mbox file to disk.", ex); //NON-NLS
|
||||
return ProcessResult.OK;
|
||||
}
|
||||
processMboxFile(splitFile, abstractFile, emailFolder);
|
||||
startingOffset = mboxSplitOffset;
|
||||
if (splitFile.delete() == false) {
|
||||
logger.log(Level.INFO, "Failed to delete temp file: {0}", splitFile); //NON-NLS
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return ProcessResult.OK;
|
||||
}
|
||||
|
||||
private List<Long> findMboxSplitOffset(AbstractFile abstractFile, File file) throws IOException {
|
||||
|
||||
List<Long> mboxSplitOffset = new ArrayList<>();
|
||||
|
||||
byte[] buffer = new byte[7];
|
||||
ReadContentInputStream in = new ReadContentInputStream(abstractFile);
|
||||
in.skip(MBOX_SIZE_TO_SPLIT);
|
||||
int len = in.read(buffer);
|
||||
while (len != -1) {
|
||||
len = in.read(buffer);
|
||||
if (buffer[0] == 13 && buffer[1] == 10 && buffer[2] == 70 && buffer[3] == 114 &&
|
||||
buffer[4] == 111 && buffer[5] == 109 && buffer[6] == 32) {
|
||||
mboxSplitOffset.add(in.getCurPosition() - 5 );
|
||||
in.skip(MBOX_SIZE_TO_SPLIT);
|
||||
}
|
||||
}
|
||||
|
||||
return mboxSplitOffset;
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void processMboxFile(File file, AbstractFile abstractFile, String emailFolder) {
|
||||
|
||||
|
||||
MboxParser emailIterator = MboxParser.getEmailIterator( emailFolder, file, abstractFile.getId());
|
||||
List<EmailMessage> emails = new ArrayList<>();
|
||||
if(emailIterator != null) {
|
||||
@ -335,11 +400,6 @@ public final class ThunderbirdMboxFileIngestModule implements FileIngestModule {
|
||||
}
|
||||
processEmails(emails, MboxParser.getEmailIterator( emailFolder, file, abstractFile.getId()), abstractFile);
|
||||
|
||||
if (file.delete() == false) {
|
||||
logger.log(Level.INFO, "Failed to delete temp file: {0}", file.getName()); //NON-NLS
|
||||
}
|
||||
|
||||
return ProcessResult.OK;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -755,4 +815,5 @@ public final class ThunderbirdMboxFileIngestModule implements FileIngestModule {
|
||||
public void shutDown() {
|
||||
// nothing to shut down
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user