mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-13 08:26:15 +00:00
Merge remote-tracking branch 'sleuthkit/develop' into 6445_persona_confidence_update
This commit is contained in:
commit
df5891f552
@ -1,4 +1,4 @@
|
|||||||
OptionsCategory_Name_TagNamesOptions=Tags
|
OptionsCategory_Name_TagNamesOptions=Custom Tags
|
||||||
OptionsCategory_TagNames=TagNames
|
OptionsCategory_TagNames=TagNames
|
||||||
TagNameDialog.title.text=New Tag
|
TagNameDialog.title.text=New Tag
|
||||||
TagNameDialog.JOptionPane.tagNameIllegalCharacters.message=Tag name may not contain any of the following symbols: \\ : * ? " < > | , ;
|
TagNameDialog.JOptionPane.tagNameIllegalCharacters.message=Tag name may not contain any of the following symbols: \\ : * ? " < > | , ;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
OptionsCategory_Name_TagNamesOptions=Tags
|
OptionsCategory_Name_TagNamesOptions=Custom Tags
|
||||||
OptionsCategory_TagNames=TagNames
|
OptionsCategory_TagNames=TagNames
|
||||||
TagNameDefinition.predefTagNames.bookmark.text=Bookmark
|
TagNameDefinition.predefTagNames.bookmark.text=Bookmark
|
||||||
TagNameDefinition.predefTagNames.followUp.text=Follow Up
|
TagNameDefinition.predefTagNames.followUp.text=Follow Up
|
||||||
|
@ -292,6 +292,14 @@ public class Persona {
|
|||||||
PersonaAccount.removePersonaAccount(account.getId());
|
PersonaAccount.removePersonaAccount(account.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marks this persona as deleted
|
||||||
|
*/
|
||||||
|
public void delete() throws CentralRepoException {
|
||||||
|
String deleteSQL = "UPDATE personas SET status_id = " + PersonaStatus.DELETED.status_id + " WHERE id = " + this.id;
|
||||||
|
CentralRepository.getInstance().executeUpdateSQL(deleteSQL);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback to process a Persona query from the persona table.
|
* Callback to process a Persona query from the persona table.
|
||||||
*/
|
*/
|
||||||
@ -363,6 +371,7 @@ public class Persona {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the rows from the Personas table with matching name.
|
* Gets the rows from the Personas table with matching name.
|
||||||
|
* Persona marked as DELETED are not returned.
|
||||||
*
|
*
|
||||||
* @param partialName Name substring to match.
|
* @param partialName Name substring to match.
|
||||||
* @return Collection of personas matching the given name substring, may be
|
* @return Collection of personas matching the given name substring, may be
|
||||||
@ -374,7 +383,8 @@ public class Persona {
|
|||||||
public static Collection<Persona> getPersonaByName(String partialName) throws CentralRepoException {
|
public static Collection<Persona> getPersonaByName(String partialName) throws CentralRepoException {
|
||||||
|
|
||||||
String queryClause = PERSONA_QUERY
|
String queryClause = PERSONA_QUERY
|
||||||
+ "WHERE LOWER(p.name) LIKE " + "LOWER('%" + partialName + "%')" ;
|
+ "WHERE p.status_id != " + PersonaStatus.DELETED.status_id +
|
||||||
|
" AND LOWER(p.name) LIKE " + "LOWER('%" + partialName + "%')" ;
|
||||||
|
|
||||||
PersonaQueryCallback queryCallback = new PersonaQueryCallback();
|
PersonaQueryCallback queryCallback = new PersonaQueryCallback();
|
||||||
CentralRepository.getInstance().executeSelectSQL(queryClause, queryCallback);
|
CentralRepository.getInstance().executeSelectSQL(queryClause, queryCallback);
|
||||||
@ -668,7 +678,8 @@ public class Persona {
|
|||||||
for (CentralRepoAccount.CentralRepoAccountType crAccountType : accountTypes) {
|
for (CentralRepoAccount.CentralRepoAccountType crAccountType : accountTypes) {
|
||||||
|
|
||||||
String querySql = getPersonaFromInstanceTableQueryTemplate(crAccountType)
|
String querySql = getPersonaFromInstanceTableQueryTemplate(crAccountType)
|
||||||
+ " WHERE case_id = " + correlationCase.getID();
|
+ " WHERE case_id = " + correlationCase.getID()
|
||||||
|
+ "AND personas.status_id != " + Persona.PersonaStatus.DELETED.getStatusId();
|
||||||
|
|
||||||
PersonaFromAccountInstanceQueryCallback queryCallback = new PersonaFromAccountInstanceQueryCallback();
|
PersonaFromAccountInstanceQueryCallback queryCallback = new PersonaFromAccountInstanceQueryCallback();
|
||||||
CentralRepository.getInstance().executeSelectSQL(querySql, queryCallback);
|
CentralRepository.getInstance().executeSelectSQL(querySql, queryCallback);
|
||||||
@ -699,7 +710,8 @@ public class Persona {
|
|||||||
for (CentralRepoAccount.CentralRepoAccountType crAccountType : accountTypes) {
|
for (CentralRepoAccount.CentralRepoAccountType crAccountType : accountTypes) {
|
||||||
|
|
||||||
String querySql = getPersonaFromInstanceTableQueryTemplate(crAccountType)
|
String querySql = getPersonaFromInstanceTableQueryTemplate(crAccountType)
|
||||||
+ " WHERE data_source_id = " + dataSource.getID();
|
+ " WHERE data_source_id = " + dataSource.getID()
|
||||||
|
+ "AND personas.status_id != " + Persona.PersonaStatus.DELETED.getStatusId();
|
||||||
|
|
||||||
PersonaFromAccountInstanceQueryCallback queryCallback = new PersonaFromAccountInstanceQueryCallback();
|
PersonaFromAccountInstanceQueryCallback queryCallback = new PersonaFromAccountInstanceQueryCallback();
|
||||||
CentralRepository.getInstance().executeSelectSQL(querySql, queryCallback);
|
CentralRepository.getInstance().executeSelectSQL(querySql, queryCallback);
|
||||||
|
@ -27,6 +27,7 @@ import java.util.Collections;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||||
|
import org.sleuthkit.datamodel.Account;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class represents an association between a Persona and an Account.
|
* This class represents an association between a Persona and an Account.
|
||||||
@ -130,7 +131,13 @@ public class PersonaAccount {
|
|||||||
* account.
|
* account.
|
||||||
*/
|
*/
|
||||||
static PersonaAccount addPersonaAccount(Persona persona, CentralRepoAccount account, String justification, Persona.Confidence confidence) throws CentralRepoException {
|
static PersonaAccount addPersonaAccount(Persona persona, CentralRepoAccount account, String justification, Persona.Confidence confidence) throws CentralRepoException {
|
||||||
CentralRepoExaminer currentExaminer = CentralRepository.getInstance().getOrInsertExaminer(System.getProperty("user.name"));
|
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();
|
Instant instant = Instant.now();
|
||||||
Long timeStampMillis = instant.toEpochMilli();
|
Long timeStampMillis = instant.toEpochMilli();
|
||||||
@ -235,38 +242,53 @@ public class PersonaAccount {
|
|||||||
* Gets all the Accounts for the specified Persona.
|
* Gets all the Accounts for the specified Persona.
|
||||||
*
|
*
|
||||||
* @param personaId Id of persona for which to get the accounts for.
|
* @param personaId Id of persona for which to get the accounts for.
|
||||||
|
*
|
||||||
* @return Collection of PersonaAccounts, may be empty.
|
* @return Collection of PersonaAccounts, may be empty.
|
||||||
*
|
*
|
||||||
* @throws CentralRepoException If there is an error in getting the
|
* @throws CentralRepoException If there is an error in getting the
|
||||||
* persona_account.
|
* persona_account.
|
||||||
*/
|
*/
|
||||||
static Collection<PersonaAccount> getPersonaAccountsForPersona(long personaId) throws CentralRepoException {
|
static Collection<PersonaAccount> getPersonaAccountsForPersona(long personaId) throws CentralRepoException {
|
||||||
String queryClause = PERSONA_ACCOUNTS_QUERY_CALUSE
|
CentralRepository cr = CentralRepository.getInstance();
|
||||||
+ " WHERE persona_accounts.persona_id = " + personaId;
|
|
||||||
|
|
||||||
PersonaAccountsQueryCallback queryCallback = new PersonaAccountsQueryCallback();
|
if (cr != null) {
|
||||||
CentralRepository.getInstance().executeSelectSQL(queryClause, queryCallback);
|
String queryClause = PERSONA_ACCOUNTS_QUERY_CALUSE
|
||||||
|
+ " WHERE persona_accounts.persona_id = " + personaId;
|
||||||
|
|
||||||
return queryCallback.getPersonaAccountsList();
|
PersonaAccountsQueryCallback queryCallback = new PersonaAccountsQueryCallback();
|
||||||
|
cr.executeSelectSQL(queryClause, queryCallback);
|
||||||
|
|
||||||
|
return queryCallback.getPersonaAccountsList();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets all the Persona for the specified Account.
|
* Gets all the Persona for the specified Account.
|
||||||
*
|
*
|
||||||
* @param accountId Id of account for which to get the Personas for.
|
* @param accountId Id of account for which to get the Personas for.
|
||||||
|
*
|
||||||
* @return Collection of PersonaAccounts. may be empty.
|
* @return Collection of PersonaAccounts. may be empty.
|
||||||
*
|
*
|
||||||
* @throws CentralRepoException If there is an error in getting the
|
* @throws CentralRepoException If there is an error in getting the
|
||||||
* persona_account.
|
* persona_account.
|
||||||
*/
|
*/
|
||||||
public static Collection<PersonaAccount> getPersonaAccountsForAccount(long accountId) throws CentralRepoException {
|
public static Collection<PersonaAccount> getPersonaAccountsForAccount(long accountId) throws CentralRepoException {
|
||||||
String queryClause = PERSONA_ACCOUNTS_QUERY_CALUSE
|
String queryClause = PERSONA_ACCOUNTS_QUERY_CALUSE
|
||||||
+ " WHERE persona_accounts.account_id = " + accountId;
|
+ " WHERE persona_accounts.account_id = " + accountId
|
||||||
|
+ "AND p.status_id != " + Persona.PersonaStatus.DELETED.getStatusId();
|
||||||
|
|
||||||
PersonaAccountsQueryCallback queryCallback = new PersonaAccountsQueryCallback();
|
CentralRepository cr = CentralRepository.getInstance();
|
||||||
CentralRepository.getInstance().executeSelectSQL(queryClause, queryCallback);
|
|
||||||
|
|
||||||
return queryCallback.getPersonaAccountsList();
|
if (cr != null) {
|
||||||
|
PersonaAccountsQueryCallback queryCallback = new PersonaAccountsQueryCallback();
|
||||||
|
cr.executeSelectSQL(queryClause, queryCallback);
|
||||||
|
|
||||||
|
return queryCallback.getPersonaAccountsList();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -274,20 +296,51 @@ public class PersonaAccount {
|
|||||||
* account identifier substring.
|
* account identifier substring.
|
||||||
*
|
*
|
||||||
* @param accountIdentifierSubstring Account identifier substring to search
|
* @param accountIdentifierSubstring Account identifier substring to search
|
||||||
* for.
|
* for.
|
||||||
|
*
|
||||||
* @return Collection of PersonaAccounts. may be empty.
|
* @return Collection of PersonaAccounts. may be empty.
|
||||||
*
|
*
|
||||||
* @throws CentralRepoException If there is an error in getting the
|
* @throws CentralRepoException If there is an error in getting the
|
||||||
* persona_account.
|
* persona_account.
|
||||||
*/
|
*/
|
||||||
public static Collection<PersonaAccount> getPersonaAccountsForIdentifierLike(String accountIdentifierSubstring) throws CentralRepoException {
|
public static Collection<PersonaAccount> getPersonaAccountsForIdentifierLike(String accountIdentifierSubstring) throws CentralRepoException {
|
||||||
String queryClause = PERSONA_ACCOUNTS_QUERY_CALUSE
|
String queryClause = PERSONA_ACCOUNTS_QUERY_CALUSE
|
||||||
+ " WHERE LOWER(accounts.account_unique_identifier) LIKE LOWER('%" + accountIdentifierSubstring + "%')";
|
+ " WHERE LOWER(accounts.account_unique_identifier) LIKE LOWER('%" + accountIdentifierSubstring + "%')"
|
||||||
|
+ "AND p.status_id != " + Persona.PersonaStatus.DELETED.getStatusId();
|
||||||
|
|
||||||
PersonaAccountsQueryCallback queryCallback = new PersonaAccountsQueryCallback();
|
CentralRepository cr = CentralRepository.getInstance();
|
||||||
CentralRepository.getInstance().executeSelectSQL(queryClause, queryCallback);
|
if (cr != null) {
|
||||||
|
PersonaAccountsQueryCallback queryCallback = new PersonaAccountsQueryCallback();
|
||||||
|
cr.executeSelectSQL(queryClause, queryCallback);
|
||||||
|
|
||||||
return queryCallback.getPersonaAccountsList();
|
return queryCallback.getPersonaAccountsList();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all the Persona associated with the given account.
|
||||||
|
*
|
||||||
|
* @param account Account to search for.
|
||||||
|
*
|
||||||
|
* @return Collection of PersonaAccounts, maybe empty if none were found or
|
||||||
|
* CR is not enabled.
|
||||||
|
*
|
||||||
|
* @throws CentralRepoException
|
||||||
|
*/
|
||||||
|
public static Collection<PersonaAccount> getPersonaAccountsForAccount(Account account) throws CentralRepoException {
|
||||||
|
String queryClause = PERSONA_ACCOUNTS_QUERY_CALUSE
|
||||||
|
+ " WHERE LOWER(accounts.account_unique_identifier) LIKE LOWER('%" + account.getTypeSpecificID() + "%') AND type_name = '" + account.getAccountType().getTypeName() + "' ";
|
||||||
|
|
||||||
|
CentralRepository cr = CentralRepository.getInstance();
|
||||||
|
if (cr != null) {
|
||||||
|
PersonaAccountsQueryCallback queryCallback = new PersonaAccountsQueryCallback();
|
||||||
|
cr.executeSelectSQL(queryClause, queryCallback);
|
||||||
|
return queryCallback.getPersonaAccountsList();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -299,8 +352,14 @@ public class PersonaAccount {
|
|||||||
* account.
|
* account.
|
||||||
*/
|
*/
|
||||||
static void removePersonaAccount(long id) throws CentralRepoException {
|
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;
|
String deleteClause = " DELETE FROM persona_accounts WHERE id = " + id;
|
||||||
CentralRepository.getInstance().executeDeleteSQL(deleteClause);
|
cr.executeDeleteSQL(deleteClause);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -343,17 +402,23 @@ public class PersonaAccount {
|
|||||||
* accounts.
|
* accounts.
|
||||||
*/
|
*/
|
||||||
static Collection<CentralRepoAccount> getAccountsForPersona(long personaId) throws CentralRepoException {
|
static Collection<CentralRepoAccount> getAccountsForPersona(long personaId) throws CentralRepoException {
|
||||||
String queryClause = "SELECT account_id, "
|
CentralRepository cr = CentralRepository.getInstance();
|
||||||
+ " accounts.account_type_id as account_type_id, accounts.account_unique_identifier as account_unique_identifier,"
|
|
||||||
+ " account_types.type_name as type_name "
|
|
||||||
+ " FROM persona_accounts "
|
|
||||||
+ " JOIN accounts as accounts on persona_accounts.account_id = accounts.id "
|
|
||||||
+ " JOIN account_types as account_types on accounts.account_type_id = account_types.id "
|
|
||||||
+ " WHERE persona_accounts.persona_id = " + personaId;
|
|
||||||
|
|
||||||
AccountsForPersonaQueryCallback queryCallback = new AccountsForPersonaQueryCallback();
|
if (cr != null) {
|
||||||
CentralRepository.getInstance().executeSelectSQL(queryClause, queryCallback);
|
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 "
|
||||||
|
+ " FROM persona_accounts "
|
||||||
|
+ " JOIN accounts as accounts on persona_accounts.account_id = accounts.id "
|
||||||
|
+ " JOIN account_types as account_types on accounts.account_type_id = account_types.id "
|
||||||
|
+ " WHERE persona_accounts.persona_id = " + personaId;
|
||||||
|
|
||||||
return queryCallback.getAccountsList();
|
AccountsForPersonaQueryCallback queryCallback = new AccountsForPersonaQueryCallback();
|
||||||
|
cr.executeSelectSQL(queryClause, queryCallback);
|
||||||
|
|
||||||
|
return queryCallback.getAccountsList();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -343,93 +343,6 @@ public class IngestEventsListener {
|
|||||||
event = evt;
|
event = evt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Automatically creates personas from all the TSK_CONTACT artifacts
|
|
||||||
* found in a data source.
|
|
||||||
*
|
|
||||||
* @param dataSource Data source that was just analyzed.
|
|
||||||
* @throws TskCoreException If there is any error getting contact
|
|
||||||
* artifacts from case database.
|
|
||||||
* @throws CentralRepoException If there is an error in creating
|
|
||||||
* personas in the Central Repo.
|
|
||||||
*/
|
|
||||||
private void autoGenerateContactPersonas(Content dataSource) throws TskCoreException, CentralRepoException {
|
|
||||||
|
|
||||||
Blackboard blackboard;
|
|
||||||
try {
|
|
||||||
blackboard = Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboard();
|
|
||||||
} catch (NoCurrentCaseException ex) {
|
|
||||||
LOGGER.log(Level.SEVERE, "Exception while getting open case.", ex);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get all TSK_CONTACT artifacts in this data source.
|
|
||||||
List<BlackboardArtifact> contactArtifacts = blackboard.getArtifacts(TSK_CONTACT.getTypeID(), dataSource.getId());
|
|
||||||
for (BlackboardArtifact artifact : contactArtifacts) {
|
|
||||||
|
|
||||||
BlackboardAttribute nameAttr = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME));
|
|
||||||
String personaName = (nameAttr != null) ? nameAttr.getValueString() : null;
|
|
||||||
|
|
||||||
// Get phone number and email attributes.
|
|
||||||
BlackboardAttribute phoneAttr = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER));
|
|
||||||
BlackboardAttribute homePhoneAttr = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_HOME));
|
|
||||||
BlackboardAttribute mobilePhoneAttr = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_MOBILE));
|
|
||||||
BlackboardAttribute emailAttr = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL));
|
|
||||||
|
|
||||||
Persona persona = personaFromContactAttribute(null, Account.Type.PHONE, phoneAttr, personaName);
|
|
||||||
persona = personaFromContactAttribute(persona, Account.Type.PHONE, homePhoneAttr, personaName);
|
|
||||||
persona = personaFromContactAttribute(persona, Account.Type.PHONE, mobilePhoneAttr, personaName);
|
|
||||||
personaFromContactAttribute(persona, Account.Type.EMAIL, emailAttr, personaName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets central repo account for the given attribute for a TSK_CONTACT
|
|
||||||
* artifact. Associates the given persona with that account. Creates a
|
|
||||||
* Persona, if one isn't provided.
|
|
||||||
*
|
|
||||||
* @param persona Persona to associate with the account. May be null, in
|
|
||||||
* which case a persona is created first.
|
|
||||||
* @param accountType Account type of account to be associated.
|
|
||||||
* @param attribute Attribute form which get the account id.
|
|
||||||
* @param personaName Persona name, if a persona needs to be created.
|
|
||||||
* @return Persona created or associated with the account.
|
|
||||||
*
|
|
||||||
* @throws TskCoreException If there is an error in normalizing the
|
|
||||||
* account id.
|
|
||||||
* @throws CentralRepoException If there is an erorr is getting the
|
|
||||||
* account or associating the persona with it.
|
|
||||||
*/
|
|
||||||
private Persona personaFromContactAttribute(Persona persona, Account.Type accountType, BlackboardAttribute attribute, String personaName) throws CentralRepoException, TskCoreException {
|
|
||||||
|
|
||||||
Persona personaToReturn = persona;
|
|
||||||
if (attribute != null) {
|
|
||||||
|
|
||||||
String accountId = attribute.getValueString();
|
|
||||||
if (CommunicationsUtils.isValidAccountId(accountType, accountId)) {
|
|
||||||
if (accountType == Account.Type.PHONE) {
|
|
||||||
accountId = CommunicationsUtils.normalizePhoneNum(accountId);
|
|
||||||
} else if (accountType == Account.Type.EMAIL) {
|
|
||||||
accountId = CommunicationsUtils.normalizeEmailAddress(accountId);
|
|
||||||
}
|
|
||||||
|
|
||||||
CentralRepoAccount.CentralRepoAccountType crAccountType = CentralRepository.getInstance().getAccountTypeByName(accountType.getTypeName());
|
|
||||||
CentralRepoAccount crAccount = CentralRepository.getInstance().getOrCreateAccount(crAccountType, accountId);
|
|
||||||
|
|
||||||
PersonaAccount personaAccount;
|
|
||||||
// If persona doesnt exist, create one
|
|
||||||
if (persona == null) {
|
|
||||||
personaToReturn = Persona.createPersonaForAccount(personaName, "Auto generated contact persona", Persona.PersonaStatus.UNKNOWN, crAccount, "Found in contact book entry", Persona.Confidence.HIGH);
|
|
||||||
} else {
|
|
||||||
persona.addAccount(crAccount, "Found in contact book entry", Persona.Confidence.HIGH);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return personaToReturn;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
// clear the tracker to reduce memory usage
|
// clear the tracker to reduce memory usage
|
||||||
@ -504,8 +417,6 @@ public class IngestEventsListener {
|
|||||||
correlationDataSource.setSha256(imageSha256Hash);
|
correlationDataSource.setSha256(imageSha256Hash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// automatically generate persona from contact artifacts.
|
|
||||||
autoGenerateContactPersonas(dataSource);
|
|
||||||
}
|
}
|
||||||
} catch (CentralRepoException ex) {
|
} catch (CentralRepoException ex) {
|
||||||
LOGGER.log(Level.SEVERE, String.format(
|
LOGGER.log(Level.SEVERE, String.format(
|
||||||
|
@ -53,3 +53,4 @@ AddAccountDialog.confidenceLbl.text=Confidence:
|
|||||||
AddAccountDialog.typeLbl.text=Type:
|
AddAccountDialog.typeLbl.text=Type:
|
||||||
AddAccountDialog.identiferLbl.text=Identifier:
|
AddAccountDialog.identiferLbl.text=Identifier:
|
||||||
AddAccountDialog.identifierTextField.text=
|
AddAccountDialog.identifierTextField.text=
|
||||||
|
PersonaManagerTopComponent.deleteBtn.text=Delete Persona
|
||||||
|
@ -1,18 +1,38 @@
|
|||||||
AddAccountDialog.title.text=Add Account
|
AddAccountDialog.title.text=Add Account
|
||||||
|
AddAccountDialog_dup_msg=This account is already added to the persona
|
||||||
|
AddAccountDialog_dup_Title=Account add failure
|
||||||
|
AddAccountDialog_empty_msg=The identifier field cannot be empty
|
||||||
|
AddAccountDialog_empty_Title=Empty identifier
|
||||||
AddAccountDialog_get_types_exception_msg=Failed to access central repository
|
AddAccountDialog_get_types_exception_msg=Failed to access central repository
|
||||||
AddAccountDialog_get_types_exception_Title=Central Repository failure
|
AddAccountDialog_get_types_exception_Title=Central Repository failure
|
||||||
AddAccountDialog_validate_id_failure=Account ID must not be empty
|
AddAccountDialog_search_empty_msg=Account not found for given identifier and type
|
||||||
AddAccountDialog_validate_id_failure_title=Account ID issue
|
AddAccountDialog_search_empty_Title=Account not found
|
||||||
|
AddAccountDialog_search_failure_msg=Central Repository account search failed
|
||||||
|
AddAccountDialog_search_failure_Title=Account add failure
|
||||||
|
AddAliasDialog.title.text=Add Alias
|
||||||
|
AddAliasDialog_dup_msg=This alias has already been added to this persona
|
||||||
|
AddAliasDialog_dup_Title=Alias add failure
|
||||||
|
AddMetadataDialog.title.text=Add Metadata
|
||||||
|
AddMetadataDialog_dup_msg=A metadata entry with this name has already been added to this persona
|
||||||
|
AddMetadataDialog_dup_Title=Metadata add failure
|
||||||
CTL_OpenPersonaManager=Persona Manager
|
CTL_OpenPersonaManager=Persona Manager
|
||||||
CTL_PersonaManagerTopComponentAction=Persona Manager
|
CTL_PersonaManagerTopComponentAction=Persona Manager
|
||||||
CTL_PersonaDetailsTopComponent=Persona Details
|
CTL_PersonaDetailsTopComponent=Persona Details
|
||||||
OpenPersonasAction.displayName=Persona Manager
|
OpenPersonasAction.displayName=Persona Manager
|
||||||
|
PersonaDetailsDialogCreateTitle=Create Persona
|
||||||
|
PersonaDetailsDialogEditTitle=Edit Persona
|
||||||
|
PersonaDetailsPanel_CentralRepoErr_msg=Failure to write to Central Repository
|
||||||
|
PersonaDetailsPanel_CentralRepoErr_Title=Central Repository failure
|
||||||
|
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_msg=Failed to load persona
|
||||||
PersonaDetailsPanel_load_exception_Title=Initialization failure
|
PersonaDetailsPanel_load_exception_Title=Initialization failure
|
||||||
PersonaDetailsPanel_NameCreate=Create Persona
|
PersonaDetailsPanel_NameCreate=Create Persona
|
||||||
PersonaDetailsPanel_NameEdit=Edit Persona
|
PersonaDetailsPanel_NameEdit=Edit Persona
|
||||||
PersonaDetailsPanel_NameView=View Persona
|
PersonaDetailsPanel_NameView=View Persona
|
||||||
PersonaManagerTopComponent.createBtn.text=Create New
|
PersonaDetailsPanel_NotEnoughAccounts_msg=Two or more accounts are necessary to create a persona
|
||||||
|
PersonaDetailsPanel_NotEnoughAccounts_Title=Not enough accounts
|
||||||
|
PersonaManagerTopComponent.createBtn.text=New Persona
|
||||||
PersonaManagerTopComponent.searchBtn.text=Search
|
PersonaManagerTopComponent.searchBtn.text=Search
|
||||||
PersonaManagerTopComponent.resultsTable.columnModel.title1=Name
|
PersonaManagerTopComponent.resultsTable.columnModel.title1=Name
|
||||||
PersonaManagerTopComponent.resultsTable.columnModel.title0=ID
|
PersonaManagerTopComponent.resultsTable.columnModel.title0=ID
|
||||||
@ -20,6 +40,17 @@ PersonaManagerTopComponent.resultsTable.toolTipText=
|
|||||||
PersonaManagerTopComponent.searchAccountRadio.text=Account
|
PersonaManagerTopComponent.searchAccountRadio.text=Account
|
||||||
PersonaManagerTopComponent.searchNameRadio.text=Name
|
PersonaManagerTopComponent.searchNameRadio.text=Name
|
||||||
PersonaManagerTopComponent.searchField.text=
|
PersonaManagerTopComponent.searchField.text=
|
||||||
|
AddAccountDialog.cancelBtn.text=Cancel
|
||||||
|
AddAccountDialog.okBtn.text=OK
|
||||||
|
PersonaManagerTopComponent.editBtn.text=Edit Persona
|
||||||
|
PersonaDetailsDialog.cancelBtn.text=Cancel
|
||||||
|
PersonaDetailsDialog.okBtn.text=OK
|
||||||
|
PersonaDetailsPanel.deleteCaseBtn.text=Delete
|
||||||
|
PersonaDetailsPanel.addCaseBtn.text=Add
|
||||||
|
PersonaDetailsPanel.casesLbl.text=Cases found in:
|
||||||
|
PersonaDetailsPanel.deleteAliasBtn.text=Delete
|
||||||
|
PersonaDetailsPanel.addAliasBtn.text=Add
|
||||||
|
PersonaDetailsPanel.aliasesLabel.text=Aliases:
|
||||||
PersonaDetailsPanel.deleteMetadataBtn.text=Delete
|
PersonaDetailsPanel.deleteMetadataBtn.text=Delete
|
||||||
PersonaDetailsPanel.addMetadataBtn.text=Add
|
PersonaDetailsPanel.addMetadataBtn.text=Add
|
||||||
PersonaDetailsPanel.metadataLabel.text=Metadata:
|
PersonaDetailsPanel.metadataLabel.text=Metadata:
|
||||||
@ -27,18 +58,32 @@ PersonaDetailsPanel.deleteAccountBtn.text=Delete
|
|||||||
PersonaDetailsPanel.addAccountBtn.text=Add
|
PersonaDetailsPanel.addAccountBtn.text=Add
|
||||||
PersonaDetailsPanel.accountsLbl.text=Accounts:
|
PersonaDetailsPanel.accountsLbl.text=Accounts:
|
||||||
PersonaDetailsPanel.nameField.text=
|
PersonaDetailsPanel.nameField.text=
|
||||||
PersonaDetailsPanel.saveBtn.toolTipText=
|
|
||||||
PersonaDetailsPanel.saveBtn.text=Save Changes
|
|
||||||
PersonaDetailsPanel.nameLbl.text=Name:
|
PersonaDetailsPanel.nameLbl.text=Name:
|
||||||
PersonaDetailsPanel.deleteCaseBtn.text=Delete
|
AddAliasDialog.accountsLbl.text=Account:
|
||||||
PersonaDetailsPanel.addCaseBtn.text=Add
|
AddAliasDialog.okBtn.text=OK
|
||||||
PersonaDetailsPanel.casesLbl.text=Cases found in:
|
AddAliasDialog.cancelBtn.text=Cancel
|
||||||
PersonaDetailsPanel.deleteAliasBtn.text=Delete
|
AddMetadataDialog.cancelBtn.text=Cancel
|
||||||
PersonaDetailsPanel.addAliasBtn.text=Add
|
AddMetadataDialog.okBtn.text=OK
|
||||||
PersonaDetailsPanel.aliasesLabel.text=Aliases:
|
AddMetadataDialog.nameLbl.text=Name:
|
||||||
AddAccountDialog.cancelBtn.text=Cancel
|
AddMetadataDialog.nameTextField.text=
|
||||||
AddAccountDialog.okBtn.text=OK
|
AddMetadataDialog.valueLbl.text=Value:
|
||||||
PersonaManagerTopComponent.editBtn.text=Edit
|
AddMetadataDialog.valueTextField.text=
|
||||||
|
AddMetadataDialog.justificationLbl.text=Justification:
|
||||||
|
AddMetadataDialog.justificationTextField.text=
|
||||||
|
AddMetadataDialog.confidenceLbl.text=Confidence:
|
||||||
|
AddAliasDialog.justificationLbl.text=Justification:
|
||||||
|
AddAliasDialog.okBtn.text_1=OK
|
||||||
|
AddAliasDialog.cancelBtn.text_1=Cancel
|
||||||
|
AddAliasDialog.confidenceLbl.text=Confidence:
|
||||||
|
AddAliasDialog.justificationTextField.text=
|
||||||
|
AddAliasDialog.aliasLbl.text=Alias:
|
||||||
|
AddAliasDialog.aliasTextField.text=
|
||||||
|
AddAccountDialog.justificationTextField.text=
|
||||||
|
AddAccountDialog.justificationLbl.text=Justification:
|
||||||
|
AddAccountDialog.confidenceLbl.text=Confidence:
|
||||||
|
AddAccountDialog.typeLbl.text=Type:
|
||||||
|
AddAccountDialog.identiferLbl.text=Identifier:
|
||||||
|
AddAccountDialog.identifierTextField.text=
|
||||||
PMTopComponent_Name=Persona Manager
|
PMTopComponent_Name=Persona Manager
|
||||||
PMTopComponent_search_exception_msg=Failed to search personas
|
PMTopComponent_search_exception_msg=Failed to search personas
|
||||||
PMTopComponent_search_exception_Title=Search failure
|
PMTopComponent_search_exception_Title=Search failure
|
||||||
|
@ -560,7 +560,7 @@ public final class PersonaDetailsPanel extends javax.swing.JPanel {
|
|||||||
|
|
||||||
void clear() {
|
void clear() {
|
||||||
currentPersona = null;
|
currentPersona = null;
|
||||||
nameField.setText(Persona.getDefaultName());
|
nameField.setText(mode == PersonaDetailsMode.CREATE ? Persona.getDefaultName() : "");
|
||||||
currentAccounts = new ArrayList<>();
|
currentAccounts = new ArrayList<>();
|
||||||
currentMetadata = new ArrayList<>();
|
currentMetadata = new ArrayList<>();
|
||||||
currentAliases = new ArrayList<>();
|
currentAliases = new ArrayList<>();
|
||||||
@ -714,8 +714,8 @@ public final class PersonaDetailsPanel extends javax.swing.JPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Messages({
|
@Messages({
|
||||||
"PersonaDetailsPanel_NotEnoughAccounts_msg=A persona needs two or more accounts",
|
"PersonaDetailsPanel_NotEnoughAccounts_msg=A persona needs at least one account",
|
||||||
"PersonaDetailsPanel_NotEnoughAccounts_Title=Not enough accounts",
|
"PersonaDetailsPanel_NotEnoughAccounts_Title=Missing account",
|
||||||
"PersonaDetailsPanel_CentralRepoErr_msg=Failure to write to Central Repository",
|
"PersonaDetailsPanel_CentralRepoErr_msg=Failure to write to Central Repository",
|
||||||
"PersonaDetailsPanel_CentralRepoErr_Title=Central Repository failure",
|
"PersonaDetailsPanel_CentralRepoErr_Title=Central Repository failure",
|
||||||
"PersonaDetailsPanel_EmptyName_msg=Persona name cannot be empty",
|
"PersonaDetailsPanel_EmptyName_msg=Persona name cannot be empty",
|
||||||
|
@ -77,7 +77,8 @@
|
|||||||
<Component id="createBtn" min="-2" max="-2" attributes="0"/>
|
<Component id="createBtn" min="-2" max="-2" attributes="0"/>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Component id="editBtn" min="-2" max="-2" attributes="0"/>
|
<Component id="editBtn" min="-2" max="-2" attributes="0"/>
|
||||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
<EmptySpace max="32767" attributes="0"/>
|
||||||
|
<Component id="deleteBtn" min="-2" max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
<Component id="resultsPane" pref="0" max="32767" attributes="0"/>
|
<Component id="resultsPane" pref="0" max="32767" attributes="0"/>
|
||||||
<Component id="searchField" max="32767" attributes="0"/>
|
<Component id="searchField" max="32767" attributes="0"/>
|
||||||
@ -110,6 +111,7 @@
|
|||||||
<Group type="103" groupAlignment="3" attributes="0">
|
<Group type="103" groupAlignment="3" attributes="0">
|
||||||
<Component id="editBtn" alignment="3" min="-2" max="-2" attributes="0"/>
|
<Component id="editBtn" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
<Component id="createBtn" alignment="3" min="-2" max="-2" attributes="0"/>
|
<Component id="createBtn" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
|
<Component id="deleteBtn" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
@ -208,6 +210,14 @@
|
|||||||
<AuxValue name="generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
|
<AuxValue name="generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
|
||||||
</AuxValues>
|
</AuxValues>
|
||||||
</Component>
|
</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="PersonaManagerTopComponent.deleteBtn.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="enabled" type="boolean" value="false"/>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
</SubComponents>
|
</SubComponents>
|
||||||
</Container>
|
</Container>
|
||||||
<Component class="org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsPanel" name="detailsPanel">
|
<Component class="org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsPanel" name="detailsPanel">
|
||||||
|
@ -54,7 +54,9 @@ public final class PersonaManagerTopComponent extends TopComponent {
|
|||||||
private Persona selectedPersona = null;
|
private Persona selectedPersona = null;
|
||||||
|
|
||||||
@Messages({
|
@Messages({
|
||||||
"PMTopComponent_Name=Persona Manager"
|
"PMTopComponent_Name=Persona Manager",
|
||||||
|
"PMTopComponent_delete_exception_Title=Delete failure",
|
||||||
|
"PMTopComponent_delete_exception_msg=Failed to delete persona",
|
||||||
})
|
})
|
||||||
public PersonaManagerTopComponent() {
|
public PersonaManagerTopComponent() {
|
||||||
initComponents();
|
initComponents();
|
||||||
@ -84,6 +86,25 @@ public final class PersonaManagerTopComponent extends TopComponent {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
deleteBtn.addActionListener(new ActionListener() {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
try {
|
||||||
|
if (selectedPersona != null) {
|
||||||
|
selectedPersona.delete();
|
||||||
|
}
|
||||||
|
} 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.ERROR_MESSAGE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
executeSearch();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Results table
|
// Results table
|
||||||
resultsTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
resultsTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||||
resultsTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
|
resultsTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
|
||||||
@ -116,6 +137,7 @@ public final class PersonaManagerTopComponent extends TopComponent {
|
|||||||
Persona persona = currentResults.get(index);
|
Persona persona = currentResults.get(index);
|
||||||
selectedPersona = persona;
|
selectedPersona = persona;
|
||||||
editBtn.setEnabled(true);
|
editBtn.setEnabled(true);
|
||||||
|
deleteBtn.setEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -147,6 +169,8 @@ public final class PersonaManagerTopComponent extends TopComponent {
|
|||||||
if (selectedRow != -1) {
|
if (selectedRow != -1) {
|
||||||
setPersona(resultsTable.getSelectedRow());
|
setPersona(resultsTable.getSelectedRow());
|
||||||
detailsPanel.setMode(this, PersonaDetailsMode.VIEW, selectedPersona);
|
detailsPanel.setMode(this, PersonaDetailsMode.VIEW, selectedPersona);
|
||||||
|
} else {
|
||||||
|
detailsPanel.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,6 +213,7 @@ public final class PersonaManagerTopComponent extends TopComponent {
|
|||||||
resultsTable.clearSelection();
|
resultsTable.clearSelection();
|
||||||
updateResultsTable(results);
|
updateResultsTable(results);
|
||||||
editBtn.setEnabled(false);
|
editBtn.setEnabled(false);
|
||||||
|
deleteBtn.setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -216,6 +241,7 @@ public final class PersonaManagerTopComponent extends TopComponent {
|
|||||||
searchBtn = new javax.swing.JButton();
|
searchBtn = new javax.swing.JButton();
|
||||||
editBtn = new javax.swing.JButton();
|
editBtn = new javax.swing.JButton();
|
||||||
createBtn = new javax.swing.JButton();
|
createBtn = new javax.swing.JButton();
|
||||||
|
deleteBtn = new javax.swing.JButton();
|
||||||
detailsPanel = new org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsPanel();
|
detailsPanel = new org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsPanel();
|
||||||
|
|
||||||
setMinimumSize(new java.awt.Dimension(400, 400));
|
setMinimumSize(new java.awt.Dimension(400, 400));
|
||||||
@ -246,6 +272,9 @@ public final class PersonaManagerTopComponent extends TopComponent {
|
|||||||
|
|
||||||
org.openide.awt.Mnemonics.setLocalizedText(createBtn, org.openide.util.NbBundle.getMessage(PersonaManagerTopComponent.class, "PersonaManagerTopComponent.createBtn.text")); // NOI18N
|
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
|
||||||
|
deleteBtn.setEnabled(false);
|
||||||
|
|
||||||
javax.swing.GroupLayout searchPanelLayout = new javax.swing.GroupLayout(searchPanel);
|
javax.swing.GroupLayout searchPanelLayout = new javax.swing.GroupLayout(searchPanel);
|
||||||
searchPanel.setLayout(searchPanelLayout);
|
searchPanel.setLayout(searchPanelLayout);
|
||||||
searchPanelLayout.setHorizontalGroup(
|
searchPanelLayout.setHorizontalGroup(
|
||||||
@ -257,7 +286,8 @@ public final class PersonaManagerTopComponent extends TopComponent {
|
|||||||
.addComponent(createBtn)
|
.addComponent(createBtn)
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addComponent(editBtn)
|
.addComponent(editBtn)
|
||||||
.addGap(0, 0, Short.MAX_VALUE))
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||||
|
.addComponent(deleteBtn))
|
||||||
.addComponent(resultsPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
|
.addComponent(resultsPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
|
||||||
.addComponent(searchField)
|
.addComponent(searchField)
|
||||||
.addGroup(searchPanelLayout.createSequentialGroup()
|
.addGroup(searchPanelLayout.createSequentialGroup()
|
||||||
@ -283,7 +313,8 @@ public final class PersonaManagerTopComponent extends TopComponent {
|
|||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addGroup(searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
.addGroup(searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||||
.addComponent(editBtn)
|
.addComponent(editBtn)
|
||||||
.addComponent(createBtn))
|
.addComponent(createBtn)
|
||||||
|
.addComponent(deleteBtn))
|
||||||
.addContainerGap())
|
.addContainerGap())
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -304,6 +335,7 @@ public final class PersonaManagerTopComponent extends TopComponent {
|
|||||||
|
|
||||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
private javax.swing.JButton createBtn;
|
private javax.swing.JButton createBtn;
|
||||||
|
private javax.swing.JButton deleteBtn;
|
||||||
private org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsPanel detailsPanel;
|
private org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsPanel detailsPanel;
|
||||||
private javax.swing.JButton editBtn;
|
private javax.swing.JButton editBtn;
|
||||||
private javax.swing.JSplitPane jSplitPane1;
|
private javax.swing.JSplitPane jSplitPane1;
|
||||||
|
@ -20,12 +20,18 @@ package org.sleuthkit.autopsy.communications;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.logging.Level;
|
||||||
import javax.swing.Action;
|
import javax.swing.Action;
|
||||||
import org.openide.nodes.AbstractNode;
|
import org.openide.nodes.AbstractNode;
|
||||||
import org.openide.nodes.Children;
|
import org.openide.nodes.Children;
|
||||||
import org.openide.nodes.Sheet;
|
import org.openide.nodes.Sheet;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
|
import org.openide.util.NbBundle.Messages;
|
||||||
import org.openide.util.lookup.Lookups;
|
import org.openide.util.lookup.Lookups;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.PersonaAccount;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.datamodel.NodeProperty;
|
import org.sleuthkit.autopsy.datamodel.NodeProperty;
|
||||||
import org.sleuthkit.datamodel.Account;
|
import org.sleuthkit.datamodel.Account;
|
||||||
import org.sleuthkit.datamodel.AccountDeviceInstance;
|
import org.sleuthkit.datamodel.AccountDeviceInstance;
|
||||||
@ -37,6 +43,8 @@ import org.sleuthkit.datamodel.CommunicationsManager;
|
|||||||
*/
|
*/
|
||||||
final class AccountDeviceInstanceNode extends AbstractNode {
|
final class AccountDeviceInstanceNode extends AbstractNode {
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger(AccountDeviceInstanceNode.class.getName());
|
||||||
|
|
||||||
private final AccountDeviceInstanceKey accountDeviceInstanceKey;
|
private final AccountDeviceInstanceKey accountDeviceInstanceKey;
|
||||||
private final CommunicationsManager commsManager;
|
private final CommunicationsManager commsManager;
|
||||||
private final Account account;
|
private final Account account;
|
||||||
@ -103,4 +111,34 @@ final class AccountDeviceInstanceNode extends AbstractNode {
|
|||||||
actions.add(ResetAndPinAccountsAction.getInstance());
|
actions.add(ResetAndPinAccountsAction.getInstance());
|
||||||
return actions.toArray(new Action[actions.size()]);
|
return actions.toArray(new Action[actions.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Messages({
|
||||||
|
"# {0} - Contact Name",
|
||||||
|
"# {1} - Persona Name",
|
||||||
|
"AccountInstanceNode_Tooltip_Template=Contact: {0} - Persona: {1}",
|
||||||
|
"# {0} - PersonaAccount count",
|
||||||
|
"AccountInstanceNode_Tooltip_suffix=(1 of {0})"
|
||||||
|
})
|
||||||
|
@Override
|
||||||
|
public String getShortDescription() {
|
||||||
|
List<PersonaAccount> personaList;
|
||||||
|
try {
|
||||||
|
personaList = CVTPersonaCache.getPersonaAccounts(account);
|
||||||
|
} catch (ExecutionException ex) {
|
||||||
|
logger.log(Level.WARNING, "Failed to retrieve Persona details for node.", ex);
|
||||||
|
return getDisplayName();
|
||||||
|
}
|
||||||
|
|
||||||
|
String personaName;
|
||||||
|
if (!personaList.isEmpty()) {
|
||||||
|
personaName = personaList.get(0).getPersona().getName();
|
||||||
|
if (personaList.size() > 1) {
|
||||||
|
personaName += Bundle.AccountInstanceNode_Tooltip_suffix(Integer.toString(personaList.size()));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
personaName = "None";
|
||||||
|
}
|
||||||
|
|
||||||
|
return Bundle.AccountInstanceNode_Tooltip_Template(getDisplayName(), personaName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
96
Core/src/org/sleuthkit/autopsy/communications/CVTPersonaCache.java
Executable file
96
Core/src/org/sleuthkit/autopsy/communications/CVTPersonaCache.java
Executable file
@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2020 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.sleuthkit.autopsy.communications;
|
||||||
|
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
|
import com.google.common.cache.LoadingCache;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
|
||||||
|
import org.sleuthkit.autopsy.centralrepository.datamodel.PersonaAccount;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
import org.sleuthkit.datamodel.Account;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A singleton cache of the PersonaAccount information. The list of
|
||||||
|
* PersonaAccounts for a given Account typeSpecificID retrieved on first access
|
||||||
|
* and evicted from the cache after 5 minutes.
|
||||||
|
*/
|
||||||
|
final class CVTPersonaCache {
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger(CVTPersonaCache.class.getName());
|
||||||
|
private final LoadingCache<Account, List<PersonaAccount>> accountMap;
|
||||||
|
|
||||||
|
private static CVTPersonaCache instance;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache constructor.
|
||||||
|
*/
|
||||||
|
private CVTPersonaCache() {
|
||||||
|
accountMap = CacheBuilder.newBuilder().expireAfterAccess(5, TimeUnit.MINUTES).build(
|
||||||
|
new CacheLoader<Account, List<PersonaAccount>>() {
|
||||||
|
@Override
|
||||||
|
public List<PersonaAccount> load(Account key) {
|
||||||
|
List<PersonaAccount> accountList = new ArrayList<>();
|
||||||
|
try {
|
||||||
|
if (CentralRepository.isEnabled()) {
|
||||||
|
Collection<PersonaAccount> accounts = PersonaAccount.getPersonaAccountsForAccount(key);
|
||||||
|
accountList.addAll(accounts);
|
||||||
|
}
|
||||||
|
} catch (CentralRepoException ex) {
|
||||||
|
logger.log(Level.WARNING, String.format("Unable to load Persona information for account: %s", key), ex);
|
||||||
|
}
|
||||||
|
return accountList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the singleton instance of the cache.
|
||||||
|
*
|
||||||
|
* @return CVTPersonaCache instance.
|
||||||
|
*/
|
||||||
|
private static synchronized CVTPersonaCache getInstance() {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new CVTPersonaCache();
|
||||||
|
}
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the list of PersonaAccounts for the given Account typeSpecificId.
|
||||||
|
*
|
||||||
|
* @param typeSpecificID Account typeSpecificId.
|
||||||
|
*
|
||||||
|
* @return List of PersonaAccounts for id or empty list if none were found.
|
||||||
|
*
|
||||||
|
* @throws ExecutionException
|
||||||
|
*/
|
||||||
|
static synchronized List<PersonaAccount> getPersonaAccounts(Account account) throws ExecutionException {
|
||||||
|
return getInstance().accountMap.get(account);
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
AbstractAbstractFileNode.accessTimeColLbl=\u30a2\u30af\u30bb\u30b9\u6642\u523b
|
AbstractAbstractFileNode.accessTimeColLbl=\u30a2\u30af\u30bb\u30b9\u65e5\u6642
|
||||||
AbstractAbstractFileNode.attrAddrColLbl=\u5c5e\u6027\u30a2\u30c9\u30ec\u30b9
|
AbstractAbstractFileNode.attrAddrColLbl=\u5c5e\u6027\u30a2\u30c9\u30ec\u30b9
|
||||||
AbstractAbstractFileNode.changeTimeColLbl=\u6642\u523b\u5909\u66f4
|
AbstractAbstractFileNode.changeTimeColLbl=\u30a8\u30f3\u30c8\u30ea\u66f4\u65b0\u65e5\u6642
|
||||||
AbstractAbstractFileNode.createdTimeColLbl=\u4f5c\u6210\u3057\u305f\u6642\u523b
|
AbstractAbstractFileNode.createdTimeColLbl=\u4f5c\u6210\u65e5\u6642
|
||||||
AbstractAbstractFileNode.createSheet.comment.displayName=C
|
AbstractAbstractFileNode.createSheet.comment.displayName=C
|
||||||
AbstractAbstractFileNode.createSheet.comment.name=C
|
AbstractAbstractFileNode.createSheet.comment.name=C
|
||||||
# {0} - occurrenceCount
|
# {0} - occurrenceCount
|
||||||
@ -26,7 +26,7 @@ AbstractAbstractFileNode.md5HashColLbl=MD5\u30cf\u30c3\u30b7\u30e5
|
|||||||
AbstractAbstractFileNode.metaAddrColLbl=\u30e1\u30bf\u30a2\u30c9\u30ec\u30b9
|
AbstractAbstractFileNode.metaAddrColLbl=\u30e1\u30bf\u30a2\u30c9\u30ec\u30b9
|
||||||
AbstractAbstractFileNode.mimeType=MIME\u30bf\u30a4\u30d7
|
AbstractAbstractFileNode.mimeType=MIME\u30bf\u30a4\u30d7
|
||||||
AbstractAbstractFileNode.modeColLbl=\u30e2\u30fc\u30c9
|
AbstractAbstractFileNode.modeColLbl=\u30e2\u30fc\u30c9
|
||||||
AbstractAbstractFileNode.modifiedTimeColLbl=MFT\u5909\u66f4\u6642\u523b
|
AbstractAbstractFileNode.modifiedTimeColLbl=\u66f4\u65b0\u65e5\u6642
|
||||||
AbstractAbstractFileNode.nameColLbl=\u540d\u524d
|
AbstractAbstractFileNode.nameColLbl=\u540d\u524d
|
||||||
AbstractAbstractFileNode.objectId=\u30aa\u30d6\u30b8\u30a7\u30af\u30c8ID
|
AbstractAbstractFileNode.objectId=\u30aa\u30d6\u30b8\u30a7\u30af\u30c8ID
|
||||||
AbstractAbstractFileNode.originalName=\u30aa\u30ea\u30b8\u30ca\u30eb\u540d
|
AbstractAbstractFileNode.originalName=\u30aa\u30ea\u30b8\u30ca\u30eb\u540d
|
||||||
@ -136,14 +136,14 @@ ImageNode.createSheet.type.name=\u30bf\u30a4\u30d7
|
|||||||
ImageNode.createSheet.type.text=\u30a4\u30e1\u30fc\u30b8
|
ImageNode.createSheet.type.text=\u30a4\u30e1\u30fc\u30b8
|
||||||
ImageNode.getActions.openFileSearchByAttr.text=\u5c5e\u6027\u5225\u306b\u30d5\u30a1\u30a4\u30eb\u691c\u7d22\u3092\u958b\u304f
|
ImageNode.getActions.openFileSearchByAttr.text=\u5c5e\u6027\u5225\u306b\u30d5\u30a1\u30a4\u30eb\u691c\u7d22\u3092\u958b\u304f
|
||||||
KeyValueNode.menuItemText.viewFileInDir=\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u30fc\u5185\u306e\u30bd\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb\u3092\u8868\u793a
|
KeyValueNode.menuItemText.viewFileInDir=\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u30fc\u5185\u306e\u30bd\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb\u3092\u8868\u793a
|
||||||
KeywordHits.createNodeForKey.accessTime.desc=\u30a2\u30af\u30bb\u30b9\u6642\u523b
|
KeywordHits.createNodeForKey.accessTime.desc=\u30a2\u30af\u30bb\u30b9\u65e5\u6642
|
||||||
KeywordHits.createNodeForKey.accessTime.displayName=\u30a2\u30af\u30bb\u30b9\u6642\u523b
|
KeywordHits.createNodeForKey.accessTime.displayName=\u30a2\u30af\u30bb\u30b9\u65e5\u6642
|
||||||
KeywordHits.createNodeForKey.accessTime.name=AccessTime
|
KeywordHits.createNodeForKey.accessTime.name=AccessTime
|
||||||
KeywordHits.createNodeForKey.chgTime.desc=\u6642\u523b\u5909\u66f4
|
KeywordHits.createNodeForKey.chgTime.desc=\u30a8\u30f3\u30c8\u30ea\u66f4\u65b0\u65e5\u6642
|
||||||
KeywordHits.createNodeForKey.chgTime.displayName=\u5909\u66f4\u6642\u523b
|
KeywordHits.createNodeForKey.chgTime.displayName=\u30a8\u30f3\u30c8\u30ea\u66f4\u65b0\u65e5\u6642
|
||||||
KeywordHits.createNodeForKey.chgTime.name=ChangeTime
|
KeywordHits.createNodeForKey.chgTime.name=ChangeTime
|
||||||
KeywordHits.createNodeForKey.modTime.desc=MFT\u5909\u66f4\u6642\u523b
|
KeywordHits.createNodeForKey.modTime.desc=\u66f4\u65b0\u65e5\u6642
|
||||||
KeywordHits.createNodeForKey.modTime.displayName=MFT\u5909\u66f4\u6642\u523b
|
KeywordHits.createNodeForKey.modTime.displayName=\u66f4\u65b0\u65e5\u6642
|
||||||
KeywordHits.createNodeForKey.modTime.name=ModifiedTime
|
KeywordHits.createNodeForKey.modTime.name=ModifiedTime
|
||||||
KeywordHits.createSheet.filesWithHits.desc=\u8aac\u660e\u306a\u3057
|
KeywordHits.createSheet.filesWithHits.desc=\u8aac\u660e\u306a\u3057
|
||||||
KeywordHits.createSheet.filesWithHits.displayName=\u30d2\u30c3\u30c8\u306e\u3042\u308b\u30d5\u30a1\u30a4\u30eb
|
KeywordHits.createSheet.filesWithHits.displayName=\u30d2\u30c3\u30c8\u306e\u3042\u308b\u30d5\u30a1\u30a4\u30eb
|
||||||
@ -199,14 +199,14 @@ ContentTagNode.createSheet.filePath.name=\u30d5\u30a1\u30a4\u30eb\u30d1\u30b9
|
|||||||
ContentTagNode.createSheet.filePath.displayName=\u30d5\u30a1\u30a4\u30eb\u30d1\u30b9
|
ContentTagNode.createSheet.filePath.displayName=\u30d5\u30a1\u30a4\u30eb\u30d1\u30b9
|
||||||
ContentTagNode.createSheet.comment.name=\u30b3\u30e1\u30f3\u30c8
|
ContentTagNode.createSheet.comment.name=\u30b3\u30e1\u30f3\u30c8
|
||||||
ContentTagNode.createSheet.comment.displayName=\u30b3\u30e1\u30f3\u30c8
|
ContentTagNode.createSheet.comment.displayName=\u30b3\u30e1\u30f3\u30c8
|
||||||
ContentTagNode.createSheet.fileModifiedTime.nam=MFT\u5909\u66f4\u6642\u523b
|
ContentTagNode.createSheet.fileModifiedTime.nam=\u66f4\u65b0\u65e5\u6642
|
||||||
ContentTagNode.createSheet.fileModifiedTime.displayName=MFT\u5909\u66f4\u6642\u523b
|
ContentTagNode.createSheet.fileModifiedTime.displayName=\u66f4\u65b0\u65e5\u6642
|
||||||
ContentTagNode.createSheet.fileChangedTime.name=\u5909\u66f4\u3055\u308c\u305f\u523b\u523b
|
ContentTagNode.createSheet.fileChangedTime.name=\u30a8\u30f3\u30c8\u30ea\u66f4\u65b0\u65e5\u6642
|
||||||
ContentTagNode.createSheet.fileChangedTime.displayName=\u5909\u66f4\u3055\u308c\u305f\u523b\u523b
|
ContentTagNode.createSheet.fileChangedTime.displayName=\u30a8\u30f3\u30c8\u30ea\u66f4\u65b0\u65e5\u6642
|
||||||
ContentTagNode.createSheet.fileAccessedTime.name=\u30a2\u30af\u30bb\u30b9\u3055\u308c\u305f\u6642\u523b
|
ContentTagNode.createSheet.fileAccessedTime.name=\u30a2\u30af\u30bb\u30b9\u65e5\u6642
|
||||||
ContentTagNode.createSheet.fileAccessedTime.displayName=\u30a2\u30af\u30bb\u30b9\u3055\u308c\u305f\u6642\u523b
|
ContentTagNode.createSheet.fileAccessedTime.displayName=\u30a2\u30af\u30bb\u30b9\u65e5\u6642
|
||||||
ContentTagNode.createSheet.fileCreatedTime.name=\u4f5c\u6210\u3057\u305f\u6642\u523b
|
ContentTagNode.createSheet.fileCreatedTime.name=\u4f5c\u6210\u65e5\u6642
|
||||||
ContentTagNode.createSheet.fileCreatedTime.displayName=\u4f5c\u6210\u3057\u305f\u6642\u523b
|
ContentTagNode.createSheet.fileCreatedTime.displayName=\u4f5c\u6210\u65e5\u6642
|
||||||
ContentTagNode.createSheet.fileSize.name=\u30b5\u30a4\u30ba
|
ContentTagNode.createSheet.fileSize.name=\u30b5\u30a4\u30ba
|
||||||
ContentTagNode.createSheet.fileSize.displayName=\u30b5\u30a4\u30ba
|
ContentTagNode.createSheet.fileSize.displayName=\u30b5\u30a4\u30ba
|
||||||
ContentTagTypeNode.displayName.text=\u30d5\u30a1\u30a4\u30eb\u30bf\u30b0
|
ContentTagTypeNode.displayName.text=\u30d5\u30a1\u30a4\u30eb\u30bf\u30b0
|
||||||
|
@ -141,10 +141,10 @@ ReportGenerator.progress.createdThumb.text=\u30b5\u30e0\u30cd\u30a4\u30eb\u306e\
|
|||||||
ReportGenerator.htmlOutput.header.file=\u30d5\u30a1\u30a4\u30eb
|
ReportGenerator.htmlOutput.header.file=\u30d5\u30a1\u30a4\u30eb
|
||||||
ReportGenerator.htmlOutput.header.tag=\u30bf\u30b0
|
ReportGenerator.htmlOutput.header.tag=\u30bf\u30b0
|
||||||
ReportGenerator.htmlOutput.header.comment=\u30b3\u30e1\u30f3\u30c8
|
ReportGenerator.htmlOutput.header.comment=\u30b3\u30e1\u30f3\u30c8
|
||||||
ReportGenerator.htmlOutput.header.timeModified=MFT\u5909\u66f4\u6642\u523b
|
ReportGenerator.htmlOutput.header.timeModified=\u66f4\u65b0\u65e5\u6642
|
||||||
ReportGenerator.htmlOutput.header.timeChanged=\u5909\u66f4\u3055\u308c\u305f\u523b\u523b
|
ReportGenerator.htmlOutput.header.timeChanged=\u30a8\u30f3\u30c8\u30ea\u66f4\u65b0\u65e5\u6642
|
||||||
ReportGenerator.htmlOutput.header.timeAccessed=\u30a2\u30af\u30bb\u30b9\u3055\u308c\u305f\u6642\u523b
|
ReportGenerator.htmlOutput.header.timeAccessed=\u30a2\u30af\u30bb\u30b9\u65e5\u6642
|
||||||
ReportGenerator.htmlOutput.header.timeCreated=\u4f5c\u6210\u3055\u308c\u305f\u6642\u523b
|
ReportGenerator.htmlOutput.header.timeCreated=\u4f5c\u6210\u65e5\u6642
|
||||||
ReportGenerator.htmlOutput.header.size=\u30b5\u30a4\u30ba(\u30d0\u30a4\u30c8)
|
ReportGenerator.htmlOutput.header.size=\u30b5\u30a4\u30ba(\u30d0\u30a4\u30c8)
|
||||||
ReportGenerator.htmlOutput.header.hash=\u30cf\u30c3\u30b7\u30e5
|
ReportGenerator.htmlOutput.header.hash=\u30cf\u30c3\u30b7\u30e5
|
||||||
ReportGenerator.thumbnailTable.name=\u30bf\u30b0\u4ed8\u304d\u30a4\u30e1\u30fc\u30b8
|
ReportGenerator.thumbnailTable.name=\u30bf\u30b0\u4ed8\u304d\u30a4\u30e1\u30fc\u30b8
|
||||||
|
@ -95,6 +95,12 @@ final public class EventTypeUtils {
|
|||||||
imageFileName = "artifact-icon.png";
|
imageFileName = "artifact-icon.png";
|
||||||
} else if (typeID == TimelineEventType.WEB_FORM_ADDRESSES.getTypeID()) {
|
} else if (typeID == TimelineEventType.WEB_FORM_ADDRESSES.getTypeID()) {
|
||||||
imageFileName = "artifact-icon.png";
|
imageFileName = "artifact-icon.png";
|
||||||
|
} else if (typeID == TimelineEventType.METADATA_CREATED.getTypeID()) {
|
||||||
|
imageFileName = "blue-document-attribute-b.png";
|
||||||
|
} else if (typeID == TimelineEventType.METADATA_LAST_SAVED.getTypeID()) {
|
||||||
|
imageFileName = "blue-document-attribute-m.png";
|
||||||
|
} else if (typeID == TimelineEventType.METADATA_LAST_PRINTED.getTypeID()) {
|
||||||
|
imageFileName = "blue-document.png";
|
||||||
}else {
|
}else {
|
||||||
imageFileName = "timeline_marker.png";
|
imageFileName = "timeline_marker.png";
|
||||||
}
|
}
|
||||||
|
@ -19,11 +19,18 @@
|
|||||||
package org.sleuthkit.autopsy.keywordsearch;
|
package org.sleuthkit.autopsy.keywordsearch;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.io.CharSource;
|
import com.google.common.io.CharSource;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import static java.util.Locale.US;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
@ -54,6 +61,10 @@ import org.sleuthkit.autopsy.textextractors.TextFileExtractor;
|
|||||||
import org.sleuthkit.autopsy.textextractors.configs.ImageConfig;
|
import org.sleuthkit.autopsy.textextractors.configs.ImageConfig;
|
||||||
import org.sleuthkit.autopsy.textextractors.configs.StringsConfig;
|
import org.sleuthkit.autopsy.textextractors.configs.StringsConfig;
|
||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
|
import org.sleuthkit.datamodel.Blackboard;
|
||||||
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
|
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||||
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
import org.sleuthkit.datamodel.TskData;
|
import org.sleuthkit.datamodel.TskData;
|
||||||
import org.sleuthkit.datamodel.TskData.FileKnown;
|
import org.sleuthkit.datamodel.TskData.FileKnown;
|
||||||
|
|
||||||
@ -114,6 +125,26 @@ public final class KeywordSearchIngestModule implements FileIngestModule {
|
|||||||
"application/x-z", //NON-NLS
|
"application/x-z", //NON-NLS
|
||||||
"application/x-compress"); //NON-NLS
|
"application/x-compress"); //NON-NLS
|
||||||
|
|
||||||
|
private static final List<String> METADATA_DATE_TYPES
|
||||||
|
= ImmutableList.of(
|
||||||
|
"Last-Save-Date", //NON-NLS
|
||||||
|
"Last-Printed", //NON-NLS
|
||||||
|
"Creation-Date"); //NON-NLS
|
||||||
|
|
||||||
|
private static final Map<String, BlackboardAttribute.ATTRIBUTE_TYPE> METADATA_TYPES_MAP = ImmutableMap.<String, BlackboardAttribute.ATTRIBUTE_TYPE>builder()
|
||||||
|
.put("Last-Save-Date", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_MODIFIED)
|
||||||
|
.put("Last-Author", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_USER_ID)
|
||||||
|
.put("Creation-Date", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED)
|
||||||
|
.put("Company", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ORGANIZATION)
|
||||||
|
.put("Author", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_OWNER)
|
||||||
|
.put("Application-Name", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME)
|
||||||
|
.put("Last-Printed", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_LAST_PRINTED_DATETIME)
|
||||||
|
.put("Producer", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME)
|
||||||
|
.put("Title", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DESCRIPTION)
|
||||||
|
.put("pdf:PDFVersion", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_VERSION)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Options for this extractor
|
* Options for this extractor
|
||||||
*/
|
*/
|
||||||
@ -493,6 +524,9 @@ public final class KeywordSearchIngestModule implements FileIngestModule {
|
|||||||
Reader finalReader;
|
Reader finalReader;
|
||||||
try {
|
try {
|
||||||
Map<String, String> metadata = extractor.getMetadata();
|
Map<String, String> metadata = extractor.getMetadata();
|
||||||
|
if (!metadata.isEmpty()) {
|
||||||
|
createMetadataArtifact(aFile, metadata);
|
||||||
|
}
|
||||||
CharSource formattedMetadata = getMetaDataCharSource(metadata);
|
CharSource formattedMetadata = getMetaDataCharSource(metadata);
|
||||||
//Append the metadata to end of the file text
|
//Append the metadata to end of the file text
|
||||||
finalReader = CharSource.concat(new CharSource() {
|
finalReader = CharSource.concat(new CharSource() {
|
||||||
@ -516,6 +550,69 @@ public final class KeywordSearchIngestModule implements FileIngestModule {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void createMetadataArtifact(AbstractFile aFile, Map<String, String> metadata) {
|
||||||
|
|
||||||
|
String moduleName = KeywordSearchIngestModule.class.getName();
|
||||||
|
|
||||||
|
Collection<BlackboardAttribute> attributes = new ArrayList<>();
|
||||||
|
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
|
||||||
|
for (Map.Entry<String, String> entry : metadata.entrySet()) {
|
||||||
|
if (METADATA_TYPES_MAP.containsKey(entry.getKey())) {
|
||||||
|
BlackboardAttribute bba = checkAttribute(entry.getKey(), entry.getValue());
|
||||||
|
if (bba != null) {
|
||||||
|
attributes.add(bba);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!attributes.isEmpty()) {
|
||||||
|
try {
|
||||||
|
BlackboardArtifact bbart = aFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_METADATA);
|
||||||
|
bbart.addAttributes(attributes);
|
||||||
|
bbartifacts.add(bbart);
|
||||||
|
} catch (TskCoreException ex) {
|
||||||
|
// Log error and return to continue processing
|
||||||
|
logger.log(Level.WARNING, String.format("Error creating or adding metadata artifact for file %s.", aFile.getParentPath() + aFile.getName()), ex); //NON-NLS
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!bbartifacts.isEmpty()) {
|
||||||
|
try{
|
||||||
|
Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboard().postArtifacts(bbartifacts, moduleName);
|
||||||
|
} catch (NoCurrentCaseException | Blackboard.BlackboardException ex) {
|
||||||
|
// Log error and return to continue processing
|
||||||
|
logger.log(Level.WARNING, String.format("Unable to post blackboard artifacts for file $s.", aFile.getParentPath() + aFile.getName()) , ex); //NON-NLS
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private BlackboardAttribute checkAttribute(String key, String value) {
|
||||||
|
String moduleName = KeywordSearchIngestModule.class.getName();
|
||||||
|
if (!value.isEmpty() && value.charAt(0) != ' ') {
|
||||||
|
if (METADATA_DATE_TYPES.contains(key)) {
|
||||||
|
SimpleDateFormat metadataDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", US);
|
||||||
|
Long metadataDateTime = Long.valueOf(0);
|
||||||
|
try {
|
||||||
|
String metadataDate = value.replaceAll("T"," ").replaceAll("Z", "");
|
||||||
|
Date usedDate = metadataDateFormat.parse(metadataDate);
|
||||||
|
metadataDateTime = usedDate.getTime()/1000;
|
||||||
|
return new BlackboardAttribute(METADATA_TYPES_MAP.get(key), moduleName, metadataDateTime);
|
||||||
|
} catch (ParseException ex) {
|
||||||
|
// catching error and displaying date that could not be parsed then will continue on.
|
||||||
|
logger.log(Level.WARNING, String.format("Failed to parse date/time %s for metadata attribute %s.", value, key), ex); //NON-NLS
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return new BlackboardAttribute(METADATA_TYPES_MAP.get(key), moduleName, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pretty print the text extractor metadata.
|
* Pretty print the text extractor metadata.
|
||||||
*
|
*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user