Merge branch 'sleuthkit:develop' into develop

This commit is contained in:
Seb2lyon 2021-06-02 18:07:14 +02:00
commit 29c4db9861
75 changed files with 2051 additions and 1793 deletions

View File

@ -1,24 +1,18 @@
AddBlackboardArtifactTagAction.pluralTagResult=Add Result Tags AddBlackboardArtifactTagAction.pluralTagResult=Add Result Tags
AddBlackboardArtifactTagAction.singularTagResult=Add Result Tag AddBlackboardArtifactTagAction.singularTagResult=Add Result Tag
AddBlackboardArtifactTagAction.taggingErr=Tagging Error AddBlackboardArtifactTagAction.taggingErr=Tagging Error
# {0} - artifactName
AddBlackboardArtifactTagAction.unableToTag.msg=Unable to tag {0}. AddBlackboardArtifactTagAction.unableToTag.msg=Unable to tag {0}.
AddContentTagAction.cannotApplyTagErr=Cannot Apply Tag AddContentTagAction.cannotApplyTagErr=Cannot Apply Tag
AddContentTagAction.pluralTagFile=Add File Tags AddContentTagAction.pluralTagFile=Add File Tags
AddContentTagAction.singularTagFile=Add File Tag AddContentTagAction.singularTagFile=Add File Tag
# {0} - fileName
# {1} - tagName
AddContentTagAction.tagExists={0} has been tagged as {1}. Cannot reapply the same tag. AddContentTagAction.tagExists={0} has been tagged as {1}. Cannot reapply the same tag.
AddContentTagAction.taggingErr=Tagging Error AddContentTagAction.taggingErr=Tagging Error
# {0} - fileName
AddContentTagAction.unableToTag.msg=Unable to tag {0}, not a regular file. AddContentTagAction.unableToTag.msg=Unable to tag {0}, not a regular file.
# {0} - fileName
AddContentTagAction.unableToTag.msg2=Unable to tag {0}. AddContentTagAction.unableToTag.msg2=Unable to tag {0}.
CTL_DumpThreadAction=Thread Dump CTL_DumpThreadAction=Thread Dump
CTL_ShowIngestProgressSnapshotAction=Ingest Status Details CTL_ShowIngestProgressSnapshotAction=Ingest Status Details
DeleteBlackboardArtifactTagAction.deleteTag=Remove Selected Tag(s) DeleteBlackboardArtifactTagAction.deleteTag=Remove Selected Tag(s)
DeleteBlackboardArtifactTagAction.tagDelErr=Tag Deletion Error DeleteBlackboardArtifactTagAction.tagDelErr=Tag Deletion Error
# {0} - tagName
DeleteBlackboardArtifactTagAction.unableToDelTag.msg=Unable to delete tag {0}. DeleteBlackboardArtifactTagAction.unableToDelTag.msg=Unable to delete tag {0}.
DeleteContentTagAction.deleteTag=Remove Selected Tag(s) DeleteContentTagAction.deleteTag=Remove Selected Tag(s)
DeleteContentTagAction.tagDelErr=Tag Deletion Error DeleteContentTagAction.tagDelErr=Tag Deletion Error
@ -84,8 +78,6 @@ CTL_OpenOutputFolder=Open Case Folder
OpenOutputFolder.error1=Case Folder Not Found: {0} OpenOutputFolder.error1=Case Folder Not Found: {0}
OpenOutputFolder.noCaseOpen=No open case, therefore no current case folder available. OpenOutputFolder.noCaseOpen=No open case, therefore no current case folder available.
OpenOutputFolder.CouldNotOpenOutputFolder=Could not open case folder OpenOutputFolder.CouldNotOpenOutputFolder=Could not open case folder
# {0} - old tag name
# {1} - artifactID
ReplaceBlackboardArtifactTagAction.replaceTag.alert=Unable to replace tag {0} for artifact {1}. ReplaceBlackboardArtifactTagAction.replaceTag.alert=Unable to replace tag {0} for artifact {1}.
# {0} - old tag name # {0} - old tag name
# {1} - content obj id # {1} - content obj id

View File

@ -247,15 +247,10 @@ AddImageWizardIngestConfigPanel.dsProcDone.errs.text=*Errors encountered in addi
AddImageWizardIngestConfigVisual.getName.text=Configure Ingest AddImageWizardIngestConfigVisual.getName.text=Configure Ingest
AddImageWizardIterator.stepXofN=Step {0} of {1} AddImageWizardIterator.stepXofN=Step {0} of {1}
AddLocalFilesTask.localFileAdd.progress.text=Adding: {0}/{1} AddLocalFilesTask.localFileAdd.progress.text=Adding: {0}/{1}
Case.getCurCase.exception.noneOpen=Cannot get the current case; there is no case open\! Case.getCurCase.exception.noneOpen=Cannot get the current case; there is no case open!
Case.open.msgDlg.updated.msg=Updated case database schema.\nA backup copy of the database with the following path has been made:\n {0} Case.open.msgDlg.updated.msg=Updated case database schema.\nA backup copy of the database with the following path has been made:\n {0}
Case.open.msgDlg.updated.title=Case Database Schema Update Case.open.msgDlg.updated.title=Case Database Schema Update
Case.checkImgExist.confDlg.doesntExist.msg=One of the images associated with \n\ Case.checkImgExist.confDlg.doesntExist.msg=One of the images associated with \nthis case are missing. Would you like to search for them now?\nPreviously, the image was located at:\n{0}\nPlease note that you will still be able to browse directories and generate reports\nif you choose No, but you will not be able to view file content or run the ingest process.
this case are missing. Would you like to search for them now?\n\
Previously, the image was located at:\n\
{0}\n\
Please note that you will still be able to browse directories and generate reports\n\
if you choose No, but you will not be able to view file content or run the ingest process.
Case.checkImgExist.confDlg.doesntExist.title=Missing Image Case.checkImgExist.confDlg.doesntExist.title=Missing Image
Case.addImg.exception.msg=Error adding image to the case Case.addImg.exception.msg=Error adding image to the case
Case.updateCaseName.exception.msg=Error while trying to update the case name. Case.updateCaseName.exception.msg=Error while trying to update the case name.
@ -274,12 +269,9 @@ Case.GetCaseTypeGivenPath.Failure=Unable to get case type
Case.metaDataFileCorrupt.exception.msg=The case metadata file (.aut) is corrupted. Case.metaDataFileCorrupt.exception.msg=The case metadata file (.aut) is corrupted.
Case.deleteReports.deleteFromDiskException.log.msg=Unable to delete the report from the disk. Case.deleteReports.deleteFromDiskException.log.msg=Unable to delete the report from the disk.
Case.deleteReports.deleteFromDiskException.msg=Unable to delete the report {0} from the disk.\nYou may manually delete it from {1} Case.deleteReports.deleteFromDiskException.msg=Unable to delete the report {0} from the disk.\nYou may manually delete it from {1}
CaseDeleteAction.closeConfMsg.text=Are you sure want to close and delete this case? \n\ CaseDeleteAction.closeConfMsg.text=Are you sure want to close and delete this case? \nCase Name: {0}\nCase Directory: {1}
Case Name: {0}\n\
Case Directory: {1}
CaseDeleteAction.closeConfMsg.title=Warning: Closing the Current Case CaseDeleteAction.closeConfMsg.title=Warning: Closing the Current Case
CaseDeleteAction.msgDlg.fileInUse.msg=The delete action cannot be fully completed because the folder or file in it is open by another program.\n\n\ CaseDeleteAction.msgDlg.fileInUse.msg=The delete action cannot be fully completed because the folder or file in it is open by another program.\n\nClose the folder and file and try again or you can delete the case manually.
Close the folder and file and try again or you can delete the case manually.
CaseDeleteAction.msgDlg.fileInUse.title=Error: Folder In Use CaseDeleteAction.msgDlg.fileInUse.title=Error: Folder In Use
CaseDeleteAction.msgDlg.caseDelete.msg=Case {0} has been deleted. CaseDeleteAction.msgDlg.caseDelete.msg=Case {0} has been deleted.
CaseOpenAction.autFilter.title={0} Case File ( {1}) CaseOpenAction.autFilter.title={0} Case File ( {1})
@ -311,8 +303,7 @@ NewCaseWizardAction.databaseProblem1.text=Cannot open database. Cancelling case
NewCaseWizardAction.databaseProblem2.text=Error NewCaseWizardAction.databaseProblem2.text=Error
NewCaseWizardPanel1.validate.errMsg.invalidSymbols=The Case Name cannot contain any of the following symbols: \\ / : * ? " < > | NewCaseWizardPanel1.validate.errMsg.invalidSymbols=The Case Name cannot contain any of the following symbols: \\ / : * ? " < > |
NewCaseWizardPanel1.validate.errMsg.dirExists=Case directory ''{0}'' already exists. NewCaseWizardPanel1.validate.errMsg.dirExists=Case directory ''{0}'' already exists.
NewCaseWizardPanel1.validate.confMsg.createDir.msg=The base directory "{0}" does not exist. \n\n\ NewCaseWizardPanel1.validate.confMsg.createDir.msg=The base directory "{0}" does not exist. \n\nDo you want to create that directory?
Do you want to create that directory?
NewCaseWizardPanel1.validate.confMsg.createDir.title=Create directory NewCaseWizardPanel1.validate.confMsg.createDir.title=Create directory
NewCaseWizardPanel1.validate.errMsg.cantCreateParDir.msg=Error: Could not create case parent directory {0} NewCaseWizardPanel1.validate.errMsg.cantCreateParDir.msg=Error: Could not create case parent directory {0}
NewCaseWizardPanel1.validate.errMsg.prevCreateBaseDir.msg=Prevented from creating base directory {0} NewCaseWizardPanel1.validate.errMsg.prevCreateBaseDir.msg=Prevented from creating base directory {0}
@ -341,7 +332,6 @@ OptionalCasePropertiesPanel.lbPointOfContactPhoneLabel.text=Phone:
OptionalCasePropertiesPanel.orgainizationPanel.border.title=Organization OptionalCasePropertiesPanel.orgainizationPanel.border.title=Organization
RecentCases.exception.caseIdxOutOfRange.msg=Recent case index {0} is out of range. RecentCases.exception.caseIdxOutOfRange.msg=Recent case index {0} is out of range.
RecentCases.getName.text=Clear Recent Cases RecentCases.getName.text=Clear Recent Cases
# {0} - case name
RecentItems.openRecentCase.msgDlg.text=Case {0} no longer exists. RecentItems.openRecentCase.msgDlg.text=Case {0} no longer exists.
SelectDataSourceProcessorPanel.name.text=Select Data Source Type SelectDataSourceProcessorPanel.name.text=Select Data Source Type
StartupWindow.title.text=Welcome StartupWindow.title.text=Welcome
@ -354,7 +344,6 @@ StartupWindowProvider.openCase.noFile=Unable to open previously open case becaus
UnpackagePortableCaseDialog.title.text=Unpackage Portable Case UnpackagePortableCaseDialog.title.text=Unpackage Portable Case
UnpackagePortableCaseDialog.UnpackagePortableCaseDialog.extensions=Portable case package (.zip, .zip.001) UnpackagePortableCaseDialog.UnpackagePortableCaseDialog.extensions=Portable case package (.zip, .zip.001)
UnpackagePortableCaseDialog.validatePaths.badExtension=File extension must be .zip or .zip.001 UnpackagePortableCaseDialog.validatePaths.badExtension=File extension must be .zip or .zip.001
# {0} - case folder
UnpackagePortableCaseDialog.validatePaths.caseFolderExists=Folder {0} already exists UnpackagePortableCaseDialog.validatePaths.caseFolderExists=Folder {0} already exists
UnpackagePortableCaseDialog.validatePaths.caseIsNotFile=Selected path is not a file UnpackagePortableCaseDialog.validatePaths.caseIsNotFile=Selected path is not a file
UnpackagePortableCaseDialog.validatePaths.caseNotFound=File does not exist UnpackagePortableCaseDialog.validatePaths.caseNotFound=File does not exist
@ -369,8 +358,8 @@ UnpackageWorker.doInBackground.previouslySeenCase=Case has been previously opene
UpdateRecentCases.menuItem.clearRecentCases.text=Clear Recent Cases UpdateRecentCases.menuItem.clearRecentCases.text=Clear Recent Cases
UpdateRecentCases.menuItem.empty=-Empty- UpdateRecentCases.menuItem.empty=-Empty-
AddImageWizardIngestConfigPanel.CANCEL_BUTTON.text=Cancel AddImageWizardIngestConfigPanel.CANCEL_BUTTON.text=Cancel
NewCaseVisualPanel1.CaseFolderOnCDriveError.text=Warning: Path to multi-user case folder is on \"C:\" drive NewCaseVisualPanel1.CaseFolderOnCDriveError.text=Warning: Path to multi-user case folder is on "C:" drive
NewCaseVisualPanel1.CaseFolderOnInternalDriveWindowsError.text=Warning: Path to case folder is on \"C:\" drive. Case folder is created on the target system NewCaseVisualPanel1.CaseFolderOnInternalDriveWindowsError.text=Warning: Path to case folder is on "C:" drive. Case folder is created on the target system
NewCaseVisualPanel1.CaseFolderOnInternalDriveLinuxError.text=Warning: Path to case folder is on the target system. Create case folder in mounted drive. NewCaseVisualPanel1.CaseFolderOnInternalDriveLinuxError.text=Warning: Path to case folder is on the target system. Create case folder in mounted drive.
NewCaseVisualPanel1.uncPath.error=Error: UNC paths are not allowed for Single-User cases NewCaseVisualPanel1.uncPath.error=Error: UNC paths are not allowed for Single-User cases
CollaborationMonitor.addingDataSourceStatus.msg={0} adding data source CollaborationMonitor.addingDataSourceStatus.msg={0} adding data source
@ -378,7 +367,7 @@ CollaborationMonitor.analyzingDataSourceStatus.msg={0} analyzing {1}
MissingImageDialog.lbWarning.text= MissingImageDialog.lbWarning.text=
MissingImageDialog.lbWarning.toolTipText= MissingImageDialog.lbWarning.toolTipText=
NewCaseVisualPanel1.caseParentDirWarningLabel.text= NewCaseVisualPanel1.caseParentDirWarningLabel.text=
NewCaseVisualPanel1.multiUserCaseRadioButton.text=Multi-User NewCaseVisualPanel1.multiUserCaseRadioButton.text=Multi-User\t\t
NewCaseVisualPanel1.singleUserCaseRadioButton.text=Single-User NewCaseVisualPanel1.singleUserCaseRadioButton.text=Single-User
NewCaseVisualPanel1.caseTypeLabel.text=Case Type: NewCaseVisualPanel1.caseTypeLabel.text=Case Type:
SingleUserCaseConverter.BadDatabaseFileName=Database file does not exist! SingleUserCaseConverter.BadDatabaseFileName=Database file does not exist!

View File

@ -85,13 +85,15 @@ import org.sleuthkit.autopsy.casemodule.events.DataSourceAddedEvent;
import org.sleuthkit.autopsy.casemodule.events.DataSourceDeletedEvent; import org.sleuthkit.autopsy.casemodule.events.DataSourceDeletedEvent;
import org.sleuthkit.autopsy.casemodule.events.DataSourceNameChangedEvent; import org.sleuthkit.autopsy.casemodule.events.DataSourceNameChangedEvent;
import org.sleuthkit.autopsy.casemodule.events.HostsAddedEvent; import org.sleuthkit.autopsy.casemodule.events.HostsAddedEvent;
import org.sleuthkit.autopsy.casemodule.events.HostsChangedEvent; import org.sleuthkit.autopsy.casemodule.events.HostsAddedToPersonEvent;
import org.sleuthkit.autopsy.casemodule.events.HostsRemovedEvent; import org.sleuthkit.autopsy.casemodule.events.HostsUpdatedEvent;
import org.sleuthkit.autopsy.casemodule.events.OsAccountAddedEvent; import org.sleuthkit.autopsy.casemodule.events.HostsDeletedEvent;
import org.sleuthkit.autopsy.casemodule.events.OsAccountChangedEvent; import org.sleuthkit.autopsy.casemodule.events.HostsRemovedFromPersonEvent;
import org.sleuthkit.autopsy.casemodule.events.OsAccountDeletedEvent; import org.sleuthkit.autopsy.casemodule.events.OsAccountsAddedEvent;
import org.sleuthkit.autopsy.casemodule.events.OsAccountsUpdatedEvent;
import org.sleuthkit.autopsy.casemodule.events.OsAccountsDeletedEvent;
import org.sleuthkit.autopsy.casemodule.events.PersonsAddedEvent; import org.sleuthkit.autopsy.casemodule.events.PersonsAddedEvent;
import org.sleuthkit.autopsy.casemodule.events.PersonsChangedEvent; import org.sleuthkit.autopsy.casemodule.events.PersonsUpdatedEvent;
import org.sleuthkit.autopsy.casemodule.events.PersonsDeletedEvent; import org.sleuthkit.autopsy.casemodule.events.PersonsDeletedEvent;
import org.sleuthkit.autopsy.casemodule.events.ReportAddedEvent; import org.sleuthkit.autopsy.casemodule.events.ReportAddedEvent;
import org.sleuthkit.autopsy.casemodule.multiusercases.CaseNodeData.CaseNodeDataException; import org.sleuthkit.autopsy.casemodule.multiusercases.CaseNodeData.CaseNodeDataException;
@ -190,7 +192,7 @@ public class Case {
private final SleuthkitEventListener sleuthkitEventListener; private final SleuthkitEventListener sleuthkitEventListener;
private CollaborationMonitor collaborationMonitor; private CollaborationMonitor collaborationMonitor;
private Services caseServices; private Services caseServices;
private volatile boolean hasDataSource = false; private volatile boolean hasDataSource = false;
private volatile boolean hasData = false; private volatile boolean hasData = false;
@ -434,43 +436,50 @@ public class Case {
*/ */
CR_COMMENT_CHANGED, CR_COMMENT_CHANGED,
/** /**
* OSAccount associated with the current case added. Call getOsAccount * One or more OS accounts have been added to the case.
* to get the added account;
*/ */
OS_ACCOUNT_ADDED, OS_ACCOUNTS_ADDED,
/** /**
* OSAccount associated with the current case has changed. Call * One or more OS accounts in the case have been updated.
* getOsAccount to get the changed account;
*/ */
OS_ACCOUNT_CHANGED, OS_ACCOUNTS_UPDATED,
/** /**
* OSAccount associated with the current case has been deleted. * One or more OS accounts have been deleted from the case.
*/ */
OS_ACCOUNT_REMOVED, OS_ACCOUNTS_DELETED,
/** /**
* Hosts associated with the current case added. * One or more hosts have been added to the case.
*/ */
HOSTS_ADDED, HOSTS_ADDED,
/** /**
* Hosts associated with the current case has changed. * One or more hosts in the case have been updated.
*/ */
HOSTS_CHANGED, HOSTS_UPDATED,
/** /**
* Hosts associated with the current case has been deleted. * One or more hosts have been deleted from the case.
*/ */
HOSTS_DELETED, HOSTS_DELETED,
/** /**
* Persons associated with the current case added. * One or more persons have been added to the case.
*/ */
PERSONS_ADDED, PERSONS_ADDED,
/** /**
* Persons associated with the current case has changed. * One or more persons in the case have been updated.
*/ */
PERSONS_CHANGED, PERSONS_UPDATED,
/** /**
* Persons associated with the current case has been deleted. * One or more persons been deleted from the case.
*/ */
PERSONS_DELETED; PERSONS_DELETED,
/**
* One or more hosts have been added to a person.
*/
HOSTS_ADDED_TO_PERSON,
/**
* One or more hosts have been removed from a person.
*/
HOSTS_REMOVED_FROM_PERSON;
}; };
/** /**
@ -505,18 +514,14 @@ public class Case {
} }
@Subscribe @Subscribe
public void publishOsAccountAddedEvent(TskEvent.OsAccountsAddedTskEvent event) { public void publishOsAccountsAddedEvent(TskEvent.OsAccountsAddedTskEvent event) {
hasData = true; hasData = true;
for (OsAccount account : event.getOsAcounts()) { eventPublisher.publish(new OsAccountsAddedEvent(event.getOsAcounts()));
eventPublisher.publish(new OsAccountAddedEvent(account));
}
} }
@Subscribe @Subscribe
public void publishOsAccountChangedEvent(TskEvent.OsAccountsChangedTskEvent event) { public void publishOsAccountsUpdatedEvent(TskEvent.OsAccountsUpdatedTskEvent event) {
for (OsAccount account : event.getOsAcounts()) { eventPublisher.publish(new OsAccountsUpdatedEvent(event.getOsAcounts()));
eventPublisher.publish(new OsAccountChangedEvent(account));
}
} }
@Subscribe @Subscribe
@ -526,10 +531,7 @@ public class Case {
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Unable to retrieve the hasData status from the db", ex); logger.log(Level.SEVERE, "Unable to retrieve the hasData status from the db", ex);
} }
eventPublisher.publish(new OsAccountsDeletedEvent(event.getOsAccountObjectIds()));
for (Long accountId : event.getOsAcountObjectIds()) {
eventPublisher.publish(new OsAccountDeletedEvent(accountId));
}
} }
/** /**
@ -541,8 +543,7 @@ public class Case {
@Subscribe @Subscribe
public void publishHostsAddedEvent(TskEvent.HostsAddedTskEvent event) { public void publishHostsAddedEvent(TskEvent.HostsAddedTskEvent event) {
hasData = true; hasData = true;
eventPublisher.publish(new HostsAddedEvent( eventPublisher.publish(new HostsAddedEvent(event.getHosts()));
event == null ? Collections.emptyList() : event.getHosts()));
} }
/** /**
@ -552,9 +553,8 @@ public class Case {
* @param event The sleuthkit event for the updating of hosts. * @param event The sleuthkit event for the updating of hosts.
*/ */
@Subscribe @Subscribe
public void publishHostsChangedEvent(TskEvent.HostsChangedTskEvent event) { public void publishHostsUpdatedEvent(TskEvent.HostsUpdatedTskEvent event) {
eventPublisher.publish(new HostsChangedEvent( eventPublisher.publish(new HostsUpdatedEvent(event.getHosts()));
event == null ? Collections.emptyList() : event.getHosts()));
} }
/** /**
@ -570,9 +570,8 @@ public class Case {
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Unable to retrieve the hasData status from the db", ex); logger.log(Level.SEVERE, "Unable to retrieve the hasData status from the db", ex);
} }
eventPublisher.publish(new HostsRemovedEvent( eventPublisher.publish(new HostsDeletedEvent(event.getHostIds()));
event == null ? Collections.emptyList() : event.getHosts()));
} }
/** /**
@ -583,8 +582,7 @@ public class Case {
*/ */
@Subscribe @Subscribe
public void publishPersonsAddedEvent(TskEvent.PersonsAddedTskEvent event) { public void publishPersonsAddedEvent(TskEvent.PersonsAddedTskEvent event) {
eventPublisher.publish(new PersonsAddedEvent( eventPublisher.publish(new PersonsAddedEvent(event.getPersons()));
event == null ? Collections.emptyList() : event.getPersons()));
} }
/** /**
@ -594,9 +592,8 @@ public class Case {
* @param event The sleuthkit event for the updating of persons. * @param event The sleuthkit event for the updating of persons.
*/ */
@Subscribe @Subscribe
public void publishPersonsChangedEvent(TskEvent.PersonsChangedTskEvent event) { public void publishPersonsUpdatedEvent(TskEvent.PersonsUpdatedTskEvent event) {
eventPublisher.publish(new PersonsChangedEvent( eventPublisher.publish(new PersonsUpdatedEvent(event.getPersons()));
event == null ? Collections.emptyList() : event.getPersons()));
} }
/** /**
@ -607,9 +604,19 @@ public class Case {
*/ */
@Subscribe @Subscribe
public void publishPersonsDeletedEvent(TskEvent.PersonsDeletedTskEvent event) { public void publishPersonsDeletedEvent(TskEvent.PersonsDeletedTskEvent event) {
eventPublisher.publish(new PersonsDeletedEvent( eventPublisher.publish(new PersonsDeletedEvent(event.getPersonIds()));
event == null ? Collections.emptyList() : event.getPersons()));
} }
@Subscribe
public void publishHostsAddedToPersonEvent(TskEvent.HostsAddedToPersonTskEvent event) {
eventPublisher.publish(new HostsAddedToPersonEvent(event.getPerson(), event.getHosts()));
}
@Subscribe
public void publisHostsRemovedFromPersonEvent(TskEvent.HostsRemovedFromPersonTskEvent event) {
eventPublisher.publish(new HostsRemovedFromPersonEvent(event.getPerson(), event.getHostIds()));
}
} }
/** /**
@ -1232,106 +1239,105 @@ public class Case {
/** /**
* Update the GUI to to reflect the current case. * Update the GUI to to reflect the current case.
*/ */
private static void updateGUIForCaseOpened(Case newCurrentCase) { private static void updateGUIForCaseOpened(Case newCurrentCase) {
/* /*
* If the case database was upgraded for a new schema and a * If the case database was upgraded for a new schema and a backup
* backup database was created, notify the user. * database was created, notify the user.
*/ */
SleuthkitCase caseDb = newCurrentCase.getSleuthkitCase(); SleuthkitCase caseDb = newCurrentCase.getSleuthkitCase();
String backupDbPath = caseDb.getBackupDatabasePath(); String backupDbPath = caseDb.getBackupDatabasePath();
if (null != backupDbPath) { if (null != backupDbPath) {
JOptionPane.showMessageDialog( JOptionPane.showMessageDialog(
mainFrame, mainFrame,
NbBundle.getMessage(Case.class, "Case.open.msgDlg.updated.msg", backupDbPath), NbBundle.getMessage(Case.class, "Case.open.msgDlg.updated.msg", backupDbPath),
NbBundle.getMessage(Case.class, "Case.open.msgDlg.updated.title"), NbBundle.getMessage(Case.class, "Case.open.msgDlg.updated.title"),
JOptionPane.INFORMATION_MESSAGE); JOptionPane.INFORMATION_MESSAGE);
} }
/* /*
* Look for the files for the data sources listed in the case * Look for the files for the data sources listed in the case database
* database and give the user the opportunity to locate any that * and give the user the opportunity to locate any that are missing.
* are missing. */
*/ Map<Long, String> imgPaths = getImagePaths(caseDb);
Map<Long, String> imgPaths = getImagePaths(caseDb); for (Map.Entry<Long, String> entry : imgPaths.entrySet()) {
for (Map.Entry<Long, String> entry : imgPaths.entrySet()) { long obj_id = entry.getKey();
long obj_id = entry.getKey(); String path = entry.getValue();
String path = entry.getValue(); boolean fileExists = (new File(path).isFile() || DriveUtils.driveExists(path));
boolean fileExists = (new File(path).isFile() || DriveUtils.driveExists(path)); if (!fileExists) {
if (!fileExists) { try {
try { // Using invokeAndWait means that the dialog will
// Using invokeAndWait means that the dialog will // open on the EDT but this thread will wait for an
// open on the EDT but this thread will wait for an // answer. Using invokeLater would cause this loop to
// answer. Using invokeLater would cause this loop to // end before all of the dialogs appeared.
// end before all of the dialogs appeared. SwingUtilities.invokeAndWait(new Runnable() {
SwingUtilities.invokeAndWait(new Runnable() { @Override
@Override public void run() {
public void run() { int response = JOptionPane.showConfirmDialog(
int response = JOptionPane.showConfirmDialog(
mainFrame, mainFrame,
NbBundle.getMessage(Case.class, "Case.checkImgExist.confDlg.doesntExist.msg", path), NbBundle.getMessage(Case.class, "Case.checkImgExist.confDlg.doesntExist.msg", path),
NbBundle.getMessage(Case.class, "Case.checkImgExist.confDlg.doesntExist.title"), NbBundle.getMessage(Case.class, "Case.checkImgExist.confDlg.doesntExist.title"),
JOptionPane.YES_NO_OPTION); JOptionPane.YES_NO_OPTION);
if (response == JOptionPane.YES_OPTION) { if (response == JOptionPane.YES_OPTION) {
MissingImageDialog.makeDialog(obj_id, caseDb); MissingImageDialog.makeDialog(obj_id, caseDb);
} else { } else {
logger.log(Level.SEVERE, "User proceeding with missing image files"); //NON-NLS logger.log(Level.SEVERE, "User proceeding with missing image files"); //NON-NLS
} }
} }
}); });
} catch (InterruptedException | InvocationTargetException ex) { } catch (InterruptedException | InvocationTargetException ex) {
logger.log(Level.SEVERE, "Failed to show missing image confirmation dialog", ex); //NON-NLS logger.log(Level.SEVERE, "Failed to show missing image confirmation dialog", ex); //NON-NLS
}
}
} }
}
}
/* /*
* Enable the case-specific actions. * Enable the case-specific actions.
*/ */
CallableSystemAction.get(AddImageAction.class).setEnabled(FeatureAccessUtils.canAddDataSources()); CallableSystemAction.get(AddImageAction.class).setEnabled(FeatureAccessUtils.canAddDataSources());
CallableSystemAction.get(OpenHostsAction.class).setEnabled(true); CallableSystemAction.get(OpenHostsAction.class).setEnabled(true);
CallableSystemAction.get(CaseCloseAction.class).setEnabled(true); CallableSystemAction.get(CaseCloseAction.class).setEnabled(true);
CallableSystemAction.get(CaseDetailsAction.class).setEnabled(true); CallableSystemAction.get(CaseDetailsAction.class).setEnabled(true);
CallableSystemAction.get(DataSourceSummaryAction.class).setEnabled(true); CallableSystemAction.get(DataSourceSummaryAction.class).setEnabled(true);
CallableSystemAction.get(CaseDeleteAction.class).setEnabled(FeatureAccessUtils.canDeleteCurrentCase()); CallableSystemAction.get(CaseDeleteAction.class).setEnabled(FeatureAccessUtils.canDeleteCurrentCase());
CallableSystemAction.get(OpenTimelineAction.class).setEnabled(true); CallableSystemAction.get(OpenTimelineAction.class).setEnabled(true);
CallableSystemAction.get(OpenCommVisualizationToolAction.class).setEnabled(true); CallableSystemAction.get(OpenCommVisualizationToolAction.class).setEnabled(true);
CallableSystemAction.get(CommonAttributeSearchAction.class).setEnabled(true); CallableSystemAction.get(CommonAttributeSearchAction.class).setEnabled(true);
CallableSystemAction.get(OpenOutputFolderAction.class).setEnabled(false); CallableSystemAction.get(OpenOutputFolderAction.class).setEnabled(false);
CallableSystemAction.get(OpenDiscoveryAction.class).setEnabled(true); CallableSystemAction.get(OpenDiscoveryAction.class).setEnabled(true);
/*
* Add the case to the recent cases tracker that supplies a list of
* recent cases to the recent cases menu item and the open/create case
* dialog.
*/
RecentCases.getInstance().addRecentCase(newCurrentCase.getDisplayName(), newCurrentCase.getMetadata().getFilePath().toString());
final boolean hasData = newCurrentCase.hasData();
SwingUtilities.invokeLater(() -> {
/* /*
* Add the case to the recent cases tracker that supplies a list * Open the top components (windows within the main application
* of recent cases to the recent cases menu item and the * window).
* open/create case dialog. *
* Note: If the core windows are not opened here, they will be
* opened via the DirectoryTreeTopComponent 'propertyChange()'
* method on a DATA_SOURCE_ADDED event.
*/ */
RecentCases.getInstance().addRecentCase(newCurrentCase.getDisplayName(), newCurrentCase.getMetadata().getFilePath().toString()); if (hasData) {
final boolean hasData = newCurrentCase.hasData(); CoreComponentControl.openCoreWindows();
} else {
SwingUtilities.invokeLater(() -> { //ensure that the DirectoryTreeTopComponent is open so that it's listener can open the core windows including making it visible.
/* DirectoryTreeTopComponent.findInstance();
* Open the top components (windows within the main application }
* window).
*
* Note: If the core windows are not opened here, they will be
* opened via the DirectoryTreeTopComponent 'propertyChange()'
* method on a DATA_SOURCE_ADDED event.
*/
if (hasData) {
CoreComponentControl.openCoreWindows();
} else {
//ensure that the DirectoryTreeTopComponent is open so that it's listener can open the core windows including making it visible.
DirectoryTreeTopComponent.findInstance();
}
/* /*
* Reset the main window title to: * Reset the main window title to:
* *
* [curent case display name] - [application name]. * [curent case display name] - [application name].
*/ */
mainFrame.setTitle(newCurrentCase.getDisplayName() + " - " + getNameForTitle()); mainFrame.setTitle(newCurrentCase.getDisplayName() + " - " + getNameForTitle());
}); });
} }
/* /*
@ -1684,16 +1690,16 @@ public class Case {
/** /**
* Returns true if there is any data in the case. * Returns true if there is any data in the case.
* *
* @return True or false. * @return True or false.
*/ */
public boolean hasData() { public boolean hasData() {
return hasData; return hasData;
} }
/** /**
* Returns true if there is one or more data sources in the case. * Returns true if there is one or more data sources in the case.
* *
* @return True or false. * @return True or false.
*/ */
public boolean hasDataSource() { public boolean hasDataSource() {
@ -1858,72 +1864,6 @@ public class Case {
eventPublisher.publish(new BlackBoardArtifactTagDeletedEvent(deletedTag)); eventPublisher.publish(new BlackBoardArtifactTagDeletedEvent(deletedTag));
} }
public void notifyOsAccountAdded(OsAccount account) {
eventPublisher.publish(new OsAccountAddedEvent(account));
}
public void notifyOsAccountChanged(OsAccount account) {
eventPublisher.publish(new OsAccountChangedEvent(account));
}
public void notifyOsAccountRemoved(Long osAccountObjectId) {
eventPublisher.publish(new OsAccountDeletedEvent(osAccountObjectId));
}
/**
* Notify via an autopsy event that a host has been added.
*
* @param host The host that has been added.
*/
public void notifyHostAdded(Host host) {
eventPublisher.publish(new HostsAddedEvent(Collections.singletonList(host)));
}
/**
* Notify via an autopsy event that a host has been changed.
*
* @param newValue The host that has been updated.
*/
public void notifyHostChanged(Host newValue) {
eventPublisher.publish(new HostsChangedEvent(Collections.singletonList(newValue)));
}
/**
* Notify via an autopsy event that a host has been deleted.
*
* @param host The host that has been deleted.
*/
public void notifyHostDeleted(Host host) {
eventPublisher.publish(new HostsRemovedEvent(Collections.singletonList(host)));
}
/**
* Notify via an autopsy event that a person has been added.
*
* @param person The person that has been added.
*/
public void notifyPersonAdded(Person person) {
eventPublisher.publish(new PersonsAddedEvent(Collections.singletonList(person)));
}
/**
* Notify via an autopsy event that a person has been changed.
*
* @param newValue The person that has been updated.
*/
public void notifyPersonChanged(Person newValue) {
eventPublisher.publish(new PersonsChangedEvent(Collections.singletonList(newValue)));
}
/**
* Notify via an autopsy event that a person has been deleted.
*
* @param person The person that has been deleted.
*/
public void notifyPersonDeleted(Person person) {
eventPublisher.publish(new PersonsDeletedEvent(Collections.singletonList(person)));
}
/** /**
* Adds a report to the case. * Adds a report to the case.
* *
@ -1966,7 +1906,7 @@ public class Case {
throw new TskCoreException(errorMsg, ex); throw new TskCoreException(errorMsg, ex);
} }
hasData = true; hasData = true;
Report report = this.caseDb.addReport(normalizedLocalPath, srcModuleName, reportName, parent); Report report = this.caseDb.addReport(normalizedLocalPath, srcModuleName, reportName, parent);
eventPublisher.publish(new ReportAddedEvent(report)); eventPublisher.publish(new ReportAddedEvent(report));
return report; return report;
@ -1996,16 +1936,16 @@ public class Case {
for (Report report : reports) { for (Report report : reports) {
this.caseDb.deleteReport(report); this.caseDb.deleteReport(report);
} }
try { try {
hasData = dbHasData(); hasData = dbHasData();
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Unable to retrieve the hasData status from the db", ex); logger.log(Level.SEVERE, "Unable to retrieve the hasData status from the db", ex);
} }
for (Report report : reports) { for (Report report : reports) {
eventPublisher.publish(new AutopsyEvent(Events.REPORT_DELETED.toString(), report, null)); eventPublisher.publish(new AutopsyEvent(Events.REPORT_DELETED.toString(), report, null));
} }
} }
/** /**
@ -3538,17 +3478,17 @@ public class Case {
} }
} }
/** /**
* Initialize the hasData and hasDataSource parameters by checking the * Initialize the hasData and hasDataSource parameters by checking the
* database. * database.
* *
* hasDataSource will be true if any data Source exists the db. * hasDataSource will be true if any data Source exists the db.
* *
* hasData will be true if hasDataSource is true or if there are entries * hasData will be true if hasDataSource is true or if there are entries in
* in the tsk_object or tsk_host tables. * the tsk_object or tsk_host tables.
* *
* @throws TskCoreException * @throws TskCoreException
*/ */
private void updateDataParameters() throws TskCoreException { private void updateDataParameters() throws TskCoreException {
hasDataSource = dbHasDataSource(); hasDataSource = dbHasDataSource();
@ -3559,13 +3499,13 @@ public class Case {
hasData = true; hasData = true;
} }
} }
/** /**
* Returns true of there are any data sources in the case database. * Returns true of there are any data sources in the case database.
* *
* @return True if this case as a data source. * @return True if this case as a data source.
* *
* @throws TskCoreException * @throws TskCoreException
*/ */
private boolean dbHasDataSource() throws TskCoreException { private boolean dbHasDataSource() throws TskCoreException {
String query = "SELECT count(*) AS count FROM (SELECT * FROM data_source_info LIMIT 1)t"; String query = "SELECT count(*) AS count FROM (SELECT * FROM data_source_info LIMIT 1)t";
@ -3580,35 +3520,35 @@ public class Case {
throw new TskCoreException("Error accessing case databse", ex); throw new TskCoreException("Error accessing case databse", ex);
} }
} }
/** /**
* Returns true if the case has data. A case has data if there is at least * Returns true if the case has data. A case has data if there is at least
* one row in either the tsk_objects or tsk_hosts table. * one row in either the tsk_objects or tsk_hosts table.
* *
* @return True if there is data in this case. * @return True if there is data in this case.
* *
* @throws TskCoreException * @throws TskCoreException
*/ */
private boolean dbHasData() throws TskCoreException { private boolean dbHasData() throws TskCoreException {
// The LIMIT 1 in the subquery should limit the data returned and // The LIMIT 1 in the subquery should limit the data returned and
// make the overall query more efficent. // make the overall query more efficent.
String query = "SELECT SUM(cnt) total FROM " String query = "SELECT SUM(cnt) total FROM "
+ "(SELECT COUNT(*) AS cnt FROM " + "(SELECT COUNT(*) AS cnt FROM "
+ "(SELECT * FROM tsk_objects LIMIT 1)t " + "(SELECT * FROM tsk_objects LIMIT 1)t "
+ "UNION ALL " + "UNION ALL "
+ "SELECT COUNT(*) AS cnt FROM " + "SELECT COUNT(*) AS cnt FROM "
+ "(SELECT * FROM tsk_hosts LIMIT 1)r) s"; + "(SELECT * FROM tsk_hosts LIMIT 1)r) s";
try (SleuthkitCase.CaseDbQuery dbQuery = caseDb.executeQuery(query)) { try (SleuthkitCase.CaseDbQuery dbQuery = caseDb.executeQuery(query)) {
ResultSet resultSet = dbQuery.getResultSet(); ResultSet resultSet = dbQuery.getResultSet();
if (resultSet.next()) { if (resultSet.next()) {
return resultSet.getLong("total") > 0; return resultSet.getLong("total") > 0;
} else { } else {
return false; return false;
} }
} catch ( SQLException ex) { } catch (SQLException ex) {
logger.log(Level.SEVERE, "Error accessing case database", ex); //NON-NLS logger.log(Level.SEVERE, "Error accessing case database", ex); //NON-NLS
throw new TskCoreException("Error accessing case databse", ex); throw new TskCoreException("Error accessing case databse", ex);
} }
} }
/** /**

View File

@ -23,17 +23,21 @@ import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.datamodel.Host; import org.sleuthkit.datamodel.Host;
/** /**
* Event fired when new hosts are added. * Application events published when hosts have been added to the Sleuth Kit
* data model for a case.
*/ */
public class HostsAddedEvent extends HostsEvent { public final class HostsAddedEvent extends HostsEvent {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** /**
* Main constructor. * Constructs an application event published when hosts have been added to
* @param dataModelObjects The hosts that have been added. * the Sleuth Kit data model for a case.
*
* @param hosts The hosts that have been added.
*/ */
public HostsAddedEvent(List<Host> dataModelObjects) { public HostsAddedEvent(List<Host> hosts) {
super(Case.Events.HOSTS_ADDED.name(), dataModelObjects); super(Case.Events.HOSTS_ADDED.name(), hosts);
} }
} }

View File

@ -0,0 +1,92 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2021 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.casemodule.events;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.datamodel.Host;
import org.sleuthkit.datamodel.Person;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
/**
* Application events published when one or more hosts have been added to a
* person.
*/
public final class HostsAddedToPersonEvent extends TskDataModelChangedEvent<Person, Host> {
private static final long serialVersionUID = 1L;
/**
* Constructs an application event published when one or more hosts have
* been added to a person.
*
* @param person The person.
* @param hosts The hosts.
*/
public HostsAddedToPersonEvent(Person person, List<Host> hosts) {
super(Case.Events.HOSTS_ADDED_TO_PERSON.toString(), Collections.singletonList(person), Person::getPersonId, hosts, Host::getHostId);
}
/**
* Gets the person.
*
* @return The person.
*/
public Person getPerson() {
return getOldValue().get(0);
}
/**
* Gets the hosts.
*
* @return The hosts.
*/
public List<Host> getHosts() {
return getNewValue();
}
@Override
protected List<Person> getOldValueObjects(SleuthkitCase caseDb, List<Long> ids) throws TskCoreException {
List<Person> persons = new ArrayList<>();
for (Long id : ids) {
Optional<Person> person = caseDb.getPersonManager().getPerson(id);
if (person.isPresent()) {
persons.add(person.get());
}
}
return persons;
}
@Override
protected List<Host> getNewValueObjects(SleuthkitCase caseDb, List<Long> ids) throws TskCoreException {
List<Host> hosts = new ArrayList<>();
for (Long id : ids) {
Optional<Host> host = caseDb.getHostManager().getHostById(id);
if (host.isPresent()) {
hosts.add(host.get());
}
}
return hosts;
}
}

View File

@ -20,20 +20,32 @@ package org.sleuthkit.autopsy.casemodule.events;
import java.util.List; import java.util.List;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.datamodel.Host;
/** /**
* Event fired when hosts are removed. * Application events published when hosts have been deleted from the Sleuth
* Kit data model for a case.
*/ */
public class HostsRemovedEvent extends HostsEvent { public final class HostsDeletedEvent extends TskDataModelObjectsDeletedEvent {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** /**
* Main constructor. * Constructs an application event published when hosts have been deleted
* @param dataModelObjects The list of hosts that have been deleted. * from the Sleuth Kit data model for a case.
*
* @param hostIds The host IDs of the deleted hosts.
*/ */
public HostsRemovedEvent(List<Host> dataModelObjects) { public HostsDeletedEvent(List<Long> hostIds) {
super(Case.Events.HOSTS_DELETED.name(), dataModelObjects); super(Case.Events.HOSTS_DELETED.name(), hostIds);
} }
/**
* Gets the host IDs of the hosts that have been deleted.
*
* @return The host IDs.
*/
public List<Long> getHostIds() {
return getOldValue();
}
} }

View File

@ -19,71 +19,51 @@
package org.sleuthkit.autopsy.casemodule.events; package org.sleuthkit.autopsy.casemodule.events;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.stream.Collectors;
import org.sleuthkit.datamodel.Host; import org.sleuthkit.datamodel.Host;
import org.sleuthkit.datamodel.HostManager;
import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
/** /**
* Base event class for when something pertaining to hosts changes. * A base class for application events published when hosts in the Sleuth Kit
* data model for a case have been added or updated.
*/ */
public class HostsEvent extends TskDataModelChangeEvent<Host> { public class HostsEvent extends TskDataModelChangedEvent<Host, Host> {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** /**
* Retrieves a list of ids from a list of hosts. * Constructs the base class part of an application event published when
* * hosts in the Sleuth Kit data model for a case have been added or updated.
* @param hosts The hosts.
* @return The list of ids.
*/
private static List<Long> getIds(List<Host> hosts) {
return getSafeList(hosts).stream()
.filter(h -> h != null)
.map(h -> h.getHostId()).collect(Collectors.toList());
}
/**
* Returns the hosts or an empty list.
*
* @param hosts The host list.
* @return The host list or an empty list if the parameter is null.
*/
private static List<Host> getSafeList(List<Host> hosts) {
return hosts == null ? Collections.emptyList() : hosts;
}
/**
* Main constructor.
* *
* @param eventName The name of the Case.Events enum value for the event * @param eventName The name of the Case.Events enum value for the event
* type. * type.
* @param dataModelObjects The list of hosts for the event. * @param hosts The hosts.
*/ */
protected HostsEvent(String eventName, List<Host> dataModelObjects) { HostsEvent(String eventName, List<Host> hosts) {
super(eventName, getIds(dataModelObjects), new ArrayList<>(getSafeList(dataModelObjects))); super(eventName, null, null, hosts, Host::getHostId);
}
/**
* Gets the hosts that have been added or updated.
*
* @return The hosts.
*/
public List<Host> getHosts() {
return getNewValue();
} }
@Override @Override
protected List<Host> getDataModelObjects(SleuthkitCase caseDb, List<Long> ids) throws TskCoreException { protected List<Host> getNewValueObjects(SleuthkitCase caseDb, List<Long> ids) throws TskCoreException {
HostManager hostManager = caseDb.getHostManager(); List<Host> hosts = new ArrayList<>();
List<Host> toRet = new ArrayList<>(); for (Long id : ids) {
if (ids != null) { Optional<Host> host = caseDb.getHostManager().getHostById(id);
for (Long id : ids) { if (host.isPresent()) {
if (id == null) { hosts.add(host.get());
continue;
}
Optional<Host> thisHostOpt = hostManager.getHostById(id);
thisHostOpt.ifPresent((h) -> toRet.add(h));
} }
} }
return hosts;
return toRet;
} }
} }

View File

@ -0,0 +1,85 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2021 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.casemodule.events;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.datamodel.Host;
import org.sleuthkit.datamodel.Person;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
/**
* Application events published when one or more hosts have been removed from a
* person.
*/
public class HostsRemovedFromPersonEvent extends TskDataModelChangedEvent<Person, Long> {
private static final long serialVersionUID = 1L;
/**
* Constructs an application event published when one or more hosts have
* been removed from a person.
*
* @param person The person.
* @param hostIds The host IDs of the removed hosts.
*/
public HostsRemovedFromPersonEvent(Person person, List<Long> hostIds) {
super(Case.Events.HOSTS_REMOVED_FROM_PERSON.toString(), Collections.singletonList(person), Person::getPersonId, hostIds, (id -> id));
}
/**
* Gets the person.
*
* @return The person.
*/
public Person getPerson() {
return getOldValue().get(0);
}
/**
* Gets the host IDs of the removed hosts.
*
* @return The host IDs.
*/
public List<Long> getHostIds() {
return getNewValue();
}
@Override
protected List<Person> getOldValueObjects(SleuthkitCase caseDb, List<Long> ids) throws TskCoreException {
List<Person> persons = new ArrayList<>();
for (Long id : ids) {
Optional<Person> person = caseDb.getPersonManager().getPerson(id);
if (person.isPresent()) {
persons.add(person.get());
}
}
return persons;
}
@Override
protected List<Long> getNewValueObjects(SleuthkitCase caseDb, List<Long> ids) throws TskCoreException {
return ids;
}
}

View File

@ -23,19 +23,21 @@ import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.datamodel.Host; import org.sleuthkit.datamodel.Host;
/** /**
* Event fired when hosts are changed. * Application events published when hosts in the Sleuth Kit data model for
* a case have been updated.
*/ */
public class HostsChangedEvent extends HostsEvent { public class HostsUpdatedEvent extends HostsEvent {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** /**
* Main constructor. * Constructs an application event published when hosts in the Sleuth Kit
* data model for a case have been updated.
* *
* @param dataModelObjects The new values for the hosts that have been * @param hosts The updated persons.
* changed.
*/ */
public HostsChangedEvent(List<Host> dataModelObjects) { public HostsUpdatedEvent(List<Host> hosts) {
super(Case.Events.HOSTS_CHANGED.name(), dataModelObjects); super(Case.Events.HOSTS_UPDATED.name(), hosts);
} }
} }

View File

@ -1,37 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2021 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.casemodule.events;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.events.AutopsyEvent;
/**
* Event published when an OsAccount is deleted.
*
* oldValue will contain the objectId of the account that was removed. newValue
* will be null.
*/
public final class OsAccountDeletedEvent extends AutopsyEvent {
private static final long serialVersionUID = 1L;
public OsAccountDeletedEvent(Long osAccountObjectId) {
super(Case.Events.OS_ACCOUNT_REMOVED.toString(), osAccountObjectId, null);
}
}

View File

@ -1,64 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2021 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.casemodule.events;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.sleuthkit.datamodel.OsAccount;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
/**
* Parent class for specific OsAccount event classes.
*/
class OsAccountEvent extends TskDataModelChangeEvent<OsAccount> {
private static final long serialVersionUID = 1L;
/**
* Construct a new OsAccountEvent.
*
* @param eventName The name of the event.
* @param account The OsAccount the event applies to.
*/
OsAccountEvent(String eventName, OsAccount account) {
super(eventName, Stream.of(account.getId()).collect(Collectors.toList()), Stream.of(account).collect(Collectors.toList()));
}
/**
* Returns the OsAccount that changed.
*
* @return The OsAccount that was changed.
*/
public OsAccount getOsAccount() {
List<OsAccount> accounts = getNewValue();
return accounts.get(0);
}
@Override
protected List<OsAccount> getDataModelObjects(SleuthkitCase caseDb, List<Long> ids) throws TskCoreException {
Long id = ids.get(0);
OsAccount account = caseDb.getOsAccountManager().getOsAccountByObjectId(id);
List<OsAccount> accounts = new ArrayList<>();
accounts.add(account);
return accounts;
}
}

View File

@ -18,17 +18,26 @@
*/ */
package org.sleuthkit.autopsy.casemodule.events; package org.sleuthkit.autopsy.casemodule.events;
import org.sleuthkit.autopsy.casemodule.Case; import java.util.List;
import static org.sleuthkit.autopsy.casemodule.Case.Events.OS_ACCOUNTS_ADDED;
import org.sleuthkit.datamodel.OsAccount; import org.sleuthkit.datamodel.OsAccount;
/** /**
* Event published when an OsAccount is updated. * An application event published when OS accounts are added to the Sleuth Kit
* data model for a case.
*/ */
public final class OsAccountChangedEvent extends OsAccountEvent { public final class OsAccountsAddedEvent extends OsAccountsEvent {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public OsAccountChangedEvent(OsAccount account) { /**
super(Case.Events.OS_ACCOUNT_CHANGED.toString(), account); * Constructs an application event published when OS accounts are added to
} * the Sleuth Kit data model for a case.
*
* @param osAccounts The OS accounts that were added.
*/
public OsAccountsAddedEvent(List<OsAccount> osAccounts) {
super(OS_ACCOUNTS_ADDED.toString(), osAccounts);
}
} }

View File

@ -0,0 +1,51 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2021 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.casemodule.events;
import java.util.List;
import org.sleuthkit.autopsy.casemodule.Case;
/**
* An application event published when OS accounts have been deleted from the
* Sleuth Kit data model for a case.
*/
public final class OsAccountsDeletedEvent extends TskDataModelObjectsDeletedEvent {
private static final long serialVersionUID = 1L;
/**
* Constructs an application event published when OS accounts have been
* deleted from the Sleuth Kit data model for a case.
*
* @param osAccountObjectIds TSK object IDs of the deleted accounts.
*/
public OsAccountsDeletedEvent(List<Long> osAccountObjectIds) {
super(Case.Events.OS_ACCOUNTS_DELETED.toString(), osAccountObjectIds);
}
/**
* Gets the Sleuth Kit object IDs of the deleted OS accounts.
*
* @return The object IDs.
*/
List<Long> getOsAccountObjectIds() {
return getOldValue();
}
}

View File

@ -0,0 +1,66 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2021 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.casemodule.events;
import java.util.ArrayList;
import java.util.List;
import org.sleuthkit.datamodel.OsAccount;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
/**
* A base class for application events published when OS accounts in the Sleuth
* Kit data model for a case have been added or updated.
*/
class OsAccountsEvent extends TskDataModelChangedEvent<OsAccount, OsAccount> {
private static final long serialVersionUID = 1L;
/**
* Constructs the base class part of an application event published when
* OS accounts in the Sleuth Kit data model for a case have been added or
* updated.
*
* @param eventName The name of the Case.Events enum value for the event
* type.
* @param account The OS accounts.
*/
OsAccountsEvent(String eventName, List<OsAccount> osAccounts) {
super(eventName, null, null, osAccounts, OsAccount::getId);
}
/**
* Gets the OS accounts that have been added or updated.
*
* @return The OS accounts.
*/
public List<OsAccount> getOsAccounts() {
return getNewValue();
}
@Override
protected List<OsAccount> getNewValueObjects(SleuthkitCase caseDb, List<Long> ids) throws TskCoreException {
List<OsAccount> osAccounts = new ArrayList<>();
for (Long id : ids) {
osAccounts.add(caseDb.getOsAccountManager().getOsAccountByObjectId(id));
}
return osAccounts;
}
}

View File

@ -18,18 +18,26 @@
*/ */
package org.sleuthkit.autopsy.casemodule.events; package org.sleuthkit.autopsy.casemodule.events;
import java.util.List;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.datamodel.OsAccount; import org.sleuthkit.datamodel.OsAccount;
/** /**
* Event published when an OsAccount is added to a case. * An application event published when OS accounts in the Sleuth Kit data model
* for a case have been updated.
*/ */
public final class OsAccountAddedEvent extends OsAccountEvent { public final class OsAccountsUpdatedEvent extends OsAccountsEvent {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public OsAccountAddedEvent(OsAccount account) {
super(Case.Events.OS_ACCOUNT_ADDED.toString(), account);
}
/**
* Constructs an application event published when OS accounts in the Sleuth
* Kit data model for a case have been updated.
*
* @param osAccounts The OS accounts that were updated.
*/
public OsAccountsUpdatedEvent(List<OsAccount> osAccounts) {
super(Case.Events.OS_ACCOUNTS_UPDATED.toString(), osAccounts);
}
} }

View File

@ -23,17 +23,21 @@ import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.datamodel.Person; import org.sleuthkit.datamodel.Person;
/** /**
* Event fired when new persons are added. * An application event published when persons have been added to the Sleuth Kit
* data model for a case.
*/ */
public class PersonsAddedEvent extends PersonsEvent { public class PersonsAddedEvent extends PersonsEvent {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** /**
* Main constructor. * Constructs an application event published when persons have been added to
* @param dataModelObjects The persons that have been added. * the Sleuth Kit data model for a case.
*
* @param persons The persons that have been added.
*/ */
public PersonsAddedEvent(List<Person> dataModelObjects) { public PersonsAddedEvent(List<Person> persons) {
super(Case.Events.PERSONS_ADDED.name(), dataModelObjects); super(Case.Events.PERSONS_ADDED.name(), persons);
} }
} }

View File

@ -20,20 +20,32 @@ package org.sleuthkit.autopsy.casemodule.events;
import java.util.List; import java.util.List;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.datamodel.Person;
/** /**
* Event fired when persons are removed. * Application events published when persons have been deleted from the Sleuth
* Kit data model for a case.
*/ */
public class PersonsDeletedEvent extends PersonsEvent { public class PersonsDeletedEvent extends TskDataModelObjectsDeletedEvent {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** /**
* Main constructor. * Constructs an application event published when persons have been deleted
* @param dataModelObjects The list of persons that have been deleted. * from the Sleuth Kit data model for a case.
*
* @param personIds The IDs of the persons that have been deleted.
*/ */
public PersonsDeletedEvent(List<Person> dataModelObjects) { public PersonsDeletedEvent(List<Long> personIds) {
super(Case.Events.PERSONS_DELETED.name(), dataModelObjects); super(Case.Events.PERSONS_DELETED.name(), personIds);
} }
/**
* Gets the person IDs of the persons that have been deleted.
*
* @return The person IDs.
*/
List<Long> getPersonIds() {
return getOldValue();
}
} }

View File

@ -19,69 +19,52 @@
package org.sleuthkit.autopsy.casemodule.events; package org.sleuthkit.autopsy.casemodule.events;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.stream.Collectors;
import org.sleuthkit.datamodel.Person; import org.sleuthkit.datamodel.Person;
import org.sleuthkit.datamodel.PersonManager;
import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
/** /**
* Base event class for when something pertaining to persons changes. * A base class for application events published when persons in the Sleuth Kit
* data model for a case have been added or updated.
*/ */
public class PersonsEvent extends TskDataModelChangeEvent<Person> { public class PersonsEvent extends TskDataModelChangedEvent<Person, Person> {
private static final long serialVersionUID = 1L;
/** /**
* Retrieves a list of ids from a list of persons. * Constructs the base class part of an application event published when
* * persons in the Sleuth Kit data model for a case have been added or
* @param persons The persons. * updated.
* @return The list of ids.
*/
private static List<Long> getIds(List<Person> persons) {
return getSafeList(persons).stream()
.filter(h -> h != null)
.map(h -> h.getPersonId()).collect(Collectors.toList());
}
/**
* Returns the persons or an empty list.
*
* @param persons The person list.
* @return The person list or an empty list if the parameter is null.
*/
private static List<Person> getSafeList(List<Person> persons) {
return persons == null ? Collections.emptyList() : persons;
}
/**
* Main constructor.
* *
* @param eventName The name of the Case.Events enum value for the event * @param eventName The name of the Case.Events enum value for the event
* type. * type.
* @param dataModelObjects The list of persons for the event. * @param persons The persons.
*/ */
protected PersonsEvent(String eventName, List<Person> dataModelObjects) { PersonsEvent(String eventName, List<Person> persons) {
super(eventName, getIds(dataModelObjects), new ArrayList<>(getSafeList(dataModelObjects))); super(eventName, null, null, persons, Person::getPersonId);
}
/**
* Gets the persons that have been added or updated.
*
* @return The persons.
*/
public List<Person> getPersons() {
return getNewValue();
} }
@Override @Override
protected List<Person> getDataModelObjects(SleuthkitCase caseDb, List<Long> ids) throws TskCoreException { protected List<Person> getNewValueObjects(SleuthkitCase caseDb, List<Long> ids) throws TskCoreException {
PersonManager personManager = caseDb.getPersonManager(); List<Person> persons = new ArrayList<>();
List<Person> toRet = new ArrayList<>(); for (Long id : ids) {
if (ids != null) { Optional<Person> person = caseDb.getPersonManager().getPerson(id);
for (Long id : ids) { if (person.isPresent()) {
if (id == null) { persons.add(person.get());
continue;
}
Optional<Person> thisPersonOpt = personManager.getPerson(id);
thisPersonOpt.ifPresent((h) -> toRet.add(h));
} }
} }
return persons;
return toRet;
} }
} }

View File

@ -23,19 +23,21 @@ import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.datamodel.Person; import org.sleuthkit.datamodel.Person;
/** /**
* Event fired when persons are changed. * Application events published when persons in the Sleuth Kit data model for
* a case have been updated.
*/ */
public class PersonsChangedEvent extends PersonsEvent { public class PersonsUpdatedEvent extends PersonsEvent {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** /**
* Main constructor. * Constructs an application event published when persons in the Sleuth Kit
* data model for a case have been updated.
* *
* @param dataModelObjects The new values for the persons that have been * @param persons The updated persons.
* changed.
*/ */
public PersonsChangedEvent(List<Person> dataModelObjects) { public PersonsUpdatedEvent(List<Person> persons) {
super(Case.Events.PERSONS_CHANGED.name(), dataModelObjects); super(Case.Events.PERSONS_UPDATED.name(), persons);
} }
} }

View File

@ -28,33 +28,38 @@ import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
/** /**
* Event published when a report is added to a case. * An application event published when a report is added to a case.
*/ */
public final class ReportAddedEvent extends TskDataModelChangeEvent<Report> { public final class ReportAddedEvent extends TskDataModelChangedEvent<Report, Report> {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** /**
* Constructs an event published when a report is added to a case. * Constructs an application event published when a report is added to a
* case.
* *
* @param report The data source that was added. * @param report The report that was added.
*/ */
public ReportAddedEvent(Report report) { public ReportAddedEvent(Report report) {
super(Case.Events.REPORT_ADDED.toString(), Stream.of(report.getId()).collect(Collectors.toList()), Stream.of(report).collect(Collectors.toList())); super(Case.Events.REPORT_ADDED.toString(), null, null, Stream.of(report).collect(Collectors.toList()), Report::getId);
} }
/**
* Gets the reoprt that was added to the case.
*
* @return The report.
*/
public Report getReport() { public Report getReport() {
List<Report> reports = getNewValue(); List<Report> reports = getNewValue();
return reports.get(0); return reports.get(0);
} }
@Override @Override
protected List<Report> getDataModelObjects(SleuthkitCase caseD, List<Long> ids) throws TskCoreException { protected List<Report> getNewValueObjects(SleuthkitCase caseDb, List<Long> ids) throws TskCoreException {
Long id = ids.get(0); Long id = ids.get(0);
Report report = caseD.getReportById(id);
List<Report> reports = new ArrayList<>(); List<Report> reports = new ArrayList<>();
reports.add(report); reports.add(caseDb.getReportById(id));
return reports; return reports;
} }
} }

View File

@ -1,124 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2021 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.casemodule.events;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.events.AutopsyEvent;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
/**
* An application event generic used as a superclass for events published when
* something changes in the Sleuth Kit Data Model for a case.
*
* @param <T> A Sleuth Kit Data Model object type.
*/
public abstract class TskDataModelChangeEvent<T> extends AutopsyEvent {
private static final long serialVersionUID = 1L;
private static final Logger logger = Logger.getLogger(TskDataModelChangeEvent.class.getName());
private final List<Long> dataModelObjectIds;
private transient List<T> dataModelObjects;
/**
* Constructs an application event generic used as a superclass for events
* published when something changes in the Sleuth Kit Data Model for a case.
*
* @param eventName The event name.
* @param dataModelObjectIds The unique numeric IDs (TSK object IDs, case
* database row IDs, etc.) of the Sleuth Kit Data
* Model objects associated with this application
* event.
* @param dataModelObjects The Sleuth Kit Data Model objects associated
* with this application event
*/
protected TskDataModelChangeEvent(String eventName, List<Long> dataModelObjectIds, List<T> dataModelObjects) {
super(eventName, null, null);
this.dataModelObjectIds = dataModelObjectIds;
this.dataModelObjects = dataModelObjects;
if (eventName == null) {
throw new IllegalArgumentException("eventName is null");
}
if (dataModelObjectIds == null) {
throw new IllegalArgumentException("dataModelObjectIds is null");
}
if (dataModelObjects == null) {
throw new IllegalArgumentException("dataModelObjects is null");
}
}
/**
* Gets the unique numeric IDs (TSK object IDs, case database row IDs, etc.)
* of the Sleuth Kit Data Model objects associated with this application
* event.
*
* @return The unique IDs.
*/
public final List<Long> getDataModelObjectIds() {
return Collections.unmodifiableList(dataModelObjectIds);
}
/**
* Gets the Sleuth Kit Data Model objects associated with this application
* event.
*
* @return The objects.
*/
@Override
public List<T> getNewValue() {
/*
* If this event came from another host collaborating on a multi-user
* case, the transient list of Sleuth Kit Data Model objects will be
* null and will need to be reconstructed on the current host.
*/
if (dataModelObjects == null) {
try {
Case currentCase = Case.getCurrentCaseThrows();
SleuthkitCase caseDb = currentCase.getSleuthkitCase();
dataModelObjects = getDataModelObjects(caseDb, dataModelObjectIds);
} catch (NoCurrentCaseException | TskCoreException ex) {
logger.log(Level.SEVERE, String.format("Error geting TSK Data Model objects for %s event (%s)", getPropertyName(), getSourceType()), ex);
return Collections.emptyList();
}
}
return Collections.unmodifiableList(dataModelObjects);
}
/**
* Gets the Sleuth Kit Data Model objects associated with this application
* event.
*
* @param caseDb The case database.
* @param ids The unique, numeric IDs (TSK object IDs, case database row
* IDs, etc.) of the Sleuth Kit Data Model objects.
*
* @return The objects.
*
* @throws org.sleuthkit.datamodel.TskCoreException If there is an error
* getting the Sleuth Kit
* Data Model objects.
*/
abstract protected List<T> getDataModelObjects(SleuthkitCase caseDb, List<Long> ids) throws TskCoreException;
}

View File

@ -0,0 +1,205 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2021 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.casemodule.events;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import java.util.logging.Level;
import java.util.stream.Collectors;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.events.AutopsyEvent;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
/**
* An abstract base class for application events published when one or more
* Sleuth Kit Data Model objects for a case change in some way.
*
* This class extends AutopsyEvent. The AutopsyEvent class extends
* PropertyChangeEvent to integrate with legacy use of JavaBeans
* PropertyChangeEvents and PropertyChangeListeners as an application event
* publisher-subcriber mechanism. Subclasses need to decide what constitutes
* "old" and "new" objects for them and are encouraged to provide getters for
* these values that do not require clients to cast the return values.
*
* The AutopsyEvent class implements Serializable to allow local event instances
* to be published to other Autopsy nodes over a network in serialized form. TSK
* Data Model objects are generally not serializable because they encapsulate a
* reference to a SleuthkitCase object that represents the case database and
* which has local JDBC Connection objects. For this reason, this class supports
* serialization of the unique numeric IDs (TSK object IDs, case database row
* IDs, etc.) of the subject TSK Data Model objects and the "reconstruction" of
* those objects on other Autopsy nodes by querying the case database by unique
* ID.
*
* @param <T> The Sleuth Kit Data Model object type of the "old" data model
* objects.
* @param <U> The Sleuth Kit Data Model object type of the "new" data model
* objects.
*/
public abstract class TskDataModelChangedEvent<T, U> extends AutopsyEvent {
private static final long serialVersionUID = 1L;
private static final Logger logger = Logger.getLogger(TskDataModelChangedEvent.class.getName());
private final boolean hasOldValue;
private final List<Long> oldValueIds;
private transient List<T> oldValueObjects;
private final boolean hasNewValue;
private final List<Long> newValueIds;
private transient List<U> newValueObjects;
/**
* Constructs the base class part for application events published when one
* or more Sleuth Kit Data Model objects for a case change in some way.
*
* @param eventName The event name.
* @param oldValueObjects A list of he Data Model objects that have been
* designated as the "old" objects in the event.
* May be null.
* @param oldValueGetIdMethod A method that can be applied to the "old" data
* model objects to get their unique numeric IDs
* (TSK object IDs, case database row IDs, etc.).
* May be null if there are no "old" objects.
* @param newValueObjects A list of he Data Model objects that have been
* designated as the "new" objects in the event.
* May be null.
* @param newValueGetIdMethod A method that can be applied to the "new" data
* model objects to get their unique numeric IDs
* (TSK object IDs, case database row IDs, etc.).
* May be null if there are no "new" objects.
*/
protected TskDataModelChangedEvent(String eventName, List<T> oldValueObjects, Function<T, Long> oldValueGetIdMethod, List<U> newValueObjects, Function<U, Long> newValueGetIdMethod) {
super(eventName, null, null);
oldValueIds = new ArrayList<>();
this.oldValueObjects = new ArrayList<>();
if (oldValueObjects != null) {
hasOldValue = true;
oldValueIds.addAll(oldValueObjects.stream()
.map(o -> oldValueGetIdMethod.apply(o))
.collect(Collectors.toList()));
this.oldValueObjects.addAll(oldValueObjects);
} else {
hasOldValue = false;
}
newValueIds = new ArrayList<>();
this.newValueObjects = new ArrayList<>();
if (newValueObjects != null) {
hasNewValue = true;
newValueIds.addAll(newValueObjects.stream()
.map(o -> newValueGetIdMethod.apply(o))
.collect(Collectors.toList()));
this.newValueObjects.addAll(newValueObjects);
} else {
hasNewValue = false;
}
}
/**
* Gets a list of the Data Model objects that have been designated as the
* "old" objects in the event.
*
* @return The list of the "old" data model objects. May be empty.
*/
@Override
public List<T> getOldValue() {
if (hasOldValue) {
if (oldValueObjects == null) {
try {
Case currentCase = Case.getCurrentCaseThrows();
SleuthkitCase caseDb = currentCase.getSleuthkitCase();
oldValueObjects = getOldValueObjects(caseDb, oldValueIds);
} catch (NoCurrentCaseException | TskCoreException ex) {
logger.log(Level.SEVERE, String.format("Error getting oldValue() TSK Data Model objects for %s event (%s)", getPropertyName(), getSourceType()), ex);
return Collections.emptyList();
}
}
return Collections.unmodifiableList(oldValueObjects);
} else {
return Collections.emptyList();
}
}
/**
* Gets a list of the Data Model objects that have been designated as the
* "new" objects in the event.
*
* @return The list of the "new" data model objects. May be empty.
*/
@Override
public List<U> getNewValue() {
if (hasNewValue) {
if (newValueObjects == null) {
try {
Case currentCase = Case.getCurrentCaseThrows();
SleuthkitCase caseDb = currentCase.getSleuthkitCase();
newValueObjects = getNewValueObjects(caseDb, newValueIds);
} catch (NoCurrentCaseException | TskCoreException ex) {
logger.log(Level.SEVERE, String.format("Error getting newValue() TSK Data Model objects for %s event (%s)", getPropertyName(), getSourceType()), ex);
return Collections.emptyList();
}
}
return Collections.unmodifiableList(newValueObjects);
} else {
return Collections.emptyList();
}
}
/**
* Reconstructs the "old" Sleuth Kit Data Model objects associated with this
* application event, if any, using the given unique numeric IDs (TSK object
* IDs, case database row IDs, etc.) to query the given case database.
*
* @param caseDb The case database.
* @param ids The unique, numeric IDs (TSK object IDs, case database row
* IDs, etc.) of the Sleuth Kit Data Model objects.
*
* @return The objects.
*
* @throws org.sleuthkit.datamodel.TskCoreException If there is an error
* getting the Sleuth Kit
* Data Model objects.
*/
protected List<T> getOldValueObjects(SleuthkitCase caseDb, List<Long> ids) throws TskCoreException {
return Collections.emptyList();
}
/**
* Reconstructs the "new" Sleuth Kit Data Model objects associated with this
* application event, if any, using the given unique numeric IDs (TSK object
* IDs, case database row IDs, etc.) to query the given case database.
*
* @param caseDb The case database.
* @param ids The unique, numeric IDs (TSK object IDs, case database row
* IDs, etc.) of the Sleuth Kit Data Model objects.
*
* @return The objects.
*
* @throws org.sleuthkit.datamodel.TskCoreException If there is an error
* getting the Sleuth Kit
* Data Model objects.
*/
protected List<U> getNewValueObjects(SleuthkitCase caseDb, List<Long> ids) throws TskCoreException {
return Collections.emptyList();
}
}

View File

@ -0,0 +1,60 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2021 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.casemodule.events;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.sleuthkit.autopsy.events.AutopsyEvent;
/**
* An abstract base class for application events published when one or more
* Sleuth Kit Data Model objects for a case have been deleted.
*
* This class extends AutopsyEvent. The AutopsyEvent class extends
* PropertyChangeEvent to integrate with legacy use of JavaBeans
* PropertyChangeEvents and PropertyChangeListeners as an application event
* publisher-subcriber mechanism. Subclasses need to decide what constitutes
* "old" and "new" objects for them.
*
* For this class the "old" values are the unique numeric IDs (TSK object IDs,
* case database row IDs, etc.) of the deleted TSK Data Model objects. There are
* no "new" values. Subclasses are encouraged to provide less generic getters
* with descriptive names for the unique IDs than the override of the inherited
* getOldValue() method below. These getters can be implemented by delegating to
* getOldValue().
*/
public class TskDataModelObjectsDeletedEvent extends AutopsyEvent {
private static final long serialVersionUID = 1L;
private final List<Long> deletedObjectIds;
protected TskDataModelObjectsDeletedEvent(String eventName, List<Long> deletedObjectIds) {
super(eventName, null, null);
this.deletedObjectIds = new ArrayList<>();
this.deletedObjectIds.addAll(deletedObjectIds);
}
@Override
public List<Long> getOldValue() {
return Collections.unmodifiableList(deletedObjectIds);
}
}

View File

@ -5,10 +5,7 @@ CentralRepoCommentDialog.title.addEditCentralRepoComment=Add/Edit Central Reposi
OpenIDE-Module-Name=Central Repository OpenIDE-Module-Name=Central Repository
OpenIDE-Module-Display-Category=Ingest Module OpenIDE-Module-Display-Category=Ingest Module
OpenIDE-Module-Short-Description=Central Repository Ingest Module OpenIDE-Module-Short-Description=Central Repository Ingest Module
OpenIDE-Module-Long-Description=\ OpenIDE-Module-Long-Description=Central Repository ingest module and central database. \n\nThe Central Repository ingest module stores attributes of artifacts matching selected correlation types into a central database.\nStored attributes are used in future cases to correlate and analyzes files and artifacts during ingest.
Central Repository ingest module and central database. \n\n\
The Central Repository ingest module stores attributes of artifacts matching selected correlation types into a central database.\n\
Stored attributes are used in future cases to correlate and analyzes files and artifacts during ingest.
CentralRepoCommentDialog.commentLabel.text=Comment: CentralRepoCommentDialog.commentLabel.text=Comment:
CentralRepoCommentDialog.okButton.text=&OK CentralRepoCommentDialog.okButton.text=&OK
CentralRepoCommentDialog.cancelButton.text=C&ancel CentralRepoCommentDialog.cancelButton.text=C&ancel

View File

@ -63,7 +63,7 @@ import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
import org.sleuthkit.datamodel.Score; import org.sleuthkit.datamodel.Score;
import org.sleuthkit.datamodel.Score.MethodCategory; import org.sleuthkit.datamodel.Score.Priority;
import org.sleuthkit.datamodel.Score.Significance; import org.sleuthkit.datamodel.Score.Significance;
/** /**
@ -72,7 +72,7 @@ import org.sleuthkit.datamodel.Score.Significance;
*/ */
@NbBundle.Messages({"IngestEventsListener.ingestmodule.name=Central Repository"}) @NbBundle.Messages({"IngestEventsListener.ingestmodule.name=Central Repository"})
public class IngestEventsListener { public class IngestEventsListener {
private static final Score LIKELY_NOTABLE_SCORE = new Score(Significance.LIKELY_NOTABLE, MethodCategory.AUTO); private static final Score LIKELY_NOTABLE_SCORE = new Score(Significance.LIKELY_NOTABLE, Priority.NORMAL);
private static final Logger LOGGER = Logger.getLogger(CorrelationAttributeInstance.class.getName()); private static final Logger LOGGER = Logger.getLogger(CorrelationAttributeInstance.class.getName());
private static final Set<IngestManager.IngestJobEvent> INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.DATA_SOURCE_ANALYSIS_COMPLETED); private static final Set<IngestManager.IngestJobEvent> INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.DATA_SOURCE_ANALYSIS_COMPLETED);
private static final Set<IngestManager.IngestModuleEvent> INGEST_MODULE_EVENTS_OF_INTEREST = EnumSet.of(DATA_ADDED); private static final Set<IngestManager.IngestModuleEvent> INGEST_MODULE_EVENTS_OF_INTEREST = EnumSet.of(DATA_ADDED);

View File

@ -67,7 +67,7 @@ import org.sleuthkit.datamodel.Score;
final class CentralRepoIngestModule implements FileIngestModule { final class CentralRepoIngestModule implements FileIngestModule {
private static final String MODULE_NAME = CentralRepoIngestModuleFactory.getModuleName(); private static final String MODULE_NAME = CentralRepoIngestModuleFactory.getModuleName();
private static final Score LIKELY_NOTABLE_SCORE = new Score(Score.Significance.LIKELY_NOTABLE, Score.MethodCategory.AUTO); private static final Score LIKELY_NOTABLE_SCORE = new Score(Score.Significance.LIKELY_NOTABLE, Score.Priority.NORMAL);
static final boolean DEFAULT_FLAG_TAGGED_NOTABLE_ITEMS = false; static final boolean DEFAULT_FLAG_TAGGED_NOTABLE_ITEMS = false;
static final boolean DEFAULT_FLAG_PREVIOUS_DEVICES = false; static final boolean DEFAULT_FLAG_PREVIOUS_DEVICES = false;
static final boolean DEFAULT_CREATE_CR_PROPERTIES = true; static final boolean DEFAULT_CREATE_CR_PROPERTIES = true;

View File

@ -3,13 +3,7 @@ Installer.closing.confirmationDialog.title=Ingest is Running
# {0} - exception message # {0} - exception message
Installer.closing.messageBox.caseCloseExceptionMessage=Error closing case: {0} Installer.closing.messageBox.caseCloseExceptionMessage=Error closing case: {0}
OpenIDE-Module-Display-Category=Infrastructure OpenIDE-Module-Display-Category=Infrastructure
OpenIDE-Module-Long-Description=\ OpenIDE-Module-Long-Description=This is the core Autopsy module.\n\nThe module contains the core components needed for the bare application to run; the RCP platform, windowing GUI, sleuthkit bindings, datamodel / storage, explorer, result viewers, content viewers, ingest framework, reporting, and core tools, such as the file search.\n\nThe framework included in the module contains APIs for developing modules for ingest, viewers and reporting. The modules can be deployed as Plugins using the Autopsy plugin installer.\nThis module should not be uninstalled - without it, Autopsy will not run.\n\nFor more information, see http://www.sleuthkit.org/autopsy/
This is the core Autopsy module.\n\n\
The module contains the core components needed for the bare application to run; the RCP platform, windowing GUI, sleuthkit bindings, datamodel / storage, explorer, result viewers, content viewers, ingest framework, reporting, and core tools, such as the file search.\n\n\
The framework included in the module contains APIs for developing modules for ingest, viewers and reporting. \
The modules can be deployed as Plugins using the Autopsy plugin installer.\n\
This module should not be uninstalled - without it, Autopsy will not run.\n\n\
For more information, see http://www.sleuthkit.org/autopsy/
OpenIDE-Module-Name=Autopsy-Core OpenIDE-Module-Name=Autopsy-Core
OpenIDE-Module-Short-Description=Autopsy Core Module OpenIDE-Module-Short-Description=Autopsy Core Module
org_sleuthkit_autopsy_core_update_center=http://sleuthkit.org/autopsy/updates.xml org_sleuthkit_autopsy_core_update_center=http://sleuthkit.org/autopsy/updates.xml

View File

@ -75,9 +75,9 @@ DataContentViewerHex.totalPageLabel.text_1=100
DataContentViewerHex.pageLabel2.text=Page DataContentViewerHex.pageLabel2.text=Page
# Product Information panel # Product Information panel
LBL_Description=<div style=\"font-size: 12pt; font-family: Verdana, 'Verdana CE', Arial, 'Arial CE', 'Lucida Grande CE', lucida, 'Helvetica CE', sans-serif;\">\n <b>Product Version:</b> {0} ({9}) <br><b>Sleuth Kit Version:</b> {7} <br><b>Netbeans RCP Build:</b> {8} <br> <b>Java:</b> {1}; {2}<br> <b>System:</b> {3}; {4}; {5}<br><b>Userdir:</b> {6}</div> LBL_Description=<div style="font-size: 12pt; font-family: Verdana, 'Verdana CE', Arial, 'Arial CE', 'Lucida Grande CE', lucida, 'Helvetica CE', sans-serif;">\n <b>Product Version:</b> {0} ({9}) <br><b>Sleuth Kit Version:</b> {7} <br><b>Netbeans RCP Build:</b> {8} <br> <b>Java:</b> {1}; {2}<br> <b>System:</b> {3}; {4}; {5}<br><b>Userdir:</b> {6}</div>
Format_OperatingSystem_Value={0} version {1} running on {2} Format_OperatingSystem_Value={0} version {1} running on {2}
LBL_Copyright=<div style\="font-size: 12pt; font-family: Verdana, 'Verdana CE', Arial, 'Arial CE', 'Lucida Grande CE', lucida, 'Helvetica CE', sans-serif; ">Autopsy&trade; is a digital forensics platform based on The Sleuth Kit&trade; and other tools. <br><ul><li>General Information: <a style\="color: \#1E2A60;" href\="http://www.sleuthkit.org">http://www.sleuthkit.org</a>.</li><li>Training: <a style\="color: \#1E2A60;" href\="https://www.autopsy.com/support/training/">https://www.autopsy.com/support/training/</a></li><li>Support: <a style\="color: \#1E2A60;" href\="https://www.sleuthkit.org/support.php">https://www.sleuthkit.org/support.php</a></li></ul>Copyright &copy; 2003-2020. </div> LBL_Copyright=<div style="font-size: 12pt; font-family: Verdana, 'Verdana CE', Arial, 'Arial CE', 'Lucida Grande CE', lucida, 'Helvetica CE', sans-serif; ">Autopsy&trade; is a digital forensics platform based on The Sleuth Kit&trade; and other tools. <br><ul><li>General Information: <a style="color: #1E2A60;" href="http://www.sleuthkit.org">http://www.sleuthkit.org</a>.</li><li>Training: <a style="color: #1E2A60;" href="https://www.autopsy.com/support/training/">https://www.autopsy.com/support/training/</a></li><li>Support: <a style="color: #1E2A60;" href="https://www.sleuthkit.org/support.php">https://www.sleuthkit.org/support.php</a></li></ul>Copyright &copy; 2003-2020. </div>
SortChooser.dialogTitle=Choose Sort Criteria SortChooser.dialogTitle=Choose Sort Criteria
ThumbnailViewChildren.progress.cancelling=(Cancelling) ThumbnailViewChildren.progress.cancelling=(Cancelling)
# {0} - file name # {0} - file name
@ -105,7 +105,7 @@ DataResultViewerThumbnail.pageNextButton.text=
DataResultViewerThumbnail.imagesLabel.text=Images: DataResultViewerThumbnail.imagesLabel.text=Images:
DataResultViewerThumbnail.imagesRangeLabel.text=- DataResultViewerThumbnail.imagesRangeLabel.text=-
DataResultViewerThumbnail.pageNumLabel.text=- DataResultViewerThumbnail.pageNumLabel.text=-
DataResultViewerThumbnail.filePathLabel.text=\ \ \ DataResultViewerThumbnail.filePathLabel.text=\
DataResultViewerThumbnail.goToPageLabel.text=Go to Page: DataResultViewerThumbnail.goToPageLabel.text=Go to Page:
DataResultViewerThumbnail.goToPageField.text= DataResultViewerThumbnail.goToPageField.text=
AdvancedConfigurationDialog.cancelButton.text=Cancel AdvancedConfigurationDialog.cancelButton.text=Cancel

View File

@ -30,9 +30,7 @@ PlatformUtil.getProcVmUsed.sigarNotInit.msg=Cannot get virt mem used, sigar not
PlatformUtil.getProcVmUsed.gen.msg=Cannot get virt mem used, {0} PlatformUtil.getProcVmUsed.gen.msg=Cannot get virt mem used, {0}
PlatformUtil.getJvmMemInfo.usageText=JVM heap usage: {0}, JVM non-heap usage: {1} PlatformUtil.getJvmMemInfo.usageText=JVM heap usage: {0}, JVM non-heap usage: {1}
PlatformUtil.getPhysicalMemInfo.usageText=Physical memory usage (max, total, free): {0}, {1}, {2} PlatformUtil.getPhysicalMemInfo.usageText=Physical memory usage (max, total, free): {0}, {1}, {2}
PlatformUtil.getAllMemUsageInfo.usageText={0}\n\ PlatformUtil.getAllMemUsageInfo.usageText={0}\n{1}\nProcess Virtual Memory: {2}
{1}\n\
Process Virtual Memory: {2}
# {0} - file name # {0} - file name
ReadImageTask.mesageText=Reading image: {0} ReadImageTask.mesageText=Reading image: {0}
StringExtract.illegalStateException.cannotInit.msg=Unicode table not properly initialized, cannot instantiate StringExtract StringExtract.illegalStateException.cannotInit.msg=Unicode table not properly initialized, cannot instantiate StringExtract

View File

@ -1,15 +1,15 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2018 Basis Technology Corp. * Copyright 2018-2021 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -43,34 +43,40 @@ import org.sleuthkit.datamodel.SleuthkitVisitableItem;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
/** /**
* Child factory to create the top level children of the autopsy tree * A child factory to create the top level nodes in the main tree view. These
* * nodes are the child nodes of the invisible root node of the tree. The child
* nodes that are created vary with the view option selected by the user: group
* by data type or group by person/host.
*/ */
public final class AutopsyTreeChildFactory extends ChildFactory.Detachable<Object> { public final class AutopsyTreeChildFactory extends ChildFactory.Detachable<Object> {
private static final Set<Case.Events> LISTENING_EVENTS = EnumSet.of( private static final Set<Case.Events> EVENTS_OF_INTEREST = EnumSet.of(Case.Events.DATA_SOURCE_ADDED,
Case.Events.DATA_SOURCE_ADDED,
Case.Events.HOSTS_ADDED, Case.Events.HOSTS_ADDED,
Case.Events.HOSTS_DELETED, Case.Events.HOSTS_DELETED,
Case.Events.PERSONS_ADDED, Case.Events.PERSONS_ADDED,
Case.Events.PERSONS_DELETED, Case.Events.PERSONS_DELETED,
Case.Events.PERSONS_CHANGED Case.Events.HOSTS_ADDED_TO_PERSON,
Case.Events.HOSTS_REMOVED_FROM_PERSON
); );
private static final Set<String> LISTENING_EVENT_NAMES = LISTENING_EVENTS.stream() private static final Set<String> EVENTS_OF_INTEREST_NAMES = EVENTS_OF_INTEREST.stream()
.map(evt -> evt.name()) .map(evt -> evt.name())
.collect(Collectors.toSet()); .collect(Collectors.toSet());
private static final Logger logger = Logger.getLogger(AutopsyTreeChildFactory.class.getName()); private static final Logger logger = Logger.getLogger(AutopsyTreeChildFactory.class.getName());
/** /**
* Listener for handling DATA_SOURCE_ADDED events. * Listener for application events published when persons and/or hosts are
* added to or deleted from the data model for the current case. If the user
* has selected the group by person/host option for the tree, these events
* mean that the top-level person/host nodes in the tree need to be
* refreshed to reflect the changes.
*/ */
private final PropertyChangeListener pcl = new PropertyChangeListener() { private final PropertyChangeListener pcl = new PropertyChangeListener() {
@Override @Override
public void propertyChange(PropertyChangeEvent evt) { public void propertyChange(PropertyChangeEvent evt) {
String eventType = evt.getPropertyName(); String eventType = evt.getPropertyName();
if (LISTENING_EVENT_NAMES.contains(eventType) if (EVENTS_OF_INTEREST_NAMES.contains(eventType)
&& Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true)) { && Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true)) {
refreshChildren(); refreshChildren();
} }
@ -80,20 +86,28 @@ public final class AutopsyTreeChildFactory extends ChildFactory.Detachable<Objec
@Override @Override
protected void addNotify() { protected void addNotify() {
super.addNotify(); super.addNotify();
Case.addEventTypeSubscriber(LISTENING_EVENTS, pcl); Case.addEventTypeSubscriber(EVENTS_OF_INTEREST, pcl);
} }
@Override @Override
protected void removeNotify() { protected void removeNotify() {
super.removeNotify(); super.removeNotify();
Case.removeEventTypeSubscriber(LISTENING_EVENTS, pcl); Case.removeEventTypeSubscriber(EVENTS_OF_INTEREST, pcl);
} }
/** /**
* Creates keys for the top level children. * Creates the keys for the top level nodes in the main tree view. These
* nodes are the child nodes of the invisible root node of the tree. The
* child nodes that are created vary with the view option selected by the
* user: group by data type or group by person/host.
* *
* @param list list of keys created * IMPORTANT: Every time a key is added to the keys list, the NetBeans
* @return true, indicating that the key list is complete * framework reacts. To avoid significant performance hits, all of the keys
* need to be added at once.
*
* @param keys A list to contain the keys.
*
* @return True, indicating that the list of keys is complete.
*/ */
@Override @Override
protected boolean createKeys(List<Object> list) { protected boolean createKeys(List<Object> list) {
@ -101,6 +115,10 @@ public final class AutopsyTreeChildFactory extends ChildFactory.Detachable<Objec
try { try {
SleuthkitCase tskCase = Case.getCurrentCaseThrows().getSleuthkitCase(); SleuthkitCase tskCase = Case.getCurrentCaseThrows().getSleuthkitCase();
if (Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true)) { if (Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true)) {
/*
* The user has selected the group by person/host tree view
* option.
*/
PersonManager personManager = tskCase.getPersonManager(); PersonManager personManager = tskCase.getPersonManager();
List<Person> persons = personManager.getPersons(); List<Person> persons = personManager.getPersons();
// show persons level if there are persons to be shown // show persons level if there are persons to be shown
@ -118,8 +136,7 @@ public final class AutopsyTreeChildFactory extends ChildFactory.Detachable<Objec
nodes = tskCase.getHostManager().getAllHosts().stream() nodes = tskCase.getHostManager().getAllHosts().stream()
.map(HostGrouping::new) .map(HostGrouping::new)
.sorted() .sorted()
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
// either way, add in reports node // either way, add in reports node
@ -137,9 +154,9 @@ public final class AutopsyTreeChildFactory extends ChildFactory.Detachable<Objec
); );
} }
} catch (NoCurrentCaseException ex) { } catch (NoCurrentCaseException ex) {
logger.log(Level.SEVERE, "Exception while getting open case.", ex); //NON-NLS logger.log(Level.SEVERE, "Failed to create tree because there is no current case", ex); //NON-NLS
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Exception while getting data from case.", ex); //NON-NLS logger.log(Level.SEVERE, "Failed to create tree because of an error querying the case database", ex); //NON-NLS
} }
// add all nodes to the netbeans node list // add all nodes to the netbeans node list
@ -148,28 +165,33 @@ public final class AutopsyTreeChildFactory extends ChildFactory.Detachable<Objec
} }
/** /**
* Creates nodes for the top level Key * Creates a node for a given key for the top level nodes in the main tree
* view.
* *
* @param key * @param key The key.
* *
* @return Node for the key, null if key is unknown. * @return A node for the key.
*/ */
@Override @Override
protected Node createNodeForKey(Object key) { protected Node createNodeForKey(Object key) {
if (key instanceof SleuthkitVisitableItem) { Node node = null;
return ((SleuthkitVisitableItem) key).accept(new CreateSleuthkitNodeVisitor()); if (key != null) {
} else if (key instanceof AutopsyVisitableItem) { if (key instanceof SleuthkitVisitableItem) {
return ((AutopsyVisitableItem) key).accept(new RootContentChildren.CreateAutopsyNodeVisitor()); node = ((SleuthkitVisitableItem) key).accept(new CreateSleuthkitNodeVisitor());
} else { } else if (key instanceof AutopsyVisitableItem) {
logger.log(Level.SEVERE, "Unknown key type ", key.getClass().getName()); node = ((AutopsyVisitableItem) key).accept(new RootContentChildren.CreateAutopsyNodeVisitor());
return null; } else {
logger.log(Level.SEVERE, "Unknown key type: ", key.getClass().getName());
}
} }
return node;
} }
/** /**
* Refresh the children * Refreshes the top level nodes in the main tree view.
*/ */
public void refreshChildren() { public void refreshChildren() {
refresh(true); refresh(true);
} }
} }

View File

@ -45,7 +45,6 @@ AttachmentNode.getActions.openInExtViewer.text=Open in External Viewer Ctrl+E
AttachmentNode.getActions.searchFilesSameMD5.text=Search for files with the same MD5 hash AttachmentNode.getActions.searchFilesSameMD5.text=Search for files with the same MD5 hash
AttachmentNode.getActions.viewFileInDir.text=View File in Directory AttachmentNode.getActions.viewFileInDir.text=View File in Directory
AttachmentNode.getActions.viewInNewWin.text=View in New Window AttachmentNode.getActions.viewInNewWin.text=View in New Window
# {0} - node name
BaseChildFactory.NoSuchEventBusException.message=No event bus for node: {0} BaseChildFactory.NoSuchEventBusException.message=No event bus for node: {0}
BlackboardArtifactNode.createSheet.artifactDetails.displayName=Result Details BlackboardArtifactNode.createSheet.artifactDetails.displayName=Result Details
BlackboardArtifactNode.createSheet.artifactDetails.name=Result Details BlackboardArtifactNode.createSheet.artifactDetails.name=Result Details
@ -272,10 +271,10 @@ ImageNode.getActions.viewInNewWin.text=View in New Window
ImageNode.createSheet.name.name=Name ImageNode.createSheet.name.name=Name
ImageNode.createSheet.name.displayName=Name ImageNode.createSheet.name.displayName=Name
ImageNode.createSheet.name.desc=no description ImageNode.createSheet.name.desc=no description
Installer.exception.tskVerStringNull.msg=Sleuth Kit JNI test call returned without error, but version string was null\! Installer.exception.tskVerStringNull.msg=Sleuth Kit JNI test call returned without error, but version string was null!
Installer.exception.taskVerStringBang.msg=Sleuth Kit JNI test call returned without error, but version string was ""\! Installer.exception.taskVerStringBang.msg=Sleuth Kit JNI test call returned without error, but version string was ""!
Installer.tskLibErr.msg=Problem with Sleuth Kit JNI. Test call failed\!\n\nDetails: {0} Installer.tskLibErr.msg=Problem with Sleuth Kit JNI. Test call failed!\n\nDetails: {0}
Installer.tskLibErr.err=Fatal Error\! Installer.tskLibErr.err=Fatal Error!
InterestingHits.interestingItems.text=INTERESTING ITEMS InterestingHits.interestingItems.text=INTERESTING ITEMS
InterestingHits.displayName.text=Interesting Items InterestingHits.displayName.text=Interesting Items
InterestingHits.createSheet.name.name=Name InterestingHits.createSheet.name.name=Name

View File

@ -0,0 +1,182 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2012-2021 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 java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.EnumSet;
import java.util.List;
import java.util.logging.Level;
import org.openide.nodes.Children;
import org.openide.nodes.Sheet;
import org.openide.util.NbBundle;
import org.openide.util.lookup.Lookups;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskDataException;
/**
* A structural node in the main tree view when the user has selected the group
* by persons/hosts option. Instances of this node appear as children of a node
* representing a data source association with a host, and as a parent of a data
* source node. For example: "Host X" -> "Data Source Y" -> "Data Source Files"
* -> "Data Source Y", where "Data Source Files" is an instance of this node.
*/
public class DataSourceFilesNode extends DisplayableItemNode {
private static final String NAME = NbBundle.getMessage(DataSourceFilesNode.class, "DataSourcesNode.name");
/**
* @return The name used to identify the node of this type with a lookup.
*/
public static String getNameIdentifier() {
return NAME;
}
private final String displayName;
// NOTE: The images passed in via argument will be ignored.
@Deprecated
public DataSourceFilesNode(List<Content> images) {
this(0);
}
public DataSourceFilesNode() {
this(0);
}
public DataSourceFilesNode(long dsObjId) {
super(Children.create(new DataSourcesNodeChildren(dsObjId), false), Lookups.singleton(NAME));
displayName = (dsObjId > 0) ? NbBundle.getMessage(DataSourceFilesNode.class, "DataSourcesNode.group_by_datasource.name") : NAME;
init();
}
private void init() {
setName(NAME);
setDisplayName(displayName);
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/image.png"); //NON-NLS
}
@Override
public String getItemType() {
return getClass().getName();
}
/*
* Custom Keys implementation that listens for new data sources being added.
*/
public static class DataSourcesNodeChildren extends AbstractContentChildren<Content> {
private static final Logger logger = Logger.getLogger(DataSourcesNodeChildren.class.getName());
private final long datasourceObjId;
List<Content> currentKeys;
public DataSourcesNodeChildren() {
this(0);
}
public DataSourcesNodeChildren(long dsObjId) {
super("ds_" + Long.toString(dsObjId));
this.currentKeys = new ArrayList<>();
this.datasourceObjId = dsObjId;
}
private final PropertyChangeListener pcl = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
String eventType = evt.getPropertyName();
if (eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) {
refresh(true);
}
}
};
@Override
protected void onAdd() {
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.DATA_SOURCE_ADDED), pcl);
}
@Override
protected void onRemove() {
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.DATA_SOURCE_ADDED), pcl);
currentKeys.clear();
}
@Override
protected List<Content> makeKeys() {
try {
if (datasourceObjId == 0) {
currentKeys = Case.getCurrentCaseThrows().getDataSources();
} else {
Content content = Case.getCurrentCaseThrows().getSleuthkitCase().getDataSource(datasourceObjId);
currentKeys = new ArrayList<>(Arrays.asList(content));
}
Collections.sort(currentKeys, new Comparator<Content>() {
@Override
public int compare(Content content1, Content content2) {
String content1Name = content1.getName().toLowerCase();
String content2Name = content2.getName().toLowerCase();
return content1Name.compareTo(content2Name);
}
});
} catch (TskCoreException | NoCurrentCaseException | TskDataException ex) {
logger.log(Level.SEVERE, "Error getting data sources: {0}", ex.getMessage()); // NON-NLS
}
return currentKeys;
}
}
@Override
public boolean isLeafTypeNode() {
return false;
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
protected Sheet createSheet() {
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "DataSourcesNode.createSheet.name.name"),
NbBundle.getMessage(this.getClass(), "DataSourcesNode.createSheet.name.displayName"),
NbBundle.getMessage(this.getClass(), "DataSourcesNode.createSheet.name.desc"),
NAME));
return sheet;
}
}

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011 Basis Technology Corp. * Copyright 2011-2021 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -19,7 +19,7 @@
package org.sleuthkit.autopsy.datamodel; package org.sleuthkit.autopsy.datamodel;
/** /**
* Root node to store the data sources in a case * An "Autopsy visitable item" that supplies a
*/ */
public class DataSources implements AutopsyVisitableItem { public class DataSources implements AutopsyVisitableItem {

View File

@ -1,156 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2021 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 java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.stream.Collectors;
import org.openide.nodes.ChildFactory;
import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.openide.nodes.Sheet;
import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
import org.openide.util.lookup.Lookups;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.TskCoreException;
/**
* Root node for hosts displaying only data sources (no results, reports, etc.).
*/
@Messages({
"DataSourcesHostsNode_name=Data Sources"
})
public class DataSourcesByTypeNode extends DisplayableItemNode {
/*
* Custom Keys implementation that listens for new data sources being added.
*/
public static class DataSourcesByTypeChildren extends ChildFactory.Detachable<HostDataSources> {
private static final Set<Case.Events> UPDATE_EVTS = EnumSet.of(
Case.Events.DATA_SOURCE_ADDED,
Case.Events.HOSTS_ADDED,
Case.Events.HOSTS_DELETED,
Case.Events.HOSTS_CHANGED);
private static final Set<String> UPDATE_EVT_STRS = UPDATE_EVTS.stream()
.map(evt -> evt.name())
.collect(Collectors.toSet());
private static final Logger logger = Logger.getLogger(DataSourcesByTypeChildren.class.getName());
private final PropertyChangeListener pcl = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
String eventType = evt.getPropertyName();
if (UPDATE_EVT_STRS.contains(eventType)) {
refresh(true);
}
}
};
@Override
protected void addNotify() {
Case.addEventTypeSubscriber(UPDATE_EVTS, pcl);
}
@Override
protected void removeNotify() {
Case.removeEventTypeSubscriber(UPDATE_EVTS, pcl);
}
@Override
protected boolean createKeys(List<HostDataSources> toPopulate) {
try {
Case.getCurrentCaseThrows().getSleuthkitCase().getHostManager().getAllHosts().stream()
.map(HostDataSources::new)
.sorted()
.forEach(toPopulate::add);
} catch (TskCoreException | NoCurrentCaseException ex) {
logger.log(Level.SEVERE, "Error getting data sources: {0}", ex.getMessage()); // NON-NLS
}
return true;
}
@Override
protected Node createNodeForKey(HostDataSources key) {
return new HostNode(key);
}
}
private static final String NAME = Bundle.DataSourcesHostsNode_name();
/**
* @return The name used to identify the node of this type with a lookup.
*/
public static String getNameIdentifier() {
return NAME;
}
/**
* Main constructor.
*/
DataSourcesByTypeNode() {
super(Children.create(new DataSourcesByTypeChildren(), false), Lookups.singleton(NAME));
setName(NAME);
setDisplayName(NAME);
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/image.png");
}
@Override
public String getItemType() {
return getClass().getName();
}
@Override
public boolean isLeafTypeNode() {
return false;
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
protected Sheet createSheet() {
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "DataSourcesNode.createSheet.name.name"),
NbBundle.getMessage(this.getClass(), "DataSourcesNode.createSheet.name.displayName"),
NbBundle.getMessage(this.getClass(), "DataSourcesNode.createSheet.name.desc"),
NAME));
return sheet;
}
}

View File

@ -1,15 +1,15 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2018 Basis Technology Corp. * Copyright 2021 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -20,135 +20,117 @@ package org.sleuthkit.autopsy.datamodel;
import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.List; import java.util.List;
import java.util.Set;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.stream.Collectors;
import org.openide.nodes.ChildFactory;
import org.openide.nodes.Children; import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.openide.nodes.Sheet; import org.openide.nodes.Sheet;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
import org.openide.util.lookup.Lookups; import org.openide.util.lookup.Lookups;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskDataException;
/** /**
* Nodes for the images * A top-level structural node (child of the invisible root node) in the main
* tree view when the user has selected the group by data type option. It
* appears as the parent node of the "directory tree" nodes that are the roots
* of the file trees for the individual data sources in a case. For example:
* "Data Sources" -> "Data Source X", "Data Source Y", where "Data Sources" is
* an instance of this node. The siblings of this node are the "Views, "Analysis
* Results," "Os Accounts," "Tags," and "Reports" nodes.
*/ */
@Messages({
"DataSourcesHostsNode_name=Data Sources"
})
public class DataSourcesNode extends DisplayableItemNode { public class DataSourcesNode extends DisplayableItemNode {
private static final String NAME = NbBundle.getMessage(DataSourcesNode.class, "DataSourcesNode.name");
/**
* @return The name used to identify the node of this type with a lookup.
*/
public static String getNameIdentifier() {
return NAME;
}
private final String displayName;
// NOTE: The images passed in via argument will be ignored.
@Deprecated
public DataSourcesNode(List<Content> images) {
this(0);
}
public DataSourcesNode() {
this(0);
}
public DataSourcesNode(long dsObjId) {
super(Children.create(new DataSourcesNodeChildren(dsObjId), false), Lookups.singleton(NAME));
displayName = (dsObjId > 0) ? NbBundle.getMessage(DataSourcesNode.class, "DataSourcesNode.group_by_datasource.name") : NAME;
init();
}
private void init() {
setName(NAME);
setDisplayName(displayName);
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/image.png"); //NON-NLS
}
@Override
public String getItemType() {
return getClass().getName();
}
/* /*
* Custom Keys implementation that listens for new data sources being added. * Custom Keys implementation that listens for new data sources being added.
*/ */
public static class DataSourcesNodeChildren extends AbstractContentChildren<Content> { public static class DataSourcesByTypeChildren extends ChildFactory.Detachable<HostDataSources> {
private static final Logger logger = Logger.getLogger(DataSourcesNodeChildren.class.getName()); private static final Set<Case.Events> UPDATE_EVTS = EnumSet.of(Case.Events.DATA_SOURCE_ADDED,
private final long datasourceObjId; Case.Events.HOSTS_ADDED,
Case.Events.HOSTS_DELETED,
List<Content> currentKeys; Case.Events.HOSTS_UPDATED);
public DataSourcesNodeChildren() { private static final Set<String> UPDATE_EVT_STRS = UPDATE_EVTS.stream()
this(0); .map(evt -> evt.name())
} .collect(Collectors.toSet());
private static final Logger logger = Logger.getLogger(DataSourcesByTypeChildren.class.getName());
public DataSourcesNodeChildren(long dsObjId) {
super("ds_" + Long.toString(dsObjId));
this.currentKeys = new ArrayList<>();
this.datasourceObjId = dsObjId;
}
private final PropertyChangeListener pcl = new PropertyChangeListener() { private final PropertyChangeListener pcl = new PropertyChangeListener() {
@Override @Override
public void propertyChange(PropertyChangeEvent evt) { public void propertyChange(PropertyChangeEvent evt) {
String eventType = evt.getPropertyName(); String eventType = evt.getPropertyName();
if (eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) { if (UPDATE_EVT_STRS.contains(eventType)) {
refresh(true); refresh(true);
} }
} }
}; };
@Override @Override
protected void onAdd() { protected void addNotify() {
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.DATA_SOURCE_ADDED), pcl); Case.addEventTypeSubscriber(UPDATE_EVTS, pcl);
} }
@Override @Override
protected void onRemove() { protected void removeNotify() {
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.DATA_SOURCE_ADDED), pcl); Case.removeEventTypeSubscriber(UPDATE_EVTS, pcl);
currentKeys.clear();
} }
@Override @Override
protected List<Content> makeKeys() { protected boolean createKeys(List<HostDataSources> toPopulate) {
try { try {
if (datasourceObjId == 0) { Case.getCurrentCaseThrows().getSleuthkitCase().getHostManager().getAllHosts().stream()
currentKeys = Case.getCurrentCaseThrows().getDataSources(); .map(HostDataSources::new)
} .sorted()
else { .forEach(toPopulate::add);
Content content = Case.getCurrentCaseThrows().getSleuthkitCase().getDataSource(datasourceObjId);
currentKeys = new ArrayList<>(Arrays.asList(content));
}
Collections.sort(currentKeys, new Comparator<Content>() {
@Override
public int compare(Content content1, Content content2) {
String content1Name = content1.getName().toLowerCase();
String content2Name = content2.getName().toLowerCase();
return content1Name.compareTo(content2Name);
}
}); } catch (TskCoreException | NoCurrentCaseException ex) {
} catch (TskCoreException | NoCurrentCaseException | TskDataException ex) {
logger.log(Level.SEVERE, "Error getting data sources: {0}", ex.getMessage()); // NON-NLS logger.log(Level.SEVERE, "Error getting data sources: {0}", ex.getMessage()); // NON-NLS
} }
return currentKeys; return true;
} }
@Override
protected Node createNodeForKey(HostDataSources key) {
return new HostNode(key);
}
}
private static final String NAME = Bundle.DataSourcesHostsNode_name();
/**
* @return The name used to identify the node of this type with a lookup.
*/
public static String getNameIdentifier() {
return NAME;
}
/**
* Main constructor.
*/
DataSourcesNode() {
super(Children.create(new DataSourcesByTypeChildren(), false), Lookups.singleton(NAME));
setName(NAME);
setDisplayName(NAME);
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/image.png");
}
@Override
public String getItemType() {
return getClass().getName();
} }
@Override @Override
@ -176,4 +158,4 @@ public class DataSourcesNode extends DisplayableItemNode {
NAME)); NAME));
return sheet; return sheet;
} }
} }

View File

@ -42,7 +42,7 @@ public interface DisplayableItemNodeVisitor<T> {
/* /*
* Data Sources Area * Data Sources Area
*/ */
T visit(DataSourcesNode in); T visit(DataSourceFilesNode in);
T visit(LayoutFileNode lfn); T visit(LayoutFileNode lfn);
@ -192,11 +192,11 @@ public interface DisplayableItemNodeVisitor<T> {
T visit(OsAccounts.OsAccountListNode node); T visit(OsAccounts.OsAccountListNode node);
T visit(PersonGroupingNode node); T visit(PersonNode node);
T visit(HostNode node); T visit(HostNode node);
T visit(DataSourcesByTypeNode node); T visit(DataSourcesNode node);
/* /*
* Unsupported node * Unsupported node
@ -406,7 +406,7 @@ public interface DisplayableItemNodeVisitor<T> {
} }
@Override @Override
public T visit(DataSourcesNode in) { public T visit(DataSourceFilesNode in) {
return defaultVisit(in); return defaultVisit(in);
} }
@ -561,12 +561,12 @@ public interface DisplayableItemNodeVisitor<T> {
} }
@Override @Override
public T visit(DataSourcesByTypeNode node) { public T visit(DataSourcesNode node) {
return defaultVisit(node); return defaultVisit(node);
} }
@Override @Override
public T visit(PersonGroupingNode node) { public T visit(PersonNode node) {
return defaultVisit(node); return defaultVisit(node);
} }

View File

@ -39,7 +39,7 @@ import org.openide.util.WeakListeners;
import org.openide.util.lookup.Lookups; import org.openide.util.lookup.Lookups;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.casemodule.events.HostsChangedEvent; import org.sleuthkit.autopsy.casemodule.events.HostsUpdatedEvent;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.hosts.AssociatePersonsMenuAction; import org.sleuthkit.autopsy.datamodel.hosts.AssociatePersonsMenuAction;
import org.sleuthkit.autopsy.datamodel.hosts.MergeHostMenuAction; import org.sleuthkit.autopsy.datamodel.hosts.MergeHostMenuAction;
@ -178,8 +178,8 @@ public class HostNode extends DisplayableItemNode {
@Override @Override
public void propertyChange(PropertyChangeEvent evt) { public void propertyChange(PropertyChangeEvent evt) {
String eventType = evt.getPropertyName(); String eventType = evt.getPropertyName();
if (hostId != null && eventType.equals(Case.Events.HOSTS_CHANGED.toString()) && evt instanceof HostsChangedEvent) { if (hostId != null && eventType.equals(Case.Events.HOSTS_UPDATED.toString()) && evt instanceof HostsUpdatedEvent) {
((HostsChangedEvent) evt).getNewValue().stream() ((HostsUpdatedEvent) evt).getHosts().stream()
.filter(h -> h != null && h.getHostId() == hostId) .filter(h -> h != null && h.getHostId() == hostId)
.findFirst() .findFirst()
.ifPresent((newHost) -> { .ifPresent((newHost) -> {
@ -247,7 +247,7 @@ public class HostNode extends DisplayableItemNode {
host == null ? Lookups.fixed(displayName) : Lookups.fixed(host, displayName)); host == null ? Lookups.fixed(displayName) : Lookups.fixed(host, displayName));
hostId = host == null ? null : host.getHostId(); hostId = host == null ? null : host.getHostId();
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.HOSTS_CHANGED), Case.addEventTypeSubscriber(EnumSet.of(Case.Events.HOSTS_UPDATED),
WeakListeners.propertyChange(hostChangePcl, this)); WeakListeners.propertyChange(hostChangePcl, this));
super.setName(displayName); super.setName(displayName);
super.setDisplayName(displayName); super.setDisplayName(displayName);

View File

@ -39,7 +39,7 @@ import org.openide.util.Exceptions;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
import org.openide.util.WeakListeners; import org.openide.util.WeakListeners;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.events.OsAccountChangedEvent; import org.sleuthkit.autopsy.casemodule.events.OsAccountsUpdatedEvent;
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
import org.sleuthkit.autopsy.corecomponents.DataResultViewerTable; import org.sleuthkit.autopsy.corecomponents.DataResultViewerTable;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
@ -125,8 +125,8 @@ public final class OsAccounts implements AutopsyVisitableItem {
@Override @Override
public void propertyChange(PropertyChangeEvent evt) { public void propertyChange(PropertyChangeEvent evt) {
String eventType = evt.getPropertyName(); String eventType = evt.getPropertyName();
if (eventType.equals(Case.Events.OS_ACCOUNT_ADDED.toString()) if (eventType.equals(Case.Events.OS_ACCOUNTS_ADDED.toString())
|| eventType.equals(Case.Events.OS_ACCOUNT_REMOVED.toString())) { || eventType.equals(Case.Events.OS_ACCOUNTS_DELETED.toString())) {
refresh(true); refresh(true);
} else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) { } 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 // case was closed. Remove listeners so that we don't get called with a stale case handle
@ -140,13 +140,13 @@ public final class OsAccounts implements AutopsyVisitableItem {
@Override @Override
protected void addNotify() { protected void addNotify() {
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.OS_ACCOUNT_ADDED, Case.Events.OS_ACCOUNT_REMOVED), listener); Case.addEventTypeSubscriber(EnumSet.of(Case.Events.OS_ACCOUNTS_ADDED, Case.Events.OS_ACCOUNTS_DELETED), listener);
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), listener); Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), listener);
} }
@Override @Override
protected void removeNotify() { protected void removeNotify() {
Case.removeEventTypeSubscriber(Collections.singleton(Case.Events.OS_ACCOUNT_ADDED), listener); Case.removeEventTypeSubscriber(Collections.singleton(Case.Events.OS_ACCOUNTS_ADDED), listener);
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), listener); Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), listener);
} }
@ -184,11 +184,14 @@ public final class OsAccounts implements AutopsyVisitableItem {
private final PropertyChangeListener listener = new PropertyChangeListener() { private final PropertyChangeListener listener = new PropertyChangeListener() {
@Override @Override
public void propertyChange(PropertyChangeEvent evt) { public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(Case.Events.OS_ACCOUNT_CHANGED.name())) { if (evt.getPropertyName().equals(Case.Events.OS_ACCOUNTS_UPDATED.name())) {
if (((OsAccountChangedEvent) evt).getOsAccount().getId() == account.getId()) { OsAccountsUpdatedEvent updateEvent = (OsAccountsUpdatedEvent) evt;
// Update the account node to the new one for (OsAccount acct : updateEvent.getOsAccounts()) {
account = ((OsAccountChangedEvent) evt).getOsAccount(); if (acct.getId() == account.getId()) {
updateSheet(); account = acct;
updateSheet();
break;
}
} }
} else if (evt.getPropertyName().equals(REALM_DATA_AVAILABLE_EVENT)) { } else if (evt.getPropertyName().equals(REALM_DATA_AVAILABLE_EVENT)) {
OsAccountRealm realm = (OsAccountRealm) evt.getNewValue(); OsAccountRealm realm = (OsAccountRealm) evt.getNewValue();
@ -222,7 +225,7 @@ public final class OsAccounts implements AutopsyVisitableItem {
setDisplayName(account.getName()); setDisplayName(account.getName());
setIconBaseWithExtension(ICON_PATH); setIconBaseWithExtension(ICON_PATH);
Case.addEventTypeSubscriber(Collections.singleton(Case.Events.OS_ACCOUNT_CHANGED), weakListener); Case.addEventTypeSubscriber(Collections.singleton(Case.Events.OS_ACCOUNTS_UPDATED), weakListener);
} }
@Override @Override

View File

@ -1,15 +1,15 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2021 Basis Technology Corp. * Copyright 2021 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -36,7 +36,7 @@ import org.openide.util.WeakListeners;
import org.openide.util.lookup.Lookups; import org.openide.util.lookup.Lookups;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.casemodule.events.PersonsChangedEvent; import org.sleuthkit.autopsy.casemodule.events.PersonsUpdatedEvent;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.persons.DeletePersonAction; import org.sleuthkit.autopsy.datamodel.persons.DeletePersonAction;
import org.sleuthkit.autopsy.datamodel.persons.EditPersonAction; import org.sleuthkit.autopsy.datamodel.persons.EditPersonAction;
@ -45,16 +45,21 @@ import org.sleuthkit.datamodel.Person;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
/** /**
* A node to be displayed in the UI tree for a person and persons grouped in * A main tree view node that represents a person in a case. Its child nodes, if
* this host. * any, represent hosts in the case. There must be at least one person in a case
* for the person nodes layer to appear. If the persons layer is present, any
* hosts that are not associated with a person are grouped under an "Unknown
* Persons" person node.
*/ */
@NbBundle.Messages(value = {"PersonNode_unknownPersonNode_title=Unknown Persons"}) @NbBundle.Messages(value = {"PersonNode_unknownPersonNode_title=Unknown Persons"})
public class PersonGroupingNode extends DisplayableItemNode { public class PersonNode extends DisplayableItemNode {
private static final String ICON_PATH = "org/sleuthkit/autopsy/images/person.png"; private static final String ICON_PATH = "org/sleuthkit/autopsy/images/person.png";
/** /**
* Returns the id of an unknown persons node. This can be used with a node lookup. * Returns the id of an unknown persons node. This can be used with a node
* lookup.
*
* @return The id of an unknown persons node. * @return The id of an unknown persons node.
*/ */
public static String getUnknownPersonId() { public static String getUnknownPersonId() {
@ -68,12 +73,13 @@ public class PersonGroupingNode extends DisplayableItemNode {
private static final Logger logger = Logger.getLogger(PersonChildren.class.getName()); private static final Logger logger = Logger.getLogger(PersonChildren.class.getName());
private static final Set<Case.Events> CHILD_EVENTS = EnumSet.of( private static final Set<Case.Events> HOST_EVENTS_OF_INTEREST = EnumSet.of(Case.Events.HOSTS_ADDED,
Case.Events.HOSTS_ADDED, Case.Events.HOSTS_ADDED,
Case.Events.HOSTS_DELETED, Case.Events.HOSTS_DELETED,
Case.Events.PERSONS_CHANGED); Case.Events.HOSTS_ADDED_TO_PERSON,
Case.Events.HOSTS_REMOVED_FROM_PERSON);
private static final Set<String> CHILD_EVENTS_STR = CHILD_EVENTS.stream()
private static final Set<String> HOST_EVENTS_OF_INTEREST_NAMES = HOST_EVENTS_OF_INTEREST.stream()
.map(ev -> ev.name()) .map(ev -> ev.name())
.collect(Collectors.toSet()); .collect(Collectors.toSet());
@ -89,13 +95,18 @@ public class PersonGroupingNode extends DisplayableItemNode {
} }
/** /**
* Listener for handling adding and removing host events. * Listener for application events that are published when hosts are
* added to or deleted from a case, and for events published when the
* associations between persons and hosts change. If the user has
* selected the group by person/host option for the main tree view,
* these events mean that person nodes in the tree need to be refreshed
* to reflect the structural changes.
*/ */
private final PropertyChangeListener hostAddedDeletedPcl = new PropertyChangeListener() { private final PropertyChangeListener hostAddedDeletedPcl = new PropertyChangeListener() {
@Override @Override
public void propertyChange(PropertyChangeEvent evt) { public void propertyChange(PropertyChangeEvent evt) {
String eventType = evt.getPropertyName(); String eventType = evt.getPropertyName();
if (eventType != null && CHILD_EVENTS_STR.contains(eventType)) { if (eventType != null && HOST_EVENTS_OF_INTEREST_NAMES.contains(eventType)) {
refresh(true); refresh(true);
} }
} }
@ -103,12 +114,12 @@ public class PersonGroupingNode extends DisplayableItemNode {
@Override @Override
protected void addNotify() { protected void addNotify() {
Case.addEventTypeSubscriber(CHILD_EVENTS, hostAddedDeletedPcl); Case.addEventTypeSubscriber(HOST_EVENTS_OF_INTEREST, hostAddedDeletedPcl);
} }
@Override @Override
protected void removeNotify() { protected void removeNotify() {
Case.removeEventTypeSubscriber(CHILD_EVENTS, hostAddedDeletedPcl); Case.removeEventTypeSubscriber(HOST_EVENTS_OF_INTEREST, hostAddedDeletedPcl);
} }
@Override @Override
@ -120,7 +131,12 @@ public class PersonGroupingNode extends DisplayableItemNode {
protected boolean createKeys(List<HostGrouping> toPopulate) { protected boolean createKeys(List<HostGrouping> toPopulate) {
List<Host> hosts = Collections.emptyList(); List<Host> hosts = Collections.emptyList();
try { try {
hosts = Case.getCurrentCaseThrows().getSleuthkitCase().getPersonManager().getHostsForPerson(this.person); if (person != null) {
hosts = Case.getCurrentCaseThrows().getSleuthkitCase().getPersonManager().getHostsForPerson(person);
} else {
// This is the "Unknown Persons" node, get the hosts that are not associated with a person.
hosts = Case.getCurrentCaseThrows().getSleuthkitCase().getPersonManager().getHostsWithoutPersons();
}
} catch (NoCurrentCaseException | TskCoreException ex) { } catch (NoCurrentCaseException | TskCoreException ex) {
String personName = person == null || person.getName() == null ? "<unknown>" : person.getName(); String personName = person == null || person.getName() == null ? "<unknown>" : person.getName();
logger.log(Level.WARNING, String.format("Unable to get data sources for host: %s", personName), ex); logger.log(Level.WARNING, String.format("Unable to get data sources for host: %s", personName), ex);
@ -139,14 +155,15 @@ public class PersonGroupingNode extends DisplayableItemNode {
private final Long personId; private final Long personId;
/** /**
* Listener for handling person change events. * Listener for application events that are published when the properties of
* persons in the case change.
*/ */
private final PropertyChangeListener personChangePcl = new PropertyChangeListener() { private final PropertyChangeListener personChangePcl = new PropertyChangeListener() {
@Override @Override
public void propertyChange(PropertyChangeEvent evt) { public void propertyChange(PropertyChangeEvent evt) {
String eventType = evt.getPropertyName(); String eventType = evt.getPropertyName();
if (personId != null && eventType.equals(Case.Events.PERSONS_CHANGED.toString()) && evt instanceof PersonsChangedEvent) { if (personId != null && eventType.equals(Case.Events.PERSONS_UPDATED.toString()) && evt instanceof PersonsUpdatedEvent) {
((PersonsChangedEvent) evt).getNewValue().stream() ((PersonsUpdatedEvent) evt).getNewValue().stream()
.filter(p -> p != null && p.getPersonId() == personId) .filter(p -> p != null && p.getPersonId() == personId)
.findFirst() .findFirst()
.ifPresent((newPerson) -> { .ifPresent((newPerson) -> {
@ -161,6 +178,7 @@ public class PersonGroupingNode extends DisplayableItemNode {
* Gets the display name for this person or "Unknown Persons". * Gets the display name for this person or "Unknown Persons".
* *
* @param person The person. * @param person The person.
*
* @return The non-empty string for the display name. * @return The non-empty string for the display name.
*/ */
private static String getDisplayName(Person person) { private static String getDisplayName(Person person) {
@ -174,17 +192,17 @@ public class PersonGroupingNode extends DisplayableItemNode {
* *
* @param person The person record to be represented. * @param person The person record to be represented.
*/ */
PersonGroupingNode(Person person) { PersonNode(Person person) {
this(person, getDisplayName(person)); this(person, getDisplayName(person));
} }
/** /**
* Constructor. * Constructor.
* *
* @param person The person. * @param person The person.
* @param displayName The display name for the person. * @param displayName The display name for the person.
*/ */
private PersonGroupingNode(Person person, String displayName) { private PersonNode(Person person, String displayName) {
super(Children.create(new PersonChildren(person), false), super(Children.create(new PersonChildren(person), false),
person == null ? Lookups.fixed(displayName) : Lookups.fixed(person, displayName)); person == null ? Lookups.fixed(displayName) : Lookups.fixed(person, displayName));
super.setName(displayName); super.setName(displayName);
@ -192,7 +210,7 @@ public class PersonGroupingNode extends DisplayableItemNode {
this.setIconBaseWithExtension(ICON_PATH); this.setIconBaseWithExtension(ICON_PATH);
this.person = person; this.person = person;
this.personId = person == null ? null : person.getPersonId(); this.personId = person == null ? null : person.getPersonId();
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.PERSONS_CHANGED), Case.addEventTypeSubscriber(EnumSet.of(Case.Events.PERSONS_UPDATED),
WeakListeners.propertyChange(personChangePcl, this)); WeakListeners.propertyChange(personChangePcl, this));
} }

View File

@ -130,7 +130,7 @@ public class RootContentChildren extends Children.Keys<Object> {
@Override @Override
public AbstractNode visit(DataSources i) { public AbstractNode visit(DataSources i) {
return new DataSourcesNode(i.filteringDataSourceObjId()); return new DataSourceFilesNode(i.filteringDataSourceObjId());
} }
@Override @Override
@ -177,7 +177,7 @@ public class RootContentChildren extends Children.Keys<Object> {
@Override @Override
public AbstractNode visit(PersonGrouping personGrouping) { public AbstractNode visit(PersonGrouping personGrouping) {
return new PersonGroupingNode(personGrouping.getPerson()); return new PersonNode(personGrouping.getPerson());
} }
@Override @Override
@ -192,7 +192,7 @@ public class RootContentChildren extends Children.Keys<Object> {
@Override @Override
public AbstractNode visit(DataSourcesByType dataSourceHosts) { public AbstractNode visit(DataSourcesByType dataSourceHosts) {
return new DataSourcesByTypeNode(); return new DataSourcesNode();
} }
@Override @Override

View File

@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.datamodel.hosts;
import java.awt.Frame; import java.awt.Frame;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.util.Collections;
import java.util.logging.Level; import java.util.logging.Level;
import javax.swing.AbstractAction; import javax.swing.AbstractAction;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
@ -66,7 +67,7 @@ public class AssociateNewPersonAction extends AbstractAction {
newPersonName = getAddDialogName(); newPersonName = getAddDialogName();
if (StringUtils.isNotBlank(newPersonName)) { if (StringUtils.isNotBlank(newPersonName)) {
Person person = Case.getCurrentCaseThrows().getSleuthkitCase().getPersonManager().newPerson(newPersonName); Person person = Case.getCurrentCaseThrows().getSleuthkitCase().getPersonManager().newPerson(newPersonName);
Case.getCurrentCaseThrows().getSleuthkitCase().getPersonManager().setPerson(host, person); Case.getCurrentCaseThrows().getSleuthkitCase().getPersonManager().addHostsToPerson(person, Collections.singletonList(host));
} }
} catch (NoCurrentCaseException | TskCoreException ex) { } catch (NoCurrentCaseException | TskCoreException ex) {
String hostName = this.host == null || this.host.getName() == null ? "" : this.host.getName(); String hostName = this.host == null || this.host.getName() == null ? "" : this.host.getName();

View File

@ -19,6 +19,7 @@
package org.sleuthkit.autopsy.datamodel.hosts; package org.sleuthkit.autopsy.datamodel.hosts;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.util.Collections;
import java.util.logging.Level; import java.util.logging.Level;
import javax.swing.AbstractAction; import javax.swing.AbstractAction;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
@ -65,7 +66,7 @@ public class AssociatePersonAction extends AbstractAction {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
try { try {
Case.getCurrentCaseThrows().getSleuthkitCase().getPersonManager().setPerson(host, person); Case.getCurrentCaseThrows().getSleuthkitCase().getPersonManager().addHostsToPerson(person, Collections.singletonList(host));
} catch (NoCurrentCaseException | TskCoreException ex) { } catch (NoCurrentCaseException | TskCoreException ex) {
String hostName = this.host == null || this.host.getName() == null ? "" : this.host.getName(); String hostName = this.host == null || this.host.getName() == null ? "" : this.host.getName();
String personName = this.person == null || this.person.getName() == null ? "" : this.person.getName(); String personName = this.person == null || this.person.getName() == null ? "" : this.person.getName();

View File

@ -19,6 +19,7 @@
package org.sleuthkit.autopsy.datamodel.hosts; package org.sleuthkit.autopsy.datamodel.hosts;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.util.Collections;
import java.util.logging.Level; import java.util.logging.Level;
import javax.swing.AbstractAction; import javax.swing.AbstractAction;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
@ -46,6 +47,7 @@ public class RemoveParentPersonAction extends AbstractAction {
private static final Logger logger = Logger.getLogger(RemoveParentPersonAction.class.getName()); private static final Logger logger = Logger.getLogger(RemoveParentPersonAction.class.getName());
private final Person person;
private final Host host; private final Host host;
/** /**
@ -59,12 +61,13 @@ public class RemoveParentPersonAction extends AbstractAction {
person == null || person.getName() == null person == null || person.getName() == null
? Bundle.RemoveParentPersonAction_unknownPerson() : person.getName())); ? Bundle.RemoveParentPersonAction_unknownPerson() : person.getName()));
this.host = host; this.host = host;
this.person = person;
} }
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
try { try {
Case.getCurrentCaseThrows().getSleuthkitCase().getPersonManager().setPerson(host, null); Case.getCurrentCaseThrows().getSleuthkitCase().getPersonManager().removeHostsFromPerson(person, Collections.singletonList(host));
} catch (NoCurrentCaseException | TskCoreException ex) { } catch (NoCurrentCaseException | TskCoreException ex) {
String hostName = this.host == null || this.host.getName() == null ? "" : this.host.getName(); String hostName = this.host == null || this.host.getName() == null ? "" : this.host.getName();
logger.log(Level.WARNING, String.format("Unable to remove parent from host: %s", hostName), ex); logger.log(Level.WARNING, String.format("Unable to remove parent from host: %s", hostName), ex);

View File

@ -85,7 +85,7 @@ import org.sleuthkit.autopsy.datamodel.InterestingHits;
import org.sleuthkit.autopsy.datamodel.KeywordHits; import org.sleuthkit.autopsy.datamodel.KeywordHits;
import org.sleuthkit.autopsy.datamodel.AutopsyTreeChildFactory; import org.sleuthkit.autopsy.datamodel.AutopsyTreeChildFactory;
import org.sleuthkit.autopsy.datamodel.DataArtifacts; import org.sleuthkit.autopsy.datamodel.DataArtifacts;
import org.sleuthkit.autopsy.datamodel.PersonGroupingNode; import org.sleuthkit.autopsy.datamodel.PersonNode;
import org.sleuthkit.autopsy.datamodel.Tags; import org.sleuthkit.autopsy.datamodel.Tags;
import org.sleuthkit.autopsy.datamodel.ViewsNode; import org.sleuthkit.autopsy.datamodel.ViewsNode;
import org.sleuthkit.autopsy.datamodel.accounts.Accounts; import org.sleuthkit.autopsy.datamodel.accounts.Accounts;
@ -240,7 +240,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
if (node == null) { if (node == null) {
return Collections.emptyList(); return Collections.emptyList();
} else if (node.getLookup().lookup(Person.class) != null } else if (node.getLookup().lookup(Person.class) != null
|| PersonGroupingNode.getUnknownPersonId().equals(node.getLookup().lookup(String.class))) { || PersonNode.getUnknownPersonId().equals(node.getLookup().lookup(String.class))) {
Children children = node.getChildren(); Children children = node.getChildren();
Node[] childNodes = children == null ? null : children.getNodes(); Node[] childNodes = children == null ? null : children.getNodes();
if (childNodes != null) { if (childNodes != null) {
@ -1192,7 +1192,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
return Optional.empty(); return Optional.empty();
} else if (node.getLookup().lookup(Host.class) != null } else if (node.getLookup().lookup(Host.class) != null
|| node.getLookup().lookup(Person.class) != null || node.getLookup().lookup(Person.class) != null
|| PersonGroupingNode.getUnknownPersonId().equals(node.getLookup().lookup(String.class))) { || PersonNode.getUnknownPersonId().equals(node.getLookup().lookup(String.class))) {
// if host or person node, recurse until we find correct data source node. // if host or person node, recurse until we find correct data source node.
Children children = node.getChildren(); Children children = node.getChildren();

View File

@ -46,10 +46,10 @@ import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode;
import org.sleuthkit.autopsy.datamodel.AbstractFsContentNode; import org.sleuthkit.autopsy.datamodel.AbstractFsContentNode;
import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode; import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode;
import org.sleuthkit.autopsy.datamodel.ContentNodeSelectionInfo; import org.sleuthkit.autopsy.datamodel.ContentNodeSelectionInfo;
import org.sleuthkit.autopsy.datamodel.DataSourcesByTypeNode;
import org.sleuthkit.autopsy.datamodel.DataSourcesNode; import org.sleuthkit.autopsy.datamodel.DataSourcesNode;
import org.sleuthkit.autopsy.datamodel.DataSourceFilesNode;
import org.sleuthkit.autopsy.datamodel.DisplayableItemNode; import org.sleuthkit.autopsy.datamodel.DisplayableItemNode;
import org.sleuthkit.autopsy.datamodel.PersonGroupingNode; import org.sleuthkit.autopsy.datamodel.PersonNode;
import org.sleuthkit.autopsy.datamodel.RootContentChildren; import org.sleuthkit.autopsy.datamodel.RootContentChildren;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
@ -227,7 +227,7 @@ public class ViewContextAction extends AbstractAction {
} }
// for this data source, get the "Data Sources" child node // for this data source, get the "Data Sources" child node
Node datasourceGroupingNode = treeNode.getChildren().findChild(DataSourcesNode.getNameIdentifier()); Node datasourceGroupingNode = treeNode.getChildren().findChild(DataSourceFilesNode.getNameIdentifier());
// check whether this is the data source we are looking for // check whether this is the data source we are looking for
parentTreeViewNode = findParentNodeInTree(parentContent, datasourceGroupingNode); parentTreeViewNode = findParentNodeInTree(parentContent, datasourceGroupingNode);
@ -243,7 +243,7 @@ public class ViewContextAction extends AbstractAction {
Node datasourceGroupingNode = rootChildren.findChild(dsname); Node datasourceGroupingNode = rootChildren.findChild(dsname);
if (!Objects.isNull(datasourceGroupingNode)) { if (!Objects.isNull(datasourceGroupingNode)) {
Children dsChildren = datasourceGroupingNode.getChildren(); Children dsChildren = datasourceGroupingNode.getChildren();
parentTreeViewNode = dsChildren.findChild(DataSourcesNode.getNameIdentifier()); parentTreeViewNode = dsChildren.findChild(DataSourceFilesNode.getNameIdentifier());
} }
} }
@ -260,7 +260,7 @@ public class ViewContextAction extends AbstractAction {
} else { // Classic view } else { // Classic view
// Start the search at the DataSourcesNode // Start the search at the DataSourcesNode
Children rootChildren = treeViewExplorerMgr.getRootContext().getChildren(); Children rootChildren = treeViewExplorerMgr.getRootContext().getChildren();
Node rootDsNode = rootChildren == null ? null : rootChildren.findChild(DataSourcesByTypeNode.getNameIdentifier()); Node rootDsNode = rootChildren == null ? null : rootChildren.findChild(DataSourcesNode.getNameIdentifier());
if (rootDsNode != null) { if (rootDsNode != null) {
for (Node dataSourceLevelNode : getDataSourceLevelNodes(rootDsNode)) { for (Node dataSourceLevelNode : getDataSourceLevelNodes(rootDsNode)) {
DataSource dataSource = dataSourceLevelNode.getLookup().lookup(DataSource.class); DataSource dataSource = dataSourceLevelNode.getLookup().lookup(DataSource.class);
@ -329,8 +329,8 @@ public class ViewContextAction extends AbstractAction {
return Collections.emptyList(); return Collections.emptyList();
} else if (node.getLookup().lookup(Host.class) != null || } else if (node.getLookup().lookup(Host.class) != null ||
node.getLookup().lookup(Person.class) != null || node.getLookup().lookup(Person.class) != null ||
DataSourcesByTypeNode.getNameIdentifier().equals(node.getLookup().lookup(String.class)) || DataSourcesNode.getNameIdentifier().equals(node.getLookup().lookup(String.class)) ||
PersonGroupingNode.getUnknownPersonId().equals(node.getLookup().lookup(String.class))) { PersonNode.getUnknownPersonId().equals(node.getLookup().lookup(String.class))) {
Children children = node.getChildren(); Children children = node.getChildren();
Node[] childNodes = children == null ? null : children.getNodes(); Node[] childNodes = children == null ? null : children.getNodes();
if (childNodes == null) { if (childNodes == null) {

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2015 Basis Technology Corp. * Copyright 2015-2021 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -22,12 +22,18 @@ import java.beans.PropertyChangeEvent;
import java.io.Serializable; import java.io.Serializable;
/** /**
* A base class for events to be published to registered subscribers on both * A base class for application events that can be published to registered
* this Autopsy node and other Autopsy nodes. The class extends * subscribers on both this Autopsy node and other Autopsy nodes.
* PropertyChangeEvent to integrate with legacy use of JavaBeans *
* PropertyChangeEvents and PropertyChangeListeners as an application event * The class extends PropertyChangeEvent to integrate with legacy use of
* system, and implements Serializable to allow it to be published over a * JavaBeans PropertyChangeEvents and PropertyChangeListeners as an application
* network in serialized form. * event publisher-subcriber mechanism. Subclasses need to decide what
* constitutes "old" and "new" objects for them and are encouraged to provide
* getters for these values that do not require clients to cast the return
* values.
*
* This class implements Serializable to allow it to be published over a network
* in serialized form.
*/ */
public class AutopsyEvent extends PropertyChangeEvent implements Serializable { public class AutopsyEvent extends PropertyChangeEvent implements Serializable {
@ -36,17 +42,22 @@ public class AutopsyEvent extends PropertyChangeEvent implements Serializable {
/** /**
* Events have a source field set to local or remote to allow event * Events have a source field set to local or remote to allow event
* subscribers to filter events by source type. * subscribers to filter events by source type. For a multi-user case, a
* local event has happened on this Autopsy node, and a remote event has
* happened on another Autopsy node.
*
* Events are local by default and are changed to remote events by the event
* publishers on other Autopsy nodes upon event receipt.
*/ */
public enum SourceType { public enum SourceType {
LOCAL, LOCAL,
REMOTE REMOTE
}; };
/** /**
* Constructs an event that can be published to registered subscribers on * Constructs the base class part of an application event that can be
* both this Autopsy node and other Autopsy nodes. * published to registered subscribers on both this Autopsy node and other
* Autopsy nodes.
* *
* @param eventName The event name. * @param eventName The event name.
* @param oldValue The "old" value to associate with the event. May be * @param oldValue The "old" value to associate with the event. May be
@ -60,7 +71,7 @@ public class AutopsyEvent extends PropertyChangeEvent implements Serializable {
} }
/** /**
* Gets the source type (local or remote). * Gets the event source type (local or remote).
* *
* @return SourceType The source type of the event, local or remote. * @return SourceType The source type of the event, local or remote.
*/ */
@ -69,12 +80,9 @@ public class AutopsyEvent extends PropertyChangeEvent implements Serializable {
} }
/** /**
* Gets the source type (local or remote) as a string. This is for clients * Gets the event source type (local or remote) as a string.
* that do not have access to the AutopsyEvent type, and is necessary
* because the events package is not currently a public package within the
* Autopsy-Core NetBeans Module (NBM).
* *
* @return A string, either "LOCAL" or "REMOTE", as an Object. * @return A string, either "LOCAL" or "REMOTE."
*/ */
@Override @Override
public Object getSource() { public Object getSource() {
@ -82,10 +90,10 @@ public class AutopsyEvent extends PropertyChangeEvent implements Serializable {
} }
/** /**
* Sets the source type (local or remote). This field is mutable in this way * Sets the source type (local or remote). This field is mutable to allow an
* to allow an event to be published both locally and remotely without * event to be published both locally and remotely without requiring the
* requiring the construction of two separate objects. It is for use by the * construction of two separate objects. It is for use by the event
* event publishing classes within this package only. * publishing classes within this package only.
* *
* @param sourceType The source type of the event, local or remote. * @param sourceType The source type of the event, local or remote.
*/ */

View File

@ -16,7 +16,7 @@ KnownStatusSearchPanel.knownCheckBox.text=Known Status:
KnownStatusSearchPanel.knownBadOptionCheckBox.text=Notable KnownStatusSearchPanel.knownBadOptionCheckBox.text=Notable
KnownStatusSearchPanel.knownOptionCheckBox.text=Known (NSRL or other) KnownStatusSearchPanel.knownOptionCheckBox.text=Known (NSRL or other)
KnownStatusSearchPanel.unknownOptionCheckBox.text=Unknown KnownStatusSearchPanel.unknownOptionCheckBox.text=Unknown
DateSearchFilter.noneSelectedMsg.text=At least one date type must be selected\! DateSearchFilter.noneSelectedMsg.text=At least one date type must be selected!
DateSearchPanel.dateCheckBox.text=Date: DateSearchPanel.dateCheckBox.text=Date:
DateSearchPanel.jLabel4.text=Timezone: DateSearchPanel.jLabel4.text=Timezone:
DateSearchPanel.createdCheckBox.text=Created DateSearchPanel.createdCheckBox.text=Created
@ -57,7 +57,7 @@ FileSearchPanel.search.results.details=Large number of matches may impact perfor
FileSearchPanel.search.exception.noFilterSelected.msg=At least one filter must be selected. FileSearchPanel.search.exception.noFilterSelected.msg=At least one filter must be selected.
FileSearchPanel.search.validationErr.msg=Validation Error: {0} FileSearchPanel.search.validationErr.msg=Validation Error: {0}
FileSearchPanel.emptyWhereClause.text=Invalid options, nothing to show. FileSearchPanel.emptyWhereClause.text=Invalid options, nothing to show.
KnownStatusSearchFilter.noneSelectedMsg.text=At least one known status must be selected\! KnownStatusSearchFilter.noneSelectedMsg.text=At least one known status must be selected!
NameSearchFilter.emptyNameMsg.text=Must enter something for name search. NameSearchFilter.emptyNameMsg.text=Must enter something for name search.
SizeSearchPanel.sizeCompareComboBox.equalTo=equal to SizeSearchPanel.sizeCompareComboBox.equalTo=equal to
SizeSearchPanel.sizeCompareComboBox.greaterThan=greater than SizeSearchPanel.sizeCompareComboBox.greaterThan=greater than

View File

@ -142,7 +142,7 @@ IngestJob.cancelReason.outOfDiskSpace.text=Out of disk space
IngestJob.cancelReason.servicesDown.text=Services Down IngestJob.cancelReason.servicesDown.text=Services Down
IngestJob.cancelReason.caseClosed.text=Case closed IngestJob.cancelReason.caseClosed.text=Case closed
IngestJobSettingsPanel.globalSettingsButton.text=Global Settings IngestJobSettingsPanel.globalSettingsButton.text=Global Settings
gest gest=
IngestJobSettingsPanel.globalSettingsButton.actionCommand=Advanced IngestJobSettingsPanel.globalSettingsButton.actionCommand=Advanced
IngestJobSettingsPanel.globalSettingsButton.text=Global Settings IngestJobSettingsPanel.globalSettingsButton.text=Global Settings
IngestJobSettingsPanel.pastJobsButton.text=History IngestJobSettingsPanel.pastJobsButton.text=History

View File

@ -100,7 +100,7 @@ final class AddLogicalImageTask implements Runnable {
} }
} }
private static final Score LIKELY_NOTABLE_SCORE = new Score(Score.Significance.LIKELY_NOTABLE, Score.MethodCategory.AUTO); private static final Score LIKELY_NOTABLE_SCORE = new Score(Score.Significance.LIKELY_NOTABLE, Score.Priority.NORMAL);
private final static Logger LOGGER = Logger.getLogger(AddLogicalImageTask.class.getName()); private final static Logger LOGGER = Logger.getLogger(AddLogicalImageTask.class.getName());
private final static String SEARCH_RESULTS_TXT = "SearchResults.txt"; //NON-NLS private final static String SEARCH_RESULTS_TXT = "SearchResults.txt"; //NON-NLS

View File

@ -51,7 +51,7 @@ import org.sleuthkit.datamodel.TskDataException;
*/ */
public class DataSourceIntegrityIngestModule implements DataSourceIngestModule { public class DataSourceIntegrityIngestModule implements DataSourceIngestModule {
private static final Score NOTABLE_SCORE = new Score(Score.Significance.NOTABLE, Score.MethodCategory.AUTO); private static final Score NOTABLE_SCORE = new Score(Score.Significance.NOTABLE, Score.Priority.NORMAL);
private static final Logger logger = Logger.getLogger(DataSourceIntegrityIngestModule.class.getName()); private static final Logger logger = Logger.getLogger(DataSourceIntegrityIngestModule.class.getName());
private static final long DEFAULT_CHUNK_SIZE = 32 * 1024; private static final long DEFAULT_CHUNK_SIZE = 32 * 1024;
private static final IngestServices services = IngestServices.getInstance(); private static final IngestServices services = IngestServices.getInstance();

View File

@ -12,12 +12,7 @@ ExtractArchiveWithPasswordAction.progress.text=Unpacking contents of archive: {0
ExtractArchiveWithPasswordAction.prompt.text=Enter Password ExtractArchiveWithPasswordAction.prompt.text=Enter Password
ExtractArchiveWithPasswordAction.prompt.title=Enter Password ExtractArchiveWithPasswordAction.prompt.title=Enter Password
OpenIDE-Module-Display-Category=Ingest Module OpenIDE-Module-Display-Category=Ingest Module
OpenIDE-Module-Long-Description=\ OpenIDE-Module-Long-Description=Embedded File Extraction Ingest Module\n\nThe Embedded File Extraction Ingest Module processes document files (such as doc, docx, ppt, pptx, xls, xlsx) and archive files (such as zip and others archive types supported by the 7zip extractor).\nContents of these files are extracted and the derived files are added back to the current ingest to be processed by the configured ingest modules.\nIf the derived file happens to be an archive file, it will be re-processed by the 7zip extractor - the extractor will process archive files N-levels deep.\n\nThe extracted files are navigable in the directory tree.\n\nThe module is supported on Windows, Linux and Mac operating systems.
Embedded File Extraction Ingest Module\n\nThe Embedded File Extraction Ingest Module processes document files (such as doc, docx, ppt, pptx, xls, xlsx) and archive files (such as zip and others archive types supported by the 7zip extractor).\n\
Contents of these files are extracted and the derived files are added back to the current ingest to be processed by the configured ingest modules.\n\
If the derived file happens to be an archive file, it will be re-processed by the 7zip extractor - the extractor will process archive files N-levels deep.\n\n\
The extracted files are navigable in the directory tree.\n\n\
The module is supported on Windows, Linux and Mac operating systems.
OpenIDE-Module-Name=Embedded File Extraction OpenIDE-Module-Name=Embedded File Extraction
OpenIDE-Module-Short-Description=Embedded File Extraction Ingest Module OpenIDE-Module-Short-Description=Embedded File Extraction Ingest Module
EmbeddedFileExtractorIngestModule.SevenZipContentReadStream.seek.exception.invalidOrigin=Invalid seek origin: {0} EmbeddedFileExtractorIngestModule.SevenZipContentReadStream.seek.exception.invalidOrigin=Invalid seek origin: {0}

View File

@ -89,8 +89,8 @@ class SevenZipExtractor {
private static final Logger logger = Logger.getLogger(SevenZipExtractor.class.getName()); private static final Logger logger = Logger.getLogger(SevenZipExtractor.class.getName());
private static final String MODULE_NAME = EmbeddedFileExtractorModuleFactory.getModuleName(); private static final String MODULE_NAME = EmbeddedFileExtractorModuleFactory.getModuleName();
private static final Score LIKELY_NOTABLE_SCORE = new Score(Score.Significance.LIKELY_NOTABLE, Score.MethodCategory.AUTO); private static final Score LIKELY_NOTABLE_SCORE = new Score(Score.Significance.LIKELY_NOTABLE, Score.Priority.NORMAL);
private static final Score NOTABLE_SCORE = new Score(Score.Significance.NOTABLE, Score.MethodCategory.AUTO); private static final Score NOTABLE_SCORE = new Score(Score.Significance.NOTABLE, Score.Priority.NORMAL);
//encryption type strings //encryption type strings
private static final String ENCRYPTION_FILE_LEVEL = NbBundle.getMessage(EmbeddedFileExtractorIngestModule.class, private static final String ENCRYPTION_FILE_LEVEL = NbBundle.getMessage(EmbeddedFileExtractorIngestModule.class,

View File

@ -47,8 +47,8 @@ import org.sleuthkit.datamodel.VolumeSystem;
*/ */
final class EncryptionDetectionDataSourceIngestModule implements DataSourceIngestModule { final class EncryptionDetectionDataSourceIngestModule implements DataSourceIngestModule {
private static final Score LIKELY_NOTABLE_SCORE = new Score(Score.Significance.LIKELY_NOTABLE, Score.MethodCategory.AUTO); private static final Score LIKELY_NOTABLE_SCORE = new Score(Score.Significance.LIKELY_NOTABLE, Score.Priority.NORMAL);
private static final Score NOTABLE_SCORE = new Score(Score.Significance.NOTABLE, Score.MethodCategory.AUTO); private static final Score NOTABLE_SCORE = new Score(Score.Significance.NOTABLE, Score.Priority.NORMAL);
private final IngestServices services = IngestServices.getInstance(); private final IngestServices services = IngestServices.getInstance();
private final Logger logger = services.getLogger(EncryptionDetectionModuleFactory.getModuleName()); private final Logger logger = services.getLogger(EncryptionDetectionModuleFactory.getModuleName());
private Blackboard blackboard; private Blackboard blackboard;

View File

@ -64,8 +64,8 @@ import org.xml.sax.SAXException;
final class EncryptionDetectionFileIngestModule extends FileIngestModuleAdapter { final class EncryptionDetectionFileIngestModule extends FileIngestModuleAdapter {
private static final int FILE_SIZE_MODULUS = 512; private static final int FILE_SIZE_MODULUS = 512;
private static final Score LIKELY_NOTABLE_SCORE = new Score(Score.Significance.LIKELY_NOTABLE, Score.MethodCategory.AUTO); private static final Score LIKELY_NOTABLE_SCORE = new Score(Score.Significance.LIKELY_NOTABLE, Score.Priority.NORMAL);
private static final Score NOTABLE_SCORE = new Score(Score.Significance.NOTABLE, Score.MethodCategory.AUTO); private static final Score NOTABLE_SCORE = new Score(Score.Significance.NOTABLE, Score.Priority.NORMAL);
private static final String DATABASE_FILE_EXTENSION = "db"; private static final String DATABASE_FILE_EXTENSION = "db";
private static final int MINIMUM_DATABASE_FILE_SIZE = 65536; //64 KB private static final int MINIMUM_DATABASE_FILE_SIZE = 65536; //64 KB

View File

@ -36,27 +36,27 @@ FileExtMismatchSettingsPanel.jLabel1.text=File Types:
FileExtMismatchSettingsPanel.newExtButton.text=New Extension FileExtMismatchSettingsPanel.newExtButton.text=New Extension
FileExtMismatchSettingsPanel.newMimePrompt.message=Add a new MIME file type: FileExtMismatchSettingsPanel.newMimePrompt.message=Add a new MIME file type:
FileExtMismatchSettingsPanel.newMimePrompt.title=New MIME FileExtMismatchSettingsPanel.newMimePrompt.title=New MIME
FileExtMismatchSettingsPanel.newMimePrompt.emptyMime.message=MIME type text is empty\! FileExtMismatchSettingsPanel.newMimePrompt.emptyMime.message=MIME type text is empty!
FileExtMismatchSettingsPanel.newMimePrompt.emptyMime.title=Empty type FileExtMismatchSettingsPanel.newMimePrompt.emptyMime.title=Empty type
FileExtMismatchSettingsPanel.newMimePrompt.mimeTypeNotSupported.message=MIME type not supported\! FileExtMismatchSettingsPanel.newMimePrompt.mimeTypeNotSupported.message=MIME type not supported!
FileExtMismatchSettingsPanel.newMimePrompt.mimeTypeNotSupported.title=Type not supported FileExtMismatchSettingsPanel.newMimePrompt.mimeTypeNotSupported.title=Type not supported
FileExtMismatchSettingsPanel.newMimePrompt.mimeTypeExists.message=MIME type already exists\! FileExtMismatchSettingsPanel.newMimePrompt.mimeTypeExists.message=MIME type already exists!
FileExtMismatchSettingsPanel.newMimePrompt.mimeTypeExists.title=Type already exists FileExtMismatchSettingsPanel.newMimePrompt.mimeTypeExists.title=Type already exists
FileExtMismatchSettingsPanel.newMimePrompt.mimeTypeNotDetectable.message=MIME type is not detectable by this module. FileExtMismatchSettingsPanel.newMimePrompt.mimeTypeNotDetectable.message=MIME type is not detectable by this module.
FileExtMismatchSettingsPanel.newMimePrompt.mimeTypeNotDetectable.title=Type not detectable FileExtMismatchSettingsPanel.newMimePrompt.mimeTypeNotDetectable.title=Type not detectable
FileExtMismatchSettingsPanel.removeTypeButton.noneSelected.message=No MIME type selected\! FileExtMismatchSettingsPanel.removeTypeButton.noneSelected.message=No MIME type selected!
FileExtMismatchSettingsPanel.removeTypeButton.noneSelected.title=No type selected FileExtMismatchSettingsPanel.removeTypeButton.noneSelected.title=No type selected
FileExtMismatchSettingsPanel.newExtPrompt.message=Add an allowed extension: FileExtMismatchSettingsPanel.newExtPrompt.message=Add an allowed extension:
FileExtMismatchSettingsPanel.newExtPrompt.title=New allowed extension FileExtMismatchSettingsPanel.newExtPrompt.title=New allowed extension
FileExtMismatchSettingsPanel.newExtPrompt.empty.message=Extension text is empty\! FileExtMismatchSettingsPanel.newExtPrompt.empty.message=Extension text is empty!
FileExtMismatchSettingsPanel.newExtPrompt.empty.title=Extension text empty FileExtMismatchSettingsPanel.newExtPrompt.empty.title=Extension text empty
FileExtMismatchSettingsPanel.newExtPrompt.noMimeType.message=No MIME type selected\! FileExtMismatchSettingsPanel.newExtPrompt.noMimeType.message=No MIME type selected!
FileExtMismatchSettingsPanel.newExtPrompt.noMimeType.title=No MIME type selected FileExtMismatchSettingsPanel.newExtPrompt.noMimeType.title=No MIME type selected
FileExtMismatchSettingsPanel.newExtPrompt.extExists.message=Extension already exists\! FileExtMismatchSettingsPanel.newExtPrompt.extExists.message=Extension already exists!
FileExtMismatchSettingsPanel.newExtPrompt.extExists.title=Extension already exists FileExtMismatchSettingsPanel.newExtPrompt.extExists.title=Extension already exists
FileExtMismatchSettingsPanel.removeExtButton.noneSelected.message=No extension selected\! FileExtMismatchSettingsPanel.removeExtButton.noneSelected.message=No extension selected!
FileExtMismatchSettingsPanel.removeExtButton.noneSelected.title=No extension selected FileExtMismatchSettingsPanel.removeExtButton.noneSelected.title=No extension selected
FileExtMismatchSettingsPanel.removeExtButton.noMimeTypeSelected.message=No MIME type selected\! FileExtMismatchSettingsPanel.removeExtButton.noMimeTypeSelected.message=No MIME type selected!
FileExtMismatchSettingsPanel.removeExtButton.noMimeTypeSelected.title=No MIME type selected FileExtMismatchSettingsPanel.removeExtButton.noMimeTypeSelected.title=No MIME type selected
FileExtMismatchSettingsPanel.removeTypeButton.toolTipText= FileExtMismatchSettingsPanel.removeTypeButton.toolTipText=
FileExtMismatchModuleSettingsPanel.checkAllRadioButton.text=Check all file types FileExtMismatchModuleSettingsPanel.checkAllRadioButton.text=Check all file types

View File

@ -53,7 +53,7 @@ import org.sleuthkit.datamodel.TskException;
"FileExtMismatchIngestModule.readError.message=Could not read settings." "FileExtMismatchIngestModule.readError.message=Could not read settings."
}) })
public class FileExtMismatchIngestModule implements FileIngestModule { public class FileExtMismatchIngestModule implements FileIngestModule {
private static final Score LIKELY_NOTABLE_SCORE = new Score(Score.Significance.LIKELY_NOTABLE, Score.MethodCategory.AUTO); private static final Score LIKELY_NOTABLE_SCORE = new Score(Score.Significance.LIKELY_NOTABLE, Score.Priority.NORMAL);
private static final Logger logger = Logger.getLogger(FileExtMismatchIngestModule.class.getName()); private static final Logger logger = Logger.getLogger(FileExtMismatchIngestModule.class.getName());
private final IngestServices services = IngestServices.getInstance(); private final IngestServices services = IngestServices.getInstance();

View File

@ -49,7 +49,7 @@ import org.sleuthkit.datamodel.TskCoreException;
*/ */
@NbBundle.Messages({"CannotRunFileTypeDetection=Unable to run file type detection."}) @NbBundle.Messages({"CannotRunFileTypeDetection=Unable to run file type detection."})
public class FileTypeIdIngestModule implements FileIngestModule { public class FileTypeIdIngestModule implements FileIngestModule {
private static final Score LIKELY_NOTABLE_SCORE = new Score(Score.Significance.LIKELY_NOTABLE, Score.MethodCategory.AUTO); private static final Score LIKELY_NOTABLE_SCORE = new Score(Score.Significance.LIKELY_NOTABLE, Score.Priority.NORMAL);
private static final Logger logger = Logger.getLogger(FileTypeIdIngestModule.class.getName()); private static final Logger logger = Logger.getLogger(FileTypeIdIngestModule.class.getName());
private static final HashMap<Long, IngestJobTotals> totalsForIngestJobs = new HashMap<>(); private static final HashMap<Long, IngestJobTotals> totalsForIngestJobs = new HashMap<>();

View File

@ -61,10 +61,7 @@ ImportCentralRepoDbProgressDialog.errorParsingFile.message=Error parsing hash se
ImportCentralRepoDbProgressDialog.linesProcessed.message=\ hashes processed ImportCentralRepoDbProgressDialog.linesProcessed.message=\ hashes processed
ImportCentralRepoDbProgressDialog.title.text=Central Repository Import Progress ImportCentralRepoDbProgressDialog.title.text=Central Repository Import Progress
OpenIDE-Module-Display-Category=Ingest Module OpenIDE-Module-Display-Category=Ingest Module
OpenIDE-Module-Long-Description=\ OpenIDE-Module-Long-Description=Hash Set ingest module. \n\nThe ingest module analyzes files in the disk image and marks them as "known" (based on NSRL hashset lookup for "known" files) and "bad / interesting" (based on one or more hash sets supplied by the user).\n\nThe module also contains additional non-ingest tools that are integrated in the GUI, such as file lookup by hash and hash set configuration.
Hash Set ingest module. \n\n\
The ingest module analyzes files in the disk image and marks them as "known" (based on NSRL hashset lookup for "known" files) and "bad / interesting" (based on one or more hash sets supplied by the user).\n\n\
The module also contains additional non-ingest tools that are integrated in the GUI, such as file lookup by hash and hash set configuration.
OpenIDE-Module-Name=HashDatabases OpenIDE-Module-Name=HashDatabases
OptionsCategory_Name_HashDatabase=Hash Sets OptionsCategory_Name_HashDatabase=Hash Sets
OptionsCategory_Keywords_HashDatabase=Hash Sets OptionsCategory_Keywords_HashDatabase=Hash Sets
@ -191,10 +188,7 @@ HashDbSearchThread.name.searching=Searching
HashDbSearchThread.noMoreFilesWithMD5Msg=No other files with the same MD5 hash were found. HashDbSearchThread.noMoreFilesWithMD5Msg=No other files with the same MD5 hash were found.
ModalNoButtons.indexingDbsTitle=Indexing hash sets ModalNoButtons.indexingDbsTitle=Indexing hash sets
ModalNoButtons.indexingDbTitle=Indexing hash set ModalNoButtons.indexingDbTitle=Indexing hash set
ModalNoButtons.exitHashDbIndexingMsg=You are about to exit out of indexing your hash sets. \n\ ModalNoButtons.exitHashDbIndexingMsg=You are about to exit out of indexing your hash sets. \nThe generated index will be left unusable. If you choose to continue,\nplease delete the corresponding -md5.idx file in the hash folder.\nExit indexing?
The generated index will be left unusable. If you choose to continue,\n\
please delete the corresponding -md5.idx file in the hash folder.\n\
Exit indexing?
ModalNoButtons.dlgTitle.unfinishedIndexing=Unfinished Indexing ModalNoButtons.dlgTitle.unfinishedIndexing=Unfinished Indexing
ModalNoButtons.indexThis.currentlyIndexing1Db=Currently indexing 1 hash set ModalNoButtons.indexThis.currentlyIndexing1Db=Currently indexing 1 hash set
ModalNoButtons.indexThese.currentlyIndexing1OfNDbs=Currently indexing 1 of {0} ModalNoButtons.indexThese.currentlyIndexing1OfNDbs=Currently indexing 1 of {0}

View File

@ -511,9 +511,9 @@ public class HashDbIngestModule implements FileIngestModule {
} }
switch (knownFilesType) { switch (knownFilesType) {
case KNOWN: case KNOWN:
return new Score(Significance.NONE, Score.MethodCategory.AUTO); return new Score(Significance.NONE, Score.Priority.NORMAL);
case KNOWN_BAD: case KNOWN_BAD:
return new Score(Significance.NOTABLE, Score.MethodCategory.AUTO); return new Score(Significance.NOTABLE, Score.Priority.NORMAL);
default: default:
case NO_CHANGE: case NO_CHANGE:
return Score.SCORE_UNKNOWN; return Score.SCORE_UNKNOWN;

View File

@ -2,7 +2,6 @@ FilesIdentifierIngestJobSettingsPanel.getError=Error getting interesting files s
FilesIdentifierIngestJobSettingsPanel.updateError=Error updating interesting files sets settings file. FilesIdentifierIngestJobSettingsPanel.updateError=Error updating interesting files sets settings file.
FilesIdentifierIngestModule.getFilesError=Error getting interesting files sets from file. FilesIdentifierIngestModule.getFilesError=Error getting interesting files sets from file.
FilesIdentifierIngestModule.indexError.message=Failed to index interesting file hit artifact for keyword search. FilesIdentifierIngestModule.indexError.message=Failed to index interesting file hit artifact for keyword search.
# {0} - daysIncluded
FilesSet.rule.dateRule.toString=(modified within {0} day(s)) FilesSet.rule.dateRule.toString=(modified within {0} day(s))
FilesSetDefsPanel.bytes=Bytes FilesSetDefsPanel.bytes=Bytes
FilesSetDefsPanel.cancelImportMsg=Cancel import FilesSetDefsPanel.cancelImportMsg=Cancel import
@ -122,8 +121,8 @@ FilesSetRulePanel.nameTextField.text=
FilesSetRulePanel.ruleNameLabel.text=Rule Name (Optional): FilesSetRulePanel.ruleNameLabel.text=Rule Name (Optional):
FilesSetRulePanel.messages.emptyNameCondition=You must specify a name pattern for this rule. FilesSetRulePanel.messages.emptyNameCondition=You must specify a name pattern for this rule.
FilesSetRulePanel.messages.invalidNameRegex=The name regular expression is not valid:\n\n{0} FilesSetRulePanel.messages.invalidNameRegex=The name regular expression is not valid:\n\n{0}
FilesSetRulePanel.messages.invalidCharInName=The name cannot contain \\, /, :, *, ?, \", <, or > unless it is a regular expression. FilesSetRulePanel.messages.invalidCharInName=The name cannot contain \\, /, :, *, ?, ", <, or > unless it is a regular expression.
FilesSetRulePanel.messages.invalidCharInPath=The path cannot contain \\, :, *, ?, \", <, or > unless it is a regular expression. FilesSetRulePanel.messages.invalidCharInPath=The path cannot contain \\, :, *, ?, ", <, or > unless it is a regular expression.
FilesSetRulePanel.messages.invalidPathRegex=The path regular expression is not valid:\n\n{0} FilesSetRulePanel.messages.invalidPathRegex=The path regular expression is not valid:\n\n{0}
FilesSetDefsPanel.doFileSetsDialog.duplicateRuleSet.text=Rule set with name {0} already exists. FilesSetDefsPanel.doFileSetsDialog.duplicateRuleSet.text=Rule set with name {0} already exists.
FilesSetRulePanel.pathSeparatorInfoLabel.text=Folder must be in parent path. Use '/' to give consecutive names FilesSetRulePanel.pathSeparatorInfoLabel.text=Folder must be in parent path. Use '/' to give consecutive names

View File

@ -53,7 +53,7 @@ import org.sleuthkit.datamodel.TskData;
*/ */
@NbBundle.Messages({"FilesIdentifierIngestModule.getFilesError=Error getting interesting files sets from file."}) @NbBundle.Messages({"FilesIdentifierIngestModule.getFilesError=Error getting interesting files sets from file."})
final class FilesIdentifierIngestModule implements FileIngestModule { final class FilesIdentifierIngestModule implements FileIngestModule {
private static final Score LIKELY_NOTABLE_SCORE = new Score(Score.Significance.LIKELY_NOTABLE, Score.MethodCategory.AUTO); private static final Score LIKELY_NOTABLE_SCORE = new Score(Score.Significance.LIKELY_NOTABLE, Score.Priority.NORMAL);
private static final Object sharedResourcesLock = new Object(); private static final Object sharedResourcesLock = new Object();
private static final Logger logger = Logger.getLogger(FilesIdentifierIngestModule.class.getName()); private static final Logger logger = Logger.getLogger(FilesIdentifierIngestModule.class.getName());

View File

@ -24,7 +24,7 @@ PhotoRecIngestModule.complete.totalParsetime=Total Parsing Time:
PhotoRecIngestModule.complete.photoRecResults=PhotoRec Results PhotoRecIngestModule.complete.photoRecResults=PhotoRec Results
PhotoRecIngestModule.NotEnoughDiskSpace.detail.msg=PhotoRec error processing {0} with {1} Not enough space on primary disk to save unallocated space. PhotoRecIngestModule.NotEnoughDiskSpace.detail.msg=PhotoRec error processing {0} with {1} Not enough space on primary disk to save unallocated space.
PhotoRecIngestModule.cancelledByUser=PhotoRec cancelled by user. PhotoRecIngestModule.cancelledByUser=PhotoRec cancelled by user.
PhotoRecIngestModule.error.exitValue=PhotoRec carver returned error exit value \= {0} when scanning {1} PhotoRecIngestModule.error.exitValue=PhotoRec carver returned error exit value = {0} when scanning {1}
PhotoRecIngestModule.error.msg=Error processing {0} with PhotoRec carver. PhotoRecIngestModule.error.msg=Error processing {0} with PhotoRec carver.
PhotoRecIngestModule.complete.numberOfErrors=Number of Errors while Carving: PhotoRecIngestModule.complete.numberOfErrors=Number of Errors while Carving:
PhotoRecCarverIngestJobSettingsPanel.detectionSettingsLabel.text=PhotoRec Settings PhotoRecCarverIngestJobSettingsPanel.detectionSettingsLabel.text=PhotoRec Settings

View File

@ -46,7 +46,7 @@ import org.sleuthkit.datamodel.TskCoreException;
*/ */
final class YaraIngestHelper { final class YaraIngestHelper {
private static final Score NOTABLE_SCORE = new Score(Score.Significance.NOTABLE, Score.MethodCategory.AUTO); private static final Score NOTABLE_SCORE = new Score(Score.Significance.NOTABLE, Score.Priority.NORMAL);
private static final String YARA_DIR = "yara"; private static final String YARA_DIR = "yara";
private static final String YARA_C_EXE = "yarac64.exe"; private static final String YARA_C_EXE = "yarac64.exe";
private static final String MODULE_NAME = YaraIngestModuleFactory.getModuleName(); private static final String MODULE_NAME = YaraIngestModuleFactory.getModuleName();

View File

@ -5,8 +5,8 @@ ReportHTML.getName.text=HTML Report
ReportHTML.getDesc.text=A report about results and tagged items in HTML format. ReportHTML.getDesc.text=A report about results and tagged items in HTML format.
ReportHTML.writeIndex.title=for case {0} ReportHTML.writeIndex.title=for case {0}
ReportHTML.writeIndex.noFrames.msg=Your browser is not compatible with our frame setup. ReportHTML.writeIndex.noFrames.msg=Your browser is not compatible with our frame setup.
ReportHTML.writeIndex.noFrames.seeNav=Please see <a href\="content\nav.html">the navigation page</a> for artifact links, ReportHTML.writeIndex.noFrames.seeNav=Please see <a href="content\nav.html">the navigation page</a> for artifact links,
ReportHTML.writeIndex.seeSum=and <a href\="content\summary.html">the summary page</a> for a case summary. ReportHTML.writeIndex.seeSum=and <a href="contentsummary.html">the summary page</a> for a case summary.
ReportHTML.writeNav.title=Report Navigation ReportHTML.writeNav.title=Report Navigation
ReportHTML.writeNav.h1=Report Navigation ReportHTML.writeNav.h1=Report Navigation
ReportHTML.writeNav.summary=Case Summary ReportHTML.writeNav.summary=Case Summary
@ -16,7 +16,7 @@ ReportHTML.writeSum.caseNumber=Case Number:
ReportHTML.writeSum.caseNumImages=Number of data sources in case: ReportHTML.writeSum.caseNumImages=Number of data sources in case:
ReportHTML.writeSum.examiner=Examiner: ReportHTML.writeSum.examiner=Examiner:
ReportHTML.writeSum.title=Case Summary ReportHTML.writeSum.title=Case Summary
ReportHTML.writeSum.warningMsg=<span>Warning, this report was run before ingest services completed\!</span> ReportHTML.writeSum.warningMsg=<span>Warning, this report was run before ingest services completed!</span>
# #
# autopsy/test/scripts/regression.py._html_report_diff() uses reportGenOn.text, caseName, caseNum, # autopsy/test/scripts/regression.py._html_report_diff() uses reportGenOn.text, caseName, caseNum,
# examiner as a regex signature to skip report.html and summary.html # examiner as a regex signature to skip report.html and summary.html

View File

@ -42,7 +42,7 @@ import org.sleuthkit.datamodel.TskCoreException;
* *
*/ */
class StixArtifactData { class StixArtifactData {
private static final Score LIKELY_NOTABLE_SCORE = new Score(Score.Significance.LIKELY_NOTABLE, Score.MethodCategory.AUTO); private static final Score LIKELY_NOTABLE_SCORE = new Score(Score.Significance.LIKELY_NOTABLE, Score.Priority.NORMAL);
private static final String MODULE_NAME = "Stix"; private static final String MODULE_NAME = "Stix";
private AbstractFile file; private AbstractFile file;

View File

@ -206,7 +206,9 @@ DeleteCaseTask.progress.parsingManifest=Parsing manifest file {0}...
DeleteCaseTask.progress.releasingManifestLock=Releasing lock on the manifest file {0}... DeleteCaseTask.progress.releasingManifestLock=Releasing lock on the manifest file {0}...
DeleteCaseTask.progress.startMessage=Starting deletion... DeleteCaseTask.progress.startMessage=Starting deletion...
DeleteOrphanCaseNodesAction.progressDisplayName=Cleanup Case Znodes DeleteOrphanCaseNodesAction.progressDisplayName=Cleanup Case Znodes
# {0} - item count
DeleteOrphanCaseNodesDialog.additionalInit.lblNodeCount.text=Znodes found: {0} DeleteOrphanCaseNodesDialog.additionalInit.lblNodeCount.text=Znodes found: {0}
# {0} - item count
DeleteOrphanCaseNodesDialog.additionalInit.znodesTextArea.countMessage=ZNODES FOUND: {0} DeleteOrphanCaseNodesDialog.additionalInit.znodesTextArea.countMessage=ZNODES FOUND: {0}
DeleteOrphanCaseNodesTask.progress.connectingToCoordSvc=Connecting to the coordination service DeleteOrphanCaseNodesTask.progress.connectingToCoordSvc=Connecting to the coordination service
# {0} - node path # {0} - node path

View File

@ -56,7 +56,7 @@ import org.sleuthkit.datamodel.TskData.TSK_DB_FILES_TYPE_ENUM;
* artifacts. * artifacts.
*/ */
class VolatilityProcessor { class VolatilityProcessor {
private static final Score LIKELY_NOTABLE_SCORE = new Score(Score.Significance.LIKELY_NOTABLE, Score.MethodCategory.AUTO); private static final Score LIKELY_NOTABLE_SCORE = new Score(Score.Significance.LIKELY_NOTABLE, Score.Priority.NORMAL);
private static final Logger logger = Logger.getLogger(VolatilityProcessor.class.getName()); private static final Logger logger = Logger.getLogger(VolatilityProcessor.class.getName());
private static final String VOLATILITY = "Volatility"; //NON-NLS private static final String VOLATILITY = "Volatility"; //NON-NLS

View File

@ -5,6 +5,7 @@ AccountsText.nextPage.exception.msg=No next page.
AccountsText.previousItem.exception.msg=No previous item. AccountsText.previousItem.exception.msg=No previous item.
AccountsText.previousPage.exception.msg=No previous page. AccountsText.previousPage.exception.msg=No previous page.
CannotRunFileTypeDetection=Unable to run file type detection. CannotRunFileTypeDetection=Unable to run file type detection.
Collection.unableToIndexData.error=Unable to add data to text index. All future text indexing for the current case will be skipped.
DropdownListSearchPanel.selected=Ad Hoc Search data source filter is selected DropdownListSearchPanel.selected=Ad Hoc Search data source filter is selected
DropdownSingleTermSearchPanel.selected=Ad Hoc Search data source filter is selected DropdownSingleTermSearchPanel.selected=Ad Hoc Search data source filter is selected
DropdownSingleTermSearchPanel.warning.text=Boundary characters ^ and $ do not match word boundaries. Consider\nreplacing with an explicit list of boundary characters, such as [ \\.,] DropdownSingleTermSearchPanel.warning.text=Boundary characters ^ and $ do not match word boundaries. Consider\nreplacing with an explicit list of boundary characters, such as [ \\.,]

View File

@ -61,7 +61,7 @@ class LuceneQuery implements KeywordSearchQuery {
static final int SNIPPET_LENGTH = 50; static final int SNIPPET_LENGTH = 50;
static final String HIGHLIGHT_FIELD = Server.Schema.TEXT.toString(); static final String HIGHLIGHT_FIELD = Server.Schema.TEXT.toString();
private static final Score KEYWORD_SEARCH_SCORE = new Score(Score.Significance.LIKELY_NOTABLE, Score.MethodCategory.AUTO); private static final Score KEYWORD_SEARCH_SCORE = new Score(Score.Significance.LIKELY_NOTABLE, Score.Priority.NORMAL);
private static final boolean DEBUG = (Version.getBuildType() == Version.Type.DEVELOPMENT); private static final boolean DEBUG = (Version.getBuildType() == Version.Type.DEVELOPMENT);
/** /**

View File

@ -72,7 +72,7 @@ import org.sleuthkit.datamodel.TskData;
final class RegexQuery implements KeywordSearchQuery { final class RegexQuery implements KeywordSearchQuery {
public static final Logger LOGGER = Logger.getLogger(RegexQuery.class.getName()); public static final Logger LOGGER = Logger.getLogger(RegexQuery.class.getName());
private static final Score LIKELY_NOTABLE_SCORE = new Score(Score.Significance.LIKELY_NOTABLE, Score.MethodCategory.AUTO); private static final Score LIKELY_NOTABLE_SCORE = new Score(Score.Significance.LIKELY_NOTABLE, Score.Priority.NORMAL);
/** /**
* Lucene regular expressions do not support the following Java predefined * Lucene regular expressions do not support the following Java predefined

View File

@ -69,7 +69,7 @@ import org.sleuthkit.datamodel.blackboardutils.WebBrowserArtifactsHelper;
* Chromium recent activity extraction * Chromium recent activity extraction
*/ */
class Chromium extends Extract { class Chromium extends Extract {
private static final Score NOTABLE_SCORE = new Score(Score.Significance.NOTABLE, Score.MethodCategory.AUTO); private static final Score NOTABLE_SCORE = new Score(Score.Significance.NOTABLE, Score.Priority.NORMAL);
private static final String HISTORY_QUERY = "SELECT urls.url, urls.title, urls.visit_count, urls.typed_count, " //NON-NLS private static final String HISTORY_QUERY = "SELECT urls.url, urls.title, urls.visit_count, urls.typed_count, " //NON-NLS
+ "last_visit_time, urls.hidden, visits.visit_time, (SELECT urls.url FROM urls WHERE urls.id=visits.url) AS from_visit, visits.transition FROM urls, visits WHERE urls.id = visits.url"; //NON-NLS + "last_visit_time, urls.hidden, visits.visit_time, (SELECT urls.url FROM urls WHERE urls.id=visits.url) AS from_visit, visits.transition FROM urls, visits WHERE urls.id = visits.url"; //NON-NLS

View File

@ -1,5 +1,5 @@
#Updated by build script #Updated by build script
#Mon, 25 Jan 2021 12:41:22 -0500 #Wed, 02 Jun 2021 10:31:03 -0400
LBL_splash_window_title=Starting Autopsy LBL_splash_window_title=Starting Autopsy
SPLASH_HEIGHT=314 SPLASH_HEIGHT=314
SPLASH_WIDTH=538 SPLASH_WIDTH=538

View File

@ -1,4 +1,4 @@
#Updated by build script #Updated by build script
#Mon, 25 Jan 2021 12:41:22 -0500 #Wed, 02 Jun 2021 10:31:04 -0400
CTL_MainWindow_Title=Autopsy 4.18.0 CTL_MainWindow_Title=Autopsy 4.18.0
CTL_MainWindow_Title_No_Project=Autopsy 4.18.0 CTL_MainWindow_Title_No_Project=Autopsy 4.18.0

View File

@ -75,7 +75,7 @@ import org.sleuthkit.datamodel.blackboardutils.attributes.MessageAttachments.Fil
* structure and metadata. * structure and metadata.
*/ */
public final class ThunderbirdMboxFileIngestModule implements FileIngestModule { public final class ThunderbirdMboxFileIngestModule implements FileIngestModule {
private static final Score NOTABLE_SCORE = new Score(Score.Significance.NOTABLE, Score.MethodCategory.AUTO); private static final Score NOTABLE_SCORE = new Score(Score.Significance.NOTABLE, Score.Priority.NORMAL);
private static final Logger logger = Logger.getLogger(ThunderbirdMboxFileIngestModule.class.getName()); private static final Logger logger = Logger.getLogger(ThunderbirdMboxFileIngestModule.class.getName());
private final IngestServices services = IngestServices.getInstance(); private final IngestServices services = IngestServices.getInstance();