mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-12 07:56:16 +00:00
Merge branch 'develop' of https://github.com/sleuthkit/autopsy into 6434-non-public-artifactviewers
This commit is contained in:
commit
a8ed98d037
@ -53,7 +53,7 @@ public interface CentralRepository {
|
||||
case SQLITE:
|
||||
return SqliteCentralRepo.getInstance();
|
||||
default:
|
||||
throw new CentralRepoException("Failed to get CentralRepository instance, Central Repositiory is not enabled.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -121,18 +121,22 @@ public class PersonaAccount {
|
||||
/**
|
||||
* Creates an account for the specified Persona.
|
||||
*
|
||||
* @param persona Persona for which the account is being added.
|
||||
* @param account Account.
|
||||
* @param persona Persona for which the account is being added.
|
||||
* @param account Account.
|
||||
* @param justification Reason for assigning the alias, may be null.
|
||||
* @param confidence Confidence level.
|
||||
* @param confidence Confidence level.
|
||||
*
|
||||
* @return PersonaAccount
|
||||
*
|
||||
* @throws CentralRepoException If there is an error in creating the
|
||||
* account.
|
||||
* 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();
|
||||
@ -147,7 +151,7 @@ public class PersonaAccount {
|
||||
+ currentExaminer.getId()
|
||||
+ ")";
|
||||
|
||||
cr.executeInsertSQL(insertClause);
|
||||
CentralRepository.getInstance().executeInsertSQL(insertClause);
|
||||
|
||||
String queryClause = PERSONA_ACCOUNTS_QUERY_CLAUSE
|
||||
+ "WHERE persona_id = " + persona.getId()
|
||||
@ -245,13 +249,19 @@ public class PersonaAccount {
|
||||
* persona_account.
|
||||
*/
|
||||
static Collection<PersonaAccount> getPersonaAccountsForPersona(long personaId) throws CentralRepoException {
|
||||
String queryClause = PERSONA_ACCOUNTS_QUERY_CLAUSE
|
||||
+ " WHERE persona_accounts.persona_id = " + personaId;
|
||||
CentralRepository cr = CentralRepository.getInstance();
|
||||
|
||||
PersonaAccountsQueryCallback queryCallback = new PersonaAccountsQueryCallback();
|
||||
CentralRepository.getInstance().executeSelectSQL(queryClause, queryCallback);
|
||||
if (cr != null) {
|
||||
String queryClause = PERSONA_ACCOUNTS_QUERY_CLAUSE
|
||||
+ " WHERE persona_accounts.persona_id = " + personaId;
|
||||
|
||||
return queryCallback.getPersonaAccountsList();
|
||||
PersonaAccountsQueryCallback queryCallback = new PersonaAccountsQueryCallback();
|
||||
cr.executeSelectSQL(queryClause, queryCallback);
|
||||
|
||||
return queryCallback.getPersonaAccountsList();
|
||||
}
|
||||
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -269,10 +279,16 @@ public class PersonaAccount {
|
||||
+ " WHERE persona_accounts.account_id = " + accountId
|
||||
+ " AND personas.status_id != " + Persona.PersonaStatus.DELETED.getStatusId();
|
||||
|
||||
PersonaAccountsQueryCallback queryCallback = new PersonaAccountsQueryCallback();
|
||||
CentralRepository.getInstance().executeSelectSQL(queryClause, queryCallback);
|
||||
CentralRepository cr = CentralRepository.getInstance();
|
||||
|
||||
return queryCallback.getPersonaAccountsList();
|
||||
if (cr != null) {
|
||||
PersonaAccountsQueryCallback queryCallback = new PersonaAccountsQueryCallback();
|
||||
cr.executeSelectSQL(queryClause, queryCallback);
|
||||
|
||||
return queryCallback.getPersonaAccountsList();
|
||||
}
|
||||
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -292,10 +308,15 @@ public class PersonaAccount {
|
||||
+ " WHERE LOWER(accounts.account_unique_identifier) LIKE LOWER('%" + accountIdentifierSubstring + "%')"
|
||||
+ " AND personas.status_id != " + Persona.PersonaStatus.DELETED.getStatusId();
|
||||
|
||||
PersonaAccountsQueryCallback queryCallback = new PersonaAccountsQueryCallback();
|
||||
CentralRepository.getInstance().executeSelectSQL(queryClause, queryCallback);
|
||||
CentralRepository cr = CentralRepository.getInstance();
|
||||
if (cr != null) {
|
||||
PersonaAccountsQueryCallback queryCallback = new PersonaAccountsQueryCallback();
|
||||
cr.executeSelectSQL(queryClause, queryCallback);
|
||||
|
||||
return queryCallback.getPersonaAccountsList();
|
||||
return queryCallback.getPersonaAccountsList();
|
||||
}
|
||||
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -314,10 +335,14 @@ public class PersonaAccount {
|
||||
+ " AND type_name = '" + account.getAccountType().getTypeName() + "' "
|
||||
+ " AND personas.status_id != " + Persona.PersonaStatus.DELETED.getStatusId();
|
||||
|
||||
PersonaAccountsQueryCallback queryCallback = new PersonaAccountsQueryCallback();
|
||||
CentralRepository.getInstance().executeSelectSQL(queryClause, queryCallback);
|
||||
return queryCallback.getPersonaAccountsList();
|
||||
CentralRepository cr = CentralRepository.getInstance();
|
||||
if (cr != null) {
|
||||
PersonaAccountsQueryCallback queryCallback = new PersonaAccountsQueryCallback();
|
||||
cr.executeSelectSQL(queryClause, queryCallback);
|
||||
return queryCallback.getPersonaAccountsList();
|
||||
}
|
||||
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -326,24 +351,36 @@ public class PersonaAccount {
|
||||
* @param id row id for the account to be removed
|
||||
*
|
||||
* @throws CentralRepoException If there is an error in removing the
|
||||
* account.
|
||||
* 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;
|
||||
CentralRepository.getInstance().executeDeleteSQL(deleteClause);
|
||||
cr.executeDeleteSQL(deleteClause);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Modifies the PersonaAccount row by the given id
|
||||
*
|
||||
* @param id row id for the account to be removed
|
||||
*
|
||||
* @throws CentralRepoException If there is an error in removing the
|
||||
* account.
|
||||
* 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;
|
||||
CentralRepository.getInstance().executeUpdateSQL(updateClause);
|
||||
cr.executeUpdateSQL(updateClause);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -381,25 +418,28 @@ public class PersonaAccount {
|
||||
* @param personaId Id of the persona to look for.
|
||||
*
|
||||
* @return Collection of all accounts associated with the given persona, may
|
||||
* be empty.
|
||||
*
|
||||
* be empty.
|
||||
* @throws CentralRepoException If there is an error in getting the
|
||||
* accounts.
|
||||
* accounts.
|
||||
*/
|
||||
static Collection<CentralRepoAccount> getAccountsForPersona(long personaId) throws CentralRepoException {
|
||||
CentralRepository cr = CentralRepository.getInstance();
|
||||
|
||||
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;
|
||||
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 "
|
||||
+ " 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();
|
||||
CentralRepository.getInstance().executeSelectSQL(queryClause, queryCallback);
|
||||
AccountsForPersonaQueryCallback queryCallback = new AccountsForPersonaQueryCallback();
|
||||
cr.executeSelectSQL(queryClause, queryCallback);
|
||||
|
||||
return queryCallback.getAccountsList();
|
||||
return queryCallback.getAccountsList();
|
||||
}
|
||||
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
@ -63,7 +63,6 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
public class ExtractedContent implements AutopsyVisitableItem {
|
||||
|
||||
private static final Set<IngestManager.IngestJobEvent> INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED);
|
||||
private static final Set<IngestManager.IngestModuleEvent> INGEST_MODULE_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestModuleEvent.DATA_ADDED);
|
||||
public static final String NAME = NbBundle.getMessage(RootNode.class, "ExtractedContentNode.name.text");
|
||||
private final long filteringDSObjId; // 0 if not filtering/grouping by data source
|
||||
private SleuthkitCase skCase; // set to null after case has been closed
|
||||
@ -145,12 +144,19 @@ public class ExtractedContent implements AutopsyVisitableItem {
|
||||
* This area has all of the blackboard artifacts that are not displayed in a
|
||||
* more specific form elsewhere in the tree.
|
||||
*/
|
||||
private class TypeFactory extends ChildFactory.Detachable<BlackboardArtifact.Type> {
|
||||
private class TypeFactory extends ChildFactory.Detachable<BlackboardArtifact.Type> implements RefreshThrottler.Refresher {
|
||||
|
||||
private final ArrayList<BlackboardArtifact.Type> doNotShow = new ArrayList<>();
|
||||
// maps the artifact type to its child node
|
||||
private final HashMap<BlackboardArtifact.Type, TypeNode> typeNodeList = new HashMap<>();
|
||||
|
||||
/**
|
||||
* RefreshThrottler is used to limit the number of refreshes performed
|
||||
* when CONTENT_CHANGED and DATA_ADDED ingest module events are
|
||||
* received.
|
||||
*/
|
||||
private final RefreshThrottler refreshThrottler = new RefreshThrottler(this);
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
TypeFactory() {
|
||||
super();
|
||||
@ -173,27 +179,11 @@ public class ExtractedContent implements AutopsyVisitableItem {
|
||||
|
||||
private final PropertyChangeListener pcl = (PropertyChangeEvent evt) -> {
|
||||
String eventType = evt.getPropertyName();
|
||||
if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) {
|
||||
/**
|
||||
* This is a stop gap measure until a different way of handling
|
||||
* the closing of cases is worked out. Currently, remote events
|
||||
* may be received for a case that is already closed.
|
||||
*/
|
||||
try {
|
||||
Case.getCurrentCaseThrows();
|
||||
/**
|
||||
* Due to some unresolved issues with how cases are closed,
|
||||
* it is possible for the event to have a null oldValue if
|
||||
* the event is a remote event.
|
||||
*/
|
||||
final ModuleDataEvent event = (ModuleDataEvent) evt.getOldValue();
|
||||
if (null != event && !(this.doNotShow.contains(event.getBlackboardArtifactType()))) {
|
||||
refresh(true);
|
||||
}
|
||||
} catch (NoCurrentCaseException notUsed) {
|
||||
/**
|
||||
* Case is closed, do nothing.
|
||||
*/
|
||||
if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
|
||||
// case was closed. Remove listeners so that we don't get called with a stale case handle
|
||||
if (evt.getNewValue() == null) {
|
||||
removeNotify();
|
||||
skCase = null;
|
||||
}
|
||||
} else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|
||||
|| eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) {
|
||||
@ -204,32 +194,26 @@ public class ExtractedContent implements AutopsyVisitableItem {
|
||||
*/
|
||||
try {
|
||||
Case.getCurrentCaseThrows();
|
||||
refresh(true);
|
||||
refresh(false);
|
||||
} catch (NoCurrentCaseException notUsed) {
|
||||
/**
|
||||
* Case is closed, do nothing.
|
||||
*/
|
||||
}
|
||||
} else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
|
||||
// case was closed. Remove listeners so that we don't get called with a stale case handle
|
||||
if (evt.getNewValue() == null) {
|
||||
removeNotify();
|
||||
skCase = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void addNotify() {
|
||||
refreshThrottler.registerForIngestModuleEvents();
|
||||
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl);
|
||||
IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl);
|
||||
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeNotify() {
|
||||
refreshThrottler.unregisterEventListener();
|
||||
IngestManager.getInstance().removeIngestJobEventListener(pcl);
|
||||
IngestManager.getInstance().removeIngestModuleEventListener(pcl);
|
||||
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl);
|
||||
typeNodeList.clear();
|
||||
}
|
||||
@ -273,6 +257,40 @@ public class ExtractedContent implements AutopsyVisitableItem {
|
||||
typeNodeList.put(key, node);
|
||||
return node;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh() {
|
||||
refresh(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRefreshRequired(PropertyChangeEvent evt) {
|
||||
String eventType = evt.getPropertyName();
|
||||
if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) {
|
||||
/**
|
||||
* This is a stop gap measure until a different way of handling
|
||||
* the closing of cases is worked out. Currently, remote events
|
||||
* may be received for a case that is already closed.
|
||||
*/
|
||||
try {
|
||||
Case.getCurrentCaseThrows();
|
||||
/**
|
||||
* Due to some unresolved issues with how cases are closed,
|
||||
* it is possible for the event to have a null oldValue if
|
||||
* the event is a remote event.
|
||||
*/
|
||||
final ModuleDataEvent event = (ModuleDataEvent) evt.getOldValue();
|
||||
if (null != event && !(this.doNotShow.contains(event.getBlackboardArtifactType()))) {
|
||||
return true;
|
||||
}
|
||||
} catch (NoCurrentCaseException notUsed) {
|
||||
/**
|
||||
* Case is closed, do nothing.
|
||||
*/
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -355,73 +373,53 @@ public class ExtractedContent implements AutopsyVisitableItem {
|
||||
/**
|
||||
* Creates children for a given artifact type
|
||||
*/
|
||||
private class ArtifactFactory extends BaseChildFactory<BlackboardArtifact> {
|
||||
private class ArtifactFactory extends BaseChildFactory<BlackboardArtifact> implements RefreshThrottler.Refresher {
|
||||
|
||||
private BlackboardArtifact.Type type;
|
||||
private final BlackboardArtifact.Type type;
|
||||
|
||||
/**
|
||||
* RefreshThrottler is used to limit the number of refreshes performed
|
||||
* when CONTENT_CHANGED and DATA_ADDED ingest module events are
|
||||
* received.
|
||||
*/
|
||||
private final RefreshThrottler refreshThrottler = new RefreshThrottler(this);
|
||||
|
||||
ArtifactFactory(BlackboardArtifact.Type type) {
|
||||
super(type.getTypeName());
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
private final PropertyChangeListener pcl = new PropertyChangeListener() {
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
String eventType = evt.getPropertyName();
|
||||
if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) {
|
||||
private final PropertyChangeListener pcl = (PropertyChangeEvent evt) -> {
|
||||
String eventType = evt.getPropertyName();
|
||||
if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|
||||
|| eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) {
|
||||
/**
|
||||
* Checking for a current case is a stop gap measure until a
|
||||
* different way of handling the closing of cases is worked out.
|
||||
* Currently, remote events may be received for a case that is
|
||||
* already closed.
|
||||
*/
|
||||
try {
|
||||
Case.getCurrentCaseThrows();
|
||||
refresh(false);
|
||||
} catch (NoCurrentCaseException notUsed) {
|
||||
/**
|
||||
* Checking for a current case is a stop gap measure until a
|
||||
* different way of handling the closing of cases is worked
|
||||
* out. Currently, remote events may be received for a case
|
||||
* that is already closed.
|
||||
* Case is closed, do nothing.
|
||||
*/
|
||||
try {
|
||||
Case.getCurrentCaseThrows();
|
||||
/**
|
||||
* Even with the check above, it is still possible that
|
||||
* the case will be closed in a different thread before
|
||||
* this code executes. If that happens, it is possible
|
||||
* for the event to have a null oldValue.
|
||||
*/
|
||||
final ModuleDataEvent event = (ModuleDataEvent) evt.getOldValue();
|
||||
if (null != event && event.getBlackboardArtifactType().equals(type)) {
|
||||
refresh(true);
|
||||
}
|
||||
} catch (NoCurrentCaseException notUsed) {
|
||||
/**
|
||||
* Case is closed, do nothing.
|
||||
*/
|
||||
}
|
||||
} else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|
||||
|| eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) {
|
||||
/**
|
||||
* Checking for a current case is a stop gap measure until a
|
||||
* different way of handling the closing of cases is worked
|
||||
* out. Currently, remote events may be received for a case
|
||||
* that is already closed.
|
||||
*/
|
||||
try {
|
||||
Case.getCurrentCaseThrows();
|
||||
refresh(true);
|
||||
} catch (NoCurrentCaseException notUsed) {
|
||||
/**
|
||||
* Case is closed, do nothing.
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void onAdd() {
|
||||
refreshThrottler.registerForIngestModuleEvents();
|
||||
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl);
|
||||
IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRemove() {
|
||||
refreshThrottler.unregisterEventListener();
|
||||
IngestManager.getInstance().removeIngestJobEventListener(pcl);
|
||||
IngestManager.getInstance().removeIngestModuleEventListener(pcl);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -451,5 +449,43 @@ public class ExtractedContent implements AutopsyVisitableItem {
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh() {
|
||||
refresh(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRefreshRequired(PropertyChangeEvent evt) {
|
||||
String eventType = evt.getPropertyName();
|
||||
if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) {
|
||||
|
||||
/**
|
||||
* Checking for a current case is a stop gap measure until a
|
||||
* different way of handling the closing of cases is worked out.
|
||||
* Currently, remote events may be received for a case that is
|
||||
* already closed.
|
||||
*/
|
||||
try {
|
||||
Case.getCurrentCaseThrows();
|
||||
/**
|
||||
* Even with the check above, it is still possible that the
|
||||
* case will be closed in a different thread before this
|
||||
* code executes. If that happens, it is possible for the
|
||||
* event to have a null oldValue.
|
||||
*/
|
||||
final ModuleDataEvent event = (ModuleDataEvent) evt.getOldValue();
|
||||
if (null != event && event.getBlackboardArtifactType().equals(type)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
} catch (NoCurrentCaseException notUsed) {
|
||||
/**
|
||||
* Case is closed, do nothing.
|
||||
*/
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -82,39 +82,26 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
|
||||
* Listens for case and ingest invest. Updates observers when events are
|
||||
* fired. FileType and FileTypes nodes are all listening to this.
|
||||
*/
|
||||
private class FileTypesByExtObservable extends Observable {
|
||||
private class FileTypesByExtObservable extends Observable implements RefreshThrottler.Refresher {
|
||||
|
||||
private final PropertyChangeListener pcl;
|
||||
private final Set<Case.Events> CASE_EVENTS_OF_INTEREST;
|
||||
/**
|
||||
* RefreshThrottler is used to limit the number of refreshes performed
|
||||
* when CONTENT_CHANGED and DATA_ADDED ingest module events are
|
||||
* received.
|
||||
*/
|
||||
private final RefreshThrottler refreshThrottler = new RefreshThrottler(this);
|
||||
|
||||
private FileTypesByExtObservable() {
|
||||
super();
|
||||
this.CASE_EVENTS_OF_INTEREST = EnumSet.of(Case.Events.DATA_SOURCE_ADDED, Case.Events.CURRENT_CASE);
|
||||
this.pcl = (PropertyChangeEvent evt) -> {
|
||||
String eventType = evt.getPropertyName();
|
||||
if (eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())
|
||||
|| eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|
||||
if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|
||||
|| eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())
|
||||
|| eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) {
|
||||
|
||||
/**
|
||||
* If a new file has been added but does not have an extension
|
||||
* there is nothing to do.
|
||||
*/
|
||||
if (eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())) {
|
||||
if ((evt.getOldValue() instanceof ModuleContentEvent) == false) {
|
||||
return;
|
||||
}
|
||||
ModuleContentEvent moduleContentEvent = (ModuleContentEvent) evt.getOldValue();
|
||||
if ((moduleContentEvent.getSource() instanceof AbstractFile) == false) {
|
||||
return;
|
||||
}
|
||||
AbstractFile abstractFile = (AbstractFile) moduleContentEvent.getSource();
|
||||
if (abstractFile.getNameExtension().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checking for a current case is a stop gap measure until a
|
||||
* different way of handling the closing of cases is worked
|
||||
@ -139,14 +126,14 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
|
||||
};
|
||||
|
||||
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl);
|
||||
IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl);
|
||||
refreshThrottler.registerForIngestModuleEvents();
|
||||
Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, pcl);
|
||||
}
|
||||
|
||||
private void removeListeners() {
|
||||
deleteObservers();
|
||||
IngestManager.getInstance().removeIngestJobEventListener(pcl);
|
||||
IngestManager.getInstance().removeIngestModuleEventListener(pcl);
|
||||
refreshThrottler.unregisterEventListener();
|
||||
Case.removeEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, pcl);
|
||||
}
|
||||
|
||||
@ -154,7 +141,52 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
|
||||
setChanged();
|
||||
notifyObservers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh() {
|
||||
typesRoot.updateShowCounts();
|
||||
update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRefreshRequired(PropertyChangeEvent evt) {
|
||||
String eventType = evt.getPropertyName();
|
||||
if (eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())) {
|
||||
|
||||
/**
|
||||
* Checking for a current case is a stop gap measure until a
|
||||
* different way of handling the closing of cases is worked out.
|
||||
* Currently, remote events may be received for a case that is
|
||||
* already closed.
|
||||
*/
|
||||
try {
|
||||
Case.getCurrentCaseThrows();
|
||||
/**
|
||||
* If a new file has been added but does not have an
|
||||
* extension there is nothing to do.
|
||||
*/
|
||||
if ((evt.getOldValue() instanceof ModuleContentEvent) == false) {
|
||||
return false;
|
||||
}
|
||||
ModuleContentEvent moduleContentEvent = (ModuleContentEvent) evt.getOldValue();
|
||||
if ((moduleContentEvent.getSource() instanceof AbstractFile) == false) {
|
||||
return false;
|
||||
}
|
||||
AbstractFile abstractFile = (AbstractFile) moduleContentEvent.getSource();
|
||||
if (!abstractFile.getNameExtension().isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
} catch (NoCurrentCaseException ex) {
|
||||
/**
|
||||
* Case is closed, no refresh needed.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static final String FNAME = NbBundle.getMessage(FileTypesByExtNode.class, "FileTypesByExtNode.fname.text");
|
||||
|
||||
/**
|
||||
|
125
Core/src/org/sleuthkit/autopsy/datamodel/RefreshThrottler.java
Normal file
125
Core/src/org/sleuthkit/autopsy/datamodel/RefreshThrottler.java
Normal file
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-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.datamodel;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
|
||||
/**
|
||||
* Utility class that can be used by UI nodes to reduce the number of
|
||||
* potentially expensive UI refresh events when DATA_ADDED and CONTENT_CHANGED
|
||||
* ingest manager events are received.
|
||||
*/
|
||||
class RefreshThrottler {
|
||||
|
||||
/**
|
||||
* The Refresher interface needs to be implemented by ChildFactory instances
|
||||
* that wish to take advantage of throttled refresh functionality.
|
||||
*/
|
||||
interface Refresher {
|
||||
|
||||
/**
|
||||
* The RefreshThrottler calls this method when the RefreshTask runs.
|
||||
*
|
||||
*/
|
||||
void refresh();
|
||||
|
||||
/**
|
||||
* Determine whether the given event should result in a refresh.
|
||||
*
|
||||
* @param evt
|
||||
*
|
||||
* @return true if event should trigger a refresh, otherwise false.
|
||||
*/
|
||||
boolean isRefreshRequired(PropertyChangeEvent evt);
|
||||
}
|
||||
|
||||
static ScheduledThreadPoolExecutor refreshExecutor = new ScheduledThreadPoolExecutor(1, new ThreadFactoryBuilder().setNameFormat("Node Refresh Thread").build());
|
||||
// Keep a thread safe reference to the current refresh task (if any)
|
||||
private final AtomicReference<RefreshTask> refreshTaskRef;
|
||||
|
||||
// The factory instance that will be called when a refresh is due.
|
||||
private final Refresher refresher;
|
||||
|
||||
private static final long MIN_SECONDS_BETWEEN_REFRESH = 5;
|
||||
|
||||
private static final Set<IngestManager.IngestModuleEvent> INGEST_MODULE_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestModuleEvent.DATA_ADDED, IngestManager.IngestModuleEvent.CONTENT_CHANGED);
|
||||
|
||||
/**
|
||||
* A RefreshTask is scheduled to run when an event arrives and there isn't
|
||||
* one already scheduled.
|
||||
*/
|
||||
private final class RefreshTask implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
// Call refresh on the factory
|
||||
refresher.refresh();
|
||||
// Clear the refresh task reference
|
||||
refreshTaskRef.set(null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* PropertyChangeListener that reacts to DATA_ADDED and CONTENT_CHANGED
|
||||
* events and schedules a refresh task if one is not already scheduled.
|
||||
*/
|
||||
private final PropertyChangeListener pcl;
|
||||
|
||||
RefreshThrottler(Refresher r) {
|
||||
this.refreshTaskRef = new AtomicReference<>(null);
|
||||
refresher = r;
|
||||
|
||||
pcl = (PropertyChangeEvent evt) -> {
|
||||
String eventType = evt.getPropertyName();
|
||||
if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())
|
||||
|| eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())) {
|
||||
if (!refresher.isRefreshRequired(evt)) {
|
||||
return;
|
||||
}
|
||||
|
||||
RefreshTask task = new RefreshTask();
|
||||
if (refreshTaskRef.compareAndSet(null, task)) {
|
||||
refreshExecutor.schedule(task, MIN_SECONDS_BETWEEN_REFRESH, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up listener for ingest module events of interest.
|
||||
*/
|
||||
void registerForIngestModuleEvents() {
|
||||
IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove ingest module event listener.
|
||||
*/
|
||||
void unregisterEventListener() {
|
||||
IngestManager.getInstance().removeIngestModuleEventListener(pcl);
|
||||
}
|
||||
}
|
@ -101,7 +101,7 @@ abstract class AbstractFiltersPanel extends JPanel implements ActionListener, Li
|
||||
constraints.weightx = LABEL_WEIGHT;
|
||||
constraints.weighty = LABEL_WEIGHT;
|
||||
constraints.gridwidth = LABEL_WIDTH;
|
||||
addToGridBagLayout(filterPanel.getCheckbox(), null, column);
|
||||
addToGridBagLayout(filterPanel.getCheckbox(), filterPanel.getAdditionalLabel(), column);
|
||||
if (filterPanel.hasPanel()) {
|
||||
constraints.gridx += constraints.gridwidth;
|
||||
constraints.fill = GridBagConstraints.BOTH;
|
||||
|
@ -101,3 +101,6 @@ DocumentFilterPanel.documentsFiltersSplitPane.border.title=Step 2: Filter which
|
||||
ImageFilterPanel.imageFiltersSplitPane.border.title=Step 2: Filter which images to show
|
||||
VideoFilterPanel.videoFiltersSplitPane.border.title=Step 2: Filter which videos to show
|
||||
DiscoveryDialog.step1Label.text=Step 1: Choose result type
|
||||
ResultsSplitPaneDivider.hideButton.text=
|
||||
ResultsSplitPaneDivider.showButton.text=
|
||||
ResultsSplitPaneDivider.detailsLabel.text=Details Area
|
||||
|
@ -11,7 +11,7 @@ DiscoveryTopComponent.name=\ Discovery
|
||||
DiscoveryTopComponent.newSearch.text=New Search
|
||||
DiscoveryTopComponent.searchCancelled.text=Search has been cancelled.
|
||||
# {0} - search
|
||||
DiscoveryTopComponent.searchComplete.text=Results for {0}
|
||||
DiscoveryTopComponent.searchComplete.text=Results with {0}
|
||||
# {0} - searchType
|
||||
DiscoveryTopComponent.searchInProgress.text=Performing search for results of type {0}. Please wait.
|
||||
DiscoveryUiUtility.bytes.text=bytes
|
||||
@ -57,18 +57,24 @@ FileSearch.InterestingItemGroupKey.noSets=None
|
||||
FileSearch.KeywordListGroupKey.noKeywords=None
|
||||
FileSearch.NoGroupingGroupKey.allFiles=All Files
|
||||
FileSearch.ObjectDetectedGroupKey.noSets=None
|
||||
FileSearchData.FileSize.LARGE_IMAGE.displayName=Large: 1-50MB
|
||||
FileSearchData.FileSize.LARGE_VIDEO.displayName=Large: 1-5GB
|
||||
FileSearchData.FileSize.MEDIUM_IMAGE.displayName=Medium: 100KB-1MB
|
||||
FileSearchData.FileSize.MEDIUM_VIDEO.displayName=Medium: 100MB-1GB
|
||||
FileSearchData.FileSize.SMALL_IMAGE.displayName=Small: 16-100KB
|
||||
FileSearchData.FileSize.SMALL_VIDEO.displayName=Small: 500KB-100MB
|
||||
FileSearchData.FileSize.XLARGE_IMAGE.displayName=XLarge: 50-200MB
|
||||
FileSearchData.FileSize.XLARGE_VIDEO.displayName=XLarge: 5-10GB
|
||||
FileSearchData.FileSize.XSMALL_IMAGE.displayName=XSmall: 0-16KB
|
||||
FileSearchData.FileSize.XSMALL_VIDEO.displayName=XSmall: 0-500KB
|
||||
FileSearchData.FileSize.XXLARGE_IMAGE.displayName=XXLarge: 200MB+
|
||||
FileSearchData.FileSize.XXLARGE_VIDEO.displayName=XXLarge: 10GB+
|
||||
FileSearchData.FileSize.100kbto1mb=: 100KB-1MB
|
||||
FileSearchData.FileSize.100mbto1gb=: 100MB-1GB
|
||||
FileSearchData.FileSize.10PlusGb=: 10GB+
|
||||
FileSearchData.FileSize.16kbto100kb=: 16-100KB
|
||||
FileSearchData.FileSize.1gbto5gb=: 1-5GB
|
||||
FileSearchData.FileSize.1mbto50mb=: 1-50MB
|
||||
FileSearchData.FileSize.200PlusMb=: 200MB+
|
||||
FileSearchData.FileSize.500kbto100mb=: 500KB-100MB
|
||||
FileSearchData.FileSize.50mbto200mb=: 50-200MB
|
||||
FileSearchData.FileSize.5gbto10gb=: 5-10GB
|
||||
FileSearchData.FileSize.LARGE.displayName=Large
|
||||
FileSearchData.FileSize.MEDIUM.displayName=Medium
|
||||
FileSearchData.FileSize.SMALL.displayName=Small
|
||||
FileSearchData.FileSize.upTo16kb=: 0-16KB
|
||||
FileSearchData.FileSize.upTo500kb=: 0-500KB
|
||||
FileSearchData.FileSize.XLARGE.displayName=XLarge
|
||||
FileSearchData.FileSize.XSMALL.displayName=XSmall
|
||||
FileSearchData.FileSize.XXLARGE.displayName=XXLarge
|
||||
FileSearchData.FileType.Audio.displayName=Audio
|
||||
FileSearchData.FileType.Documents.displayName=Documents
|
||||
FileSearchData.FileType.Executables.displayName=Executables
|
||||
@ -106,45 +112,44 @@ FileSearchFiltering.concatenateSetNamesForDisplay.comma=,
|
||||
# {1} - Data source ID
|
||||
FileSearchFiltering.DataSourceFilter.datasource={0}({1})
|
||||
# {0} - filters
|
||||
FileSearchFiltering.DataSourceFilter.desc=Files in data source(s): {0}
|
||||
FileSearchFiltering.DataSourceFilter.or=\ or
|
||||
FileSearchFiltering.DataSourceFilter.desc=Data source(s): {0}
|
||||
FileSearchFiltering.DataSourceFilter.or=,
|
||||
# {0} - filters
|
||||
FileSearchFiltering.FileTypeFilter.desc=Files with type: {0}
|
||||
FileSearchFiltering.FileTypeFilter.or=\ or
|
||||
FileSearchFiltering.FileTypeFilter.desc=Type: {0}
|
||||
FileSearchFiltering.FileTypeFilter.or=,
|
||||
# {0} - filters
|
||||
FileSearchFiltering.FrequencyFilter.desc=Files with frequency: {0}
|
||||
FileSearchFiltering.FrequencyFilter.or=\ or
|
||||
FileSearchFiltering.FrequencyFilter.desc=Past occurrences: {0}
|
||||
FileSearchFiltering.FrequencyFilter.or=,
|
||||
# {0} - filters
|
||||
FileSearchFiltering.HashSetFilter.desc=Files with hash set hits in set(s): {0}
|
||||
FileSearchFiltering.HashSetFilter.desc=Hash set hits in set(s): {0}
|
||||
# {0} - filters
|
||||
FileSearchFiltering.InterestingItemSetFilter.desc=Files with interesting item hits in set(s): {0}
|
||||
FileSearchFiltering.InterestingItemSetFilter.desc=Interesting item hits in set(s): {0}
|
||||
# {0} - filters
|
||||
FileSearchFiltering.KeywordListFilter.desc=Files with keywords in list(s): {0}
|
||||
FileSearchFiltering.KnownFilter.desc=Files which are not known
|
||||
FileSearchFiltering.KeywordListFilter.desc=Keywords in list(s): {0}
|
||||
FileSearchFiltering.KnownFilter.desc=which are not known
|
||||
# {0} - filters
|
||||
FileSearchFiltering.ObjectDetectionFilter.desc=Files with objects detected in set(s): {0}
|
||||
FileSearchFiltering.ObjectDetectionFilter.desc=Objects detected in set(s): {0}
|
||||
# {0} - filters
|
||||
FileSearchFiltering.ParentFilter.desc=Files with paths matching: {0}
|
||||
FileSearchFiltering.ParentFilter.desc=Paths matching: {0}
|
||||
FileSearchFiltering.ParentFilter.exact=(exact match)
|
||||
FileSearchFiltering.ParentFilter.or=\ or
|
||||
FileSearchFiltering.ParentFilter.excluded=(excluded)
|
||||
FileSearchFiltering.ParentFilter.included=(included)
|
||||
FileSearchFiltering.ParentFilter.or=,
|
||||
FileSearchFiltering.ParentFilter.substring=(substring)
|
||||
FileSearchFiltering.ParentSearchTerm.excludeString=\ (exclude)
|
||||
FileSearchFiltering.ParentSearchTerm.fullString=\ (exact)
|
||||
FileSearchFiltering.ParentSearchTerm.includeString=\ (include)
|
||||
FileSearchFiltering.ParentSearchTerm.subString=\ (substring)
|
||||
FileSearchFiltering.PreviouslyNotableFilter.desc=Files that were previously marked as notable
|
||||
FileSearchFiltering.PreviouslyNotableFilter.desc=that were previously marked as notable
|
||||
# {0} - filters
|
||||
FileSearchFiltering.ScoreFilter.desc=Files with score(s) of : {0}
|
||||
FileSearchFiltering.ScoreFilter.desc=Score(s) of : {0}
|
||||
# {0} - filters
|
||||
FileSearchFiltering.SizeFilter.desc=Files with size in range(s): {0}
|
||||
FileSearchFiltering.SizeFilter.or=\ or
|
||||
# {0} - Minimum bytes
|
||||
# {1} - Maximum bytes
|
||||
FileSearchFiltering.SizeFilter.range=({0} to {1})
|
||||
FileSearchFiltering.SizeFilter.desc=Size(s): {0}
|
||||
FileSearchFiltering.SizeFilter.or=,
|
||||
# {0} - tag names
|
||||
FileSearchFiltering.TagsFilter.desc=Files that have been tagged {0}
|
||||
FileSearchFiltering.TagsFilter.or=\ or
|
||||
FileSearchFiltering.UserCreatedFilter.desc=Files that contain EXIF data
|
||||
FileSearchFiltering.TagsFilter.desc=Tagged {0}
|
||||
FileSearchFiltering.TagsFilter.or=,
|
||||
FileSearchFiltering.UserCreatedFilter.desc=that contain EXIF data
|
||||
FileSearchPanel.sortingPanel.border.title=Grouping
|
||||
FileSearchPanel.addButton.text=Add
|
||||
FileSearchPanel.substringRadioButton.text=Substring
|
||||
@ -259,6 +264,9 @@ DocumentFilterPanel.documentsFiltersSplitPane.border.title=Step 2: Filter which
|
||||
ImageFilterPanel.imageFiltersSplitPane.border.title=Step 2: Filter which images to show
|
||||
VideoFilterPanel.videoFiltersSplitPane.border.title=Step 2: Filter which videos to show
|
||||
DiscoveryDialog.step1Label.text=Step 1: Choose result type
|
||||
ResultsSplitPaneDivider.hideButton.text=
|
||||
ResultsSplitPaneDivider.showButton.text=
|
||||
ResultsSplitPaneDivider.detailsLabel.text=Details Area
|
||||
VideoThumbnailPanel.bytes.text=bytes
|
||||
VideoThumbnailPanel.deleted.text=All instances of file are deleted.
|
||||
VideoThumbnailPanel.gigaBytes.text=GB
|
||||
|
@ -43,23 +43,25 @@
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace pref="196" max="32767" attributes="0"/>
|
||||
<Group type="103" groupAlignment="1" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="filler1" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="step1Label" min="-2" pref="243" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace min="10" pref="10" max="-2" attributes="0"/>
|
||||
<Component id="imagesButton" min="-2" pref="110" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="videosButton" min="-2" pref="110" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="documentsButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace pref="370" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="step1Label" min="-2" pref="243" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="filler1" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace pref="391" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace pref="196" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
|
@ -275,19 +275,21 @@ final class DiscoveryDialog extends javax.swing.JDialog {
|
||||
toolBarPanelLayout.setHorizontalGroup(
|
||||
toolBarPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(toolBarPanelLayout.createSequentialGroup()
|
||||
.addContainerGap(196, Short.MAX_VALUE)
|
||||
.addGroup(toolBarPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, toolBarPanelLayout.createSequentialGroup()
|
||||
.addComponent(filler1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(step1Label, javax.swing.GroupLayout.PREFERRED_SIZE, 243, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addContainerGap()
|
||||
.addGroup(toolBarPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(toolBarPanelLayout.createSequentialGroup()
|
||||
.addGap(10, 10, 10)
|
||||
.addComponent(imagesButton, javax.swing.GroupLayout.PREFERRED_SIZE, 110, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(videosButton, javax.swing.GroupLayout.PREFERRED_SIZE, 110, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(documentsButton)))
|
||||
.addContainerGap(196, Short.MAX_VALUE))
|
||||
.addComponent(documentsButton)
|
||||
.addContainerGap(370, Short.MAX_VALUE))
|
||||
.addGroup(toolBarPanelLayout.createSequentialGroup()
|
||||
.addComponent(step1Label, javax.swing.GroupLayout.PREFERRED_SIZE, 243, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(filler1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap(391, Short.MAX_VALUE))))
|
||||
);
|
||||
toolBarPanelLayout.setVerticalGroup(
|
||||
toolBarPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
|
@ -41,7 +41,7 @@
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JSplitPane" name="rightSplitPane">
|
||||
<Properties>
|
||||
<Property name="dividerSize" type="int" value="15"/>
|
||||
<Property name="dividerSize" type="int" value="35"/>
|
||||
<Property name="orientation" type="int" value="0"/>
|
||||
<Property name="resizeWeight" type="double" value="1.0"/>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
|
@ -19,11 +19,14 @@
|
||||
package org.sleuthkit.autopsy.discovery;
|
||||
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.swing.JSplitPane;
|
||||
import javax.swing.plaf.basic.BasicSplitPaneDivider;
|
||||
import javax.swing.plaf.basic.BasicSplitPaneUI;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.openide.windows.Mode;
|
||||
@ -67,6 +70,34 @@ public final class DiscoveryTopComponent extends TopComponent {
|
||||
mainSplitPane.setLeftComponent(groupListPanel);
|
||||
rightSplitPane.setTopComponent(resultsPanel);
|
||||
rightSplitPane.setBottomComponent(detailsPanel);
|
||||
//set color of divider
|
||||
rightSplitPane.setUI(new BasicSplitPaneUI() {
|
||||
@Override
|
||||
public BasicSplitPaneDivider createDefaultDivider() {
|
||||
return new BasicSplitPaneDividerImpl(this);
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Private class for replacing the divider for the results split pane.
|
||||
*/
|
||||
private final class BasicSplitPaneDividerImpl extends BasicSplitPaneDivider {
|
||||
|
||||
/**
|
||||
* Construct a new BasicSplitPaneDividerImpl.
|
||||
*
|
||||
* @param ui The component which contains the split pane this divider is
|
||||
* in.
|
||||
*/
|
||||
BasicSplitPaneDividerImpl(BasicSplitPaneUI ui) {
|
||||
super(ui);
|
||||
this.setLayout(new BorderLayout());
|
||||
this.add(new ResultsSplitPaneDivider());
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -129,7 +160,7 @@ public final class DiscoveryTopComponent extends TopComponent {
|
||||
mainSplitPane.setDividerLocation(250);
|
||||
mainSplitPane.setPreferredSize(new java.awt.Dimension(1100, 700));
|
||||
|
||||
rightSplitPane.setDividerSize(15);
|
||||
rightSplitPane.setDividerSize(35);
|
||||
rightSplitPane.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
|
||||
rightSplitPane.setResizeWeight(1.0);
|
||||
rightSplitPane.setPreferredSize(new java.awt.Dimension(800, 700));
|
||||
@ -249,11 +280,11 @@ public final class DiscoveryTopComponent extends TopComponent {
|
||||
@Subscribe
|
||||
@Messages({"DiscoveryTopComponent.newSearch.text=New Search",
|
||||
"# {0} - search",
|
||||
"DiscoveryTopComponent.searchComplete.text=Results for {0}"})
|
||||
"DiscoveryTopComponent.searchComplete.text=Results with {0}"})
|
||||
void handleSearchCompleteEvent(DiscoveryEventUtils.SearchCompleteEvent searchCompleteEvent) {
|
||||
newSearchButton.setText(Bundle.DiscoveryTopComponent_newSearch_text());
|
||||
progressMessageTextArea.setForeground(Color.black);
|
||||
progressMessageTextArea.setText(Bundle.DiscoveryTopComponent_searchComplete_text(searchCompleteEvent.getFilters().stream().map(FileFilter::getDesc).collect(Collectors.joining(", "))));
|
||||
progressMessageTextArea.setText(Bundle.DiscoveryTopComponent_searchComplete_text(searchCompleteEvent.getFilters().stream().map(FileFilter::getDesc).collect(Collectors.joining("; "))));
|
||||
progressMessageTextArea.setCaretPosition(0);
|
||||
}
|
||||
|
||||
@ -269,6 +300,7 @@ public final class DiscoveryTopComponent extends TopComponent {
|
||||
newSearchButton.setText(Bundle.DiscoveryTopComponent_newSearch_text());
|
||||
progressMessageTextArea.setForeground(Color.red);
|
||||
progressMessageTextArea.setText(Bundle.DiscoveryTopComponent_searchCancelled_text());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -45,7 +45,6 @@ final class DocumentFilterPanel extends AbstractFiltersPanel {
|
||||
addFilter(new PastOccurrencesFilterPanel(), true, pastOccurrencesIndices, 0);
|
||||
addFilter(new HashSetFilterPanel(), false, null, 1);
|
||||
addFilter(new InterestingItemsFilterPanel(), false, null, 1);
|
||||
addFilter(new ObjectDetectedFilterPanel(), false, null, 1);
|
||||
addFilter(new ParentFolderFilterPanel(), false, null, 1);
|
||||
addPanelsToScrollPane(documentsFiltersSplitPane);
|
||||
}
|
||||
|
@ -126,39 +126,46 @@ final class FileSearchData {
|
||||
* Enum representing the file size
|
||||
*/
|
||||
@NbBundle.Messages({
|
||||
"FileSearchData.FileSize.XXLARGE_IMAGE.displayName=XXLarge: 200MB+",
|
||||
"FileSearchData.FileSize.XLARGE_IMAGE.displayName=XLarge: 50-200MB",
|
||||
"FileSearchData.FileSize.LARGE_IMAGE.displayName=Large: 1-50MB",
|
||||
"FileSearchData.FileSize.MEDIUM_IMAGE.displayName=Medium: 100KB-1MB",
|
||||
"FileSearchData.FileSize.SMALL_IMAGE.displayName=Small: 16-100KB",
|
||||
"FileSearchData.FileSize.XSMALL_IMAGE.displayName=XSmall: 0-16KB",
|
||||
"FileSearchData.FileSize.XXLARGE_VIDEO.displayName=XXLarge: 10GB+",
|
||||
"FileSearchData.FileSize.XLARGE_VIDEO.displayName=XLarge: 5-10GB",
|
||||
"FileSearchData.FileSize.LARGE_VIDEO.displayName=Large: 1-5GB",
|
||||
"FileSearchData.FileSize.MEDIUM_VIDEO.displayName=Medium: 100MB-1GB",
|
||||
"FileSearchData.FileSize.SMALL_VIDEO.displayName=Small: 500KB-100MB",
|
||||
"FileSearchData.FileSize.XSMALL_VIDEO.displayName=XSmall: 0-500KB",})
|
||||
"FileSearchData.FileSize.XXLARGE.displayName=XXLarge",
|
||||
"FileSearchData.FileSize.XLARGE.displayName=XLarge",
|
||||
"FileSearchData.FileSize.LARGE.displayName=Large",
|
||||
"FileSearchData.FileSize.MEDIUM.displayName=Medium",
|
||||
"FileSearchData.FileSize.SMALL.displayName=Small",
|
||||
"FileSearchData.FileSize.XSMALL.displayName=XSmall",
|
||||
"FileSearchData.FileSize.10PlusGb=: 10GB+",
|
||||
"FileSearchData.FileSize.5gbto10gb=: 5-10GB",
|
||||
"FileSearchData.FileSize.1gbto5gb=: 1-5GB",
|
||||
"FileSearchData.FileSize.100mbto1gb=: 100MB-1GB",
|
||||
"FileSearchData.FileSize.200PlusMb=: 200MB+",
|
||||
"FileSearchData.FileSize.50mbto200mb=: 50-200MB",
|
||||
"FileSearchData.FileSize.500kbto100mb=: 500KB-100MB",
|
||||
"FileSearchData.FileSize.1mbto50mb=: 1-50MB",
|
||||
"FileSearchData.FileSize.100kbto1mb=: 100KB-1MB",
|
||||
"FileSearchData.FileSize.16kbto100kb=: 16-100KB",
|
||||
"FileSearchData.FileSize.upTo500kb=: 0-500KB",
|
||||
"FileSearchData.FileSize.upTo16kb=: 0-16KB",})
|
||||
enum FileSize {
|
||||
XXLARGE_VIDEO(0, 10000 * BYTES_PER_MB, -1, Bundle.FileSearchData_FileSize_XXLARGE_VIDEO_displayName()),
|
||||
XLARGE_VIDEO(1, 5000 * BYTES_PER_MB, 10000 * BYTES_PER_MB, Bundle.FileSearchData_FileSize_XLARGE_VIDEO_displayName()),
|
||||
LARGE_VIDEO(2, 1000 * BYTES_PER_MB, 5000 * BYTES_PER_MB, Bundle.FileSearchData_FileSize_LARGE_VIDEO_displayName()),
|
||||
MEDIUM_VIDEO(3, 100 * BYTES_PER_MB, 1000 * BYTES_PER_MB, Bundle.FileSearchData_FileSize_MEDIUM_VIDEO_displayName()),
|
||||
SMALL_VIDEO(4, 500000, 100 * BYTES_PER_MB, Bundle.FileSearchData_FileSize_SMALL_VIDEO_displayName()),
|
||||
XSMALL_VIDEO(5, 0, 500000, Bundle.FileSearchData_FileSize_XSMALL_VIDEO_displayName()),
|
||||
XXLARGE_IMAGE(6, 200 * BYTES_PER_MB, -1, Bundle.FileSearchData_FileSize_XXLARGE_IMAGE_displayName()),
|
||||
XLARGE_IMAGE(7, 50 * BYTES_PER_MB, 200 * BYTES_PER_MB, Bundle.FileSearchData_FileSize_XLARGE_IMAGE_displayName()),
|
||||
LARGE_IMAGE(8, 1 * BYTES_PER_MB, 50 * BYTES_PER_MB, Bundle.FileSearchData_FileSize_LARGE_IMAGE_displayName()),
|
||||
MEDIUM_IMAGE(9, 100000, 1 * BYTES_PER_MB, Bundle.FileSearchData_FileSize_MEDIUM_IMAGE_displayName()),
|
||||
SMALL_IMAGE(10, 16000, 100000, Bundle.FileSearchData_FileSize_SMALL_IMAGE_displayName()),
|
||||
XSMALL_IMAGE(11, 0, 16000, Bundle.FileSearchData_FileSize_XSMALL_IMAGE_displayName());
|
||||
XXLARGE_VIDEO(0, 10000 * BYTES_PER_MB, -1, Bundle.FileSearchData_FileSize_XXLARGE_displayName(), Bundle.FileSearchData_FileSize_10PlusGb()),
|
||||
XLARGE_VIDEO(1, 5000 * BYTES_PER_MB, 10000 * BYTES_PER_MB, Bundle.FileSearchData_FileSize_XLARGE_displayName(), Bundle.FileSearchData_FileSize_5gbto10gb()),
|
||||
LARGE_VIDEO(2, 1000 * BYTES_PER_MB, 5000 * BYTES_PER_MB, Bundle.FileSearchData_FileSize_LARGE_displayName(), Bundle.FileSearchData_FileSize_1gbto5gb()),
|
||||
MEDIUM_VIDEO(3, 100 * BYTES_PER_MB, 1000 * BYTES_PER_MB, Bundle.FileSearchData_FileSize_MEDIUM_displayName(), Bundle.FileSearchData_FileSize_100mbto1gb()),
|
||||
SMALL_VIDEO(4, 500000, 100 * BYTES_PER_MB, Bundle.FileSearchData_FileSize_SMALL_displayName(), Bundle.FileSearchData_FileSize_500kbto100mb()),
|
||||
XSMALL_VIDEO(5, 0, 500000, Bundle.FileSearchData_FileSize_XSMALL_displayName(), Bundle.FileSearchData_FileSize_upTo500kb()),
|
||||
XXLARGE_IMAGE(6, 200 * BYTES_PER_MB, -1, Bundle.FileSearchData_FileSize_XXLARGE_displayName(), Bundle.FileSearchData_FileSize_200PlusMb()),
|
||||
XLARGE_IMAGE(7, 50 * BYTES_PER_MB, 200 * BYTES_PER_MB, Bundle.FileSearchData_FileSize_XLARGE_displayName(), Bundle.FileSearchData_FileSize_50mbto200mb()),
|
||||
LARGE_IMAGE(8, 1 * BYTES_PER_MB, 50 * BYTES_PER_MB, Bundle.FileSearchData_FileSize_LARGE_displayName(), Bundle.FileSearchData_FileSize_1mbto50mb()),
|
||||
MEDIUM_IMAGE(9, 100000, 1 * BYTES_PER_MB, Bundle.FileSearchData_FileSize_MEDIUM_displayName(), Bundle.FileSearchData_FileSize_100kbto1mb()),
|
||||
SMALL_IMAGE(10, 16000, 100000, Bundle.FileSearchData_FileSize_SMALL_displayName(), Bundle.FileSearchData_FileSize_16kbto100kb()),
|
||||
XSMALL_IMAGE(11, 0, 16000, Bundle.FileSearchData_FileSize_XSMALL_displayName(), Bundle.FileSearchData_FileSize_upTo16kb());
|
||||
|
||||
private final int ranking; // Must be unique for each value
|
||||
private final long minBytes; // Note that the size must be strictly greater than this to match
|
||||
private final long maxBytes;
|
||||
private final String displayName;
|
||||
private final String sizeGroup;
|
||||
private final String displaySize;
|
||||
final static long NO_MAXIMUM = -1;
|
||||
|
||||
FileSize(int ranking, long minB, long maxB, String displayName) {
|
||||
FileSize(int ranking, long minB, long maxB, String displayName, String displaySize) {
|
||||
this.ranking = ranking;
|
||||
this.minBytes = minB;
|
||||
if (maxB >= 0) {
|
||||
@ -166,7 +173,8 @@ final class FileSearchData {
|
||||
} else {
|
||||
this.maxBytes = NO_MAXIMUM;
|
||||
}
|
||||
this.displayName = displayName;
|
||||
this.sizeGroup = displayName;
|
||||
this.displaySize = displaySize;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -246,7 +254,11 @@ final class FileSearchData {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return displayName;
|
||||
return sizeGroup + displaySize;
|
||||
}
|
||||
|
||||
String getSizeGroup(){
|
||||
return sizeGroup;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -207,11 +207,8 @@ class FileSearchFiltering {
|
||||
|
||||
@NbBundle.Messages({
|
||||
"# {0} - filters",
|
||||
"FileSearchFiltering.SizeFilter.desc=Files with size in range(s): {0}",
|
||||
"FileSearchFiltering.SizeFilter.or= or ",
|
||||
"# {0} - Minimum bytes",
|
||||
"# {1} - Maximum bytes",
|
||||
"FileSearchFiltering.SizeFilter.range=({0} to {1})",})
|
||||
"FileSearchFiltering.SizeFilter.desc=Size(s): {0}",
|
||||
"FileSearchFiltering.SizeFilter.or=, "})
|
||||
@Override
|
||||
String getDesc() {
|
||||
String desc = ""; // NON-NLS
|
||||
@ -219,7 +216,7 @@ class FileSearchFiltering {
|
||||
if (!desc.isEmpty()) {
|
||||
desc += Bundle.FileSearchFiltering_SizeFilter_or();
|
||||
}
|
||||
desc += Bundle.FileSearchFiltering_SizeFilter_range(size.getMinBytes(), size.getMaxBytes());
|
||||
desc += size.getSizeGroup();
|
||||
}
|
||||
desc = Bundle.FileSearchFiltering_SizeFilter_desc(desc);
|
||||
return desc;
|
||||
@ -364,10 +361,12 @@ class FileSearchFiltering {
|
||||
|
||||
@NbBundle.Messages({
|
||||
"# {0} - filters",
|
||||
"FileSearchFiltering.ParentFilter.desc=Files with paths matching: {0}",
|
||||
"FileSearchFiltering.ParentFilter.or= or ",
|
||||
"FileSearchFiltering.ParentFilter.desc=Paths matching: {0}",
|
||||
"FileSearchFiltering.ParentFilter.or=, ",
|
||||
"FileSearchFiltering.ParentFilter.exact=(exact match)",
|
||||
"FileSearchFiltering.ParentFilter.substring=(substring)",})
|
||||
"FileSearchFiltering.ParentFilter.substring=(substring)",
|
||||
"FileSearchFiltering.ParentFilter.included=(included)",
|
||||
"FileSearchFiltering.ParentFilter.excluded=(excluded)"})
|
||||
@Override
|
||||
String getDesc() {
|
||||
String desc = ""; // NON-NLS
|
||||
@ -380,6 +379,11 @@ class FileSearchFiltering {
|
||||
} else {
|
||||
desc += searchTerm.getSearchStr() + Bundle.FileSearchFiltering_ParentFilter_substring();
|
||||
}
|
||||
if (searchTerm.isIncluded()) {
|
||||
desc += Bundle.FileSearchFiltering_ParentFilter_included();
|
||||
} else {
|
||||
desc += Bundle.FileSearchFiltering_ParentFilter_excluded();
|
||||
}
|
||||
}
|
||||
desc = Bundle.FileSearchFiltering_ParentFilter_desc(desc);
|
||||
return desc;
|
||||
@ -417,8 +421,8 @@ class FileSearchFiltering {
|
||||
|
||||
@NbBundle.Messages({
|
||||
"# {0} - filters",
|
||||
"FileSearchFiltering.DataSourceFilter.desc=Files in data source(s): {0}",
|
||||
"FileSearchFiltering.DataSourceFilter.or= or ",
|
||||
"FileSearchFiltering.DataSourceFilter.desc=Data source(s): {0}",
|
||||
"FileSearchFiltering.DataSourceFilter.or=, ",
|
||||
"# {0} - Data source name",
|
||||
"# {1} - Data source ID",
|
||||
"FileSearchFiltering.DataSourceFilter.datasource={0}({1})",})
|
||||
@ -466,7 +470,7 @@ class FileSearchFiltering {
|
||||
|
||||
@NbBundle.Messages({
|
||||
"# {0} - filters",
|
||||
"FileSearchFiltering.KeywordListFilter.desc=Files with keywords in list(s): {0}",})
|
||||
"FileSearchFiltering.KeywordListFilter.desc=Keywords in list(s): {0}",})
|
||||
@Override
|
||||
String getDesc() {
|
||||
return Bundle.FileSearchFiltering_KeywordListFilter_desc(concatenateSetNamesForDisplay(listNames));
|
||||
@ -516,8 +520,8 @@ class FileSearchFiltering {
|
||||
|
||||
@NbBundle.Messages({
|
||||
"# {0} - filters",
|
||||
"FileSearchFiltering.FileTypeFilter.desc=Files with type: {0}",
|
||||
"FileSearchFiltering.FileTypeFilter.or= or ",})
|
||||
"FileSearchFiltering.FileTypeFilter.desc=Type: {0}",
|
||||
"FileSearchFiltering.FileTypeFilter.or=, ",})
|
||||
@Override
|
||||
String getDesc() {
|
||||
String desc = "";
|
||||
@ -586,8 +590,8 @@ class FileSearchFiltering {
|
||||
|
||||
@NbBundle.Messages({
|
||||
"# {0} - filters",
|
||||
"FileSearchFiltering.FrequencyFilter.desc=Files with frequency: {0}",
|
||||
"FileSearchFiltering.FrequencyFilter.or= or ",})
|
||||
"FileSearchFiltering.FrequencyFilter.desc=Past occurrences: {0}",
|
||||
"FileSearchFiltering.FrequencyFilter.or=, ",})
|
||||
@Override
|
||||
String getDesc() {
|
||||
String desc = ""; // NON-NLS
|
||||
@ -595,7 +599,7 @@ class FileSearchFiltering {
|
||||
if (!desc.isEmpty()) {
|
||||
desc += Bundle.FileSearchFiltering_FrequencyFilter_or();
|
||||
}
|
||||
desc += freq.name();
|
||||
desc += freq.toString();
|
||||
}
|
||||
return Bundle.FileSearchFiltering_FrequencyFilter_desc(desc);
|
||||
}
|
||||
@ -632,7 +636,7 @@ class FileSearchFiltering {
|
||||
|
||||
@NbBundle.Messages({
|
||||
"# {0} - filters",
|
||||
"FileSearchFiltering.HashSetFilter.desc=Files with hash set hits in set(s): {0}",})
|
||||
"FileSearchFiltering.HashSetFilter.desc=Hash set hits in set(s): {0}",})
|
||||
@Override
|
||||
String getDesc() {
|
||||
return Bundle.FileSearchFiltering_HashSetFilter_desc(concatenateSetNamesForDisplay(setNames));
|
||||
@ -670,7 +674,7 @@ class FileSearchFiltering {
|
||||
|
||||
@NbBundle.Messages({
|
||||
"# {0} - filters",
|
||||
"FileSearchFiltering.InterestingItemSetFilter.desc=Files with interesting item hits in set(s): {0}",})
|
||||
"FileSearchFiltering.InterestingItemSetFilter.desc=Interesting item hits in set(s): {0}",})
|
||||
@Override
|
||||
String getDesc() {
|
||||
return Bundle.FileSearchFiltering_InterestingItemSetFilter_desc(concatenateSetNamesForDisplay(setNames));
|
||||
@ -708,7 +712,7 @@ class FileSearchFiltering {
|
||||
|
||||
@NbBundle.Messages({
|
||||
"# {0} - filters",
|
||||
"FileSearchFiltering.ObjectDetectionFilter.desc=Files with objects detected in set(s): {0}",})
|
||||
"FileSearchFiltering.ObjectDetectionFilter.desc=Objects detected in set(s): {0}",})
|
||||
@Override
|
||||
String getDesc() {
|
||||
return Bundle.FileSearchFiltering_ObjectDetectionFilter_desc(concatenateSetNamesForDisplay(typeNames));
|
||||
@ -784,7 +788,7 @@ class FileSearchFiltering {
|
||||
|
||||
@NbBundle.Messages({
|
||||
"# {0} - filters",
|
||||
"FileSearchFiltering.ScoreFilter.desc=Files with score(s) of : {0}",})
|
||||
"FileSearchFiltering.ScoreFilter.desc=Score(s) of : {0}",})
|
||||
@Override
|
||||
String getDesc() {
|
||||
return Bundle.FileSearchFiltering_ScoreFilter_desc(
|
||||
@ -826,8 +830,8 @@ class FileSearchFiltering {
|
||||
|
||||
@NbBundle.Messages({
|
||||
"# {0} - tag names",
|
||||
"FileSearchFiltering.TagsFilter.desc=Files that have been tagged {0}",
|
||||
"FileSearchFiltering.TagsFilter.or= or ",})
|
||||
"FileSearchFiltering.TagsFilter.desc=Tagged {0}",
|
||||
"FileSearchFiltering.TagsFilter.or=, ",})
|
||||
@Override
|
||||
String getDesc() {
|
||||
String desc = ""; // NON-NLS
|
||||
@ -862,7 +866,7 @@ class FileSearchFiltering {
|
||||
}
|
||||
|
||||
@NbBundle.Messages({
|
||||
"FileSearchFiltering.UserCreatedFilter.desc=Files that contain EXIF data",})
|
||||
"FileSearchFiltering.UserCreatedFilter.desc=that contain EXIF data",})
|
||||
@Override
|
||||
String getDesc() {
|
||||
return Bundle.FileSearchFiltering_UserCreatedFilter_desc();
|
||||
@ -931,7 +935,7 @@ class FileSearchFiltering {
|
||||
}
|
||||
|
||||
@NbBundle.Messages({
|
||||
"FileSearchFiltering.PreviouslyNotableFilter.desc=Files that were previously marked as notable",})
|
||||
"FileSearchFiltering.PreviouslyNotableFilter.desc=that were previously marked as notable",})
|
||||
@Override
|
||||
String getDesc() {
|
||||
return Bundle.FileSearchFiltering_PreviouslyNotableFilter_desc();
|
||||
@ -949,7 +953,7 @@ class FileSearchFiltering {
|
||||
}
|
||||
|
||||
@NbBundle.Messages({
|
||||
"FileSearchFiltering.KnownFilter.desc=Files which are not known"})
|
||||
"FileSearchFiltering.KnownFilter.desc=which are not known"})
|
||||
@Override
|
||||
String getDesc() {
|
||||
return Bundle.FileSearchFiltering_KnownFilter_desc();
|
||||
|
@ -37,6 +37,18 @@
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.ButtonGroup" name="includeButtonGroup">
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="javax.swing.ButtonGroup" name="pathTypeButtonGroup">
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
</NonVisualComponents>
|
||||
<Properties>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
@ -143,6 +155,9 @@
|
||||
</Container>
|
||||
<Component class="javax.swing.JRadioButton" name="fullRadioButton">
|
||||
<Properties>
|
||||
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
|
||||
<ComponentRef name="pathTypeButtonGroup"/>
|
||||
</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/discovery/Bundle.properties" key="ParentFolderFilterPanel.fullRadioButton.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
@ -152,6 +167,9 @@
|
||||
</Component>
|
||||
<Component class="javax.swing.JRadioButton" name="includeRadioButton">
|
||||
<Properties>
|
||||
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
|
||||
<ComponentRef name="includeButtonGroup"/>
|
||||
</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/discovery/Bundle.properties" key="ParentFolderFilterPanel.includeRadioButton.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
@ -161,6 +179,9 @@
|
||||
</Component>
|
||||
<Component class="javax.swing.JRadioButton" name="substringRadioButton">
|
||||
<Properties>
|
||||
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
|
||||
<ComponentRef name="pathTypeButtonGroup"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/discovery/Bundle.properties" key="ParentFolderFilterPanel.substringRadioButton.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
@ -169,6 +190,9 @@
|
||||
</Component>
|
||||
<Component class="javax.swing.JRadioButton" name="excludeRadioButton">
|
||||
<Properties>
|
||||
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
|
||||
<ComponentRef name="includeButtonGroup"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/discovery/Bundle.properties" key="ParentFolderFilterPanel.excludeRadioButton.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
|
@ -66,6 +66,8 @@ final class ParentFolderFilterPanel extends AbstractDiscoveryFilterPanel {
|
||||
|
||||
parentCheckbox = new javax.swing.JCheckBox();
|
||||
parentLabel = new javax.swing.JLabel();
|
||||
javax.swing.ButtonGroup includeButtonGroup = new javax.swing.ButtonGroup();
|
||||
javax.swing.ButtonGroup pathTypeButtonGroup = new javax.swing.ButtonGroup();
|
||||
parentScrollPane = new javax.swing.JScrollPane();
|
||||
parentList = new javax.swing.JList<>();
|
||||
fullRadioButton = new javax.swing.JRadioButton();
|
||||
@ -106,17 +108,21 @@ final class ParentFolderFilterPanel extends AbstractDiscoveryFilterPanel {
|
||||
});
|
||||
parentScrollPane.setViewportView(parentList);
|
||||
|
||||
pathTypeButtonGroup.add(fullRadioButton);
|
||||
fullRadioButton.setSelected(true);
|
||||
org.openide.awt.Mnemonics.setLocalizedText(fullRadioButton, org.openide.util.NbBundle.getMessage(ParentFolderFilterPanel.class, "ParentFolderFilterPanel.fullRadioButton.text_1")); // NOI18N
|
||||
fullRadioButton.setEnabled(false);
|
||||
|
||||
includeButtonGroup.add(includeRadioButton);
|
||||
includeRadioButton.setSelected(true);
|
||||
org.openide.awt.Mnemonics.setLocalizedText(includeRadioButton, org.openide.util.NbBundle.getMessage(ParentFolderFilterPanel.class, "ParentFolderFilterPanel.includeRadioButton.text_1")); // NOI18N
|
||||
includeRadioButton.setEnabled(false);
|
||||
|
||||
pathTypeButtonGroup.add(substringRadioButton);
|
||||
org.openide.awt.Mnemonics.setLocalizedText(substringRadioButton, org.openide.util.NbBundle.getMessage(ParentFolderFilterPanel.class, "ParentFolderFilterPanel.substringRadioButton.text_1")); // NOI18N
|
||||
substringRadioButton.setEnabled(false);
|
||||
|
||||
includeButtonGroup.add(excludeRadioButton);
|
||||
org.openide.awt.Mnemonics.setLocalizedText(excludeRadioButton, org.openide.util.NbBundle.getMessage(ParentFolderFilterPanel.class, "ParentFolderFilterPanel.excludeRadioButton.text_1")); // NOI18N
|
||||
excludeRadioButton.setEnabled(false);
|
||||
|
||||
@ -188,7 +194,7 @@ final class ParentFolderFilterPanel extends AbstractDiscoveryFilterPanel {
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
private void parentCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_parentCheckboxActionPerformed
|
||||
// parentFilterSettings(true, true, parentCheckbox.isSelected(), null);
|
||||
configurePanel(parentCheckbox.isSelected(), null);
|
||||
}//GEN-LAST:event_parentCheckboxActionPerformed
|
||||
|
||||
private void parentListValueChanged(javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_parentListValueChanged
|
||||
@ -235,6 +241,7 @@ final class ParentFolderFilterPanel extends AbstractDiscoveryFilterPanel {
|
||||
parentCheckbox.setSelected(selected);
|
||||
if (parentCheckbox.isEnabled() && parentCheckbox.isSelected()) {
|
||||
parentScrollPane.setEnabled(true);
|
||||
parentLabel.setEnabled(true);
|
||||
includeRadioButton.setEnabled(true);
|
||||
excludeRadioButton.setEnabled(true);
|
||||
fullRadioButton.setEnabled(true);
|
||||
@ -248,6 +255,7 @@ final class ParentFolderFilterPanel extends AbstractDiscoveryFilterPanel {
|
||||
}
|
||||
} else {
|
||||
parentScrollPane.setEnabled(false);
|
||||
parentLabel.setEnabled(false);
|
||||
parentList.setEnabled(false);
|
||||
includeRadioButton.setEnabled(false);
|
||||
excludeRadioButton.setEnabled(false);
|
||||
|
@ -0,0 +1,141 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||
<Properties>
|
||||
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="aa" green="aa" red="aa" type="rgb"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<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" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="detailsLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace pref="251" max="32767" attributes="0"/>
|
||||
<Component id="showButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="hideButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="filler2" alignment="1" max="32767" attributes="0"/>
|
||||
<Component id="filler1" alignment="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<Component id="filler2" max="32767" attributes="0"/>
|
||||
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||
<Component id="hideButton" max="32767" attributes="0"/>
|
||||
<Component id="showButton" max="32767" attributes="0"/>
|
||||
<Component id="detailsLabel" alignment="0" min="-2" pref="25" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
||||
<Component id="filler1" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="detailsLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/discovery/Bundle.properties" key="ResultsSplitPaneDivider.detailsLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="focusable" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="hideButton">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/discovery/arrow-down.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/discovery/Bundle.properties" key="ResultsSplitPaneDivider.hideButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="null"/>
|
||||
</Property>
|
||||
<Property name="focusable" type="boolean" value="false"/>
|
||||
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
|
||||
<Insets value="[0, 0, 0, 0]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="hideButtonActionPerformed"/>
|
||||
</Events>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="hideButton.setCursor(Cursor.getDefaultCursor());"/>
|
||||
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="showButton">
|
||||
<Properties>
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/discovery/arrow-up.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/discovery/Bundle.properties" key="ResultsSplitPaneDivider.showButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="null"/>
|
||||
</Property>
|
||||
<Property name="focusable" type="boolean" value="false"/>
|
||||
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
|
||||
<Insets value="[0, 0, 0, 0]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="showButtonActionPerformed"/>
|
||||
</Events>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="showButton.setCursor(Cursor.getDefaultCursor());"/>
|
||||
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
<Component class="javax.swing.Box$Filler" name="filler1">
|
||||
<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>
|
||||
</Component>
|
||||
<Component class="javax.swing.Box$Filler" name="filler2">
|
||||
<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>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Autopsy
|
||||
*
|
||||
* 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.discovery;
|
||||
|
||||
import java.awt.Cursor;
|
||||
|
||||
/**
|
||||
* Panel for separating the results list from the details area.
|
||||
*/
|
||||
final class ResultsSplitPaneDivider extends javax.swing.JPanel {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Creates new form LabeledSplitPaneDivider.
|
||||
*/
|
||||
ResultsSplitPaneDivider() {
|
||||
initComponents();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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() {
|
||||
|
||||
javax.swing.JLabel detailsLabel = new javax.swing.JLabel();
|
||||
javax.swing.JButton hideButton = new javax.swing.JButton();
|
||||
javax.swing.JButton showButton = new javax.swing.JButton();
|
||||
javax.swing.Box.Filler filler1 = 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 filler2 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 32767));
|
||||
|
||||
setBackground(new java.awt.Color(170, 170, 170));
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(detailsLabel, org.openide.util.NbBundle.getMessage(ResultsSplitPaneDivider.class, "ResultsSplitPaneDivider.detailsLabel.text")); // NOI18N
|
||||
detailsLabel.setFocusable(false);
|
||||
|
||||
hideButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/discovery/arrow-down.png"))); // NOI18N
|
||||
org.openide.awt.Mnemonics.setLocalizedText(hideButton, org.openide.util.NbBundle.getMessage(ResultsSplitPaneDivider.class, "ResultsSplitPaneDivider.hideButton.text")); // NOI18N
|
||||
hideButton.setBorder(null);
|
||||
hideButton.setFocusable(false);
|
||||
hideButton.setMargin(new java.awt.Insets(0, 0, 0, 0));
|
||||
hideButton.setCursor(Cursor.getDefaultCursor());
|
||||
hideButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
hideButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
showButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/discovery/arrow-up.png"))); // NOI18N
|
||||
org.openide.awt.Mnemonics.setLocalizedText(showButton, org.openide.util.NbBundle.getMessage(ResultsSplitPaneDivider.class, "ResultsSplitPaneDivider.showButton.text")); // NOI18N
|
||||
showButton.setBorder(null);
|
||||
showButton.setFocusable(false);
|
||||
showButton.setMargin(new java.awt.Insets(0, 0, 0, 0));
|
||||
showButton.setCursor(Cursor.getDefaultCursor());
|
||||
showButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
showButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(detailsLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 251, Short.MAX_VALUE)
|
||||
.addComponent(showButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(hideButton)
|
||||
.addContainerGap())
|
||||
.addComponent(filler2, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(filler1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||
.addComponent(filler2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGap(0, 0, 0)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
|
||||
.addComponent(hideButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(showButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(detailsLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addGap(0, 0, 0)
|
||||
.addComponent(filler1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
private void showButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_showButtonActionPerformed
|
||||
DiscoveryEventUtils.getDiscoveryEventBus().post(new DiscoveryEventUtils.DetailsVisibleEvent(true));
|
||||
}//GEN-LAST:event_showButtonActionPerformed
|
||||
|
||||
private void hideButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_hideButtonActionPerformed
|
||||
DiscoveryEventUtils.getDiscoveryEventBus().post(new DiscoveryEventUtils.DetailsVisibleEvent(false));
|
||||
}//GEN-LAST:event_hideButtonActionPerformed
|
||||
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
// End of variables declaration//GEN-END:variables
|
||||
}
|
@ -11,12 +11,17 @@
|
||||
<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,0,73,0,0,1,24"/>
|
||||
<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,0,102,0,0,1,56"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JScrollPane" name="videoFiltersScrollPane">
|
||||
<Properties>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[312, 102]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||
@ -32,7 +37,7 @@
|
||||
<Container class="javax.swing.JPanel" name="videoFiltersPanel">
|
||||
<Properties>
|
||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[223, 66]"/>
|
||||
<Dimension value="[310, 100]"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
@ -45,7 +50,7 @@
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" pref="8" max="-2" attributes="0"/>
|
||||
<Component id="videoFiltersSplitPane" max="32767" attributes="0"/>
|
||||
<Component id="videoFiltersSplitPane" pref="294" max="32767" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="8" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
@ -54,7 +59,7 @@
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" pref="8" max="-2" attributes="0"/>
|
||||
<Component id="videoFiltersSplitPane" max="32767" attributes="0"/>
|
||||
<Component id="videoFiltersSplitPane" pref="84" max="32767" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="8" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
|
@ -66,7 +66,9 @@ final class VideoFilterPanel extends AbstractFiltersPanel {
|
||||
|
||||
setLayout(new java.awt.BorderLayout());
|
||||
|
||||
videoFiltersPanel.setPreferredSize(new java.awt.Dimension(223, 66));
|
||||
videoFiltersScrollPane.setPreferredSize(new java.awt.Dimension(312, 102));
|
||||
|
||||
videoFiltersPanel.setPreferredSize(new java.awt.Dimension(310, 100));
|
||||
|
||||
videoFiltersSplitPane.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(VideoFilterPanel.class, "VideoFilterPanel.videoFiltersSplitPane.border.title"))); // NOI18N
|
||||
videoFiltersSplitPane.setResizeWeight(0.5);
|
||||
@ -77,14 +79,14 @@ final class VideoFilterPanel extends AbstractFiltersPanel {
|
||||
videoFiltersPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(videoFiltersPanelLayout.createSequentialGroup()
|
||||
.addGap(8, 8, 8)
|
||||
.addComponent(videoFiltersSplitPane)
|
||||
.addComponent(videoFiltersSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 294, Short.MAX_VALUE)
|
||||
.addGap(8, 8, 8))
|
||||
);
|
||||
videoFiltersPanelLayout.setVerticalGroup(
|
||||
videoFiltersPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(videoFiltersPanelLayout.createSequentialGroup()
|
||||
.addGap(8, 8, 8)
|
||||
.addComponent(videoFiltersSplitPane)
|
||||
.addComponent(videoFiltersSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 84, Short.MAX_VALUE)
|
||||
.addGap(8, 8, 8))
|
||||
);
|
||||
|
||||
|
BIN
Core/src/org/sleuthkit/autopsy/discovery/arrow-down.png
Normal file
BIN
Core/src/org/sleuthkit/autopsy/discovery/arrow-down.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.1 KiB |
BIN
Core/src/org/sleuthkit/autopsy/discovery/arrow-up.png
Normal file
BIN
Core/src/org/sleuthkit/autopsy/discovery/arrow-up.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.1 KiB |
@ -1388,7 +1388,8 @@ class ExtractRegistry extends Extract {
|
||||
line = reader.readLine();
|
||||
// Columns are
|
||||
// FileX -> <file>
|
||||
while (!line.contains(SECTION_DIVIDER) && !line.isEmpty() && !line.contains("Applets")) {
|
||||
while (!line.contains(SECTION_DIVIDER) && !line.isEmpty() && !line.contains("Applets")
|
||||
&& !line.contains(("Recent File List"))) {
|
||||
// Split line on "> " which is the record delimiter between position and file
|
||||
String tokens[] = line.split("> ");
|
||||
String fileName = tokens[1];
|
||||
|
73
thirdparty/rr/plugins/arunmru.pl
vendored
73
thirdparty/rr/plugins/arunmru.pl
vendored
@ -36,43 +36,44 @@ sub pluginmain {
|
||||
my $class = shift;
|
||||
my $ntuser = shift;
|
||||
#::logMsg("autospyrunmru");
|
||||
my $reg = Parse::Win32Registry->new($ntuser);
|
||||
my $root_key = $reg->get_root_key;
|
||||
if (defined(Parse::Win32Registry->new($ntuser))) {
|
||||
my $reg = Parse::Win32Registry->new($ntuser);
|
||||
my $root_key = $reg->get_root_key;
|
||||
|
||||
my $key_path = 'Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RunMRU';
|
||||
my $key;
|
||||
if ($key = $root_key->get_subkey($key_path)) {
|
||||
#::rptMsg("RunMru");
|
||||
#::rptMsg($key_path);
|
||||
|
||||
my @vals = $key->get_list_of_values();
|
||||
::rptMsg("<runMRU>");
|
||||
::rptMsg("<mtime>".gmtime($key->get_timestamp())."</mtime>");
|
||||
::rptMsg("<artifacts>");
|
||||
my %runvals;
|
||||
my $mru;
|
||||
if (scalar(@vals) > 0) {
|
||||
foreach my $v (@vals) {
|
||||
$runvals{$v->get_name()} = $v->get_data() unless ($v->get_name() =~ m/^MRUList/i);
|
||||
$mru = $v->get_data() if ($v->get_name() =~ m/^MRUList/i);
|
||||
}
|
||||
::rptMsg("<MRUList>".$mru."</MRUList>");
|
||||
foreach my $r (sort keys %runvals) {
|
||||
::rptMsg("<MRU>".$r." ".$runvals{$r}."</MRU>");
|
||||
}
|
||||
}
|
||||
else {
|
||||
#::rptMsg($key_path." has no values.");
|
||||
#::logMsg($key_path." has no values.");
|
||||
}
|
||||
::rptMsg("</artifacts>");
|
||||
::rptMsg("</runMRU>");
|
||||
}
|
||||
else {
|
||||
#::rptMsg($key_path." not found.");
|
||||
#::logMsg($key_path." not found.");
|
||||
}
|
||||
|
||||
my $key_path = 'Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RunMRU';
|
||||
my $key;
|
||||
if ($key = $root_key->get_subkey($key_path)) {
|
||||
#::rptMsg("RunMru");
|
||||
#::rptMsg($key_path);
|
||||
|
||||
my @vals = $key->get_list_of_values();
|
||||
::rptMsg("<runMRU>");
|
||||
::rptMsg("<mtime>".gmtime($key->get_timestamp())."</mtime>");
|
||||
::rptMsg("<artifacts>");
|
||||
my %runvals;
|
||||
my $mru;
|
||||
if (scalar(@vals) > 0) {
|
||||
foreach my $v (@vals) {
|
||||
$runvals{$v->get_name()} = $v->get_data() unless ($v->get_name() =~ m/^MRUList/i);
|
||||
$mru = $v->get_data() if ($v->get_name() =~ m/^MRUList/i);
|
||||
}
|
||||
::rptMsg("<MRUList>".$mru."</MRUList>");
|
||||
foreach my $r (sort keys %runvals) {
|
||||
::rptMsg("<MRU>".$r." ".$runvals{$r}."</MRU>");
|
||||
}
|
||||
}
|
||||
else {
|
||||
#::rptMsg($key_path." has no values.");
|
||||
#::logMsg($key_path." has no values.");
|
||||
}
|
||||
::rptMsg("</artifacts>");
|
||||
::rptMsg("</runMRU>");
|
||||
}
|
||||
else {
|
||||
#::rptMsg($key_path." not found.");
|
||||
#::logMsg($key_path." not found.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
62
thirdparty/rr/plugins/autopsylogin.pl
vendored
62
thirdparty/rr/plugins/autopsylogin.pl
vendored
@ -35,36 +35,38 @@ sub pluginmain {
|
||||
my $class = shift;
|
||||
my $ntuser = shift;
|
||||
#::logMsg("||logonusername||");
|
||||
my $reg = Parse::Win32Registry->new($ntuser);
|
||||
my $root_key = $reg->get_root_key;
|
||||
|
||||
my $logon_name = "Username";
|
||||
|
||||
my $key_path = 'Software\\Microsoft\\Windows\\CurrentVersion\\Explorer';
|
||||
my $key;
|
||||
if ($key = $root_key->get_subkey($key_path)) {
|
||||
my @vals = $key->get_list_of_values();
|
||||
if (scalar(@vals) > 0) {
|
||||
#::rptMsg("Logon User Name");
|
||||
#::rptMsg($key_path);
|
||||
::rptMsg("<logon>");
|
||||
::rptMsg("<mtime>".gmtime($key->get_timestamp())."</mtime><artifacts>");
|
||||
foreach my $v (@vals) {
|
||||
if ($v->get_name() eq $logon_name) {
|
||||
::rptMsg("<user name=\"".$logon_name."\"> ".$v->get_data() ."</user>");
|
||||
}
|
||||
}
|
||||
::rptMsg("</artifacts></logon>");
|
||||
}
|
||||
else {
|
||||
#::rptMsg($key_path." has no values.");
|
||||
#::logMsg($key_path." has no values.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
#::rptMsg($key_path." not found.");
|
||||
#::logMsg($key_path." not found.");
|
||||
}
|
||||
if (defined(Parse::Win32Registry->new($ntuser))) {
|
||||
my $reg = Parse::Win32Registry->new($ntuser);
|
||||
my $root_key = $reg->get_root_key;
|
||||
|
||||
my $logon_name = "Username";
|
||||
|
||||
my $key_path = 'Software\\Microsoft\\Windows\\CurrentVersion\\Explorer';
|
||||
my $key;
|
||||
if ($key = $root_key->get_subkey($key_path)) {
|
||||
my @vals = $key->get_list_of_values();
|
||||
if (scalar(@vals) > 0) {
|
||||
#::rptMsg("Logon User Name");
|
||||
#::rptMsg($key_path);
|
||||
::rptMsg("<logon>");
|
||||
::rptMsg("<mtime>".gmtime($key->get_timestamp())."</mtime><artifacts>");
|
||||
foreach my $v (@vals) {
|
||||
if ($v->get_name() eq $logon_name) {
|
||||
::rptMsg("<user name=\"".$logon_name."\"> ".$v->get_data() ."</user>");
|
||||
}
|
||||
}
|
||||
::rptMsg("</artifacts></logon>");
|
||||
}
|
||||
else {
|
||||
#::rptMsg($key_path." has no values.");
|
||||
#::logMsg($key_path." has no values.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
#::rptMsg($key_path." not found.");
|
||||
#::logMsg($key_path." not found.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
107
thirdparty/rr/plugins/autopsyntusernetwork.pl
vendored
107
thirdparty/rr/plugins/autopsyntusernetwork.pl
vendored
@ -30,64 +30,67 @@ sub pluginmain {
|
||||
my $ntuser = shift;
|
||||
#::logMsg("Launching ntusernetwork v.".$VERSION);
|
||||
#::rptMsg("ntusernetwork v.".$VERSION); # banner
|
||||
#::rptMsg("(".$config{hive}.") ".getShortDescr()."\n"); # banner
|
||||
my $reg = Parse::Win32Registry->new($ntuser);
|
||||
my $root_key = $reg->get_root_key;
|
||||
|
||||
::rptMsg("<NtuserNetwork>");
|
||||
::rptMsg("<mtime></mtime>");
|
||||
::rptMsg("<artifacts>");
|
||||
#::rptMsg("(".$config{hive}.") ".getShortDescr()."\n"); # banner
|
||||
if (defined(Parse::Win32Registry->new($ntuser))) {
|
||||
|
||||
my $reg = Parse::Win32Registry->new($ntuser);
|
||||
my $root_key = $reg->get_root_key;
|
||||
|
||||
::rptMsg("<NtuserNetwork>");
|
||||
::rptMsg("<mtime></mtime>");
|
||||
::rptMsg("<artifacts>");
|
||||
|
||||
my $key_path = 'Network';
|
||||
my $key;
|
||||
if ($key = $root_key->get_subkey($key_path)) {
|
||||
my $key_path = 'Network';
|
||||
my $key;
|
||||
if ($key = $root_key->get_subkey($key_path)) {
|
||||
|
||||
|
||||
my @subkeys = $key->get_list_of_subkeys();
|
||||
if (scalar @subkeys > 0) {
|
||||
foreach my $s (@subkeys) {
|
||||
#::rptMsg($key_path."\\".$s->get_name());
|
||||
my $localPath = $key_path."\\".$s->get_name();
|
||||
my @subkeys = $key->get_list_of_subkeys();
|
||||
if (scalar @subkeys > 0) {
|
||||
foreach my $s (@subkeys) {
|
||||
#::rptMsg($key_path."\\".$s->get_name());
|
||||
my $localPath = $key_path."\\".$s->get_name();
|
||||
|
||||
my $remotePath;
|
||||
eval {
|
||||
$remotePath = $s->get_value("RemotePath")->get_data();
|
||||
};
|
||||
if ($@) {
|
||||
# ::rptMsg("OS value not found.");
|
||||
}
|
||||
else {
|
||||
::rptMsg("<network localPath=\"" . $localPath . "\">". $remotePath . "</network>");
|
||||
}
|
||||
}
|
||||
}
|
||||
my $remotePath;
|
||||
eval {
|
||||
$remotePath = $s->get_value("RemotePath")->get_data();
|
||||
};
|
||||
if ($@) {
|
||||
# ::rptMsg("OS value not found.");
|
||||
}
|
||||
else {
|
||||
::rptMsg("<network localPath=\"" . $localPath . "\">". $remotePath . "</network>");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ::rptMsg($key_path);
|
||||
# ::rptMsg("");
|
||||
# ::rptMsg($key_path);
|
||||
# ::rptMsg("");
|
||||
|
||||
|
||||
|
||||
# my @subkeys = $key->get_list_of_subkeys();
|
||||
# if (scalar @subkeys > 0) {
|
||||
# foreach my $s (@subkeys) {
|
||||
# ::rptMsg($key_path."\\".$s->get_name());
|
||||
# ::rptMsg("LastWrite time: ".gmtime($s->get_timestamp()));
|
||||
# my @vals = $s->get_list_of_values();
|
||||
# if (scalar @vals > 0) {
|
||||
# foreach my $v (@vals) {
|
||||
# ::rptMsg(sprintf " %-15s %-25s",$v->get_name(),$v->get_data());
|
||||
# }
|
||||
# ::rptMsg("");
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
# else {
|
||||
# ::rptMsg($key_path." key has no subkeys.");
|
||||
# }
|
||||
}
|
||||
else {
|
||||
#::rptMsg($key_path." key not found.");
|
||||
}
|
||||
::rptMsg("</artifacts></NtuserNetwork>");
|
||||
|
||||
# my @subkeys = $key->get_list_of_subkeys();
|
||||
# if (scalar @subkeys > 0) {
|
||||
# foreach my $s (@subkeys) {
|
||||
# ::rptMsg($key_path."\\".$s->get_name());
|
||||
# ::rptMsg("LastWrite time: ".gmtime($s->get_timestamp()));
|
||||
# my @vals = $s->get_list_of_values();
|
||||
# if (scalar @vals > 0) {
|
||||
# foreach my $v (@vals) {
|
||||
# ::rptMsg(sprintf " %-15s %-25s",$v->get_name(),$v->get_data());
|
||||
# }
|
||||
# ::rptMsg("");
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
# else {
|
||||
# ::rptMsg($key_path." key has no subkeys.");
|
||||
# }
|
||||
}
|
||||
else {
|
||||
#::rptMsg($key_path." key not found.");
|
||||
}
|
||||
::rptMsg("</artifacts></NtuserNetwork>");
|
||||
}
|
||||
}
|
||||
1;
|
||||
|
150
thirdparty/rr/plugins/autopsyrecentdocs.pl
vendored
150
thirdparty/rr/plugins/autopsyrecentdocs.pl
vendored
@ -41,80 +41,82 @@ sub pluginmain {
|
||||
my $class = shift;
|
||||
my $ntuser = shift;
|
||||
#::logMsg("||recentdocs||");
|
||||
my $reg = Parse::Win32Registry->new($ntuser);
|
||||
my $root_key = $reg->get_root_key;
|
||||
my $key_path = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RecentDocs";
|
||||
my $key;
|
||||
if ($key = $root_key->get_subkey($key_path)) {
|
||||
#::rptMsg("RecentDocs");
|
||||
#::rptMsg("**All values printed in MRUList\\MRUListEx order.");
|
||||
#::rptMsg($key_path);
|
||||
::rptMsg("<recentdocs><mtime>".gmtime($key->get_timestamp())."</mtime><artifacts>");
|
||||
# Get RecentDocs values
|
||||
my %rdvals = getRDValues($key);
|
||||
if (%rdvals) {
|
||||
my $tag;
|
||||
if (exists $rdvals{"MRUListEx"}) {
|
||||
$tag = "MRUListEx";
|
||||
}
|
||||
elsif (exists $rdvals{"MRUList"}) {
|
||||
$tag = "MRUList";
|
||||
}
|
||||
else {
|
||||
|
||||
}
|
||||
|
||||
my @list = split(/,/,$rdvals{$tag});
|
||||
foreach my $i (@list) {
|
||||
::rptMsg("<doc name=\"Windows\">".$rdvals{$i} . "</doc>");
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
#::rptMsg($key_path." has no values.");
|
||||
#::logMsg("Error: ".$key_path." has no values.");
|
||||
}
|
||||
::rptMsg("</artifacts></recentdocs>");
|
||||
# Get RecentDocs subkeys' values
|
||||
my @subkeys = $key->get_list_of_subkeys();
|
||||
if (scalar(@subkeys) > 0) {
|
||||
foreach my $s (@subkeys) {
|
||||
#::rptMsg($key_path."\\".$s->get_name());
|
||||
#::rptMsg("LastWrite Time ".gmtime($s->get_timestamp())." (UTC)");
|
||||
|
||||
my %rdvals = getRDValues($s);
|
||||
if (%rdvals) {
|
||||
my $tag;
|
||||
if (exists $rdvals{"MRUListEx"}) {
|
||||
$tag = "MRUListEx";
|
||||
}
|
||||
elsif (exists $rdvals{"MRUList"}) {
|
||||
$tag = "MRUList";
|
||||
}
|
||||
else {
|
||||
|
||||
}
|
||||
|
||||
my @list = split(/,/,$rdvals{$tag});
|
||||
#::rptMsg($tag." = ".$rdvals{$tag});
|
||||
foreach my $i (@list) {
|
||||
#::rptMsg("".$rdvals{$i});
|
||||
}
|
||||
|
||||
#::rptMsg("");
|
||||
}
|
||||
else {
|
||||
#::rptMsg($key_path." has no values.");
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
#::rptMsg($key_path." has no subkeys.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
#::rptMsg($key_path." not found.");
|
||||
}
|
||||
if (defined(Parse::Win32Registry->new($ntuser))) {
|
||||
my $reg = Parse::Win32Registry->new($ntuser);
|
||||
my $root_key = $reg->get_root_key;
|
||||
my $key_path = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RecentDocs";
|
||||
my $key;
|
||||
if ($key = $root_key->get_subkey($key_path)) {
|
||||
#::rptMsg("RecentDocs");
|
||||
#::rptMsg("**All values printed in MRUList\\MRUListEx order.");
|
||||
#::rptMsg($key_path);
|
||||
::rptMsg("<recentdocs><mtime>".gmtime($key->get_timestamp())."</mtime><artifacts>");
|
||||
# Get RecentDocs values
|
||||
my %rdvals = getRDValues($key);
|
||||
if (%rdvals) {
|
||||
my $tag;
|
||||
if (exists $rdvals{"MRUListEx"}) {
|
||||
$tag = "MRUListEx";
|
||||
}
|
||||
elsif (exists $rdvals{"MRUList"}) {
|
||||
$tag = "MRUList";
|
||||
}
|
||||
else {
|
||||
|
||||
}
|
||||
|
||||
my @list = split(/,/,$rdvals{$tag});
|
||||
foreach my $i (@list) {
|
||||
::rptMsg("<doc name=\"Windows\">".$rdvals{$i} . "</doc>");
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
#::rptMsg($key_path." has no values.");
|
||||
#::logMsg("Error: ".$key_path." has no values.");
|
||||
}
|
||||
::rptMsg("</artifacts></recentdocs>");
|
||||
# Get RecentDocs subkeys' values
|
||||
my @subkeys = $key->get_list_of_subkeys();
|
||||
if (scalar(@subkeys) > 0) {
|
||||
foreach my $s (@subkeys) {
|
||||
#::rptMsg($key_path."\\".$s->get_name());
|
||||
#::rptMsg("LastWrite Time ".gmtime($s->get_timestamp())." (UTC)");
|
||||
|
||||
my %rdvals = getRDValues($s);
|
||||
if (%rdvals) {
|
||||
my $tag;
|
||||
if (exists $rdvals{"MRUListEx"}) {
|
||||
$tag = "MRUListEx";
|
||||
}
|
||||
elsif (exists $rdvals{"MRUList"}) {
|
||||
$tag = "MRUList";
|
||||
}
|
||||
else {
|
||||
|
||||
}
|
||||
|
||||
my @list = split(/,/,$rdvals{$tag});
|
||||
#::rptMsg($tag." = ".$rdvals{$tag});
|
||||
foreach my $i (@list) {
|
||||
#::rptMsg("".$rdvals{$i});
|
||||
}
|
||||
|
||||
#::rptMsg("");
|
||||
}
|
||||
else {
|
||||
#::rptMsg($key_path." has no values.");
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
#::rptMsg($key_path." has no subkeys.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
#::rptMsg($key_path." not found.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
55
thirdparty/rr/plugins/autopsyshellfolders.pl
vendored
55
thirdparty/rr/plugins/autopsyshellfolders.pl
vendored
@ -41,32 +41,35 @@ sub pluginmain {
|
||||
my $class = shift;
|
||||
my $hive = shift;
|
||||
#::logMsg("Launching shellfolders v.".$VERSION);
|
||||
my $reg = Parse::Win32Registry->new($hive);
|
||||
my $root_key = $reg->get_root_key;
|
||||
if (defined(Parse::Win32Registry->new($hive))) {
|
||||
my $reg = Parse::Win32Registry->new($hive);
|
||||
|
||||
my $key_path = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders";
|
||||
my $key;
|
||||
if ($key = $root_key->get_subkey($key_path)) {
|
||||
::rptMsg("<shellfolders>");
|
||||
::rptMsg("<mtime>".gmtime($key->get_timestamp())."</mtime>");
|
||||
|
||||
my @vals = $key->get_list_of_values();
|
||||
::rptMsg("<artifacts>");
|
||||
if (scalar(@vals) > 0) {
|
||||
foreach my $v (@vals) {
|
||||
my $str = sprintf "%-20s %-40s","<shell name=\"".$v->get_name()."\">",$v->get_data()."</shell>";
|
||||
::rptMsg($str);
|
||||
}
|
||||
::rptMsg("");
|
||||
}
|
||||
else {
|
||||
#::rptMsg($key_path." has no values.");
|
||||
}
|
||||
::rptMsg("</artifacts></shellfolders>");
|
||||
}
|
||||
else {
|
||||
#::rptMsg($key_path." not found.");
|
||||
#::logMsg($key_path." not found.");
|
||||
}
|
||||
my $root_key = $reg->get_root_key;
|
||||
|
||||
my $key_path = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders";
|
||||
my $key;
|
||||
if ($key = $root_key->get_subkey($key_path)) {
|
||||
::rptMsg("<shellfolders>");
|
||||
::rptMsg("<mtime>".gmtime($key->get_timestamp())."</mtime>");
|
||||
|
||||
my @vals = $key->get_list_of_values();
|
||||
::rptMsg("<artifacts>");
|
||||
if (scalar(@vals) > 0) {
|
||||
foreach my $v (@vals) {
|
||||
my $str = sprintf "%-20s %-40s","<shell name=\"".$v->get_name()."\">",$v->get_data()."</shell>";
|
||||
::rptMsg($str);
|
||||
}
|
||||
::rptMsg("");
|
||||
}
|
||||
else {
|
||||
#::rptMsg($key_path." has no values.");
|
||||
}
|
||||
::rptMsg("</artifacts></shellfolders>");
|
||||
}
|
||||
else {
|
||||
#::rptMsg($key_path." not found.");
|
||||
#::logMsg($key_path." not found.");
|
||||
}
|
||||
}
|
||||
}
|
||||
1;
|
||||
|
220
thirdparty/rr/plugins/officedocs.pl
vendored
220
thirdparty/rr/plugins/officedocs.pl
vendored
@ -37,115 +37,117 @@ sub pluginmain {
|
||||
# ::rptMsg("officedocs v.".$VERSION); # 20110830 [fpi] + banner
|
||||
# ::rptMsg("(".getHive().") ".getShortDescr()."\n"); # 20110830 [fpi] + banner
|
||||
::rptMsg("<office>");
|
||||
my $reg = Parse::Win32Registry->new($ntuser);
|
||||
my $root_key = $reg->get_root_key;
|
||||
#::rptMsg("officedocs v.".$VERSION);
|
||||
# First, let's find out which version of Office is installed
|
||||
my $version;
|
||||
my $tag = 0;
|
||||
my @versions = ("7\.0","8\.0", "9\.0", "10\.0", "11\.0","12\.0");
|
||||
foreach my $ver (@versions) {
|
||||
my $key_path = "Software\\Microsoft\\Office\\".$ver."\\Common\\Open Find";
|
||||
if (defined($root_key->get_subkey($key_path))) {
|
||||
$version = $ver;
|
||||
$tag = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ($tag) {
|
||||
#::rptMsg("MSOffice version ".$version." located.");
|
||||
my $key_path = "Software\\Microsoft\\Office\\".$version;
|
||||
my $of_key = $root_key->get_subkey($key_path);
|
||||
::rptMsg("<mtime> ".gmtime($of_key->get_timestamp())."</mtime>");
|
||||
::rptMsg("<artifacts>");
|
||||
if ($of_key) {
|
||||
# Attempt to retrieve Word docs
|
||||
my @funcs = ("Open","Save As","File Save");
|
||||
foreach my $func (@funcs) {
|
||||
my $word = "Common\\Open Find\\Microsoft Office Word\\Settings\\".$func."\\File Name MRU";
|
||||
my $word_key = $of_key->get_subkey($word);
|
||||
if ($word_key) {
|
||||
#::rptMsg($word);
|
||||
|
||||
#::rptMsg("");
|
||||
my $value = $word_key->get_value("Value")->get_data();
|
||||
my @data = split(/\00/,$value);
|
||||
::rptMsg("<Word name=\"".$value."\">". @data . "</Word>");
|
||||
#map{::rptMsg("$_");}@data;
|
||||
}
|
||||
else {
|
||||
# ::rptMsg("Could not access ".$word);
|
||||
}
|
||||
#::rptMsg("");
|
||||
}
|
||||
# Attempt to retrieve Excel docs
|
||||
my $excel = 'Excel\\Recent Files';
|
||||
if (my $excel_key = $of_key->get_subkey($excel)) {
|
||||
#::rptMsg($key_path."\\".$excel);
|
||||
#::rptMsg("LastWrite Time ".gmtime($excel_key->get_timestamp())." (UTC)");
|
||||
my @vals = $excel_key->get_list_of_values();
|
||||
if (scalar(@vals) > 0) {
|
||||
my %files;
|
||||
# Retrieve values and load into a hash for sorting
|
||||
foreach my $v (@vals) {
|
||||
my $val = $v->get_name();
|
||||
my $data = $v->get_data();
|
||||
my $tag = (split(/File/,$val))[1];
|
||||
$files{$tag} = $val.":".$data;
|
||||
}
|
||||
# Print sorted content to report file
|
||||
foreach my $u (sort {$a <=> $b} keys %files) {
|
||||
my ($val,$data) = split(/:/,$files{$u},2);
|
||||
::rptMsg("<Excel name=\"".$val."\">".$data . "</Excel>");
|
||||
}
|
||||
}
|
||||
else {
|
||||
#::rptMsg($key_path.$excel." has no values.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
#::rptMsg($key_path.$excel." not found.");
|
||||
}
|
||||
#::rptMsg("");
|
||||
# Attempt to retrieve PowerPoint docs
|
||||
my $ppt = 'PowerPoint\\Recent File List';
|
||||
if (my $ppt_key = $of_key->get_subkey($ppt)) {
|
||||
#::rptMsg($key_path."\\".$ppt);
|
||||
#::rptMsg("LastWrite Time ".gmtime($ppt_key->get_timestamp())." (UTC)");
|
||||
my @vals = $ppt_key->get_list_of_values();
|
||||
if (scalar(@vals) > 0) {
|
||||
my %files;
|
||||
# Retrieve values and load into a hash for sorting
|
||||
foreach my $v (@vals) {
|
||||
my $val = $v->get_name();
|
||||
my $data = $v->get_data();
|
||||
my $tag = (split(/File/,$val))[1];
|
||||
$files{$tag} = $val.":".$data;
|
||||
}
|
||||
# Print sorted content to report file
|
||||
foreach my $u (sort {$a <=> $b} keys %files) {
|
||||
my ($val,$data) = split(/:/,$files{$u},2);
|
||||
::rptMsg("<PowerPoint name=\"".$val."\">".$data . "</PowerPoint>");
|
||||
}
|
||||
}
|
||||
else {
|
||||
#::rptMsg($key_path."\\".$ppt." has no values.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
#::rptMsg($key_path."\\".$ppt." not found.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
#::rptMsg("Could not access ".$key_path);
|
||||
#::logMsg("Could not access ".$key_path);
|
||||
}
|
||||
::rptMsg("</artifacts>");
|
||||
}
|
||||
else {
|
||||
#::logMsg("MSOffice version not found.");
|
||||
#::rptMsg("MSOffice version not found.");
|
||||
}
|
||||
if (defined(Parse::Win32Registry->new($ntuser))) {
|
||||
my $reg = Parse::Win32Registry->new($ntuser);
|
||||
my $root_key = $reg->get_root_key;
|
||||
#::rptMsg("officedocs v.".$VERSION);
|
||||
# First, let's find out which version of Office is installed
|
||||
my $version;
|
||||
my $tag = 0;
|
||||
my @versions = ("7\.0","8\.0", "9\.0", "10\.0", "11\.0","12\.0");
|
||||
foreach my $ver (@versions) {
|
||||
my $key_path = "Software\\Microsoft\\Office\\".$ver."\\Common\\Open Find";
|
||||
if (defined($root_key->get_subkey($key_path))) {
|
||||
$version = $ver;
|
||||
$tag = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ($tag) {
|
||||
#::rptMsg("MSOffice version ".$version." located.");
|
||||
my $key_path = "Software\\Microsoft\\Office\\".$version;
|
||||
my $of_key = $root_key->get_subkey($key_path);
|
||||
::rptMsg("<mtime> ".gmtime($of_key->get_timestamp())."</mtime>");
|
||||
::rptMsg("<artifacts>");
|
||||
if ($of_key) {
|
||||
# Attempt to retrieve Word docs
|
||||
my @funcs = ("Open","Save As","File Save");
|
||||
foreach my $func (@funcs) {
|
||||
my $word = "Common\\Open Find\\Microsoft Office Word\\Settings\\".$func."\\File Name MRU";
|
||||
my $word_key = $of_key->get_subkey($word);
|
||||
if ($word_key) {
|
||||
#::rptMsg($word);
|
||||
|
||||
#::rptMsg("");
|
||||
my $value = $word_key->get_value("Value")->get_data();
|
||||
my @data = split(/\00/,$value);
|
||||
::rptMsg("<Word name=\"".$value."\">". @data . "</Word>");
|
||||
#map{::rptMsg("$_");}@data;
|
||||
}
|
||||
else {
|
||||
# ::rptMsg("Could not access ".$word);
|
||||
}
|
||||
#::rptMsg("");
|
||||
}
|
||||
# Attempt to retrieve Excel docs
|
||||
my $excel = 'Excel\\Recent Files';
|
||||
if (my $excel_key = $of_key->get_subkey($excel)) {
|
||||
#::rptMsg($key_path."\\".$excel);
|
||||
#::rptMsg("LastWrite Time ".gmtime($excel_key->get_timestamp())." (UTC)");
|
||||
my @vals = $excel_key->get_list_of_values();
|
||||
if (scalar(@vals) > 0) {
|
||||
my %files;
|
||||
# Retrieve values and load into a hash for sorting
|
||||
foreach my $v (@vals) {
|
||||
my $val = $v->get_name();
|
||||
my $data = $v->get_data();
|
||||
my $tag = (split(/File/,$val))[1];
|
||||
$files{$tag} = $val.":".$data;
|
||||
}
|
||||
# Print sorted content to report file
|
||||
foreach my $u (sort {$a <=> $b} keys %files) {
|
||||
my ($val,$data) = split(/:/,$files{$u},2);
|
||||
::rptMsg("<Excel name=\"".$val."\">".$data . "</Excel>");
|
||||
}
|
||||
}
|
||||
else {
|
||||
#::rptMsg($key_path.$excel." has no values.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
#::rptMsg($key_path.$excel." not found.");
|
||||
}
|
||||
#::rptMsg("");
|
||||
# Attempt to retrieve PowerPoint docs
|
||||
my $ppt = 'PowerPoint\\Recent File List';
|
||||
if (my $ppt_key = $of_key->get_subkey($ppt)) {
|
||||
#::rptMsg($key_path."\\".$ppt);
|
||||
#::rptMsg("LastWrite Time ".gmtime($ppt_key->get_timestamp())." (UTC)");
|
||||
my @vals = $ppt_key->get_list_of_values();
|
||||
if (scalar(@vals) > 0) {
|
||||
my %files;
|
||||
# Retrieve values and load into a hash for sorting
|
||||
foreach my $v (@vals) {
|
||||
my $val = $v->get_name();
|
||||
my $data = $v->get_data();
|
||||
my $tag = (split(/File/,$val))[1];
|
||||
$files{$tag} = $val.":".$data;
|
||||
}
|
||||
# Print sorted content to report file
|
||||
foreach my $u (sort {$a <=> $b} keys %files) {
|
||||
my ($val,$data) = split(/:/,$files{$u},2);
|
||||
::rptMsg("<PowerPoint name=\"".$val."\">".$data . "</PowerPoint>");
|
||||
}
|
||||
}
|
||||
else {
|
||||
#::rptMsg($key_path."\\".$ppt." has no values.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
#::rptMsg($key_path."\\".$ppt." not found.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
#::rptMsg("Could not access ".$key_path);
|
||||
#::logMsg("Could not access ".$key_path);
|
||||
}
|
||||
::rptMsg("</artifacts>");
|
||||
}
|
||||
else {
|
||||
#::logMsg("MSOffice version not found.");
|
||||
#::rptMsg("MSOffice version not found.");
|
||||
}
|
||||
}
|
||||
::rptMsg("</office>");
|
||||
}
|
||||
|
||||
|
289
thirdparty/rr/plugins/officedocs2010.pl
vendored
289
thirdparty/rr/plugins/officedocs2010.pl
vendored
@ -72,150 +72,151 @@ sub pluginmain {
|
||||
#::logMsg("Launching officedocs2010 v.".$VERSION);
|
||||
#::rptMsg("officedocs2010 v.".$VERSION); # 20110830 [fpi] + banner
|
||||
#::rptMsg("(".getHive().") ".getShortDescr()."\n"); # 20110830 [fpi] + banner
|
||||
|
||||
my $reg = Parse::Win32Registry->new($ntuser);
|
||||
my $root_key = $reg->get_root_key;
|
||||
# ::rptMsg("officedocs v.".$VERSION); # 20110830 [fpi] - redundant
|
||||
my $tag = 0;
|
||||
my $key_path = "Software\\Microsoft\\Office\\14.0";
|
||||
if (defined($root_key->get_subkey($key_path))) {
|
||||
$tag = 1;
|
||||
}
|
||||
|
||||
if ($tag) {
|
||||
#::rptMsg("MSOffice version 2010 located.");
|
||||
my $key_path = "Software\\Microsoft\\Office\\14.0";
|
||||
my $of_key = $root_key->get_subkey($key_path);
|
||||
if ($of_key) {
|
||||
# Attempt to retrieve Word docs
|
||||
my $word = 'Word\\File MRU';
|
||||
if (my $word_key = $of_key->get_subkey($word)) {
|
||||
#::rptMsg($key_path."\\".$word);
|
||||
#::rptMsg("LastWrite Time ".gmtime($word_key->get_timestamp())." (UTC)");
|
||||
my @vals = $word_key->get_list_of_values();
|
||||
if (scalar(@vals) > 0) {
|
||||
my %files;
|
||||
# Retrieve values and load into a hash for sorting
|
||||
foreach my $v (@vals) {
|
||||
my $val = $v->get_name();
|
||||
if ($val eq "Max Display") { next; }
|
||||
my $data = getWinTS($v->get_data());
|
||||
my $tag = (split(/Item/,$val))[1];
|
||||
$files{$tag} = $val.":".$data;
|
||||
}
|
||||
# Print sorted content to report file
|
||||
foreach my $u (sort {$a <=> $b} keys %files) {
|
||||
my ($val,$data) = split(/:/,$files{$u},2);
|
||||
::rptMsg("<Word name=\"".$val."\">".$data . "</Word>");
|
||||
}
|
||||
}
|
||||
else {
|
||||
#::rptMsg($key_path.$word." has no values.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
#::rptMsg($key_path.$word." not found.");
|
||||
}
|
||||
#::rptMsg("");
|
||||
# Attempt to retrieve Excel docs
|
||||
my $excel = 'Excel\\File MRU';
|
||||
if (my $excel_key = $of_key->get_subkey($excel)) {
|
||||
#::rptMsg($key_path."\\".$excel);
|
||||
#::rptMsg("LastWrite Time ".gmtime($excel_key->get_timestamp())." (UTC)");
|
||||
my @vals = $excel_key->get_list_of_values();
|
||||
if (scalar(@vals) > 0) {
|
||||
my %files;
|
||||
# Retrieve values and load into a hash for sorting
|
||||
foreach my $v (@vals) {
|
||||
my $val = $v->get_name();
|
||||
if ($val eq "Max Display") { next; }
|
||||
my $data = getWinTS($v->get_data());
|
||||
my $tag = (split(/Item/,$val))[1];
|
||||
$files{$tag} = $val.":".$data;
|
||||
}
|
||||
# Print sorted content to report file
|
||||
foreach my $u (sort {$a <=> $b} keys %files) {
|
||||
my ($val,$data) = split(/:/,$files{$u},2);
|
||||
::rptMsg("<Excel name=\"".$val."\">".$data . "</Excel>");
|
||||
}
|
||||
}
|
||||
else {
|
||||
#::rptMsg($key_path.$excel." has no values.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
#::rptMsg($key_path.$excel." not found.");
|
||||
}
|
||||
#::rptMsg("");
|
||||
# Attempt to retrieve Access docs
|
||||
my $access = 'Access\\File MRU';
|
||||
if (my $access_key = $of_key->get_subkey($access)) {
|
||||
#::rptMsg($key_path."\\".$access);
|
||||
#::rptMsg("LastWrite Time ".gmtime($access_key->get_timestamp())." (UTC)");
|
||||
my @vals = $access_key->get_list_of_values();
|
||||
if (scalar(@vals) > 0) {
|
||||
my %files;
|
||||
# Retrieve values and load into a hash for sorting
|
||||
foreach my $v (@vals) {
|
||||
my $val = $v->get_name();
|
||||
if ($val eq "Max Display") { next; }
|
||||
my $data = getWinTS($v->get_data());
|
||||
my $tag = (split(/Item/,$val))[1];
|
||||
$files{$tag} = $val.":".$data;
|
||||
}
|
||||
# Print sorted content to report file
|
||||
foreach my $u (sort {$a <=> $b} keys %files) {
|
||||
my ($val,$data) = split(/:/,$files{$u},2);
|
||||
::rptMsg("<Access name=\"".$val."\">".$data . "</Access>");
|
||||
}
|
||||
}
|
||||
else {
|
||||
# ::rptMsg($key_path.$access." has no values.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
# ::rptMsg($key_path.$access." not found.");
|
||||
}
|
||||
#::rptMsg("");
|
||||
# Attempt to retrieve PowerPoint docs
|
||||
my $ppt = 'PowerPoint\\File MRU';
|
||||
if (my $ppt_key = $of_key->get_subkey($ppt)) {
|
||||
#::rptMsg($key_path."\\".$ppt);
|
||||
#::rptMsg("LastWrite Time ".gmtime($ppt_key->get_timestamp())." (UTC)");
|
||||
my @vals = $ppt_key->get_list_of_values();
|
||||
if (scalar(@vals) > 0) {
|
||||
my %files;
|
||||
# Retrieve values and load into a hash for sorting
|
||||
foreach my $v (@vals) {
|
||||
my $val = $v->get_name();
|
||||
if ($val eq "Max Display") { next; }
|
||||
my $data = getWinTS($v->get_data());
|
||||
my $tag = (split(/Item/,$val))[1];
|
||||
$files{$tag} = $val.":".$data;
|
||||
}
|
||||
# Print sorted content to report file
|
||||
foreach my $u (sort {$a <=> $b} keys %files) {
|
||||
my ($val,$data) = split(/:/,$files{$u},2);
|
||||
::rptMsg("<PowerPoint name=\"".$val."\">".$data . "</PowerPoint>");
|
||||
}
|
||||
}
|
||||
else {
|
||||
# ::rptMsg($key_path."\\".$ppt." has no values.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
# ::rptMsg($key_path."\\".$ppt." not found.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
# ::rptMsg("Could not access ".$key_path);
|
||||
# ::logMsg("Could not access ".$key_path);
|
||||
}
|
||||
}
|
||||
else {
|
||||
# ::logMsg("MSOffice version not found.");
|
||||
# ::rptMsg("MSOffice version not found.");
|
||||
}
|
||||
if (defined(Parse::Win32Registry->new($ntuser))) {
|
||||
my $reg = Parse::Win32Registry->new($ntuser);
|
||||
my $root_key = $reg->get_root_key;
|
||||
# ::rptMsg("officedocs v.".$VERSION); # 20110830 [fpi] - redundant
|
||||
my $tag = 0;
|
||||
my $key_path = "Software\\Microsoft\\Office\\14.0";
|
||||
if (defined($root_key->get_subkey($key_path))) {
|
||||
$tag = 1;
|
||||
}
|
||||
|
||||
if ($tag) {
|
||||
#::rptMsg("MSOffice version 2010 located.");
|
||||
my $key_path = "Software\\Microsoft\\Office\\14.0";
|
||||
my $of_key = $root_key->get_subkey($key_path);
|
||||
if ($of_key) {
|
||||
# Attempt to retrieve Word docs
|
||||
my $word = 'Word\\File MRU';
|
||||
if (my $word_key = $of_key->get_subkey($word)) {
|
||||
#::rptMsg($key_path."\\".$word);
|
||||
#::rptMsg("LastWrite Time ".gmtime($word_key->get_timestamp())." (UTC)");
|
||||
my @vals = $word_key->get_list_of_values();
|
||||
if (scalar(@vals) > 0) {
|
||||
my %files;
|
||||
# Retrieve values and load into a hash for sorting
|
||||
foreach my $v (@vals) {
|
||||
my $val = $v->get_name();
|
||||
if ($val eq "Max Display") { next; }
|
||||
my $data = getWinTS($v->get_data());
|
||||
my $tag = (split(/Item/,$val))[1];
|
||||
$files{$tag} = $val.":".$data;
|
||||
}
|
||||
# Print sorted content to report file
|
||||
foreach my $u (sort {$a <=> $b} keys %files) {
|
||||
my ($val,$data) = split(/:/,$files{$u},2);
|
||||
::rptMsg("<Word name=\"".$val."\">".$data . "</Word>");
|
||||
}
|
||||
}
|
||||
else {
|
||||
#::rptMsg($key_path.$word." has no values.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
#::rptMsg($key_path.$word." not found.");
|
||||
}
|
||||
#::rptMsg("");
|
||||
# Attempt to retrieve Excel docs
|
||||
my $excel = 'Excel\\File MRU';
|
||||
if (my $excel_key = $of_key->get_subkey($excel)) {
|
||||
#::rptMsg($key_path."\\".$excel);
|
||||
#::rptMsg("LastWrite Time ".gmtime($excel_key->get_timestamp())." (UTC)");
|
||||
my @vals = $excel_key->get_list_of_values();
|
||||
if (scalar(@vals) > 0) {
|
||||
my %files;
|
||||
# Retrieve values and load into a hash for sorting
|
||||
foreach my $v (@vals) {
|
||||
my $val = $v->get_name();
|
||||
if ($val eq "Max Display") { next; }
|
||||
my $data = getWinTS($v->get_data());
|
||||
my $tag = (split(/Item/,$val))[1];
|
||||
$files{$tag} = $val.":".$data;
|
||||
}
|
||||
# Print sorted content to report file
|
||||
foreach my $u (sort {$a <=> $b} keys %files) {
|
||||
my ($val,$data) = split(/:/,$files{$u},2);
|
||||
::rptMsg("<Excel name=\"".$val."\">".$data . "</Excel>");
|
||||
}
|
||||
}
|
||||
else {
|
||||
#::rptMsg($key_path.$excel." has no values.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
#::rptMsg($key_path.$excel." not found.");
|
||||
}
|
||||
#::rptMsg("");
|
||||
# Attempt to retrieve Access docs
|
||||
my $access = 'Access\\File MRU';
|
||||
if (my $access_key = $of_key->get_subkey($access)) {
|
||||
#::rptMsg($key_path."\\".$access);
|
||||
#::rptMsg("LastWrite Time ".gmtime($access_key->get_timestamp())." (UTC)");
|
||||
my @vals = $access_key->get_list_of_values();
|
||||
if (scalar(@vals) > 0) {
|
||||
my %files;
|
||||
# Retrieve values and load into a hash for sorting
|
||||
foreach my $v (@vals) {
|
||||
my $val = $v->get_name();
|
||||
if ($val eq "Max Display") { next; }
|
||||
my $data = getWinTS($v->get_data());
|
||||
my $tag = (split(/Item/,$val))[1];
|
||||
$files{$tag} = $val.":".$data;
|
||||
}
|
||||
# Print sorted content to report file
|
||||
foreach my $u (sort {$a <=> $b} keys %files) {
|
||||
my ($val,$data) = split(/:/,$files{$u},2);
|
||||
::rptMsg("<Access name=\"".$val."\">".$data . "</Access>");
|
||||
}
|
||||
}
|
||||
else {
|
||||
# ::rptMsg($key_path.$access." has no values.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
# ::rptMsg($key_path.$access." not found.");
|
||||
}
|
||||
#::rptMsg("");
|
||||
# Attempt to retrieve PowerPoint docs
|
||||
my $ppt = 'PowerPoint\\File MRU';
|
||||
if (my $ppt_key = $of_key->get_subkey($ppt)) {
|
||||
#::rptMsg($key_path."\\".$ppt);
|
||||
#::rptMsg("LastWrite Time ".gmtime($ppt_key->get_timestamp())." (UTC)");
|
||||
my @vals = $ppt_key->get_list_of_values();
|
||||
if (scalar(@vals) > 0) {
|
||||
my %files;
|
||||
# Retrieve values and load into a hash for sorting
|
||||
foreach my $v (@vals) {
|
||||
my $val = $v->get_name();
|
||||
if ($val eq "Max Display") { next; }
|
||||
my $data = getWinTS($v->get_data());
|
||||
my $tag = (split(/Item/,$val))[1];
|
||||
$files{$tag} = $val.":".$data;
|
||||
}
|
||||
# Print sorted content to report file
|
||||
foreach my $u (sort {$a <=> $b} keys %files) {
|
||||
my ($val,$data) = split(/:/,$files{$u},2);
|
||||
::rptMsg("<PowerPoint name=\"".$val."\">".$data . "</PowerPoint>");
|
||||
}
|
||||
}
|
||||
else {
|
||||
# ::rptMsg($key_path."\\".$ppt." has no values.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
# ::rptMsg($key_path."\\".$ppt." not found.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
# ::rptMsg("Could not access ".$key_path);
|
||||
# ::logMsg("Could not access ".$key_path);
|
||||
}
|
||||
}
|
||||
else {
|
||||
# ::logMsg("MSOffice version not found.");
|
||||
# ::rptMsg("MSOffice version not found.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
Loading…
x
Reference in New Issue
Block a user