diff --git a/Core/manifest.mf b/Core/manifest.mf index 9225bd195e..b1b23a7da3 100644 --- a/Core/manifest.mf +++ b/Core/manifest.mf @@ -2,7 +2,7 @@ Manifest-Version: 1.0 OpenIDE-Module: org.sleuthkit.autopsy.core/10 OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/core/Bundle.properties OpenIDE-Module-Layer: org/sleuthkit/autopsy/core/layer.xml -OpenIDE-Module-Implementation-Version: 35 +OpenIDE-Module-Implementation-Version: 36 OpenIDE-Module-Requires: org.openide.windows.WindowManager AutoUpdate-Show-In-Client: true AutoUpdate-Essential-Module: true diff --git a/Core/nbproject/project.properties b/Core/nbproject/project.properties index fceb64d406..8a1c304521 100644 --- a/Core/nbproject/project.properties +++ b/Core/nbproject/project.properties @@ -109,8 +109,8 @@ file.reference.protobuf-java-util-3.7.0.jar=release\\modules\\ext\\protobuf-java file.reference.Rejistry-1.1-SNAPSHOT.jar=release\\modules\\ext\\Rejistry-1.1-SNAPSHOT.jar file.reference.sevenzipjbinding-AllPlatforms.jar=release\\modules\\ext\\sevenzipjbinding-AllPlatforms.jar file.reference.sevenzipjbinding.jar=release\\modules\\ext\\sevenzipjbinding.jar -file.reference.sleuthkit-4.10.2.jar=release/modules/ext/sleuthkit-4.10.2.jar -file.reference.sleuthkit-caseuco-4.10.2.jar=release/modules/ext/sleuthkit-caseuco-4.10.2.jar +file.reference.sleuthkit-4.11.0.jar=release/modules/ext/sleuthkit-4.11.0.jar +file.reference.sleuthkit-caseuco-4.11.0.jar=release/modules/ext/sleuthkit-caseuco-4.11.0.jar file.reference.slf4j-api-1.7.6.jar=release\\modules\\ext\\slf4j-api-1.7.6.jar file.reference.slf4j-log4j12-1.7.6.jar=release\\modules\\ext\\slf4j-log4j12-1.7.6.jar file.reference.SparseBitSet-1.1.jar=release\\modules\\ext\\SparseBitSet-1.1.jar @@ -128,4 +128,4 @@ nbm.homepage=http://www.sleuthkit.org/ nbm.module.author=Brian Carrier nbm.needs.restart=true source.reference.curator-recipes-2.8.0.jar=release/modules/ext/curator-recipes-2.8.0-sources.jar -spec.version.base=10.23 +spec.version.base=10.24 diff --git a/Core/nbproject/project.xml b/Core/nbproject/project.xml index ab23992798..efab89ff8b 100644 --- a/Core/nbproject/project.xml +++ b/Core/nbproject/project.xml @@ -682,8 +682,8 @@ release\modules\ext\grpc-alts-1.19.0.jar - ext/sleuthkit-caseuco-4.10.2.jar - release/modules/ext/sleuthkit-caseuco-4.10.2.jar + ext/sleuthkit-caseuco-4.11.0.jar + release/modules/ext/sleuthkit-caseuco-4.11.0.jar ext/jdom-2.0.5.jar @@ -802,8 +802,8 @@ release\modules\ext\sevenzipjbinding-AllPlatforms.jar - ext/sleuthkit-4.10.2.jar - release/modules/ext/sleuthkit-4.10.2.jar + ext/sleuthkit-4.11.0.jar + release/modules/ext/sleuthkit-4.11.0.jar ext/jutf7-1.0.0.jar diff --git a/Core/src/org/sleuthkit/autopsy/actions/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/actions/Bundle.properties-MERGED index 5c9a0ea3ac..cc5c9222e4 100755 --- a/Core/src/org/sleuthkit/autopsy/actions/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/actions/Bundle.properties-MERGED @@ -1,24 +1,18 @@ AddBlackboardArtifactTagAction.pluralTagResult=Add Result Tags AddBlackboardArtifactTagAction.singularTagResult=Add Result Tag AddBlackboardArtifactTagAction.taggingErr=Tagging Error -# {0} - artifactName AddBlackboardArtifactTagAction.unableToTag.msg=Unable to tag {0}. AddContentTagAction.cannotApplyTagErr=Cannot Apply Tag AddContentTagAction.pluralTagFile=Add File Tags AddContentTagAction.singularTagFile=Add File Tag -# {0} - fileName -# {1} - tagName AddContentTagAction.tagExists={0} has been tagged as {1}. Cannot reapply the same tag. AddContentTagAction.taggingErr=Tagging Error -# {0} - fileName AddContentTagAction.unableToTag.msg=Unable to tag {0}, not a regular file. -# {0} - fileName AddContentTagAction.unableToTag.msg2=Unable to tag {0}. CTL_DumpThreadAction=Thread Dump CTL_ShowIngestProgressSnapshotAction=Ingest Status Details DeleteBlackboardArtifactTagAction.deleteTag=Remove Selected Tag(s) DeleteBlackboardArtifactTagAction.tagDelErr=Tag Deletion Error -# {0} - tagName DeleteBlackboardArtifactTagAction.unableToDelTag.msg=Unable to delete tag {0}. DeleteContentTagAction.deleteTag=Remove Selected Tag(s) DeleteContentTagAction.tagDelErr=Tag Deletion Error @@ -84,8 +78,6 @@ CTL_OpenOutputFolder=Open Case Folder OpenOutputFolder.error1=Case Folder Not Found: {0} OpenOutputFolder.noCaseOpen=No open case, therefore no current case folder available. OpenOutputFolder.CouldNotOpenOutputFolder=Could not open case folder -# {0} - old tag name -# {1} - artifactID ReplaceBlackboardArtifactTagAction.replaceTag.alert=Unable to replace tag {0} for artifact {1}. # {0} - old tag name # {1} - content obj id diff --git a/Core/src/org/sleuthkit/autopsy/actions/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/actions/Bundle_ja.properties index a4fff0acfa..c5346f4cf9 100644 --- a/Core/src/org/sleuthkit/autopsy/actions/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/actions/Bundle_ja.properties @@ -1,4 +1,4 @@ -#Fri Feb 12 16:56:28 UTC 2021 +#Thu Jul 01 11:56:41 UTC 2021 AddBlackboardArtifactTagAction.pluralTagResult=\u7d50\u679c\u30bf\u30b0\u3092\u8ffd\u52a0 AddBlackboardArtifactTagAction.singularTagResult=\u7d50\u679c\u30bf\u30b0\u3092\u8ffd\u52a0 AddBlackboardArtifactTagAction.taggingErr=\u30bf\u30b0\u4ed8\u3051\u30a8\u30e9\u30fc @@ -17,6 +17,7 @@ AddTagAction.noTags=\u30bf\u30b0\u306a\u3057 AddTagAction.quickTag=\u30af\u30a4\u30c3\u30af\u30bf\u30b0 AddTagAction.tagAndComment=\u30bf\u30b0\u3068\u30b3\u30e1\u30f3\u30c8... CTL_DumpThreadAction=\u30b9\u30ec\u30c3\u30c9 \u30c0\u30f3\u30d7 +CTL_ExitAction=\u51fa\u53e3 CTL_OpenLogFolder=\u30ed\u30b0\u30d5\u30a9\u30eb\u30c0\u30fc\u3092\u958b\u304f CTL_OpenOutputFolder=\u51fa\u529b\u30d5\u30a9\u30eb\u30c0\u30fc\u3092\u958b\u304f CTL_OpenPythonModulesFolderAction=Python\u30d7\u30e9\u30b0\u30a4\u30f3 diff --git a/Core/src/org/sleuthkit/autopsy/apputils/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/apputils/Bundle_ja.properties new file mode 100644 index 0000000000..13d8229e84 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/apputils/Bundle_ja.properties @@ -0,0 +1,5 @@ +#Thu Jul 01 11:56:40 UTC 2021 +CTL_ResetWindowsAction=\u30a6\u30a3\u30f3\u30c9\u30a6\u3092\u30ea\u30bb\u30c3\u30c8 +ResetWindowAction.caseCloseFailure.text=\u73fe\u5728\u306e\u30b1\u30fc\u30b9\u3092\u9589\u3058\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u305b\u3093\u3002\u30bd\u30d5\u30c8\u30a6\u30a7\u30a2\u306f\u518d\u8d77\u52d5\u3057\u3001\u6b21\u306b\u30bd\u30d5\u30c8\u30a6\u30a7\u30a2\u3092\u9589\u3058\u308b\u3068\u304d\u306bWindows\u306e\u5834\u6240\u304c\u30ea\u30bb\u30c3\u30c8\u3055\u308c\u307e\u3059\u3002 +ResetWindowAction.caseSaveMetadata.text=\u73fe\u5728\u306e\u30b1\u30fc\u30b9\u30d1\u30b9\u3092\u4fdd\u5b58\u3067\u304d\u307e\u305b\u3093\u3002\u30bd\u30d5\u30c8\u30a6\u30a7\u30a2\u306f\u518d\u8d77\u52d5\u3057\u3001Windows\u306e\u5834\u6240\u306f\u30ea\u30bb\u30c3\u30c8\u3055\u308c\u307e\u3059\u304c\u3001\u518d\u8d77\u52d5\u6642\u306b\u73fe\u5728\u306e\u30b1\u30fc\u30b9\u306f\u958b\u304b\u308c\u307e\u305b\u3093\u3002 +ResetWindowAction.confirm.text=\u30a6\u30a3\u30f3\u30c9\u30a6\u306e\u5834\u6240\u306e\u30ea\u30bb\u30c3\u30c8\u3092\u5b9f\u884c\u3059\u308b\u305f\u3081\u306b\u3001\u30bd\u30d5\u30c8\u30a6\u30a7\u30a2\u306f\u9589\u3058\u3066\u518d\u8d77\u52d5\u3057\u307e\u3059\u3002 \u30b1\u30fc\u30b9\u304c\u73fe\u5728\u958b\u3044\u3066\u3044\u308b\u5834\u5408\u306f\u3001\u9589\u3058\u3089\u308c\u307e\u3059\u3002 \u53d6\u308a\u8fbc\u307f\u307e\u305f\u306f\u691c\u7d22\u304c\u73fe\u5728\u5b9f\u884c\u4e2d\u306e\u5834\u5408\u3001\u305d\u308c\u306f\u5f37\u5236\u7d42\u4e86\u3057\u307e\u3059\u3002 \u30bd\u30d5\u30c8\u30a6\u30a7\u30a2\u3092\u518d\u8d77\u52d5\u3057\u3066\u3001\u3059\u3079\u3066\u306e\u30a6\u30a3\u30f3\u30c9\u30a6\u306e\u5834\u6240\u3092\u30ea\u30bb\u30c3\u30c8\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b\uff1f diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties-MERGED index 528d3a5088..9a43ffe229 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties-MERGED @@ -247,15 +247,10 @@ AddImageWizardIngestConfigPanel.dsProcDone.errs.text=*Errors encountered in addi AddImageWizardIngestConfigVisual.getName.text=Configure Ingest AddImageWizardIterator.stepXofN=Step {0} of {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.title=Case Database Schema Update -Case.checkImgExist.confDlg.doesntExist.msg=One of the images associated with \n\ -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.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. Case.checkImgExist.confDlg.doesntExist.title=Missing Image Case.addImg.exception.msg=Error adding image to the case 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.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} -CaseDeleteAction.closeConfMsg.text=Are you sure want to close and delete this case? \n\ - Case Name: {0}\n\ - Case Directory: {1} +CaseDeleteAction.closeConfMsg.text=Are you sure want to close and delete this case? \nCase Name: {0}\nCase Directory: {1} 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\ -Close the folder and file and try again or you can delete the case manually. +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. CaseDeleteAction.msgDlg.fileInUse.title=Error: Folder In Use CaseDeleteAction.msgDlg.caseDelete.msg=Case {0} has been deleted. CaseOpenAction.autFilter.title={0} Case File ( {1}) @@ -311,8 +303,7 @@ NewCaseWizardAction.databaseProblem1.text=Cannot open database. Cancelling case NewCaseWizardAction.databaseProblem2.text=Error 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.confMsg.createDir.msg=The base directory "{0}" does not exist. \n\n\ - Do you want to create that directory? +NewCaseWizardPanel1.validate.confMsg.createDir.msg=The base directory "{0}" does not exist. \n\nDo you want to create that directory? NewCaseWizardPanel1.validate.confMsg.createDir.title=Create directory NewCaseWizardPanel1.validate.errMsg.cantCreateParDir.msg=Error: Could not create case parent 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 RecentCases.exception.caseIdxOutOfRange.msg=Recent case index {0} is out of range. RecentCases.getName.text=Clear Recent Cases -# {0} - case name RecentItems.openRecentCase.msgDlg.text=Case {0} no longer exists. SelectDataSourceProcessorPanel.name.text=Select Data Source Type 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.UnpackagePortableCaseDialog.extensions=Portable case package (.zip, .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.caseIsNotFile=Selected path is not a file 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.empty=-Empty- AddImageWizardIngestConfigPanel.CANCEL_BUTTON.text=Cancel -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.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.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 CollaborationMonitor.addingDataSourceStatus.msg={0} adding data source @@ -378,7 +367,7 @@ CollaborationMonitor.analyzingDataSourceStatus.msg={0} analyzing {1} MissingImageDialog.lbWarning.text= MissingImageDialog.lbWarning.toolTipText= NewCaseVisualPanel1.caseParentDirWarningLabel.text= -NewCaseVisualPanel1.multiUserCaseRadioButton.text=Multi-User +NewCaseVisualPanel1.multiUserCaseRadioButton.text=Multi-User\t\t NewCaseVisualPanel1.singleUserCaseRadioButton.text=Single-User NewCaseVisualPanel1.caseTypeLabel.text=Case Type: SingleUserCaseConverter.BadDatabaseFileName=Database file does not exist! diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle_ja.properties index f85f5c62d2..1e4326befe 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle_ja.properties @@ -1,4 +1,4 @@ -#Fri Feb 12 16:56:28 UTC 2021 +#Mon Jul 12 13:21:59 UTC 2021 AddImageAction.ingestConfig.ongoingIngest.msg=\u5225\u306e\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3067\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u304c\u9032\u884c\u4e2d\u3067\u3059\u3002\u65b0\u898f\u30bd\u30fc\u30b9\u3092\u4eca\u8ffd\u52a0\u3059\u308b\u3068\u3001\u73fe\u5728\u306e\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u306e\u51e6\u7406\u304c\u9045\u304f\u306a\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002
\u7d9a\u884c\u3057\u3066\u65b0\u898f\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u4eca\u3059\u3050\u8ffd\u52a0\u3057\u307e\u3059\u304b? AddImageAction.ingestConfig.ongoingIngest.title=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u304c\u9032\u884c\u4e2d\u3067\u3059 AddImageAction.wizard.title=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u8ffd\u52a0 @@ -25,10 +25,17 @@ AddImageWizardChooseDataSourceVisual.getName.text=\u30c7\u30fc\u30bf\u30bd\u30fc AddImageWizardIngestConfigPanel.CANCEL_BUTTON.text=\u53d6\u308a\u6d88\u3057 AddImageWizardIngestConfigPanel.dsProcDone.errs.text=*\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u306e\u8ffd\u52a0\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 AddImageWizardIngestConfigPanel.dsProcDone.noErrs.text=*\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u8ffd\u52a0\u3057\u307e\u3057\u305f\u3002 -AddImageWizardIngestConfigPanel.name.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u69cb\u6210 -AddImageWizardIngestConfigVisual.getName.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u69cb\u6210 +AddImageWizardIngestConfigPanel.name.text=\u53d6\u8fbc\u307f\u306e\u69cb\u6210 +AddImageWizardIngestConfigVisual.getName.text=\u53d6\u8fbc\u307f\u306e\u69cb\u6210 AddImageWizardIterator.stepXofN=\u624b\u9806 {0} / {1} AddImageWizardSelectDspVisual.multiUserWarning.text=\u3053\u306e\u30bf\u30a4\u30d7\u306e\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u30d7\u30ed\u30bb\u30c3\u30b5\u30fc\u306f\u30de\u30eb\u30c1\u30e6\u30fc\u30b6\u30fc\u30e2\u30fc\u30c9\u3067\u5229\u7528\u3067\u304d\u307e\u305b\u3093\u3002 +AddImageWizardSelectHostPanel_title=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u8ffd\u52a0\u3059\u308b\u30db\u30b9\u30c8\u306e\u9078\u629e +AddImageWizardSelectHostVisual.generateNewRadio.text=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u540d\u306b\u57fa\u3065\u3044\u3066\u65b0\u30db\u30b9\u30c8\u540d\u306e\u4f5c\u6210 +AddImageWizardSelectHostVisual.hostDescription.text=\u30db\u30b9\u30c8\u306f\u3001\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3084\u305d\u306e\u4ed6\u306e\u30c7\u30fc\u30bf\u3092\u6574\u7406\u3059\u308b\u305f\u3081\u306b\u4f7f\u7528\u3055\u308c\u307e\u3059\u3002 +AddImageWizardSelectHostVisual.specifyNewHostRadio.text=\u65b0\u30db\u30b9\u30c8\u540d\u306e\u6307\u5b9a +AddImageWizardSelectHostVisual.useExistingHostRadio.text=\u65e2\u5b58\u306e\u30db\u30b9\u30c8\u306e\u4f7f\u7528 +AddImageWizardSelectHostVisual_getValidationMessage_noHostSelected=\u65e2\u5b58\u306e\u30db\u30b9\u30c8\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002 +AddImageWizardSelectHostVisual_title=\u30db\u30b9\u30c8\u306e\u9078\u629e AddLocalFilesTask.localFileAdd.progress.text=\u6b21\u3092\u8ffd\u52a0\u4e2d\u3067\u3059\: {0}/{1} CTL_AddImage=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u8ffd\u52a0 CTL_AddImageButton=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u8ffd\u52a0 @@ -60,6 +67,7 @@ Case.deleteCaseFailureMessageBox.title=\u30b1\u30fc\u30b9\u3092\u524a\u9664\u306 Case.deleteReports.deleteFromDiskException.log.msg=\u30c7\u30a3\u30b9\u30af\u304b\u3089\u30ec\u30dd\u30fc\u30c8\u3092\u524a\u9664\u3067\u304d\u307e\u305b\u3093\u3002 Case.deleteReports.deleteFromDiskException.msg=\u30c7\u30a3\u30b9\u30af\u304b\u3089\u30ec\u30dd\u30fc\u30c8 {0} \u3092\u524a\u9664\u3067\u304d\u307e\u305b\u3093\u3002\n{1} \u304b\u3089\u624b\u52d5\u3067\u524a\u9664\u3067\u304d\u307e\u3059 Case.exception.errGetRootObj=\u30eb\u30fc\u30c8\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306e\u53d6\u5f97\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +Case.exceptionMessage.cancelled=\u30ad\u30e3\u30f3\u30bb\u30eb\u3002 Case.exceptionMessage.cancelledByUser=\u30e6\u30fc\u30b6\u30fc\u306b\u3088\u3063\u3066\u53d6\u308a\u6d88\u3055\u308c\u307e\u3057\u305f\u3002 Case.exceptionMessage.cannotDeleteCurrentCase=\u73fe\u5728\u306e\u30b1\u30fc\u30b9\u3092\u524a\u9664\u3067\u304d\u307e\u305b\u3093\u3002\u6700\u521d\u306b\u9589\u3058\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002 Case.exceptionMessage.cannotGetLockToDeleteCase=\u5225\u306e\u30e6\u30fc\u30b6\u30fc\u307e\u305f\u306f\u30db\u30b9\u30c8\u304c\u958b\u3044\u3066\u3044\u308b\u305f\u3081\u73fe\u5728\u306e\u30b1\u30fc\u30b9\u3092\u524a\u9664\u3067\u304d\u307e\u305b\u3093\u3002 @@ -74,9 +82,12 @@ Case.exceptionMessage.couldNotOpenRemoteEventChannel=\u30ea\u30e2\u30fc\u30c8\u3 Case.exceptionMessage.couldNotSaveCaseMetadata=\u30b1\u30fc\u30b9\u30e1\u30bf\u30c7\u30fc\u30bf\u3092\u4fdd\u5b58\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\:\n{0}\u3002 Case.exceptionMessage.couldNotSaveDbNameToMetadataFile=\u30b1\u30fc\u30b9\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u540d\u3092\u30b1\u30fc\u30b9\u30e1\u30bf\u30c7\u30fc\u30bf\u30d5\u30a1\u30a4\u30eb\u306b\u4fdd\u5b58\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\:\n{0}\u3002 Case.exceptionMessage.couldNotUpdateCaseNodeData=\u5ea7\u6a19\u30b5\u30fc\u30d3\u30b9\u30ce\u30fc\u30c9\u30c7\u30fc\u30bf\u3092\u66f4\u65b0\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\:\n{0}\u3002 +Case.exceptionMessage.dataSourceNotFound=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f\u3002 Case.exceptionMessage.deletionInterrupted=\u30b1\u30fc\u30b9 {0} \u306e\u524a\u9664\u304c\u53d6\u308a\u6d88\u3055\u308c\u307e\u3057\u305f\u3002 Case.exceptionMessage.emptyCaseDir=\u30b1\u30fc\u30b9\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u30fc\u30d1\u30b9\u3092\u6307\u5b9a\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002 Case.exceptionMessage.emptyCaseName=\u30b1\u30fc\u30b9\u540d\u3092\u6307\u5b9a\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002 +Case.exceptionMessage.errorDeletingDataSourceFromCaseDb=\u30b1\u30fc\u30b9\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304b\u3089\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u524a\u9664\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +Case.exceptionMessage.errorDeletingDataSourceFromTextIndex=\u30c6\u30ad\u30b9\u30c8\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u304b\u3089\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u524a\u9664\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 Case.exceptionMessage.errorsDeletingCase=\u30b1\u30fc\u30b9\u306e\u524a\u9664\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002\u8a73\u7d30\u306f\u3001\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u30ed\u30b0\u3092\u53c2\u7167\u3057\u3066\u304f\u3060\u3055\u3044\u3002 Case.exceptionMessage.execExceptionWrapperMessage={0} Case.exceptionMessage.failedToConnectToCoordSvc=\u5ea7\u6a19\u30b5\u30fc\u30d3\u30b9\u306b\u63a5\u7d9a\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\:\n{0}. @@ -86,6 +97,8 @@ Case.exceptionMessage.failedToReadMetadata=\u30b1\u30fc\u30b9\u30e1\u30bf\u30c7\ Case.exceptionMessage.metadataUpdateError=\u30b1\u30fc\u30b9\u30e1\u30bf\u30c7\u30fc\u30bf\u3092\u66f4\u65b0\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f Case.exceptionMessage.unsupportedSchemaVersionMessage=\u30b5\u30dd\u30fc\u30c8\u3055\u308c\u3066\u3044\u306a\u3044\u30b1\u30fc\u30b9\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30b9\u30ad\u30fc\u30de\u30d0\u30fc\u30b8\u30e7\u30f3\u3067\u3059\:\n{0}\u3002 Case.getCurCase.exception.noneOpen=\u73fe\u5728\u306e\u30b1\u30fc\u30b9\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3002\u30b1\u30fc\u30b9\u304c\u958b\u304b\u308c\u3066\u3044\u307e\u305b\u3093\! +Case.lockingException.couldNotAcquireExclusiveLock=\u30b1\u30fc\u30b9\u306e\u6392\u4ed6\u30ed\u30c3\u30af\u304c\u51fa\u6765\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +Case.lockingException.couldNotAcquireSharedLock=\u30b1\u30fc\u30b9\u306e\u5171\u6709\u30ed\u30c3\u30af\u304c\u51fa\u6765\u307e\u305b\u3093\u3067\u3057\u305f\u3002 Case.metaDataFileCorrupt.exception.msg=\u30b1\u30fc\u30b9\u30e1\u30bf\u30c7\u30fc\u30bf\u30d5\u30a1\u30a4\u30eb(.aut)\u304c\u7834\u640d\u3057\u3066\u3044\u307e\u3059\u3002 Case.open.exception.multiUserCaseNotEnabled=\u30de\u30eb\u30c1\u30e6\u30fc\u30b6\u30fc\u30b1\u30fc\u30b9\u304c\u6709\u52b9\u3067\u306a\u3044\u5834\u5408\u306f\u30de\u30eb\u30c1\u30e6\u30fc\u30b6\u30fc\u30b1\u30fc\u30b9\u3092\u958b\u3051\u307e\u305b\u3093\u3002[\u30c4\u30fc\u30eb]\u3001[\u30aa\u30d7\u30b7\u30e7\u30f3]\u3001[\u30de\u30eb\u30c1\u30e6\u30fc\u30b6\u30fc] \u3092\u53c2\u7167\u3057\u3066\u304f\u3060\u3055\u3044\u3002 Case.open.msgDlg.updated.msg=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30b9\u30ad\u30fc\u30de\u3092\u66f4\u65b0\u3057\u307e\u3057\u305f\u3002\n\u6b21\u306e\u30d1\u30b9\u3092\u6301\u3064\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30d0\u30c3\u30af\u30a2\u30c3\u30d7\u30b3\u30d4\u30fc\u3092\u4f5c\u6210\u3057\u307e\u3057\u305f\:\n {0} @@ -96,6 +109,7 @@ Case.progressIndicatorCancelButton.label=\u53d6\u308a\u6d88\u3057 Case.progressIndicatorTitle.closingCase=\u30b1\u30fc\u30b9\u3092\u9589\u3058\u3066\u3044\u307e\u3059 Case.progressIndicatorTitle.creatingCase=\u30b1\u30fc\u30b9\u3092\u4f5c\u6210\u4e2d\u3067\u3059 Case.progressIndicatorTitle.deletingCase=\u30b1\u30fc\u30b9\u3092\u524a\u9664\u4e2d\u3067\u3059 +Case.progressIndicatorTitle.deletingDataSource=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u306e\u524a\u9664\u4e2d Case.progressIndicatorTitle.openingCase=\u30b1\u30fc\u30b9\u3092\u958b\u3044\u3066\u3044\u307e\u3059 Case.progressMessage.cancelling=\u53d6\u308a\u6d88\u3057\u4e2d\u3067\u3059... Case.progressMessage.clearingTempDirectory=\u30b1\u30fc\u30b9\u306e\u4e00\u6642\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u30fc\u3092\u6d88\u53bb\u4e2d\u3067\u3059... @@ -109,6 +123,7 @@ Case.progressMessage.creatingCaseNodeData=\u5ea7\u6a19\u30b5\u30fc\u30d3\u30b9\u Case.progressMessage.deletingCaseDatabase=\u30b1\u30fc\u30b9\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u524a\u9664\u4e2d\u3067\u3059... Case.progressMessage.deletingCaseDirCoordSvcNode=\u30b1\u30fc\u30b9\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u30fc\u306e\u5ea7\u6a19\u30b5\u30fc\u30d3\u30b9\u30ce\u30fc\u30c9\u30c7\u30fc\u30bf\u3092\u524a\u9664\u4e2d\u3067\u3059... Case.progressMessage.deletingCaseDirectory=\u30b1\u30fc\u30b9\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u30fc\u3092\u524a\u9664\u4e2d\u3067\u3059... +Case.progressMessage.deletingDataSource=\u30b1\u30fc\u30b9\u304b\u3089\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u524a\u9664\u4e2d... Case.progressMessage.deletingResourcesCoordSvcNode=\u30b1\u30fc\u30b9\u30ea\u30bd\u30fc\u30b9\u306e\u5ea7\u6a19\u30b5\u30fc\u30d3\u30b9\u30ce\u30fc\u30c9\u30c7\u30fc\u30bf\u3092\u524a\u9664\u4e2d\u3067\u3059... Case.progressMessage.deletingTextIndex=\u30c6\u30ad\u30b9\u30c8\u7d22\u5f15\u3092\u524a\u9664\u4e2d\u3067\u3059... Case.progressMessage.fetchingCoordSvcNodeData=\u30b1\u30fc\u30b9\u306e\u5ea7\u6a19\u30b5\u30fc\u30d3\u30b9\u30ce\u30fc\u30c9\u30c7\u30fc\u30bf\u3092\u53d6\u5f97\u4e2d\u3067\u3059... @@ -179,6 +194,11 @@ CueBannerPanel.openCaseLabel.text=\u30b1\u30fc\u30b9\u3092\u958b\u304f CueBannerPanel.openRecentCaseButton.text= CueBannerPanel.openRecentCaseLabel.text=\u6700\u8fd1\u306e\u30b1\u30fc\u30b9\u3092\u958b\u304f CueBannerPanel.title.text=\u6700\u8fd1\u306e\u30b1\u30fc\u30b9\u3092\u958b\u304f +DeleteDataSourceAction.confirmationDialog.message=\u9078\u629e\u3057\u305f\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u30b1\u30fc\u30b9\u304b\u3089\u524a\u9664\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b\uff1f\n\u6ce8\u610f\uff1a\u524a\u9664\u4e2d\u306b\u30b1\u30fc\u30b9\u304c\u9589\u3058\u3089\u308c\u3001\u518d\u3073\u958b\u304b\u308c\u307e\u3059\u3002\u300d +DeleteDataSourceAction.exceptionMessage.couldNotReopenCase=\u30b1\u30fc\u30b9\u3092\u518d\u958b\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\uff1a\n{0}\n\u8a73\u7d30\u306b\u3064\u3044\u3066\u306f\u3001\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u30ed\u30b0\u3092\u53c2\u7167\u3057\u3066\u304f\u3060\u3055\u3044\u3002 +DeleteDataSourceAction.exceptionMessage.dataSourceDeletionError=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u306e\u524a\u9664\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\uff1a\n{0}\n\u8a73\u7d30\u306b\u3064\u3044\u3066\u306f\u3001\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u30ed\u30b0\u3092\u53c2\u7167\u3057\u3066\u304f\u3060\u3055\u3044\u3002 +DeleteDataSourceAction.ingestRunningWarningDialog.message=\u53d6\u8fbc\u307f\u306e\u5b9f\u884c\u4e2d\u306f\u3001\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u30b1\u30fc\u30b9\u304b\u3089\u524a\u9664\u3059\u308b\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093\u3002 +DeleteDataSourceAction.name.text=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u524a\u9664\u3059\u308b EditOptionalCasePropertiesPanel.cancelButton.text=\u53d6\u308a\u6d88\u3057 EditOptionalCasePropertiesPanel.saveButton.text=\u4fdd\u5b58 GeneralFilter.encaseImageDesc.text=\u30a4\u30e1\u30fc\u30b8(*.e01)\u3092\u5305\u542b @@ -297,7 +317,6 @@ LogicalEvidenceFilePanel.selectButton.toolTipText=\u30ed\u30fc\u30ab\u30eb\u30d5 LogicalEvidenceFilePanel.validatePanel.nonL01Error.text=\u3053\u3053\u3067\u306f .l01\u30d5\u30a1\u30a4\u30eb\u62e1\u5f35\u5b50\u3092\u6301\u3064\u30d5\u30a1\u30a4\u30eb\u306e\u307f\u304c\u30b5\u30dd\u30fc\u30c8\u3055\u308c\u3066\u3044\u307e\u3059\u3002 LogicalFilesDspPanel.subTypeComboBox.l01FileOption.text=\u8ad6\u7406\u8a3c\u62e0\u30d5\u30a1\u30a4\u30eb(L01) LogicalFilesDspPanel.subTypeComboBox.localFilesOption.text=\u30ed\u30fc\u30ab\u30eb\u30d5\u30a1\u30a4\u30eb\u304a\u3088\u3073\u30d5\u30a9\u30eb\u30c0\u30fc -Menu/Case/OpenRecentCase=\u6700\u8fd1\u306e\u30b1\u30fc\u30b9\u3092\u958b\u304f MissingImageDialog.ErrorSettingImage=\u30a4\u30e1\u30fc\u30b8\u30d1\u30b9\u306e\u8a2d\u5b9a\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002\u3082\u3046\u4e00\u5ea6\u304a\u8a66\u3057\u304f\u3060\u3055\u3044\u3002 MissingImageDialog.browseButton.text=\u53c2\u7167 MissingImageDialog.cancelButton.text=\u53d6\u308a\u6d88\u3057 @@ -349,6 +368,7 @@ OpenMultiUserCaseDialog.title=\u30de\u30eb\u30c1\u30e6\u30fc\u30b6\u30fc\u30b1\u OpenMultiUserCasePanel.cancelButton.text=\u53d6\u308a\u6d88\u3057 OpenMultiUserCasePanel.openSelectedCaseButton.text=\u9078\u629e\u3057\u305f\u30b1\u30fc\u30b9\u3092\u958b\u304f OpenMultiUserCasePanel.openSingleUserCaseButton.tex=\u30b7\u30f3\u30b0\u30eb\u30e6\u30fc\u30b6\u30fc\u30b1\u30fc\u30b9\u3092\u958b\u304f... +OpenMultiUserCasePanel.openSingleUserCaseButton.text=\u5358\u72ec\u30e6\u30fc\u30b6\u30fc\u30b1\u30fc\u30b9\u3092\u958b\u304f... OpenMultiUserCasePanel.searchLabel.text=\u4efb\u610f\u306e\u30b1\u30fc\u30b9\u3092\u9078\u629e\u3057\u3001\u5165\u529b\u3092\u958b\u59cb\u3057\u3066\u30b1\u30fc\u30b9\u540d\u3067\u691c\u7d22 OpenRecentCasePanel.cancelButton.text=\u53d6\u308a\u6d88\u3057 OpenRecentCasePanel.colName.caseName=\u30b1\u30fc\u30b9\u540d @@ -384,7 +404,7 @@ ReviewModeCasePanel.StatusIconHeaderText=\u30b9\u30c6\u30fc\u30bf\u30b9 ReviewModeCasePanel.cannotOpenCase=\u30b1\u30fc\u30b9\u3092\u958b\u3051\u307e\u305b\u3093 ReviewModeCasePanel.caseIsLocked=\u30b7\u30f3\u30b0\u30eb\u30e6\u30fc\u30b6\u30fc\u304c\u30ed\u30c3\u30af\u3055\u308c\u3066\u3044\u307e\u3059\u3002 ReviewModeCasePanel.casePathNotFound=\u30b1\u30fc\u30b9\u30d1\u30b9\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093 -SelectDataSourceProcessorPanel.name.text=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u306e\u30bf\u30a4\u30d7\u3092\u9078\u629e\u3057\u3066\u8ffd\u52a0 +SelectDataSourceProcessorPanel.name.text=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u30bf\u30a4\u30d7\u306e\u9078\u629e SingleUserCaseConverter.AlreadyMultiUser=\u30b1\u30fc\u30b9\u306f\u3059\u3067\u306b\u30de\u30eb\u30c1\u30e6\u30fc\u30b6\u30fc\u3067\u3059\! SingleUserCaseConverter.BadDatabaseFileName=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb\u306f\u5b58\u5728\u3057\u307e\u305b\u3093\! SingleUserCaseConverter.CanNotOpenDatabase=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u958b\u3051\u307e\u305b\u3093 @@ -395,6 +415,9 @@ SolrNotConfiguredDialog.messageLabel.text=\u30de\u30eb\u30c1\u30e6\u30fc\u SolrNotConfiguredDialog.okButton.text=OK SolrNotConfiguredDialog.title=Solr8\u30b5\u30fc\u30d0\u30fc\u304c\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u307e\u305b\u3093 StartupWindow.title.text=\u3088\u3046\u3053\u305d +StartupWindowProvider.openCase.cantOpen=\u4ee5\u524d\u306b\u958b\u3044\u305f\u30e1\u30bf\u30c7\u30fc\u30bf\u30d5\u30a1\u30a4\u30eb\u4ed8\u304d\u306e\u30b1\u30fc\u30b9\u3092\u958b\u304f\u3053\u3068\u304c\u3067\u304d\u307e\u305b\u3093\uff1a{0} +StartupWindowProvider.openCase.deleteOpenFailure=\u4ee5\u524d\u306b\u958b\u3044\u305f\u30d1\u30b9{0}\u3092\u542b\u3080\u30b1\u30fc\u30b9\u306e\u30d5\u30a1\u30a4\u30eb\u3092\u958b\u3044\u305f\u308a\u524a\u9664\u3092\u3067\u304d\u307e\u305b\u3093\u3002 +StartupWindowProvider.openCase.noFile=\u30e1\u30bf\u30c7\u30fc\u30bf\u30d5\u30a1\u30a4\u30eb\u304c{0}\u306b\u898b\u3064\u304b\u3089\u306a\u3044\u305f\u3081\u3001\u4ee5\u524d\u306b\u958b\u3044\u305f\u30b1\u30fc\u30b9\u3092\u958b\u304f\u3053\u3068\u304c\u3067\u304d\u307e\u305b\u3093\u3002 UnpackagePortableCaseDialog.UnpackagePortableCaseDialog.extensions=\u30dd\u30fc\u30bf\u30d6\u30eb\u30b1\u30fc\u30b9\u30d1\u30c3\u30b1\u30fc\u30b8(.zip, .zip.001) UnpackagePortableCaseDialog.caseErrorLabel.text=jLabel1 UnpackagePortableCaseDialog.caseLabel.text=\u30dd\u30fc\u30bf\u30d6\u30eb\u30b1\u30fc\u30b9\: diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index 6c4ede3d99..6f2e6f0816 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -22,6 +22,7 @@ import org.sleuthkit.autopsy.featureaccess.FeatureAccessUtils; import com.google.common.annotations.Beta; import com.google.common.eventbus.Subscribe; import com.google.common.util.concurrent.ThreadFactoryBuilder; +import java.awt.Cursor; import org.sleuthkit.autopsy.casemodule.multiusercases.CaseNodeData; import java.awt.Frame; import java.awt.event.ActionEvent; @@ -85,13 +86,16 @@ import org.sleuthkit.autopsy.casemodule.events.DataSourceAddedEvent; import org.sleuthkit.autopsy.casemodule.events.DataSourceDeletedEvent; import org.sleuthkit.autopsy.casemodule.events.DataSourceNameChangedEvent; import org.sleuthkit.autopsy.casemodule.events.HostsAddedEvent; -import org.sleuthkit.autopsy.casemodule.events.HostsChangedEvent; -import org.sleuthkit.autopsy.casemodule.events.HostsRemovedEvent; -import org.sleuthkit.autopsy.casemodule.events.OsAccountAddedEvent; -import org.sleuthkit.autopsy.casemodule.events.OsAccountChangedEvent; -import org.sleuthkit.autopsy.casemodule.events.OsAccountDeletedEvent; +import org.sleuthkit.autopsy.casemodule.events.HostsAddedToPersonEvent; +import org.sleuthkit.autopsy.casemodule.events.HostsUpdatedEvent; +import org.sleuthkit.autopsy.casemodule.events.HostsDeletedEvent; +import org.sleuthkit.autopsy.casemodule.events.HostsRemovedFromPersonEvent; +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.OsAcctInstancesAddedEvent; 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.ReportAddedEvent; import org.sleuthkit.autopsy.casemodule.multiusercases.CaseNodeData.CaseNodeDataException; @@ -190,7 +194,7 @@ public class Case { private final SleuthkitEventListener sleuthkitEventListener; private CollaborationMonitor collaborationMonitor; private Services caseServices; - + private volatile boolean hasDataSource = false; private volatile boolean hasData = false; @@ -434,43 +438,54 @@ public class Case { */ CR_COMMENT_CHANGED, /** - * OSAccount associated with the current case added. Call getOsAccount - * to get the added account; + * One or more OS accounts have been added to the case. */ - OS_ACCOUNT_ADDED, + OS_ACCOUNTS_ADDED, /** - * OSAccount associated with the current case has changed. Call - * getOsAccount to get the changed account; + * One or more OS accounts in the case have been updated. */ - 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 OS account instances have been added to the case. + */ + OS_ACCT_INSTANCES_ADDED, + /** + * One or more hosts have been added to the case. */ 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, /** - * Persons associated with the current case added. + * One or more persons have been added to the case. */ 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 +520,14 @@ public class Case { } @Subscribe - public void publishOsAccountAddedEvent(TskEvent.OsAccountsAddedTskEvent event) { + public void publishOsAccountsAddedEvent(TskEvent.OsAccountsAddedTskEvent event) { hasData = true; - for (OsAccount account : event.getOsAcounts()) { - eventPublisher.publish(new OsAccountAddedEvent(account)); - } + eventPublisher.publish(new OsAccountsAddedEvent(event.getOsAcounts())); } @Subscribe - public void publishOsAccountChangedEvent(TskEvent.OsAccountsChangedTskEvent event) { - for (OsAccount account : event.getOsAcounts()) { - eventPublisher.publish(new OsAccountChangedEvent(account)); - } + public void publishOsAccountsUpdatedEvent(TskEvent.OsAccountsUpdatedTskEvent event) { + eventPublisher.publish(new OsAccountsUpdatedEvent(event.getOsAcounts())); } @Subscribe @@ -526,12 +537,14 @@ public class Case { } catch (TskCoreException ex) { logger.log(Level.SEVERE, "Unable to retrieve the hasData status from the db", ex); } - - for (Long accountId : event.getOsAcountObjectIds()) { - eventPublisher.publish(new OsAccountDeletedEvent(accountId)); - } + eventPublisher.publish(new OsAccountsDeletedEvent(event.getOsAccountObjectIds())); } + @Subscribe + public void publishOsAccountInstancesAddedEvent(TskEvent.OsAcctInstancesAddedTskEvent event) { + eventPublisher.publish(new OsAcctInstancesAddedEvent(event.getOsAccountInstances())); + } + /** * Publishes an autopsy event from the sleuthkit HostAddedEvent * indicating that hosts have been created. @@ -541,8 +554,7 @@ public class Case { @Subscribe public void publishHostsAddedEvent(TskEvent.HostsAddedTskEvent event) { hasData = true; - eventPublisher.publish(new HostsAddedEvent( - event == null ? Collections.emptyList() : event.getHosts())); + eventPublisher.publish(new HostsAddedEvent(event.getHosts())); } /** @@ -552,9 +564,8 @@ public class Case { * @param event The sleuthkit event for the updating of hosts. */ @Subscribe - public void publishHostsChangedEvent(TskEvent.HostsChangedTskEvent event) { - eventPublisher.publish(new HostsChangedEvent( - event == null ? Collections.emptyList() : event.getHosts())); + public void publishHostsUpdatedEvent(TskEvent.HostsUpdatedTskEvent event) { + eventPublisher.publish(new HostsUpdatedEvent(event.getHosts())); } /** @@ -570,9 +581,8 @@ public class Case { } catch (TskCoreException ex) { logger.log(Level.SEVERE, "Unable to retrieve the hasData status from the db", ex); } - - eventPublisher.publish(new HostsRemovedEvent( - event == null ? Collections.emptyList() : event.getHosts())); + + eventPublisher.publish(new HostsDeletedEvent(event.getHostIds())); } /** @@ -583,8 +593,7 @@ public class Case { */ @Subscribe public void publishPersonsAddedEvent(TskEvent.PersonsAddedTskEvent event) { - eventPublisher.publish(new PersonsAddedEvent( - event == null ? Collections.emptyList() : event.getPersons())); + eventPublisher.publish(new PersonsAddedEvent(event.getPersons())); } /** @@ -594,9 +603,8 @@ public class Case { * @param event The sleuthkit event for the updating of persons. */ @Subscribe - public void publishPersonsChangedEvent(TskEvent.PersonsChangedTskEvent event) { - eventPublisher.publish(new PersonsChangedEvent( - event == null ? Collections.emptyList() : event.getPersons())); + public void publishPersonsUpdatedEvent(TskEvent.PersonsUpdatedTskEvent event) { + eventPublisher.publish(new PersonsUpdatedEvent(event.getPersons())); } /** @@ -607,9 +615,19 @@ public class Case { */ @Subscribe public void publishPersonsDeletedEvent(TskEvent.PersonsDeletedTskEvent event) { - eventPublisher.publish(new PersonsDeletedEvent( - event == null ? Collections.emptyList() : event.getPersons())); + eventPublisher.publish(new PersonsDeletedEvent(event.getPersonIds())); } + + @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 +1250,107 @@ public class Case { /** * Update the GUI to to reflect the current case. */ - private static void updateGUIForCaseOpened(Case newCurrentCase) { - /* - * If the case database was upgraded for a new schema and a - * backup database was created, notify the user. - */ - SleuthkitCase caseDb = newCurrentCase.getSleuthkitCase(); - String backupDbPath = caseDb.getBackupDatabasePath(); - if (null != backupDbPath) { - JOptionPane.showMessageDialog( - mainFrame, - NbBundle.getMessage(Case.class, "Case.open.msgDlg.updated.msg", backupDbPath), - NbBundle.getMessage(Case.class, "Case.open.msgDlg.updated.title"), - JOptionPane.INFORMATION_MESSAGE); - } + private static void updateGUIForCaseOpened(Case newCurrentCase) { + /* + * If the case database was upgraded for a new schema and a backup + * database was created, notify the user. + */ + SleuthkitCase caseDb = newCurrentCase.getSleuthkitCase(); + String backupDbPath = caseDb.getBackupDatabasePath(); + if (null != backupDbPath) { + JOptionPane.showMessageDialog( + mainFrame, + NbBundle.getMessage(Case.class, "Case.open.msgDlg.updated.msg", backupDbPath), + NbBundle.getMessage(Case.class, "Case.open.msgDlg.updated.title"), + JOptionPane.INFORMATION_MESSAGE); + } - /* - * Look for the files for the data sources listed in the case - * database and give the user the opportunity to locate any that - * are missing. - */ - Map imgPaths = getImagePaths(caseDb); - for (Map.Entry entry : imgPaths.entrySet()) { - long obj_id = entry.getKey(); - String path = entry.getValue(); - boolean fileExists = (new File(path).isFile() || DriveUtils.driveExists(path)); - if (!fileExists) { - try { - // Using invokeAndWait means that the dialog will - // open on the EDT but this thread will wait for an - // answer. Using invokeLater would cause this loop to - // end before all of the dialogs appeared. - SwingUtilities.invokeAndWait(new Runnable() { - @Override - public void run() { - int response = JOptionPane.showConfirmDialog( + /* + * Look for the files for the data sources listed in the case database + * and give the user the opportunity to locate any that are missing. + */ + Map imgPaths = getImagePaths(caseDb); + for (Map.Entry entry : imgPaths.entrySet()) { + long obj_id = entry.getKey(); + String path = entry.getValue(); + boolean fileExists = (new File(path).isFile() || DriveUtils.driveExists(path)); + if (!fileExists) { + try { + // Using invokeAndWait means that the dialog will + // open on the EDT but this thread will wait for an + // answer. Using invokeLater would cause this loop to + // end before all of the dialogs appeared. + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + int response = JOptionPane.showConfirmDialog( mainFrame, NbBundle.getMessage(Case.class, "Case.checkImgExist.confDlg.doesntExist.msg", path), NbBundle.getMessage(Case.class, "Case.checkImgExist.confDlg.doesntExist.title"), JOptionPane.YES_NO_OPTION); - if (response == JOptionPane.YES_OPTION) { - MissingImageDialog.makeDialog(obj_id, caseDb); - } else { - logger.log(Level.SEVERE, "User proceeding with missing image files"); //NON-NLS + if (response == JOptionPane.YES_OPTION) { + MissingImageDialog.makeDialog(obj_id, caseDb); + } else { + logger.log(Level.SEVERE, "User proceeding with missing image files"); //NON-NLS - } - } - - }); - } catch (InterruptedException | InvocationTargetException ex) { - logger.log(Level.SEVERE, "Failed to show missing image confirmation dialog", ex); //NON-NLS - } - } + } + } + + }); + } catch (InterruptedException | InvocationTargetException ex) { + logger.log(Level.SEVERE, "Failed to show missing image confirmation dialog", ex); //NON-NLS } + } + } - /* - * Enable the case-specific actions. - */ - CallableSystemAction.get(AddImageAction.class).setEnabled(FeatureAccessUtils.canAddDataSources()); - CallableSystemAction.get(OpenHostsAction.class).setEnabled(true); - CallableSystemAction.get(CaseCloseAction.class).setEnabled(true); - CallableSystemAction.get(CaseDetailsAction.class).setEnabled(true); - CallableSystemAction.get(DataSourceSummaryAction.class).setEnabled(true); - CallableSystemAction.get(CaseDeleteAction.class).setEnabled(FeatureAccessUtils.canDeleteCurrentCase()); - CallableSystemAction.get(OpenTimelineAction.class).setEnabled(true); - CallableSystemAction.get(OpenCommVisualizationToolAction.class).setEnabled(true); - CallableSystemAction.get(CommonAttributeSearchAction.class).setEnabled(true); - CallableSystemAction.get(OpenOutputFolderAction.class).setEnabled(false); - CallableSystemAction.get(OpenDiscoveryAction.class).setEnabled(true); - + /* + * Enable the case-specific actions. + */ + CallableSystemAction.get(AddImageAction.class).setEnabled(FeatureAccessUtils.canAddDataSources()); + CallableSystemAction.get(OpenHostsAction.class).setEnabled(true); + CallableSystemAction.get(CaseCloseAction.class).setEnabled(true); + CallableSystemAction.get(CaseDetailsAction.class).setEnabled(true); + CallableSystemAction.get(DataSourceSummaryAction.class).setEnabled(true); + CallableSystemAction.get(CaseDeleteAction.class).setEnabled(FeatureAccessUtils.canDeleteCurrentCase()); + CallableSystemAction.get(OpenTimelineAction.class).setEnabled(true); + CallableSystemAction.get(OpenCommVisualizationToolAction.class).setEnabled(true); + CallableSystemAction.get(CommonAttributeSearchAction.class).setEnabled(true); + CallableSystemAction.get(OpenOutputFolderAction.class).setEnabled(false); + 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 - * of recent cases to the recent cases menu item and the - * open/create case dialog. + * 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. */ - RecentCases.getInstance().addRecentCase(newCurrentCase.getDisplayName(), newCurrentCase.getMetadata().getFilePath().toString()); - final boolean hasData = newCurrentCase.hasData(); - - SwingUtilities.invokeLater(() -> { - /* - * 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(); - } + mainFrame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + 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(); + } + mainFrame.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); - /* - * Reset the main window title to: - * - * [curent case display name] - [application name]. - */ - mainFrame.setTitle(newCurrentCase.getDisplayName() + " - " + getNameForTitle()); - }); + /* + * Reset the main window title to: + * + * [curent case display name] - [application name]. + */ + mainFrame.setTitle(newCurrentCase.getDisplayName() + " - " + getNameForTitle()); + }); } /* @@ -1684,16 +1703,16 @@ public class Case { /** * Returns true if there is any data in the case. - * + * * @return True or false. */ public boolean hasData() { return hasData; } - + /** * Returns true if there is one or more data sources in the case. - * + * * @return True or false. */ public boolean hasDataSource() { @@ -1858,72 +1877,6 @@ public class Case { 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. * @@ -1966,7 +1919,7 @@ public class Case { throw new TskCoreException(errorMsg, ex); } hasData = true; - + Report report = this.caseDb.addReport(normalizedLocalPath, srcModuleName, reportName, parent); eventPublisher.publish(new ReportAddedEvent(report)); return report; @@ -1996,16 +1949,16 @@ public class Case { for (Report report : reports) { this.caseDb.deleteReport(report); } - + try { hasData = dbHasData(); } catch (TskCoreException ex) { logger.log(Level.SEVERE, "Unable to retrieve the hasData status from the db", ex); } - + for (Report report : reports) { eventPublisher.publish(new AutopsyEvent(Events.REPORT_DELETED.toString(), report, null)); - } + } } /** @@ -3538,17 +3491,17 @@ public class Case { } } - + /** - * Initialize the hasData and hasDataSource parameters by checking the + * Initialize the hasData and hasDataSource parameters by checking the * database. - * + * * hasDataSource will be true if any data Source exists the db. - * - * hasData will be true if hasDataSource is true or if there are entries - * in the tsk_object or tsk_host tables. - * - * @throws TskCoreException + * + * hasData will be true if hasDataSource is true or if there are entries in + * the tsk_object or tsk_host tables. + * + * @throws TskCoreException */ private void updateDataParameters() throws TskCoreException { hasDataSource = dbHasDataSource(); @@ -3559,13 +3512,13 @@ public class Case { hasData = true; } } - + /** * Returns true of there are any data sources in the case database. - * + * * @return True if this case as a data source. - * - * @throws TskCoreException + * + * @throws TskCoreException */ private boolean dbHasDataSource() throws TskCoreException { String query = "SELECT count(*) AS count FROM (SELECT * FROM data_source_info LIMIT 1)t"; @@ -3580,35 +3533,35 @@ public class Case { throw new TskCoreException("Error accessing case databse", ex); } } - + /** * 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. - * + * * @return True if there is data in this case. - * - * @throws TskCoreException + * + * @throws TskCoreException */ private boolean dbHasData() throws TskCoreException { // The LIMIT 1 in the subquery should limit the data returned and // make the overall query more efficent. String query = "SELECT SUM(cnt) total FROM " + "(SELECT COUNT(*) AS cnt FROM " - + "(SELECT * FROM tsk_objects LIMIT 1)t " + + "(SELECT * FROM tsk_objects LIMIT 1)t " + "UNION ALL " + "SELECT COUNT(*) AS cnt FROM " + "(SELECT * FROM tsk_hosts LIMIT 1)r) s"; try (SleuthkitCase.CaseDbQuery dbQuery = caseDb.executeQuery(query)) { ResultSet resultSet = dbQuery.getResultSet(); if (resultSet.next()) { - return resultSet.getLong("total") > 0; + return resultSet.getLong("total") > 0; } else { return false; } - } catch ( SQLException ex) { + } catch (SQLException ex) { logger.log(Level.SEVERE, "Error accessing case database", ex); //NON-NLS throw new TskCoreException("Error accessing case databse", ex); - } + } } /** diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/IngestJobInfoPanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/IngestJobInfoPanel.form index c183e0de36..4ec9df679e 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/IngestJobInfoPanel.form +++ b/Core/src/org/sleuthkit/autopsy/casemodule/IngestJobInfoPanel.form @@ -1,11 +1,6 @@
- - - - - @@ -16,6 +11,7 @@ + @@ -35,9 +31,6 @@ - - - @@ -60,9 +53,6 @@ - - - @@ -85,6 +75,12 @@ + + + + + + @@ -157,6 +153,12 @@ + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/IngestJobInfoPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/IngestJobInfoPanel.java index 4dcdc5260f..89b696c041 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/IngestJobInfoPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/IngestJobInfoPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2016-2019 Basis Technology Corp. + * Copyright 2016-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -26,8 +26,11 @@ import java.util.Date; import java.util.EnumSet; import java.util.List; import java.util.Set; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; import java.util.logging.Level; import javax.swing.JOptionPane; +import javax.swing.SwingWorker; import javax.swing.event.ListSelectionEvent; import javax.swing.table.AbstractTableModel; import org.openide.util.NbBundle.Messages; @@ -50,13 +53,14 @@ public final class IngestJobInfoPanel extends javax.swing.JPanel { private static final Logger logger = Logger.getLogger(IngestJobInfoPanel.class.getName()); private static final Set INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.STARTED, IngestManager.IngestJobEvent.CANCELLED, IngestManager.IngestJobEvent.COMPLETED); private static final Set CASE_EVENTS_OF_INTEREST = EnumSet.of(Case.Events.CURRENT_CASE); - - private List ingestJobs; + private static final int EXTRA_ROW_HEIGHT = 4; + private final List ingestJobs = new ArrayList<>(); private final List ingestJobsForSelectedDataSource = new ArrayList<>(); private IngestJobTableModel ingestJobTableModel = new IngestJobTableModel(); private IngestModuleTableModel ingestModuleTableModel = new IngestModuleTableModel(null); private final DateFormat datetimeFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); private DataSource selectedDataSource; + private static SwingWorker refreshWorker = null; /** * Creates new form IngestJobInfoPanel @@ -76,19 +80,19 @@ public final class IngestJobInfoPanel extends javax.swing.JPanel { this.ingestModuleTable.setModel(this.ingestModuleTableModel); }); - IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST , (PropertyChangeEvent evt) -> { + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, (PropertyChangeEvent evt) -> { if (evt.getPropertyName().equals(IngestManager.IngestJobEvent.STARTED.toString()) || evt.getPropertyName().equals(IngestManager.IngestJobEvent.CANCELLED.toString()) || evt.getPropertyName().equals(IngestManager.IngestJobEvent.COMPLETED.toString())) { refresh(); } }); - + Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, (PropertyChangeEvent evt) -> { if (!(evt instanceof AutopsyEvent) || (((AutopsyEvent) evt).getSourceType() != AutopsyEvent.SourceType.LOCAL)) { return; } - + // Check whether we have a case open or case close event. if ((CURRENT_CASE == Case.Events.valueOf(evt.getPropertyName()))) { if (evt.getNewValue() != null) { @@ -100,6 +104,9 @@ public final class IngestJobInfoPanel extends javax.swing.JPanel { } } }); + ingestJobTable.setRowHeight(ingestJobTable.getRowHeight() + EXTRA_ROW_HEIGHT); + ingestModuleTable.setRowHeight(ingestModuleTable.getRowHeight() + EXTRA_ROW_HEIGHT); + } /** @@ -130,27 +137,53 @@ public final class IngestJobInfoPanel extends javax.swing.JPanel { * Get the updated complete list of ingest jobs. */ private void refresh() { - try { - if (Case.isCaseOpen()) { // Note - this will generally return true when handling a case close event - SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase(); - this.ingestJobs = skCase.getIngestJobs(); - setDataSource(selectedDataSource); - } else { - this.ingestJobs = new ArrayList<>(); - setDataSource(null); - } - - } catch (TskCoreException | NoCurrentCaseException ex) { - logger.log(Level.SEVERE, "Failed to load ingest jobs.", ex); - JOptionPane.showMessageDialog(this, Bundle.IngestJobInfoPanel_loadIngestJob_error_text(), Bundle.IngestJobInfoPanel_loadIngestJob_error_title(), JOptionPane.ERROR_MESSAGE); + if (refreshWorker != null && !refreshWorker.isDone()) { + refreshWorker.cancel(true); } + refreshWorker = new SwingWorker() { + + @Override + protected Boolean doInBackground() throws Exception { + ingestJobs.clear(); + try { + if (Case.isCaseOpen()) { // Note - this will generally return true when handling a case close event + SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase(); + ingestJobs.addAll(skCase.getIngestJobs()); + setDataSource(selectedDataSource); + } else { + setDataSource(null); + } + return true; + } catch (TskCoreException | NoCurrentCaseException ex) { + logger.log(Level.SEVERE, "Failed to load ingest jobs.", ex); + return false; + } + } + + @Override + protected void done() { + try { + if (!get()) { + JOptionPane.showMessageDialog(IngestJobInfoPanel.this, Bundle.IngestJobInfoPanel_loadIngestJob_error_text(), Bundle.IngestJobInfoPanel_loadIngestJob_error_title(), JOptionPane.ERROR_MESSAGE); + } + } catch (InterruptedException | ExecutionException ex) { + logger.log(Level.WARNING, "Error getting results from Ingest Job Info Panel's refresh worker", ex); + } catch (CancellationException ignored){ + logger.log(Level.INFO, "The refreshing of the IngestJobInfoPanel was cancelled"); + } + } + }; + refreshWorker.execute(); } - + /** * Reset the panel. */ private void reset() { - this.ingestJobs = new ArrayList<>(); + if (refreshWorker != null) { + refreshWorker.cancel(true); + } + this.ingestJobs.clear(); setDataSource(null); } @@ -267,19 +300,18 @@ public final class IngestJobInfoPanel extends javax.swing.JPanel { javax.swing.JScrollPane ingestModulesScrollPane = new javax.swing.JScrollPane(); ingestModuleTable = new javax.swing.JTable(); - setMaximumSize(new java.awt.Dimension(32767, 32767)); setLayout(new java.awt.BorderLayout()); - contentPanel.setMaximumSize(new java.awt.Dimension(32767, 32767)); contentPanel.setMinimumSize(new java.awt.Dimension(625, 150)); contentPanel.setPreferredSize(new java.awt.Dimension(625, 150)); contentPanel.setLayout(new java.awt.GridBagLayout()); ingestJobsScrollPane.setBorder(null); ingestJobsScrollPane.setMinimumSize(new java.awt.Dimension(16, 16)); - ingestJobsScrollPane.setPreferredSize(null); ingestJobTable.setModel(ingestJobTableModel); + ingestJobTable.setGridColor(javax.swing.UIManager.getDefaults().getColor("InternalFrame.borderColor")); + ingestJobTable.setIntercellSpacing(new java.awt.Dimension(4, 2)); ingestJobTable.getTableHeader().setReorderingAllowed(false); ingestJobsScrollPane.setViewportView(ingestJobTable); ingestJobTable.getColumnModel().getSelectionModel().setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); @@ -315,6 +347,8 @@ public final class IngestJobInfoPanel extends javax.swing.JPanel { ingestModulesScrollPane.setPreferredSize(new java.awt.Dimension(254, 16)); ingestModuleTable.setModel(ingestModuleTableModel); + ingestModuleTable.setGridColor(javax.swing.UIManager.getDefaults().getColor("InternalFrame.borderColor")); + ingestModuleTable.setIntercellSpacing(new java.awt.Dimension(4, 2)); ingestModulesScrollPane.setViewportView(ingestModuleTable); gridBagConstraints = new java.awt.GridBagConstraints(); diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardAction.java b/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardAction.java index 92f83ba26c..936249dad4 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardAction.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardAction.java @@ -70,9 +70,7 @@ final class NewCaseWizardAction extends CallableSystemAction { final WizardDescriptor wizardDescriptor = new WizardDescriptor(getNewCaseWizardPanels()); wizardDescriptor.setTitleFormat(new MessageFormat("{0}")); wizardDescriptor.setTitle(NbBundle.getMessage(this.getClass(), "NewCaseWizardAction.newCase.windowTitle.text")); - Dialog dialog = DialogDisplayer.getDefault().createDialog(wizardDescriptor); - // Workaround to ensure new case dialog is not hidden on macOS - dialog.setAlwaysOnTop(true); + Dialog dialog = DialogDisplayer.getDefault().createDialog(wizardDescriptor, WindowManager.getDefault().getMainWindow()); dialog.setVisible(true); dialog.toFront(); if (wizardDescriptor.getValue() == WizardDescriptor.FINISH_OPTION) { diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/events/HostsAddedEvent.java b/Core/src/org/sleuthkit/autopsy/casemodule/events/HostsAddedEvent.java index c10b66face..f188c7d5a3 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/events/HostsAddedEvent.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/events/HostsAddedEvent.java @@ -23,17 +23,21 @@ import org.sleuthkit.autopsy.casemodule.Case; 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; - + /** - * Main constructor. - * @param dataModelObjects The hosts that have been added. + * Constructs an application event published when hosts have been added to + * the Sleuth Kit data model for a case. + * + * @param hosts The hosts that have been added. */ - public HostsAddedEvent(List dataModelObjects) { - super(Case.Events.HOSTS_ADDED.name(), dataModelObjects); + public HostsAddedEvent(List hosts) { + super(Case.Events.HOSTS_ADDED.name(), hosts); } + } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/events/HostsAddedToPersonEvent.java b/Core/src/org/sleuthkit/autopsy/casemodule/events/HostsAddedToPersonEvent.java new file mode 100755 index 0000000000..fffb39d82c --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/events/HostsAddedToPersonEvent.java @@ -0,0 +1,92 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2021 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may 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 { + + 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 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 getHosts() { + return getNewValue(); + } + + @Override + protected List getOldValueObjects(SleuthkitCase caseDb, List ids) throws TskCoreException { + List persons = new ArrayList<>(); + for (Long id : ids) { + Optional person = caseDb.getPersonManager().getPerson(id); + if (person.isPresent()) { + persons.add(person.get()); + } + } + return persons; + } + + @Override + protected List getNewValueObjects(SleuthkitCase caseDb, List ids) throws TskCoreException { + List hosts = new ArrayList<>(); + for (Long id : ids) { + Optional host = caseDb.getHostManager().getHostById(id); + if (host.isPresent()) { + hosts.add(host.get()); + } + } + return hosts; + } + +} diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/events/HostsRemovedEvent.java b/Core/src/org/sleuthkit/autopsy/casemodule/events/HostsDeletedEvent.java old mode 100644 new mode 100755 similarity index 56% rename from Core/src/org/sleuthkit/autopsy/casemodule/events/HostsRemovedEvent.java rename to Core/src/org/sleuthkit/autopsy/casemodule/events/HostsDeletedEvent.java index 407b83c32a..24c2ae091b --- a/Core/src/org/sleuthkit/autopsy/casemodule/events/HostsRemovedEvent.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/events/HostsDeletedEvent.java @@ -20,20 +20,32 @@ package org.sleuthkit.autopsy.casemodule.events; import java.util.List; 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; - + /** - * Main constructor. - * @param dataModelObjects The list of hosts that have been deleted. + * Constructs an application event published when hosts have been deleted + * from the Sleuth Kit data model for a case. + * + * @param hostIds The host IDs of the deleted hosts. */ - public HostsRemovedEvent(List dataModelObjects) { - super(Case.Events.HOSTS_DELETED.name(), dataModelObjects); + public HostsDeletedEvent(List hostIds) { + super(Case.Events.HOSTS_DELETED.name(), hostIds); } + + /** + * Gets the host IDs of the hosts that have been deleted. + * + * @return The host IDs. + */ + public List getHostIds() { + return getOldValue(); + } + } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/events/HostsEvent.java b/Core/src/org/sleuthkit/autopsy/casemodule/events/HostsEvent.java index 7c9a31f01e..465d265083 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/events/HostsEvent.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/events/HostsEvent.java @@ -19,71 +19,51 @@ package org.sleuthkit.autopsy.casemodule.events; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Optional; -import java.util.stream.Collectors; import org.sleuthkit.datamodel.Host; -import org.sleuthkit.datamodel.HostManager; import org.sleuthkit.datamodel.SleuthkitCase; 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 { +public class HostsEvent extends TskDataModelChangedEvent { private static final long serialVersionUID = 1L; /** - * Retrieves a list of ids from a list of hosts. - * - * @param hosts The hosts. - * @return The list of ids. - */ - private static List getIds(List 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 getSafeList(List hosts) { - return hosts == null ? Collections.emptyList() : hosts; - } - - /** - * Main constructor. + * 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 eventName The name of the Case.Events enum value for the event - * type. - * @param dataModelObjects The list of hosts for the event. + * type. + * @param hosts The hosts. */ - protected HostsEvent(String eventName, List dataModelObjects) { - super(eventName, getIds(dataModelObjects), new ArrayList<>(getSafeList(dataModelObjects))); + HostsEvent(String eventName, List hosts) { + super(eventName, null, null, hosts, Host::getHostId); + } + + /** + * Gets the hosts that have been added or updated. + * + * @return The hosts. + */ + public List getHosts() { + return getNewValue(); } @Override - protected List getDataModelObjects(SleuthkitCase caseDb, List ids) throws TskCoreException { - HostManager hostManager = caseDb.getHostManager(); - List toRet = new ArrayList<>(); - if (ids != null) { - for (Long id : ids) { - if (id == null) { - continue; - } - - Optional thisHostOpt = hostManager.getHostById(id); - thisHostOpt.ifPresent((h) -> toRet.add(h)); + protected List getNewValueObjects(SleuthkitCase caseDb, List ids) throws TskCoreException { + List hosts = new ArrayList<>(); + for (Long id : ids) { + Optional host = caseDb.getHostManager().getHostById(id); + if (host.isPresent()) { + hosts.add(host.get()); } } - - return toRet; + return hosts; } } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/events/HostsRemovedFromPersonEvent.java b/Core/src/org/sleuthkit/autopsy/casemodule/events/HostsRemovedFromPersonEvent.java new file mode 100755 index 0000000000..e23ef786ee --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/events/HostsRemovedFromPersonEvent.java @@ -0,0 +1,85 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2021 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may 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 { + + 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 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 getHostIds() { + return getNewValue(); + } + + @Override + protected List getOldValueObjects(SleuthkitCase caseDb, List ids) throws TskCoreException { + List persons = new ArrayList<>(); + for (Long id : ids) { + Optional person = caseDb.getPersonManager().getPerson(id); + if (person.isPresent()) { + persons.add(person.get()); + } + } + return persons; + } + + @Override + protected List getNewValueObjects(SleuthkitCase caseDb, List ids) throws TskCoreException { + return ids; + } + +} diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/events/HostsChangedEvent.java b/Core/src/org/sleuthkit/autopsy/casemodule/events/HostsUpdatedEvent.java old mode 100644 new mode 100755 similarity index 68% rename from Core/src/org/sleuthkit/autopsy/casemodule/events/HostsChangedEvent.java rename to Core/src/org/sleuthkit/autopsy/casemodule/events/HostsUpdatedEvent.java index a5b8692c03..ec00fc5ad6 --- a/Core/src/org/sleuthkit/autopsy/casemodule/events/HostsChangedEvent.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/events/HostsUpdatedEvent.java @@ -23,19 +23,21 @@ import org.sleuthkit.autopsy.casemodule.Case; 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; /** - * 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 - * changed. + * @param hosts The updated persons. */ - public HostsChangedEvent(List dataModelObjects) { - super(Case.Events.HOSTS_CHANGED.name(), dataModelObjects); + public HostsUpdatedEvent(List hosts) { + super(Case.Events.HOSTS_UPDATED.name(), hosts); } + } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/events/OsAccountDeletedEvent.java b/Core/src/org/sleuthkit/autopsy/casemodule/events/OsAccountDeletedEvent.java deleted file mode 100644 index adc726fca8..0000000000 --- a/Core/src/org/sleuthkit/autopsy/casemodule/events/OsAccountDeletedEvent.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2021 Basis Technology Corp. - * Contact: carrier sleuthkit org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may 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); - } -} diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/events/OsAccountEvent.java b/Core/src/org/sleuthkit/autopsy/casemodule/events/OsAccountEvent.java deleted file mode 100755 index d34da7822d..0000000000 --- a/Core/src/org/sleuthkit/autopsy/casemodule/events/OsAccountEvent.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2021 Basis Technology Corp. - * Contact: carrier sleuthkit org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may 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 { - - 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 accounts = getNewValue(); - return accounts.get(0); - } - - @Override - protected List getDataModelObjects(SleuthkitCase caseDb, List ids) throws TskCoreException { - Long id = ids.get(0); - OsAccount account = caseDb.getOsAccountManager().getOsAccountByObjectId(id); - List accounts = new ArrayList<>(); - accounts.add(account); - return accounts; - } -} diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/events/OsAccountChangedEvent.java b/Core/src/org/sleuthkit/autopsy/casemodule/events/OsAccountsAddedEvent.java similarity index 58% rename from Core/src/org/sleuthkit/autopsy/casemodule/events/OsAccountChangedEvent.java rename to Core/src/org/sleuthkit/autopsy/casemodule/events/OsAccountsAddedEvent.java index 237373a8b9..f4273408c6 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/events/OsAccountChangedEvent.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/events/OsAccountsAddedEvent.java @@ -18,17 +18,26 @@ */ 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; /** - * 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; - - 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 osAccounts) { + super(OS_ACCOUNTS_ADDED.toString(), osAccounts); + } + } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/events/OsAccountsDeletedEvent.java b/Core/src/org/sleuthkit/autopsy/casemodule/events/OsAccountsDeletedEvent.java new file mode 100755 index 0000000000..f3f65a0aed --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/events/OsAccountsDeletedEvent.java @@ -0,0 +1,51 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2021 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may 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 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 getOsAccountObjectIds() { + return getOldValue(); + } + +} diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/events/OsAccountsEvent.java b/Core/src/org/sleuthkit/autopsy/casemodule/events/OsAccountsEvent.java new file mode 100755 index 0000000000..434d8c8f60 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/events/OsAccountsEvent.java @@ -0,0 +1,66 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2021 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may 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 { + + 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 osAccounts) { + super(eventName, null, null, osAccounts, OsAccount::getId); + } + + /** + * Gets the OS accounts that have been added or updated. + * + * @return The OS accounts. + */ + public List getOsAccounts() { + return getNewValue(); + } + + @Override + protected List getNewValueObjects(SleuthkitCase caseDb, List ids) throws TskCoreException { + List osAccounts = new ArrayList<>(); + for (Long id : ids) { + osAccounts.add(caseDb.getOsAccountManager().getOsAccountByObjectId(id)); + } + return osAccounts; + } + +} diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/events/OsAccountAddedEvent.java b/Core/src/org/sleuthkit/autopsy/casemodule/events/OsAccountsUpdatedEvent.java similarity index 61% rename from Core/src/org/sleuthkit/autopsy/casemodule/events/OsAccountAddedEvent.java rename to Core/src/org/sleuthkit/autopsy/casemodule/events/OsAccountsUpdatedEvent.java index c9f89903f4..65767ccdfc 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/events/OsAccountAddedEvent.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/events/OsAccountsUpdatedEvent.java @@ -18,18 +18,26 @@ */ package org.sleuthkit.autopsy.casemodule.events; +import java.util.List; import org.sleuthkit.autopsy.casemodule.Case; 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; - - 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 osAccounts) { + super(Case.Events.OS_ACCOUNTS_UPDATED.toString(), osAccounts); + } + } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/events/OsAcctInstancesAddedEvent.java b/Core/src/org/sleuthkit/autopsy/casemodule/events/OsAcctInstancesAddedEvent.java new file mode 100755 index 0000000000..d752bf27fb --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/events/OsAcctInstancesAddedEvent.java @@ -0,0 +1,59 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2021 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may 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 static org.sleuthkit.autopsy.casemodule.Case.Events.OS_ACCT_INSTANCES_ADDED; +import org.sleuthkit.datamodel.OsAccountInstance; +import org.sleuthkit.datamodel.SleuthkitCase; +import org.sleuthkit.datamodel.TskCoreException; + +/** + * An application event published when OS account instances are added to the + * Sleuth Kit data model for a case. + */ +public final class OsAcctInstancesAddedEvent extends TskDataModelChangedEvent { + + private static final long serialVersionUID = 1L; + + /** + * Constructs an application event published when OS account instances are + * added to the Sleuth Kit data model for a case. + * + * @param osAcctInstances The OS account instances that were added. + */ + public OsAcctInstancesAddedEvent(List osAcctInstances) { + super(OS_ACCT_INSTANCES_ADDED.toString(), null, null, osAcctInstances, OsAccountInstance::getInstanceId); + } + + /** + * Gets the OS account instances that have been added. + * + * @return The OS account instances. + */ + public List getOsAccountInstances() { + return getNewValue(); + } + + @Override + protected List getNewValueObjects(SleuthkitCase caseDb, List ids) throws TskCoreException { + return caseDb.getOsAccountManager().getOsAccountInstances(ids); + } + +} diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/events/PersonsAddedEvent.java b/Core/src/org/sleuthkit/autopsy/casemodule/events/PersonsAddedEvent.java index e2a8a7aabd..afd101eac3 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/events/PersonsAddedEvent.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/events/PersonsAddedEvent.java @@ -23,17 +23,21 @@ import org.sleuthkit.autopsy.casemodule.Case; 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 { - + private static final long serialVersionUID = 1L; - + /** - * Main constructor. - * @param dataModelObjects The persons that have been added. + * Constructs an application event published when persons have been added to + * the Sleuth Kit data model for a case. + * + * @param persons The persons that have been added. */ - public PersonsAddedEvent(List dataModelObjects) { - super(Case.Events.PERSONS_ADDED.name(), dataModelObjects); + public PersonsAddedEvent(List persons) { + super(Case.Events.PERSONS_ADDED.name(), persons); } + } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/events/PersonsDeletedEvent.java b/Core/src/org/sleuthkit/autopsy/casemodule/events/PersonsDeletedEvent.java index a63fef32cb..46c024b7dd 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/events/PersonsDeletedEvent.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/events/PersonsDeletedEvent.java @@ -20,20 +20,32 @@ package org.sleuthkit.autopsy.casemodule.events; import java.util.List; 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; - + /** - * Main constructor. - * @param dataModelObjects The list of persons that have been deleted. + * Constructs an application event published when persons 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 dataModelObjects) { - super(Case.Events.PERSONS_DELETED.name(), dataModelObjects); + public PersonsDeletedEvent(List personIds) { + super(Case.Events.PERSONS_DELETED.name(), personIds); } + + /** + * Gets the person IDs of the persons that have been deleted. + * + * @return The person IDs. + */ + List getPersonIds() { + return getOldValue(); + } + } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/events/PersonsEvent.java b/Core/src/org/sleuthkit/autopsy/casemodule/events/PersonsEvent.java index e3f584d58a..2d3b322ea7 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/events/PersonsEvent.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/events/PersonsEvent.java @@ -19,69 +19,52 @@ package org.sleuthkit.autopsy.casemodule.events; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Optional; -import java.util.stream.Collectors; import org.sleuthkit.datamodel.Person; -import org.sleuthkit.datamodel.PersonManager; import org.sleuthkit.datamodel.SleuthkitCase; 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 { +public class PersonsEvent extends TskDataModelChangedEvent { + + private static final long serialVersionUID = 1L; /** - * Retrieves a list of ids from a list of persons. - * - * @param persons The persons. - * @return The list of ids. - */ - private static List getIds(List 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 getSafeList(List persons) { - return persons == null ? Collections.emptyList() : persons; - } - - /** - * Main constructor. + * 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 + * updated. * * @param eventName The name of the Case.Events enum value for the event - * type. - * @param dataModelObjects The list of persons for the event. + * type. + * @param persons The persons. */ - protected PersonsEvent(String eventName, List dataModelObjects) { - super(eventName, getIds(dataModelObjects), new ArrayList<>(getSafeList(dataModelObjects))); + PersonsEvent(String eventName, List persons) { + super(eventName, null, null, persons, Person::getPersonId); + } + + /** + * Gets the persons that have been added or updated. + * + * @return The persons. + */ + public List getPersons() { + return getNewValue(); } @Override - protected List getDataModelObjects(SleuthkitCase caseDb, List ids) throws TskCoreException { - PersonManager personManager = caseDb.getPersonManager(); - List toRet = new ArrayList<>(); - if (ids != null) { - for (Long id : ids) { - if (id == null) { - continue; - } - - Optional thisPersonOpt = personManager.getPerson(id); - thisPersonOpt.ifPresent((h) -> toRet.add(h)); + protected List getNewValueObjects(SleuthkitCase caseDb, List ids) throws TskCoreException { + List persons = new ArrayList<>(); + for (Long id : ids) { + Optional person = caseDb.getPersonManager().getPerson(id); + if (person.isPresent()) { + persons.add(person.get()); } } - - return toRet; + return persons; } } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/events/PersonsChangedEvent.java b/Core/src/org/sleuthkit/autopsy/casemodule/events/PersonsUpdatedEvent.java old mode 100644 new mode 100755 similarity index 67% rename from Core/src/org/sleuthkit/autopsy/casemodule/events/PersonsChangedEvent.java rename to Core/src/org/sleuthkit/autopsy/casemodule/events/PersonsUpdatedEvent.java index f375a125bb..572b832688 --- a/Core/src/org/sleuthkit/autopsy/casemodule/events/PersonsChangedEvent.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/events/PersonsUpdatedEvent.java @@ -23,19 +23,21 @@ import org.sleuthkit.autopsy.casemodule.Case; 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; /** - * 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 - * changed. + * @param persons The updated persons. */ - public PersonsChangedEvent(List dataModelObjects) { - super(Case.Events.PERSONS_CHANGED.name(), dataModelObjects); + public PersonsUpdatedEvent(List persons) { + super(Case.Events.PERSONS_UPDATED.name(), persons); } + } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/events/ReportAddedEvent.java b/Core/src/org/sleuthkit/autopsy/casemodule/events/ReportAddedEvent.java index bb4145c804..9da76a4366 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/events/ReportAddedEvent.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/events/ReportAddedEvent.java @@ -28,33 +28,38 @@ import org.sleuthkit.datamodel.SleuthkitCase; 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 { +public final class ReportAddedEvent extends TskDataModelChangedEvent { 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) { - 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() { List reports = getNewValue(); return reports.get(0); } - + @Override - protected List getDataModelObjects(SleuthkitCase caseD, List ids) throws TskCoreException { + protected List getNewValueObjects(SleuthkitCase caseDb, List ids) throws TskCoreException { Long id = ids.get(0); - Report report = caseD.getReportById(id); List reports = new ArrayList<>(); - reports.add(report); + reports.add(caseDb.getReportById(id)); return reports; } - + } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/events/TskDataModelChangeEvent.java b/Core/src/org/sleuthkit/autopsy/casemodule/events/TskDataModelChangeEvent.java deleted file mode 100755 index 1bd9fd81ac..0000000000 --- a/Core/src/org/sleuthkit/autopsy/casemodule/events/TskDataModelChangeEvent.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2021 Basis Technology Corp. - * Contact: carrier sleuthkit org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may 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 A Sleuth Kit Data Model object type. - */ -public abstract class TskDataModelChangeEvent extends AutopsyEvent { - - private static final long serialVersionUID = 1L; - private static final Logger logger = Logger.getLogger(TskDataModelChangeEvent.class.getName()); - private final List dataModelObjectIds; - private transient List 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 dataModelObjectIds, List 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 getDataModelObjectIds() { - return Collections.unmodifiableList(dataModelObjectIds); - } - - /** - * Gets the Sleuth Kit Data Model objects associated with this application - * event. - * - * @return The objects. - */ - @Override - public List 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 getDataModelObjects(SleuthkitCase caseDb, List ids) throws TskCoreException; - -} diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/events/TskDataModelChangedEvent.java b/Core/src/org/sleuthkit/autopsy/casemodule/events/TskDataModelChangedEvent.java new file mode 100755 index 0000000000..83ced035fc --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/events/TskDataModelChangedEvent.java @@ -0,0 +1,205 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2021 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may 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 The Sleuth Kit Data Model object type of the "old" data model + * objects. + * @param The Sleuth Kit Data Model object type of the "new" data model + * objects. + */ +public abstract class TskDataModelChangedEvent 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 oldValueIds; + private transient List oldValueObjects; + private final boolean hasNewValue; + private final List newValueIds; + private transient List 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 oldValueObjects, Function oldValueGetIdMethod, List newValueObjects, Function 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 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 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 getOldValueObjects(SleuthkitCase caseDb, List 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 getNewValueObjects(SleuthkitCase caseDb, List ids) throws TskCoreException { + return Collections.emptyList(); + } + +} diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/events/TskDataModelObjectsDeletedEvent.java b/Core/src/org/sleuthkit/autopsy/casemodule/events/TskDataModelObjectsDeletedEvent.java new file mode 100755 index 0000000000..7e5929e4a1 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/events/TskDataModelObjectsDeletedEvent.java @@ -0,0 +1,60 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2021 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may 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 deletedObjectIds; + + protected TskDataModelObjectsDeletedEvent(String eventName, List deletedObjectIds) { + super(eventName, null, null); + this.deletedObjectIds = new ArrayList<>(); + this.deletedObjectIds.addAll(deletedObjectIds); + } + + @Override + public List getOldValue() { + return Collections.unmodifiableList(deletedObjectIds); + } + +} diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle_ja.properties index fa3334f939..0fb5047324 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle_ja.properties @@ -1,4 +1,4 @@ -#Fri Feb 12 16:56:28 UTC 2021 +#Mon Jul 12 13:21:59 UTC 2021 OptionsCategory_Name_TagNamesOptions=\u30ab\u30b9\u30bf\u30e0\u30fb\u30bf\u30b0 OptionsCategory_TagNames=TagNames TagNameDefinition.predefTagNames.bookmark.text=\u30d6\u30c3\u30af\u30de\u30fc\u30af @@ -11,14 +11,21 @@ TagNameDialog.JOptionPane.tagNameEmpty.title=\u7a7a(\u672a\u5165\u529b)\u306e\u7 TagNameDialog.JOptionPane.tagNameIllegalCharacters.message=\u30bf\u30b0\u540d\u306b\u6b21\u306e\u8a18\u53f7\u3092\u542b\u3081\u3089\u308c\u307e\u305b\u3093\: \\ \: * ? " < > | , ; TagNameDialog.JOptionPane.tagNameIllegalCharacters.title=\u30bf\u30b0\u540d\u306b\u7121\u52b9\u306a\u6587\u5b57\u304c\u3042\u308a\u307e\u3059 TagNameDialog.cancelButton.text=\u53d6\u308a\u6d88\u3057 +TagNameDialog.descriptionLabel.text=\u8aac\u660e\uff1a TagNameDialog.editTitle.text=\u30bf\u30b0\u3092\u7de8\u96c6 TagNameDialog.newTagNameLabel.text=\u540d\u524d\: +TagNameDialog.notableCheckbox.text=\u30bf\u30b0\u306f\u30a2\u30a4\u30c6\u30e0\u304c\u6ce8\u76ee\u306b\u5024\u3059\u308b\u3053\u3068\u3092\u793a\u3057\u307e\u3059\u3002 TagNameDialog.okButton.text=OK TagNameDialog.tagNameTextField.text= TagNameDialog.title.text=\u65b0\u898f\u30bf\u30b0 TagOptionsPanel.TagNameDialog.tagNameAlreadyExists.message=\u30bf\u30b0\u540d\u306f\u4e00\u610f\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002\u3053\u306e\u540d\u524d\u306e\u30bf\u30b0\u306f\u3059\u3067\u306b\u5b58\u5728\u3057\u307e\u3059\u3002 TagOptionsPanel.TagNameDialog.tagNameAlreadyExists.title=\u30bf\u30b0\u540d\u3092\u8907\u88fd TagOptionsPanel.deleteTagNameButton.text=\u30bf\u30b0\u3092\u524a\u9664 +TagOptionsPanel.descriptionLabel.text=\u30bf\u30b0\u306e\u8aac\u660e\uff1a +TagOptionsPanel.editTagNameButton.text=\u30bf\u30b0\u306e\u7de8\u96c6 +TagOptionsPanel.ingestRunningWarningLabel.text=\u53d6\u8fbc\u307f\u306e\u5b9f\u884c\u4e2d\u306f\u3001\u65e2\u5b58\u306e\u30bf\u30b0\u3092\u5909\u66f4\u3067\u304d\u307e\u305b\u3093\u3002 +TagOptionsPanel.isNotableLabel.text=\u30bf\u30b0\u306f\u30a2\u30a4\u30c6\u30e0\u304c\u6ce8\u76ee\u306b\u5024\u3059\u308b\u3053\u3068\u3092\u793a\u3057\u307e\u3059\uff1a TagOptionsPanel.newTagNameButton.text=\u65b0\u898f\u30bf\u30b0 +TagOptionsPanel.panelDescriptionTextArea.text=\u30bf\u30b0\u3092\u4f5c\u6210\u3068\u7ba1\u7406\u3002 \u30bf\u30b0\u306f\u3001\u30b1\u30fc\u30b9\u5185\u306e\u30d5\u30a1\u30a4\u30eb\u3068\u7d50\u679c\u306b\u9069\u7528\u3067\u304d\u307e\u3059\u3002 \u6ce8\u76ee\u306e\u30bf\u30b0\u3092\u4f7f\u7528\u3059\u308b\u3068\u3001\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u3067\u30bf\u30b0\u304c\u4ed8\u3051\u3089\u308c\u305f\u30a2\u30a4\u30c6\u30e0\u306b\u6ce8\u76ee\u306e\u30d5\u30e9\u30b0\u304c\u4ed8\u3051\u3089\u308c\u307e\u3059\u3002 \u30bf\u30b0\u306e\u30b9\u30c6\u30fc\u30bf\u30b9\u3092\u5909\u66f4\u3059\u308b\u3068\u3001\u73fe\u5728\u306e\u30b1\u30fc\u30b9\u306e\u30a2\u30a4\u30c6\u30e0\u306e\u307f\u306b\u5f71\u97ff\u3057\u307e\u3059\u3002 TagOptionsPanel.tagTypesListLabel.text=\u30bf\u30b0\u540d\: TagsManager.notableTagEnding.text=\ (\u9855\u8457) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/FileManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/FileManager.java index f9095876d9..34f26eb1ac 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/FileManager.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/FileManager.java @@ -130,8 +130,7 @@ public class FileManager implements Closeable { * @throws TskCoreException */ public List findFilesExactName(long parentId, String name) throws TskCoreException{ - String whereClause = "name = '%s'"; - return caseDb.findAllFilesInFolderWhere(parentId, String.format(whereClause, name)); + return caseDb.getFileManager().findFilesExactName(parentId, name); } /** @@ -220,12 +219,7 @@ public class FileManager implements Closeable { * database. */ public List findFiles(String fileName, AbstractFile parent) throws TskCoreException { - List result = new ArrayList<>(); - List dataSources = caseDb.getRootObjects(); - for (Content dataSource : dataSources) { - result.addAll(findFiles(dataSource, fileName, parent)); - } - return result; + return caseDb.findFilesInFolder(fileName, parent); } /** @@ -268,25 +262,6 @@ public class FileManager implements Closeable { return caseDb.findFiles(dataSource, fileName, parentSubString); } - /** - * Finds all files and directories with a given file name and given parent - * file or directory in a given data source (image, local/logical files set, - * etc.). The name search is for full or partial matches and is case - * insensitive (a case insensitive SQL LIKE clause is used to query the case - * database). - * - * @param dataSource The data source. - * @param fileName The full name or a pattern to match on part of the name - * @param parent The parent file or directory. - * - * @return The matching files and directories. - * - * @throws TskCoreException if there is a problem querying the case - * database. - */ - public List findFiles(Content dataSource, String fileName, AbstractFile parent) throws TskCoreException { - return findFiles(dataSource, fileName, parent.getName()); - } /** * Finds all files and directories with a given file name and path in a @@ -779,5 +754,28 @@ public class FileManager implements Closeable { private AbstractFile addLocalFile(CaseDbTransaction trans, SpecialDirectory parentDirectory, java.io.File localFile, FileAddProgressUpdater progressUpdater) throws TskCoreException { return addLocalFile(trans, parentDirectory, localFile, TskData.EncodingType.NONE, progressUpdater); } + + /** + * Finds all files and directories with a given file name and given parent + * file or directory in a given data source (image, local/logical files set, + * etc.). The name search is for full or partial matches and is case + * insensitive (a case insensitive SQL LIKE clause is used to query the case + * database). + * + * @param dataSource The data source. + * @param fileName The full name or a pattern to match on part of the name + * @param parent The parent file or directory. + * + * @return The matching files and directories. + * + * @throws TskCoreException if there is a problem querying the case + * database. + * + * @deprecated Use version without the unnecessary dataSource argument + */ + @Deprecated + public List findFiles(Content dataSource, String fileName, AbstractFile parent) throws TskCoreException { + return findFiles(fileName, parent); + } } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/centralrepository/Bundle_ja.properties index cb6299b983..990e91a73e 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/Bundle_ja.properties @@ -1,3 +1,12 @@ -#Fri Feb 12 16:56:28 UTC 2021 +#Mon Jul 12 13:21:59 UTC 2021 +AddEditCentralRepoCommentAction.menuItemText.addEditCentralRepoComment=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u30b3\u30e1\u30f3\u30c8\u306e\u8ffd\u52a0/\u7de8\u96c6 +AddEditCentralRepoCommentAction.menuItemText.addEditCentralRepoCommentEmptyFile=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u30b3\u30e1\u30f3\u30c8\u306e\u8ffd\u52a0/\u7de8\u96c6\uff08\u7a7a\u306e\u30d5\u30a1\u30a4\u30eb\uff09 +AddEditCentralRepoCommentAction.menuItemText.addEditCentralRepoCommentNoMD5=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u30b3\u30e1\u30f3\u30c8\u306e\u8ffd\u52a0/\u7de8\u96c6\uff08MD5\u30cf\u30c3\u30b7\u30e5\u7121\u3057\uff09 +CentralRepoCommentDialog.cancelButton.text=C&ancel +CentralRepoCommentDialog.commentLabel.text=\u30b3\u30e1\u30f3\u30c8\uff1a +CentralRepoCommentDialog.okButton.text=&OK +CentralRepoCommentDialog.title.addEditCentralRepoComment=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u30b3\u30e1\u30f3\u30c8\u306e\u8ffd\u52a0/\u7de8\u96c6 +OpenIDE-Module-Display-Category=\u53d6\u8fbc\u307f\u30e2\u30b8\u30e5\u30fc\u30eb OpenIDE-Module-Long-Description=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u53d6\u308a\u8fbc\u307f\u30e2\u30b8\u30e5\u30fc\u30eb\u3068\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\n\n\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u306e\u53d6\u308a\u8fbc\u307f\u30e2\u30b8\u30e5\u30fc\u30eb\u306f\u3001\u9078\u629e\u3057\u305f\u76f8\u95a2\u30bf\u30a4\u30d7\u306b\u4e00\u81f4\u3059\u308b\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u306e\u5c5e\u6027\u3092\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306b\u683c\u7d0d\u3057\u307e\u3059\u3002\n\u4fdd\u5b58\u3055\u308c\u305f\u5c5e\u6027\u306f\u3001\u5c06\u6765\u306e\u30b1\u30fc\u30b9\u3067\u3001\u53d6\u308a\u8fbc\u307f\u4e2d\u306b\u30d5\u30a1\u30a4\u30eb\u3068\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u3092\u76f8\u4e92\u306b\u95a2\u9023\u4ed8\u3051\u3066\u5206\u6790\u3059\u308b\u305f\u3081\u306b\u4f7f\u7528\u3055\u308c\u307e\u3059\u3002 +OpenIDE-Module-Name=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea OpenIDE-Module-Short-Description=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u53d6\u308a\u8fbc\u307f\u30e2\u30b8\u30e5\u30fc\u30eb diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/application/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/centralrepository/application/Bundle_ja.properties new file mode 100644 index 0000000000..6e58d70fc8 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/application/Bundle_ja.properties @@ -0,0 +1,9 @@ +#Thu Jul 01 11:56:41 UTC 2021 +OtherOccurrences.csvHeader.attribute=\u4e00\u81f4\u3057\u305f\u30a2\u30c8\u30ea\u30d3\u30e5\u30fc\u30c8 +OtherOccurrences.csvHeader.case=\u30b1\u30fc\u30b9 +OtherOccurrences.csvHeader.comment=\u30b3\u30e1\u30f3\u30c8 +OtherOccurrences.csvHeader.dataSource=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9 +OtherOccurrences.csvHeader.device=\u30c7\u30d0\u30a4\u30b9 +OtherOccurrences.csvHeader.known=\u65e2\u77e5 +OtherOccurrences.csvHeader.path=\u30d1\u30b9 +OtherOccurrences.csvHeader.value=\u30a2\u30c8\u30ea\u30d3\u30e5\u30fc\u30c8\u5024 diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/application/OtherOccurrences.java b/Core/src/org/sleuthkit/autopsy/centralrepository/application/OtherOccurrences.java index 934c8015a4..155ca727d5 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/application/OtherOccurrences.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/application/OtherOccurrences.java @@ -31,6 +31,7 @@ import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Optional; import java.util.logging.Level; import org.apache.commons.lang3.StringUtils; import org.joda.time.DateTimeZone; @@ -52,6 +53,9 @@ import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifactTag; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.ContentTag; +import org.sleuthkit.datamodel.DataSource; +import org.sleuthkit.datamodel.OsAccount; +import org.sleuthkit.datamodel.OsAccountInstance; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; @@ -63,17 +67,63 @@ import org.sleuthkit.datamodel.TskData; public final class OtherOccurrences { private static final Logger logger = Logger.getLogger(OtherOccurrences.class.getName()); - + private static final String UUID_PLACEHOLDER_STRING = "NoCorrelationAttributeInstance"; private OtherOccurrences() { } + /** + * Determine what attributes can be used for correlation based on the node. + * + * @param node The node to correlate + * @param osAccount the osAccount to correlate + * + * @return A list of attributes that can be used for correlation + */ + public static Collection getCorrelationAttributeFromOsAccount(Node node, OsAccount osAccount) { + Collection ret = new ArrayList<>(); + Optional osAccountAddr = osAccount.getAddr(); + + if (osAccountAddr.isPresent()) { + try { + for (OsAccountInstance instance : osAccount.getOsAccountInstances()) { + DataSource osAccountDataSource = instance.getDataSource(); + try { + CorrelationCase correlationCase = CentralRepository.getInstance().getCase(Case.getCurrentCaseThrows()); + CorrelationAttributeInstance correlationAttributeInstance = new CorrelationAttributeInstance( + CentralRepository.getInstance().getCorrelationTypeById(CorrelationAttributeInstance.OSACCOUNT_TYPE_ID), + osAccountAddr.get(), + correlationCase, + CorrelationDataSource.fromTSKDataSource(correlationCase, instance.getDataSource()), + "", + "", + TskData.FileKnown.KNOWN, + osAccount.getId()); + + ret.add(correlationAttributeInstance); + } catch (CentralRepoException ex) { + logger.log(Level.SEVERE, String.format("Cannot get central repository for OsAccount: %s.", osAccountAddr.get()), ex); //NON-NLS + } catch (NoCurrentCaseException ex) { + logger.log(Level.WARNING, String.format("Exception while getting open case looking up osAccount %s.", osAccountAddr.get()), ex); //NON-NLS + } catch (CorrelationAttributeNormalizationException ex) { + logger.log(Level.SEVERE, String.format("Exception with Correlation Attribute Normalization for osAccount %s.", osAccountAddr.get()), ex); //NON-NLS + } + } + } catch (TskCoreException ex) { + logger.log(Level.INFO, String.format("Unable to check create CorrelationAttribtueInstance for osAccount %s.", osAccountAddr.get()), ex); + } + } + + return ret; + } + /** * Determine what attributes can be used for correlation based on the node. * If EamDB is not enabled, get the default Files correlation. * - * @param node The node to correlate + * @param node The node to correlate. + * @param file The file to correlate. * * @return A list of attributes that can be used for correlation */ @@ -170,7 +220,6 @@ public final class OtherOccurrences { public static AbstractFile getAbstractFileFromNode(Node node) { BlackboardArtifactTag nodeBbArtifactTag = node.getLookup().lookup(BlackboardArtifactTag.class); ContentTag nodeContentTag = node.getLookup().lookup(ContentTag.class); - BlackboardArtifact nodeBbArtifact = node.getLookup().lookup(BlackboardArtifact.class); AbstractFile nodeAbstractFile = node.getLookup().lookup(AbstractFile.class); if (nodeBbArtifactTag != null) { @@ -180,18 +229,6 @@ public final class OtherOccurrences { } } else if (nodeContentTag != null) { Content content = nodeContentTag.getContent(); - if (content instanceof AbstractFile) { - return (AbstractFile) content; - } - } else if (nodeBbArtifact != null) { - Content content; - try { - content = nodeBbArtifact.getSleuthkitCase().getContentById(nodeBbArtifact.getObjectID()); - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Error retrieving blackboard artifact", ex); // NON-NLS - return null; - } - if (content instanceof AbstractFile) { return (AbstractFile) content; } @@ -208,7 +245,10 @@ public final class OtherOccurrences { * artifact. If the central repo is not enabled, this will only return files * from the current case with matching MD5 hashes. * - * @param corAttr CorrelationAttribute to query for + * @param file The current file. + * @param deviceId The device ID for the current data source. + * @param dataSourceName The name of the current data source. + * @param corAttr CorrelationAttribute to query for * * @return A collection of correlated artifact instances */ @@ -240,12 +280,12 @@ public final class OtherOccurrences { UniquePathKey uniquePathKey = new UniquePathKey(newNode); nodeDataMap.put(uniquePathKey, newNode); } - if (file != null && corAttr.getCorrelationType().getDisplayName().equals("Files")) { - List caseDbFiles = getCaseDbMatches(corAttr, openCase, file); + } + if (file != null && corAttr.getCorrelationType().getDisplayName().equals("Files")) { + List caseDbFiles = getCaseDbMatches(corAttr, openCase, file); - for (AbstractFile caseDbFile : caseDbFiles) { - addOrUpdateNodeData(openCase, nodeDataMap, caseDbFile); - } + for (AbstractFile caseDbFile : caseDbFiles) { + addOrUpdateNodeData(openCase, nodeDataMap, caseDbFile); } } return nodeDataMap; @@ -347,7 +387,7 @@ public final class OtherOccurrences { public static String makeDataSourceString(String caseUUID, String deviceId, String dataSourceName) { return caseUUID + deviceId + dataSourceName; } - + /** * Gets the list of Eam Cases and determines the earliest case creation * date. Sets the label to display the earliest date string to the user. @@ -377,8 +417,8 @@ public final class OtherOccurrences { return dateStringDisplay; } - - @NbBundle.Messages({ + + @NbBundle.Messages({ "OtherOccurrences.csvHeader.case=Case", "OtherOccurrences.csvHeader.device=Device", "OtherOccurrences.csvHeader.dataSource=Data Source", diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/Bundle.properties-MERGED index e4507c7d3b..a97cc319da 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/Bundle.properties-MERGED @@ -43,5 +43,5 @@ OtherOccurrencesPanel.showCommonalityMenuItem.text=Show Frequency OtherOccurrencesPanel.showCaseDetailsMenuItem.text=Show Case Details OtherOccurrencesPanel.table.noArtifacts=Item has no attributes with which to search. OtherOccurrencesPanel.table.noResultsFound=No results found. -OtherOccurrencesPanel_earliestCaseNotAvailable=Not Availble. +OtherOccurrencesPanel_earliestCaseNotAvailable=Not Available. OtherOccurrencesPanel_table_loadingResults=Loading results diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/Bundle_ja.properties index 68dfcf62be..bf7a9c108a 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/Bundle_ja.properties @@ -1,54 +1,42 @@ -DataContentViewerOtherCases.caseDetailsDialog.noCaseNameError=\u30a8\u30e9\u30fc -DataContentViewerOtherCases.caseDetailsDialog.noDetails=\u3053\u306e\u30b1\u30fc\u30b9\u306e\u8a73\u7d30\u306f\u3042\u308a\u307e\u305b\u3093\u3002 -DataContentViewerOtherCases.caseDetailsDialog.noDetailsReference=\u30b0\u30ed\u30fc\u30d0\u30eb\u30ec\u30d5\u30a1\u30ec\u30f3\u30b9\u30d7\u30ed\u30d1\u30c6\u30a3\u306e\u30b1\u30fc\u30b9\u8a73\u7d30\u306f\u3042\u308a\u307e\u305b\u3093\u3002 -DataContentViewerOtherCases.caseDetailsDialog.notSelected=\u884c\u304c\u9078\u629e\u3055\u308c\u3066\u3044\u307e\u305b\u3093 -# {0} - \u5171\u6709\u6027\u306e\u5272\u5408 -# {1} - \u76f8\u95a2\u5206\u6790\u30bf\u30a4\u30d7 -# {2} - \u76f8\u95a2\u5206\u6790\u5024 -DataContentViewerOtherCases.correlatedArtifacts.byType=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u306e {0}% \u306b {2} \u304c\u3042\u308a\u307e\u3059(\u30bf\u30a4\u30d7: {1})\n -DataContentViewerOtherCases.correlatedArtifacts.failed=\u983b\u5ea6\u306e\u8a73\u7d30\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 -DataContentViewerOtherCases.correlatedArtifacts.isEmpty=\u76f8\u95a2\u5206\u6790\u3059\u308b\u305f\u3081\u306e\u30d5\u30a1\u30a4\u30eb\u3084\u904e\u53bb\u306e\u691c\u7d22\u7d50\u679c\u304c\u3042\u308a\u307e\u305b\u3093\u3002 -DataContentViewerOtherCases.correlatedArtifacts.title=\u5c5e\u6027\u983b\u5ea6 -DataContentViewerOtherCases.dataSources.header.text=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u540d -DataContentViewerOtherCases.earliestCaseNotAvailable=\ \u6709\u52b9\u306b\u306a\u3063\u3066\u3044\u307e\u305b\u3093\u3002 -DataContentViewerOtherCases.foundIn.text=%d \u306e\u30b1\u30fc\u30b9\u3068 %d \u306e\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u5185\u306b %d \u306e\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u304c\u898b\u3064\u304b\u308a\u307e\u3057\u305f\u3002 -DataContentViewerOtherCases.noOpenCase.errMsg=\u958b\u3044\u3066\u3044\u308b\u30b1\u30fc\u30b9\u306f\u3042\u308a\u307e\u305b\u3093\u3002 -DataContentViewerOtherCases.table.noArtifacts=\u9805\u76ee\u306b\u691c\u7d22\u306b\u5229\u7528\u3067\u304d\u308b\u5c5e\u6027\u306f\u3042\u308a\u307e\u305b\u3093\u3002 -DataContentViewerOtherCases.table.noResultsFound=\u8a72\u5f53\u3059\u308b\u7d50\u679c\u304c\u3042\u308a\u307e\u305b\u3093\u3002 +#Thu Jul 01 11:56:41 UTC 2021 DataContentViewerOtherCases.table.toolTip.text=\u5217\u540d\u3092\u30af\u30ea\u30c3\u30af\u3057\u3066\u30bd\u30fc\u30c8\u3057\u307e\u3059\u3002\u30c6\u30fc\u30d6\u30eb\u3092\u53f3\u30af\u30ea\u30c3\u30af\u3057\u3066\u3055\u3089\u306a\u308b\u30aa\u30d7\u30b7\u30e7\u30f3\u3092\u8868\u793a\u3057\u307e\u3059\u3002 DataContentViewerOtherCases.title=\u305d\u306e\u4ed6\u306e\u767a\u751f DataContentViewerOtherCases.toolTip=\u305d\u306e\u4ed6\u306e\u767a\u751f\u304b\u3089\u9078\u629e\u3057\u305f\u30d5\u30a1\u30a4\u30eb/\u904e\u53bb\u306e\u691c\u7d22\u7d50\u679c\u306e\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u3092\u8868\u793a\u3057\u307e\u3059\u3002 -DataContentViewerOtherCasesModel.csvHeader.attribute=\u4e00\u81f4\u3057\u305f\u5c5e\u6027 -DataContentViewerOtherCasesModel.csvHeader.case=\u30b1\u30fc\u30b9 -DataContentViewerOtherCasesModel.csvHeader.comment=\u30b3\u30e1\u30f3\u30c8 -DataContentViewerOtherCasesModel.csvHeader.dataSource=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9 -DataContentViewerOtherCasesModel.csvHeader.device=\u30c7\u30d0\u30a4\u30b9 -DataContentViewerOtherCasesModel.csvHeader.known=\u65e2\u77e5 -DataContentViewerOtherCasesModel.csvHeader.path=\u30d1\u30b9 -DataContentViewerOtherCasesModel.csvHeader.value=\u5c5e\u6027\u5024 -OccurrencePanel.caseCreatedDateLabel.text=\u4f5c\u6210\u65e5: +OccurrencePanel.caseCreatedDateLabel.text=\u4f5c\u6210\u65e5\: OccurrencePanel.caseDetails.text=\u30b1\u30fc\u30b9\u8a73\u7d30 -OccurrencePanel.caseNameLabel.text=\u540d\u524d: +OccurrencePanel.caseNameLabel.text=\u540d\u524d\: OccurrencePanel.commonProperties.text=\u5171\u901a\u306e\u30d7\u30ed\u30d1\u30c6\u30a3 -OccurrencePanel.commonPropertyCommentLabel.text=\u30b3\u30e1\u30f3\u30c8: -OccurrencePanel.commonPropertyKnownStatusLabel.text=\u65e2\u77e5\u306e\u30b9\u30c6\u30fc\u30bf\u30b9: -OccurrencePanel.commonPropertyTypeLabel.text=\u30bf\u30a4\u30d7: -OccurrencePanel.commonPropertyValueLabel.text=\u5024: +OccurrencePanel.commonPropertyCommentLabel.text=\u30b3\u30e1\u30f3\u30c8\: +OccurrencePanel.commonPropertyKnownStatusLabel.text=\u65e2\u77e5\u306e\u30b9\u30c6\u30fc\u30bf\u30b9\: +OccurrencePanel.commonPropertyTypeLabel.text=\u30bf\u30a4\u30d7\: +OccurrencePanel.commonPropertyValueLabel.text=\u5024\: OccurrencePanel.dataSourceDetails.text=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u8a73\u7d30 -OccurrencePanel.dataSourceNameLabel.text=\u540d\u524d: +OccurrencePanel.dataSourceNameLabel.text=\u540d\u524d\: OccurrencePanel.fileDetails.text=\u30d5\u30a1\u30a4\u30eb\u8a73\u7d30 -OccurrencePanel.filePathLabel.text=\u30d5\u30a1\u30a4\u30eb\u30d1\u30b9: +OccurrencePanel.filePathLabel.text=\u30d5\u30a1\u30a4\u30eb\u30d1\u30b9\: OtherOccurrencesCasesTableModel.case=\u30b1\u30fc\u30b9 OtherOccurrencesCasesTableModel.noData=\u30c7\u30fc\u30bf\u304c\u3042\u308a\u307e\u305b\u3093\u3002 OtherOccurrencesDataSourcesTableModel.dataSourceName=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u540d OtherOccurrencesDataSourcesTableModel.noData=\u30c7\u30fc\u30bf\u304c\u3042\u308a\u307e\u305b\u3093\u3002 OtherOccurrencesFilesTableModel.fileName=\u30d5\u30a1\u30a4\u30eb\u540d OtherOccurrencesFilesTableModel.noData=\u30c7\u30fc\u30bf\u304c\u3042\u308a\u307e\u305b\u3093\u3002 -OtherOccurrencesPanel.filesTable.toolTipText=\u5217\u540d\u3092\u30af\u30ea\u30c3\u30af\u3057\u3066\u30bd\u30fc\u30c8\u3057\u307e\u3059\u3002\u30c6\u30fc\u30d6\u30eb\u3092\u53f3\u30af\u30ea\u30c3\u30af\u3057\u3066\u3055\u3089\u306a\u308b\u30aa\u30d7\u30b7\u30e7\u30f3\u3092\u8868\u793a\u3057\u307e\u3059\u3002 -OtherOccurrencesPanel.earliestCaseLabel.toolTipText= -OtherOccurrencesPanel.earliestCaseLabel.text=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ec\u30dd\u30b8\u30c8\u30ea\u30fc\u958b\u59cb\u65e5: -OtherOccurrencesPanel.earliestCaseDate.text=\u6700\u3082\u53e4\u3044\u30b1\u30fc\u30b9\u65e5\u4ed8 -OtherOccurrencesPanel.foundInLabel.text= +OtherOccurrencesPanel.caseDetailsDialog.noCaseNameError=\u30a8\u30e9\u30fc +OtherOccurrencesPanel.caseDetailsDialog.noDetails=\u3053\u306e\u30b1\u30fc\u30b9\u306e\u8a73\u7d30\u306f\u3042\u308a\u307e\u305b\u3093\u3002 +OtherOccurrencesPanel.caseDetailsDialog.noDetailsReference=\u30b0\u30ed\u30fc\u30d0\u30eb\u53c2\u7167\u30d7\u30ed\u30d1\u30c6\u30a3\u306e\u30b1\u30fc\u30b9\u306e\u8a73\u7d30\u306f\u3042\u308a\u307e\u305b\u3093\u3002 +OtherOccurrencesPanel.caseDetailsDialog.notSelected=\u884c\u304c\u9078\u629e\u3055\u308c\u3066\u3044\u307e\u305b\u3093 +OtherOccurrencesPanel.correlatedArtifacts.byType=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u306e{0}\uff05\u306b{2}\u304c\u3042\u308a\u307e\u3059\uff08\u30bf\u30a4\u30d7\uff1a{1}\uff09 +OtherOccurrencesPanel.correlatedArtifacts.failed=\u983b\u5ea6\u306e\u8a73\u7d30\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +OtherOccurrencesPanel.correlatedArtifacts.isEmpty=\u95a2\u9023\u4ed8\u3051\u308b\u30d5\u30a1\u30a4\u30eb\u3084\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u306f\u3042\u308a\u307e\u305b\u3093\u3002 +OtherOccurrencesPanel.correlatedArtifacts.title=\u30a2\u30c8\u30ea\u30d3\u30e5\u30fc\u30c8\u306e\u983b\u5ea6 +OtherOccurrencesPanel.earliestCaseDate.text=\u30b1\u30fc\u30b9\u306e\u6700\u521d\u306e\u65e5\u4ed8 +OtherOccurrencesPanel.earliestCaseLabel.text=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u306e\u958b\u59cb\u65e5\uff1a +OtherOccurrencesPanel.exportToCSVMenuItem.text=\u305d\u306e\u4ed6\u306e\u3059\u3079\u3066\u306e\u767a\u751f\u3092CSV\u306b\u30a8\u30af\u30b9\u30dd\u30fc\u30c8 +OtherOccurrencesPanel.filesTable.toolTipText=\u4e26\u3079\u66ff\u3048\u306f\u5217\u540d\u3092\u30af\u30ea\u30c3\u30af\u3002 \u305d\u306e\u4ed6\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u306f\u3001\u30c6\u30fc\u30d6\u30eb\u3092\u53f3\u30af\u30ea\u30c3\u30af\u3002 +OtherOccurrencesPanel.foundIn.text=\uff05d\u30b1\u30fc\u30b9\u3068\uff05d\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3067\uff05d\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u304c\u898b\u3064\u304b\u308a\u307e\u3057\u305f\u3002 +OtherOccurrencesPanel.noOpenCase.errMsg=\u30aa\u30fc\u30d7\u30f3\u30b1\u30fc\u30b9\u306f\u3042\u308a\u307e\u305b\u3093\u3002 +OtherOccurrencesPanel.showCaseDetailsMenuItem.text=\u30b1\u30fc\u30b9\u306e\u8a73\u7d30\u3092\u8868\u793a OtherOccurrencesPanel.showCommonalityMenuItem.text=\u983b\u5ea6\u3092\u8868\u793a -OtherOccurrencesPanel.showCaseDetailsMenuItem.text=\u30b1\u30fc\u30b9\u8a73\u7d30\u3092\u8868\u793a -OtherOccurrencesPanel.exportToCSVMenuItem.text=\u305d\u306e\u4ed6\u3059\u3079\u3066\u306e\u767a\u751f\u3092CSV\u306b\u30a8\u30af\u30b9\u30dd\u30fc\u30c8 +OtherOccurrencesPanel.table.noArtifacts=\u30a2\u30a4\u30c6\u30e0\u306b\u306f\u3001\u691c\u7d22\u3059\u308b\u30a2\u30c8\u30ea\u30d3\u30e5\u30fc\u30c8\u304c\u3042\u308a\u307e\u305b\u3093\u3002 +OtherOccurrencesPanel.table.noResultsFound=\u7d50\u679c\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3002 +OtherOccurrencesPanel_earliestCaseNotAvailable=\u5229\u7528\u4e0d\u53ef\u3002 +OtherOccurrencesPanel_table_loadingResults=\u7d50\u679c\u306e\u8aad\u8fbc\u4e2d diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java index c44b4e2479..282a77c246 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java @@ -31,6 +31,7 @@ import org.sleuthkit.autopsy.centralrepository.application.OtherOccurrences; import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; +import org.sleuthkit.datamodel.OsAccount; /** * View correlation results from other cases @@ -90,17 +91,18 @@ public final class DataContentViewerOtherCases extends JPanel implements DataCon public boolean isSupported(Node node) { // Is supported if one of the following is true: - // - The central repo is enabled and the node has correlatable content - // (either through the MD5 hash of the associated file or through a BlackboardArtifact) + // - The central repo is enabled and the node is not null // - The central repo is disabled and the backing file has a valid MD5 hash - AbstractFile file = OtherOccurrences.getAbstractFileFromNode(node); - if (CentralRepository.isEnabled()) { - return !OtherOccurrences.getCorrelationAttributesFromNode(node, file).isEmpty(); - } else { + // And the node has information which could be correlated on. + if (CentralRepository.isEnabled() && node != null) { + return OtherOccurrences.getAbstractFileFromNode(node) != null || OtherOccurrences.getBlackboardArtifactFromNode(node) != null || node.getLookup().lookup(OsAccount.class) != null; + } else if (node != null) { + AbstractFile file = OtherOccurrences.getAbstractFileFromNode(node); return file != null && file.getSize() > 0 && ((file.getMd5Hash() != null) && (!file.getMd5Hash().isEmpty())); } + return false; } @Override diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/OtherOccurrencesNodeWorker.java b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/OtherOccurrencesNodeWorker.java index 0654002f6f..ab8821931a 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/OtherOccurrencesNodeWorker.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/OtherOccurrencesNodeWorker.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.centralrepository.contentviewer; +import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; @@ -37,6 +38,7 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationCase; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Content; +import org.sleuthkit.datamodel.OsAccount; import org.sleuthkit.datamodel.TskException; /** @@ -60,7 +62,11 @@ class OtherOccurrencesNodeWorker extends SwingWorker @Override protected OtherOccurrencesData doInBackground() throws Exception { + OsAccount osAccount = node.getLookup().lookup(OsAccount.class); AbstractFile file = OtherOccurrences.getAbstractFileFromNode(node); + if (osAccount != null) { + file = node.getLookup().lookup(AbstractFile.class); + } String deviceId = ""; String dataSourceName = ""; Map caseNames = new HashMap<>(); @@ -77,8 +83,12 @@ class OtherOccurrencesNodeWorker extends SwingWorker // @@@ Review this behavior return null; } - Collection correlationAttributes = OtherOccurrences.getCorrelationAttributesFromNode(node, file); - + Collection correlationAttributes = new ArrayList<>(); + if (osAccount != null) { + correlationAttributes = OtherOccurrences.getCorrelationAttributeFromOsAccount(node, osAccount); + } else { + correlationAttributes = OtherOccurrences.getCorrelationAttributesFromNode(node, file); + } int totalCount = 0; Set dataSources = new HashSet<>(); for (CorrelationAttributeInstance corAttr : correlationAttributes) { diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/OtherOccurrencesPanel.form b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/OtherOccurrencesPanel.form index 237bfe4ce8..13284ecec9 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/OtherOccurrencesPanel.form +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/OtherOccurrencesPanel.form @@ -34,8 +34,6 @@ - - diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/OtherOccurrencesPanel.java b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/OtherOccurrencesPanel.java index c4d0bf0e0a..9e962b1a1b 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/OtherOccurrencesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/OtherOccurrencesPanel.java @@ -35,6 +35,9 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.FutureTask; import java.util.logging.Level; import javax.swing.JFileChooser; import javax.swing.JMenuItem; @@ -46,7 +49,6 @@ import javax.swing.SwingWorker; import javax.swing.filechooser.FileNameExtensionFilter; import javax.swing.table.TableModel; import javax.swing.table.TableRowSorter; -import org.openide.util.Exceptions; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; @@ -71,7 +73,6 @@ public final class OtherOccurrencesPanel extends javax.swing.JPanel { private static final CorrelationCaseWrapper NO_ARTIFACTS_CASE = new CorrelationCaseWrapper(Bundle.OtherOccurrencesPanel_table_noArtifacts()); private static final CorrelationCaseWrapper NO_RESULTS_CASE = new CorrelationCaseWrapper(Bundle.OtherOccurrencesPanel_table_noResultsFound()); - private static final CorrelationCaseWrapper LOADING_CASE = new CorrelationCaseWrapper(Bundle.OtherOccurrencesPanel_table_loadingResults()); private static final Logger logger = Logger.getLogger(OtherOccurrencesPanel.class.getName()); private static final long serialVersionUID = 1L; private final OtherOccurrencesFilesTableModel filesTableModel; @@ -85,6 +86,11 @@ public final class OtherOccurrencesPanel extends javax.swing.JPanel { private SwingWorker worker; + // Initializing the JFileChooser in a thread to prevent a block on the EDT + // see https://stackoverflow.com/questions/49792375/jfilechooser-is-very-slow-when-using-windows-look-and-feel + private final FutureTask futureFileChooser = new FutureTask<>(JFileChooser::new); + private JFileChooser CSVFileChooser; + /** * Creates new form OtherOccurrencesPanel */ @@ -93,9 +99,11 @@ public final class OtherOccurrencesPanel extends javax.swing.JPanel { this.casesTableModel = new OtherOccurrencesCasesTableModel(); this.dataSourcesTableModel = new OtherOccurrencesDataSourcesTableModel(); this.correlationAttributes = new ArrayList<>(); - occurrencePanel = new OccurrencePanel(); initComponents(); customizeComponents(); + + ExecutorService executor = Executors.newSingleThreadExecutor(); + executor.execute(futureFileChooser); } private void customizeComponents() { @@ -215,7 +223,7 @@ public final class OtherOccurrencesPanel extends javax.swing.JPanel { String caseDisplayName = Bundle.OtherOccurrencesPanel_caseDetailsDialog_noCaseNameError(); String details = Bundle.OtherOccurrencesPanel_caseDetailsDialog_noDetails(); try { - if (-1 != selectedRowViewIdx) { + if (-1 != selectedRowViewIdx && filesTableModel.getRowCount() > 0) { CentralRepository dbManager = CentralRepository.getInstance(); int selectedRowModelIdx = filesTable.convertRowIndexToModel(selectedRowViewIdx); List rowList = filesTableModel.getListOfNodesForFile(selectedRowModelIdx); @@ -245,6 +253,18 @@ public final class OtherOccurrencesPanel extends javax.swing.JPanel { private void saveToCSV() throws NoCurrentCaseException { if (casesTableModel.getRowCount() > 0) { + + if (CSVFileChooser == null) { + try { + CSVFileChooser = futureFileChooser.get(); + } catch (InterruptedException | ExecutionException ex) { + // If something happened with the thread try and + // initalized the chooser now + logger.log(Level.WARNING, "A failure occurred in the JFileChooser background thread"); + CSVFileChooser = new JFileChooser(); + } + } + Calendar now = Calendar.getInstance(); String fileName = String.format("%1$tY%1$tm%1$te%1$tI%1$tM%1$tS_other_data_sources.csv", now); CSVFileChooser.setCurrentDirectory(new File(Case.getCurrentCaseThrows().getExportDirectory())); @@ -258,13 +278,13 @@ public final class OtherOccurrencesPanel extends javax.swing.JPanel { if (!selectedFile.getName().endsWith(".csv")) { // NON-NLS selectedFile = new File(selectedFile.toString() + ".csv"); // NON-NLS } - CSVWorker worker = new CSVWorker(selectedFile, file, dataSourceName, deviceId, Collections.unmodifiableCollection(correlationAttributes)); - worker.execute(); + CSVWorker csvWorker = new CSVWorker(selectedFile, file, dataSourceName, deviceId, Collections.unmodifiableCollection(correlationAttributes)); + csvWorker.execute(); } } } - @NbBundle.Messages({"OtherOccurrencesPanel_earliestCaseNotAvailable=Not Availble."}) + @NbBundle.Messages({"OtherOccurrencesPanel_earliestCaseNotAvailable=Not Available."}) /** * Reset the UI and clear cached data. */ @@ -309,8 +329,9 @@ public final class OtherOccurrencesPanel extends javax.swing.JPanel { } casesTableModel.clearTable(); - - OtherOccurrenceOneTypeWorker.OneTypeData data = get(); + + OtherOccurrenceOneTypeWorker.OneTypeData data = get(); + correlationAttributes.addAll(data.getCorrelationAttributesToAdd()); for (CorrelationCase corCase : data.getCaseNames().values()) { casesTableModel.addCorrelationCase(new CorrelationCaseWrapper(corCase)); } @@ -319,12 +340,13 @@ public final class OtherOccurrencesPanel extends javax.swing.JPanel { casesTableModel.addCorrelationCase(NO_ARTIFACTS_CASE); } else if (caseCount == 0) { casesTableModel.addCorrelationCase(NO_RESULTS_CASE); - } - String earliestDate = data.getEarliestCaseDate(); - earliestCaseDate.setText(earliestDate.isEmpty() ? Bundle.OtherOccurrencesPanel_earliestCaseNotAvailable() : earliestDate); - foundInLabel.setText(String.format(Bundle.OtherOccurrencesPanel_foundIn_text(), data.getTotalCount(), caseCount, data.getDataSourceCount())); - if (caseCount > 0) { - casesTable.setRowSelectionInterval(0, 0); + } else { + String earliestDate = data.getEarliestCaseDate(); + earliestCaseDate.setText(earliestDate.isEmpty() ? Bundle.OtherOccurrencesPanel_earliestCaseNotAvailable() : earliestDate); + foundInLabel.setText(String.format(Bundle.OtherOccurrencesPanel_foundIn_text(), data.getTotalCount(), caseCount, data.getDataSourceCount())); + if (caseCount > 0) { + casesTable.setRowSelectionInterval(0, 0); + } } } catch (InterruptedException | ExecutionException ex) { @@ -369,12 +391,13 @@ public final class OtherOccurrencesPanel extends javax.swing.JPanel { casesTableModel.addCorrelationCase(NO_ARTIFACTS_CASE); } else if (caseCount == 0) { casesTableModel.addCorrelationCase(NO_RESULTS_CASE); - } - String earliestDate = data.getEarliestCaseDate(); - earliestCaseDate.setText(earliestDate.isEmpty() ? Bundle.OtherOccurrencesPanel_earliestCaseNotAvailable() : earliestDate); - foundInLabel.setText(String.format(Bundle.OtherOccurrencesPanel_foundIn_text(), data.getInstanceDataCount(), caseCount, data.getDataSourceCount())); - if (caseCount > 0) { - casesTable.setRowSelectionInterval(0, 0); + } else { + String earliestDate = data.getEarliestCaseDate(); + earliestCaseDate.setText(earliestDate.isEmpty() ? Bundle.OtherOccurrencesPanel_earliestCaseNotAvailable() : earliestDate); + foundInLabel.setText(String.format(Bundle.OtherOccurrencesPanel_foundIn_text(), data.getInstanceDataCount(), caseCount, data.getDataSourceCount())); + if (caseCount > 0) { + casesTable.setRowSelectionInterval(0, 0); + } } } @@ -400,7 +423,7 @@ public final class OtherOccurrencesPanel extends javax.swing.JPanel { return; } - + setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); worker = new SelectionWorker(correlationAttributes, file, deviceId, dataSourceName) { @@ -420,31 +443,32 @@ public final class OtherOccurrencesPanel extends javax.swing.JPanel { currentCaseName = null; logger.log(Level.WARNING, "Unable to get current case for other occurrences content viewer", ex); } - - for (NodeData nodeData : correlatedNodeDataMap.values()) { - for (int selectedRow : selectedCaseIndexes) { - try { - if (nodeData.isCentralRepoNode()) { - if (casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(selectedRow)) != null - && casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(selectedRow)).getCaseUUID().equals(nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID())) { + if (casesTableModel.getRowCount() > 0) { + for (NodeData nodeData : correlatedNodeDataMap.values()) { + for (int selectedRow : selectedCaseIndexes) { + try { + if (nodeData.isCentralRepoNode()) { + if (casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(selectedRow)) != null + && casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(selectedRow)).getCaseUUID().equals(nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID())) { + dataSourcesTableModel.addNodeData(nodeData); + } + } else if (currentCaseName != null && (casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(selectedRow)).getCaseUUID().equals(currentCaseName))) { dataSourcesTableModel.addNodeData(nodeData); } - } else if (currentCaseName != null && (casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(selectedRow)).getCaseUUID().equals(currentCaseName))) { - dataSourcesTableModel.addNodeData(nodeData); + } catch (CentralRepoException ex) { + logger.log(Level.WARNING, "Unable to get correlation attribute instance from OtherOccurrenceNodeInstanceData for case " + nodeData.getCaseName(), ex); } - } catch (CentralRepoException ex) { - logger.log(Level.WARNING, "Unable to get correlation attribute instance from OtherOccurrenceNodeInstanceData for case " + nodeData.getCaseName(), ex); } } } - if (dataSourcesTable.getRowCount() > 0) { + if (dataSourcesTableModel.getRowCount() > 0) { dataSourcesTable.setRowSelectionInterval(0, 0); } - + setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); } catch (InterruptedException | ExecutionException ex) { - logger.log(Level.SEVERE, "Failed to update OtherOccurrencesPanel on data source selection", ex); + logger.log(Level.SEVERE, "Failed to update OtherOccurrencesPanel on data source selection", ex); } } }; @@ -476,25 +500,29 @@ public final class OtherOccurrencesPanel extends javax.swing.JPanel { try { Map correlatedNodeDataMap = get(); - for (NodeData nodeData : correlatedNodeDataMap.values()) { - for (int selectedDataSourceRow : selectedDataSources) { - try { - if (nodeData.isCentralRepoNode()) { - if (dataSourcesTableModel.getCaseUUIDForRow(dataSourcesTable.convertRowIndexToModel(selectedDataSourceRow)).equals(nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID()) - && dataSourcesTableModel.getDeviceIdForRow(dataSourcesTable.convertRowIndexToModel(selectedDataSourceRow)).equals(nodeData.getDeviceID())) { - filesTableModel.addNodeData(nodeData); - } - } else { - if (dataSourcesTableModel.getDeviceIdForRow(dataSourcesTable.convertRowIndexToModel(selectedDataSourceRow)).equals(nodeData.getDeviceID())) { - filesTableModel.addNodeData(nodeData); + if (dataSourcesTableModel.getRowCount() > 0) { + for (NodeData nodeData : correlatedNodeDataMap.values()) { + for (int selectedDataSourceRow : selectedDataSources) { + int rowModelIndex = dataSourcesTable.convertRowIndexToModel(selectedDataSourceRow); + try { + if (nodeData.isCentralRepoNode()) { + if (dataSourcesTableModel.getCaseUUIDForRow(rowModelIndex).equals(nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID()) + && dataSourcesTableModel.getDeviceIdForRow(rowModelIndex).equals(nodeData.getDeviceID())) { + filesTableModel.addNodeData(nodeData); + } + } else { + if (dataSourcesTableModel.getDeviceIdForRow(dataSourcesTable.convertRowIndexToModel(selectedDataSourceRow)).equals(nodeData.getDeviceID())) { + filesTableModel.addNodeData(nodeData); + } } + } catch (CentralRepoException ex) { + logger.log(Level.WARNING, "Unable to get correlation attribute instance from OtherOccurrenceNodeInstanceData for case " + nodeData.getCaseName(), ex); } - } catch (CentralRepoException ex) { - logger.log(Level.WARNING, "Unable to get correlation attribute instance from OtherOccurrenceNodeInstanceData for case " + nodeData.getCaseName(), ex); } } } - if (filesTable.getRowCount() > 0) { + + if (filesTableModel.getRowCount() > 0) { filesTable.setRowSelectionInterval(0, 0); } } catch (InterruptedException | ExecutionException ex) { @@ -515,18 +543,20 @@ public final class OtherOccurrencesPanel extends javax.swing.JPanel { private void updateOnFileSelection() { setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); try { - if (filesTable.getSelectedRowCount() == 1) { + if (filesTableModel.getRowCount() > 0 && filesTable.getSelectedRowCount() == 1) { //if there is one file selected update the deatils to show the data for that file occurrencePanel = new OccurrencePanel(filesTableModel.getListOfNodesForFile(filesTable.convertRowIndexToModel(filesTable.getSelectedRow()))); - } else if (dataSourcesTable.getSelectedRowCount() == 1) { + } else if (dataSourcesTableModel.getRowCount() > 0 && dataSourcesTable.getSelectedRowCount() == 1) { //if no files were selected and only one data source is selected update the information to reflect the data source String caseName = dataSourcesTableModel.getCaseNameForRow(dataSourcesTable.convertRowIndexToModel(dataSourcesTable.getSelectedRow())); String dsName = dataSourcesTableModel.getValueAt(dataSourcesTable.convertRowIndexToModel(dataSourcesTable.getSelectedRow()), 0).toString(); String caseCreatedDate = ""; - for (int row : casesTable.getSelectedRows()) { - if (casesTableModel.getValueAt(casesTable.convertRowIndexToModel(row), 0).toString().equals(caseName)) { - caseCreatedDate = getCaseCreatedDate(row); - break; + if (casesTableModel.getRowCount() > 0) { + for (int row : casesTable.getSelectedRows()) { + if (casesTableModel.getValueAt(casesTable.convertRowIndexToModel(row), 0).toString().equals(caseName)) { + caseCreatedDate = getCaseCreatedDate(row); + break; + } } } occurrencePanel = new OccurrencePanel(caseName, caseCreatedDate, dsName); @@ -535,7 +565,7 @@ public final class OtherOccurrencesPanel extends javax.swing.JPanel { //update the information to reflect the case String createdDate; String caseName = ""; - if (casesTable.getRowCount() > 0) { + if (casesTableModel.getRowCount() > 0) { caseName = casesTableModel.getValueAt(casesTable.convertRowIndexToModel(casesTable.getSelectedRow()), 0).toString(); } if (caseName.isEmpty()) { @@ -566,7 +596,7 @@ public final class OtherOccurrencesPanel extends javax.swing.JPanel { */ private String getCaseCreatedDate(int caseTableRowIdx) { try { - if (CentralRepository.isEnabled()) { + if (CentralRepository.isEnabled() && casesTableModel.getRowCount() > 0) { CorrelationCase partialCase; partialCase = casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(caseTableRowIdx)); if (partialCase == null) { @@ -594,11 +624,11 @@ public final class OtherOccurrencesPanel extends javax.swing.JPanel { /** * Construct a new SelectionWorker. - * + * * @param coAtInstances * @param abstractFile * @param deviceIdStr - * @param dataSourceNameStr + * @param dataSourceNameStr */ SelectionWorker(Collection coAtInstances, AbstractFile abstractFile, String deviceIdStr, String dataSourceNameStr) { this.coAtInstances = coAtInstances; @@ -612,12 +642,12 @@ public final class OtherOccurrencesPanel extends javax.swing.JPanel { Map correlatedNodeDataMap = new HashMap<>(); for (CorrelationAttributeInstance corAttr : coAtInstances) { correlatedNodeDataMap.putAll(OtherOccurrences.getCorrelatedInstances(abstractFile, deviceIdStr, dataSourceNameStr, corAttr)); - - if(isCancelled()) { + + if (isCancelled()) { return new HashMap<>(); } } - + return correlatedNodeDataMap; } } @@ -685,7 +715,6 @@ public final class OtherOccurrencesPanel extends javax.swing.JPanel { exportToCSVMenuItem = new javax.swing.JMenuItem(); showCaseDetailsMenuItem = new javax.swing.JMenuItem(); showCommonalityMenuItem = new javax.swing.JMenuItem(); - CSVFileChooser = new javax.swing.JFileChooser(); tableContainerPanel = new javax.swing.JPanel(); tablesViewerSplitPane = new javax.swing.JSplitPane(); caseDatasourceFileSplitPane = new javax.swing.JSplitPane(); @@ -704,12 +733,12 @@ public final class OtherOccurrencesPanel extends javax.swing.JPanel { filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(32767, 0)); rightClickPopupMenu.addPopupMenuListener(new javax.swing.event.PopupMenuListener() { - public void popupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent evt) { - rightClickPopupMenuPopupMenuWillBecomeVisible(evt); + public void popupMenuCanceled(javax.swing.event.PopupMenuEvent evt) { } public void popupMenuWillBecomeInvisible(javax.swing.event.PopupMenuEvent evt) { } - public void popupMenuCanceled(javax.swing.event.PopupMenuEvent evt) { + public void popupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent evt) { + rightClickPopupMenuPopupMenuWillBecomeVisible(evt); } }); @@ -857,7 +886,6 @@ public final class OtherOccurrencesPanel extends javax.swing.JPanel { // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JFileChooser CSVFileChooser; private javax.swing.JSplitPane caseDatasourceFileSplitPane; private javax.swing.JSplitPane caseDatasourceSplitPane; private javax.swing.JScrollPane caseScrollPane; diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/Bundle.properties-MERGED index f43b438b2c..a80f1f7d86 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/Bundle.properties-MERGED @@ -25,7 +25,9 @@ CorrelationType.ICCID.displayName=ICCID Number CorrelationType.IMEI.displayName=IMEI Number CorrelationType.IMSI.displayName=IMSI Number CorrelationType.MAC.displayName=MAC Addresses +CorrelationType.OS_ACCOUNT.displayName=Os Account CorrelationType.PHONE.displayName=Phone Numbers +CorrelationType.PROG_NAME.displayName=Installed Programs CorrelationType.SSID.displayName=Wireless Networks CorrelationType.USBID.displayName=USB Devices EamArtifactInstances.knownStatus.bad=Bad diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/Bundle_ja.properties index f52884e26c..d3e93e4c2b 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/Bundle_ja.properties @@ -1,11 +1,51 @@ -#Fri Feb 12 16:56:28 UTC 2021 +#Mon Jul 12 13:21:59 UTC 2021 +AbstractSqlEamDb.badMajorSchema.message=\u30b9\u30ad\u30fc\u30de\u30d0\u30fc\u30b8\u30e7\u30f3\u306e\u5024\u304c\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093\uff08{0}\uff09-\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304c\u7834\u640d\u3057\u3066\u3044\u307e\u3059\u3002 +AbstractSqlEamDb.badMinorSchema.message=\u30b9\u30ad\u30fc\u30de\u30de\u30a4\u30ca\u30fc\u30d0\u30fc\u30b8\u30e7\u30f3\uff08{0}\uff09\u306e\u5024\u304c\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093-\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304c\u7834\u640d\u3057\u3066\u3044\u307e\u3059\u3002 +AbstractSqlEamDb.cannotUpgrage.message=\u73fe\u5728\u9078\u629e\u3055\u308c\u3066\u3044\u308b\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30d7\u30e9\u30c3\u30c8\u30d5\u30a9\u30fc\u30e0 "{0}"\u306f\u30a2\u30c3\u30d7\u30b0\u30ec\u30fc\u30c9\u3067\u304d\u307e\u305b\u3093\u3002 +AbstractSqlEamDb.failedToReadMajorVersion.message=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u306e\u30b9\u30ad\u30fc\u30de\u30d0\u30fc\u30b8\u30e7\u30f3\u306e\u8aad\u53d6\u308a\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 +AbstractSqlEamDb.failedToReadMinorVersion.message=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u306e\u30b9\u30ad\u30fc\u30de\u30de\u30a4\u30ca\u30fc\u30d0\u30fc\u30b8\u30e7\u30f3\u306e\u8aad\u53d6\u308a\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 +AbstractSqlEamDb.upgradeSchema.incompatible=\u9078\u629e\u3057\u305f\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u306f\u3001\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u30d0\u30fc\u30b8\u30e7\u30f3\u3068\u4e92\u63db\u6027\u304c\u3042\u308a\u307e\u305b\u3093\u3002\u3053\u306e\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u3092\u4f7f\u7528\u3059\u308b\u306b\u306f\u3001\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3092\u30a2\u30c3\u30d7\u30b0\u30ec\u30fc\u30c9\u3057\u3066\u304f\u3060\u3055\u3044\u3002 CentralRepoDbChoice.Disabled.Text=\u7121\u52b9 CentralRepoDbChoice.PostgreSQL.Text=\u30ab\u30b9\u30bf\u30e0PostgreSQL CentralRepoDbChoice.PostgreSQL_Multiuser.Text=\u30de\u30eb\u30c1\u30e6\u30fc\u30b6\u30fc\u8a2d\u5b9a\u4f7f\u7528PostgreSQL CentralRepoDbChoice.Sqlite.Text=SQLite CentralRepoDbManager.connectionErrorMsg.text=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u30fc\u30fb\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3078\u306e\u63a5\u7d9a\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 -CentralRepositoryService.progressMsg.updatingSchema=\u30b9\u30ad\u30fc\u30de\u3092\u66f4\u65b0\u3057\u3066\u3044\u307e\u3059\u2026 +CentralRepositoryService.progressMsg.updatingSchema=\u30b9\u30ad\u30fc\u30de\u306e\u66f4\u65b0\u3092\u78ba\u8a8d\u3057\u3066\u3044\u307e\u3059... CentralRepositoryService.progressMsg.waitingForListeners=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u3078\u30c7\u30fc\u30bf\u306e\u8ffd\u52a0\u3092\u7d42\u4e86\u4e2d...\u3002 CentralRepositoryService.serviceName=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u30fc\u30fb\u30b5\u30fc\u30d3\u30b9 +CorrelationAttributeInstance.invalidName.message=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30c6\u30fc\u30d6\u30eb\u540d\u304c\u7121\u52b9\u3067\u3059\u3002 \u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30c6\u30fc\u30d6\u30eb\u540d\u306b\u306f\u5c0f\u6587\u5b57\u30a2\u30eb\u30d5\u30a1\u30d9\u30c3\u30c8\u3001\u6570\u5b57\u3001\u304a\u3088\u3073\u300c_\u300d\u306e\u307f\u304c\u4f7f\u7528\u3067\u304d\u307e\u3059\u3002 +CorrelationAttributeInstance.nullName.message=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u540d\u304cnull\u3067\u3059\u3002 CorrelationAttributeUtil.emailaddresses.text=\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9 +CorrelationType.DOMAIN.displayName=\u30c9\u30e1\u30a4\u30f3 +CorrelationType.EMAIL.displayName=\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9 +CorrelationType.FILES.displayName=\u30d5\u30a1\u30a4\u30eb +CorrelationType.ICCID.displayName=ICCID\u756a\u53f7 +CorrelationType.IMEI.displayName=IMEI\u756a\u53f7 +CorrelationType.IMSI.displayName=IMSI\u756a\u53f7 +CorrelationType.MAC.displayName=MAC\u30a2\u30c9\u30ec\u30b9 +CorrelationType.PHONE.displayName=\u96fb\u8a71\u756a\u53f7 +CorrelationType.SSID.displayName=\u30ef\u30a4\u30e4\u30ec\u30b9\u30cd\u30c3\u30c8\u30ef\u30fc\u30af +CorrelationType.USBID.displayName=USB\u30c7\u30d0\u30a4\u30b9 +EamArtifactInstances.knownStatus.bad=\u4e0d\u53ef +EamArtifactInstances.knownStatus.known=\u65e2\u77e5 +EamArtifactInstances.knownStatus.unknown=\u4e0d\u660e +EamCase.title.caseDisplayName=\u30b1\u30fc\u30b9\u540d\uff1a +EamCase.title.caseNumber=\u30b1\u30fc\u30b9\u756a\u53f7\uff1a +EamCase.title.caseUUID=\u30b1\u30fc\u30b9UUID\uff1a +EamCase.title.creationDate=\u4f5c\u6210\u65e5\uff1a +EamCase.title.examinerEmail=\u5be9\u67fb\u5b98\u306e\u96fb\u5b50\u30e1\u30fc\u30eb\uff1a +EamCase.title.examinerName=\u5be9\u67fb\u5b98\u540d\uff1a +EamCase.title.examinerPhone=\u5be9\u67fb\u5b98\u306e\u96fb\u8a71\u756a\u53f7\uff1a +EamCase.title.notes=\u30ce\u30fc\u30c8\uff1a +EamCase.title.org=\u7d44\u7e54\uff1a +EamDbUtil.centralRepoConnectionFailed.message=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u306b\u63a5\u7d9a\u3067\u304d\u307e\u305b\u3093\u3002 +EamDbUtil.centralRepoDisabled.message=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u304c\u7121\u52b9\u306b\u306a\u3063\u3066\u3044\u307e\u3059\u3002 +EamDbUtil.centralRepoUpgradeFailed.message=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u306e\u30a2\u30c3\u30d7\u30b0\u30ec\u30fc\u30c9\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 +EamDbUtil.exclusiveLockAquisitionFailure.message=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u306e\u6392\u4ed6\u30ed\u30c3\u30af\u304c\u3067\u304d\u307e\u305b\u3093\u3002 Persona.defaultName=\u7121\u540d +PostgresEamDb.centralRepoDisabled.message=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u6709\u52b9\u306b\u306a\u3063\u3066\u3044\u307e\u305b\u3093\u3002 +PostgresEamDb.connectionFailed.message=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3078\u306e\u63a5\u7d9a\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +PostgresEamDb.multiUserLockError.message=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30ed\u30c3\u30af\u306e\u53d6\u5f97\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +SqliteEamDb.centralRepositoryDisabled.message=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u6709\u52b9\u306b\u306a\u3063\u3066\u3044\u307e\u305b\u3093\u3002 +SqliteEamDb.connectionFailedMessage.message=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3078\u306e\u63a5\u7d9a\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +SqliteEamDb.databaseMissing.message=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304c\u3042\u308a\u307e\u305b\u3093 diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbUpgrader15To16.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbUpgrader15To16.java new file mode 100644 index 0000000000..e19cfd8155 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbUpgrader15To16.java @@ -0,0 +1,63 @@ +/* + * Central Repository + * + * Copyright 2021 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.centralrepository.datamodel; + +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; +import org.sleuthkit.datamodel.CaseDbSchemaVersionNumber; + +/** + * This class updates CR schema to 1.6 + * + */ +public class CentralRepoDbUpgrader15To16 implements CentralRepoDbUpgrader { + + @Override + public void upgradeSchema(CaseDbSchemaVersionNumber dbSchemaVersion, Connection connection) throws CentralRepoException, SQLException { + + if (dbSchemaVersion.compareTo(new CaseDbSchemaVersionNumber(1, 6)) < 0) { + + try (Statement statement = connection.createStatement();) { + + CentralRepoPlatforms selectedPlatform = CentralRepoDbManager.getSavedDbChoice().getDbPlatform(); + + for (CorrelationAttributeInstance.Type type : CorrelationAttributeInstance.getDefaultCorrelationTypes()) { + String instance_type_dbname = CentralRepoDbUtil.correlationTypeToInstanceTableName(type); + + if ((type.getId() == CorrelationAttributeInstance.INSTALLED_PROGS_TYPE_ID) || + (type.getId() == CorrelationAttributeInstance.OSACCOUNT_TYPE_ID)){ + + // these are new Correlation types - new tables need to be created + statement.execute(String.format(RdbmsCentralRepoFactory.getCreateAccountInstancesTableTemplate(selectedPlatform), instance_type_dbname, instance_type_dbname)); + statement.execute(String.format(RdbmsCentralRepoFactory.getAddCaseIdIndexTemplate(), instance_type_dbname, instance_type_dbname)); + statement.execute(String.format(RdbmsCentralRepoFactory.getAddDataSourceIdIndexTemplate(), instance_type_dbname, instance_type_dbname)); + statement.execute(String.format(RdbmsCentralRepoFactory.getAddValueIndexTemplate(), instance_type_dbname, instance_type_dbname)); + statement.execute(String.format(RdbmsCentralRepoFactory.getAddKnownStatusIndexTemplate(), instance_type_dbname, instance_type_dbname)); + statement.execute(String.format(RdbmsCentralRepoFactory.getAddObjectIdIndexTemplate(), instance_type_dbname, instance_type_dbname)); + + // add new correlation type + CentralRepoDbUtil.insertCorrelationType(connection, type); + + } + } + } + } + } +} diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeInstance.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeInstance.java index 32121989e0..64d41dcf25 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeInstance.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeInstance.java @@ -257,6 +257,8 @@ public class CorrelationAttributeInstance implements Serializable { public static final int IMEI_TYPE_ID = 7; public static final int IMSI_TYPE_ID = 8; public static final int ICCID_TYPE_ID = 9; + public static final int INSTALLED_PROGS_TYPE_ID = 10; + public static final int OSACCOUNT_TYPE_ID = 11; // An offset to assign Ids for additional correlation types. public static final int ADDITIONAL_TYPES_BASE_ID = 1000; @@ -276,7 +278,9 @@ public class CorrelationAttributeInstance implements Serializable { "CorrelationType.MAC.displayName=MAC Addresses", "CorrelationType.IMEI.displayName=IMEI Number", "CorrelationType.IMSI.displayName=IMSI Number", - "CorrelationType.ICCID.displayName=ICCID Number"}) + "CorrelationType.PROG_NAME.displayName=Installed Programs", + "CorrelationType.ICCID.displayName=ICCID Number", + "CorrelationType.OS_ACCOUNT.displayName=Os Account"}) public static List getDefaultCorrelationTypes() throws CentralRepoException { List defaultCorrelationTypes = new ArrayList<>(); @@ -290,6 +294,8 @@ public class CorrelationAttributeInstance implements Serializable { defaultCorrelationTypes.add(new CorrelationAttributeInstance.Type(IMEI_TYPE_ID, Bundle.CorrelationType_IMEI_displayName(), "imei_number", true, true)); //NON-NLS defaultCorrelationTypes.add(new CorrelationAttributeInstance.Type(IMSI_TYPE_ID, Bundle.CorrelationType_IMSI_displayName(), "imsi_number", true, true)); //NON-NLS defaultCorrelationTypes.add(new CorrelationAttributeInstance.Type(ICCID_TYPE_ID, Bundle.CorrelationType_ICCID_displayName(), "iccid_number", true, true)); //NON-NLS + defaultCorrelationTypes.add(new CorrelationAttributeInstance.Type(INSTALLED_PROGS_TYPE_ID, Bundle.CorrelationType_PROG_NAME_displayName(), "installed_programs", true, true)); //NON-NLS + defaultCorrelationTypes.add(new CorrelationAttributeInstance.Type(OSACCOUNT_TYPE_ID, Bundle.CorrelationType_OS_ACCOUNT_displayName(), "os_accounts", true, true)); //NON-NLS // Create Correlation Types for Accounts. int correlationTypeId = ADDITIONAL_TYPES_BASE_ID; diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeUtil.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeUtil.java index 2d0315ef7b..f9b3c8642d 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeUtil.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeUtil.java @@ -36,6 +36,8 @@ import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE; +import org.sleuthkit.datamodel.Content; +import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.HashUtility; import org.sleuthkit.datamodel.InvalidAccountIDException; import org.sleuthkit.datamodel.TskCoreException; @@ -93,6 +95,7 @@ public class CorrelationAttributeUtil { add(ARTIFACT_TYPE.TSK_SIM_ATTACHED.getTypeID()); add(ARTIFACT_TYPE.TSK_WEB_FORM_ADDRESS.getTypeID()); add(ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID()); + add(ARTIFACT_TYPE.TSK_INSTALLED_PROG.getTypeID()); } }; @@ -189,6 +192,17 @@ public class CorrelationAttributeUtil { } else if (artifactTypeID == ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID()) { makeCorrAttrFromAcctArtifact(correlationAttrs, sourceArtifact); + } else if (artifactTypeID == ARTIFACT_TYPE.TSK_INSTALLED_PROG.getTypeID()) { + BlackboardAttribute setNameAttr = sourceArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH)); + String pathAttrString = null; + if (setNameAttr != null) { + pathAttrString = setNameAttr.getValueString(); + } + if (pathAttrString != null && !pathAttrString.isEmpty()) { + makeCorrAttrFromArtifactAttr(correlationAttrs, sourceArtifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH, CorrelationAttributeInstance.INSTALLED_PROGS_TYPE_ID); + } else { + makeCorrAttrFromArtifactAttr(correlationAttrs, sourceArtifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME, CorrelationAttributeInstance.INSTALLED_PROGS_TYPE_ID); + } } else if (artifactTypeID == ARTIFACT_TYPE.TSK_CONTACT.getTypeID() || artifactTypeID == ARTIFACT_TYPE.TSK_CALLLOG.getTypeID() || artifactTypeID == ARTIFACT_TYPE.TSK_MESSAGE.getTypeID()) { @@ -213,7 +227,7 @@ public class CorrelationAttributeUtil { } return correlationAttrs; } - + /** * Makes a correlation attribute instance from a phone number attribute of * an artifact. @@ -381,23 +395,49 @@ public class CorrelationAttributeUtil { private static CorrelationAttributeInstance makeCorrAttr(BlackboardArtifact artifact, CorrelationAttributeInstance.Type correlationType, String value) { try { Case currentCase = Case.getCurrentCaseThrows(); - AbstractFile bbSourceFile = currentCase.getSleuthkitCase().getAbstractFileById(artifact.getObjectID()); - if (null == bbSourceFile) { - logger.log(Level.SEVERE, "Error creating artifact instance. Abstract File was null."); // NON-NLS + Content sourceContent = currentCase.getSleuthkitCase().getContentById(artifact.getObjectID()); + if (null == sourceContent) { + logger.log(Level.SEVERE, "Error creating artifact instance of type {0}. Failed to load content with ID: {1} associated with artifact with ID: {2}", + new Object[]{correlationType.getDisplayName(), artifact.getObjectID(), artifact.getId()}); // NON-NLS + return null; + } + + Content ds = sourceContent.getDataSource(); + if (ds == null) { + logger.log(Level.SEVERE, "Error creating artifact instance of type {0}. Failed to load data source for content with ID: {1}", + new Object[]{correlationType.getDisplayName(), artifact.getObjectID()}); // NON-NLS return null; } CorrelationCase correlationCase = CentralRepository.getInstance().getCase(Case.getCurrentCaseThrows()); - return new CorrelationAttributeInstance( + if (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_INSTALLED_PROG.getTypeID()) { + return new CorrelationAttributeInstance( + correlationType, + value, + correlationCase, + CorrelationDataSource.fromTSKDataSource(correlationCase, ds), + "", + "", + TskData.FileKnown.UNKNOWN, + sourceContent.getId()); + } else { + if (! (sourceContent instanceof AbstractFile)) { + logger.log(Level.SEVERE, "Error creating artifact instance of type {0}. Source content of artifact with ID: {1} is not an AbstractFile", + new Object[]{correlationType.getDisplayName(), artifact.getId()}); + return null; + } + AbstractFile bbSourceFile = (AbstractFile) sourceContent; + + return new CorrelationAttributeInstance( correlationType, value, correlationCase, - CorrelationDataSource.fromTSKDataSource(correlationCase, bbSourceFile.getDataSource()), + CorrelationDataSource.fromTSKDataSource(correlationCase, ds), bbSourceFile.getParentPath() + bbSourceFile.getName(), "", TskData.FileKnown.UNKNOWN, bbSourceFile.getId()); - + } } catch (TskCoreException ex) { logger.log(Level.SEVERE, String.format("Error getting querying case database (%s)", artifact), ex); // NON-NLS return null; diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepo.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepo.java index 1b4ce08c18..2e2dafbefd 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepo.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepo.java @@ -69,7 +69,7 @@ abstract class RdbmsCentralRepo implements CentralRepository { static final String SCHEMA_MINOR_VERSION_KEY = "SCHEMA_MINOR_VERSION"; static final String CREATION_SCHEMA_MAJOR_VERSION_KEY = "CREATION_SCHEMA_MAJOR_VERSION"; static final String CREATION_SCHEMA_MINOR_VERSION_KEY = "CREATION_SCHEMA_MINOR_VERSION"; - static final CaseDbSchemaVersionNumber SOFTWARE_CR_DB_SCHEMA_VERSION = new CaseDbSchemaVersionNumber(1, 5); + static final CaseDbSchemaVersionNumber SOFTWARE_CR_DB_SCHEMA_VERSION = new CaseDbSchemaVersionNumber(1, 6); protected final List defaultCorrelationTypes; @@ -3976,6 +3976,9 @@ abstract class RdbmsCentralRepo implements CentralRepository { // Upgrade to 1.5 (new CentralRepoDbUpgrader14To15()).upgradeSchema(dbSchemaVersion, conn); + // Upgrade to 1.6 + (new CentralRepoDbUpgrader15To16()).upgradeSchema(dbSchemaVersion, conn); + updateSchemaVersion(conn); conn.commit(); logger.log(Level.INFO, String.format("Central Repository schema updated to version %s", SOFTWARE_CR_DB_SCHEMA_VERSION)); diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Bundle.properties-MERGED index e95a759c4f..d71782c0ee 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Bundle.properties-MERGED @@ -1,4 +1,7 @@ caseeventlistener.evidencetag=Evidence +CaseEventsListener.module.name=Central Repository +CaseEventsListener.prevCaseComment.text=Users seen in previous cases +CaseEventsListener.prevExists.text=Previously Seen Users (Central Repository) CentralRepositoryNotificationDialog.bulletHeader=This data is used to: CentralRepositoryNotificationDialog.bulletOne=Ignore common items (files, domains, and accounts) CentralRepositoryNotificationDialog.bulletThree=Create personas that group accounts diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Bundle_ja.properties index e58016c3e8..da9b1e0403 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Bundle_ja.properties @@ -1,4 +1,4 @@ -#Fri Feb 12 16:56:28 UTC 2021 +#Mon Jul 12 13:21:59 UTC 2021 CentralRepositoryNotificationDialog.bulletHeader=\u3053\u306e\u30c7\u30fc\u30bf\u306e\u4f7f\u7528\u76ee\u7684\u306f\uff1a CentralRepositoryNotificationDialog.bulletOne=\u4e00\u822c\u7684\u306a\u30a2\u30a4\u30c6\u30e0\uff08\u30d5\u30a1\u30a4\u30eb\u3001\u30c9\u30e1\u30a4\u30f3\u3001\u30a2\u30ab\u30a6\u30f3\u30c8\uff09\u3092\u7121\u8996\u3059\u308b CentralRepositoryNotificationDialog.bulletThree=\u30a2\u30ab\u30a6\u30f3\u30c8\u3092\u30b0\u30eb\u30fc\u30d7\u5316\u3059\u308b\u30da\u30eb\u30bd\u30ca\u3092\u4f5c\u6210\u3059\u308b @@ -6,3 +6,9 @@ CentralRepositoryNotificationDialog.bulletTwo=\u30a2\u30a4\u30c6\u30e0\u304c\u4e CentralRepositoryNotificationDialog.finalRemarks=\u4fdd\u5b58\u3059\u308b\u5185\u5bb9\u3092\u5236\u9650\u3059\u308b\u306b\u306f\u3001\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u30fb\u30aa\u30d7\u30b7\u30e7\u30f3\u30d1\u30cd\u30eb\u3092\u4f7f\u7528\u3057\u3066\u4e0b\u3055\u3044\u3002 CentralRepositoryNotificationDialog.header=Autopsy\u306f\u3001\u5404\u30b1\u30fc\u30b9\u306b\u95a2\u3059\u308b\u30c7\u30fc\u30bf\u3092\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u306b\u4fdd\u5b58\u3057\u307e\u3059\u3002 IngestEventsListener.ingestmodule.name=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea +IngestEventsListener.prevCaseComment.text=\u524d\u306e\u30b1\u30fc\u30b9\uff1a +IngestEventsListener.prevCount.text=\u524d\u306e{0}\u306e\u6570\uff1a{1} +IngestEventsListener.prevExists.text=\u4ee5\u524d\u898b\u305f\u30c7\u30d0\u30a4\u30b9\uff08\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\uff09 +IngestEventsListener.prevTaggedSet.text=\u4ee5\u524d\u306b\u6ce8\u76ee\u3059\u3079\u304d\u3068\u3057\u3066\u30bf\u30b0\u4ed8\u3051\u3055\u308c\u305f\uff08\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\uff09 +Installer.centralRepoUpgradeFailed.title=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u304c\u7121\u52b9\u306b\u306a\u3063\u3066\u3044\u307e\u3059\u3002 +caseeventlistener.evidencetag=\u8a3c\u62e0 diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java index 806d18c63f..a3ccca4ccf 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java @@ -1,7 +1,7 @@ /* * Central Repository * - * Copyright 2017-2020 Basis Technology Corp. + * Copyright 2017-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,13 +21,17 @@ package org.sleuthkit.autopsy.centralrepository.eventlisteners; import com.google.common.util.concurrent.ThreadFactoryBuilder; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; +import java.util.Arrays; +import java.util.Collection; import java.util.EnumSet; import java.util.List; +import java.util.Optional; import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.logging.Level; import org.apache.commons.lang.StringUtils; +import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; @@ -37,6 +41,7 @@ import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent; import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent; import org.sleuthkit.autopsy.casemodule.events.DataSourceAddedEvent; import org.sleuthkit.autopsy.casemodule.events.DataSourceNameChangedEvent; +import org.sleuthkit.autopsy.casemodule.events.OsAcctInstancesAddedEvent; import org.sleuthkit.autopsy.casemodule.services.TagsManager; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance; @@ -54,8 +59,18 @@ import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; +import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeNormalizationException; import org.sleuthkit.datamodel.Tag; import org.sleuthkit.autopsy.events.AutopsyEvent; +import org.sleuthkit.autopsy.ingest.IngestManager; +import org.sleuthkit.datamodel.Blackboard; +import org.sleuthkit.datamodel.BlackboardAttribute; +import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT; +import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME; +import org.sleuthkit.datamodel.OsAccount; +import org.sleuthkit.datamodel.OsAccountInstance; +import org.sleuthkit.datamodel.Score; +import org.sleuthkit.datamodel.SleuthkitCase; /** * Listen for case events and update entries in the Central Repository database @@ -75,7 +90,8 @@ public final class CaseEventListener implements PropertyChangeListener { Case.Events.DATA_SOURCE_ADDED, Case.Events.TAG_DEFINITION_CHANGED, Case.Events.CURRENT_CASE, - Case.Events.DATA_SOURCE_NAME_CHANGED); + Case.Events.DATA_SOURCE_NAME_CHANGED, + Case.Events.OS_ACCT_INSTANCES_ADDED); public CaseEventListener() { jobProcessingExecutor = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat(CASE_EVENT_THREAD_NAME).build()); @@ -130,6 +146,12 @@ public final class CaseEventListener implements PropertyChangeListener { jobProcessingExecutor.submit(new DataSourceNameChangedTask(dbManager, evt)); } break; + case OS_ACCT_INSTANCES_ADDED: { + if (((AutopsyEvent) evt).getSourceType() == AutopsyEvent.SourceType.LOCAL) { + jobProcessingExecutor.submit(new OsAccountInstancesAddedTask(dbManager, evt)); + } + } + break; } } @@ -289,10 +311,10 @@ public final class CaseEventListener implements PropertyChangeListener { * Sets the known status for the correlation attribute instance for the * given abstract file. * - * @param af The abstract file for which to set the correlation - * attribute instance. + * @param af The abstract file for which to set the correlation + * attribute instance. * @param knownStatus The new known status for the correlation attribute - * instance. + * instance. */ private void setContentKnownStatus(AbstractFile af, TskData.FileKnown knownStatus) { final CorrelationAttributeInstance eamArtifact = CorrelationAttributeUtil.makeCorrAttrFromFile(af); @@ -385,7 +407,7 @@ public final class CaseEventListener implements PropertyChangeListener { * for the item. If there are, set known status as notable. If not set * status as unknown. * - * @param content The content for the tag that was added or deleted. + * @param content The content for the tag that was added or deleted. * @param bbArtifact The artifact for the tag that was added or deleted. */ private void handleTagChange(Content content, BlackboardArtifact bbArtifact) { @@ -430,7 +452,7 @@ public final class CaseEventListener implements PropertyChangeListener { * Sets the known status of a blackboard artifact in the central * repository. * - * @param bbArtifact The blackboard artifact to set known status. + * @param bbArtifact The blackboard artifact to set known status. * @param knownStatus The new known status. */ private void setArtifactKnownStatus(BlackboardArtifact bbArtifact, TskData.FileKnown knownStatus) { @@ -635,6 +657,104 @@ public final class CaseEventListener implements PropertyChangeListener { } // CURRENT_CASE } + @NbBundle.Messages({"CaseEventsListener.module.name=Central Repository", + "CaseEventsListener.prevCaseComment.text=Users seen in previous cases", + "CaseEventsListener.prevExists.text=Previously Seen Users (Central Repository)"}) + /** + * Add OsAccount Instance to CR and find interesting items based on the OsAccount + */ + private final class OsAccountInstancesAddedTask implements Runnable { + + private final CentralRepository dbManager; + private final PropertyChangeEvent event; + private final String MODULE_NAME = Bundle.CaseEventsListener_module_name(); + + private OsAccountInstancesAddedTask(CentralRepository db, PropertyChangeEvent evt) { + dbManager = db; + event = evt; + } + + @Override + public void run() { + //Nothing to do here if the central repo is not enabled or if ingest is running but is set to not save data/make artifacts + if (!CentralRepository.isEnabled() + || (IngestManager.getInstance().isIngestRunning() && !(IngestEventsListener.isFlagSeenDevices() || IngestEventsListener.shouldCreateCrProperties()))) { + return; + } + + final OsAcctInstancesAddedEvent osAcctInstancesAddedEvent = (OsAcctInstancesAddedEvent) event; + List addedOsAccountNew = osAcctInstancesAddedEvent.getOsAccountInstances(); + for (OsAccountInstance osAccountInstance : addedOsAccountNew) { + try { + OsAccount osAccount = osAccountInstance.getOsAccount(); + Optional accountAddr = osAccount.getAddr(); + // Check address if it is null or one of the ones below we want to ignore it since they will always be one a windows system + // and they are not unique + if (!accountAddr.isPresent() || accountAddr.get().equals("S-1-5-18") || accountAddr.get().equals("S-1-5-19") || accountAddr.get().equals("S-1-5-20")) { + return; + } + try { + + CorrelationCase correlationCase = CentralRepository.getInstance().getCase(Case.getCurrentCaseThrows()); + CorrelationAttributeInstance correlationAttributeInstance = new CorrelationAttributeInstance( + CentralRepository.getInstance().getCorrelationTypeById(CorrelationAttributeInstance.OSACCOUNT_TYPE_ID), + accountAddr.get(), + correlationCase, + CorrelationDataSource.fromTSKDataSource(correlationCase, osAccountInstance.getDataSource()), + "", + "", + TskData.FileKnown.KNOWN, + osAccount.getId()); + + // Save to the database if requested + if(IngestEventsListener.shouldCreateCrProperties()) { + dbManager.addArtifactInstance(correlationAttributeInstance); + } + + // Look up and create artifacts for previously seen accounts if requested + if (IngestEventsListener.isFlagSeenDevices()) { + List previousOccurences = dbManager.getArtifactInstancesByTypeValue(CentralRepository.getInstance().getCorrelationTypeById(CorrelationAttributeInstance.OSACCOUNT_TYPE_ID), correlationAttributeInstance.getCorrelationValue()); + for (CorrelationAttributeInstance instance : previousOccurences) { + if (!instance.getCorrelationCase().getCaseUUID().equals(correlationAttributeInstance.getCorrelationCase().getCaseUUID())) { + SleuthkitCase tskCase = osAccount.getSleuthkitCase(); + Blackboard blackboard = tskCase.getBlackboard(); + + Collection attributesForNewArtifact = Arrays.asList( + new BlackboardAttribute( + TSK_SET_NAME, MODULE_NAME, + Bundle.CaseEventsListener_prevExists_text()), + new BlackboardAttribute( + TSK_COMMENT, MODULE_NAME, + Bundle.CaseEventsListener_prevCaseComment_text())); + BlackboardArtifact newAnalysisResult = osAccount.newAnalysisResult( + BlackboardArtifact.Type.TSK_INTERESTING_ARTIFACT_HIT, Score.SCORE_LIKELY_NOTABLE, + null, Bundle.CaseEventsListener_prevExists_text(), null, attributesForNewArtifact, osAccountInstance.getDataSource().getId()).getAnalysisResult(); + try { + // index the artifact for keyword search + blackboard.postArtifact(newAnalysisResult, MODULE_NAME); + break; + } catch (Blackboard.BlackboardException ex) { + LOGGER.log(Level.SEVERE, "Unable to index blackboard artifact " + newAnalysisResult.getArtifactID(), ex); //NON-NLS + } + } + } + } + + } catch (CentralRepoException ex) { + LOGGER.log(Level.SEVERE, String.format("Cannot get central repository for OsAccount: %s.", accountAddr.get()), ex); //NON-NLS + } catch (NoCurrentCaseException ex) { + LOGGER.log(Level.SEVERE, "Exception while getting open case.", ex); //NON-NLS + } catch (CorrelationAttributeNormalizationException ex) { + LOGGER.log(Level.SEVERE, "Exception with Correlation Attribute Normalization.", ex); //NON-NLS + } + + } catch (TskCoreException ex) { + LOGGER.log(Level.SEVERE, "Cannot get central repository for OsAccount: " + "OsAccount", ex); + } + } + } + } + private final class DataSourceNameChangedTask implements Runnable { private final CentralRepository dbManager; diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java index 1de62fedd1..7aa229949e 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java @@ -37,7 +37,6 @@ import org.apache.commons.lang3.StringUtils; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; -import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoAccount; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeNormalizationException; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeUtil; @@ -63,11 +62,6 @@ import org.sleuthkit.datamodel.Image; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; -import org.sleuthkit.autopsy.centralrepository.datamodel.Persona; -import org.sleuthkit.autopsy.centralrepository.datamodel.PersonaAccount; -import org.sleuthkit.datamodel.Account; -import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT; -import org.sleuthkit.datamodel.CommunicationsUtils; import org.sleuthkit.datamodel.Score; /** @@ -76,7 +70,6 @@ import org.sleuthkit.datamodel.Score; */ @NbBundle.Messages({"IngestEventsListener.ingestmodule.name=Central Repository"}) public class IngestEventsListener { - private static final Logger LOGGER = Logger.getLogger(CorrelationAttributeInstance.class.getName()); private static final Set INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.DATA_SOURCE_ANALYSIS_COMPLETED); private static final Set INGEST_MODULE_EVENTS_OF_INTEREST = EnumSet.of(DATA_ADDED); @@ -216,17 +209,17 @@ public class IngestEventsListener { @NbBundle.Messages({"IngestEventsListener.prevTaggedSet.text=Previously Tagged As Notable (Central Repository)", "IngestEventsListener.prevCaseComment.text=Previous Case: "}) static private void makeAndPostPreviousNotableArtifact(BlackboardArtifact originalArtifact, List caseDisplayNames) { - - Collection attributesForNewArtifact = Arrays.asList(new BlackboardAttribute( - TSK_SET_NAME, MODULE_NAME, - Bundle.IngestEventsListener_prevTaggedSet_text()), + Collection attributesForNewArtifact = Arrays.asList( + new BlackboardAttribute( + TSK_SET_NAME, MODULE_NAME, + Bundle.IngestEventsListener_prevTaggedSet_text()), new BlackboardAttribute( TSK_COMMENT, MODULE_NAME, Bundle.IngestEventsListener_prevCaseComment_text() + caseDisplayNames.stream().distinct().collect(Collectors.joining(","))), new BlackboardAttribute( TSK_ASSOCIATED_ARTIFACT, MODULE_NAME, originalArtifact.getArtifactID())); - makeAndPostInterestingArtifact(originalArtifact, attributesForNewArtifact); + makeAndPostInterestingArtifact(originalArtifact, attributesForNewArtifact, Bundle.IngestEventsListener_prevTaggedSet_text()); } /** @@ -251,26 +244,28 @@ public class IngestEventsListener { new BlackboardAttribute( TSK_ASSOCIATED_ARTIFACT, MODULE_NAME, originalArtifact.getArtifactID())); - makeAndPostInterestingArtifact(originalArtifact, attributesForNewArtifact); + makeAndPostInterestingArtifact(originalArtifact, attributesForNewArtifact, Bundle.IngestEventsListener_prevExists_text()); } - + + /** * Make an interesting item artifact to flag the passed in artifact. * * @param originalArtifact Artifact in current case we want to flag * @param attributesForNewArtifact Attributes to assign to the new * Interesting items artifact + * @param configuration The configuration to be specified for the new interesting artifact hit */ - private static void makeAndPostInterestingArtifact(BlackboardArtifact originalArtifact, Collection attributesForNewArtifact) { + private static void makeAndPostInterestingArtifact(BlackboardArtifact originalArtifact, Collection attributesForNewArtifact, String configuration) { try { SleuthkitCase tskCase = originalArtifact.getSleuthkitCase(); AbstractFile abstractFile = tskCase.getAbstractFileById(originalArtifact.getObjectID()); Blackboard blackboard = tskCase.getBlackboard(); // Create artifact if it doesn't already exist. if (!blackboard.artifactExists(abstractFile, TSK_INTERESTING_ARTIFACT_HIT, attributesForNewArtifact)) { - BlackboardArtifact newInterestingArtifact = abstractFile.newAnalysisResult( - new BlackboardArtifact.Type(TSK_INTERESTING_ARTIFACT_HIT), - Score.SCORE_UNKNOWN, null, null, null, attributesForNewArtifact) + BlackboardArtifact newInterestingArtifact = abstractFile.newAnalysisResult( + BlackboardArtifact.Type.TSK_INTERESTING_ARTIFACT_HIT, Score.SCORE_LIKELY_NOTABLE, + null, configuration, null, attributesForNewArtifact) .getAnalysisResult(); try { diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/Bundle.properties b/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/Bundle.properties index 8ca571695b..88832acd4b 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/Bundle.properties @@ -1,4 +1,4 @@ IngestSettingsPanel.ingestSettingsLabel.text=Ingest Settings IngestSettingsPanel.flagTaggedNotableItemsCheckbox.text=Flag items previously tagged as notable -IngestSettingsPanel.flagPreviouslySeenDevicesCheckbox.text=Flag devices previously seen in other cases +IngestSettingsPanel.flagPreviouslySeenDevicesCheckbox.text=Flag devices and users previously seen in other cases IngestSettingsPanel.createCorrelationPropertiesCheckbox.text=Save items to the Central Repository diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/Bundle.properties-MERGED index 46a2f01a64..c5ac5ed8db 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/Bundle.properties-MERGED @@ -11,5 +11,5 @@ CentralRepoIngestModuleFactory.ingestmodule.desc=Saves properties to the central CentralRepoIngestModuleFactory.ingestmodule.name=Central Repository IngestSettingsPanel.ingestSettingsLabel.text=Ingest Settings IngestSettingsPanel.flagTaggedNotableItemsCheckbox.text=Flag items previously tagged as notable -IngestSettingsPanel.flagPreviouslySeenDevicesCheckbox.text=Flag devices previously seen in other cases +IngestSettingsPanel.flagPreviouslySeenDevicesCheckbox.text=Flag devices and users previously seen in other cases IngestSettingsPanel.createCorrelationPropertiesCheckbox.text=Save items to the Central Repository diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/Bundle_ja.properties index a53f5ec2f6..1899d309b9 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/Bundle_ja.properties @@ -1,7 +1,15 @@ -#Fri Feb 12 16:56:28 UTC 2021 +#Mon Jul 12 13:21:59 UTC 2021 CentralRepoIngestModel_name_header=\u540d\u524d\uff1a
CentralRepoIngestModel_previous_case_header=
\u4ee5\u524d\u306e\u30b1\u30fc\u30b9\uff1a
CentralRepoIngestModule.errorMessage.isNotEnabled=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u8a2d\u5b9a\u304c\u521d\u671f\u5316\u3055\u308c\u3066\u304a\u3089\u305a\u3001\u53d6\u308a\u8fbc\u307f\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u5b9f\u884c\u3067\u304d\u307e\u305b\u3093\u3002 +CentralRepoIngestModule.notfyBubble.title=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u304c\u521d\u671f\u5316\u3055\u308c\u3066\u3044\u307e\u305b\u3093 +CentralRepoIngestModule.prevCaseComment.text=\u524d\u306e\u30b1\u30fc\u30b9\uff1a +CentralRepoIngestModule.prevTaggedSet.text=\u4ee5\u524d\u306b\u6ce8\u76ee\u3059\u3079\u304d\u3068\u3057\u3066\u30bf\u30b0\u4ed8\u3051\u3055\u308c\u305f\uff08\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\uff09 +CentralRepoIngestModuleFactory.ingestmodule.desc=\u8ffd\u3063\u3066\u76f8\u95a2\u7528\u306b\u3001\u30d7\u30ed\u30d1\u30c6\u30a3\u3092\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u306b\u4fdd\u5b58\u3057\u307e\u3059 CentralRepoIngestModuleFactory.ingestmodule.name=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea CentralRepoIngestModule_notable_message_header=\u3053\u306e\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u5185\u306e\u30d5\u30a1\u30a4\u30eb\u306f\u4ee5\u524d\u300c\u6ce8\u76ee\u300d\u3068\u3057\u3066\u30bf\u30b0\u4ed8\u3051\u3055\u308c\u3066\u3044\u307e\u3059\u3002
CentralRepoIngestModule_postToBB_knownBadMsg=\u6ce8\u76ee\uff1a {0} +IngestSettingsPanel.createCorrelationPropertiesCheckbox.text=\u30a2\u30a4\u30c6\u30e0\u3092\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u306b\u4fdd\u5b58\u3059\u308b +IngestSettingsPanel.flagPreviouslySeenDevicesCheckbox.text=\u4ee5\u524d\u306e\u30b1\u30fc\u30b9\u3067\u898b\u3089\u308c\u305f\u30c7\u30d0\u30a4\u30b9\u306b\u30d5\u30e9\u30b0\u3092\u4ed8\u3051\u308b +IngestSettingsPanel.flagTaggedNotableItemsCheckbox.text=\u4ee5\u524d\u306b\u6ce8\u76ee\u3059\u3079\u304d\u30bf\u30b0\u4ed8\u3051\u305f\u30a2\u30a4\u30c6\u30e0\u306b\u30d5\u30e9\u30b0\u3092\u4ed8\u3051\u308b +IngestSettingsPanel.ingestSettingsLabel.text=\u53d6\u8fbc\u307f\u8a2d\u5b9a diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/CentralRepoIngestModule.java b/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/CentralRepoIngestModule.java index 6d2f0a7e40..d40b45be86 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/CentralRepoIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/CentralRepoIngestModule.java @@ -67,7 +67,6 @@ import org.sleuthkit.datamodel.Score; final class CentralRepoIngestModule implements FileIngestModule { private static final String MODULE_NAME = CentralRepoIngestModuleFactory.getModuleName(); - static final boolean DEFAULT_FLAG_TAGGED_NOTABLE_ITEMS = false; static final boolean DEFAULT_FLAG_PREVIOUS_DEVICES = false; static final boolean DEFAULT_CREATE_CR_PROPERTIES = true; @@ -334,7 +333,6 @@ final class CentralRepoIngestModule implements FileIngestModule { * @param caseDisplayNames Case names to be added to a TSK_COMMON attribute. */ private void postCorrelatedBadFileToBlackboard(AbstractFile abstractFile, List caseDisplayNames) { - Collection attributes = Arrays.asList( new BlackboardAttribute( TSK_SET_NAME, MODULE_NAME, @@ -347,8 +345,8 @@ final class CentralRepoIngestModule implements FileIngestModule { // Create artifact if it doesn't already exist. if (!blackboard.artifactExists(abstractFile, TSK_INTERESTING_FILE_HIT, attributes)) { BlackboardArtifact tifArtifact = abstractFile.newAnalysisResult( - new BlackboardArtifact.Type(TSK_INTERESTING_FILE_HIT), - Score.SCORE_UNKNOWN, null, null, null, attributes) + BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT, Score.SCORE_LIKELY_NOTABLE, + null, Bundle.CentralRepoIngestModule_prevTaggedSet_text(), null, attributes) .getAnalysisResult(); try { // index the artifact for keyword search diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestSettingsPanel.form b/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestSettingsPanel.form index fe8d28c6f4..b685d08432 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestSettingsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestSettingsPanel.form @@ -29,7 +29,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestSettingsPanel.java index befe405281..2804cf1ce7 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestSettingsPanel.java @@ -88,7 +88,7 @@ final class IngestSettingsPanel extends IngestModuleIngestJobSettingsPanel { .addComponent(flagTaggedNotableItemsCheckbox, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(flagPreviouslySeenDevicesCheckbox, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(createCorrelationPropertiesCheckbox, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))) - .addContainerGap(47, Short.MAX_VALUE)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties-MERGED index 329bcdd88f..f49116150d 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties-MERGED @@ -39,7 +39,8 @@ GlobalSettingsPanel.askForCentralRepoDbChoice.sqliteChoice.text=Use SQLite GlobalSettingsPanel.onMultiUserChange.disabledMu.description=The Central Repository will be reconfigured to use a local SQLite database. GlobalSettingsPanel.onMultiUserChange.disabledMu.description2=Press Configure PostgreSQL to change to a PostgreSQL database. GlobalSettingsPanel.onMultiUserChange.disabledMu.title=Central Repository Change Necessary -GlobalSettingsPanel.onMultiUserChange.enable.description=Do you want to update the Central Repository to use this PostgreSQL server? +# {0} - server name +GlobalSettingsPanel.onMultiUserChange.enable.description=Do you want to update the Central Repository to use the PostgreSQL server on {0}? GlobalSettingsPanel.onMultiUserChange.enable.description2=Any data in an existing SQLite Central Repository will not be transferred to the new database. GlobalSettingsPanel.onMultiUserChange.enable.title=Central Repository GlobalSettingsPanel.testCurrentConfiguration.dbDoesNotExist.message=Database does not exist. diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle_ja.properties index f92bd670f4..07a447b55c 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle_ja.properties @@ -1,4 +1,4 @@ -#Tue Aug 18 18:09:20 UTC 2020 +#Mon Jun 14 12:23:19 UTC 2021 AddNewOrganizationDialog.addNewOrg.msg=\u65b0\u898f\u7d44\u7e54\u3092\u8ffd\u52a0 AddNewOrganizationDialog.bnCancel.text=\u53d6\u308a\u6d88\u3057 AddNewOrganizationDialog.bnOK.text=OK @@ -93,9 +93,9 @@ GlobalSettingsPanel.manageOrganizationButton.text=\u7d44\u7e54\u3092\u7ba1\u7406 GlobalSettingsPanel.onMultiUserChange.disabledMu.description=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u30fc\u306f\u30ed\u30fc\u30ab\u30ebSQLite\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3068\u3057\u3066\u518d\u69cb\u6210\u3055\u308c\u307e\u3059 GlobalSettingsPanel.onMultiUserChange.disabledMu.description2=[PostgreSQL\u306e\u69cb\u6210]\u3092\u62bc\u3057\u3066\u3001PostgreSQL\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306b\u5909\u66f4\u3057\u307e\u3059\u3002 GlobalSettingsPanel.onMultiUserChange.disabledMu.title=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u30fc\u306e\u5909\u66f4\u304c\u5fc5\u8981\u3067\u3059 -GlobalSettingsPanel.onMultiUserChange.enable.description=\u3053\u306ePostgreSQL\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u4f7f\u7528\u3059\u308b\u3088\u3046\u306b\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u30fc\u3092\u66f4\u65b0\u3057\u307e\u3059\u304b\uff1f -GlobalSettingsPanel.onMultiUserChange.enable.description2=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u30fc\u306b\u306f\u904e\u53bb\u306e\u30b1\u30fc\u30b9\u304b\u3089\u306e\u30cf\u30c3\u30b7\u30e5\u5024\u3068\u30a2\u30ab\u30a6\u30f3\u30c8\u304c\u4fdd\u5b58\u3055\u308c\u307e\u3059\u3002 -GlobalSettingsPanel.onMultiUserChange.enable.title=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u30fc\u3067\u4f7f\u7528\u3057\u307e\u3059\u304b\uff1f +GlobalSettingsPanel.onMultiUserChange.enable.description=\u3053\u306ePostgreSQL\u30b5\u30fc\u30d0\u30fc\u3092\u4f7f\u7528\u3059\u308b\u3088\u3046\u306b\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u3092\u66f4\u65b0\u3057\u307e\u3059\u304b\uff1f +GlobalSettingsPanel.onMultiUserChange.enable.description2=\u65e2\u5b58\u306eSQLite\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u306e\u30c7\u30fc\u30bf\u306f\u65b0\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306b\u8ee2\u9001\u3055\u308c\u307e\u305b\u3093\u3002 +GlobalSettingsPanel.onMultiUserChange.enable.title=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea GlobalSettingsPanel.organizationPanel.border.title=\u7d44\u7e54 GlobalSettingsPanel.organizationTextArea.text=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ec\u30dd\u30b8\u30c8\u30ea\u30fc\u5185\u3067\u7d44\u7e54\u60c5\u5831\u3092\u8ffd\u8de1\u3067\u304d\u307e\u3059\u3002 GlobalSettingsPanel.pnCorrelationProperties.border.title=\u76f8\u95a2\u5206\u6790\u30d7\u30ed\u30d1\u30c6\u30a3 diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.java index d4dc547018..6c8c2a9b72 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.java @@ -47,6 +47,7 @@ import java.util.logging.Level; import javax.swing.ImageIcon; import org.openide.util.ImageUtilities; import org.sleuthkit.autopsy.centralrepository.datamodel.DatabaseTestResult; +import org.sleuthkit.autopsy.centralrepository.datamodel.PostgresSettingsLoader; @@ -152,7 +153,8 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i */ @NbBundle.Messages({ "GlobalSettingsPanel.onMultiUserChange.enable.title=Central Repository", - "GlobalSettingsPanel.onMultiUserChange.enable.description=Do you want to update the Central Repository to use this PostgreSQL server?", + "# {0} - server name", + "GlobalSettingsPanel.onMultiUserChange.enable.description=Do you want to update the Central Repository to use the PostgreSQL server on {0}?", "GlobalSettingsPanel.onMultiUserChange.enable.description2=Any data in an existing SQLite Central Repository will not be transferred to the new database." }) public static void onMultiUserChange(Component parent, boolean muPreviouslySelected, boolean muCurrentlySelected) { @@ -161,10 +163,12 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i if (!muPreviouslySelected && muCurrentlySelected) { SwingUtilities.invokeLater(() -> { + PostgresCentralRepoSettings multiUserSettings + = new PostgresCentralRepoSettings(PostgresSettingsLoader.MULTIUSER_SETTINGS_LOADER); if (JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(parent, "" + "
" - + "

" + Bundle.GlobalSettingsPanel_onMultiUserChange_enable_description() + "

" + + "

" + Bundle.GlobalSettingsPanel_onMultiUserChange_enable_description(multiUserSettings.getHost()) + "

" + "

" + Bundle.GlobalSettingsPanel_onMultiUserChange_enable_description2() + "

" + "
" + "", diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/persona/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/centralrepository/persona/Bundle_ja.properties index 998d515e18..f10efec41a 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/persona/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/persona/Bundle_ja.properties @@ -1,4 +1,4 @@ -#Fri Feb 12 16:56:28 UTC 2021 +#Mon Jul 12 13:21:59 UTC 2021 AddAliasDialog.accountsLbl.text=\u30a2\u30ab\u30a6\u30f3\u30c8\uff1a AddAliasDialog.cancelBtn.text=\u30ad\u30e3\u30f3\u30bb\u30eb AddAliasDialog.okBtn.text=OK @@ -17,6 +17,7 @@ CreatePersonaAccountDialog.title.text=\u30a2\u30ab\u30a6\u30f3\u30c8\u3092\u4f5c CreatePersonaAccountDialog.typeLbl.text=\u30bf\u30a4\u30d7\uff1a CreatePersonaAccountDialog_error_msg=\u30a2\u30ab\u30a6\u30f3\u30c8\u306e\u4f5c\u6210\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 CreatePersonaAccountDialog_error_title=\u30a2\u30ab\u30a6\u30f3\u30c8\u306e\u30a8\u30e9\u30fc +CreatePersonaAccountDialog_invalid_account_Title=\u30a2\u30ab\u30a6\u30f3\u30c8\u8b58\u5225\u5b50\u304c\u7121\u52b9\u3067\u3059 CreatePersonaAccountDialog_invalid_account_msg=\u30a2\u30ab\u30a6\u30f3\u30c8\u8b58\u5225\u5b50\u304c\u7121\u52b9\u3067\u3059\u3002 CreatePersonaAccountDialog_success_msg=\u30a2\u30ab\u30a6\u30f3\u30c8\u304c\u8ffd\u52a0\u3055\u308c\u307e\u3057\u305f\u3002 CreatePersonaAccountDialog_success_title=\u30a2\u30ab\u30a6\u30f3\u30c8\u304c\u8ffd\u52a0\u3055\u308c\u307e\u3057\u305f\u3002 diff --git a/Core/src/org/sleuthkit/autopsy/commandlineingest/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/commandlineingest/Bundle_ja.properties index 3c234acd31..a49a787f67 100644 --- a/Core/src/org/sleuthkit/autopsy/commandlineingest/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/commandlineingest/Bundle_ja.properties @@ -1,4 +1,4 @@ -#Fri Feb 12 16:56:28 UTC 2021 +#Mon Jul 12 13:21:59 UTC 2021 AutopsyOptionsPanel.agencyLogoPathFieldValidationLabel.invalidPath.text=\u30d1\u30b9\u306f\u6709\u52b9\u3067\u306f\u3042\u308a\u307e\u305b\u3093 CommandLineIngestSettingPanel_empty_report_name_mgs=\u30ec\u30dd\u30fc\u30c8\u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u540d\u306f\u7a7a\u767d\u306a\u306e\u3067\u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u306f\u4f5c\u6210\u3057\u307e\u305b\u3093\u3002 CommandLineIngestSettingPanel_existing_report_name_mgs=\u30ec\u30dd\u30fc\u30c8\u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u540d\u306f\u3059\u3067\u306b\u5b58\u5728\u3059\u308b\u306e\u3067\u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u306f\u4f5c\u6210\u3057\u307e\u305b\u3093\u3002 @@ -8,7 +8,9 @@ CommandLineIngestSettingsPanel.ResultsDirectoryUnspecified=\u51fa\u529b\u30d5\u3 CommandLineIngestSettingsPanel.bnEditIngestSettings.text=\u8a2d\u5b9a CommandLineIngestSettingsPanel.bnEditIngestSettings.toolTipText=\u30b3\u30de\u30f3\u30c9\u30e9\u30a4\u30f3\u51e6\u7406\u30e2\u30fc\u30c9\u306e\u30b3\u30f3\u30c6\u30ad\u30b9\u30c8\u306e\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30b8\u30e7\u30d6\u8a2d\u5b9a\u3067\u3059\u3002 CommandLineIngestSettingsPanel.bnEditReportSettings.AccessibleContext.accessibleName=\u8a2d\u5b9a +CommandLineIngestSettingsPanel.bnEditReportSettings.actionCommand=\u30ec\u30dd\u30fc\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u8a2d\u5b9a CommandLineIngestSettingsPanel.bnEditReportSettings.text=\u8a2d\u5b9a +CommandLineIngestSettingsPanel.bnEditReportSettings.toolTipText=\u30b3\u30de\u30f3\u30c9\u30e9\u30a4\u30f3\u51e6\u7406\u30e2\u30fc\u30c9\u30b3\u30f3\u30c6\u30ad\u30b9\u30c8\u306e\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u8a2d\u5b9a\u3002 CommandLineIngestSettingsPanel.browseOutputFolderButton.text=\u53c2\u7167 CommandLineIngestSettingsPanel.ingestDescriptionTextPane.text=\u30b3\u30de\u30f3\u30c9\u30e9\u30a4\u30f3\u304b\u3089\u4f7f\u7528\u3059\u308b\u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u3092\u8a2d\u5b9a\u3057\u307e\u3059\u3002 CommandLineIngestSettingsPanel.ingestProfileLabel.text=\u53d6\u8fbc\u307f\u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\uff1a diff --git a/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InstanceCountNode.java b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InstanceCountNode.java index 5be8f8bae2..628bec9291 100644 --- a/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InstanceCountNode.java +++ b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InstanceCountNode.java @@ -2,7 +2,7 @@ * * Autopsy Forensic Browser * - * Copyright 2018-2019 Basis Technology Corp. + * Copyright 2018-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -60,7 +60,7 @@ public final class InstanceCountNode extends DisplayableItemNode { "InstanceCountNode.displayName=Exists in %s data sources (%s)" }) public InstanceCountNode(int instanceCount, CommonAttributeValueList attributeValues, CorrelationAttributeInstance.Type type) { - super(Children.create(new CommonAttributeValueNodeFactory(attributeValues.getMetadataList(), type), false)); + super(Children.create(new CommonAttributeValueNodeFactory(attributeValues.getMetadataList(), type), true)); this.type = type; this.instanceCount = instanceCount; this.attributeValues = attributeValues; diff --git a/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InterCasePanel.java b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InterCasePanel.java index 5eb521f3d5..923e2195f2 100644 --- a/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InterCasePanel.java +++ b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InterCasePanel.java @@ -128,8 +128,10 @@ public final class InterCasePanel extends javax.swing.JPanel { } }); for (CorrelationAttributeInstance.Type type : types) { - correlationTypeFilters.put(type.getDisplayName(), type); - this.correlationTypeComboBox.addItem(type.getDisplayName()); + if (! type.getDbTableName().contains("os_account") && ! type.getDbTableName().contains("installed_program")) { + correlationTypeFilters.put(type.getDisplayName(), type); + this.correlationTypeComboBox.addItem(type.getDisplayName()); + } } } catch (CentralRepoException ex) { logger.log(Level.WARNING, "Error getting correlation types", ex); diff --git a/Core/src/org/sleuthkit/autopsy/communications/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/communications/Bundle_ja.properties index 9deed89128..53b9636ea1 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/communications/Bundle_ja.properties @@ -1,4 +1,4 @@ -#Fri Feb 12 16:56:28 UTC 2021 +#Mon Jul 12 13:21:59 UTC 2021 AccountInstanceNode_Tooltip_Template=\u9023\u7d61\u5148\uff1a{0}-\u30da\u30eb\u30bd\u30ca\uff1a{1} AccountInstanceNode_Tooltip_suffix=(1 of {0}) AccountNode.accountName=\u30a2\u30ab\u30a6\u30f3\u30c8 @@ -10,6 +10,8 @@ CVTTopComponent.TabConstraints.tabTitle=\u53ef\u8996\u5316 CVTTopComponent.accountsBrowser.TabConstraints.tabTitle=\u53c2\u7167 CVTTopComponent.accountsBrowser.TabConstraints.tabTitle_1=\u53c2\u7167 CVTTopComponent.browseVisualizeTabPane.AccessibleContext.accessibleName=\u53ef\u8996\u5316 +CVTTopComponent.filterTabPanel.TabConstraints.tabTitle=\u30d5\u30a3\u30eb\u30bf\u30fc +CVTTopComponent.filtersPane.TabConstraints.tabTitle=\u30d5\u30a3\u30eb\u30bf\u30fc CVTTopComponent.name=\ \u30b3\u30df\u30e5\u30cb\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u53ef\u8996\u5316 CVTTopComponent.vizPanel.TabConstraints.tabTitle=\u53ef\u8996\u5316 CVTTopComponent.vizPanel.TabConstraints.tabTitle_1=\u53ef\u8996\u5316 @@ -68,6 +70,8 @@ VisualizationPanel.fitZoomButton.text= VisualizationPanel.fitZoomButton.toolTipText=\u53ef\u8996\u5316\u3092\u9069\u5408 VisualizationPanel.forwardButton.text= VisualizationPanel.forwardButton.toolTipText=\u30af\u30ea\u30c3\u30af\u3057\u3066\u9032\u3080 +VisualizationPanel.hierarchyLayoutButton.text=\u968e\u5c64\u7684 +VisualizationPanel.jButton1.text=Fast Organic VisualizationPanel.jTextPane1.text=[\u30a2\u30ab\u30a6\u30f3\u30c8\u306e\u53c2\u7167]\u30c6\u30fc\u30d6\u30eb\u3067\u30a2\u30ab\u30a6\u30f3\u30c8\u3092\u53f3\u30af\u30ea\u30c3\u30af\u3057\u3001[\u8868\u793a]\u3092\u9078\u629e\u3057\u3066\u958b\u59cb\u3002 VisualizationPanel.layoutFail.text={0} \u30ec\u30a4\u30a2\u30a6\u30c8\u304c\u5931\u6557\u3057\u307e\u3057\u305f\u3002\u5225\u306e\u30ec\u30a4\u30a2\u30a6\u30c8\u3092\u304a\u8a66\u3057\u304f\u3060\u3055\u3044\u3002 VisualizationPanel.layoutFailWithLockedVertices.text=\u9802\u70b9\u304c\u30ed\u30c3\u30af\u3055\u308c\u305f {0} \u30ec\u30a4\u30a2\u30a6\u30c8\u304c\u5931\u6557\u3057\u307e\u3057\u305f\u3002\u4e00\u90e8\u306e\u9802\u70b9\u306e\u30ed\u30c3\u30af\u3092\u89e3\u9664\u3059\u308b\u304b\u3001\u5225\u306e\u30ec\u30a4\u30a2\u30a6\u30c8\u3092\u304a\u8a66\u3057\u304f\u3060\u3055\u3044\u3002 @@ -75,6 +79,7 @@ VisualizationPanel.lockAction.pluralText=\u9078\u629e\u3057\u305f\u30a2\u30ab\u3 VisualizationPanel.lockAction.singularText=\u9078\u629e\u3057\u305f\u30a2\u30ab\u30a6\u30f3\u30c8\u3092\u30ed\u30c3\u30af VisualizationPanel.organicLayoutButton.text=\u6709\u6a5f\u7684 VisualizationPanel.snapshotButton.text_1=\u30b9\u30ca\u30c3\u30d7\u30b7\u30e7\u30c3\u30c8\u30fb\u30ec\u30dd\u30fc\u30c8 +VisualizationPanel.snapshotButton.toolTipText=\u30b9\u30ca\u30c3\u30d7\u30b7\u30e7\u30c3\u30c8\u30ec\u30dd\u30fc\u30c8 VisualizationPanel.unlockAction.pluralText=\u9078\u629e\u3057\u305f\u30a2\u30ab\u30a6\u30f3\u30c8\u306e\u30ed\u30c3\u30af\u3092\u89e3\u9664 VisualizationPanel.unlockAction.singularText=\u9078\u629e\u3057\u305f\u30a2\u30ab\u30a6\u30f3\u30c8\u3092\u30ed\u30c3\u30af VisualizationPanel.zoomActualButton.text= @@ -84,6 +89,7 @@ VisualizationPanel.zoomInButton.toolTipText=\u30ba\u30fc\u30e0\u30a4\u30f3 VisualizationPanel.zoomLabel.text=100% VisualizationPanel.zoomOutButton.text= VisualizationPanel.zoomOutButton.toolTipText=\u30ba\u30fc\u30e0\u30a2\u30a6\u30c8 +VisualizationPanel.zoomPercentLabel.text=100% VisualizationPanel_action_dialogs_title=\u30b3\u30df\u30e5\u30cb\u30b1\u30fc\u30b7\u30e7\u30f3 VisualizationPanel_action_name_text=\u30b9\u30ca\u30c3\u30d7\u30b7\u30e7\u30c3\u30c8\u30fb\u30ec\u30dd\u30fc\u30c8 VisualizationPanel_module_name=\u30b3\u30df\u30e5\u30cb\u30b1\u30fc\u30b7\u30e7\u30f3 diff --git a/Core/src/org/sleuthkit/autopsy/communications/VisualizationPanel.java b/Core/src/org/sleuthkit/autopsy/communications/VisualizationPanel.java index 0fb2beac00..9e13769730 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/VisualizationPanel.java +++ b/Core/src/org/sleuthkit/autopsy/communications/VisualizationPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2017-2018 Basis Technology Corp. + * Copyright 2017-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -70,7 +70,6 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; -import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.function.BiConsumer; import java.util.logging.Level; @@ -583,30 +582,14 @@ final public class VisualizationPanel extends JPanel { ModalDialogProgressIndicator progressIndicator = new ModalDialogProgressIndicator(windowAncestor, Bundle.VisualizationPanel_computingLayout()); progressIndicator.start(Bundle.VisualizationPanel_computingLayout()); - - new SwingWorker() { - @Override - protected Void doInBackground() { - graph.getModel().beginUpdate(); - try { - layout.execute(graph.getDefaultParent()); - fitGraph(); - } finally { - graph.getModel().endUpdate(); - progressIndicator.finish(); - } - return null; - } - - @Override - protected void done() { - try { - get(); - } catch (InterruptedException | ExecutionException ex) { - logger.log(Level.WARNING, "CVT graph layout failed.", ex); - } - } - }.execute(); + graph.getModel().beginUpdate(); + try { + layout.execute(graph.getDefaultParent()); + fitGraph(); + } finally { + graph.getModel().endUpdate(); + progressIndicator.finish(); + } } private void clearVizButtonActionPerformed(ActionEvent evt) {//GEN-FIRST:event_clearVizButtonActionPerformed diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/communications/relationships/Bundle_ja.properties index b02216ee0e..a7f4b32435 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/Bundle_ja.properties @@ -1,4 +1,9 @@ -#Fri Feb 12 16:56:28 UTC 2021 +#Mon Jul 12 13:21:59 UTC 2021 +CallLogViewer_device_label=\u30c7\u30d0\u30a4\u30b9 +CallLogViewer_duration_label=\u671f\u9593\uff08\u79d2\uff09 +CallLogViewer_noCallLogs=<\u9078\u629e\u3057\u305f\u30a2\u30ab\u30a6\u30f3\u30c8\u306e\u901a\u8a71\u30ed\u30b0\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093> +CallLogViewer_recipient_label=\u5b9b\u5148/\u53d7\u4fe1 +CallLogViewer_title=\u30b3\u30fc\u30eb\u30ed\u30b0 ContactDetailsPane.nameLabel.text=\u30d7\u30ec\u30fc\u30b9\u30db\u30eb\u30c0\u30fc ContactNode_Email=\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9 ContactNode_Home_Number=\u81ea\u5b85\u96fb\u8a71\u756a\u53f7 @@ -46,6 +51,10 @@ SummaryPersonaPane.createButton.text=\u4f5c\u6210 SummaryPersonaPane.messageLabel.text=<\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u304c\u30da\u30eb\u30bd\u30ca\u3092\u4f5c\u6210\u304a\u3088\u3073\u8868\u793a\u3067\u304d\u308b\u3088\u3046\u306b\u3059\u308b> SummaryPersonaPane.noPersonaLabel.text=\u30da\u30eb\u30bd\u30ca\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093 SummaryPersonaPane_not_account_in_cr=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u3067\u8b58\u5225\u5b50{0}\u306e\u30a2\u30ab\u30a6\u30f3\u30c8\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3002 +SummaryViewer.accountCountry.text=<\u30a2\u30ab\u30a6\u30f3\u30c8\u306e\u56fd> +SummaryViewer.accountLabel.text=<\u30a2\u30ab\u30a6\u30f3\u30c8\u540d> +SummaryViewer.accoutDescriptionLabel.text=<\u30a2\u30ab\u30a6\u30f3\u30c8\u306e\u8aac\u660e> +SummaryViewer.attachmentDataLabel.text=\u30ab\u30a6\u30f3\u30c8 SummaryViewer.attachmentsDataLabel.text=\u6dfb\u4ed8\u30d5\u30a1\u30a4\u30eb SummaryViewer.attachmentsLabel.text=\u30e1\u30c7\u30a3\u30a2\u6dfb\u4ed8\u30d5\u30a1\u30a4\u30eb\: SummaryViewer.callLogsDataLabel.text=callLogs @@ -53,18 +62,28 @@ SummaryViewer.callLogsLabel.text=\u901a\u8a71\u30ed\u30b0\: SummaryViewer.caseReferencesPanel.border.title=\u305d\u306e\u4ed6\u306e\u767a\u751f SummaryViewer.contactsDataLabel.text=\u9023\u7d61\u5148 SummaryViewer.contactsLabel.text=\u9023\u7d61\u5148\: +SummaryViewer.contanctsPanel.border.title=\u30a2\u30ab\u30a6\u30f3\u30c8\u306e\u9023\u7d61\u5148 SummaryViewer.countsPanel.border.title=\u30ab\u30a6\u30f3\u30c8 SummaryViewer.fileRefPane.border.title=\u73fe\u30b1\u30fc\u30b9\u306e\u30d5\u30a1\u30a4\u30eb\u53c2\u7167 SummaryViewer.messagesDataLabel.text=\u30e1\u30c3\u30bb\u30fc\u30b8 SummaryViewer.messagesLabel.text=\u30e1\u30c3\u30bb\u30fc\u30b8\: SummaryViewer.personaPanel.border.title=\u30da\u30eb\u30bd\u30ca +SummaryViewer.referencesDataLabel.text=<\u53c2\u7167\u30ab\u30a6\u30f3\u30c8> +SummaryViewer.referencesLabel.text=\u901a\u4fe1\u30ea\u30d5\u30a1\u30ec\u30f3\u30b9\uff1a SummaryViewer.selectAccountFileRefLabel.text=<\u30d5\u30a1\u30a4\u30eb\u53c2\u7167\u3092\u8868\u793a\u3059\u308b\u306b\u306f\u3001\u5358\u4e00\u306e\u30a2\u30ab\u30a6\u30f3\u30c8\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044> +SummaryViewer.thumbnailCntLabel.text=\u30e1\u30c7\u30a3\u30a2\u306e\u6dfb\u4ed8\u30d5\u30a1\u30a4\u30eb\uff1a +SummaryViewer.thumbnailsDataLabel.text=\u6dfb\u4ed8\u30d5\u30a1\u30a4\u30eb +SummaryViewer_Account_Description=\u3053\u306e\u30a2\u30ab\u30a6\u30f3\u30c8\u306f\u3001\u30b1\u30fc\u30b9\u5185\u306e\u30c7\u30d0\u30a4\u30b9\u3092\u8868\u3057\u307e\u3059\u3002 +SummaryViewer_Account_Description_MuliSelect=\u8907\u6570\u306e\u30a2\u30ab\u30a6\u30f3\u30c8\u304c\u9078\u629e\u3055\u308c\u3066\u3044\u308b\u5834\u5408\u3001\u6982\u8981\u60c5\u5831\u306f\u5229\u7528\u3067\u304d\u307e\u305b\u3093\u3002 SummaryViewer_CaseRefNameColumn_Title=\u30b1\u30fc\u30b9\u540d SummaryViewer_CentralRepository_Message=<\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ec\u30dd\u30b8\u30c8\u30ea\u30fc\u3092\u6709\u52b9\u5316\u3057\u3066\u305d\u306e\u4ed6\u306e\u767a\u751f\u3092\u8868\u793a> +SummaryViewer_Country_Code=\u56fd\uff1a SummaryViewer_Creation_Date_Title=\u4f5c\u6210\u65e5 +SummaryViewer_Device_Account_Description=\u3053\u306e\u30a2\u30ab\u30a6\u30f3\u30c8\u306f\u3001\u30b1\u30fc\u30b9\u5185\u306e\u30c7\u30d0\u30a4\u30b9\u306b\u3088\u3063\u3066\u53c2\u7167\u3055\u308c\u307e\u3057\u305f\u3002 SummaryViewer_Fetching_References=<\u30d5\u30a1\u30a4\u30eb\u53c2\u7167\u306e\u53d6\u5f97> SummaryViewer_FileRefNameColumn_Title=\u30d1\u30b9 -SummaryViewer_Persona_Message=<\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u304c\u30da\u30eb\u30bd\u30ca\u3092\u8868\u793a\u53ef\u80fd\u306b\u3059\u308b> +SummaryViewer_FileRef_Message=<\u30d5\u30a1\u30a4\u30eb\u53c2\u7167\u3092\u8868\u793a\u3059\u308b\u306b\u306f\u3001\u5358\u4e00\u306e\u30a2\u30ab\u30a6\u30f3\u30c8\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044> +SummaryViewer_Persona_CR_Message=<\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u304c\u30da\u30eb\u30bd\u30ca\u3092\u8868\u793a\u3067\u304d\u308b\u3088\u3046\u306b\u3059\u308b> SummaryViewer_Select_account_for_persona=<\u30da\u30eb\u30bd\u30ca\u3092\u8868\u793a\u3059\u308b\u306b\u306f\u3001\u30a2\u30ab\u30a6\u30f3\u30c8\u30921\u3064\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044> SummaryViewer_TabTitle=\u30b5\u30de\u30ea\u30fc SummeryViewer_FileRef_Message=<\u30a2\u30ab\u30a6\u30f3\u30c8\u30921\u3064\u9078\u629e\u3057\u3066\u30d5\u30a1\u30a4\u30eb\u30ec\u30d5\u30a1\u30ec\u30f3\u30b9\u3092\u8868\u793a> diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogViewer.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogViewer.java index 21d7deb8bd..f2b99df0dd 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogViewer.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/CallLogViewer.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2019 Basis Technology Corp. + * Copyright 2019-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -119,9 +119,9 @@ final class CallLogViewer extends javax.swing.JPanel implements RelationshipsVie updateOutlineViewPanel(); } }); - + TableColumn column = outline.getColumnModel().getColumn(2); - column.setCellRenderer(new NodeTableCellRenderer() ); + column.setCellRenderer(new NodeTableCellRenderer()); } @@ -164,7 +164,9 @@ final class CallLogViewer extends javax.swing.JPanel implements RelationshipsVie @Override public void setSelectionInfo(SelectionInfo info) { + callLogDataViewer.setNode(null); nodeFactory.refresh(info); + } @Override @@ -229,7 +231,7 @@ final class CallLogViewer extends javax.swing.JPanel implements RelationshipsVie } } - + // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JScrollPane bottomScrollPane; private org.sleuthkit.autopsy.communications.relationships.OutlineViewPanel outlineViewPanel; diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/ContactsChildNodeFactory.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/ContactsChildNodeFactory.java index 28666c8fdd..ab980ee101 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/ContactsChildNodeFactory.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/ContactsChildNodeFactory.java @@ -35,7 +35,8 @@ import org.sleuthkit.datamodel.TskCoreException; /** * ChildFactory for ContactNodes. */ -final class ContactsChildNodeFactory extends ChildFactory{ +final class ContactsChildNodeFactory extends ChildFactory { + private static final Logger logger = Logger.getLogger(ContactsChildNodeFactory.class.getName()); private SelectionInfo selectionInfo; @@ -47,12 +48,13 @@ final class ContactsChildNodeFactory extends ChildFactory{ * accounts */ ContactsChildNodeFactory(SelectionInfo selectionInfo) { - this.selectionInfo = selectionInfo; + this.selectionInfo = selectionInfo; } - + /** - * Updates the current instance of selectionInfo and calls the refresh method. - * + * Updates the current instance of selectionInfo and calls the refresh + * method. + * * @param selectionInfo New instance of the currently selected accounts */ public void refresh(SelectionInfo selectionInfo) { @@ -63,13 +65,15 @@ final class ContactsChildNodeFactory extends ChildFactory{ /** * Creates a list of Keys (BlackboardArtifact) for only contacts of the * currently selected accounts + * * @param list List of BlackboardArtifact to populate + * * @return True on success */ @Override protected boolean createKeys(List list) { - - if(selectionInfo == null) { + + if (selectionInfo == null) { return true; } @@ -80,7 +84,7 @@ final class ContactsChildNodeFactory extends ChildFactory{ logger.log(Level.SEVERE, "Failed to load relationship sources.", ex); //NON-NLS return false; } - + relationshipSources.stream().filter((content) -> (content instanceof BlackboardArtifact)).forEachOrdered((content) -> { BlackboardArtifact bba = (BlackboardArtifact) content; diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/ContactsViewer.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/ContactsViewer.java index 1d11b3ef6d..6366d4e517 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/ContactsViewer.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/ContactsViewer.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2019 Basis Technology Corp. + * Copyright 2019-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -35,7 +35,6 @@ import org.openide.nodes.NodeAdapter; import org.openide.nodes.NodeMemberEvent; import org.openide.util.Lookup; import org.openide.util.NbBundle; -import org.openide.util.lookup.ServiceProvider; import org.sleuthkit.autopsy.communications.ModifiableProxyLookup; import org.sleuthkit.autopsy.corecomponents.TableFilterNode; import org.sleuthkit.autopsy.directorytree.DataResultFilterNode; @@ -126,6 +125,7 @@ final class ContactsViewer extends JPanel implements RelationshipsViewer { @Override public void setSelectionInfo(SelectionInfo info) { + contactPane.setNode(null); nodeFactory.refresh(info); } diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/MediaViewer.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/MediaViewer.java index daffdafb81..63988b200d 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/MediaViewer.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/MediaViewer.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2019 Basis Technology Corp. + * Copyright 2019-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -99,18 +99,19 @@ final class MediaViewer extends JPanel implements RelationshipsViewer, ExplorerM public void setSelectionInfo(SelectionInfo info) { Set relationshipSources; Set artifactList = new HashSet<>(); + contentViewer.setNode(null); + if (info != null) { + try { + relationshipSources = info.getRelationshipSources(); - try { - relationshipSources = info.getRelationshipSources(); + relationshipSources.stream().filter((content) -> (content instanceof BlackboardArtifact)).forEachOrdered((content) -> { + artifactList.add((BlackboardArtifact) content); + }); - relationshipSources.stream().filter((content) -> (content instanceof BlackboardArtifact)).forEachOrdered((content) -> { - artifactList.add((BlackboardArtifact) content); - }); - - } catch (TskCoreException ex) { - logger.log(Level.WARNING, "Unable to update selection.", ex); + } catch (TskCoreException ex) { + logger.log(Level.WARNING, "Unable to update selection.", ex); + } } - thumbnailViewer.resetComponent(); thumbnailViewer.setNode(new TableFilterNode(new DataResultFilterNode(new AbstractNode(new AttachmentThumbnailsChildren(artifactList)), tableEM), true, this.getClass().getName())); diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipBrowser.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipBrowser.java index 229a0067de..8910472295 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipBrowser.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/RelationshipBrowser.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2019 Basis Technology Corp. + * Copyright 2019-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,7 +18,6 @@ */ package org.sleuthkit.autopsy.communications.relationships; -import java.awt.Component; import javax.swing.JPanel; import org.openide.util.Lookup; import org.sleuthkit.autopsy.communications.ModifiableProxyLookup; @@ -37,15 +36,15 @@ public final class RelationshipBrowser extends JPanel implements Lookup.Provider */ public RelationshipBrowser() { initComponents(); - + MessageViewer messagesViewer = new MessageViewer(); ContactsViewer contactsViewer = new ContactsViewer(); SummaryViewer summaryViewer = new SummaryViewer(); MediaViewer mediaViewer = new MediaViewer(); CallLogViewer callLogViewer = new CallLogViewer(); - + proxyLookup = new ModifiableProxyLookup(messagesViewer.getLookup()); - + tabPane.add(summaryViewer.getDisplayName(), summaryViewer); tabPane.add(messagesViewer.getDisplayName(), messagesViewer); tabPane.add(callLogViewer.getDisplayName(), callLogViewer); @@ -95,13 +94,11 @@ public final class RelationshipBrowser extends JPanel implements Lookup.Provider }// //GEN-END:initComponents private void tabPaneStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_tabPaneStateChanged - if(currentSelection != null) { - ((RelationshipsViewer) tabPane.getSelectedComponent()).setSelectionInfo(currentSelection); - } - - Component selectedComponent = tabPane.getSelectedComponent(); - if(selectedComponent instanceof Lookup.Provider) { - Lookup lookup = ((Lookup.Provider)selectedComponent).getLookup(); + RelationshipsViewer viewer = ((RelationshipsViewer) tabPane.getSelectedComponent()); + //clear old values + viewer.setSelectionInfo(currentSelection); + if (viewer instanceof Lookup.Provider) { + Lookup lookup = viewer.getLookup(); proxyLookup.setNewLookups(lookup); } }//GEN-LAST:event_tabPaneStateChanged diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java index 5d109438c3..b61abfceee 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2018-2020 Basis Technology Corp. + * Copyright 2018-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,10 +21,7 @@ package org.sleuthkit.autopsy.contentviewers; import java.awt.Component; import java.util.concurrent.ExecutionException; import java.util.logging.Level; -import javax.swing.JLabel; import javax.swing.SwingWorker; -import javax.swing.text.EditorKit; -import javax.swing.text.html.HTMLEditorKit; import static org.openide.util.NbBundle.Messages; import org.openide.nodes.Node; @@ -36,6 +33,7 @@ import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.autopsy.contentviewers.application.Annotations; import org.sleuthkit.autopsy.coreutils.Logger; import org.jsoup.nodes.Document; +import org.sleuthkit.autopsy.contentviewers.layout.ContentViewerHtmlStyles; /** * Annotations view of file contents. @@ -48,33 +46,6 @@ import org.jsoup.nodes.Document; "AnnotationsContentViewer.onEmpty=No annotations were found for this particular item." }) public class AnnotationsContentViewer extends javax.swing.JPanel implements DataContentViewer { - - private static final int DEFAULT_FONT_SIZE = new JLabel().getFont().getSize(); - - // how big the subheader should be - private static final int SUBHEADER_FONT_SIZE = DEFAULT_FONT_SIZE * 12 / 11; - - // how big the header should be - private static final int HEADER_FONT_SIZE = DEFAULT_FONT_SIZE * 14 / 11; - - // the subsection indent - private static final int DEFAULT_SUBSECTION_LEFT_PAD = DEFAULT_FONT_SIZE; - - // spacing occurring after an item - private static final int DEFAULT_SECTION_SPACING = DEFAULT_FONT_SIZE * 2; - private static final int DEFAULT_SUBSECTION_SPACING = DEFAULT_FONT_SIZE / 2; - private static final int CELL_SPACING = DEFAULT_FONT_SIZE / 2; - - // additional styling for components - private static final String STYLE_SHEET_RULE - = String.format(" .%s { font-size: %dpx;font-style:italic; margin: 0px; padding: 0px; } ", Annotations.MESSAGE_CLASSNAME, DEFAULT_FONT_SIZE) - + String.format(" .%s {font-size:%dpx;font-weight:bold; margin: 0px; margin-top: %dpx; padding: 0px; } ", - Annotations.SUBHEADER_CLASSNAME, SUBHEADER_FONT_SIZE, DEFAULT_SUBSECTION_SPACING) - + String.format(" .%s { font-size:%dpx;font-weight:bold; margin: 0px; padding: 0px; } ", Annotations.HEADER_CLASSNAME, HEADER_FONT_SIZE) - + String.format(" td { vertical-align: top; font-size:%dpx; text-align: left; margin: 0px; padding: 0px %dpx 0px 0px;} ", DEFAULT_FONT_SIZE, CELL_SPACING) - + String.format(" th { vertical-align: top; text-align: left; margin: 0px; padding: 0px %dpx 0px 0px} ", DEFAULT_FONT_SIZE, CELL_SPACING) - + String.format(" .%s { margin: %dpx 0px; padding-left: %dpx; } ", Annotations.SUBSECTION_CLASSNAME, DEFAULT_SUBSECTION_SPACING, DEFAULT_SUBSECTION_LEFT_PAD) - + String.format(" .%s { margin-bottom: %dpx; } ", Annotations.SECTION_CLASSNAME, DEFAULT_SECTION_SPACING); private static final long serialVersionUID = 1L; private static final Logger logger = Logger.getLogger(AnnotationsContentViewer.class.getName()); @@ -86,13 +57,7 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data */ public AnnotationsContentViewer() { initComponents(); - Utilities.configureTextPaneAsHtml(textPanel); - // get html editor kit and apply additional style rules - EditorKit editorKit = textPanel.getEditorKit(); - if (editorKit instanceof HTMLEditorKit) { - HTMLEditorKit htmlKit = (HTMLEditorKit) editorKit; - htmlKit.getStyleSheet().addRule(STYLE_SHEET_RULE); - } + ContentViewerHtmlStyles.setupHtmlJTextPane(textPanel); } @Override @@ -165,25 +130,7 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data @Override public boolean isSupported(Node node) { - BlackboardArtifact artifact = node.getLookup().lookup(BlackboardArtifact.class); - - try { - if (artifact != null) { - if (artifact.getSleuthkitCase().getAbstractFileById(artifact.getObjectID()) != null) { - return true; - } - } else { - if (node.getLookup().lookup(AbstractFile.class) != null) { - return true; - } - } - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, String.format( - "Exception while trying to retrieve a Content instance from the BlackboardArtifact '%s' (id=%d).", - artifact.getDisplayName(), artifact.getArtifactID()), ex); - } - - return false; + return node != null && node.getLookup().lookup(AbstractFile.class) != null; } @Override @@ -223,7 +170,7 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data if(doc != null) { return doc.html(); } else { - return Bundle.AnnotationsContentViewer_onEmpty(); + return "" + Bundle.AnnotationsContentViewer_onEmpty() + ""; } } @@ -235,6 +182,7 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data try { String text = get(); + ContentViewerHtmlStyles.setStyles(textPanel); textPanel.setText(text); textPanel.setCaretPosition(0); } catch (InterruptedException | ExecutionException ex) { diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties-MERGED index 4714416d46..d17c1766d6 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties-MERGED @@ -70,6 +70,7 @@ MediaViewVideoPanel.progressLabel.text=00:00 MediaViewVideoPanel.infoLabel.text=info MediaViewImagePanel.imgFileTooLarge.msg=Could not load image file (too large): {0} +Metadata.headerTitle=Metadata Metadata.nodeText.loading=Metadata loading... Metadata.nodeText.none=None Metadata.nodeText.truncated=(results truncated) @@ -105,6 +106,8 @@ Metadata.nodeText.exceptionNotice.text=Error getting file metadata: MessageArtifactViewer.textbodyScrollPane.TabConstraints.tabTitle=Text JPEGViewerDummy.jLabel1.text=You are looking at a JPEG file: JPEGViewerDummy.jTextField1.text=jTextField1 +Metadata_dataArtifactTitle=Source File Metadata +MetadataWorker.doInBackground.noDataMsg=No Data PDFViewer.encryptedDialog=This document is password protected. PDFViewer.errorDialog=An error occurred while opening this PDF document. Check the logs for more information. You may continue to use this feature on other PDF documents. PListNode.KeyCol=Key diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle_ja.properties index 8ebdcdfe58..5369a796b2 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle_ja.properties @@ -1,20 +1,5 @@ -#Fri Feb 12 16:56:28 UTC 2021 -AnnotationsContentViewer.centralRepositoryEntry.title=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u306e\u30b3\u30e1\u30f3\u30c8 -AnnotationsContentViewer.centralRepositoryEntryDataLabel.case=\u30b1\u30fc\u30b9\: -AnnotationsContentViewer.centralRepositoryEntryDataLabel.comment=\u30b3\u30e1\u30f3\u30c8\: -AnnotationsContentViewer.centralRepositoryEntryDataLabel.path=\u30d1\u30b9\: -AnnotationsContentViewer.centralRepositoryEntryDataLabel.type=\u30bf\u30a4\u30d7\: -AnnotationsContentViewer.fileHitEntry.artifactCommentTitle=\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u30b3\u30e1\u30f3\u30c8 -AnnotationsContentViewer.fileHitEntry.comment=\u30b3\u30e1\u30f3\u30c8\uff1a -AnnotationsContentViewer.fileHitEntry.hashSetHitTitle=\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u30fb\u30d2\u30c3\u30c8\u30b3\u30e1\u30f3\u30c8 -AnnotationsContentViewer.fileHitEntry.interestingFileHitTitle=\u8208\u5473\u6df1\u3044\u30d5\u30a1\u30a4\u30eb\u30d2\u30c3\u30c8\u30b3\u30e1\u30f3\u30c8 -AnnotationsContentViewer.fileHitEntry.setName=\u30bb\u30c3\u30c8\u540d\uff1a +#Mon Jul 12 13:21:59 UTC 2021 AnnotationsContentViewer.onEmpty=\u3053\u306e\u30a2\u30a4\u30c6\u30e0\u306e\u6ce8\u91c8\u306f\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f\u3002 -AnnotationsContentViewer.sourceFile.title=\u30bd\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb -AnnotationsContentViewer.tagEntry.title=\u30bf\u30b0 -AnnotationsContentViewer.tagEntryDataLabel.comment=\u30b3\u30e1\u30f3\u30c8\: -AnnotationsContentViewer.tagEntryDataLabel.tag=\u30bf\u30b0\: -AnnotationsContentViewer.tagEntryDataLabel.tagUser=\u5be9\u67fb\u5b98\uff1a AnnotationsContentViewer.title=\u30a2\u30ce\u30c6\u30fc\u30b7\u30e7\u30f3 AnnotationsContentViewer.toolTip=\u9078\u629e\u3057\u305f\u30b3\u30f3\u30c6\u30f3\u30c4\u3068\u95a2\u9023\u4ed8\u3051\u3089\u308c\u3066\u3044\u308b\u30bf\u30b0\u3068\u30b3\u30e1\u30f3\u30c8\u3092\u8868\u793a\u3057\u307e\u3059\u3002 ApplicationContentViewer.title=\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 @@ -43,6 +28,7 @@ GstVideoPanel.setupVideo.infoLabel.text=\u524a\u9664\u3057\u305f\u52d5\u753b\u30 HtmlPanel.showImagesToggleButton.text=\u30a4\u30e1\u30fc\u30b8\u3092\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9 HtmlPanel_showImagesToggleButton_hide=\u30a4\u30e1\u30fc\u30b8\u3092\u975e\u8868\u793a\u306b\u3059\u308b HtmlPanel_showImagesToggleButton_show=\u30a4\u30e1\u30fc\u30b8\u3092\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9 +HtmlViewer_encoding_error=\u3059\u3079\u3066\u306e\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u8868\u793a HtmlViewer_file_error=\u3053\u306e\u30d5\u30a1\u30a4\u30eb\u306f\u898b\u3064\u304b\u3089\u306a\u3044\u304b\u3001\u89e3\u8aad\u3067\u304d\u307e\u305b\u3093\u3002 Html_text_display_error=HTML\u30c6\u30ad\u30b9\u30c8\u3092\u8868\u793a\u3067\u304d\u307e\u305b\u3093\u3002 \u6b63\u3057\u304f\u30d5\u30a9\u30fc\u30de\u30c3\u30c8\u3055\u308c\u305fHTML\u3067\u306a\u3044\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 JPEGViewerDummy.jLabel1.text=JPEG\u30d5\u30a1\u30a4\u30eb\u304c\u8868\u793a\u3055\u308c\u3066\u3044\u307e\u3059\: @@ -55,6 +41,7 @@ MediaPlayerPanel.VolumeIcon.text=\ \u30dc\u30ea\u30e5\u30fc\u30e0 MediaPlayerPanel.audioSlider.toolTipText= MediaPlayerPanel.infoLabel.text=\u30a8\u30e9\u30fc\u306a\u3057 MediaPlayerPanel.noSupport=\u30b5\u30dd\u30fc\u30c8\u3055\u308c\u3066\u3044\u306a\u3044\u30d5\u30a1\u30a4\u30eb\u3067\u3059\u3002 +MediaPlayerPanel.playBackSpeedLabel.text=\u901f\u5ea6\uff1a MediaPlayerPanel.playButton.text=\u25ba MediaPlayerPanel.playbackDisabled=\u30d3\u30c7\u30aa\u3068\u30aa\u30fc\u30c7\u30a3\u30aa\u306e\u518d\u751f\u3067\u554f\u984c\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 \u30bb\u30c3\u30b7\u30e7\u30f3\u306e\u6b8b\u308a\u306e\u671f\u9593\u3001\u30d3\u30c7\u30aa\u3068\u30aa\u30fc\u30c7\u30a3\u30aa\u306e\u518d\u751f\u306f\u7121\u52b9\u306b\u306a\u308a\u307e\u3059\u3002 MediaPlayerPanel.progressLabel.text=00\:00\:00/00\:00\:00 @@ -86,6 +73,7 @@ MediaViewVideoPanel.pauseButton.text=\u25ba MediaViewVideoPanel.progressLabel.text=00\:00 MessageArtifactViewer.textbodyScrollPane.TabConstraints.tabTitle=\u30c6\u30ad\u30b9\u30c8 Metadata.nodeText.exceptionNotice.text=\u30d5\u30a1\u30a4\u30eb\u306e\u30e1\u30bf\u30c7\u30fc\u30bf\u3092\u53d6\u5f97\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\: +Metadata.nodeText.loading=\u30e1\u30bf\u30c7\u30fc\u30bf\u306e\u8aad\u8fbc\u4e2d... Metadata.nodeText.nonFilePassedIn=\u30d5\u30a1\u30a4\u30eb\u4ee5\u5916\u306e\u3082\u306e\u304c\u901a\u904e\u3057\u307e\u3057\u305f Metadata.nodeText.none=\u306a\u3057 Metadata.nodeText.text=\u9001\u4fe1\u5143\u306eSleuth Kit\u306eistat\u30c4\u30fc\u30eb\: @@ -116,6 +104,7 @@ Metadata.tableRowTitle.timezone=\u30bf\u30a4\u30e0\u30be\u30fc\u30f3 Metadata.tableRowTitle.type=\u30bf\u30a4\u30d7 Metadata.title=\u30d5\u30a1\u30a4\u30eb\u306e\u30e1\u30bf\u30c7\u30fc\u30bf Metadata.toolTip=\u30d5\u30a1\u30a4\u30eb\u306e\u30e1\u30bf\u30c7\u30fc\u30bf\u3092\u8868\u793a\u3057\u307e\u3059\u3002 +Metadata_dataArtifactTitle=\u30bd\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb\u306e\u30e1\u30bf\u30c7\u30fc\u30bf PDFViewer.encryptedDialog=\u3053\u306e\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8\u306f\u30d1\u30b9\u30ef\u30fc\u30c9\u3067\u4fdd\u8b77\u3055\u308c\u3066\u3044\u307e\u3059\u3002 PDFViewer.errorDialog=PDF\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8\u3092\u958b\u304f\u3068\u304d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 \u8a73\u7d30\u306b\u3064\u3044\u3066\u306f\u3001\u30ed\u30b0\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002 \u3053\u306e\u6a5f\u80fd\u306f\u3001\u4ed6\u306ePDF\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8\u3067\u5f15\u304d\u7d9a\u304d\u4f7f\u7528\u3067\u304d\u307e\u3059\u3002 PListNode.KeyCol=\u30ad\u30fc @@ -227,6 +216,7 @@ viewer.annotation.signature.validation.common.doc.unmodified.label=- \u7f72\u540 viewer.annotation.signature.validation.common.identity.unchecked.label=-\u7f72\u540d\u306f\u6709\u52b9\u3067\u3059\u304c\u3001ID\u306e\u5931\u52b9\u3092\u78ba\u8a8d\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f viewer.annotation.signature.validation.common.identity.unknown.label=- \u7f72\u540d\u8005\u306eID\u306f\u4e0d\u660e\u3067\u3059\u3001\u30ad\u30fc\u30b9\u30c8\u30a2\u306b\u5b58\u5728\u3057\u307e\u305b\u3093\u3002 viewer.annotation.signature.validation.common.identity.valid.label=-\u7f72\u540d\u8005\u306eID\u306f\u6709\u52b9\u3067\u3059 +viewer.annotation.signature.validation.common.invalid.label=\u7f72\u540d\u304c\u7121\u52b9\u3067\u3059\uff1a viewer.annotation.signature.validation.common.notAvailable.label=\u8a72\u5f53\u306a\u3057 viewer.annotation.signature.validation.common.signedBy.label=-{0} {1}\u306b\u3088\u308b\u7f72\u540d viewer.annotation.signature.validation.common.time.embedded.label=-\u7f72\u540d\u306b\u30bf\u30a4\u30e0\u30b9\u30bf\u30f3\u30d7\u304c\u542b\u307e\u308c\u3066\u3044\u307e\u3057\u305f\u304c\u3001\u691c\u8a3c\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/MediaViewImagePanel.java b/Core/src/org/sleuthkit/autopsy/contentviewers/MediaViewImagePanel.java index 06b0a42fb7..177c397c78 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/MediaViewImagePanel.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/MediaViewImagePanel.java @@ -34,6 +34,9 @@ import java.util.Collections; import java.util.List; import static java.util.Objects.nonNull; import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.FutureTask; import java.util.logging.Level; import java.util.stream.Collectors; import javafx.application.Platform; @@ -150,7 +153,7 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan @ThreadConfined(type = ThreadConfined.ThreadType.AWT) private final JMenuItem exportTagsMenuItem; @ThreadConfined(type = ThreadConfined.ThreadType.AWT) - private final JFileChooser exportChooser; + private JFileChooser exportChooser; @ThreadConfined(type = ThreadConfined.ThreadType.AWT) private final JFXPanel fxPanel; @@ -189,10 +192,10 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan @ThreadConfined(type = ThreadConfined.ThreadType.JFX) private Task readImageFileTask; private volatile ImageTransforms imageTransforms; - - static { - ImageIO.scanForPlugins(); - } + + // Initializing the JFileChooser in a thread to prevent a block on the EDT + // see https://stackoverflow.com/questions/49792375/jfilechooser-is-very-slow-when-using-windows-look-and-feel + private final FutureTask futureFileChooser = new FutureTask<>(JFileChooser::new); /** * Constructs a media image file viewer implemented as a Swing panel that @@ -210,9 +213,9 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan initComponents(); imageTransforms = new ImageTransforms(0, 0, true); - - exportChooser = new JFileChooser(); - exportChooser.setDialogTitle(Bundle.MediaViewImagePanel_fileChooserTitle()); + + ExecutorService executor = Executors.newSingleThreadExecutor(); + executor.execute(futureFileChooser); //Build popupMenu when Tags Menu button is pressed. imageTaggingOptions = new JPopupMenu(); @@ -1043,6 +1046,18 @@ class MediaViewImagePanel extends JPanel implements MediaFileViewer.MediaViewPan final AbstractFile file = imageFile; tagsGroup.clearFocus(); SwingUtilities.invokeLater(() -> { + + if(exportChooser == null) { + try { + exportChooser = futureFileChooser.get(); + } catch (InterruptedException | ExecutionException ex) { + // If something happened with the thread try and + // initalized the chooser now + logger.log(Level.WARNING, "A failure occurred in the JFileChooser background thread"); + exportChooser = new JFileChooser(); + } + } + exportChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); //Always base chooser location to export folder exportChooser.setCurrentDirectory(new File(Case.getCurrentCase().getExportDirectory())); diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/Metadata.form b/Core/src/org/sleuthkit/autopsy/contentviewers/Metadata.form index b175b6b512..8e6f123911 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/Metadata.form +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/Metadata.form @@ -41,8 +41,6 @@ - - diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/Metadata.java b/Core/src/org/sleuthkit/autopsy/contentviewers/Metadata.java index 2c695dfcb4..be7b093d0e 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/Metadata.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/Metadata.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013-2018 Basis Technology Corp. + * Copyright 2013-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,24 +20,30 @@ package org.sleuthkit.autopsy.contentviewers; import java.awt.Component; import java.awt.Cursor; +import java.text.MessageFormat; +import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.logging.Level; +import java.util.stream.Stream; import javax.swing.SwingWorker; import org.apache.commons.lang3.StringUtils; import org.openide.nodes.Node; -import org.openide.util.Exceptions; import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; import org.openide.util.lookup.ServiceProvider; +import org.sleuthkit.autopsy.contentviewers.layout.ContentViewerHtmlStyles; import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer; -import org.sleuthkit.autopsy.datamodel.ContentUtils; +import org.sleuthkit.autopsy.coreutils.EscapeUtil; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.TimeZoneUtils; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE; +import org.sleuthkit.datamodel.DataArtifact; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.Image; import org.sleuthkit.datamodel.FsContent; @@ -49,7 +55,7 @@ import org.sleuthkit.datamodel.TskData.TSK_DB_FILES_TYPE_ENUM; * shows the same data that can also be found in the ResultViewer table, just a * different order and allows the full path to be visible in the bottom area. */ -@ServiceProvider(service = DataContentViewer.class, position = 6) +@ServiceProvider(service = DataContentViewer.class, position = 4) @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives public class Metadata extends javax.swing.JPanel implements DataContentViewer { @@ -63,6 +69,7 @@ public class Metadata extends javax.swing.JPanel implements DataContentViewer { public Metadata() { initComponents(); customizeComponents(); + ContentViewerHtmlStyles.setupHtmlJTextPane(jTextPane1); } /** @@ -80,8 +87,6 @@ public class Metadata extends javax.swing.JPanel implements DataContentViewer { setPreferredSize(new java.awt.Dimension(100, 52)); - jScrollPane2.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); - jScrollPane2.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); jScrollPane2.setPreferredSize(new java.awt.Dimension(610, 52)); jTextPane1.setEditable(false); @@ -116,30 +121,59 @@ public class Metadata extends javax.swing.JPanel implements DataContentViewer { * selectAllMenuItem.addActionListener(actList); */ - Utilities.configureTextPaneAsHtml(jTextPane1); } private void setText(String str) { - jTextPane1.setText("" + str + ""); //NON-NLS + ContentViewerHtmlStyles.setupHtmlJTextPane(jTextPane1); + jTextPane1.setText("" + str + ""); //NON-NLS + } + + private void addHeader(StringBuilder sb, String header, boolean spaced) { + sb.append(MessageFormat.format("

{2}

", + (spaced) ? ContentViewerHtmlStyles.getSpacedSectionClassName() : "", + ContentViewerHtmlStyles.getHeaderClassName(), + header)); } private void startTable(StringBuilder sb) { - sb.append(""); //NON-NLS + sb.append(MessageFormat.format("
", + ContentViewerHtmlStyles.getIndentedClassName())); //NON-NLS } private void endTable(StringBuilder sb) { - sb.append("
"); //NON-NLS + sb.append(""); //NON-NLS } private void addRow(StringBuilder sb, String key, String value) { - sb.append(""); //NON-NLS - sb.append(key); - sb.append(""); //NON-NLS - sb.append(value); - sb.append(""); //NON-NLS + sb.append(MessageFormat.format("{2}:{4}", + ContentViewerHtmlStyles.getKeyColumnClassName(), + ContentViewerHtmlStyles.getTextClassName(), + EscapeUtil.escapeHtml(key), + ContentViewerHtmlStyles.getTextClassName(), + EscapeUtil.escapeHtml(value) + )); + } + + private void addMonospacedRow(StringBuilder sb, String key) { + sb.append(MessageFormat.format("{2}", + ContentViewerHtmlStyles.getKeyColumnClassName(), + ContentViewerHtmlStyles.getMonospacedClassName(), + EscapeUtil.escapeHtml(key) + )); + } + + private void addRowWithMultipleValues(StringBuilder sb, String key, String[] values) { + String[] safeValues = values == null || values.length < 1 ? new String[]{""} : values; + + addRow(sb, key, safeValues[0]); + Stream.of(safeValues) + .skip(1) + .filter(line -> line != null) + .forEach(line -> addRow(sb, "", EscapeUtil.escapeHtml(line))); } @Messages({ + "Metadata.headerTitle=Metadata", "Metadata.tableRowTitle.mimeType=MIME Type", "Metadata.nodeText.truncated=(results truncated)", "Metadata.tableRowTitle.sha1=SHA1", @@ -219,8 +253,11 @@ public class Metadata extends javax.swing.JPanel implements DataContentViewer { if (StringUtils.isEmpty(details)) { details = Bundle.Metadata_nodeText_unknown(); } - details = details.replaceAll("\n", "
"); - addRow(sb, NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.acquisitionDetails"), details); + String[] lines = (details != null) ? details.split("\n") : new String[]{""}; + addRowWithMultipleValues(sb, + NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.acquisitionDetails"), + lines); + } catch (TskCoreException ex) { LOGGER.log(Level.SEVERE, "Error reading acquisition details from case database", ex); //NON-NLS } @@ -229,7 +266,19 @@ public class Metadata extends javax.swing.JPanel implements DataContentViewer { @Override public String getTitle() { - return NbBundle.getMessage(this.getClass(), "Metadata.title"); + return getTitle(null); + } + + @Messages({ + "Metadata_dataArtifactTitle=Source File Metadata" + }) + @Override + public String getTitle(Node node) { + if (node != null && !node.getLookup().lookupAll(DataArtifact.class).isEmpty()) { + return Bundle.Metadata_dataArtifactTitle(); + } else { + return NbBundle.getMessage(this.getClass(), "Metadata.title"); + } } @Override @@ -275,6 +324,7 @@ public class Metadata extends javax.swing.JPanel implements DataContentViewer { this.node = node; } + @Messages("MetadataWorker.doInBackground.noDataMsg=No Data") @Override protected String doInBackground() throws Exception { AbstractFile file = node.getLookup().lookup(AbstractFile.class); @@ -285,6 +335,7 @@ public class Metadata extends javax.swing.JPanel implements DataContentViewer { } StringBuilder sb = new StringBuilder(); + addHeader(sb, Bundle.Metadata_headerTitle(), false); startTable(sb); if (file != null) { @@ -299,10 +350,10 @@ public class Metadata extends javax.swing.JPanel implements DataContentViewer { addRow(sb, NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.size"), Long.toString(file.getSize())); addRow(sb, NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.fileNameAlloc"), file.getDirFlagAsString()); addRow(sb, NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.metadataAlloc"), file.getMetaFlagsAsString()); - addRow(sb, NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.modified"), ContentUtils.getStringTime(file.getMtime(), file)); - addRow(sb, NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.accessed"), ContentUtils.getStringTime(file.getAtime(), file)); - addRow(sb, NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.created"), ContentUtils.getStringTime(file.getCrtime(), file)); - addRow(sb, NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.changed"), ContentUtils.getStringTime(file.getCtime(), file)); + addRow(sb, NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.modified"), TimeZoneUtils.getFormattedTime(file.getMtime())); + addRow(sb, NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.accessed"), TimeZoneUtils.getFormattedTime(file.getAtime())); + addRow(sb, NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.created"), TimeZoneUtils.getFormattedTime(file.getCrtime())); + addRow(sb, NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.changed"), TimeZoneUtils.getFormattedTime(file.getCtime())); String md5 = file.getMd5Hash(); if (md5 == null) { @@ -343,30 +394,43 @@ public class Metadata extends javax.swing.JPanel implements DataContentViewer { * If we have a file system file, grab the more detailed * metadata text too */ - try { - if (file instanceof FsContent) { - FsContent fsFile = (FsContent) file; + if (file instanceof FsContent) { + FsContent fsFile = (FsContent) file; - sb.append("
\n"); //NON-NLS
-                        sb.append(NbBundle.getMessage(this.getClass(), "Metadata.nodeText.text"));
-                        sb.append(" 

"); // NON-NLS - for (String str : fsFile.getMetaDataText()) { - sb.append(str).append("
"); //NON-NLS + addHeader(sb, NbBundle.getMessage(this.getClass(), "Metadata.nodeText.text"), true); + + List istatStrings = Collections.emptyList(); + try { + istatStrings = fsFile.getMetaDataText(); + } catch (TskCoreException ex) { + istatStrings = Arrays.asList(NbBundle.getMessage(this.getClass(), "Metadata.nodeText.exceptionNotice.text") + ex.getLocalizedMessage()); + } + + if (istatStrings.isEmpty() || (istatStrings.size() == 1 && StringUtils.isEmpty(istatStrings.get(0)))) { + sb.append(MessageFormat.format("

{2}

", + ContentViewerHtmlStyles.getIndentedClassName(), + ContentViewerHtmlStyles.getTextClassName(), + Bundle.MetadataWorker_doInBackground_noDataMsg())); + } else { + startTable(sb); + + for (String str : istatStrings) { + addMonospacedRow(sb, str); /* * Very long results can cause the UI to hang before * displaying, so truncate the results if necessary. */ if (sb.length() > 50000) { - sb.append(NbBundle.getMessage(this.getClass(), "Metadata.nodeText.truncated")); + addMonospacedRow(sb, NbBundle.getMessage(this.getClass(), "Metadata.nodeText.truncated")); break; } } - sb.append("
\n"); //NON-NLS + + endTable(sb); } - } catch (TskCoreException ex) { - sb.append(NbBundle.getMessage(this.getClass(), "Metadata.nodeText.exceptionNotice.text")).append(ex.getLocalizedMessage()); } + } else { try { addRow(sb, NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.name"), image.getUniquePath()); @@ -405,20 +469,17 @@ public class Metadata extends javax.swing.JPanel implements DataContentViewer { // Add all the data source paths to the "Local Path" value cell. String[] imagePaths = image.getPaths(); + if (imagePaths.length > 0) { - StringBuilder pathValues = new StringBuilder("
"); - pathValues.append(imagePaths[0]); - pathValues.append("
"); - for (int i = 1; i < imagePaths.length; i++) { - pathValues.append("
"); - pathValues.append(imagePaths[i]); - pathValues.append("
"); - } - addRow(sb, NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.localPath"), pathValues.toString()); + addRowWithMultipleValues(sb, + NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.localPath"), + imagePaths); } else { addRow(sb, NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.localPath"), NbBundle.getMessage(this.getClass(), "Metadata.nodeText.none")); } + + endTable(sb); } if (isCancelled()) { diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/AnalysisResultsContentPanel.form b/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/AnalysisResultsContentPanel.form new file mode 100644 index 0000000000..98fb50c89a --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/AnalysisResultsContentPanel.form @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/AnalysisResultsContentPanel.java b/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/AnalysisResultsContentPanel.java new file mode 100644 index 0000000000..d19cf80b5c --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/AnalysisResultsContentPanel.java @@ -0,0 +1,285 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2021 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may 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.contentviewers.analysisresults; + +import java.text.MessageFormat; +import java.util.List; +import java.util.Optional; +import org.apache.commons.lang3.tuple.Pair; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.openide.util.NbBundle; +import org.openide.util.NbBundle.Messages; +import org.sleuthkit.autopsy.contentviewers.analysisresults.AnalysisResultsViewModel.NodeResults; +import org.sleuthkit.autopsy.contentviewers.analysisresults.AnalysisResultsViewModel.ResultDisplayAttributes; +import org.sleuthkit.autopsy.contentviewers.layout.ContentViewerHtmlStyles; +import org.sleuthkit.autopsy.coreutils.EscapeUtil; +import org.sleuthkit.datamodel.AnalysisResult; +import org.sleuthkit.datamodel.Content; +import org.sleuthkit.datamodel.Score; + +/** + * Displays a list of analysis results in a panel. + */ +public class AnalysisResultsContentPanel extends javax.swing.JPanel { + + private static final long serialVersionUID = 1L; + + private static final String EMPTY_HTML = ""; + + // Anchors are inserted into the navigation so that the viewer can navigate to a selection. + // This is the prefix of those anchors. + private static final String RESULT_ANCHOR_PREFIX = "AnalysisResult_"; + + /** + * Creates new form AnalysisResultsContentViewer + */ + public AnalysisResultsContentPanel() { + initComponents(); + ContentViewerHtmlStyles.setupHtmlJTextPane(textPanel); + } + + /** + * Clears current text and shows text provided in the message. + * + * @param message The message to be displayed. + */ + void showMessage(String message) { + ContentViewerHtmlStyles.setStyles(textPanel); + textPanel.setText("" + + MessageFormat.format("

{1}

", + ContentViewerHtmlStyles.getMessageClassName(), + message == null ? "" : EscapeUtil.escapeHtml(message)) + + ""); + } + + /** + * Resets the current view and displays nothing. + */ + void reset() { + textPanel.setText(EMPTY_HTML); + } + + /** + * Displays analysis results for the node in the text pane. + * + * @param nodeResults The analysis results data to display. + */ + void displayResults(NodeResults nodeResults) { + Document document = Jsoup.parse(EMPTY_HTML); + Element body = document.getElementsByTag("body").first(); + + Optional panelHeader = appendPanelHeader(body, nodeResults.getContent(), nodeResults.getAggregateScore()); + + // for each analysis result item, display the data. + List displayAttributes = nodeResults.getAnalysisResults(); + for (int idx = 0; idx < displayAttributes.size(); idx++) { + AnalysisResultsViewModel.ResultDisplayAttributes resultAttrs = displayAttributes.get(idx); + Element sectionDiv = appendResult(body, idx, resultAttrs); + if (idx > 0 || panelHeader.isPresent()) { + sectionDiv.attr("class", ContentViewerHtmlStyles.getSpacedSectionClassName()); + } + } + + // set the body html + ContentViewerHtmlStyles.setStyles(textPanel); + textPanel.setText(document.html()); + + // if there is a selected result scroll to it + Optional selectedResult = nodeResults.getSelectedResult(); + if (selectedResult.isPresent()) { + textPanel.scrollToReference(getAnchor(selectedResult.get())); + } else { + // otherwise, scroll to the beginning. + textPanel.setCaretPosition(0); + } + } + + /** + * Appends the header to the panel. + * + * @param parent The parent html element. + * @param content The content whose name will be added if present. + * @param score The aggregate score whose significance will be added if + * present. + * + * @return The html element. + */ + @Messages({ + "AnalysisResultsContentPanel_aggregateScore_displayKey=Aggregate Score", + "AnalysisResultsContentPanel_content_displayKey=Item" + }) + private Optional appendPanelHeader(Element parent, Optional content, Optional score) { + if (!content.isPresent() || !score.isPresent()) { + return Optional.empty(); + } + + Element container = parent.appendElement("div"); + + // if there is content append the name + content.ifPresent((c) -> { + container.appendElement("p") + .attr("class", ContentViewerHtmlStyles.getTextClassName()) + .text(MessageFormat.format("{0}: {1}", + Bundle.AnalysisResultsContentPanel_content_displayKey(), + c.getName())); + }); + + // if there is an aggregate score, append the value + score.ifPresent((s) -> { + container.appendElement("p") + .attr("class", ContentViewerHtmlStyles.getTextClassName()) + .text(MessageFormat.format("{0}: {1}", + Bundle.AnalysisResultsContentPanel_aggregateScore_displayKey(), + s.getSignificance().getDisplayName())); + }); + + return Optional.ofNullable(container); + } + + /** + * Returns the anchor id to use with the analysis result (based on the id). + * + * @param analysisResult The analysis result. + * + * @return The anchor id. + */ + private String getAnchor(AnalysisResult analysisResult) { + return RESULT_ANCHOR_PREFIX + analysisResult.getId(); + } + + /** + * Appends a result item to the parent element of an html document. + * + * @param parent The parent element. + * @param index The index of the item in the list of all items. + * @param attrs The attributes of this item. + * + * @return The result div. + */ + @NbBundle.Messages({"# {0} - analysisResultsNumber", + "AnalysisResultsContentPanel_result_headerKey=Analysis Result {0}" + }) + private Element appendResult(Element parent, int index, AnalysisResultsViewModel.ResultDisplayAttributes attrs) { + // create a new section with appropriate header + Element sectionDiv = appendSection(parent, + Bundle.AnalysisResultsContentPanel_result_headerKey(index + 1), + Optional.ofNullable(getAnchor(attrs.getAnalysisResult()))); + + // create a table + Element table = sectionDiv.appendElement("table") + .attr("valign", "top") + .attr("align", "left"); + + table.attr("class", ContentViewerHtmlStyles.getIndentedClassName()); + + Element tableBody = table.appendElement("tbody"); + + // append a row for each item + for (Pair keyVal : attrs.getAttributesToDisplay()) { + Element row = tableBody.appendElement("tr"); + String keyString = keyVal.getKey() == null ? "" : keyVal.getKey() + ":"; + Element keyTd = row.appendElement("td") + .attr("class", ContentViewerHtmlStyles.getKeyColumnClassName()); + + keyTd.appendElement("span") + .text(keyString) + .attr("class", ContentViewerHtmlStyles.getTextClassName()); + + String valueString = keyVal.getValue() == null ? "" : keyVal.getValue(); + row.appendElement("td") + .text(valueString) + .attr("class", ContentViewerHtmlStyles.getTextClassName()); + } + + return sectionDiv; + } + + /** + * Appends a new section with a section header to the parent element. + * + * @param parent The element to append this section to. + * @param headerText The text for the section. + * @param anchorId The anchor id for this section. + * + * @return The div for the new section. + */ + private Element appendSection(Element parent, String headerText, Optional anchorId) { + Element sectionDiv = parent.appendElement("div"); + + // append an anchor tag if there is one + Element anchorEl = null; + if (anchorId.isPresent()) { + anchorEl = sectionDiv.appendElement("a"); + anchorEl.attr("name", anchorId.get()); + anchorEl.attr("style", "padding: 0px; margin: 0px; display: inline-block;"); + } + + // append the header + Element header = null; + header = (anchorEl == null) + ? sectionDiv.appendElement("h1") + : anchorEl.appendElement("h1"); + + header.text(headerText); + header.attr("class", ContentViewerHtmlStyles.getHeaderClassName()); + header.attr("style", "display: inline-block"); + + // return the section element + return sectionDiv; + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + javax.swing.JScrollPane scrollPane = new javax.swing.JScrollPane(); + textPanel = new javax.swing.JTextPane(); + + setPreferredSize(new java.awt.Dimension(100, 58)); + + textPanel.setEditable(false); + textPanel.setName(""); // NOI18N + textPanel.setPreferredSize(new java.awt.Dimension(600, 52)); + scrollPane.setViewportView(textPanel); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(scrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 907, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(scrollPane, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 435, Short.MAX_VALUE) + ); + }// //GEN-END:initComponents + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JTextPane textPanel; + // End of variables declaration//GEN-END:variables + +} diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/AnalysisResultsContentViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/AnalysisResultsContentViewer.java new file mode 100644 index 0000000000..f853eae777 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/AnalysisResultsContentViewer.java @@ -0,0 +1,159 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2021 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may 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.contentviewers.analysisresults; + +import java.awt.Component; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.SwingWorker; +import org.openide.nodes.Node; +import org.openide.util.NbBundle; +import org.openide.util.lookup.ServiceProvider; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; +import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer; +import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult; +import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchWorker; +import org.sleuthkit.datamodel.AnalysisResult; +import org.sleuthkit.datamodel.BlackboardArtifact; +import org.sleuthkit.datamodel.Content; +import org.sleuthkit.datamodel.TskCoreException; + +/** + * Displays a list of analysis results as a content viewer. + */ +@ServiceProvider(service = DataContentViewer.class, position = 7) +public class AnalysisResultsContentViewer implements DataContentViewer { + private static final Logger logger = Logger.getLogger(AnalysisResultsContentPanel.class.getName()); + + // isPreferred value + private static final int PREFERRED_VALUE = 6; + + private final AnalysisResultsViewModel viewModel = new AnalysisResultsViewModel(); + private final AnalysisResultsContentPanel panel = new AnalysisResultsContentPanel(); + + private SwingWorker worker = null; + + + + @NbBundle.Messages({ + "AnalysisResultsContentViewer_title=Analysis Results" + }) + @Override + public String getTitle() { + return Bundle.AnalysisResultsContentViewer_title(); + } + + @NbBundle.Messages({ + "AnalysisResultsContentViewer_tooltip=Viewer for Analysis Results related to the selected node." + }) + @Override + public String getToolTip() { + return Bundle.AnalysisResultsContentViewer_tooltip(); + } + + @Override + public DataContentViewer createInstance() { + return new AnalysisResultsContentViewer(); + } + + @Override + public Component getComponent() { + return panel; + } + + @Override + public void resetComponent() { + panel.reset(); + } + + @Override + @NbBundle.Messages({ + "AnalysisResultsContentViewer_setNode_loadingMessage=Loading...", + "AnalysisResultsContentViewer_setNode_errorMessage=There was an error loading results.",}) + public synchronized void setNode(Node node) { + // reset the panel + panel.reset(); + + // if there is a worker running, cancel it + if (worker != null) { + worker.cancel(true); + worker = null; + } + + // if no node, nothing to do + if (node == null) { + return; + } + + // show a loading message + panel.showMessage(Bundle.AnalysisResultsContentViewer_setNode_loadingMessage()); + + // create the worker + worker = new DataFetchWorker<>( + // load a view model from the node + (selectedNode) -> viewModel.getAnalysisResults(selectedNode), + (nodeAnalysisResults) -> { + if (nodeAnalysisResults.getResultType() == DataFetchResult.ResultType.SUCCESS) { + // if successful, display the results + panel.displayResults(nodeAnalysisResults.getData()); + } else { + // if there was an error, display an error message + panel.showMessage(Bundle.AnalysisResultsContentViewer_setNode_errorMessage()); + } + }, + node); + + // kick off the swing worker + worker.execute(); + } + + @Override + public boolean isSupported(Node node) { + if (node == null) { + return false; + } + + // There needs to either be a file with an AnalysisResult or an AnalysisResult in the lookup. + for (Content content : node.getLookup().lookupAll(Content.class)) { + if (content instanceof AnalysisResult) { + return true; + } + + if (content == null || content instanceof BlackboardArtifact) { + continue; + } + + try { + if (Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboard().hasAnalysisResults(content.getId())) { + return true; + } + } catch (NoCurrentCaseException | TskCoreException ex) { + logger.log(Level.SEVERE, "Unable to get analysis results for file with obj id " + content.getId(), ex); + } + } + + return false; + } + + @Override + public int isPreferred(Node node) { + return PREFERRED_VALUE; + } +} diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/AnalysisResultsViewModel.java b/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/AnalysisResultsViewModel.java new file mode 100644 index 0000000000..00cc170b14 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/AnalysisResultsViewModel.java @@ -0,0 +1,295 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2021 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may 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.contentviewers.analysisresults; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.apache.commons.lang3.tuple.Pair; +import org.openide.nodes.Node; +import org.openide.util.NbBundle; +import org.sleuthkit.datamodel.AnalysisResult; +import org.sleuthkit.datamodel.BlackboardArtifact; +import org.sleuthkit.datamodel.Content; +import org.sleuthkit.datamodel.Score; +import org.sleuthkit.datamodel.TskCoreException; + +/** + * + * Creates a representation of a list of analysis results gathered from a node. + */ +public class AnalysisResultsViewModel { + + private static final Logger logger = Logger.getLogger(AnalysisResultsViewModel.class.getName()); + + /** + * The attributes to display for a particular Analysis Result. + */ + static class ResultDisplayAttributes { + + private final AnalysisResult analysisResult; + private final List> attributesToDisplay; + + /** + * Constructor. + * + * @param analysisResult The analysis result which these attributes + * describe. + * @param attributesToDisplay The attributes to display in the order + * they should be displayed. + */ + ResultDisplayAttributes(AnalysisResult analysisResult, List> attributesToDisplay) { + this.analysisResult = analysisResult; + this.attributesToDisplay = attributesToDisplay; + } + + /** + * Returns the attributes to display. + * + * @return The attributes to display. + */ + List> getAttributesToDisplay() { + return attributesToDisplay; + } + + /** + * Returns the analysis result which these attributes describe. + * + * @return The analysis result. + */ + AnalysisResult getAnalysisResult() { + return analysisResult; + } + } + + /** + * The analysis results relating to a node (i.e. belonging to source content + * or directly in the lookup) to be displayed. + */ + static class NodeResults { + + private final List analysisResults; + private final Optional selectedResult; + private final Optional aggregateScore; + private final Optional content; + + /** + * Constructor. + * + * @param analysisResults The analysis results to be displayed. + * @param selectedResult The selected analysis result or empty if none + * selected. + * @param aggregateScore The aggregate score or empty if no score. + * @param content The content associated with these results. + */ + NodeResults(List analysisResults, Optional selectedResult, Optional aggregateScore, Optional content) { + this.analysisResults = analysisResults; + this.selectedResult = selectedResult; + this.aggregateScore = aggregateScore; + this.content = content; + } + + /** + * Returns the analysis results to be displayed. + * + * @return The analysis results to be displayed. + */ + List getAnalysisResults() { + return analysisResults; + } + + /** + * Returns the selected analysis result or empty if none selected. + * + * @return The selected analysis result or empty if none selected. + */ + Optional getSelectedResult() { + return selectedResult; + } + + /** + * Returns the aggregate score or empty if no score. + * + * @return The aggregate score or empty if no score. + */ + Optional getAggregateScore() { + return aggregateScore; + } + + /** + * Returns the content associated with these results or empty if not + * present. + * + * @return The content associated with these results or empty if not + * present. + */ + Optional getContent() { + return content; + } + } + + /** + * Normalizes the value of an attribute of an analysis result for display + * purposes. + * + * @param originalAttrStr The original attribute value. + * + * @return The normalized value for display. + */ + private String normalizeAttr(String originalAttrStr) { + return (originalAttrStr == null) ? "" : originalAttrStr.trim(); + } + + /** + * Returns the attributes to be displayed for an analysis result. + * + * @param analysisResult The analysis result. + * + * @return The attributes to be displayed. + */ + @NbBundle.Messages({ + "AnalysisResultsViewModel_displayAttributes_score=Score", + "AnalysisResultsViewModel_displayAttributes_type=Type", + "AnalysisResultsViewModel_displayAttributes_configuration=Configuration", + "AnalysisResultsViewModel_displayAttributes_conclusion=Conclusion" + }) + private ResultDisplayAttributes getDisplayAttributes(AnalysisResult analysisResult) { + // The type of BlackboardArtifact.Type of the analysis result. + String type = ""; + try { + type = normalizeAttr(analysisResult.getType().getDisplayName()); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Unable to get type for analysis result with id: " + analysisResult.getArtifactID(), ex); + } + + // The standard attributes to display (score, type, configuration, conclusion) + Stream> baseAnalysisAttrs = Stream.of( + Pair.of(Bundle.AnalysisResultsViewModel_displayAttributes_score(), + normalizeAttr(analysisResult.getScore().getSignificance().getDisplayName())), + Pair.of(Bundle.AnalysisResultsViewModel_displayAttributes_type(), + normalizeAttr(type)), + Pair.of(Bundle.AnalysisResultsViewModel_displayAttributes_configuration(), + normalizeAttr(analysisResult.getConfiguration())), + Pair.of(Bundle.AnalysisResultsViewModel_displayAttributes_conclusion(), + normalizeAttr(analysisResult.getConclusion())) + ); + + // The BlackboardAttributes sorted by type display name. + Stream> blackboardAttributes = Stream.empty(); + try { + + blackboardAttributes = analysisResult.getAttributes().stream() + .filter(attr -> attr != null && attr.getAttributeType() != null && attr.getAttributeType().getDisplayName() != null) + .map(attr -> Pair.of(attr.getAttributeType().getDisplayName(), normalizeAttr(attr.getDisplayString()))) + .sorted((a, b) -> a.getKey().compareToIgnoreCase(b.getKey())); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Unable to get attributes for analysis result with id: " + analysisResult.getArtifactID(), ex); + } + + // return the standard attributes along with the key value pairs of the BlackboardAttribute values. + List> allDisplayAttributes = Stream.concat(baseAnalysisAttrs, blackboardAttributes) + .collect(Collectors.toList()); + + return new ResultDisplayAttributes(analysisResult, allDisplayAttributes); + } + + private List getOrderedDisplayAttributes(Collection analysisResults) { + return analysisResults.stream() + .filter(ar -> ar != null && ar.getScore() != null) + // reverse order to push more important scores to the top + .sorted((a, b) -> -a.getScore().compareTo(b.getScore())) + .map((ar) -> getDisplayAttributes(ar)) + .collect(Collectors.toList()); + } + + /** + * Returns the view model data representing the analysis results to be + * displayed for the node. + * + * @param node The node. + * + * @return The analysis results view model data to display. + */ + NodeResults getAnalysisResults(Node node) { + if (node == null) { + return new NodeResults(Collections.emptyList(), Optional.empty(), Optional.empty(), Optional.empty()); + } + + Optional aggregateScore = Optional.empty(); + Optional nodeContent = Optional.empty(); + // maps id of analysis result to analysis result to prevent duplication + Map allAnalysisResults = new HashMap<>(); + Optional selectedResult = Optional.empty(); + + // Find first content that is not an artifact within node + for (Content content : node.getLookup().lookupAll(Content.class)) { + if (content == null || content instanceof BlackboardArtifact) { + continue; + } + + try { + nodeContent = Optional.of(content); + + // get the aggregate score of that content + aggregateScore = Optional.ofNullable(content.getAggregateScore()); + + // and add all analysis results to mapping + content.getAllAnalysisResults().stream() + .forEach((ar) -> allAnalysisResults.put(ar.getArtifactID(), ar)); + + break; + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Unable to get analysis results for content with obj id " + content.getId(), ex); + } + } + + // Find any analysis results in the node + Collection analysisResults = node.getLookup().lookupAll(AnalysisResult.class); + if (analysisResults.size() > 0) { + + // get any items with a score + List filteredResults = analysisResults.stream() + .collect(Collectors.toList()); + + // add them to the map to display + filteredResults.forEach((ar) -> allAnalysisResults.put(ar.getArtifactID(), ar)); + + // the selected result will be the highest scored analysis result in the node. + selectedResult = filteredResults.stream() + .max((a, b) -> a.getScore().compareTo(b.getScore())); + + // if no aggregate score determined at this point, use the selected result score. + if (!aggregateScore.isPresent()) { + aggregateScore = selectedResult.flatMap(selectedRes -> Optional.ofNullable(selectedRes.getScore())); + } + } + + // get view model representation + List displayAttributes = getOrderedDisplayAttributes(allAnalysisResults.values()); + + return new NodeResults(displayAttributes, selectedResult, aggregateScore, nodeContent); + } +} diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/Bundle.properties-MERGED new file mode 100644 index 0000000000..f4558602d8 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/Bundle.properties-MERGED @@ -0,0 +1,11 @@ +AnalysisResultsContentPanel_aggregateScore_displayKey=Aggregate Score +# {0} - analysisResultsNumber +AnalysisResultsContentPanel_result_headerKey=Analysis Result {0} +AnalysisResultsContentViewer_setNode_errorMessage=There was an error loading results. +AnalysisResultsContentViewer_setNode_loadingMessage=Loading... +AnalysisResultsContentViewer_title=Analysis Results +AnalysisResultsContentViewer_tooltip=Viewer for Analysis Results related to the selected node. +AnalysisResultsViewModel_displayAttributes_conclusion=Conclusion +AnalysisResultsViewModel_displayAttributes_configuration=Configuration +AnalysisResultsViewModel_displayAttributes_score=Score +AnalysisResultsViewModel_displayAttributes_type=Type diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/Bundle_ja.properties new file mode 100644 index 0000000000..14c0eb0f44 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/analysisresults/Bundle_ja.properties @@ -0,0 +1,11 @@ +#Thu Jul 01 11:56:41 UTC 2021 +AnalysisResultsContentPanel_aggregateScore_displayKey=\u96c6\u8a08\u30b9\u30b3\u30a2 +AnalysisResultsContentPanel_result_headerKey=\u5206\u6790\u7d50\u679c{0} +AnalysisResultsContentViewer_setNode_errorMessage=\u7d50\u679c\u306e\u8aad\u8fbc\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +AnalysisResultsContentViewer_setNode_loadingMessage=\u8aad\u307f\u8fbc\u307f\u4e2d... +AnalysisResultsContentViewer_title=\u5206\u6790\u7d50\u679c +AnalysisResultsContentViewer_tooltip=\u9078\u629e\u3057\u305f\u30ce\u30fc\u30c9\u306b\u95a2\u9023\u3059\u308b\u5206\u6790\u7d50\u679c\u306e\u30d3\u30e5\u30fc\u30a2\u3002 +AnalysisResultsViewModel_displayAttributes_conclusion=\u7d50\u8ad6 +AnalysisResultsViewModel_displayAttributes_configuration=\u69cb\u6210 +AnalysisResultsViewModel_displayAttributes_score=\u30b9\u30b3\u30a2 +AnalysisResultsViewModel_displayAttributes_type=\u30bf\u30a4\u30d7 diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/application/Annotations.java b/Core/src/org/sleuthkit/autopsy/contentviewers/application/Annotations.java index feec2703dc..67124d1502 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/application/Annotations.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/application/Annotations.java @@ -24,7 +24,6 @@ import java.util.List; import java.util.function.Function; import java.util.logging.Level; import java.util.stream.Collectors; -import javax.swing.JLabel; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.jsoup.Jsoup; @@ -39,6 +38,7 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeNormalizationException; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeUtil; +import org.sleuthkit.autopsy.contentviewers.layout.ContentViewerHtmlStyles; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; @@ -80,18 +80,6 @@ public class Annotations { private static final String EMPTY_HTML = ""; - private static final int DEFAULT_FONT_SIZE = new JLabel().getFont().getSize(); - // spacing occurring after an item - private static final int DEFAULT_TABLE_SPACING = DEFAULT_FONT_SIZE; - - // html stylesheet classnames for components - public static final String MESSAGE_CLASSNAME = "message"; - public static final String SUBSECTION_CLASSNAME = "subsection"; - public static final String SUBHEADER_CLASSNAME = "subheader"; - public static final String SECTION_CLASSNAME = "section"; - public static final String HEADER_CLASSNAME = "header"; - public static final String VERTICAL_TABLE_CLASSNAME = "vertical-table"; - // describing table values for a tag private static final List> TAG_ENTRIES = Arrays.asList( new ItemEntry<>(Bundle.Annotations_tagEntryDataLabel_tag(), @@ -200,11 +188,11 @@ public class Annotations { * @return If any content was actually rendered. */ private static boolean renderArtifact(Element parent, BlackboardArtifact bba, Content sourceContent) { - boolean contentRendered = appendEntries(parent, TAG_CONFIG, getTags(bba), false); + boolean contentRendered = appendEntries(parent, TAG_CONFIG, getTags(bba), false, true); if (CentralRepository.isEnabled()) { List centralRepoComments = getCentralRepositoryData(bba); - boolean crRendered = appendEntries(parent, CR_COMMENTS_CONFIG, centralRepoComments, false); + boolean crRendered = appendEntries(parent, CR_COMMENTS_CONFIG, centralRepoComments, false, !contentRendered); contentRendered = contentRendered || crRendered; } @@ -213,12 +201,17 @@ public class Annotations { || BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID() == bba.getArtifactTypeID()) && (hasTskComment(bba))) { - boolean filesetRendered = appendEntries(parent, ARTIFACT_COMMENT_CONFIG, Arrays.asList(bba), false); + boolean filesetRendered = appendEntries(parent, ARTIFACT_COMMENT_CONFIG, Arrays.asList(bba), false, !contentRendered); contentRendered = contentRendered || filesetRendered; } Element sourceFileSection = appendSection(parent, Bundle.Annotations_sourceFile_title()); - boolean sourceFileRendered = renderContent(sourceFileSection, sourceContent, true); + sourceFileSection.attr("class", ContentViewerHtmlStyles.getSpacedSectionClassName()); + + Element sourceFileContainer = sourceFileSection.appendElement("div"); + sourceFileContainer.attr("class", ContentViewerHtmlStyles.getIndentedClassName()); + + boolean sourceFileRendered = renderContent(sourceFileContainer, sourceContent, true); if (!sourceFileRendered) { sourceFileSection.remove(); @@ -238,24 +231,27 @@ public class Annotations { * @return If any content was actually rendered. */ private static boolean renderContent(Element parent, Content sourceContent, boolean isSubheader) { - boolean contentRendered = appendEntries(parent, TAG_CONFIG, getTags(sourceContent), isSubheader); + boolean contentRendered = appendEntries(parent, TAG_CONFIG, getTags(sourceContent), isSubheader, true); if (sourceContent instanceof AbstractFile) { AbstractFile sourceFile = (AbstractFile) sourceContent; if (CentralRepository.isEnabled()) { List centralRepoComments = getCentralRepositoryData(sourceFile); - boolean crRendered = appendEntries(parent, CR_COMMENTS_CONFIG, centralRepoComments, isSubheader); + boolean crRendered = appendEntries(parent, CR_COMMENTS_CONFIG, centralRepoComments, isSubheader, + !contentRendered); contentRendered = contentRendered || crRendered; } boolean hashsetRendered = appendEntries(parent, HASHSET_CONFIG, getFileSetHits(sourceFile, BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT), - isSubheader); + isSubheader, + !contentRendered); boolean interestingFileRendered = appendEntries(parent, INTERESTING_FILE_CONFIG, getFileSetHits(sourceFile, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT), - isSubheader); + isSubheader, + !contentRendered); contentRendered = contentRendered || hashsetRendered || interestingFileRendered; } @@ -456,24 +452,36 @@ public class Annotations { * will be formatted as a table in the format specified in the * SectionConfig. * - * @param parent The parent element for which the entries will be - * attached. - * @param config The display configuration for this entry type (i.e. - * table type, name, if data is not present). - * @param items The items to display. - * @param isSubsection Whether or not this should be displayed as a - * subsection. If not displayed as a top-level section. + * @param parent The parent element for which the entries will be + * attached. + * @param config The display configuration for this entry type (i.e. + * table type, name, if data is not present). + * @param items The items to display. + * @param isSubsection Whether or not this should be displayed as a + * subsection. If not displayed as a top-level + * section. + * @param isFirstSection Whether or not this is the first section appended. * * @return If there was actual content rendered for this set of entries. */ private static boolean appendEntries(Element parent, Annotations.SectionConfig config, List items, - boolean isSubsection) { + boolean isSubsection, boolean isFirstSection) { if (items == null || items.isEmpty()) { return false; } Element sectionDiv = (isSubsection) ? appendSubsection(parent, config.getTitle()) : appendSection(parent, config.getTitle()); - appendVerticalEntryTables(sectionDiv, items, config.getAttributes()); + if (!isFirstSection) { + sectionDiv.attr("class", ContentViewerHtmlStyles.getSpacedSectionClassName()); + } + + Element sectionContainer = sectionDiv.appendElement("div"); + + if (!isSubsection) { + sectionContainer.attr("class", ContentViewerHtmlStyles.getIndentedClassName()); + } + + appendVerticalEntryTables(sectionContainer, items, config.getAttributes()); return true; } @@ -499,12 +507,11 @@ public class Annotations { .collect(Collectors.toList()); Element childTable = appendTable(parent, 2, tableData, null); - childTable.attr("class", VERTICAL_TABLE_CLASSNAME); if (isFirst) { isFirst = false; } else { - childTable.attr("style", String.format("margin-top: %dpx;", DEFAULT_TABLE_SPACING)); + childTable.attr("class", ContentViewerHtmlStyles.getSpacedSectionClassName()); } } @@ -524,7 +531,10 @@ public class Annotations { * @return The created table. */ private static Element appendTable(Element parent, int columnNumber, List> content, List columnHeaders) { - Element table = parent.appendElement("table"); + Element table = parent.appendElement("table") + .attr("valign", "top") + .attr("align", "left"); + if (columnHeaders != null && !columnHeaders.isEmpty()) { Element header = table.appendElement("thead"); appendRow(header, columnHeaders, columnNumber, true); @@ -551,8 +561,15 @@ public class Annotations { Element row = rowParent.appendElement("tr"); for (int i = 0; i < columnNumber; i++) { Element cell = row.appendElement(cellType); + + if (i == 0) { + cell.attr("class", ContentViewerHtmlStyles.getKeyColumnClassName()); + } + if (data != null && i < data.size()) { - cell.text(StringUtils.isEmpty(data.get(i)) ? "" : data.get(i)); + cell.appendElement("span") + .attr("class", ContentViewerHtmlStyles.getTextClassName()) + .text(StringUtils.isEmpty(data.get(i)) ? "" : data.get(i)); } } return row; @@ -568,10 +585,9 @@ public class Annotations { */ private static Element appendSection(Element parent, String headerText) { Element sectionDiv = parent.appendElement("div"); - sectionDiv.attr("class", SECTION_CLASSNAME); Element header = sectionDiv.appendElement("h1"); header.text(headerText); - header.attr("class", HEADER_CLASSNAME); + header.attr("class", ContentViewerHtmlStyles.getHeaderClassName()); return sectionDiv; } @@ -585,10 +601,9 @@ public class Annotations { */ private static Element appendSubsection(Element parent, String headerText) { Element subsectionDiv = parent.appendElement("div"); - subsectionDiv.attr("class", SUBSECTION_CLASSNAME); Element header = subsectionDiv.appendElement("h2"); header.text(headerText); - header.attr("class", SUBHEADER_CLASSNAME); + header.attr("class", ContentViewerHtmlStyles.getHeaderClassName()); return subsectionDiv; } @@ -605,7 +620,7 @@ public class Annotations { private static Element appendMessage(Element parent, String message) { Element messageEl = parent.appendElement("p"); messageEl.text(message); - messageEl.attr("class", MESSAGE_CLASSNAME); + messageEl.attr("class", ContentViewerHtmlStyles.getMessageClassName()); return messageEl; } diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/application/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/contentviewers/application/Bundle_ja.properties new file mode 100644 index 0000000000..ad13ec51b3 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/application/Bundle_ja.properties @@ -0,0 +1,19 @@ +#Thu Jul 01 11:56:41 UTC 2021 +Annotations.centralRepositoryEntry.title=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u306e\u30b3\u30e1\u30f3\u30c8 +Annotations.centralRepositoryEntryDataLabel.case=\u30b1\u30fc\u30b9\: +Annotations.centralRepositoryEntryDataLabel.comment=\u30b3\u30e1\u30f3\u30c8\: +Annotations.centralRepositoryEntryDataLabel.path=\u30d1\u30b9\: +Annotations.centralRepositoryEntryDataLabel.type=\u30bf\u30a4\u30d7\: +Annotations.fileHitEntry.artifactCommentTitle=\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u30b3\u30e1\u30f3\u30c8 +Annotations.fileHitEntry.comment=\u30b3\u30e1\u30f3\u30c8\: +Annotations.fileHitEntry.hashSetHitTitle=\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u30fb\u30d2\u30c3\u30c8\u30b3\u30e1\u30f3\u30c8 +Annotations.fileHitEntry.interestingFileHitTitle=\u8208\u5473\u6df1\u3044\u30d5\u30a1\u30a4\u30eb\u30d2\u30c3\u30c8\u30b3\u30e1\u30f3\u30c8 +Annotations.fileHitEntry.setName=\u30bb\u30c3\u30c8\u540d\: +Annotations.onEmpty=\u3053\u306e\u30a2\u30a4\u30c6\u30e0\u306e\u6ce8\u91c8\u306f\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +Annotations.sourceFile.title=\u30bd\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb +Annotations.tagEntry.title=\u30bf\u30b0 +Annotations.tagEntryDataLabel.comment=\u30b3\u30e1\u30f3\u30c8\: +Annotations.tagEntryDataLabel.tag=\u30bf\u30b0\: +Annotations.tagEntryDataLabel.tagUser=\u5be9\u67fb\u5b98\uff1a +Annotations.title=\u30a2\u30ce\u30c6\u30fc\u30b7\u30e7\u30f3 +Annotations.toolTip=\u9078\u629e\u3057\u305f\u30b3\u30f3\u30c6\u30f3\u30c4\u3068\u95a2\u9023\u4ed8\u3051\u3089\u308c\u3066\u3044\u308b\u30bf\u30b0\u3068\u30b3\u30e1\u30f3\u30c8\u3092\u8868\u793a\u3057\u307e\u3059\u3002 diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/CallLogArtifactViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/CallLogArtifactViewer.java index 8d27c6c5be..0830e8e6ef 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/CallLogArtifactViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/CallLogArtifactViewer.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2020 Basis Technology Corp. + * Copyright 2020-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.contentviewers.artifactviewers; import java.awt.Component; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; +import java.awt.Insets; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -30,11 +31,13 @@ import java.util.Map; import java.util.Set; import java.util.logging.Level; import javax.swing.JScrollPane; +import javax.swing.border.EmptyBorder; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.openide.util.NbBundle; import org.openide.util.lookup.ServiceProvider; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; +import org.sleuthkit.autopsy.contentviewers.layout.ContentViewerDefaults; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.guiutils.ContactCache; import org.sleuthkit.datamodel.BlackboardArtifact; @@ -75,6 +78,7 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac */ public CallLogArtifactViewer() { initComponents(); + this.setBorder(new EmptyBorder(ContentViewerDefaults.getPanelInsets())); } /** @@ -93,29 +97,28 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac public void setArtifact(BlackboardArtifact artifact) { resetComponent(); - if (artifact == null) { - return; - } - CallLogViewData callLogViewData = null; try { callLogViewData = getCallLogViewData(artifact); } catch (TskCoreException ex) { logger.log(Level.SEVERE, String.format("Error getting attributes for Calllog artifact (artifact_id=%d, obj_id=%d)", artifact.getArtifactID(), artifact.getObjectID()), ex); } - + List personaSearchDataList = new ArrayList<>(); // update the view with the call log data if (callLogViewData != null) { - List personaSearchDataList = updateView(callLogViewData); - if (!personaSearchDataList.isEmpty()) { - currentAccountFetcher = new PersonaAccountFetcher(artifact, personaSearchDataList, this); - currentAccountFetcher.execute(); - } else { - currentAccountFetcher = null; - } + personaSearchDataList.addAll(updateView(callLogViewData)); + } + if (!personaSearchDataList.isEmpty()) { + currentAccountFetcher = new PersonaAccountFetcher(artifact, personaSearchDataList, this); + currentAccountFetcher.execute(); + } else { + currentAccountFetcher = null; + } + // repaint this.revalidate(); + this.repaint(); } /** @@ -309,13 +312,13 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac }) private List updateView(CallLogViewData callLogViewData) { - CommunicationArtifactViewerHelper.addHeader(this, m_gridBagLayout, this.m_constraints, Bundle.CallLogArtifactViewer_heading_parties()); + CommunicationArtifactViewerHelper.addHeader(this, m_gridBagLayout, this.m_constraints, 0, Bundle.CallLogArtifactViewer_heading_parties()); List dataList = new ArrayList<>(); // Display "From" if we have non-local device accounts if (callLogViewData.getFromAccount() != null) { CommunicationArtifactViewerHelper.addKey(this, m_gridBagLayout, this.m_constraints, Bundle.CallLogArtifactViewer_label_from()); - + // check if this is local account String accountDisplayString = getAccountDisplayString(callLogViewData.getFromAccount(), callLogViewData); CommunicationArtifactViewerHelper.addValue(this, m_gridBagLayout, this.m_constraints, accountDisplayString); @@ -366,8 +369,6 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac this.setLayout(m_gridBagLayout); this.revalidate(); - this.repaint(); - return dataList; } @@ -384,7 +385,7 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac }) private void updateMetadataView(CallLogViewData callLogViewData) { - CommunicationArtifactViewerHelper.addHeader(this, m_gridBagLayout, this.m_constraints, Bundle.CallLogArtifactViewer_heading_metadata()); + CommunicationArtifactViewerHelper.addHeader(this, m_gridBagLayout, this.m_constraints, ContentViewerDefaults.getSectionSpacing(), Bundle.CallLogArtifactViewer_heading_metadata()); CommunicationArtifactViewerHelper.addKey(this, m_gridBagLayout, this.m_constraints, Bundle.CallLogArtifactViewer_label_direction()); if (callLogViewData.getDirection() != null) { @@ -414,7 +415,7 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac "CallLogArtifactViewer_heading_Source=Source", "CallLogArtifactViewer_label_datasource=Data Source",}) private void updateSourceView(CallLogViewData callLogViewData) { - CommunicationArtifactViewerHelper.addHeader(this, m_gridBagLayout, this.m_constraints, Bundle.CallLogArtifactViewer_heading_Source()); + CommunicationArtifactViewerHelper.addHeader(this, m_gridBagLayout, this.m_constraints, ContentViewerDefaults.getSectionSpacing(), Bundle.CallLogArtifactViewer_heading_Source()); CommunicationArtifactViewerHelper.addKey(this, m_gridBagLayout, this.m_constraints, Bundle.CallLogArtifactViewer_label_datasource()); CommunicationArtifactViewerHelper.addValue(this, m_gridBagLayout, this.m_constraints, callLogViewData.getDataSourceName()); } @@ -432,7 +433,7 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac if (callLogViewData.getOtherAttributes().isEmpty()) { return; } - CommunicationArtifactViewerHelper.addHeader(this, m_gridBagLayout, this.m_constraints, Bundle.CallLogArtifactViewer_heading_others()); + CommunicationArtifactViewerHelper.addHeader(this, m_gridBagLayout, this.m_constraints, ContentViewerDefaults.getSectionSpacing(), Bundle.CallLogArtifactViewer_heading_others()); for (Map.Entry entry : callLogViewData.getOtherAttributes().entrySet()) { CommunicationArtifactViewerHelper.addKey(this, m_gridBagLayout, this.m_constraints, entry.getKey()); @@ -444,9 +445,8 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac "CalllogArtifactViewer_cr_disabled_message=Enable Central Repository to view, create and edit personas." }) private void showCRDisabledMessage() { - CommunicationArtifactViewerHelper.addBlankLine(this, m_gridBagLayout, m_constraints); - m_constraints.gridy++; - CommunicationArtifactViewerHelper.addMessageRow(this, m_gridBagLayout, m_constraints, Bundle.ContactArtifactViewer_cr_disabled_message()); + Insets messageInsets = new Insets(ContentViewerDefaults.getSectionSpacing(), 0, ContentViewerDefaults.getLineSpacing(), 0); + CommunicationArtifactViewerHelper.addMessageRow(this, m_gridBagLayout, messageInsets, m_constraints, Bundle.ContactArtifactViewer_cr_disabled_message()); m_constraints.gridy++; } @@ -505,7 +505,7 @@ public class CallLogArtifactViewer extends javax.swing.JPanel implements Artifac m_constraints.gridx = 0; m_constraints.weighty = 0.0; m_constraints.weightx = 0.0; // keep components fixed horizontally. - m_constraints.insets = new java.awt.Insets(0, CommunicationArtifactViewerHelper.LEFT_INSET, 0, 0); + m_constraints.insets = new java.awt.Insets(0, ContentViewerDefaults.getSectionIndent(), 0, 0); m_constraints.fill = GridBagConstraints.NONE; } diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/CommunicationArtifactViewerHelper.java b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/CommunicationArtifactViewerHelper.java index fe5e19aff5..6f7e4cff2f 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/CommunicationArtifactViewerHelper.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/CommunicationArtifactViewerHelper.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2020 Basis Technology Corp. + * Copyright 2020-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,7 +19,6 @@ package org.sleuthkit.autopsy.contentviewers.artifactviewers; import java.awt.Dimension; -import java.awt.Font; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; @@ -38,6 +37,7 @@ import javax.swing.JTextPane; import javax.swing.SwingUtilities; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; +import org.sleuthkit.autopsy.contentviewers.layout.ContentViewerDefaults; /** * @@ -49,8 +49,6 @@ final class CommunicationArtifactViewerHelper { // Number of columns in the gridbag layout. private final static int MAX_COLS = 4; - final static int LEFT_INSET = 12; - /** * Empty private constructor */ @@ -64,34 +62,34 @@ final class CommunicationArtifactViewerHelper { * @param panel Panel to update. * @param gridbagLayout Layout to use. * @param constraints Constraints to use. + * @param spacing Spacing to add to top insets (in pixels). * @param headerString Heading string to display. * * @return JLabel Heading label added. */ - static JLabel addHeader(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints, String headerString) { + static JLabel addHeader(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints, int topSpacing, String headerString) { Insets savedInsets = constraints.insets; // create label for heading javax.swing.JLabel headingLabel = new javax.swing.JLabel(); - // add a blank line before the start of new section, unless it's - // the first section - if (constraints.gridy != 0) { - addBlankLine(panel, gridbagLayout, constraints); - } + constraints.gridy++; constraints.gridx = 0; // let the header span all of the row constraints.gridwidth = MAX_COLS; - constraints.insets = new Insets(0, 0, 0, 0); // No inset for header + constraints.anchor = GridBagConstraints.LINE_START; + constraints.fill = GridBagConstraints.NONE; + + constraints.insets = new Insets(topSpacing, 0, ContentViewerDefaults.getLineSpacing(), 0); // set text - headingLabel.setText(headerString); + headingLabel.setText(headerString.trim()); // make it large and bold - headingLabel.setFont(headingLabel.getFont().deriveFont(Font.BOLD, headingLabel.getFont().getSize() + 2)); + headingLabel.setFont(ContentViewerDefaults.getHeaderFont()); // add to panel gridbagLayout.setConstraints(headingLabel, constraints); @@ -159,7 +157,7 @@ final class CommunicationArtifactViewerHelper { int savedFill = constraints.fill; constraints.weightx = 1.0; // take up all the horizontal space - constraints.fill = GridBagConstraints.BOTH; + constraints.fill = GridBagConstraints.HORIZONTAL; javax.swing.Box.Filler horizontalFiller = new javax.swing.Box.Filler(new Dimension(0, 0), new Dimension(0, 0), new Dimension(32767, 0)); gridbagLayout.setConstraints(horizontalFiller, constraints); @@ -181,6 +179,7 @@ final class CommunicationArtifactViewerHelper { static void addPageEndGlue(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints) { constraints.gridx = 0; + constraints.gridy++; double savedWeighty = constraints.weighty; int savedFill = constraints.fill; @@ -197,24 +196,6 @@ final class CommunicationArtifactViewerHelper { constraints.fill = savedFill; } - /** - * Adds a blank line to the panel. - * - * @param panel Panel to update. - * @param gridbagLayout Layout to use. - * @param constraints Constraints to use. - */ - static void addBlankLine(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints) { - constraints.gridy++; - constraints.gridx = 0; - - javax.swing.JLabel filler = new javax.swing.JLabel(" "); - gridbagLayout.setConstraints(filler, constraints); - panel.add(filler); - - addLineEndGlue(panel, gridbagLayout, constraints); - } - /** * Adds a label/key to the panel at col 0. * @@ -247,9 +228,12 @@ final class CommunicationArtifactViewerHelper { constraints.gridy++; constraints.gridx = gridx < MAX_COLS - 1 ? gridx : MAX_COLS - 2; + constraints.anchor = GridBagConstraints.LINE_START; + constraints.insets = new Insets(0, ContentViewerDefaults.getSectionIndent(), ContentViewerDefaults.getLineSpacing(), 0); // set text - keyLabel.setText(keyString + ": "); + String preppedKeyString = keyString == null ? null : keyString.trim() + ":"; + keyLabel.setText(preppedKeyString); // add to panel gridbagLayout.setConstraints(keyLabel, constraints); @@ -288,6 +272,7 @@ final class CommunicationArtifactViewerHelper { JTextPane valueField = new JTextPane(); valueField.setEditable(false); valueField.setOpaque(false); + valueField.setMargin(new Insets(0,0,0,0)); constraints.gridx = gridx < MAX_COLS ? gridx : MAX_COLS - 1; @@ -295,7 +280,8 @@ final class CommunicationArtifactViewerHelper { // let the value span 2 cols cloneConstraints.gridwidth = 2; - cloneConstraints.fill = GridBagConstraints.BOTH; + constraints.anchor = GridBagConstraints.LINE_START; + cloneConstraints.insets = new Insets(0, ContentViewerDefaults.getColumnSpacing(), ContentViewerDefaults.getLineSpacing(), 0); // set text valueField.setText(valueString); @@ -325,13 +311,13 @@ final class CommunicationArtifactViewerHelper { * @param panel Panel to show. * @param gridbagLayout Layout to use. * @param constraints Constraints to use. - * + * @param insets The insets to be used for the grid bag layout constraints. If null, default insets are assumed. * @param messageString Message to display. * * @return Label for message added. */ - static JLabel addMessageRow(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints, String messageString) { - return addMessageRow(panel, gridbagLayout, constraints, messageString, 0); + static JLabel addMessageRow(JPanel panel, GridBagLayout gridbagLayout, Insets insets, GridBagConstraints constraints, String messageString) { + return addMessageRow(panel, gridbagLayout, constraints, insets, messageString, 0); } /** @@ -340,26 +326,33 @@ final class CommunicationArtifactViewerHelper { * * @param panel Panel to show. * @param gridbagLayout Layout to use. + * @param insets The insets to be used for the grid bag layout constraints. * @param constraints Constraints to use. - * + * @param insets The insets to be used for the grid bag layout constraints. If null, default insets are assumed. * @param messageString Message to display. + * @param gridx The grid x location to use. * * @return Label for message added. */ - static JLabel addMessageRow(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints, String messageString, int gridx) { + static JLabel addMessageRow(JPanel panel, GridBagLayout gridbagLayout, GridBagConstraints constraints, Insets insets, String messageString, int gridx) { // create label javax.swing.JLabel messageLabel = new javax.swing.JLabel(); constraints.gridy++; constraints.gridx = gridx < MAX_COLS - 1 ? gridx : MAX_COLS - 2; - + constraints.insets = insets == null + ? new Insets(0, 0, ContentViewerDefaults.getLineSpacing(), 0) : + insets; + constraints.anchor = GridBagConstraints.LINE_START; + int savedGridwidth = constraints.gridwidth; constraints.gridwidth = 3; // set text - messageLabel.setText(messageString); + messageLabel.setText(messageString == null ? null : messageString.trim()); + messageLabel.setFont(ContentViewerDefaults.getMessageFont()); // add to panel gridbagLayout.setConstraints(messageLabel, constraints); @@ -406,8 +399,9 @@ final class CommunicationArtifactViewerHelper { Insets savedInsets = constraints.insets; // extra Indent in - constraints.insets = new java.awt.Insets(0, 2 * LEFT_INSET, 0, 0); - + constraints.insets = new java.awt.Insets(0, ContentViewerDefaults.getColumnSpacing(), ContentViewerDefaults.getLineSpacing(), 0); + constraints.anchor = GridBagConstraints.LINE_START; + // create label javax.swing.JLabel personaLabel = new javax.swing.JLabel(); String personaLabelText = Bundle.CommunicationArtifactViewerHelper_persona_label(); @@ -415,15 +409,12 @@ final class CommunicationArtifactViewerHelper { ? Bundle.CommunicationArtifactViewerHelper_persona_searching() : Bundle.CommunicationArtifactViewerHelper_persona_unknown()); - personaLabel.setText(personaLabelText); - + personaLabel.setText(personaLabelText == null ? null : personaLabelText.trim()); + // add to panel gridbagLayout.setConstraints(personaLabel, constraints); panel.add(personaLabel); - // restore constraint - constraints.insets = savedInsets; - constraints.gridx++; // Place a button as place holder. It will be enabled when persona is available. @@ -441,6 +432,9 @@ final class CommunicationArtifactViewerHelper { } else { personaLabel.setEnabled(false); } + + // restore constraint + constraints.insets = savedInsets; addLineEndGlue(panel, gridbagLayout, constraints); @@ -469,7 +463,7 @@ final class CommunicationArtifactViewerHelper { GridBagConstraints indentedConstraints = (GridBagConstraints) constraints.clone(); // Add an indent to match persona labels - indentedConstraints.insets = new java.awt.Insets(0, 2 * LEFT_INSET, 0, 0); + indentedConstraints.insets = new java.awt.Insets(0, ContentViewerDefaults.getSectionIndent(), ContentViewerDefaults.getLineSpacing(), 0); String contactInfo = Bundle.CommunicationArtifactViewerHelper_contact_label(contactId != null && !contactId.isEmpty() ? contactId : Bundle.CommunicationArtifactViewerHelper_contact_label_unknown()); diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/ContactArtifactViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/ContactArtifactViewer.java index b17263a26d..e1181f80cd 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/ContactArtifactViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/ContactArtifactViewer.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2020 Basis Technology Corp. + * Copyright 2020-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -41,9 +41,9 @@ import javax.imageio.ImageIO; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JLabel; -import javax.swing.JOptionPane; import javax.swing.JScrollPane; import javax.swing.SwingWorker; +import javax.swing.border.EmptyBorder; import org.apache.commons.lang.StringUtils; import org.openide.util.NbBundle; import org.openide.util.lookup.ServiceProvider; @@ -57,6 +57,7 @@ import org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsDialog; import org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsDialogCallback; import org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsMode; import org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsPanel; +import org.sleuthkit.autopsy.contentviewers.layout.ContentViewerDefaults; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Account; @@ -64,6 +65,7 @@ import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.CommunicationsManager; import org.sleuthkit.datamodel.Content; +import org.sleuthkit.datamodel.InvalidAccountIDException; import org.sleuthkit.datamodel.TskCoreException; /** @@ -107,7 +109,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac */ public ContactArtifactViewer() { initComponents(); - + this.setBorder(new EmptyBorder(ContentViewerDefaults.getPanelInsets())); defaultImage = new ImageIcon(ContactArtifactViewer.class.getResource(DEFAULT_IMAGE_PATH)); } @@ -129,19 +131,15 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac // Reset the panel. resetComponent(); - if (artifact == null) { - return; + if (artifact != null) { + try { + extractArtifactData(artifact); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, String.format("Error getting attributes for artifact (artifact_id=%d, obj_id=%d)", artifact.getArtifactID(), artifact.getObjectID()), ex); + return; + } + updateView(); } - - try { - extractArtifactData(artifact); - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, String.format("Error getting attributes for artifact (artifact_id=%d, obj_id=%d)", artifact.getArtifactID(), artifact.getObjectID()), ex); - return; - } - - updateView(); - this.setLayout(this.m_gridBagLayout); this.revalidate(); this.repaint(); @@ -163,6 +161,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac * Extracts data from the artifact to be displayed in the panel. * * @param artifact Artifact to show. + * * @throws TskCoreException */ private void extractArtifactData(BlackboardArtifact artifact) throws TskCoreException { @@ -234,7 +233,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac /** * Updates the contact image in the view. * - * @param contactPanelLayout Panel layout. + * @param contactPanelLayout Panel layout. * @param contactPanelConstraints Layout constraints. * */ @@ -245,8 +244,11 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac Insets savedInsets = contactPanelConstraints.insets; contactPanelConstraints.gridy = 0; contactPanelConstraints.gridx = 0; - contactPanelConstraints.insets = new Insets(0, 0, 0, 0); - + contactPanelConstraints.insets = new Insets(0, 0, ContentViewerDefaults.getLineSpacing(), 0); + int prevGridWidth = contactPanelConstraints.gridwidth; + contactPanelConstraints.gridwidth = 3; + contactPanelConstraints.anchor = GridBagConstraints.LINE_START; + javax.swing.JLabel contactImage = new javax.swing.JLabel(); contactImage.setIcon(getImageFromArtifact(contactArtifact)); contactImage.setText(Bundle.ContactArtifactViewer_contactImage_text()); @@ -256,13 +258,14 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac CommunicationArtifactViewerHelper.addLineEndGlue(this, contactPanelLayout, contactPanelConstraints); contactPanelConstraints.gridy++; + contactPanelConstraints.gridwidth = prevGridWidth; contactPanelConstraints.insets = savedInsets; } /** * Updates the contact name in the view. * - * @param contactPanelLayout Panel layout. + * @param contactPanelLayout Panel layout. * @param contactPanelConstraints Layout constraints. * */ @@ -275,13 +278,13 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac if (StringUtils.isEmpty(bba.getValueString()) == false) { contactName = bba.getDisplayString(); - CommunicationArtifactViewerHelper.addHeader(this, contactPanelLayout, contactPanelConstraints, contactName); + CommunicationArtifactViewerHelper.addHeader(this, contactPanelLayout, contactPanelConstraints, 0, contactName); foundName = true; break; } } if (foundName == false) { - CommunicationArtifactViewerHelper.addHeader(this, contactPanelLayout, contactPanelConstraints, Bundle.ContactArtifactViewer_contactname_unknown()); + CommunicationArtifactViewerHelper.addHeader(this, contactPanelLayout, contactPanelConstraints, ContentViewerDefaults.getSectionSpacing(), Bundle.ContactArtifactViewer_contactname_unknown()); } } @@ -289,9 +292,9 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac * Updates the view by displaying the given list of attributes in the given * section panel. * - * @param sectionAttributesList List of attributes to display. - * @param sectionHeader Section name label. - * @param contactPanelLayout Panel layout. + * @param sectionAttributesList List of attributes to display. + * @param sectionHeader Section name label. + * @param contactPanelLayout Panel layout. * @param contactPanelConstraints Layout constraints. * */ @@ -302,7 +305,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac return; } - CommunicationArtifactViewerHelper.addHeader(this, contactPanelLayout, contactPanelConstraints, sectionHeader); + CommunicationArtifactViewerHelper.addHeader(this, contactPanelLayout, contactPanelConstraints, ContentViewerDefaults.getSectionSpacing(), sectionHeader); for (BlackboardAttribute bba : sectionAttributesList) { CommunicationArtifactViewerHelper.addKey(this, contactPanelLayout, contactPanelConstraints, bba.getAttributeType().getDisplayName()); CommunicationArtifactViewerHelper.addValue(this, contactPanelLayout, contactPanelConstraints, bba.getDisplayString()); @@ -316,7 +319,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac "ContactArtifactViewer_heading_Source=Source", "ContactArtifactViewer_label_datasource=Data Source",}) private void updateSource() { - CommunicationArtifactViewerHelper.addHeader(this, this.m_gridBagLayout, m_constraints, Bundle.ContactArtifactViewer_heading_Source()); + CommunicationArtifactViewerHelper.addHeader(this, this.m_gridBagLayout, m_constraints, ContentViewerDefaults.getSectionSpacing(), Bundle.ContactArtifactViewer_heading_Source()); CommunicationArtifactViewerHelper.addKey(this, m_gridBagLayout, m_constraints, Bundle.ContactArtifactViewer_label_datasource()); CommunicationArtifactViewerHelper.addValue(this, m_gridBagLayout, m_constraints, datasourceName); } @@ -335,7 +338,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac private void initiatePersonasSearch() { // add a section header - JLabel personaHeader = CommunicationArtifactViewerHelper.addHeader(this, m_gridBagLayout, m_constraints, Bundle.ContactArtifactViewer_persona_header()); + JLabel personaHeader = CommunicationArtifactViewerHelper.addHeader(this, m_gridBagLayout, m_constraints, ContentViewerDefaults.getSectionSpacing(), Bundle.ContactArtifactViewer_persona_header()); m_constraints.gridy++; @@ -346,8 +349,10 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac this.personaSearchStatusLabel = new javax.swing.JLabel(); personaSearchStatusLabel.setText(personaStatusLabelText); - + personaSearchStatusLabel.setFont(ContentViewerDefaults.getMessageFont()); + m_constraints.gridx = 0; + m_constraints.anchor = GridBagConstraints.LINE_START; CommunicationArtifactViewerHelper.addComponent(this, m_gridBagLayout, m_constraints, personaSearchStatusLabel); @@ -359,9 +364,8 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac personaHeader.setEnabled(false); personaSearchStatusLabel.setEnabled(false); - CommunicationArtifactViewerHelper.addBlankLine(this, m_gridBagLayout, m_constraints); - m_constraints.gridy++; - CommunicationArtifactViewerHelper.addMessageRow(this, m_gridBagLayout, m_constraints, Bundle.ContactArtifactViewer_cr_disabled_message()); + Insets messageInsets = new Insets(ContentViewerDefaults.getSectionSpacing(), 0, ContentViewerDefaults.getLineSpacing(), 0); + CommunicationArtifactViewerHelper.addMessageRow(this, m_gridBagLayout, messageInsets, m_constraints, Bundle.ContactArtifactViewer_cr_disabled_message()); m_constraints.gridy++; CommunicationArtifactViewerHelper.addPageEndGlue(this, m_gridBagLayout, this.m_constraints); @@ -412,12 +416,12 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac /** * Displays the given persona in the persona panel. * - * @param persona Persona to display. - * @param matchNumber Number of matches. + * @param persona Persona to display. + * @param matchNumber Number of matches. * @param missingAccountsList List of contact accounts this persona may be - * missing. - * @param gridBagLayout Layout to use. - * @param constraints layout constraints. + * missing. + * @param gridBagLayout Layout to use. + * @param constraints layout constraints. * * @throws CentralRepoException */ @@ -435,12 +439,9 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac // save the original insets Insets savedInsets = constraints.insets; - // some label are indented 2x to appear indented w.r.t column above - Insets extraIndentInsets = new java.awt.Insets(0, 2 * CommunicationArtifactViewerHelper.LEFT_INSET, 0, 0); - // Add a Match X label in col 0. constraints.gridx = 0; - javax.swing.JLabel matchNumberLabel = CommunicationArtifactViewerHelper.addKey(this, gridBagLayout, constraints, String.format("%s %d", Bundle.ContactArtifactViewer_persona_match_num(), matchNumber)); + javax.swing.JLabel matchNumberLabel = CommunicationArtifactViewerHelper.addKey(this, gridBagLayout, constraints, String.format("%s %d", Bundle.ContactArtifactViewer_persona_match_num(), matchNumber).trim()); javax.swing.JLabel personaNameLabel = new javax.swing.JLabel(); javax.swing.JButton personaButton = new javax.swing.JButton(); @@ -461,6 +462,8 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac //constraints.gridwidth = 1; // TBD: this may not be needed if we use single panel constraints.gridx++; + constraints.insets = new Insets(0, ContentViewerDefaults.getColumnSpacing(), ContentViewerDefaults.getLineSpacing(), 0); + constraints.anchor = GridBagConstraints.LINE_START; personaNameLabel.setText(personaName); gridBagLayout.setConstraints(personaNameLabel, constraints); CommunicationArtifactViewerHelper.addComponent(this, gridBagLayout, constraints, personaNameLabel); @@ -474,6 +477,8 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac // Shirnk the button height. personaButton.setMargin(new Insets(0, 5, 0, 5)); + constraints.insets = new Insets(0, ContentViewerDefaults.getColumnSpacing(), ContentViewerDefaults.getLineSpacing(), 0); + constraints.anchor = GridBagConstraints.LINE_START; gridBagLayout.setConstraints(personaButton, constraints); CommunicationArtifactViewerHelper.addComponent(this, gridBagLayout, constraints, personaButton); CommunicationArtifactViewerHelper.addLineEndGlue(this, gridBagLayout, constraints); @@ -488,7 +493,8 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac //constraints.insets = labelInsets; javax.swing.JLabel accountsStatus = new javax.swing.JLabel(Bundle.ContactArtifactViewer_found_all_accounts_label()); - constraints.insets = extraIndentInsets; + constraints.insets = new Insets(0, ContentViewerDefaults.getColumnSpacing(), ContentViewerDefaults.getLineSpacing(), 0); + constraints.anchor = GridBagConstraints.LINE_START; CommunicationArtifactViewerHelper.addComponent(this, gridBagLayout, constraints, accountsStatus); constraints.insets = savedInsets; @@ -501,7 +507,6 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac constraints.gridy++; // this needs an extra indent - constraints.insets = extraIndentInsets; CommunicationArtifactViewerHelper.addKeyAtCol(this, gridBagLayout, constraints, Bundle.ContactArtifactViewer_missing_account_label(), 1); constraints.insets = savedInsets; @@ -544,12 +549,12 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac m_gridBagLayout = new GridBagLayout(); m_constraints = new GridBagConstraints(); - m_constraints.anchor = GridBagConstraints.FIRST_LINE_START; + m_constraints.anchor = GridBagConstraints.LINE_START; m_constraints.gridy = 0; m_constraints.gridx = 0; m_constraints.weighty = 0.0; m_constraints.weightx = 0.0; // keep components fixed horizontally. - m_constraints.insets = new java.awt.Insets(0, CommunicationArtifactViewerHelper.LEFT_INSET, 0, 0); + m_constraints.insets = new java.awt.Insets(0, ContentViewerDefaults.getSectionIndent(), 0, 0); m_constraints.fill = GridBagConstraints.NONE; } @@ -560,7 +565,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac * @param artifact * * @return Image from a TSK_CONTACT artifact or default image if none was - * found or the artifact is not a TSK_CONTACT + * found or the artifact is not a TSK_CONTACT */ private ImageIcon getImageFromArtifact(BlackboardArtifact artifact) { ImageIcon imageIcon = defaultImage; @@ -610,7 +615,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac * Creates a persona searcher task. * * @param accountAttributesList List of attributes that may map to - * accounts. + * accounts. */ ContactPersonaSearcherTask(BlackboardArtifact artifact) { this.artifact = artifact; @@ -620,48 +625,52 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac protected Map> doInBackground() throws Exception { Map> uniquePersonas = new HashMap<>(); - CommunicationsManager commManager = Case.getCurrentCase().getSleuthkitCase().getCommunicationsManager(); List contactAccountsList = commManager.getAccountsRelatedToArtifact(artifact); for (Account account : contactAccountsList) { - if (isCancelled()) { - return new HashMap<>(); - } + try { + if (isCancelled()) { + return new HashMap<>(); + } - // make a list of all unique accounts for this contact - if (!account.getAccountType().equals(Account.Type.DEVICE)) { - Optional optCrAccountType = CentralRepository.getInstance().getAccountTypeByName(account.getAccountType().getTypeName()); - if (optCrAccountType.isPresent()) { - CentralRepoAccount crAccount = CentralRepository.getInstance().getAccount(optCrAccountType.get(), account.getTypeSpecificID()); + // make a list of all unique accounts for this contact + if (!account.getAccountType().equals(Account.Type.DEVICE)) { + Optional optCrAccountType = CentralRepository.getInstance().getAccountTypeByName(account.getAccountType().getTypeName()); + if (optCrAccountType.isPresent()) { + CentralRepoAccount crAccount = CentralRepository.getInstance().getAccount(optCrAccountType.get(), account.getTypeSpecificID()); - if (crAccount != null && uniqueAccountsList.contains(crAccount) == false) { - uniqueAccountsList.add(crAccount); + if (crAccount != null && uniqueAccountsList.contains(crAccount) == false) { + uniqueAccountsList.add(crAccount); + } } } - } - - Collection personaAccounts = PersonaAccount.getPersonaAccountsForAccount(account); - if (personaAccounts != null && !personaAccounts.isEmpty()) { - // get personas for the account - Collection personas - = personaAccounts - .stream() - .map(PersonaAccount::getPersona) - .collect(Collectors.toList()); - // make a list of unique personas, along with all their accounts - for (Persona persona : personas) { - if (uniquePersonas.containsKey(persona) == false) { - Collection accounts = persona.getPersonaAccounts() - .stream() - .map(PersonaAccount::getAccount) - .collect(Collectors.toList()); + Collection personaAccounts = PersonaAccount.getPersonaAccountsForAccount(account); + if (personaAccounts != null && !personaAccounts.isEmpty()) { + // get personas for the account + Collection personas + = personaAccounts + .stream() + .map(PersonaAccount::getPersona) + .collect(Collectors.toList()); - ArrayList personaAccountsList = new ArrayList<>(accounts); - uniquePersonas.put(persona, personaAccountsList); + // make a list of unique personas, along with all their accounts + for (Persona persona : personas) { + if (uniquePersonas.containsKey(persona) == false) { + Collection accounts = persona.getPersonaAccounts() + .stream() + .map(PersonaAccount::getAccount) + .collect(Collectors.toList()); + + ArrayList personaAccountsList = new ArrayList<>(accounts); + uniquePersonas.put(persona, personaAccountsList); + } } } + } catch (InvalidAccountIDException ex) { + // Do nothing, the account has an identifier that not an + // acceptable format for the cr. } } @@ -709,7 +718,7 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac /** * Constructor. * - * @param personaNameLabel Persona name label. + * @param personaNameLabel Persona name label. * @param personaActionButton Persona action button. */ PersonaUIComponents(JLabel personaNameLabel, JButton personaActionButton) { @@ -777,8 +786,8 @@ public class ContactArtifactViewer extends javax.swing.JPanel implements Artifac for (CentralRepoAccount account : contactUniqueAccountsList) { personaPanel.addAccount(account, Bundle.ContactArtifactViewer_persona_account_justification(), Persona.Confidence.HIGH); } - - if(contactName != null && contactUniqueAccountsList.isEmpty()) { + + if (contactName != null && contactUniqueAccountsList.isEmpty()) { createPersonaDialog.setStartupPopupMessage(Bundle.ContactArtifactViewer_id_not_found_in_cr(contactName)); } diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/DefaultTableArtifactContentViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/DefaultTableArtifactContentViewer.java index 0c90993a61..75882a39b0 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/DefaultTableArtifactContentViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/DefaultTableArtifactContentViewer.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2020 Basis Technology Corp. + * Copyright 2011-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -41,7 +41,6 @@ import javax.swing.text.View; import org.apache.commons.lang.StringUtils; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.datamodel.ContentUtils; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.Content; @@ -54,6 +53,7 @@ import com.google.gson.JsonArray; import java.util.Locale; import java.util.Map; import javax.swing.SwingUtilities; +import org.sleuthkit.autopsy.coreutils.TimeZoneUtils; import org.sleuthkit.autopsy.discovery.ui.AbstractArtifactDetailsPanel; //import org.sleuthkit.autopsy.contentviewers.Bundle; @@ -343,7 +343,7 @@ public class DefaultTableArtifactContentViewer extends AbstractArtifactDetailsPa // Use Autopsy date formatting settings, not TSK defaults case DATETIME: - value = epochTimeToString(attr.getValueLong()); + value = TimeZoneUtils.getFormattedTime(attr.getValueLong()); break; case JSON: // Get the attribute's JSON value and convert to indented multiline display string @@ -454,7 +454,7 @@ public class DefaultTableArtifactContentViewer extends AbstractArtifactDetailsPa String attributeName = jsonKey; String attributeValue; if (attributeName.toUpperCase().contains("DATETIME")) { - attributeValue = epochTimeToString(Long.parseLong(jsonElement.getAsString())); + attributeValue = TimeZoneUtils.getFormattedTime(Long.parseLong(jsonElement.getAsString())); } else { attributeValue = jsonElement.getAsString(); } @@ -463,23 +463,6 @@ public class DefaultTableArtifactContentViewer extends AbstractArtifactDetailsPa sb.append(NEW_LINE).append(String.format("%s%s = null", startIndent, jsonKey)); } } - - /** - * Converts epoch time to readable string. - * - * @param epochTime epoch time value to be converted to string. - * - * @return String with human readable time. - */ - private String epochTimeToString(long epochTime) { - String dateTimeString = "0000-00-00 00:00:00"; - if (null != content && 0 != epochTime) { - dateFormatter.setTimeZone(ContentUtils.getTimeZone(content)); - dateTimeString = dateFormatter.format(new java.util.Date(epochTime * 1000)); - } - return dateTimeString; - } - } /** diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/GeneralPurposeArtifactViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/GeneralPurposeArtifactViewer.java index 1b07ecd754..e81b6705c6 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/GeneralPurposeArtifactViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/GeneralPurposeArtifactViewer.java @@ -1,7 +1,7 @@ /* * Autopsy * - * Copyright 2020 Basis Technology Corp. + * Copyright 2020-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,9 +18,9 @@ */ package org.sleuthkit.autopsy.contentviewers.artifactviewers; +import java.awt.Color; import java.awt.Component; import java.awt.Dimension; -import java.awt.Font; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; @@ -30,25 +30,30 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.logging.Level; +import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.swing.JLabel; import javax.swing.JMenuItem; import javax.swing.JPopupMenu; import javax.swing.JTextPane; import javax.swing.SwingUtilities; +import javax.swing.border.EmptyBorder; import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.tuple.Pair; import org.openide.util.NbBundle; import org.openide.util.lookup.ServiceProvider; +import org.sleuthkit.autopsy.contentviewers.layout.ContentViewerDefaults; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.ThreadConfined; -import org.sleuthkit.autopsy.datamodel.ContentUtils; +import org.sleuthkit.autopsy.coreutils.TimeZoneUtils; import org.sleuthkit.autopsy.discovery.ui.AbstractArtifactDetailsPanel; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; -import org.sleuthkit.datamodel.TimeUtilities; import org.sleuthkit.datamodel.TskCoreException; /** @@ -56,13 +61,18 @@ import org.sleuthkit.datamodel.TskCoreException; */ @ServiceProvider(service = ArtifactContentViewer.class) public class GeneralPurposeArtifactViewer extends AbstractArtifactDetailsPanel implements ArtifactContentViewer { - + private static final long serialVersionUID = 1L; private static final Logger logger = Logger.getLogger(GeneralPurposeArtifactViewer.class.getName()); // Number of columns in the gridbag layout. private final static int MAX_COLS = 4; - private final static Insets ROW_INSETS = new java.awt.Insets(0, 12, 0, 0); - private final static Insets HEADER_INSETS = new java.awt.Insets(0, 0, 0, 0); + private final static Insets ZERO_INSETS = new java.awt.Insets(0, 0, 0, 0); + + private final static Insets FIRST_HEADER_INSETS = ZERO_INSETS; + private final static Insets HEADER_INSETS = new Insets(ContentViewerDefaults.getSectionSpacing(), 0, ContentViewerDefaults.getLineSpacing(), 0); + private final static Insets VALUE_COLUMN_INSETS = new Insets(0, ContentViewerDefaults.getColumnSpacing(), ContentViewerDefaults.getLineSpacing(), 0); + private final static Insets KEY_COLUMN_INSETS = new Insets(0, ContentViewerDefaults.getSectionIndent(), ContentViewerDefaults.getLineSpacing(), 0); + private final static double GLUE_WEIGHT_X = 1.0; private final static double TEXT_WEIGHT_X = 0.0; private final static int LABEL_COLUMN = 0; @@ -92,6 +102,7 @@ public class GeneralPurposeArtifactViewer extends AbstractArtifactDetailsPanel i initComponents(); gridBagConstraints.anchor = GridBagConstraints.FIRST_LINE_START; detailsPanel.setLayout(gridBagLayout); + detailsPanel.setBorder(new EmptyBorder(ContentViewerDefaults.getPanelInsets())); } /** @@ -181,7 +192,7 @@ public class GeneralPurposeArtifactViewer extends AbstractArtifactDetailsPanel i gridBagConstraints.weighty = 0.0; gridBagConstraints.weightx = TEXT_WEIGHT_X; // keep components fixed horizontally. gridBagConstraints.fill = GridBagConstraints.NONE; - gridBagConstraints.insets = ROW_INSETS; + gridBagConstraints.insets = ZERO_INSETS; } @ThreadConfined(type = ThreadConfined.ThreadType.AWT) @@ -263,9 +274,9 @@ public class GeneralPurposeArtifactViewer extends AbstractArtifactDetailsPanel i for (BlackboardAttribute bba : attrList) { if (bba.getAttributeType().getTypeName().startsWith("TSK_DATETIME")) { if (artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY.getTypeID()) { - addNameValueRow(Bundle.GeneralPurposeArtifactViewer_dates_time(), TimeUtilities.epochToTime(bba.getValueLong(), ContentUtils.getTimeZone(artifact))); + addNameValueRow(Bundle.GeneralPurposeArtifactViewer_dates_time(), TimeZoneUtils.getFormattedTime(bba.getValueLong())); } else { - addNameValueRow(bba.getAttributeType().getDisplayName(), TimeUtilities.epochToTime(bba.getValueLong(), ContentUtils.getTimeZone(artifact))); + addNameValueRow(bba.getAttributeType().getDisplayName(), TimeZoneUtils.getFormattedTime(bba.getValueLong())); } } else if (bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT.getTypeID() && artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY.getTypeID()) { addNameValueRow(Bundle.GeneralPurposeArtifactViewer_term_label(), bba.getDisplayString()); @@ -293,7 +304,7 @@ public class GeneralPurposeArtifactViewer extends AbstractArtifactDetailsPanel i for (int key : attributeMap.keySet()) { for (BlackboardAttribute bba : attributeMap.get(key)) { if (bba.getAttributeType().getTypeName().startsWith("TSK_DATETIME")) { - addNameValueRow(bba.getAttributeType().getDisplayName(), TimeUtilities.epochToTime(bba.getValueLong(), ContentUtils.getTimeZone(artifact))); + addNameValueRow(bba.getAttributeType().getDisplayName(), TimeZoneUtils.getFormattedTime(bba.getValueLong())); } else { addNameValueRow(bba.getAttributeType().getDisplayName(), bba.getDisplayString()); } @@ -387,29 +398,26 @@ public class GeneralPurposeArtifactViewer extends AbstractArtifactDetailsPanel i headingLabel.setEditable(false); // add a blank line before the start of new section, unless it's // the first section - if (gridBagConstraints.gridy != 0) { - gridBagConstraints.gridy++; - // add to panel - addToPanel(new javax.swing.JLabel(" ")); - addLineEndGlue(); - headingLabel.setFocusable(false); - } + gridBagConstraints.insets = (gridBagConstraints.gridy == 0) + ? FIRST_HEADER_INSETS + : HEADER_INSETS; + gridBagConstraints.gridy++; gridBagConstraints.gridx = LABEL_COLUMN;; // let the header span all of the row gridBagConstraints.gridwidth = MAX_COLS; - gridBagConstraints.insets = HEADER_INSETS; // set text headingLabel.setText(headerString); // make it large and bold - headingLabel.setFont(headingLabel.getFont().deriveFont(Font.BOLD, headingLabel.getFont().getSize() + 2)); + headingLabel.setFont(ContentViewerDefaults.getHeaderFont()); + headingLabel.setMargin(ZERO_INSETS); // add to panel addToPanel(headingLabel); // reset constraints to normal gridBagConstraints.gridwidth = LABEL_WIDTH; // add line end glue addLineEndGlue(); - gridBagConstraints.insets = ROW_INSETS; + gridBagConstraints.insets = ZERO_INSETS; return headingLabel; } @@ -466,6 +474,7 @@ public class GeneralPurposeArtifactViewer extends AbstractArtifactDetailsPanel i javax.swing.JLabel keyLabel = new javax.swing.JLabel(); keyLabel.setFocusable(false); gridBagConstraints.gridy++; + gridBagConstraints.insets = KEY_COLUMN_INSETS; gridBagConstraints.gridx = LABEL_COLUMN; gridBagConstraints.gridwidth = LABEL_WIDTH; // set text @@ -493,7 +502,9 @@ public class GeneralPurposeArtifactViewer extends AbstractArtifactDetailsPanel i valueField.setFocusable(false); valueField.setEditable(false); valueField.setOpaque(false); + valueField.setMargin(ZERO_INSETS); gridBagConstraints.gridx = VALUE_COLUMN; + gridBagConstraints.insets = VALUE_COLUMN_INSETS; GridBagConstraints cloneConstraints = (GridBagConstraints) gridBagConstraints.clone(); // let the value span 2 cols cloneConstraints.gridwidth = VALUE_WIDTH; diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/MessageAccountPanel.java b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/MessageAccountPanel.java index fbf1ada856..c2847223e6 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/MessageAccountPanel.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/artifactviewers/MessageAccountPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2020 Basis Technology Corp. + * Copyright 2020-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,6 +19,7 @@ package org.sleuthkit.autopsy.contentviewers.artifactviewers; import java.awt.Dimension; +import java.awt.Insets; import java.awt.Toolkit; import java.awt.datatransfer.StringSelection; import java.awt.event.ActionEvent; @@ -44,6 +45,7 @@ import javax.swing.JTextPane; import javax.swing.LayoutStyle.ComponentPlacement; import javax.swing.SwingUtilities; import javax.swing.SwingWorker; +import javax.swing.border.EmptyBorder; import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; @@ -56,6 +58,7 @@ import org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsDialog; import org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsDialogCallback; import org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsMode; import org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsPanel; +import org.sleuthkit.autopsy.contentviewers.layout.ContentViewerDefaults; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.guiutils.ContactCache; import org.sleuthkit.datamodel.Account; @@ -77,6 +80,15 @@ final class MessageAccountPanel extends JPanel { private AccountFetcher currentFetcher = null; + + + /** + * Main constructor. + */ + MessageAccountPanel() { + this.setBorder(new EmptyBorder(ContentViewerDefaults.getPanelInsets())); + } + /** * Set the new artifact for the panel. * @@ -170,9 +182,7 @@ final class MessageAccountPanel extends JPanel { layout.setHorizontalGroup( layout.createParallelGroup(Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addGroup(getMainHorizontalGroup(layout, dataList)) - .addContainerGap(158, Short.MAX_VALUE))); + .addGroup(getMainHorizontalGroup(layout, dataList)))); layout.setVerticalGroup(getMainVerticalGroup(layout, dataList)); setLayout(layout); @@ -186,6 +196,7 @@ final class MessageAccountPanel extends JPanel { messageLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); messageLabel.setText(Bundle.MessageAccountPanel_no_matches()); + messageLabel.setFont(ContentViewerDefaults.getMessageFont()); messageLabel.setEnabled(false); messagePanel.add(messageLabel, java.awt.BorderLayout.CENTER); @@ -224,14 +235,12 @@ final class MessageAccountPanel extends JPanel { private ParallelGroup getMainVerticalGroup(GroupLayout layout, List data) { SequentialGroup group = layout.createSequentialGroup(); for (AccountContainer o : data) { - group.addGap(5) - .addComponent(o.getAccountLabel()) + group.addComponent(o.getAccountLabel()) .addGroup(o.getContactLineVerticalGroup(layout)) .addGroup(o.getPersonLineVerticalGroup(layout)); + group.addGap(ContentViewerDefaults.getSectionSpacing()); } - group.addContainerGap(83, Short.MAX_VALUE); - return layout.createParallelGroup().addGroup(group); } @@ -259,12 +268,11 @@ final class MessageAccountPanel extends JPanel { private SequentialGroup getPersonaHorizontalGroup(GroupLayout layout, List data) { SequentialGroup group = layout.createSequentialGroup(); ParallelGroup pgroup = layout.createParallelGroup(Alignment.LEADING); - group.addGap(10); for (AccountContainer o : data) { pgroup.addGroup(o.getPersonaSequentialGroup(layout)); pgroup.addGroup(o.getContactSequentialGroup(layout)); } - group.addGap(10) + group.addGap(ContentViewerDefaults.getSectionIndent()) .addGroup(pgroup) .addPreferredGap(ComponentPlacement.RELATED) .addGroup(getButtonGroup(layout, data)); @@ -343,7 +351,9 @@ final class MessageAccountPanel extends JPanel { button = new JButton(); button.addActionListener(new PersonaButtonListener(this)); + accountLabel.setMargin(new Insets(0, 0, 0, 0)); accountLabel.setText(account.getTypeSpecificID()); + accountLabel.setFont(ContentViewerDefaults.getHeaderFont()); contactDisplayName.setText(contactName); personaDisplayName.setText(persona != null ? persona.getName() : Bundle.MessageAccountPanel_unknown_label()); diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextSourcePanel.form b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextSourcePanel.form index c57a0990a8..9b2e224b22 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextSourcePanel.form +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextSourcePanel.form @@ -2,11 +2,17 @@
- - + + + + + + + + - + @@ -24,15 +30,13 @@ - - + - - + - + @@ -41,14 +45,13 @@ - - + diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextSourcePanel.java b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextSourcePanel.java index 02bd3f2ae6..0f7d2855bf 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextSourcePanel.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextSourcePanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2020 Basis Technology Corp. + * Copyright 2020-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.contentviewers.contextviewer; import java.util.ArrayList; import java.util.List; import org.sleuthkit.autopsy.contentviewers.contextviewer.ContextViewer.DateTimePanel; +import org.sleuthkit.autopsy.contentviewers.layout.ContentViewerDefaults; import org.sleuthkit.autopsy.directorytree.DirectoryTreeTopComponent; import org.sleuthkit.datamodel.BlackboardArtifact; import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT; @@ -75,8 +76,10 @@ public final class ContextSourcePanel extends javax.swing.JPanel implements Date jSourceNameLabel = new javax.swing.JLabel(); jSourceTextLabel = new javax.swing.JLabel(); - setBackground(new java.awt.Color(255, 255, 255)); - setPreferredSize(new java.awt.Dimension(495, 75)); + setBackground(ContentViewerDefaults.getPanelBackground()); + setMaximumSize(new java.awt.Dimension(495, 55)); + setMinimumSize(new java.awt.Dimension(300, 55)); + setPreferredSize(new java.awt.Dimension(495, 55)); org.openide.awt.Mnemonics.setLocalizedText(jSourceGoToResultButton, org.openide.util.NbBundle.getMessage(ContextSourcePanel.class, "ContextSourcePanel.jSourceGoToResultButton.text")); // NOI18N jSourceGoToResultButton.addActionListener(new java.awt.event.ActionListener() { @@ -94,26 +97,23 @@ public final class ContextSourcePanel extends javax.swing.JPanel implements Date layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addGap(50, 50, 50) .addComponent(jSourceNameLabel) .addGap(36, 36, 36) - .addComponent(jSourceTextLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGap(260, 260, 260)) + .addComponent(jSourceTextLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 360, Short.MAX_VALUE)) .addGroup(layout.createSequentialGroup() - .addGap(90, 90, 90) + .addGap(40, 40, 40) .addComponent(jSourceGoToResultButton) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addGap(2, 2, 2) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jSourceNameLabel) .addComponent(jSourceTextLabel)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jSourceGoToResultButton) - .addGap(0, 0, 0)) + .addGap(0, 11, Short.MAX_VALUE)) ); }// //GEN-END:initComponents diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextUsagePanel.form b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextUsagePanel.form index a3e2a90f84..2faf5bf779 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextUsagePanel.form +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextUsagePanel.form @@ -2,11 +2,17 @@ - - + + + + + + + + - + @@ -24,30 +30,28 @@ - - + - - + - + - + - + diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextUsagePanel.java b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextUsagePanel.java index 4a96dfcffd..c3c74da190 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextUsagePanel.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextUsagePanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2020 Basis Technology Corp. + * Copyright 2020-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.contentviewers.contextviewer; import java.util.ArrayList; import java.util.List; +import org.sleuthkit.autopsy.contentviewers.layout.ContentViewerDefaults; import org.sleuthkit.autopsy.directorytree.DirectoryTreeTopComponent; import org.sleuthkit.datamodel.BlackboardArtifact; import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT; @@ -74,8 +75,10 @@ public final class ContextUsagePanel extends javax.swing.JPanel implements Conte jUsageNameLabel = new javax.swing.JLabel(); jUsageTextLabel = new javax.swing.JLabel(); - setBackground(new java.awt.Color(255, 255, 255)); - setPreferredSize(new java.awt.Dimension(495, 75)); + setBackground(ContentViewerDefaults.getPanelBackground()); + setMaximumSize(new java.awt.Dimension(32767, 55)); + setMinimumSize(new java.awt.Dimension(300, 55)); + setPreferredSize(new java.awt.Dimension(495, 55)); org.openide.awt.Mnemonics.setLocalizedText(jUsageGoToResultButton, org.openide.util.NbBundle.getMessage(ContextUsagePanel.class, "ContextUsagePanel.jUsageGoToResultButton.text")); // NOI18N jUsageGoToResultButton.addActionListener(new java.awt.event.ActionListener() { @@ -93,25 +96,23 @@ public final class ContextUsagePanel extends javax.swing.JPanel implements Conte layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addGap(50, 50, 50) .addComponent(jUsageNameLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(jUsageTextLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 240, Short.MAX_VALUE) - .addGap(36, 36, 36)) + .addComponent(jUsageTextLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 420, Short.MAX_VALUE)) .addGroup(layout.createSequentialGroup() - .addGap(90, 90, 90) + .addGap(40, 40, 40) .addComponent(jUsageGoToResultButton) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap(275, javax.swing.GroupLayout.PREFERRED_SIZE)) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addGap(2, 2, 2) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jUsageTextLabel) .addComponent(jUsageNameLabel, javax.swing.GroupLayout.Alignment.TRAILING)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jUsageGoToResultButton)) + .addComponent(jUsageGoToResultButton) + .addGap(0, 11, Short.MAX_VALUE)) ); }// //GEN-END:initComponents diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextViewer.form b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextViewer.form index 01c484ba9e..47c452eccb 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextViewer.form +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextViewer.form @@ -4,38 +4,19 @@ - - + + - - - - - - - - - - - - - - - - - - - + + - - - - + + @@ -50,38 +31,19 @@ - - + + - - - - - - - - - - - - - - - - - - - + + - - - - + + @@ -95,31 +57,9 @@ - - - - - - - - - - - - - - - - - - - - - - - - + + @@ -127,6 +67,9 @@ + + + @@ -137,11 +80,8 @@ - - - - + @@ -171,8 +111,8 @@ - - + + diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextViewer.java index bfa0cfc3e9..eae47348d2 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextViewer.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2019 Basis Technology Corp. + * Copyright 2019-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,6 +19,7 @@ package org.sleuthkit.autopsy.contentviewers.contextviewer; import java.awt.Component; +import java.awt.Insets; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -28,12 +29,14 @@ import java.util.Map; import java.util.logging.Level; import javax.swing.BoxLayout; import static javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED; +import javax.swing.border.EmptyBorder; import org.apache.commons.lang.StringUtils; import org.openide.nodes.Node; import org.openide.util.NbBundle; import org.openide.util.lookup.ServiceProvider; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; +import org.sleuthkit.autopsy.contentviewers.layout.ContentViewerDefaults; import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.AbstractFile; @@ -55,6 +58,10 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte private static final Logger logger = Logger.getLogger(ContextViewer.class.getName()); private static final int ARTIFACT_STR_MAX_LEN = 1024; private static final int ATTRIBUTE_STR_MAX_LEN = 200; + + private final static Insets FIRST_HEADER_INSETS = new Insets(0, 0, 0, 0); + private final static Insets HEADER_INSETS = new Insets(ContentViewerDefaults.getSectionSpacing(), 0, ContentViewerDefaults.getLineSpacing(), 0); + private final static Insets DATA_ROW_INSETS = new Insets(0, ContentViewerDefaults.getSectionIndent(), ContentViewerDefaults.getLineSpacing(), 0); // defines a list of artifacts that provide context for a file private static final List CONTEXT_ARTIFACTS = new ArrayList<>(); @@ -91,75 +98,30 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte javax.swing.JLabel jUnknownLabel = new javax.swing.JLabel(); jScrollPane = new javax.swing.JScrollPane(); - jSourcePanel.setBackground(javax.swing.UIManager.getDefaults().getColor("window")); + jSourcePanel.setBorder(new EmptyBorder(FIRST_HEADER_INSETS)); + jSourcePanel.setLayout(new javax.swing.BoxLayout(jSourcePanel, javax.swing.BoxLayout.PAGE_AXIS)); - jSourceLabel.setFont(jSourceLabel.getFont().deriveFont(jSourceLabel.getFont().getStyle() | java.awt.Font.BOLD, jSourceLabel.getFont().getSize()+1)); + jSourceLabel.setFont(ContentViewerDefaults.getHeaderFont()); org.openide.awt.Mnemonics.setLocalizedText(jSourceLabel, org.openide.util.NbBundle.getMessage(ContextViewer.class, "ContextViewer.jSourceLabel.text")); // NOI18N + jSourcePanel.add(jSourceLabel); - javax.swing.GroupLayout jSourcePanelLayout = new javax.swing.GroupLayout(jSourcePanel); - jSourcePanel.setLayout(jSourcePanelLayout); - jSourcePanelLayout.setHorizontalGroup( - jSourcePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jSourcePanelLayout.createSequentialGroup() - .addGap(40, 40, 40) - .addComponent(jSourceLabel) - .addContainerGap(304, Short.MAX_VALUE)) + jUsagePanel.setBorder(new EmptyBorder(HEADER_INSETS)); + jUsagePanel.setLayout(new javax.swing.BoxLayout(jUsagePanel, javax.swing.BoxLayout.PAGE_AXIS)); + + jUsageLabel.setFont(ContentViewerDefaults.getHeaderFont() ); - jSourcePanelLayout.setVerticalGroup( - jSourcePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jSourcePanelLayout.createSequentialGroup() - .addGap(5, 5, 5) - .addComponent(jSourceLabel) - .addGap(2, 2, 2)) - ); - - jUsagePanel.setBackground(javax.swing.UIManager.getDefaults().getColor("window")); - - jUsageLabel.setFont(jUsageLabel.getFont().deriveFont(jUsageLabel.getFont().getStyle() | java.awt.Font.BOLD, jUsageLabel.getFont().getSize()+1)); org.openide.awt.Mnemonics.setLocalizedText(jUsageLabel, org.openide.util.NbBundle.getMessage(ContextViewer.class, "ContextViewer.jUsageLabel.text")); // NOI18N + jUsagePanel.add(jUsageLabel); - javax.swing.GroupLayout jUsagePanelLayout = new javax.swing.GroupLayout(jUsagePanel); - jUsagePanel.setLayout(jUsagePanelLayout); - jUsagePanelLayout.setHorizontalGroup( - jUsagePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jUsagePanelLayout.createSequentialGroup() - .addGap(40, 40, 40) - .addComponent(jUsageLabel) - .addContainerGap(298, Short.MAX_VALUE)) - ); - jUsagePanelLayout.setVerticalGroup( - jUsagePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jUsagePanelLayout.createSequentialGroup() - .addGap(2, 2, 2) - .addComponent(jUsageLabel) - .addGap(2, 2, 2)) - ); - - jUnknownPanel.setBackground(new java.awt.Color(255, 255, 255)); + jUnknownPanel.setLayout(new javax.swing.BoxLayout(jUnknownPanel, javax.swing.BoxLayout.PAGE_AXIS)); org.openide.awt.Mnemonics.setLocalizedText(jUnknownLabel, org.openide.util.NbBundle.getMessage(ContextViewer.class, "ContextViewer.jUnknownLabel.text")); // NOI18N + jUnknownLabel.setBorder(new EmptyBorder(DATA_ROW_INSETS)); + jUnknownPanel.add(jUnknownLabel); - javax.swing.GroupLayout jUnknownPanelLayout = new javax.swing.GroupLayout(jUnknownPanel); - jUnknownPanel.setLayout(jUnknownPanelLayout); - jUnknownPanelLayout.setHorizontalGroup( - jUnknownPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jUnknownPanelLayout.createSequentialGroup() - .addGap(50, 50, 50) - .addComponent(jUnknownLabel) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - ); - jUnknownPanelLayout.setVerticalGroup( - jUnknownPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jUnknownPanelLayout.createSequentialGroup() - .addGap(2, 2, 2) - .addComponent(jUnknownLabel) - .addGap(2, 2, 2)) - ); + setPreferredSize(new java.awt.Dimension(0, 0)); - setBackground(new java.awt.Color(255, 255, 255)); - setPreferredSize(new java.awt.Dimension(495, 358)); - - jScrollPane.setBackground(new java.awt.Color(255, 255, 255)); + jScrollPane.setPreferredSize(new java.awt.Dimension(16, 16)); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); @@ -275,13 +237,17 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte } } javax.swing.JPanel contextContainer = new javax.swing.JPanel(); - contextContainer.add(jSourcePanel); contextContainer.setLayout(new BoxLayout(contextContainer, BoxLayout.Y_AXIS)); + contextContainer.setBorder(new EmptyBorder(ContentViewerDefaults.getPanelInsets())); + + contextContainer.add(jSourcePanel); + if (contextSourcePanels.isEmpty()) { contextContainer.add(jUnknownPanel); } else { for (javax.swing.JPanel sourcePanel : contextSourcePanels) { contextContainer.add(sourcePanel); + contextContainer.setAlignmentX(0); } } contextContainer.add(jUsagePanel); @@ -290,10 +256,11 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte } else { for (javax.swing.JPanel usagePanel : contextUsagePanels) { contextContainer.add(usagePanel); + contextContainer.setAlignmentX(0); } } - contextContainer.setBackground(javax.swing.UIManager.getDefaults().getColor("window")); + contextContainer.setBackground(ContentViewerDefaults.getPanelBackground()); contextContainer.setEnabled(foundASource); contextContainer.setVisible(foundASource); jScrollPane.getViewport().setView(contextContainer); @@ -346,6 +313,8 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte String sourceName = Bundle.ContextViewer_attachmentSource(); String sourceText = msgArtifactToAbbreviatedString(associatedArtifact); ContextSourcePanel sourcePanel = new ContextSourcePanel(sourceName, sourceText, associatedArtifact, dateTime); + sourcePanel.setBorder(new EmptyBorder(DATA_ROW_INSETS)); + sourcePanel.setAlignmentX(0); contextSourcePanels.add(sourcePanel); } else if (BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID() == associatedArtifact.getArtifactTypeID() @@ -353,18 +322,24 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte String sourceName = Bundle.ContextViewer_downloadSource(); String sourceText = webDownloadArtifactToString(associatedArtifact); ContextSourcePanel sourcePanel = new ContextSourcePanel(sourceName, sourceText, associatedArtifact, dateTime); + sourcePanel.setBorder(new EmptyBorder(DATA_ROW_INSETS)); + sourcePanel.setAlignmentX(0); contextSourcePanels.add(sourcePanel); } else if (BlackboardArtifact.ARTIFACT_TYPE.TSK_RECENT_OBJECT.getTypeID() == associatedArtifact.getArtifactTypeID()) { String sourceName = Bundle.ContextViewer_recentDocs(); String sourceText = recentDocArtifactToString(associatedArtifact); - ContextUsagePanel usagePanel = new ContextUsagePanel(sourceName, sourceText, associatedArtifact, dateTime); + ContextUsagePanel usagePanel = new ContextUsagePanel(sourceName, sourceText, associatedArtifact, dateTime); + usagePanel.setBorder(new EmptyBorder(DATA_ROW_INSETS)); + usagePanel.setAlignmentX(0); contextUsagePanels.add(usagePanel); } else if (BlackboardArtifact.ARTIFACT_TYPE.TSK_PROG_RUN.getTypeID() == associatedArtifact.getArtifactTypeID()) { String sourceName = Bundle.ContextViewer_programExecution(); String sourceText = programExecArtifactToString(associatedArtifact); - ContextUsagePanel usagePanel = new ContextUsagePanel(sourceName, sourceText, associatedArtifact, dateTime); + ContextUsagePanel usagePanel = new ContextUsagePanel(sourceName, sourceText, associatedArtifact, dateTime); + usagePanel.setBorder(new EmptyBorder(DATA_ROW_INSETS)); + usagePanel.setAlignmentX(0); contextUsagePanels.add(usagePanel); } diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/layout/ContentViewerDefaults.java b/Core/src/org/sleuthkit/autopsy/contentviewers/layout/ContentViewerDefaults.java new file mode 100644 index 0000000000..65023b9110 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/layout/ContentViewerDefaults.java @@ -0,0 +1,167 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2021 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may 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.contentviewers.layout; + +import java.awt.Font; +import java.awt.Insets; +import java.awt.Toolkit; +import java.awt.Color; +import javax.swing.UIManager; + +/** + * Default values for layout of content values. + */ +public class ContentViewerDefaults { + + private static final Font DEFAULT_FONT = UIManager.getDefaults().getFont("Label.font"); + + // based on https://stackoverflow.com/questions/5829703/java-getting-a-font-with-a-specific-height-in-pixels/26564924#26564924 + private static final Double PT_TO_PX = Toolkit.getDefaultToolkit().getScreenResolution() / 72.0; + + private static final int DEFAULT_FONT_PX = (int) Math.round(DEFAULT_FONT.getSize() * PT_TO_PX); + + private static final Font SUB_HEADER_FONT = DEFAULT_FONT.deriveFont(Font.BOLD); + + private static final Font HEADER_FONT = DEFAULT_FONT.deriveFont(Font.BOLD, DEFAULT_FONT.getSize() + 2); + + private static final Font MESSAGE_FONT = DEFAULT_FONT.deriveFont(Font.ITALIC); + + private static final Font MONOSPACED_FONT = new Font(Font.MONOSPACED, Font.PLAIN, DEFAULT_FONT.getSize()); + + private static final Insets DEFAULT_PANEL_INSETS = UIManager.getDefaults().getInsets("TextPane.margin"); + + private static final int DEFAULT_INDENT = DEFAULT_FONT_PX; + private static final int DEFAULT_SECTION_SPACING = DEFAULT_FONT_PX; + + private static final int DEFAULT_COLUMN_SPACING = (int) Math.round((double) DEFAULT_FONT_PX / 3); + + private static final int DEFAULT_LINE_SPACING = (int) Math.round((double) DEFAULT_FONT_PX / 5); + + private static final Color DEFAULT_BACKGROUND = UIManager.getColor("Panel.background"); + + /** + * Returns the horizontal spacing between columns in a table in pixels. + * + * @return The horizontal spacing between columns in a table in pixels. + */ + public static int getColumnSpacing() { + return DEFAULT_COLUMN_SPACING; + } + + /** + * Returns the default font to be used. + * + * @return the default font to be used. + */ + public static Font getFont() { + return DEFAULT_FONT; + } + + /** + * Returns the font to be displayed for messages. + * + * @return The font to be displayed for messages. + */ + public static Font getMessageFont() { + return MESSAGE_FONT; + } + + /** + * Returns the font to be displayed for messages. + * + * @return The font to be displayed for messages. + */ + public static Font getHeaderFont() { + return HEADER_FONT; + } + + /** + * Returns the font to be displayed for sub headers. + * + * @return The font to be displayed for sub headers. + */ + public static Font getSubHeaderFont() { + return SUB_HEADER_FONT; + } + + /** + * Returns the font to be used for normal monospace. + * + * @return The font to be used for normal monospace. + */ + public static Font getMonospacedFont() { + return MONOSPACED_FONT; + } + + /** + * Returns the insets of the content within the parent content viewer panel. + * + * @return The insets of the content within the parent content viewer panel. + */ + public static Insets getPanelInsets() { + return DEFAULT_PANEL_INSETS; + } + + /** + * Returns the size in pixels that sections should be indented. + * + * @return The size in pixels that sections should be indented. + */ + public static Integer getSectionIndent() { + return DEFAULT_INDENT; + } + + /** + * Returns the spacing between sections in pixels. + * + * @return The spacing between sections in pixels. + */ + public static Integer getSectionSpacing() { + return DEFAULT_SECTION_SPACING; + } + + /** + * Returns the spacing between lines of text in pixels. + * + * @return The spacing between lines of text in pixels. + */ + public static Integer getLineSpacing() { + return DEFAULT_LINE_SPACING; + } + + /** + * Returns the color to be used as the background of the panel. + * + * @return The color to be used as the background of the panel. + */ + public static Color getPanelBackground() { + return DEFAULT_BACKGROUND; + } + + /** + * Returns the ratio of point size to pixel size for the user's screen + * resolution. + * + * @return The ratio of point size to pixel size for the user's screen + * resolution. + */ + public static Double getPtToPx() { + return PT_TO_PX; + } +} diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/layout/ContentViewerHtmlStyles.java b/Core/src/org/sleuthkit/autopsy/contentviewers/layout/ContentViewerHtmlStyles.java new file mode 100644 index 0000000000..6321f5c78c --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/layout/ContentViewerHtmlStyles.java @@ -0,0 +1,194 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2021 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may 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.contentviewers.layout; + +import java.awt.Font; +import javax.swing.JTextPane; +import javax.swing.text.EditorKit; +import javax.swing.text.html.HTMLEditorKit; +import javax.swing.text.html.StyleSheet; + +/** + * The style sheet an class names to be used with content viewers using html + * rendering. + */ +public class ContentViewerHtmlStyles { + + // html stylesheet classnames for components + private static final String CLASS_PREFIX = ContentViewerHtmlStyles.class.getSimpleName(); + + private static final String HEADER_CLASSNAME = CLASS_PREFIX + "header"; + private static final String SUB_HEADER_CLASSNAME = CLASS_PREFIX + "subHeader"; + + private static final String MESSAGE_CLASSNAME = CLASS_PREFIX + "message"; + private static final String TEXT_CLASSNAME = CLASS_PREFIX + "text"; + private static final String MONOSPACED_CLASSNAME = CLASS_PREFIX + "monospaced"; + private static final String INDENTED_CLASSNAME = CLASS_PREFIX + "indent"; + private static final String SPACED_SECTION_CLASSNAME = CLASS_PREFIX + "spacedSection"; + private static final String KEY_COLUMN_TD_CLASSNAME = CLASS_PREFIX + "keyKolumn"; + + private static final Font DEFAULT_FONT = ContentViewerDefaults.getFont(); + private static final Font MESSAGE_FONT = ContentViewerDefaults.getMessageFont(); + private static final Font HEADER_FONT = ContentViewerDefaults.getHeaderFont(); + private static final Font SUB_HEADER_FONT = ContentViewerDefaults.getSubHeaderFont(); + private static final Font MONOSPACED_FONT = ContentViewerDefaults.getMonospacedFont(); + + // additional styling for components + private static final String STYLE_SHEET_RULE + = String.format(" .%s { font-family: %s; font-size: %dpt;font-style:italic; margin: 0px; padding: 0px 0px %dpt 0px; } ", + MESSAGE_CLASSNAME, MESSAGE_FONT.getFamily(), MESSAGE_FONT.getSize(), pxToPt(ContentViewerDefaults.getLineSpacing())) + + String.format(" .%s { font-family: %s; font-size: %dpt; font-weight: bold; margin: 0px; padding: 0px 0px %dpt 0px; } ", + HEADER_CLASSNAME, HEADER_FONT.getFamily(), HEADER_FONT.getSize(), pxToPt(ContentViewerDefaults.getLineSpacing())) + + String.format(" .%s { font-family: %s; font-size: %dpt; font-weight: bold; margin: 0px; padding: 0px 0px %dpt 0px; } ", + SUB_HEADER_CLASSNAME, SUB_HEADER_FONT.getFamily(), SUB_HEADER_FONT.getSize(), pxToPt(ContentViewerDefaults.getLineSpacing())) + + String.format(" .%s { font-family: %s; font-size: %dpt; margin: 0px; padding: 0px 0px %dpt 0px; } ", + TEXT_CLASSNAME, DEFAULT_FONT.getFamily(), DEFAULT_FONT.getSize(), pxToPt(ContentViewerDefaults.getLineSpacing())) + + String.format(" .%s { font-family: %s; font-size: %dpt; margin: 0px; padding: 0px 0px %dpt 0px; } ", + MONOSPACED_CLASSNAME, Font.MONOSPACED, MONOSPACED_FONT.getSize(), pxToPt(ContentViewerDefaults.getLineSpacing())) + + String.format(" .%s { padding-left: %dpt } ", + INDENTED_CLASSNAME, pxToPt(ContentViewerDefaults.getSectionIndent())) + + String.format(" .%s { padding-top: %dpt } ", + SPACED_SECTION_CLASSNAME, pxToPt(ContentViewerDefaults.getSectionSpacing())) + + String.format(" .%s { padding-right: %dpt; white-space: nowrap; } ", + KEY_COLUMN_TD_CLASSNAME, pxToPt(ContentViewerDefaults.getColumnSpacing())); + + private static final StyleSheet STYLE_SHEET = new StyleSheet(); + + static { + // add the style rule to the style sheet. + STYLE_SHEET.addRule(STYLE_SHEET_RULE); + } + + /** + * Converts pixel size to point size. The html rendering seems more + * consistent with point size versus pixel size. + * + * @param px The pixel size. + * + * @return The point size. + */ + private static int pxToPt(int px) { + return (int) Math.round(((double) px) / ContentViewerDefaults.getPtToPx()); + } + + /** + * Returns the class name to use for header text. + * + * @return The class name to use for header text. + */ + public static String getHeaderClassName() { + return HEADER_CLASSNAME; + } + + /** + * Returns the class name to use for sub header text. + * + * @return The class name to use for sub header text. + */ + public static String getSubHeaderClassName() { + return SUB_HEADER_CLASSNAME; + } + + /** + * Returns the class name to use for message text. + * + * @return The class name to use for message text. + */ + public static String getMessageClassName() { + return MESSAGE_CLASSNAME; + } + + /** + * Returns the class name to use for regular text. + * + * @return The class name to use for regular text. + */ + public static String getTextClassName() { + return TEXT_CLASSNAME; + } + + /** + * Returns the class name to use for monospaced text. + * + * @return The class name to use for monospaced text. + */ + public static String getMonospacedClassName() { + return MONOSPACED_CLASSNAME; + } + + /** + * Returns the class name to use for an indented (left padding) section. + * + * @return The class name to use for an indented (left padding) section. + */ + public static String getIndentedClassName() { + return INDENTED_CLASSNAME; + } + + /** + * Returns the class name to use for a section with spacing (top padding) + * section. + * + * @return The class name to use for a section with spacing (top padding) + * section. + */ + public static String getSpacedSectionClassName() { + return SPACED_SECTION_CLASSNAME; + } + + /** + * Returns the class name to use for a key column with right spacing (right + * padding). + * + * @return The class name to use for a key column with right spacing (right + * padding). + */ + public static String getKeyColumnClassName() { + return KEY_COLUMN_TD_CLASSNAME; + } + + /** + * If the textPane has an HTMLEditorKit, specifies the + * ContentViewerHTMLStyles styles to use refreshing the styles. + * + * @param textPane The text pane. + */ + public static void setStyles(JTextPane textPane) { + EditorKit editorKit = textPane.getEditorKit(); + if (editorKit instanceof HTMLEditorKit) { + ((HTMLEditorKit) editorKit).setStyleSheet(STYLE_SHEET); + } + } + + /** + * Sets up a JTextPane for html rendering using the css class names + * specified in this class. + * + * @param textPane The JTextPane to set up for content viewer html + * rendering. + */ + public static void setupHtmlJTextPane(JTextPane textPane) { + textPane.setContentType("text/html;charset=UTF-8"); //NON-NLS + HTMLEditorKit kit = new HTMLEditorKit(); + textPane.setEditorKit(kit); + kit.setStyleSheet(STYLE_SHEET); + textPane.setMargin(ContentViewerDefaults.getPanelInsets()); + textPane.setBackground(ContentViewerDefaults.getPanelBackground()); + } +} diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/Bundle_ja.properties new file mode 100644 index 0000000000..9b0e640012 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/Bundle_ja.properties @@ -0,0 +1,21 @@ +#Mon Jun 14 12:23:19 UTC 2021 +OsAccountDataPanel_administrator_title=\u7ba1\u7406\u8005 +OsAccountDataPanel_basic_address=\u4f4f\u6240 +OsAccountDataPanel_basic_admin=\u7ba1\u7406\u8005 +OsAccountDataPanel_basic_creationDate=\u4f5c\u6210\u65e5 +OsAccountDataPanel_basic_fullname=\u6c0f\u540d +OsAccountDataPanel_basic_login=\u30ed\u30b0\u30a4\u30f3 +OsAccountDataPanel_basic_title=\u57fa\u672c\u30d7\u30ed\u30d1\u30c6\u30a3 +OsAccountDataPanel_basic_type=\u30bf\u30a4\u30d7 +OsAccountDataPanel_data_accessed_title=\u524d\u56de\u306e\u30ed\u30b0\u30a4\u30f3 +OsAccountDataPanel_host_count_title=\u30ed\u30b0\u30a4\u30f3\u6570 +OsAccountDataPanel_host_section_title={0} \u8a73\u7d30 +OsAccountDataPanel_realm_address=\u4f4f\u6240 +OsAccountDataPanel_realm_confidence=\u4fe1\u983c\u5ea6 +OsAccountDataPanel_realm_name=\u540d\u524d +OsAccountDataPanel_realm_scope=\u30b9\u30b3\u30fc\u30d7 +OsAccountDataPanel_realm_title=\u5206\u91ce\u30d7\u30ed\u30d1\u30c6\u30a3 +OsAccountDataPanel_realm_unknown=\u4e0d\u660e +OsAccountViewer_title=OS\u30a2\u30ab\u30a6\u30f3\u30c8 +OsAccountViewer_tooltip=\u9078\u629e\u3057\u305f\u30ce\u30fc\u30c9\u306b\u95a2\u9023\u3059\u308b\u30aa\u30da\u30ec\u30fc\u30c6\u30a3\u30f3\u30b0\u30b7\u30b9\u30c6\u30e0\u30a2\u30ab\u30a6\u30f3\u30c8\u306e\u30d3\u30e5\u30fc\u30a2\u3002 +TableDataPanel.titleLabel.text=\u79f0\u53f7 diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountDataPanel.java b/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountDataPanel.java index 2c88660cb0..4eef25539f 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountDataPanel.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountDataPanel.java @@ -19,7 +19,6 @@ package org.sleuthkit.autopsy.contentviewers.osaccount; import java.awt.BorderLayout; -import java.awt.Font; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; @@ -38,9 +37,12 @@ import javax.swing.Box; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.SwingWorker; +import javax.swing.border.EmptyBorder; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.contentviewers.layout.ContentViewerDefaults; import org.sleuthkit.autopsy.contentviewers.osaccount.SectionData.RowData; +import org.sleuthkit.autopsy.coreutils.TimeZoneUtils; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.Host; @@ -61,7 +63,11 @@ public class OsAccountDataPanel extends JPanel { private static final int KEY_COLUMN = 0; private static final int VALUE_COLUMN = 1; - + + private final static Insets FIRST_HEADER_INSETS = new Insets(0, 0, 0, 0); + private final static Insets HEADER_INSETS = new Insets(ContentViewerDefaults.getSectionSpacing(), 0, ContentViewerDefaults.getLineSpacing(), 0); + private final static Insets VALUE_COLUMN_INSETS = new Insets(0, ContentViewerDefaults.getColumnSpacing(), ContentViewerDefaults.getLineSpacing(), 0); + private final static Insets KEY_COLUMN_INSETS = new Insets(0, ContentViewerDefaults.getSectionIndent(), ContentViewerDefaults.getLineSpacing(), 0); private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("MMM dd yyyy", US); private PanelDataFetcher dataFetcher = null; @@ -76,6 +82,7 @@ public class OsAccountDataPanel extends JPanel { */ private void initialize() { this.setLayout(new GridBagLayout()); + this.setBorder(new EmptyBorder(ContentViewerDefaults.getPanelInsets())); } /** @@ -184,12 +191,8 @@ public class OsAccountDataPanel extends JPanel { data.addData(Bundle.OsAccountDataPanel_basic_type(), account.getOsAccountType().isPresent() ? account.getOsAccountType().get().getName() : ""); - Optional crTime = account.getCreationTime(); - if (crTime.isPresent()) { - data.addData(Bundle.OsAccountDataPanel_basic_creationDate(), DATE_FORMAT.format(new Date(crTime.get() * 1000))); - } else { - data.addData(Bundle.OsAccountDataPanel_basic_creationDate(), ""); - } + Optional crTime = account.getCreationTime(); + data.addData(Bundle.OsAccountDataPanel_basic_creationDate(), crTime.isPresent() ? TimeZoneUtils.getFormattedTime(crTime.get()) : ""); return data; } @@ -269,7 +272,7 @@ public class OsAccountDataPanel extends JPanel { private void addTitle(String title, int row) { JLabel label = new JLabel(title); // Make the title bold. - label.setFont(label.getFont().deriveFont(Font.BOLD)); + label.setFont(ContentViewerDefaults.getHeaderFont()); add(label, getTitleContraints(row)); } @@ -312,7 +315,9 @@ public class OsAccountDataPanel extends JPanel { constraints.anchor = GridBagConstraints.NORTHWEST; constraints.fill = GridBagConstraints.HORIZONTAL; constraints.weightx = 1; - constraints.insets = new Insets(5, 5, 5, 9); + constraints.insets = (row == 0) + ? FIRST_HEADER_INSETS + : HEADER_INSETS; return constraints; } @@ -332,7 +337,7 @@ public class OsAccountDataPanel extends JPanel { constraints.gridwidth = 1; // The title goes across the other columns constraints.gridheight = 1; constraints.anchor = GridBagConstraints.WEST; - constraints.insets = new Insets(0, 13, 5, 5); + constraints.insets = KEY_COLUMN_INSETS; return constraints; } @@ -352,8 +357,8 @@ public class OsAccountDataPanel extends JPanel { constraints.gridwidth = 1; // The title goes across the other columns constraints.gridheight = 1; constraints.fill = GridBagConstraints.HORIZONTAL; + constraints.insets = VALUE_COLUMN_INSETS; constraints.weightx = 1; - constraints.insets = new Insets(0, 5, 5, 5); return constraints; } diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountViewer.java index 2195e4fbdb..4b2b4ac972 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountViewer.java @@ -37,7 +37,7 @@ import org.sleuthkit.datamodel.TskCoreException; /** * DataContentViewer for OsAccounts. */ -@ServiceProvider(service = DataContentViewer.class, position = 7) +@ServiceProvider(service = DataContentViewer.class, position = 5) public class OsAccountViewer extends javax.swing.JPanel implements DataContentViewer { private static final long serialVersionUID = 1L; diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/textcontentviewer/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/contentviewers/textcontentviewer/Bundle_ja.properties index 8ce5b3ba54..120b0844e2 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/textcontentviewer/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/textcontentviewer/Bundle_ja.properties @@ -1,23 +1,25 @@ -StringsTextViewer.goToPageTextField.msgDlg=1 \u304b\u3089 {0} \u307e\u3067\u306e\u6709\u52b9\u306a\u30da\u30fc\u30b8\u756a\u53f7\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044 +#Thu Jul 01 11:56:41 UTC 2021 +StringContentPanel_Loading_String=\u30c6\u30ad\u30b9\u30c8\u3092\u8aad\u8fbc\u4e2d... +StringsContentPanel.copyMenuItem.text=\u30b3\u30d4\u30fc +StringsContentPanel.currentPageLabel.text_1=1 +StringsContentPanel.goToPageLabel.text=\u30da\u30fc\u30b8\u306b\u79fb\u52d5\: +StringsContentPanel.goToPageTextField.text= +StringsContentPanel.languageCombo.toolTipText=\u30d0\u30a4\u30ca\u30ea\u30fc\u30c7\u30fc\u30bf\u306e\u6587\u5b57\u5217\u306e\u89e3\u91c8(\u62bd\u51fa\u304a\u3088\u3073\u30c7\u30b3\u30fc\u30c9)\u4e2d\u306b\u8a66\u3059\u8a00\u8a9e +StringsContentPanel.languageLabel.text=\u30b9\u30af\u30ea\u30d7\u30c8\: +StringsContentPanel.languageLabel.toolTipText= +StringsContentPanel.nextPageButton.text= +StringsContentPanel.ofLabel.text_1=/ +StringsContentPanel.pageLabel.text_1=\u30da\u30fc\u30b8\: +StringsContentPanel.pageLabel2.text=\u30da\u30fc\u30b8 +StringsContentPanel.prevPageButton.text= +StringsContentPanel.selectAllMenuItem.text=\u3059\u3079\u3066\u9078\u629e +StringsContentPanel.totalPageLabel.text_1=100 StringsTextViewer.goToPageTextField.err=\u7121\u52b9\u306a\u30da\u30fc\u30b8\u756a\u53f7\u3067\u3059 -StringsTextViewer.setDataView.errorText=(\u30aa\u30d5\u30bb\u30c3\u30c8 {0}-{1} \u3092\u8aad\u307f\u8fbc\u3081\u307e\u305b\u3093\u3067\u3057\u305f) +StringsTextViewer.goToPageTextField.msgDlg=1 \u304b\u3089 {0} \u307e\u3067\u306e\u6709\u52b9\u306a\u30da\u30fc\u30b8\u756a\u53f7\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044 StringsTextViewer.setDataView.errorNoText=(\u30aa\u30d5\u30bb\u30c3\u30c8 {0}-{1} \u306b\u306f\u30c6\u30ad\u30b9\u30c8\u304c\u542b\u307e\u308c\u3066\u3044\u307e\u305b\u3093) +StringsTextViewer.setDataView.errorText=(\u30aa\u30d5\u30bb\u30c3\u30c8 {0}-{1} \u3092\u8aad\u307f\u8fbc\u3081\u307e\u305b\u3093\u3067\u3057\u305f) StringsTextViewer.title=\u6587\u5b57\u5217 StringsTextViewer.toolTip=\u30d5\u30a1\u30a4\u30eb\u304b\u3089\u62bd\u51fa\u3057\u305fASCII\u6587\u5b57\u5217\u3068Unicode\u6587\u5b57\u5217\u3092\u8868\u793a -StringsContentPanel.selectAllMenuItem.text=\u3059\u3079\u3066\u9078\u629e -StringsContentPanel.currentPageLabel.text_1=1 -StringsContentPanel.copyMenuItem.text=\u30b3\u30d4\u30fc -StringsContentPanel.ofLabel.text_1=/ -StringsContentPanel.totalPageLabel.text_1=100 -StringsContentPanel.languageLabel.toolTipText= -StringsContentPanel.languageLabel.text=\u30b9\u30af\u30ea\u30d7\u30c8: -StringsContentPanel.languageCombo.toolTipText=\u30d0\u30a4\u30ca\u30ea\u30fc\u30c7\u30fc\u30bf\u306e\u6587\u5b57\u5217\u306e\u89e3\u91c8(\u62bd\u51fa\u304a\u3088\u3073\u30c7\u30b3\u30fc\u30c9)\u4e2d\u306b\u8a66\u3059\u8a00\u8a9e -StringsContentPanel.goToPageTextField.text= -StringsContentPanel.goToPageLabel.text=\u30da\u30fc\u30b8\u306b\u79fb\u52d5: -StringsContentPanel.prevPageButton.text= -StringsContentPanel.pageLabel2.text=\u30da\u30fc\u30b8 -StringsContentPanel.nextPageButton.text= -StringsContentPanel.pageLabel.text_1=\u30da\u30fc\u30b8: TextContentViewer.title=\u30c6\u30ad\u30b9\u30c8 TextContentViewer.tooltip=\u9078\u629e\u3057\u305f\u9805\u76ee\u306b\u95a2\u9023\u4ed8\u3051\u3089\u308c\u3066\u3044\u308b\u30c6\u30ad\u30b9\u30c8\u3092\u8868\u793a TextContentViewerPanel.defaultName=\u30c6\u30ad\u30b9\u30c8 diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/textcontentviewer/TextContentViewerPanel.java b/Core/src/org/sleuthkit/autopsy/contentviewers/textcontentviewer/TextContentViewerPanel.java index 7c80d606fd..62062cbc95 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/textcontentviewer/TextContentViewerPanel.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/textcontentviewer/TextContentViewerPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2019 Basis Technology Corp. + * Copyright 2019-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -79,9 +79,9 @@ public class TextContentViewerPanel extends javax.swing.JPanel implements DataCo } /** - * Determine whether the content viewer which displays this panel isSupported. - * This panel is supported if any of the TextViewer's displayed in it are - * supported. + * Determine whether the content viewer which displays this panel + * isSupported. This panel is supported if any of the TextViewer's displayed + * in it are supported. * * @param node * @@ -213,7 +213,7 @@ public class TextContentViewerPanel extends javax.swing.JPanel implements DataCo // Get and set current selected tab int currentTab = pane.getSelectedIndex(); - if (currentTab != -1) { + if (currentTab != -1 && pane.isEnabledAt(currentTab)) { UpdateWrapper dcv = textViewers.get(currentTab); if (dcv.isOutdated()) { // change the cursor to "waiting cursor" for this operation diff --git a/Core/src/org/sleuthkit/autopsy/core/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/core/Bundle.properties-MERGED index 1d50092e80..51f1208f61 100755 --- a/Core/src/org/sleuthkit/autopsy/core/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/core/Bundle.properties-MERGED @@ -3,13 +3,7 @@ Installer.closing.confirmationDialog.title=Ingest is Running # {0} - exception message Installer.closing.messageBox.caseCloseExceptionMessage=Error closing case: {0} OpenIDE-Module-Display-Category=Infrastructure -OpenIDE-Module-Long-Description=\ - 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-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/ OpenIDE-Module-Name=Autopsy-Core OpenIDE-Module-Short-Description=Autopsy Core Module org_sleuthkit_autopsy_core_update_center=http://sleuthkit.org/autopsy/updates.xml diff --git a/Core/src/org/sleuthkit/autopsy/core/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/core/Bundle_ja.properties index d611fd6338..7037baa2dc 100644 --- a/Core/src/org/sleuthkit/autopsy/core/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/core/Bundle_ja.properties @@ -1,9 +1,12 @@ -#Fri Feb 12 16:56:28 UTC 2021 +#Thu Jul 01 11:56:41 UTC 2021 +Actions/Case=\u30b1\u30fc\u30b9 Installer.closing.confirmationDialog.message=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u306e\u5b9f\u884c\u4e2d\u3067\u3059\u3002\u7d42\u4e86\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? Installer.closing.confirmationDialog.title=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u306e\u5b9f\u884c\u4e2d\u3067\u3059 Installer.closing.messageBox.caseCloseExceptionMessage=\u6b21\u306e\u30b1\u30fc\u30b9\u3092\u9589\u3058\u3066\u3044\u308b\u9593\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\: {0} Installer.errorInitJavafx.details=\ \u4e00\u90e8\u306e\u6a5f\u80fd\u304c\u5229\u7528\u3067\u304d\u306a\u304f\u306a\u308a\u307e\u3059\u3002 \u9069\u5207\u306aJRE\u304c\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3055\u308c\u3066\u3044\u308b\u304b\u78ba\u8a8d\u304f\u3060\u3055\u3044(Oracle JRE 1.7.10\u4ee5\u964d)\u3002 Installer.errorInitJavafx.msg=JavaFX\u306e\u521d\u671f\u5316\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +Menu/Case=\u30b1\u30fc\u30b9 +Menu/Case/OpenRecentCase=\u6700\u8fd1\u306e\u30b1\u30fc\u30b9\u3092\u958b\u304f OpenIDE-Module-Display-Category=\u30a4\u30f3\u30d5\u30e9\u30b9\u30c8\u30e9\u30af\u30c1\u30e3\u30fc OpenIDE-Module-Long-Description=\u3053\u308c\u306fAutopsy\u306e\u30b3\u30a2\u30e2\u30b8\u30e5\u30fc\u30eb\u3067\u3059\u3002\n\n\u30e2\u30b8\u30e5\u30fc\u30eb\u306b\u306f\u3001RCP\u30d7\u30e9\u30c3\u30c8\u30d5\u30a9\u30fc\u30e0\u3001\u30a6\u30a3\u30f3\u30c9\u30a6\u4f5c\u6210GUI\u3001sleuthkit\u30d0\u30a4\u30f3\u30c7\u30a3\u30f3\u30b0\u3001\u30c7\u30fc\u30bf\u30e2\u30c7\u30eb / \u30b9\u30c8\u30ec\u30fc\u30b8\u3001\u30a8\u30af\u30b9\u30d7\u30ed\u30fc\u30e9\u30fc\u3001\u7d50\u679c\u30d3\u30e5\u30fc\u30ef\u30fc\u3001\u30b3\u30f3\u30c6\u30f3\u30c4\u30d3\u30e5\u30fc\u30ef\u30fc\u3001\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30d5\u30ec\u30fc\u30e0\u30ef\u30fc\u30af\u3001\u30ec\u30dd\u30fc\u30c6\u30a3\u30f3\u30b0\u3001\u30d5\u30a1\u30a4\u30eb\u691c\u7d22\u306a\u3069\u306e\u30b3\u30a2\u30c4\u30fc\u30eb\u3068\u3044\u3063\u305f\u3001\u30d9\u30a2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u5b9f\u884c\u306b\u5fc5\u8981\u306a\u30b3\u30a2\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u304c\u542b\u307e\u308c\u3066\u3044\u307e\u3059\u3002\n\n\u30e2\u30b8\u30e5\u30fc\u30eb\u306b\u542b\u307e\u308c\u308b\u30d5\u30ec\u30fc\u30e0\u30ef\u30fc\u30af\u306b\u306f\u3001\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u3001\u30d3\u30e5\u30fc\u30ef\u30fc\u3001\u30ec\u30dd\u30fc\u30c6\u30a3\u30f3\u30b0\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u4f5c\u6210\u7528API\u304c\u542b\u307e\u308c\u3066\u3044\u307e\u3059\u3002 \u30e2\u30b8\u30e5\u30fc\u30eb\u306fAutopsy\u30d7\u30e9\u30b0\u30a4\u30f3\u30a4\u30f3\u30b9\u30c8\u30fc\u30e9\u30fc\u3092\u7528\u3044\u308b\u30d7\u30e9\u30b0\u30a4\u30f3\u3068\u3057\u3066\u5c55\u958b\u3067\u304d\u307e\u3059\u3002\n\u3053\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u306f\u30a2\u30f3\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3057\u306a\u3044\u3067\u304f\u3060\u3055\u3044 - \u3053\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u306a\u3044\u3068Autopsy\u304c\u5b9f\u884c\u3055\u308c\u307e\u305b\u3093\u3002\n\n\u8a73\u7d30\u306f\u3001http\://www.sleuthkit.org/autopsy/ \u3092\u53c2\u7167\u3057\u3066\u304f\u3060\u3055\u3044 OpenIDE-Module-Name=Autopsy-Core @@ -24,4 +27,5 @@ ServicesMonitor.restoredService.notify.title=\u30b5\u30fc\u30d3\u30b9\u304c\u5b9 ServicesMonitor.statusChange.notify.msg={0} \u306e\u30b9\u30c6\u30fc\u30bf\u30b9\u306f {1} \u3067\u3059 ServicesMonitor.statusChange.notify.title=\u30b5\u30fc\u30d3\u30b9\u30b9\u30c6\u30fc\u30bf\u30b9\u66f4\u65b0 ServicesMonitor.unknownServiceName.excepton.txt=\u30ea\u30af\u30a8\u30b9\u30c8\u3055\u308c\u305f\u30b5\u30fc\u30d3\u30b9\u540d {0} \u306f\u4e0d\u660e\u3067\u3059 +Toolbars/Case=\u30b1\u30fc\u30b9 org_sleuthkit_autopsy_core_update_center=http\://sleuthkit.org/autopsy/updates.xml diff --git a/Core/src/org/sleuthkit/autopsy/core/Installer.java b/Core/src/org/sleuthkit/autopsy/core/Installer.java index 5bd649e8cb..7411377733 100644 --- a/Core/src/org/sleuthkit/autopsy/core/Installer.java +++ b/Core/src/org/sleuthkit/autopsy/core/Installer.java @@ -33,6 +33,7 @@ import java.util.logging.Handler; import java.util.logging.Level; import javafx.application.Platform; import javafx.embed.swing.JFXPanel; +import javax.imageio.ImageIO; import net.sf.sevenzipjbinding.SevenZip; import net.sf.sevenzipjbinding.SevenZipNativeInitializationException; import org.apache.commons.io.FileUtils; @@ -44,6 +45,7 @@ import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.actions.IngestRunningCheck; import org.sleuthkit.autopsy.casemodule.Case; import static org.sleuthkit.autopsy.core.UserPreferences.SETTINGS_PROPERTIES; +import org.sleuthkit.autopsy.corelibs.OpenCvLoader; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.ModuleSettings; @@ -66,6 +68,13 @@ public class Installer extends ModuleInstall { static { loadDynLibraries(); + + // This call was moved from MediaViewImagePanel so that it is + // not called during top level component construction. + ImageIO.scanForPlugins(); + + // This will cause OpenCvLoader to load its library instead of + OpenCvLoader.openCvIsLoaded(); } private static void loadDynLibraries() { diff --git a/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DataContentViewer.java b/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DataContentViewer.java index ee84e67293..561d343e72 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DataContentViewer.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DataContentViewer.java @@ -51,6 +51,16 @@ public interface DataContentViewer { * */ public String getTitle(); + + /** + * Returns the title of this viewer to display in the tab. + * + * @param node The node to be viewed in the DataContentViewer. + * @return the title of DataContentViewer. + */ + public default String getTitle(Node node) { + return getTitle(); + } /** * Returns a short description of this viewer to use as a tool tip for its diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AutoWrappingJTextPane.java b/Core/src/org/sleuthkit/autopsy/corecomponents/AutoWrappingJTextPane.java index 1e4c1f4c63..652034dacc 100755 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AutoWrappingJTextPane.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AutoWrappingJTextPane.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2019 Basis Technology Corp. + * Copyright 2019-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.corecomponents; +import java.text.MessageFormat; import javax.swing.JTextPane; import javax.swing.SizeRequirements; import javax.swing.text.Element; @@ -27,6 +28,8 @@ import javax.swing.text.ViewFactory; import javax.swing.text.html.HTMLEditorKit; import javax.swing.text.html.InlineView; import javax.swing.text.html.ParagraphView; +import javax.swing.text.html.StyleSheet; +import org.sleuthkit.autopsy.contentviewers.layout.ContentViewerDefaults; import org.sleuthkit.autopsy.coreutils.EscapeUtil; /** @@ -96,9 +99,15 @@ public class AutoWrappingJTextPane extends JTextPane { this.setEditorKit(editorKit); } + + @Override public void setText(String text) { - super.setText("
" + EscapeUtil.escapeHtml(text) + "
"); + // setting the text format with style to avoid problems with overridden styles. + String style = String.format("font-family: %s; font-size: %dpt; margin: 0px; padding: 0px 0px %dpx 0px;", + ContentViewerDefaults.getFont().getFamily(), ContentViewerDefaults.getFont().getSize(), ContentViewerDefaults.getLineSpacing()); + + super.setText(MessageFormat.format("
{1}
", style, EscapeUtil.escapeHtml(text))); } } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties index 725d5d83d1..584ba1dcd1 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties @@ -23,13 +23,13 @@ INDEX_FOR_LOCAL_HELP=/docs/index.html LBL_Close=Close DataContentViewerHex.copyMenuItem.text=Copy DataContentViewerHex.selectAllMenuItem.text=Select All -DataContentViewerArtifact.totalPageLabel.text=100 -DataContentViewerArtifact.prevPageButton.text= -DataContentViewerArtifact.pageLabel2.text=Result -DataContentViewerArtifact.nextPageButton.text= -DataContentViewerArtifact.currentPageLabel.text=1 -DataContentViewerArtifact.ofLabel.text=of -DataContentViewerArtifact.pageLabel.text=Result: +DataArtifactContentViewer.totalPageLabel.text=100 +DataArtifactContentViewer.prevPageButton.text= +DataArtifactContentViewer.pageLabel2.text=Result +DataArtifactContentViewer.nextPageButton.text= +DataArtifactContentViewer.currentPageLabel.text=1 +DataArtifactContentViewer.ofLabel.text=of +DataArtifactContentViewer.pageLabel.text=Result: AdvancedConfigurationDialog.applyButton.text=OK DataContentViewerHex.goToPageTextField.text= DataContentViewerHex.goToPageLabel.text=Go to Page: @@ -44,10 +44,10 @@ DataResultViewerThumbnail.filePathLabel.text=\ \ \ DataResultViewerThumbnail.goToPageLabel.text=Go to Page: DataResultViewerThumbnail.goToPageField.text= AdvancedConfigurationDialog.cancelButton.text=Cancel -DataContentViewerArtifact.waitText=Retrieving and preparing data, please wait... -DataContentViewerArtifact.errorText=Error retrieving result -DataContentViewerArtifact.title=Results -DataContentViewerArtifact.toolTip=Displays Results associated with the file +DataArtifactContentViewer.waitText=Retrieving and preparing data, please wait... +DataArtifactContentViewer.errorText=Error retrieving result +DataArtifactContentViewer.title=Data Artifacts +DataArtifactContentViewer.toolTip=Displays Results associated with the file DataContentViewerHex.goToPageTextField.msgDlg=Please enter a valid page number between 1 and {0} DataContentViewerHex.goToPageTextField.err=Invalid page number DataContentViewerHex.setDataView.errorText=(offset {0}-{1} could not be read) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties-MERGED index b39205f8e1..609d68bcd1 100755 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties-MERGED @@ -30,8 +30,8 @@ CTL_DataContentAction=DataContent CTL_DataContentTopComponent=Data Content CTL_OfflineHelpAction=Offline Autopsy Documentation CTL_OnlineHelpAction=Online Autopsy Documentation -DataContentViewerArtifact.failedToGetAttributes.message=Failed to get some or all attributes from case database -DataContentViewerArtifact.failedToGetSourcePath.message=Failed to get source file path from case database +DataArtifactContentViewer.failedToGetAttributes.message=Failed to get some or all attributes from case database +DataArtifactContentViewer.failedToGetSourcePath.message=Failed to get source file path from case database DataContentViewerHex.copyingFile=Copying file to open in HxD... DataContentViewerHex.launchError=Unable to launch HxD Editor. Please specify the HxD install location in Tools -> Options -> External Viewer DataContentViewerHex_loading_text=Loading hex from file... @@ -75,9 +75,9 @@ DataContentViewerHex.totalPageLabel.text_1=100 DataContentViewerHex.pageLabel2.text=Page # Product Information panel -LBL_Description=
\n Product Version: {0} ({9})
Sleuth Kit Version: {7}
Netbeans RCP Build: {8}
Java: {1}; {2}
System: {3}; {4}; {5}
Userdir: {6}
+LBL_Description=
\n Product Version: {0} ({9})
Sleuth Kit Version: {7}
Netbeans RCP Build: {8}
Java: {1}; {2}
System: {3}; {4}; {5}
Userdir: {6}
Format_OperatingSystem_Value={0} version {1} running on {2} -LBL_Copyright=
Autopsy™ is a digital forensics platform based on The Sleuth Kit™ and other tools.
Copyright © 2003-2020.
+LBL_Copyright=
Autopsy™ is a digital forensics platform based on The Sleuth Kit™ and other tools.
Copyright © 2003-2020.
SortChooser.dialogTitle=Choose Sort Criteria ThumbnailViewChildren.progress.cancelling=(Cancelling) # {0} - file name @@ -88,13 +88,13 @@ INDEX_FOR_LOCAL_HELP=/docs/index.html LBL_Close=Close DataContentViewerHex.copyMenuItem.text=Copy DataContentViewerHex.selectAllMenuItem.text=Select All -DataContentViewerArtifact.totalPageLabel.text=100 -DataContentViewerArtifact.prevPageButton.text= -DataContentViewerArtifact.pageLabel2.text=Result -DataContentViewerArtifact.nextPageButton.text= -DataContentViewerArtifact.currentPageLabel.text=1 -DataContentViewerArtifact.ofLabel.text=of -DataContentViewerArtifact.pageLabel.text=Result: +DataArtifactContentViewer.totalPageLabel.text=100 +DataArtifactContentViewer.prevPageButton.text= +DataArtifactContentViewer.pageLabel2.text=Result +DataArtifactContentViewer.nextPageButton.text= +DataArtifactContentViewer.currentPageLabel.text=1 +DataArtifactContentViewer.ofLabel.text=of +DataArtifactContentViewer.pageLabel.text=Result: AdvancedConfigurationDialog.applyButton.text=OK DataContentViewerHex.goToPageTextField.text= DataContentViewerHex.goToPageLabel.text=Go to Page: @@ -105,14 +105,14 @@ DataResultViewerThumbnail.pageNextButton.text= DataResultViewerThumbnail.imagesLabel.text=Images: DataResultViewerThumbnail.imagesRangeLabel.text=- DataResultViewerThumbnail.pageNumLabel.text=- -DataResultViewerThumbnail.filePathLabel.text=\ \ \ +DataResultViewerThumbnail.filePathLabel.text=\ DataResultViewerThumbnail.goToPageLabel.text=Go to Page: DataResultViewerThumbnail.goToPageField.text= AdvancedConfigurationDialog.cancelButton.text=Cancel -DataContentViewerArtifact.waitText=Retrieving and preparing data, please wait... -DataContentViewerArtifact.errorText=Error retrieving result -DataContentViewerArtifact.title=Results -DataContentViewerArtifact.toolTip=Displays Results associated with the file +DataArtifactContentViewer.waitText=Retrieving and preparing data, please wait... +DataArtifactContentViewer.errorText=Error retrieving result +DataArtifactContentViewer.title=Data Artifacts +DataArtifactContentViewer.toolTip=Displays Results associated with the file DataContentViewerHex.goToPageTextField.msgDlg=Please enter a valid page number between 1 and {0} DataContentViewerHex.goToPageTextField.err=Invalid page number DataContentViewerHex.setDataView.errorText=(offset {0}-{1} could not be read) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle_ja.properties index 9717d32fbb..36db21b1c7 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle_ja.properties @@ -1,4 +1,4 @@ -#Fri Feb 12 16:56:28 UTC 2021 +#Thu Jul 01 11:56:41 UTC 2021 AboutWindowPanel.actVerboseLogging.text=\u8a73\u7d30\u30ed\u30ae\u30f3\u30b0\u3092\u30a2\u30af\u30c6\u30a3\u30d6\u5316 AddExternalViewerRulePanel.browseButton.text=\u53c2\u7167 AddExternalViewerRulePanel.exePathLabel.text=\u3053\u306e\u30bf\u30a4\u30d7\u307e\u305f\u306f\u62e1\u5f35\u5b50\u306e\u30d5\u30a1\u30a4\u30eb\u306b\u4f7f\u7528\u3059\u308b\u30d7\u30ed\u30b0\u30e9\u30e0\u306e\u30d1\u30b9 @@ -9,6 +9,7 @@ AddExternalViewerRulePanel.nameLabel.text=MIME\u30bf\u30a4\u30d7\u307e\u305f\u30 AddExternalViewerRulePanel.nameTextField.text= AdvancedConfigurationDialog.applyButton.text=OK AdvancedConfigurationDialog.cancelButton.text=\u53d6\u308a\u6d88\u3057 +AutopsyOPtionsPanel_isHeapPathValid_illegalCharacters=\u5f15\u7528\u7b26\u304c\u306a\u3044\u30d1\u30b9\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002 AutopsyOptionsPanel.a.AccessibleContext.accessibleName=\u4e00\u6642\u30d5\u30a9\u30eb\u30c0 AutopsyOptionsPanel.agencyLogoImageLabel.toolTipText= AutopsyOptionsPanel.agencyLogoPathField.text= @@ -19,6 +20,8 @@ AutopsyOptionsPanel.agencyLogoPathFieldValidationLabel.text= AutopsyOptionsPanel.agencyLogoPreview.text=
\u30ed\u30b4\u304c\u3042\u308a\u307e\u305b\u3093
selected
AutopsyOptionsPanel.browseLogosButton.text=\u53c2\u7167 AutopsyOptionsPanel.defaultLogoRB.text=\u30c7\u30d5\u30a9\u30eb\u30c8\u3092\u4f7f\u7528 +AutopsyOptionsPanel.heapDumpBrowseButton.text=\u53c2\u7167 +AutopsyOptionsPanel.heapFileLabel.text=\u30ab\u30b9\u30bf\u30e0\u30d2\u30fc\u30d7\u30c0\u30f3\u30d7\u306e\u5834\u6240\uff1a AutopsyOptionsPanel.invalidImageFile.msg=\u9078\u629e\u3057\u305f\u30d5\u30a1\u30a4\u30eb\u3092\u30a8\u30fc\u30b8\u30a7\u30f3\u30b7\u30fc\u30ed\u30b4\u3068\u3057\u3066\u4f7f\u7528\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 AutopsyOptionsPanel.invalidImageFile.title=\u7121\u52b9\u306a\u30a4\u30e1\u30fc\u30b8\u30d5\u30a1\u30a4\u30eb\u3067\u3059 AutopsyOptionsPanel.logNumAlert.invalidInput.text=\u3053\u3053\u3067\u306f\u6b63\u306e\u6574\u6570\u304c\u5fc5\u8981\u3067\u3059\u3002 @@ -41,17 +44,27 @@ AutopsyOptionsPanel.runtimePanel.border.title=\u30e9\u30f3\u30bf\u30a4\u30e0 AutopsyOptionsPanel.sizingTextPane.text=\u9ad8DPI\u30b7\u30b9\u30c6\u30e0\u3067\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u30ca\u30d3\u30b2\u30fc\u30c8\u304c\u96e3\u3057\u3044\u5834\u5408\u306f\u3001\u6b21\u306e\u5909\u66f4\u3092\u884c\u3063\u3066\u304f\u3060\u3055\u3044\u3002\n\n1.\u30c7\u30b9\u30af\u30c8\u30c3\u30d7\u3001\u30b9\u30bf\u30fc\u30c8\u30e1\u30cb\u30e5\u30fc\u306a\u3069\u306e\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u30a2\u30a4\u30b3\u30f3\u3092\u53f3\u30af\u30ea\u30c3\u30af\n2.\u30d7\u30ed\u30d1\u30c6\u30a3\u3092\u9078\u629e\n3. [\u4e92\u63db\u6027]\u30bf\u30d6\u306b\u79fb\u52d5\n4. [\u9ad8DPI\u8a2d\u5b9a\u306e\u5909\u66f4]\u30dc\u30bf\u30f3\u3092\u30af\u30ea\u30c3\u30af\n5. [\u9ad8DPI\u30b9\u30b1\u30fc\u30ea\u30f3\u30b0\u52d5\u4f5c\u3092\u5909\u66f4]\u3092\u9078\u629e\n6.\u300c\u30b9\u30b1\u30fc\u30ea\u30f3\u30b0\u306e\u5b9f\u884c\uff1a\u300d\u30c9\u30ed\u30c3\u30d7\u30c0\u30a6\u30f3\u30dc\u30c3\u30af\u30b9\u3092\u300c\u30b7\u30b9\u30c6\u30e0\u300d\u306b\u5909\u66f4\u3057\u307e\u3059\u3002\n7.Autopsy\u3092\u518d\u5b9f\u884c AutopsyOptionsPanel.solrJVMHeapWarning.text=\u6ce8\: \u3053\u308c\u3092\u3042\u307e\u308a\u306b\u3082\u5927\u304d\u304f\u8a2d\u5b9a\u3059\u308b\u3068\u3001\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u5168\u4f53\u306b\u5f71\u97ff\u3059\u308b\u3053\u3068\u304c\u3042\u308a\u307e\u3059\u3002 AutopsyOptionsPanel.specifyLogoRB.text=\u30ed\u30b4\u3092\u6307\u5b9a +AutopsyOptionsPanel.tempCaseRadio.text=\u30b1\u30fc\u30b9\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u306e\u4e00\u6642\u30d5\u30a9\u30eb\u30c0 +AutopsyOptionsPanel.tempCustomRadio.text=\u30ab\u30b9\u30bf\u30e0 AutopsyOptionsPanel.tempDirectoryBrowseButton.text=\u30d6\u30e9\u30a6\u30ba AutopsyOptionsPanel.tempDirectoryPanel.AccessibleContext.accessibleName=\u4e00\u6642\u30d5\u30a9\u30eb\u30c0 -AutopsyOptionsPanel.tempDirectoryPanel.border.title=\u4e00\u6642\u30d5\u30a9\u30eb\u30c0 +AutopsyOptionsPanel.tempDirectoryPanel.border.title=\u30eb\u30fc\u30c8\u4e00\u6642\u30c7\u30a3\u30ec\u30af\u30c8\u30ea AutopsyOptionsPanel.tempDirectoryPanel.name=\u4e00\u6642\u30d5\u30a9\u30eb\u30c0 AutopsyOptionsPanel.tempDirectoryWarningLabel.text=\u4e00\u6642\u30d5\u30a9\u30eb\u30c0\u3092\u5909\u66f4\u3059\u308b\u306b\u306f\u30b1\u30fc\u30b9\u3092\u9589\u3058\u3066\u4e0b\u3055\u3044\u3002 +AutopsyOptionsPanel.tempLocalRadio.text=\u30ed\u30fc\u30ab\u30eb\u4e00\u6642\u30c7\u30a3\u30ec\u30af\u30c8\u30ea +AutopsyOptionsPanel.tempOnCustomNoPath.text=\u30ab\u30b9\u30bf\u30e0\u30eb\u30fc\u30c8\u306e\u4e00\u6642\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u30fb\u30d1\u30b9\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002 AutopsyOptionsPanel.totalMemoryLabel.text=\u5408\u8a08\u30b7\u30b9\u30c6\u30e0\u30e1\u30e2\u30ea\u30fc\: +AutopsyOptionsPanel_heapDumpBrowseButtonActionPerformed_fileAlreadyExistsMessage=\u30d5\u30a1\u30a4\u30eb\u306f\u65e2\u306b\u5b58\u5728\u3057\u3066\u3044\u307e\u3059\u3002 \u65b0\u3057\u3044\u5834\u6240\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002 +AutopsyOptionsPanel_heapDumpBrowseButtonActionPerformed_fileAlreadyExistsTitle=\u30d5\u30a1\u30a4\u30eb\u304c\u65e2\u306b\u5b58\u5728\u3057\u307e\u3059 +AutopsyOptionsPanel_isHeapPathValid_developerMode=\u958b\u767a\u8005\u30e2\u30fc\u30c9\u3067\u306f\u3001\u30d2\u30fc\u30d7\u30c0\u30f3\u30d7\u30d1\u30b9\u3092\u5909\u66f4\u3067\u304d\u307e\u305b\u3093\u3002 +AutopsyOptionsPanel_isHeapPathValid_not64BitMachine=\u30d2\u30fc\u30d7\u30c0\u30f3\u30d7\u30d1\u30b9\u8a2d\u5b9a\u306e\u5909\u66f4\u306f\u300164\u30d3\u30c3\u30c8\u7248\u306e\u307f\u3067\u6709\u52b9\u306b\u306a\u3063\u3066\u3044\u307e\u3059\u3002 +AutopsyOptionsPanel_isHeapPathValid_selectValidDirectory=\u65e2\u5b58\u306e\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002 +AutopsyOptionsPanel_storeTempDir_onChoiceError_description=\u4e00\u6642\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u9078\u629e\u306e\u66f4\u65b0\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +AutopsyOptionsPanel_storeTempDir_onChoiceError_title=\u4e00\u6642\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u9078\u629e\u306e\u4fdd\u5b58\u30a8\u30e9\u30fc AutopsyOptionsPanel_storeTempDir_onError_description=\u30b7\u30b9\u30c6\u30e0\u4e00\u6642\u30d5\u30a9\u30eb\u30c0{0}\u3092\u4f5c\u6210\u3059\u308b\u3068\u304d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 AutopsyOptionsPanel_storeTempDir_onError_title=\u4e00\u6642\u30d5\u30a9\u30eb\u30c0\u4fdd\u5b58\u306b\u5931\u6557\u3057\u307e\u3057\u305f AutopsyOptionsPanel_tempDirectoryBrowseButtonActionPerformed_onInvalidPath_description=\u6307\u5b9a\u3055\u308c\u305f\u30d1\u30b9\u5185\u306b\u4e00\u6642\u30d5\u30a9\u30eb\u30c0\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\uff1a{0} AutopsyOptionsPanel_tempDirectoryBrowseButtonActionPerformed_onInvalidPath_title=\u30d1\u30b9\u306f\u4f7f\u7528\u3067\u304d\u307e\u305b\u3093 -CTL_CustomAboutAction=\u6982\u8981 CTL_DataContentAction=DataContent CTL_DataContentTopComponent=\u30c7\u30fc\u30bf\u30b3\u30f3\u30c6\u30f3\u30c4 CTL_OfflineHelpAction=Autopsy\u30aa\u30d5\u30e9\u30a4\u30f3\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8 @@ -59,19 +72,17 @@ CTL_OnlineHelpAction=Autopsy\u30aa\u30f3\u30e9\u30a4\u30f3\u30c9\u30ad\u30e5\u30 CriterionChooser.ascendingRadio.text=\u25b2 \u6607\u9806\n CriterionChooser.descendingRadio.text=\u25bc \u964d\u9806 CriterionChooser.removeButton.text=\u524a\u9664 -DataContentViewerArtifact.currentPageLabel.text=1 -DataContentViewerArtifact.errorText=\u7d50\u679c\u306e\u691c\u7d22\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f -DataContentViewerArtifact.failedToGetAttributes.message=\u30b1\u30fc\u30b9\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304b\u3089\u4e00\u90e8\u307e\u305f\u306f\u3059\u3079\u3066\u306e\u5c5e\u6027\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f -DataContentViewerArtifact.failedToGetSourcePath.message=\u30b1\u30fc\u30b9\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304b\u3089\u30bd\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb\u30d1\u30b9\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f -DataContentViewerArtifact.nextPageButton.text= -DataContentViewerArtifact.ofLabel.text=/ -DataContentViewerArtifact.pageLabel.text=\u7d50\u679c\: -DataContentViewerArtifact.pageLabel2.text=\u7d50\u679c -DataContentViewerArtifact.prevPageButton.text= -DataContentViewerArtifact.title=\u7d50\u679c -DataContentViewerArtifact.toolTip=\u30d5\u30a1\u30a4\u30eb\u3068\u95a2\u9023\u4ed8\u3051\u3089\u308c\u3066\u3044\u308b\u7d50\u679c\u3092\u8868\u793a -DataContentViewerArtifact.totalPageLabel.text=100 -DataContentViewerArtifact.waitText=\u30c7\u30fc\u30bf\u3092\u691c\u7d22\u3057\u3066\u6e96\u5099\u4e2d\u3067\u3059\u3002\u304a\u5f85\u3061\u304f\u3060\u3055\u3044... +DataArtifactContentViewer.currentPageLabel.text=1 +DataArtifactContentViewer.errorText=\u7d50\u679c\u306e\u53d6\u5f97\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +DataArtifactContentViewer.failedToGetAttributes.message=\u30b1\u30fc\u30b9\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304b\u3089\u5168\u3066\u306e\u60c5\u5831\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f +DataArtifactContentViewer.failedToGetSourcePath.message=\u30b1\u30fc\u30b9\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304b\u3089\u30bd\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb\u30d1\u30b9\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f +DataArtifactContentViewer.ofLabel.text=/ +DataArtifactContentViewer.pageLabel.text=\u7d50\u679c\: +DataArtifactContentViewer.pageLabel2.text=\u7d50\u679c +DataArtifactContentViewer.title=\u30c7\u30fc\u30bf\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8 +DataArtifactContentViewer.toolTip=\u30d5\u30a1\u30a4\u30eb\u306b\u95a2\u9023\u4ed8\u3051\u3089\u308c\u305f\u7d50\u679c\u3092\u8868\u793a\u3057\u307e\u3059 +DataArtifactContentViewer.totalPageLabel.text=100 +DataArtifactContentViewer.waitText=\u30c7\u30fc\u30bf\u306e\u53d6\u5f97\u3068\u6e96\u5099\u4e2d\u3001\u304a\u5f85\u3061\u304f\u3060\u3055\u3044... DataContentViewerHex.copyMenuItem.text=\u30b3\u30d4\u30fc DataContentViewerHex.copyingFile=HxD\u3067\u958b\u304f\u30d5\u30a1\u30a4\u30eb\u3092\u30b3\u30d4\u30fc\u4e2d\u3067\u3059... DataContentViewerHex.currentPageLabel.text_1=1 @@ -95,6 +106,7 @@ DataContentViewerHex.setDataView.invalidOffset.negativeOffsetValue=\u7d50\u679c\ DataContentViewerHex.title=16\u9032\u6570 DataContentViewerHex.toolTip=\u30d5\u30a1\u30a4\u30eb\u306e\u30d0\u30a4\u30ca\u30ea\u30fc\u30b3\u30f3\u30c6\u30f3\u30c4\u309216\u9032\u6570\u3068\u3057\u3066\u8868\u793a\u3057\u307e\u3059\u3002\u53f3\u5074\u306bASCII\u6587\u5b57\u3068\u3057\u3066\u8868\u793a\u53ef\u80fd\u306a\u30d0\u30a4\u30c8\u304c\u793a\u3055\u308c\u307e\u3059\u3002 DataContentViewerHex.totalPageLabel.text_1=100 +DataContentViewerHex_loading_text=\u30d5\u30a1\u30a4\u30eb\u304b\u308916\u9032\u6570\u3092\u8aad\u8fbc\u4e2d... DataResultPanel.descriptionLabel.text=directoryPath DataResultPanel.matchLabel.text=\u7d50\u679c DataResultPanel.numberOfChildNodesLabel.text=0 @@ -241,6 +253,7 @@ MultiUserSettingsPanel.validationErrMsg.invalidSolr4ServerPort=Solr4\u30b5\u30fc MultiUserSettingsPanel.validationErrMsg.invalidZkServerHostName=ZooKeeper\u30b5\u30fc\u30d0\u30fc\u306e\u30db\u30b9\u30c8\u540d\u304c\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u307e\u305b\u3093 MultiUserSettingsPanel.validationErrMsg.invalidZkServerPort=ZooKeeper\u30b5\u30fc\u30d0\u30fc\u306e\u30dd\u30fc\u30c8\u756a\u53f7\u304c\u7121\u52b9\u3067\u3059 MultiUserSettingsPanel.validationErrMsg.solrNotConfigured=Solr8\u3068Solr4\u30b5\u30fc\u30d0\u30fc\u306e\u3044\u305a\u308c\u304b\u3092\u69cb\u6210\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059 +MultiUserSettingsPanel_Close_Case_To_Modify=\u8a2d\u5b9a\u3092\u5909\u66f4\u3059\u308b\u306b\u306f\u30b1\u30fc\u30b9\u3092\u9589\u3058\u3066\u304f\u3060\u3055\u3044 OpenIDE-Module-Name=CoreComponents OptionsCategory_Keywords_General=Autopsy\u30aa\u30d7\u30b7\u30e7\u30f3 OptionsCategory_Keywords_Multi_User_Options=\u30de\u30eb\u30c1\u30e6\u30fc\u30b6\u30fc\u8a2d\u5b9a @@ -267,7 +280,6 @@ ViewPreferencesPanel.dataSourcesHideSlackCheckbox.text=\u30c7\u30fc\u30bf\u30bd\ ViewPreferencesPanel.displayTimeLabel.text=\u6642\u523b\u8868\u793a\u6642\: ViewPreferencesPanel.fileNameTranslationColumnCheckbox.text=\u7d50\u679c\u30d3\u30e5\u30fc\u30ef\u30fc\u306b\u30d5\u30a1\u30a4\u30eb\u540d\u7ffb\u8a33\u7528\u5217\u3092\u8ffd\u52a0 ViewPreferencesPanel.globalSettingsPanel.border.title=\u30b0\u30ed\u30fc\u30d0\u30eb\u8a2d\u5b9a -ViewPreferencesPanel.groupByDataSourceCheckbox.text=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u5225\u306b\u30b0\u30eb\u30fc\u30d7\u5316 ViewPreferencesPanel.hideKnownFilesLabel.text=\u6b21\u306e\u65e2\u77e5\u306e\u30d5\u30a1\u30a4\u30eb(NIST NSRL\u5185\u306e\u30d5\u30a1\u30a4\u30eb)\u3092\u975e\u8868\u793a\u306b\u3059\u308b\: ViewPreferencesPanel.hideOtherUsersTagsCheckbox.text=\u30c4\u30ea\u30fc\u5185\u306e\u30bf\u30b0\u9818\u57df ViewPreferencesPanel.hideOtherUsersTagsLabel.text=\u6b21\u306e\u305d\u306e\u4ed6\u306e\u30e6\u30fc\u30b6\u30fc\u306e\u30bf\u30b0\u3092\u975e\u8868\u793a\u306b\u3059\u308b\: @@ -277,6 +289,8 @@ ViewPreferencesPanel.keepCurrentViewerRadioButton.text=\u540c\u3058\u30d5\u30a1\ ViewPreferencesPanel.keepCurrentViewerRadioButton.toolTipText=\u305f\u3068\u3048\u3070\u3001JPEG\u9078\u629e\u6642\u306f16\u9032\u30d3\u30e5\u30fc\u306e\u307e\u307e\u306b\u3057\u307e\u3059\u3002 ViewPreferencesPanel.maxResultsLabel.text=\u30c6\u30fc\u30d6\u30eb\u3067\u8868\u793a\u3059\u308b\u6700\u5927\u7d50\u679c\u6570\: ViewPreferencesPanel.maxResultsLabel.toolTipText=\n\u3053\u306e\u5024\u30920 \u306b\u8a2d\u5b9a\u3059\u308b\u3068\u3001\u3059\u3079\u3066\u306e\u7d50\u679c\u304c\u7d50\u679c\u30c6\u30fc\u30d6\u30eb\u306b\u8868\u793a\u3055\u308c\u307e\u3059\u3002\n
\u3053\u306e\u5024\u30920 \u306b\u8a2d\u5b9a\u3059\u308b\u3068\u3001\u7d50\u679c\u6570\u304c\u591a\u3044\u5834\u5408UI\u306e\u5fdc\u7b54\u6027\u304c\u60aa\u304f\u306a\u308b\u3053\u3068\u304c\u3042\u308a\u307e\u3059 \u3002\n +ViewPreferencesPanel.radioGroupByDataType.text=\u30c7\u30fc\u30bf\u30fb\u30bf\u30a4\u30d7\u3067\u30b0\u30eb\u30fc\u30d7\u5316 +ViewPreferencesPanel.radioGroupByPersonHost.text=\u4eba/\u30db\u30b9\u30c8\u3067\u30b0\u30eb\u30fc\u30d7\u5316 ViewPreferencesPanel.scoColumnsCheckbox.text=S(\u30b9\u30b3\u30a2)\u3001C(\u30b3\u30e1\u30f3\u30c8)\u3001O(\u767a\u751f) ViewPreferencesPanel.scoColumnsLabel.text=\u6b21\u306e\u305f\u3081\u306e\u5217\u3092\u8ffd\u52a0\u3057\u306a\u3044\: ViewPreferencesPanel.scoColumnsWrapAroundText.text=\u975e\u8868\u793a\u306b\u3059\u308b\u3068\u8aad\u8fbc\u307f\u304c\u65e9\u304f\u306a\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.form b/Core/src/org/sleuthkit/autopsy/corecomponents/DataArtifactContentViewer.form similarity index 89% rename from Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.form rename to Core/src/org/sleuthkit/autopsy/corecomponents/DataArtifactContentViewer.form index c4928f5111..3b33fc6d9f 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.form +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataArtifactContentViewer.form @@ -2,8 +2,11 @@ + + + - + @@ -21,33 +24,42 @@ - + - + - + - + + + + - + + + + + + + - + @@ -56,13 +68,13 @@ - + - + - + @@ -74,7 +86,7 @@ - + @@ -86,28 +98,25 @@ - + - - - - + - + - + - + @@ -122,7 +131,7 @@ - + @@ -151,7 +160,7 @@ - + @@ -162,7 +171,7 @@ - + @@ -172,7 +181,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataArtifactContentViewer.java similarity index 81% rename from Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java rename to Core/src/org/sleuthkit/autopsy/corecomponents/DataArtifactContentViewer.java index f27ac62a1a..a210cdfc36 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataArtifactContentViewer.java @@ -32,36 +32,40 @@ import org.openide.util.NbBundle; import org.openide.util.lookup.ServiceProvider; import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskException; import java.util.Collections; import java.util.HashSet; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.contentviewers.artifactviewers.ArtifactContentViewer; import org.sleuthkit.autopsy.contentviewers.artifactviewers.DefaultTableArtifactContentViewer; +import org.sleuthkit.datamodel.AnalysisResult; +import org.sleuthkit.datamodel.BlackboardArtifact; +import org.sleuthkit.datamodel.DataArtifact; /** - * Instances of this class display the BlackboardArtifacts associated with the + * Instances of this class display the DataArtifact associated with the * Content represented by a Node. * * It goes through a list of known ArtifactContentViewer to find a viewer that * supports a given artifact and then hands it the artifact to display. */ -@ServiceProvider(service = DataContentViewer.class, position = 7) +@ServiceProvider(service = DataContentViewer.class, position = 6) @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives -public class DataContentViewerArtifact extends javax.swing.JPanel implements DataContentViewer { +public class DataArtifactContentViewer extends javax.swing.JPanel implements DataContentViewer { private static final long serialVersionUID = 1L; @NbBundle.Messages({ - "DataContentViewerArtifact.failedToGetSourcePath.message=Failed to get source file path from case database", - "DataContentViewerArtifact.failedToGetAttributes.message=Failed to get some or all attributes from case database" + "DataArtifactContentViewer.failedToGetSourcePath.message=Failed to get source file path from case database", + "DataArtifactContentViewer.failedToGetAttributes.message=Failed to get some or all attributes from case database" }) - private final static Logger logger = Logger.getLogger(DataContentViewerArtifact.class.getName()); - private final static String WAIT_TEXT = NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.waitText"); - private final static String ERROR_TEXT = NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.errorText"); + private final static Logger logger = Logger.getLogger(DataArtifactContentViewer.class.getName()); + private final static String WAIT_TEXT = NbBundle.getMessage(DataArtifactContentViewer.class, "DataArtifactContentViewer.waitText"); + private final static String ERROR_TEXT = NbBundle.getMessage(DataArtifactContentViewer.class, "DataArtifactContentViewer.errorText"); // Value to return in isPreferred if this viewer is less preferred. private static final int LESS_PREFERRED = 3; @@ -71,12 +75,12 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat private Node currentNode; // @@@ Remove this when the redundant setNode() calls problem is fixed. private int currentPage = 1; private final Object lock = new Object(); - private List artifactTableContents; // Accessed by multiple threads, use getArtifactContents() and setArtifactContents() + private List artifactTableContents; // Accessed by multiple threads, use getArtifactContents() and setArtifactContents() private SwingWorker currentTask; // Accessed by multiple threads, use startNewTask() private final Collection knowArtifactViewers = new HashSet<>(Lookup.getDefault().lookupAll(ArtifactContentViewer.class)); - public DataContentViewerArtifact() { + public DataArtifactContentViewer() { initComponents(); @@ -93,8 +97,8 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat private void initComponents() { java.awt.GridBagConstraints gridBagConstraints; - jScrollPane1 = new javax.swing.JScrollPane(); - jPanel1 = new javax.swing.JPanel(); + scrollPane = new javax.swing.JScrollPane(); + menuBar = new javax.swing.JPanel(); totalPageLabel = new javax.swing.JLabel(); ofLabel = new javax.swing.JLabel(); currentPageLabel = new javax.swing.JLabel(); @@ -106,57 +110,60 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(32767, 0)); artifactContentPanel = new javax.swing.JPanel(); - setPreferredSize(new java.awt.Dimension(100, 58)); + setMinimumSize(new java.awt.Dimension(300, 60)); + setPreferredSize(new java.awt.Dimension(300, 60)); - jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); - jScrollPane1.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER); + scrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + scrollPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER); + scrollPane.setPreferredSize(new java.awt.Dimension(6, 60)); - jPanel1.setPreferredSize(new java.awt.Dimension(620, 58)); - jPanel1.setLayout(new java.awt.GridBagLayout()); + menuBar.setMaximumSize(null); + menuBar.setMinimumSize(null); + menuBar.setPreferredSize(null); + menuBar.setLayout(new java.awt.GridBagLayout()); - totalPageLabel.setText(org.openide.util.NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.totalPageLabel.text")); // NOI18N - totalPageLabel.setMaximumSize(new java.awt.Dimension(40, 16)); - totalPageLabel.setPreferredSize(new java.awt.Dimension(25, 16)); + totalPageLabel.setText(org.openide.util.NbBundle.getMessage(DataArtifactContentViewer.class, "DataArtifactContentViewer.totalPageLabel.text")); // NOI18N + totalPageLabel.setMaximumSize(null); + totalPageLabel.setPreferredSize(null); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 3; gridBagConstraints.gridy = 0; gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.insets = new java.awt.Insets(3, 12, 0, 0); - jPanel1.add(totalPageLabel, gridBagConstraints); + menuBar.add(totalPageLabel, gridBagConstraints); - ofLabel.setText(org.openide.util.NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.ofLabel.text")); // NOI18N + ofLabel.setText(org.openide.util.NbBundle.getMessage(DataArtifactContentViewer.class, "DataArtifactContentViewer.ofLabel.text")); // NOI18N gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 2; gridBagConstraints.gridy = 0; gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.insets = new java.awt.Insets(3, 12, 0, 0); - jPanel1.add(ofLabel, gridBagConstraints); + menuBar.add(ofLabel, gridBagConstraints); - currentPageLabel.setText(org.openide.util.NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.currentPageLabel.text")); // NOI18N - currentPageLabel.setMaximumSize(new java.awt.Dimension(38, 14)); - currentPageLabel.setMinimumSize(new java.awt.Dimension(18, 14)); - currentPageLabel.setPreferredSize(new java.awt.Dimension(20, 14)); + currentPageLabel.setText(org.openide.util.NbBundle.getMessage(DataArtifactContentViewer.class, "DataArtifactContentViewer.currentPageLabel.text")); // NOI18N + currentPageLabel.setMaximumSize(null); + currentPageLabel.setPreferredSize(null); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 0; gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.insets = new java.awt.Insets(4, 7, 0, 0); - jPanel1.add(currentPageLabel, gridBagConstraints); + gridBagConstraints.insets = new java.awt.Insets(3, 7, 0, 0); + menuBar.add(currentPageLabel, gridBagConstraints); - pageLabel.setText(org.openide.util.NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.pageLabel.text")); // NOI18N + pageLabel.setText(org.openide.util.NbBundle.getMessage(DataArtifactContentViewer.class, "DataArtifactContentViewer.pageLabel.text")); // NOI18N gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 0; gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.insets = new java.awt.Insets(3, 12, 0, 0); - jPanel1.add(pageLabel, gridBagConstraints); + menuBar.add(pageLabel, gridBagConstraints); nextPageButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_forward.png"))); // NOI18N - nextPageButton.setText(org.openide.util.NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.nextPageButton.text")); // NOI18N + nextPageButton.setText(org.openide.util.NbBundle.getMessage(DataArtifactContentViewer.class, "DataArtifactContentViewer.nextPageButton.text")); // NOI18N nextPageButton.setBorderPainted(false); nextPageButton.setContentAreaFilled(false); nextPageButton.setDisabledIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_forward_disabled.png"))); // NOI18N @@ -173,9 +180,9 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat gridBagConstraints.gridy = 0; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.insets = new java.awt.Insets(0, 0, 35, 0); - jPanel1.add(nextPageButton, gridBagConstraints); + menuBar.add(nextPageButton, gridBagConstraints); - pageLabel2.setText(org.openide.util.NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.pageLabel2.text")); // NOI18N + pageLabel2.setText(org.openide.util.NbBundle.getMessage(DataArtifactContentViewer.class, "DataArtifactContentViewer.pageLabel2.text")); // NOI18N pageLabel2.setMaximumSize(new java.awt.Dimension(29, 14)); pageLabel2.setMinimumSize(new java.awt.Dimension(29, 14)); gridBagConstraints = new java.awt.GridBagConstraints(); @@ -183,11 +190,11 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat gridBagConstraints.gridy = 0; gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; - gridBagConstraints.insets = new java.awt.Insets(3, 41, 0, 0); - jPanel1.add(pageLabel2, gridBagConstraints); + gridBagConstraints.insets = new java.awt.Insets(3, 30, 0, 0); + menuBar.add(pageLabel2, gridBagConstraints); prevPageButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_back.png"))); // NOI18N - prevPageButton.setText(org.openide.util.NbBundle.getMessage(DataContentViewerArtifact.class, "DataContentViewerArtifact.prevPageButton.text")); // NOI18N + prevPageButton.setText(org.openide.util.NbBundle.getMessage(DataArtifactContentViewer.class, "DataArtifactContentViewer.prevPageButton.text")); // NOI18N prevPageButton.setBorderPainted(false); prevPageButton.setContentAreaFilled(false); prevPageButton.setDisabledIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/btn_step_back_disabled.png"))); // NOI18N @@ -204,22 +211,22 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat gridBagConstraints.gridy = 0; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints.insets = new java.awt.Insets(0, 5, 35, 0); - jPanel1.add(prevPageButton, gridBagConstraints); + menuBar.add(prevPageButton, gridBagConstraints); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 8; gridBagConstraints.gridy = 0; gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST; gridBagConstraints.insets = new java.awt.Insets(3, 0, 0, 8); - jPanel1.add(artifactLabel, gridBagConstraints); + menuBar.add(artifactLabel, gridBagConstraints); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 7; gridBagConstraints.gridy = 0; gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.weightx = 0.1; - jPanel1.add(filler1, gridBagConstraints); + menuBar.add(filler1, gridBagConstraints); - jScrollPane1.setViewportView(jPanel1); + scrollPane.setViewportView(menuBar); artifactContentPanel.setLayout(new javax.swing.OverlayLayout(artifactContentPanel)); @@ -227,15 +234,15 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 561, Short.MAX_VALUE) + .addComponent(scrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE) .addComponent(artifactContentPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(scrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(artifactContentPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 397, Short.MAX_VALUE)) + .addComponent(artifactContentPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 30, Short.MAX_VALUE)) ); }// //GEN-END:initComponents @@ -258,13 +265,13 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat private javax.swing.JLabel artifactLabel; private javax.swing.JLabel currentPageLabel; private javax.swing.Box.Filler filler1; - private javax.swing.JPanel jPanel1; - private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JPanel menuBar; private javax.swing.JButton nextPageButton; private javax.swing.JLabel ofLabel; private javax.swing.JLabel pageLabel; private javax.swing.JLabel pageLabel2; private javax.swing.JButton prevPageButton; + private javax.swing.JScrollPane scrollPane; private javax.swing.JLabel totalPageLabel; // End of variables declaration//GEN-END:variables @@ -286,10 +293,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat @Override public void setNode(Node selectedNode) { - if (currentNode == selectedNode) { - return; - } - currentNode = selectedNode; + currentNode = null; // Make sure there is a node. Null might be passed to reset the viewer. if (selectedNode == null) { @@ -308,17 +312,17 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat @Override public String getTitle() { - return NbBundle.getMessage(this.getClass(), "DataContentViewerArtifact.title"); + return NbBundle.getMessage(this.getClass(), "DataArtifactContentViewer.title"); } @Override public String getToolTip() { - return NbBundle.getMessage(this.getClass(), "DataContentViewerArtifact.toolTip"); + return NbBundle.getMessage(this.getClass(), "DataArtifactContentViewer.toolTip"); } @Override public DataContentViewer createInstance() { - return new DataContentViewerArtifact(); + return new DataArtifactContentViewer(); } @Override @@ -338,21 +342,22 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat } for (Content content : node.getLookup().lookupAll(Content.class)) { - if ((content != null) && (!(content instanceof BlackboardArtifact))) { + if ((content != null) && (!(content instanceof DataArtifact)) && (!(content instanceof AnalysisResult))) { try { - return content.getAllArtifactsCount() > 0; - } catch (TskException ex) { - logger.log(Level.SEVERE, "Couldn't get count of BlackboardArtifacts for content", ex); //NON-NLS + return Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboard().hasDataArtifacts(content.getId()); + } catch (NoCurrentCaseException | TskException ex) { + logger.log(Level.SEVERE, "Couldn't get count of DataArtifacts for content", ex); //NON-NLS } } } + return false; } @Override public int isPreferred(Node node) { // get the artifact from the lookup - BlackboardArtifact artifact = node.getLookup().lookup(BlackboardArtifact.class); + DataArtifact artifact = node.getLookup().lookup(DataArtifact.class); if (artifact == null) { return LESS_PREFERRED; } @@ -386,7 +391,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat } } - private ArtifactContentViewer getSupportingViewer(BlackboardArtifact artifact) { + private ArtifactContentViewer getSupportingViewer(DataArtifact artifact) { for (ArtifactContentViewer viewer : knowArtifactViewers) { if (viewer.isSupported(artifact)) { return viewer; @@ -403,10 +408,10 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat int numberOfPages; int currentPage; - BlackboardArtifact artifact; + DataArtifact artifact; String errorMsg; - ViewUpdate(int numberOfPages, int currentPage, BlackboardArtifact artifact) { + ViewUpdate(int numberOfPages, int currentPage, DataArtifact artifact) { this.currentPage = currentPage; this.numberOfPages = numberOfPages; this.artifact = artifact; @@ -442,7 +447,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat if (viewUpdate.artifact != null) { artifactLabel.setText(viewUpdate.artifact.getDisplayName()); - BlackboardArtifact artifact = viewUpdate.artifact; + DataArtifact artifact = viewUpdate.artifact; ArtifactContentViewer viewer = this.getSupportingViewer(artifact); viewer.setArtifact(artifact); @@ -484,7 +489,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat * @param artifactList A list of ResultsTableArtifact representations of * artifacts. */ - private void setArtifactContents(List artifactList) { + private void setArtifactContents(List artifactList) { synchronized (lock) { this.artifactTableContents = artifactList; } @@ -495,11 +500,22 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat * * @return A list of artifacts. */ - private List getArtifactContents() { + private List getArtifactContents() { synchronized (lock) { return Collections.unmodifiableList(artifactTableContents); } } + + /** + * Metric for determining if content is parent source content. + * @param content The content. + * @return True if this content should be used for source content. + */ + private static boolean isSourceContent(Content content) { + return (content != null) && + (!(content instanceof DataArtifact)) && + (!(content instanceof AnalysisResult)); + } /** * Instances of this class use a background thread to generate a ViewUpdate @@ -520,20 +536,18 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat // blackboard artifact, if any. Lookup lookup = selectedNode.getLookup(); - // Get the content. We may get BlackboardArtifacts, ignore those here. - ArrayList artifacts = new ArrayList<>(); + // Get the content. We may get DataArtifacts, ignore those here. + List artifacts = Collections.emptyList(); Collection contents = lookup.lookupAll(Content.class); if (contents.isEmpty()) { return new ViewUpdate(getArtifactContents().size(), currentPage, ERROR_TEXT); } - Content underlyingContent = null; for (Content content : contents) { - if ((content != null) && (!(content instanceof BlackboardArtifact))) { + if (isSourceContent(content)) { // Get all of the blackboard artifacts associated with the content. These are what this // viewer displays. try { - artifacts = content.getAllArtifacts(); - underlyingContent = content; + artifacts = content.getAllDataArtifacts(); break; } catch (TskException ex) { logger.log(Level.SEVERE, "Couldn't get artifacts", ex); //NON-NLS @@ -547,15 +561,15 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat } // Build the new artifact contents cache. - ArrayList artifactContents = new ArrayList<>(); - for (BlackboardArtifact artifact : artifacts) { + ArrayList artifactContents = new ArrayList<>(); + for (DataArtifact artifact : artifacts) { artifactContents.add(artifact); } - // If the node has an underlying blackboard artifact, show it. If not, + // If the node has an underlying data artifact, show it. If not, // show the first artifact. int index = 0; - BlackboardArtifact artifact = lookup.lookup(BlackboardArtifact.class); + DataArtifact artifact = lookup.lookup(DataArtifact.class); if (artifact != null) { index = artifacts.indexOf(artifact); if (index == -1) { @@ -567,7 +581,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat if (attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID()) { long assocArtifactId = attr.getValueLong(); int assocArtifactIndex = -1; - for (BlackboardArtifact art : artifacts) { + for (DataArtifact art : artifacts) { if (assocArtifactId == art.getArtifactID()) { assocArtifactIndex = artifacts.indexOf(art); break; @@ -610,6 +624,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat try { ViewUpdate viewUpdate = get(); if (viewUpdate != null) { + currentNode = selectedNode; updateView(viewUpdate); } } catch (InterruptedException | ExecutionException ex) { @@ -636,14 +651,14 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat protected ViewUpdate doInBackground() { // Get the artifact content to display from the cache. Note that one must be subtracted from the // page index to get the corresponding artifact content index. - List artifactContents = getArtifactContents(); + List artifactContents = getArtifactContents(); // It may take a considerable amount of time to fetch the attributes of the selected artifact so check for cancellation. if (isCancelled()) { return null; } - BlackboardArtifact artifactContent = artifactContents.get(pageIndex - 1); + DataArtifact artifactContent = artifactContents.get(pageIndex - 1); return new ViewUpdate(artifactContents.size(), pageIndex, artifactContent); } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentPanel.java index 8e8183e2f1..018db45817 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentPanel.java @@ -145,6 +145,12 @@ public class DataContentPanel extends javax.swing.JPanel implements DataContent, // Reset everything for (int index = 0; index < jTabbedPane1.getTabCount(); index++) { jTabbedPane1.setEnabledAt(index, false); + String tabTitle = viewers.get(index).getTitle(selectedNode); + tabTitle = tabTitle == null ? "" : tabTitle; + if (!tabTitle.equals(jTabbedPane1.getTitleAt(index))) { + jTabbedPane1.setTitleAt(index, tabTitle); + } + viewers.get(index).resetComponent(); } @@ -202,7 +208,7 @@ public class DataContentPanel extends javax.swing.JPanel implements DataContent, int currentTab = pane.getSelectedIndex(); if (currentTab != -1) { UpdateWrapper dcv = viewers.get(currentTab); - if (dcv.isOutdated()) { + if (dcv.isOutdated() || dcv.getViewer() instanceof DataArtifactContentViewer) { // change the cursor to "waiting cursor" for this operation this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); try { @@ -245,6 +251,14 @@ public class DataContentPanel extends javax.swing.JPanel implements DataContent, int isPreferred(Node node) { return this.wrapped.isPreferred(node); } + + String getTitle(Node node) { + return this.wrapped.getTitle(node); + } + + DataContentViewer getViewer() { + return wrapped; + } } /** diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java index e8c5ae4aea..3c0686c1a0 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java @@ -21,8 +21,6 @@ package org.sleuthkit.autopsy.corecomponents; import com.google.common.eventbus.Subscribe; import java.awt.Component; import java.awt.Cursor; -import java.awt.FontMetrics; -import java.awt.Graphics; import java.awt.dnd.DnDConstants; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; @@ -49,6 +47,7 @@ import javax.swing.JTable; import javax.swing.ListSelectionModel; import static javax.swing.SwingConstants.CENTER; import javax.swing.SwingUtilities; +import javax.swing.UIManager; import javax.swing.event.ChangeEvent; import javax.swing.event.ListSelectionEvent; import javax.swing.event.TableColumnModelEvent; @@ -106,6 +105,27 @@ public class DataResultViewerTable extends AbstractDataResultViewer { private static final long serialVersionUID = 1L; private static final Logger LOGGER = Logger.getLogger(DataResultViewerTable.class.getName()); + // How many rows to sample in order to determine column width. + private static final int SAMPLE_ROW_NUM = 100; + + // The padding to be added in addition to content size when considering column width. + private static final int COLUMN_PADDING = 15; + + // The minimum column width. + private static final int MIN_COLUMN_WIDTH = 30; + + // The maximum column width. + private static final int MAX_COLUMN_WIDTH = 300; + + // The minimum row height to use when calculating whether scroll bar will be used. + private static final int MIN_ROW_HEIGHT = 10; + + // The width of the scroll bar. + private static final int SCROLL_BAR_WIDTH = ((Integer) UIManager.get("ScrollBar.width")).intValue(); + + // Any additional padding to be used for the first column. + private static final int FIRST_COL_ADDITIONAL_WIDTH = 0; + private static final String NOTEPAD_ICON_PATH = "org/sleuthkit/autopsy/images/notepad16.png"; private static final String RED_CIRCLE_ICON_PATH = "org/sleuthkit/autopsy/images/red-circle-exclamation.png"; private static final String YELLOW_CIRCLE_ICON_PATH = "org/sleuthkit/autopsy/images/yellow-circle-yield.png"; @@ -152,7 +172,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { * OutlineView to the actions global context. * * @param explorerManager The explorer manager of the ancestor top - * component. + * component. */ public DataResultViewerTable(ExplorerManager explorerManager) { this(explorerManager, Bundle.DataResultViewerTable_title()); @@ -165,8 +185,8 @@ public class DataResultViewerTable extends AbstractDataResultViewer { * in the OutlineView to the actions global context. * * @param explorerManager The explorer manager of the ancestor top - * component. - * @param title The title. + * component. + * @param title The title. */ public DataResultViewerTable(ExplorerManager explorerManager, String title) { super(explorerManager); @@ -361,15 +381,10 @@ public class DataResultViewerTable extends AbstractDataResultViewer { * If the given node is not null and has children, set it as the * root context of the child OutlineView, otherwise make an * "empty"node the root context. - * - * IMPORTANT NOTE: This is the first of many times where a - * getChildren call on the current root node causes all of the - * children of the root node to be created and defeats lazy child - * node creation, if it is enabled. It also likely leads to many - * case database round trips. */ if (rootNode != null && rootNode.getChildren().getNodesCount() > 0) { this.getExplorerManager().setRootContext(this.rootNode); + outline.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); setupTable(); } else { Node emptyNode = new AbstractNode(Children.LEAF); @@ -422,13 +437,6 @@ public class DataResultViewerTable extends AbstractDataResultViewer { firstProp = props.remove(0); } - /* - * show the horizontal scroll panel and show all the content & header If - * there is only one column (which was removed from props above) Just - * let the table resize itself. - */ - outline.setAutoResizeMode((props.isEmpty()) ? JTable.AUTO_RESIZE_ALL_COLUMNS : JTable.AUTO_RESIZE_OFF); - assignColumns(props); // assign columns to match the properties if (firstProp != null) { ((DefaultOutlineModel) outline.getOutlineModel()).setNodesColumnLabel(firstProp.getDisplayName()); @@ -513,87 +521,59 @@ public class DataResultViewerTable extends AbstractDataResultViewer { /* * Sets the column widths for the child OutlineView of this tabular results - * viewer. + * viewer providing any additional width to last column. */ protected void setColumnWidths() { - if (rootNode.getChildren().getNodesCount() != 0) { - final Graphics graphics = outlineView.getGraphics(); + // based on https://stackoverflow.com/questions/17627431/auto-resizing-the-jtable-column-widths + final TableColumnModel columnModel = outline.getColumnModel(); - if (graphics != null) { - // Current width of the outlineView - double outlineViewWidth = outlineView.getSize().getWidth(); - // List of the column widths - List columnWidths = new ArrayList<>(); - final FontMetrics metrics = graphics.getFontMetrics(); + // the remaining table width that can be used in last row + double availableTableWidth = outlineView.getSize().getWidth(); - int margin = 4; - int padding = 8; + for (int columnIdx = 0; columnIdx < outline.getColumnCount(); columnIdx++) { + int columnPadding = (columnIdx == 0) ? FIRST_COL_ADDITIONAL_WIDTH + COLUMN_PADDING : COLUMN_PADDING; + TableColumn tableColumn = columnModel.getColumn(columnIdx); - int totalColumnWidth = 0; - int cntMaxSizeColumns = 0; + // The width of this column + int width = MIN_COLUMN_WIDTH; - // Calulate the width for each column keeping track of the number - // of columns that were set to columnwidthLimit. - for (int column = 0; column < outline.getModel().getColumnCount(); column++) { - int firstColumnPadding = (column == 0) ? 32 : 0; - int columnWidthLimit = (column == 0) ? 350 : 300; - int valuesWidth = 0; - - // find the maximum width needed to fit the values for the first 100 rows, at most - for (int row = 0; row < Math.min(100, outline.getRowCount()); row++) { - TableCellRenderer renderer = outline.getCellRenderer(row, column); - Component comp = outline.prepareRenderer(renderer, row, column); - valuesWidth = Math.max(comp.getPreferredSize().width, valuesWidth); - } - - int headerWidth = metrics.stringWidth(outline.getColumnName(column)); - valuesWidth += firstColumnPadding; // add extra padding for first column - - int columnWidth = Math.max(valuesWidth, headerWidth); - columnWidth += 2 * margin + padding; // add margin and regular padding - - columnWidth = Math.min(columnWidth, columnWidthLimit); - columnWidths.add(columnWidth); - - totalColumnWidth += columnWidth; - - if (columnWidth == columnWidthLimit) { - cntMaxSizeColumns++; - } - } - - // Figure out how much extra, if any can be given to the columns - // so that the table is as wide as outlineViewWidth. If cntMaxSizeColumns - // is greater than 0 divide the extra space between the columns - // that could use more space. Otherwise divide evenly amoung - // all columns. - int extraWidth = 0; - - if (totalColumnWidth < outlineViewWidth) { - if (cntMaxSizeColumns > 0) { - extraWidth = (int) ((outlineViewWidth - totalColumnWidth) / cntMaxSizeColumns); - } else { - extraWidth = (int) ((outlineViewWidth - totalColumnWidth) / columnWidths.size()); - } - } - - for (int column = 0; column < columnWidths.size(); column++) { - int columnWidth = columnWidths.get(column); - - if (cntMaxSizeColumns > 0) { - if (columnWidth >= ((column == 0) ? 350 : 300)) { - columnWidth += extraWidth; - } - } else { - columnWidth += extraWidth; - } - - outline.getColumnModel().getColumn(column).setPreferredWidth(columnWidth); - } + // get header cell width + // taken in part from https://stackoverflow.com/a/18381924 + TableCellRenderer headerRenderer = tableColumn.getHeaderRenderer(); + if (headerRenderer == null) { + headerRenderer = outline.getTableHeader().getDefaultRenderer(); + } + Object headerValue = tableColumn.getHeaderValue(); + Component headerComp = headerRenderer.getTableCellRendererComponent(outline, headerValue, false, false, 0, columnIdx); + width = Math.max(headerComp.getPreferredSize().width + columnPadding, width); + + // get the max of row widths from the first SAMPLE_ROW_NUM rows + Component comp = null; + int rowCount = outline.getRowCount(); + for (int row = 0; row < Math.min(rowCount, SAMPLE_ROW_NUM); row++) { + TableCellRenderer renderer = outline.getCellRenderer(row, columnIdx); + comp = outline.prepareRenderer(renderer, row, columnIdx); + width = Math.max(comp.getPreferredSize().width + columnPadding, width); + } + + // no higher than maximum column width + if (width > MAX_COLUMN_WIDTH) { + width = MAX_COLUMN_WIDTH; + } + + // if last column, calculate remaining width factoring in the possibility of a scroll bar. + if (columnIdx == outline.getColumnCount() - 1) { + int rowHeight = comp == null ? MIN_ROW_HEIGHT : comp.getPreferredSize().height; + if (headerComp.getPreferredSize().height + rowCount * rowHeight > outlineView.getSize().getHeight()) { + availableTableWidth -= SCROLL_BAR_WIDTH; + } + + columnModel.getColumn(columnIdx).setPreferredWidth(Math.max(width, (int) availableTableWidth)); + } else { + // otherwise set preferred width to width and decrement availableTableWidth accordingly + columnModel.getColumn(columnIdx).setPreferredWidth(width); + availableTableWidth -= width; } - } else { - // if there's no content just auto resize all columns - outline.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); } } @@ -749,7 +729,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { * order. * * @return a List> of the properties in the persisted - * order. + * order. */ private synchronized List> loadColumnOrder() { @@ -1266,18 +1246,20 @@ public class DataResultViewerTable extends AbstractDataResultViewer { /** * Returns the icon denoted by the Score's Significance. + * * @param significance The Score's Significance. + * * @return The icon (or null) related to that significance. */ private ImageIcon getIcon(Significance significance) { if (significance == null) { return null; } - + switch (significance) { case NOTABLE: return NOTABLE_ICON_SCORE; - case LIKELY_NOTABLE: + case LIKELY_NOTABLE: return INTERESTING_SCORE_ICON; case LIKELY_NONE: case NONE: @@ -1286,7 +1268,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { return null; } } - + @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { Component component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/coreutils/Bundle.properties-MERGED index a0d535f8e6..18e279dd2c 100755 --- a/Core/src/org/sleuthkit/autopsy/coreutils/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/coreutils/Bundle.properties-MERGED @@ -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.getJvmMemInfo.usageText=JVM heap usage: {0}, JVM non-heap usage: {1} PlatformUtil.getPhysicalMemInfo.usageText=Physical memory usage (max, total, free): {0}, {1}, {2} -PlatformUtil.getAllMemUsageInfo.usageText={0}\n\ -{1}\n\ -Process Virtual Memory: {2} +PlatformUtil.getAllMemUsageInfo.usageText={0}\n{1}\nProcess Virtual Memory: {2} # {0} - file name ReadImageTask.mesageText=Reading image: {0} StringExtract.illegalStateException.cannotInit.msg=Unicode table not properly initialized, cannot instantiate StringExtract diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/coreutils/Bundle_ja.properties index 5f460a7c53..bdd8fab25e 100644 --- a/Core/src/org/sleuthkit/autopsy/coreutils/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/coreutils/Bundle_ja.properties @@ -1,35 +1,37 @@ -# {0} - \u30d5\u30a1\u30a4\u30eb\u540d +#Mon Jul 12 13:21:59 UTC 2021 +FileTypeCategory.Audio.displayName=\u30aa\u30fc\u30c7\u30a3\u30aa +FileTypeCategory.Documents.displayName=\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8 +FileTypeCategory.Executables.displayName=\u5b9f\u884c\u30d5\u30a1\u30a4\u30eb +FileTypeCategory.Image.displayName=\u753b\u50cf +FileTypeCategory.Media.displayName=\u30e1\u30c7\u30a3\u30a2 +FileTypeCategory.Video.displayName=\u30d3\u30c7\u30aa +FileTypeCategory.Visual.displayName=\u30d3\u30b8\u30e5\u30a2\u30eb GetOrGenerateThumbnailTask.generatingPreviewFor={0} \u306e\u30d7\u30ec\u30d3\u30e5\u30fc\u3092\u751f\u6210\u4e2d\u3067\u3059 -# {0} - \u30d5\u30a1\u30a4\u30eb\u540d GetOrGenerateThumbnailTask.loadingThumbnailFor={0} \u306e\u30b5\u30e0\u30cd\u30a4\u30eb\u3092\u8aad\u307f\u8fbc\u307f\u4e2d\u3067\u3059 ImageUtils.ffmpegLoadedError.msg=OpenCV FFMpeg\u30e9\u30a4\u30d6\u30e9\u30ea\u30fc\u304c\u8aad\u307f\u8fbc\u3081\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u8a73\u7d30\u306f\u30ed\u30b0\u3092\u53c2\u7167\u3057\u3066\u304f\u3060\u3055\u3044 ImageUtils.ffmpegLoadedError.title=OpenCV FFMpeg -OpenIDE-Module-Name=CoreUtils JLNK.noPrefPath.text=\u63a8\u5968\u30d1\u30b9\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f +OpenIDE-Module-Name=CoreUtils +PlatformUtil.archUnknown=\u4e0d\u660e +PlatformUtil.getAllMemUsageInfo.usageText={0}\n{1}\n\u6b21\u306e\u4eee\u60f3\u30e1\u30e2\u30ea\u30fc\u3092\u51e6\u7406\: {2} +PlatformUtil.getJavaPID.gen.msg=\u6b21\u306e\u30af\u30a8\u30ea\u306ePID\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\: {0}\u3001{1} +PlatformUtil.getJavaPID.sigarNotInit.msg=java\u30d7\u30ed\u30bb\u30b9\u306ePID\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3002Sigar\u304c\u521d\u671f\u5316\u3055\u308c\u3066\u3044\u307e\u305b\u3093 +PlatformUtil.getJavaPIDs.gen.msg=\u6b21\u306e\u30af\u30a8\u30ea\u306ePID\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\: {0}\u3001{1} +PlatformUtil.getJavaPIDs.sigarNotInit=java\u30d7\u30ed\u30bb\u30b9\u306ePID\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3002Sigar\u304c\u521d\u671f\u5316\u3055\u308c\u3066\u3044\u307e\u305b\u3093 +PlatformUtil.getJvmMemInfo.usageText=JVM \u30d2\u30fc\u30d7\u4f7f\u7528\u7387\: {0}\u3001\u4f7f\u7528\u3055\u308c\u3066\u3044\u306a\u3044JVM\u30d2\u30fc\u30d7\u9818\u57df\: {1} +PlatformUtil.getPID.gen.msg=PID,{0} \u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093 +PlatformUtil.getPID.sigarNotInit.msg=PID\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3002Sigar\u304c\u521d\u671f\u5316\u3055\u308c\u3066\u3044\u307e\u305b\u3093 +PlatformUtil.getPhysicalMemInfo.usageText=\u7269\u7406\u30e1\u30e2\u30ea\u30fc\u4f7f\u7528\u7387\uff08\u6700\u5927\u3001\u5408\u8a08\u3001\u7a7a\u304d\uff09\: {0}\u3001{1}\u3001{2} +PlatformUtil.getProcVmUsed.gen.msg=\u4f7f\u7528\u3057\u3066\u3044\u308b\u4eee\u60f3\u30e1\u30e2\u30ea\u30fc\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3001{0} +PlatformUtil.getProcVmUsed.sigarNotInit.msg=\u4f7f\u7528\u3057\u3066\u3044\u308b\u4eee\u60f3\u30e1\u30e2\u30ea\u30fc\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3002Sigar\u304c\u521d\u671f\u5316\u3055\u308c\u3066\u3044\u307e\u305b\u3093 +PlatformUtil.jrePath.jreDir.msg=\u57cb\u3081\u8fbc\u307fjre\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u30fc\u304c\u691c\u51fa\u3055\u308c\u305f\u5834\u6240\: {0} +PlatformUtil.jrePath.usingJavaPath.msg=\u6b21\u306ejava\u30d0\u30a4\u30ca\u30ea\u30fc\u30d1\u30b9\u3092\u4f7f\u7528\u4e2d\u3067\u3059\: {0} +PlatformUtil.killProcess.gen.msg=\u6b21\u306e\u30d7\u30ed\u30bb\u30b9\u3092\u5f37\u5236\u7d42\u4e86\u3067\u304d\u307e\u305b\u3093\: {0}\u3001{1} +PlatformUtil.killProcess.sigarNotInit.msg=PID\u306e\u30d7\u30ed\u30bb\u30b9\u3092\u5f37\u5236\u7d42\u4e86\u3067\u304d\u307e\u305b\u3093\u3002Sigar\u304c\u521d\u671f\u5316\u3055\u308c\u3066\u3044\u307e\u305b\u3093 PlatformUtil.nameUnknown=\u4e0d\u660e PlatformUtil.verUnknown=\u4e0d\u660e -PlatformUtil.archUnknown=\u4e0d\u660e -PlatformUtil.jrePath.jreDir.msg=\u57cb\u3081\u8fbc\u307fjre\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u30fc\u304c\u691c\u51fa\u3055\u308c\u305f\u5834\u6240: {0} -PlatformUtil.jrePath.usingJavaPath.msg=\u6b21\u306ejava\u30d0\u30a4\u30ca\u30ea\u30fc\u30d1\u30b9\u3092\u4f7f\u7528\u4e2d\u3067\u3059: {0} -PlatformUtil.getPID.sigarNotInit.msg=PID\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3002Sigar\u304c\u521d\u671f\u5316\u3055\u308c\u3066\u3044\u307e\u305b\u3093 -PlatformUtil.getPID.gen.msg=PID,{0} \u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093 -PlatformUtil.getJavaPID.sigarNotInit.msg=java\u30d7\u30ed\u30bb\u30b9\u306ePID\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3002Sigar\u304c\u521d\u671f\u5316\u3055\u308c\u3066\u3044\u307e\u305b\u3093 -PlatformUtil.getJavaPID.gen.msg=\u6b21\u306e\u30af\u30a8\u30ea\u306ePID\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093: {0}\u3001{1} -PlatformUtil.getJavaPIDs.sigarNotInit=java\u30d7\u30ed\u30bb\u30b9\u306ePID\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3002Sigar\u304c\u521d\u671f\u5316\u3055\u308c\u3066\u3044\u307e\u305b\u3093 -PlatformUtil.getJavaPIDs.gen.msg=\u6b21\u306e\u30af\u30a8\u30ea\u306ePID\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093: {0}\u3001{1} -PlatformUtil.killProcess.sigarNotInit.msg=PID\u306e\u30d7\u30ed\u30bb\u30b9\u3092\u5f37\u5236\u7d42\u4e86\u3067\u304d\u307e\u305b\u3093\u3002Sigar\u304c\u521d\u671f\u5316\u3055\u308c\u3066\u3044\u307e\u305b\u3093 -PlatformUtil.killProcess.gen.msg=\u6b21\u306e\u30d7\u30ed\u30bb\u30b9\u3092\u5f37\u5236\u7d42\u4e86\u3067\u304d\u307e\u305b\u3093: {0}\u3001{1} -PlatformUtil.getProcVmUsed.sigarNotInit.msg=\u4f7f\u7528\u3057\u3066\u3044\u308b\u4eee\u60f3\u30e1\u30e2\u30ea\u30fc\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3002Sigar\u304c\u521d\u671f\u5316\u3055\u308c\u3066\u3044\u307e\u305b\u3093 -PlatformUtil.getProcVmUsed.gen.msg=\u4f7f\u7528\u3057\u3066\u3044\u308b\u4eee\u60f3\u30e1\u30e2\u30ea\u30fc\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3001{0} -PlatformUtil.getJvmMemInfo.usageText=JVM \u30d2\u30fc\u30d7\u4f7f\u7528\u7387: {0}\u3001\u4f7f\u7528\u3055\u308c\u3066\u3044\u306a\u3044JVM\u30d2\u30fc\u30d7\u9818\u57df: {1} -PlatformUtil.getPhysicalMemInfo.usageText=\u7269\u7406\u30e1\u30e2\u30ea\u30fc\u4f7f\u7528\u7387\uff08\u6700\u5927\u3001\u5408\u8a08\u3001\u7a7a\u304d\uff09: {0}\u3001{1}\u3001{2} -PlatformUtil.getAllMemUsageInfo.usageText={0}\n\ -{1}\n\ -\u6b21\u306e\u4eee\u60f3\u30e1\u30e2\u30ea\u30fc\u3092\u51e6\u7406: {2} -# {0} - \u30d5\u30a1\u30a4\u30eb\u540d -ReadImageTask.mesageText=\u6b21\u306e\u30a4\u30e1\u30fc\u30b8\u3092\u8aad\u307f\u8fbc\u307f\u4e2d\u3067\u3059: {0} +ReadImageTask.mesageText=\u6b21\u306e\u30a4\u30e1\u30fc\u30b8\u3092\u8aad\u307f\u8fbc\u307f\u4e2d\u3067\u3059\: {0} StringExtract.illegalStateException.cannotInit.msg=Unicode\u30c6\u30fc\u30d6\u30eb\u304c\u6b63\u3057\u304f\u521d\u671f\u5316\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002StringExtract\u3092\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u5316\u3067\u304d\u307e\u305b\u3093 TextConverter.convert.exception.txt=\u30c6\u30ad\u30b9\u30c8 {0} \u309216\u9032\u6570\u30c6\u30ad\u30b9\u30c8\u306b\u5909\u63db\u3067\u304d\u307e\u305b\u3093 TextConverter.convertFromHex.exception.txt=16\u9032\u6570\u30c6\u30ad\u30b9\u30c8\u3092\u30c6\u30ad\u30b9\u30c8\u306b\u5909\u63db\u3067\u304d\u307e\u305b\u3093 -# {0} - \u30d5\u30a1\u30a4\u30eb\u540d VideoUtils.genVideoThumb.progress.text=\u4e00\u6642\u30d5\u30a1\u30a4\u30eb {0} \u3092\u62bd\u51fa\u4e2d\u3067\u3059 diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/ImageUtils.java b/Core/src/org/sleuthkit/autopsy/coreutils/ImageUtils.java index 6ae521de1e..8d9c3a02b9 100644 --- a/Core/src/org/sleuthkit/autopsy/coreutils/ImageUtils.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/ImageUtils.java @@ -194,7 +194,7 @@ public class ImageUtils { public static SortedSet getSupportedImageMimeTypes() { return Collections.unmodifiableSortedSet(SUPPORTED_IMAGE_MIME_TYPES); } - + /** * Get the default thumbnail, which is the icon for a file. Used when we can * not generate a content based thumbnail. diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/TimeZoneUtils.java b/Core/src/org/sleuthkit/autopsy/coreutils/TimeZoneUtils.java index c844d9ce97..5f2ac6d4cc 100644 --- a/Core/src/org/sleuthkit/autopsy/coreutils/TimeZoneUtils.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/TimeZoneUtils.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2018 Basis Technology Corp. + * Copyright 2011-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -27,6 +27,8 @@ import java.util.GregorianCalendar; import java.util.List; import java.util.SimpleTimeZone; import java.util.TimeZone; +import org.sleuthkit.autopsy.core.UserPreferences; +import org.sleuthkit.datamodel.TimeUtilities; /** * Utility methods for workig with time zones. @@ -52,7 +54,7 @@ public class TimeZoneUtils { DateFormat dfm = new SimpleDateFormat("z"); dfm.setTimeZone(zone); boolean hasDaylight = zone.useDaylightTime(); - String first = dfm.format(new GregorianCalendar(2010, 1, 1).getTime()).substring(0, 3); + String first = dfm.format(new GregorianCalendar(2010, 1, 1).getTime()).substring(0, 3); String second = dfm.format(new GregorianCalendar(2011, 6, 6).getTime()).substring(0, 3); int mid = hour * -1; String result = first + Integer.toString(mid); @@ -65,19 +67,19 @@ public class TimeZoneUtils { return result; } - + /** * Generate a time zone string containing the GMT offset and ID. - * + * * @param timeZone The time zone. - * + * * @return The time zone string. */ public static String createTimeZoneString(TimeZone timeZone) { int offset = timeZone.getRawOffset() / 1000; int hour = offset / 3600; int minutes = Math.abs((offset % 3600) / 60); - + return String.format("(GMT%+d:%02d) %s", hour, minutes, timeZone.getID()); //NON-NLS } @@ -89,7 +91,7 @@ public class TimeZoneUtils { * Create a list of time zones. */ List timeZoneList = new ArrayList<>(); - + String[] ids = SimpleTimeZone.getAvailableIDs(); for (String id : ids) { /* @@ -103,36 +105,72 @@ public class TimeZoneUtils { */ timeZoneList.add(TimeZone.getTimeZone(id)); } - + /* * Sort the list of time zones first by offset, then by ID. */ - Collections.sort(timeZoneList, new Comparator(){ + Collections.sort(timeZoneList, new Comparator() { @Override - public int compare(TimeZone o1, TimeZone o2){ + public int compare(TimeZone o1, TimeZone o2) { int offsetDelta = Integer.compare(o1.getRawOffset(), o2.getRawOffset()); - + if (offsetDelta == 0) { return o1.getID().compareToIgnoreCase(o2.getID()); } - + return offsetDelta; } }); - + /* * Create a list of Strings encompassing both the GMT offset and the * time zone ID. */ List outputList = new ArrayList<>(); - + for (TimeZone timeZone : timeZoneList) { outputList.add(createTimeZoneString(timeZone)); } - + return outputList; } + /** + * Returns the time formatted in the user selected time zone. + * + * @param epochTime + * + * @return + */ + public static String getFormattedTime(long epochTime) { + return TimeUtilities.epochToTime(epochTime, getTimeZone()); + } + + /** + * Returns the formatted time in the user selected time zone in ISO8601 + * format. + * + * @param epochTime Seconds from java epoch + * + * @return Formatted date time string in ISO8601 + */ + public static String getFormattedTimeISO8601(long epochTime) { + return TimeUtilities.epochToTimeISO8601(epochTime, getTimeZone()); + } + + /** + * Returns the user preferred timezone. + * + * @return TimeZone to use when formatting time values. + */ + public static TimeZone getTimeZone() { + if (UserPreferences.displayTimesInLocalTime()) { + return TimeZone.getDefault(); + } + + return TimeZone.getTimeZone(UserPreferences.getTimeZoneForDisplays()); + } + /** * Prevents instantiation. */ diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java index 2bd4e702c3..14534c3e3e 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2012-2020 Basis Technology Corp. + * Copyright 2012-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -63,6 +63,7 @@ import org.sleuthkit.datamodel.ContentTag; import org.sleuthkit.datamodel.Tag; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; +import org.sleuthkit.autopsy.coreutils.TimeZoneUtils; import org.sleuthkit.autopsy.texttranslation.utils.FileNameTranslationUtil; import org.sleuthkit.datamodel.Score; @@ -348,10 +349,10 @@ public abstract class AbstractAbstractFileNode extends A new WeakReference<>(this), weakPcl)); } - properties.add(new NodeProperty<>(MOD_TIME.toString(), MOD_TIME.toString(), NO_DESCR, ContentUtils.getStringTime(content.getMtime(), content))); - properties.add(new NodeProperty<>(CHANGED_TIME.toString(), CHANGED_TIME.toString(), NO_DESCR, ContentUtils.getStringTime(content.getCtime(), content))); - properties.add(new NodeProperty<>(ACCESS_TIME.toString(), ACCESS_TIME.toString(), NO_DESCR, ContentUtils.getStringTime(content.getAtime(), content))); - properties.add(new NodeProperty<>(CREATED_TIME.toString(), CREATED_TIME.toString(), NO_DESCR, ContentUtils.getStringTime(content.getCrtime(), content))); + properties.add(new NodeProperty<>(MOD_TIME.toString(), MOD_TIME.toString(), NO_DESCR, TimeZoneUtils.getFormattedTime(content.getMtime()))); + properties.add(new NodeProperty<>(CHANGED_TIME.toString(), CHANGED_TIME.toString(), NO_DESCR, TimeZoneUtils.getFormattedTime(content.getCtime()))); + properties.add(new NodeProperty<>(ACCESS_TIME.toString(), ACCESS_TIME.toString(), NO_DESCR, TimeZoneUtils.getFormattedTime(content.getAtime()))); + properties.add(new NodeProperty<>(CREATED_TIME.toString(), CREATED_TIME.toString(), NO_DESCR, TimeZoneUtils.getFormattedTime(content.getCrtime()))); properties.add(new NodeProperty<>(SIZE.toString(), SIZE.toString(), NO_DESCR, content.getSize())); properties.add(new NodeProperty<>(FLAGS_DIR.toString(), FLAGS_DIR.toString(), NO_DESCR, content.getDirFlagAsString())); properties.add(new NodeProperty<>(FLAGS_META.toString(), FLAGS_META.toString(), NO_DESCR, content.getMetaFlagsAsString())); @@ -532,10 +533,10 @@ public abstract class AbstractAbstractFileNode extends A static public void fillPropertyMap(Map map, AbstractFile content) { map.put(NAME.toString(), getContentDisplayName(content)); map.put(LOCATION.toString(), getContentPath(content)); - map.put(MOD_TIME.toString(), ContentUtils.getStringTime(content.getMtime(), content)); - map.put(CHANGED_TIME.toString(), ContentUtils.getStringTime(content.getCtime(), content)); - map.put(ACCESS_TIME.toString(), ContentUtils.getStringTime(content.getAtime(), content)); - map.put(CREATED_TIME.toString(), ContentUtils.getStringTime(content.getCrtime(), content)); + map.put(MOD_TIME.toString(), TimeZoneUtils.getFormattedTime(content.getMtime())); + map.put(CHANGED_TIME.toString(), TimeZoneUtils.getFormattedTime(content.getCtime())); + map.put(ACCESS_TIME.toString(), TimeZoneUtils.getFormattedTime(content.getAtime())); + map.put(CREATED_TIME.toString(), TimeZoneUtils.getFormattedTime(content.getCrtime())); map.put(SIZE.toString(), content.getSize()); map.put(FLAGS_DIR.toString(), content.getDirFlagAsString()); map.put(FLAGS_META.toString(), content.getMetaFlagsAsString()); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentNode.java index 7e0ee1a883..0a43d47102 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentNode.java @@ -112,7 +112,7 @@ public abstract class AbstractContentNode extends ContentNode * @param lookup The Lookup object for the node. */ AbstractContentNode(T content, Lookup lookup) { - super(Children.create(new ContentChildren(content), false), lookup); + super(Children.create(new ContentChildren(content), true), lookup); this.content = content; //super.setName(ContentUtils.getSystemName(content)); super.setName("content_" + Long.toString(content.getId())); //NON-NLS @@ -349,11 +349,7 @@ public abstract class AbstractContentNode extends ContentNode protected Pair getScorePropertyAndDescription(List tags) { Score score = Score.SCORE_UNKNOWN; try { - if (content instanceof AnalysisResult) { - score = ((AnalysisResult) content).getScore(); - } else { - score = this.content.getAggregateScore(); - } + score = this.content.getAggregateScore(); } catch (TskCoreException ex) { logger.log(Level.WARNING, "Unable to get aggregate score for content with id: " + this.content.getId(), ex); } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ArtifactStringContent.java b/Core/src/org/sleuthkit/autopsy/datamodel/ArtifactStringContent.java index e2950e5b12..ea3fa67060 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ArtifactStringContent.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/ArtifactStringContent.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2017 Basis Technology Corp. + * Copyright 2011-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,12 +18,12 @@ */ package org.sleuthkit.autopsy.datamodel; -import java.text.SimpleDateFormat; import java.util.logging.Level; import org.apache.commons.lang.StringUtils; import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.TimeZoneUtils; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.Content; @@ -39,8 +39,7 @@ import org.sleuthkit.datamodel.TskCoreException; */ @Deprecated public class ArtifactStringContent implements StringContent { - - private final static SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + private final static Logger logger = Logger.getLogger(ArtifactStringContent.class.getName()); private final BlackboardArtifact artifact; private String stringContent = ""; @@ -130,11 +129,7 @@ public class ArtifactStringContent implements StringContent { // Use Autopsy date formatting settings, not TSK defaults case DATETIME: long epoch = attr.getValueLong(); - value = "0000-00-00 00:00:00"; - if (null != content && 0 != epoch) { - dateFormatter.setTimeZone(ContentUtils.getTimeZone(content)); - value = dateFormatter.format(new java.util.Date(epoch * 1000)); - } + value = TimeZoneUtils.getFormattedTime(epoch * 1000); break; } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Artifacts.java b/Core/src/org/sleuthkit/autopsy/datamodel/Artifacts.java index 796be557fd..cd0b03fd98 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Artifacts.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Artifacts.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2020 Basis Technology Corp. + * Copyright 2011-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -36,6 +36,7 @@ import org.openide.nodes.Node; import org.openide.nodes.Sheet; import org.openide.util.Lookup; import org.openide.util.NbBundle; +import org.openide.util.WeakListeners; import org.openide.util.lookup.Lookups; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; @@ -277,6 +278,8 @@ public class Artifacts { */ private final RefreshThrottler refreshThrottler = new RefreshThrottler(this); private final Category category; + + private final PropertyChangeListener weakPcl; /** * Main constructor. @@ -290,45 +293,50 @@ public class Artifacts { super(); this.filteringDSObjId = filteringDSObjId; this.category = category; - } - - private final PropertyChangeListener pcl = (PropertyChangeEvent evt) -> { - String eventType = evt.getPropertyName(); - if (eventType.equals(Case.Events.CURRENT_CASE.toString())) { - // case was closed. Remove listeners so that we don't get called with a stale case handle - if (evt.getNewValue() == null) { - removeNotify(); - } - } else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) - || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) { - /** - * This is a stop gap measure until a different way of handling - * the closing of cases is worked out. Currently, remote events - * may be received for a case that is already closed. - */ - try { - Case.getCurrentCaseThrows(); - refresh(false); - } catch (NoCurrentCaseException notUsed) { + + PropertyChangeListener pcl = (PropertyChangeEvent evt) -> { + String eventType = evt.getPropertyName(); + if (eventType.equals(Case.Events.CURRENT_CASE.toString())) { + // case was closed. Remove listeners so that we don't get called with a stale case handle + if (evt.getNewValue() == null) { + removeNotify(); + } + } else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) + || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) { /** - * Case is closed, do nothing. + * This is a stop gap measure until a different way of + * handling the closing of cases is worked out. Currently, + * remote events may be received for a case that is already + * closed. */ + try { + Case.getCurrentCaseThrows(); + refresh(false); + } catch (NoCurrentCaseException notUsed) { + /** + * Case is closed, do nothing. + */ + } } - } - }; + }; + weakPcl = WeakListeners.propertyChange(pcl, null); + } + @Override - protected void addNotify() { + protected void addNotify() { + super.addNotify(); refreshThrottler.registerForIngestModuleEvents(); - IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); - Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl); + Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); } @Override - protected void removeNotify() { + protected void finalize() throws Throwable { + super.finalize(); refreshThrottler.unregisterEventListener(); - IngestManager.getInstance().removeIngestJobEventListener(pcl); - Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); + IngestManager.getInstance().removeIngestJobEventListener(weakPcl); + Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); typeNodeMap.clear(); } @@ -624,17 +632,21 @@ public class Artifacts { } } }; + + private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null); @Override protected void onAdd() { refreshThrottler.registerForIngestModuleEvents(); - IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl); } @Override protected void onRemove() { - refreshThrottler.unregisterEventListener(); - IngestManager.getInstance().removeIngestJobEventListener(pcl); + if(refreshThrottler != null) { + refreshThrottler.unregisterEventListener(); + } + IngestManager.getInstance().removeIngestJobEventListener(weakPcl); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyTreeChildFactory.java b/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyTreeChildFactory.java index aa481b021e..d4becd5d63 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyTreeChildFactory.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyTreeChildFactory.java @@ -1,15 +1,14 @@ /* * Autopsy Forensic Browser - * - * Copyright 2018 Basis Technology Corp. + * Copyright 2018-2021 Basis Technology Corp. * Contact: carrier sleuthkit org - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may 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. @@ -20,7 +19,6 @@ 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.EnumSet; @@ -32,6 +30,7 @@ import java.util.stream.Collectors; import org.apache.commons.collections.CollectionUtils; import org.openide.nodes.ChildFactory; import org.openide.nodes.Node; +import org.openide.util.WeakListeners; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.CasePreferences; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; @@ -43,57 +42,73 @@ import org.sleuthkit.datamodel.SleuthkitVisitableItem; 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 { - private static final Set LISTENING_EVENTS = EnumSet.of( - Case.Events.DATA_SOURCE_ADDED, + private static final Set EVENTS_OF_INTEREST = EnumSet.of(Case.Events.DATA_SOURCE_ADDED, Case.Events.HOSTS_ADDED, Case.Events.HOSTS_DELETED, Case.Events.PERSONS_ADDED, Case.Events.PERSONS_DELETED, - Case.Events.PERSONS_CHANGED + Case.Events.HOSTS_ADDED_TO_PERSON, + Case.Events.HOSTS_REMOVED_FROM_PERSON ); - private static final Set LISTENING_EVENT_NAMES = LISTENING_EVENTS.stream() + private static final Set EVENTS_OF_INTEREST_NAMES = EVENTS_OF_INTEREST.stream() .map(evt -> evt.name()) .collect(Collectors.toSet()); 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() { @Override public void propertyChange(PropertyChangeEvent evt) { String eventType = evt.getPropertyName(); - if (LISTENING_EVENT_NAMES.contains(eventType) + if (EVENTS_OF_INTEREST_NAMES.contains(eventType) && Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true)) { refreshChildren(); } } }; + private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null); + @Override protected void addNotify() { super.addNotify(); - Case.addEventTypeSubscriber(LISTENING_EVENTS, pcl); + Case.addEventTypeSubscriber(EVENTS_OF_INTEREST, weakPcl); } - + @Override - protected void removeNotify() { - super.removeNotify(); - Case.removeEventTypeSubscriber(LISTENING_EVENTS, pcl); + protected void finalize() throws Throwable { + super.finalize(); + Case.removeEventTypeSubscriber(EVENTS_OF_INTEREST, weakPcl); } /** - * 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 - * @return true, indicating that the key list is complete + * IMPORTANT: Every time a key is added to the keys list, the NetBeans + * framework reacts. To avoid significant performance hits, all of the keys + * need to be added at once. + * + * @param list A list to contain the keys. + * + * @return True, indicating that the list of keys is complete. */ @Override protected boolean createKeys(List list) { @@ -101,6 +116,10 @@ public final class AutopsyTreeChildFactory extends ChildFactory.Detachable persons = personManager.getPersons(); // show persons level if there are persons to be shown @@ -110,7 +129,7 @@ public final class AutopsyTreeChildFactory extends ChildFactory.Detachable extends ChildFactory.D isPageSizeChangeEvent = false; this.filter = filter; } - + @Override protected void addNotify() { onAdd(); } @Override - protected void removeNotify() { + protected void finalize() throws Throwable { + super.finalize(); onRemove(); } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java index 8e52e6d8b7..e3bad44705 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2012-2020 Basis Technology Corp. + * Copyright 2012-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -75,9 +75,12 @@ import org.sleuthkit.datamodel.Tag; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.autopsy.datamodel.utils.IconsUtil; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; +import org.sleuthkit.autopsy.coreutils.TimeZoneUtils; import static org.sleuthkit.autopsy.datamodel.AbstractContentNode.NO_DESCR; import org.sleuthkit.autopsy.texttranslation.TextTranslationService; import org.sleuthkit.autopsy.datamodel.utils.FileNameTransTask; +import org.sleuthkit.datamodel.AnalysisResult; +import org.sleuthkit.datamodel.BlackboardArtifact.Category; import org.sleuthkit.datamodel.Score; /** @@ -107,17 +110,6 @@ public class BlackboardArtifactNode extends AbstractContentNode( NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileChangedTime.name"), NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileChangedTime.displayName"), "", - file == null ? "" : ContentUtils.getStringTime(file.getCtime(), file))); + file == null ? "" : TimeZoneUtils.getFormattedTime(file.getCtime()))); sheetSet.put(new NodeProperty<>( NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileAccessedTime.name"), NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileAccessedTime.displayName"), "", - file == null ? "" : ContentUtils.getStringTime(file.getAtime(), file))); + file == null ? "" : TimeZoneUtils.getFormattedTime(file.getAtime()))); sheetSet.put(new NodeProperty<>( NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileCreatedTime.name"), NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileCreatedTime.displayName"), "", - file == null ? "" : ContentUtils.getStringTime(file.getCrtime(), file))); + file == null ? "" : TimeZoneUtils.getFormattedTime(file.getCrtime()))); sheetSet.put(new NodeProperty<>( NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileSize.name"), NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileSize.displayName"), @@ -943,7 +957,7 @@ public class BlackboardArtifactNode extends AbstractContentNode { @Override protected List makeKeys() { - return getDisplayChildren(parent); + List contentList = getDisplayChildren(parent); + + // Call the getUniquePath method to cache the value for future use + // in the EDT + contentList.forEach(content->{ + try { + content.getUniquePath(); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, String.format("Failed attempt to cache the " + + "unique path of the abstract file instance. Name: %s (objID=%d)", + content.getName(), content.getId()), ex); + } + }); + + return contentList; } @Override diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ContentNodeVisitor.java b/Core/src/org/sleuthkit/autopsy/datamodel/ContentNodeVisitor.java index 3f6706952a..e7ce03dd7d 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ContentNodeVisitor.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/ContentNodeVisitor.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011 Basis Technology Corp. + * Copyright 2011-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -55,6 +55,8 @@ interface ContentNodeVisitor { T visit(UnsupportedContentNode ucn); T visit(OsAccountNode bban); + + T visit(LocalFilesDataSourceNode lfdsn); /** * Visitor with an implementable default behavior for all types. Override @@ -137,5 +139,10 @@ interface ContentNodeVisitor { public T visit(OsAccountNode bban) { return defaultVisit(bban); } + + @Override + public T visit(LocalFilesDataSourceNode lfdsn) { + return defaultVisit(lfdsn); + } } } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ContentTagNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/ContentTagNode.java index 89d6c2fae2..b67405b43d 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ContentTagNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/ContentTagNode.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013-2020 Basis Technology Corp. + * Copyright 2013-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -29,6 +29,7 @@ import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; import org.openide.util.lookup.Lookups; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.TimeZoneUtils; import org.sleuthkit.autopsy.timeline.actions.ViewFileInTimelineAction; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Content; @@ -96,22 +97,22 @@ class ContentTagNode extends TagNode { properties.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileModifiedTime.name"), NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileModifiedTime.displayName"), "", - file != null ? ContentUtils.getStringTime(file.getMtime(), file) : "")); + file != null ? TimeZoneUtils.getFormattedTime(file.getMtime()) : "")); properties.put(new NodeProperty<>( NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileChangedTime.name"), NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileChangedTime.displayName"), "", - file != null ? ContentUtils.getStringTime(file.getCtime(), file) : "")); + file != null ? TimeZoneUtils.getFormattedTime(file.getCtime()) : "")); properties.put(new NodeProperty<>( NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileAccessedTime.name"), NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileAccessedTime.displayName"), "", - file != null ? ContentUtils.getStringTime(file.getAtime(), file) : "")); + file != null ? TimeZoneUtils.getFormattedTime(file.getAtime()) : "")); properties.put(new NodeProperty<>( NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileCreatedTime.name"), NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileCreatedTime.displayName"), "", - file != null ? ContentUtils.getStringTime(file.getCrtime(), file) : "")); + file != null ? TimeZoneUtils.getFormattedTime(file.getCrtime()) : "")); properties.put(new NodeProperty<>( NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileSize.name"), NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileSize.displayName"), diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ContentUtils.java b/Core/src/org/sleuthkit/autopsy/datamodel/ContentUtils.java index 34ebfac8a6..6def78b83d 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ContentUtils.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/ContentUtils.java @@ -26,8 +26,6 @@ import java.util.TimeZone; import java.util.concurrent.Future; import java.util.function.Supplier; import java.util.logging.Level; -import java.util.prefs.PreferenceChangeEvent; -import java.util.prefs.PreferenceChangeListener; import javax.swing.SwingWorker; import org.netbeans.api.progress.ProgressHandle; import org.openide.util.NbBundle; @@ -39,7 +37,6 @@ import org.sleuthkit.datamodel.ContentVisitor; import org.sleuthkit.datamodel.DerivedFile; import org.sleuthkit.datamodel.Directory; import org.sleuthkit.datamodel.File; -import org.sleuthkit.datamodel.Image; import org.sleuthkit.datamodel.LayoutFile; import org.sleuthkit.datamodel.LocalFile; import org.sleuthkit.datamodel.LocalDirectory; @@ -55,21 +52,9 @@ import org.sleuthkit.datamodel.VirtualDirectory; public final class ContentUtils { private final static Logger logger = Logger.getLogger(ContentUtils.class.getName()); - private static boolean displayTimesInLocalTime = UserPreferences.displayTimesInLocalTime(); private static final SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z"); private static final SimpleDateFormat dateFormatterISO8601 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); - static { - UserPreferences.addChangeListener(new PreferenceChangeListener() { - @Override - public void preferenceChange(PreferenceChangeEvent evt) { - if (evt.getKey().equals(UserPreferences.DISPLAY_TIMES_IN_LOCAL_TIME)) { - displayTimesInLocalTime = UserPreferences.displayTimesInLocalTime(); - } - } - }); - } - /** * Don't instantiate */ @@ -85,6 +70,7 @@ public final class ContentUtils { * * @return The time */ + @Deprecated public static String getStringTime(long epochSeconds, TimeZone tzone) { String time = "0000-00-00 00:00:00"; if (epochSeconds != 0) { @@ -104,6 +90,7 @@ public final class ContentUtils { * * @return The time */ + @Deprecated public static String getStringTimeISO8601(long epochSeconds, TimeZone tzone) { String time = "0000-00-00T00:00:00Z"; //NON-NLS if (epochSeconds != 0) { @@ -123,7 +110,10 @@ public final class ContentUtils { * @param content * * @return + * + * @deprecated Use org.sleuthkit.autopsy.coreutils.TimeZoneUtils.getFormattedTime instead */ + @Deprecated public static String getStringTime(long epochSeconds, Content content) { return getStringTime(epochSeconds, getTimeZone(content)); } @@ -136,29 +126,30 @@ public final class ContentUtils { * @param c * * @return + * + * @deprecated Use org.sleuthkit.autopsy.coreutils.TimeZoneUtils.getFormattedTimeISO8601 instead */ + @Deprecated public static String getStringTimeISO8601(long epochSeconds, Content c) { return getStringTimeISO8601(epochSeconds, getTimeZone(c)); } + /** + * Returns either the user selected time zone or the system time zone. + * + * @param content + * + * @return + * + * @deprecated Use org.sleuthkit.autopsy.coreutils.TimeZoneUtils.getTimeZone instead + */ + @Deprecated public static TimeZone getTimeZone(Content content) { - - try { - if (!shouldDisplayTimesInLocalTime()) { - return TimeZone.getTimeZone(UserPreferences.getTimeZoneForDisplays()); - } else { - final Content dataSource = content.getDataSource(); - if ((dataSource != null) && (dataSource instanceof Image)) { - Image image = (Image) dataSource; - return TimeZone.getTimeZone(image.getTimeZone()); - } else { - //case such as top level VirtualDirectory - return TimeZone.getDefault(); - } - } - } catch (TskCoreException ex) { + if (!shouldDisplayTimesInLocalTime()) { + return TimeZone.getTimeZone(UserPreferences.getTimeZoneForDisplays()); + } else { return TimeZone.getDefault(); - } + } } private static final SystemNameVisitor systemName = new SystemNameVisitor(); @@ -553,9 +544,12 @@ public final class ContentUtils { * Indicates whether or not times should be displayed using local time. * * @return True or false. + * + * @deprecated Call UserPreferences.displayTimesInLocalTime instead. */ + @Deprecated public static boolean shouldDisplayTimesInLocalTime() { - return displayTimesInLocalTime; + return UserPreferences.displayTimesInLocalTime(); } } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/CreateSleuthkitNodeVisitor.java b/Core/src/org/sleuthkit/autopsy/datamodel/CreateSleuthkitNodeVisitor.java index 7601f4a88c..00712fc99a 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/CreateSleuthkitNodeVisitor.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/CreateSleuthkitNodeVisitor.java @@ -28,6 +28,7 @@ import org.sleuthkit.datamodel.Image; import org.sleuthkit.datamodel.LayoutFile; import org.sleuthkit.datamodel.LocalDirectory; import org.sleuthkit.datamodel.LocalFile; +import org.sleuthkit.datamodel.LocalFilesDataSource; import org.sleuthkit.datamodel.Pool; import org.sleuthkit.datamodel.SlackFile; import org.sleuthkit.datamodel.SleuthkitItemVisitor; @@ -111,4 +112,9 @@ public class CreateSleuthkitNodeVisitor extends SleuthkitItemVisitor.Default visit(LocalFilesDataSource ld) { + return new LocalFilesDataSourceNode(ld); + } } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DataSourceFilesNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/DataSourceFilesNode.java new file mode 100644 index 0000000000..b7e33860b9 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DataSourceFilesNode.java @@ -0,0 +1,182 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2012-2021 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may 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 images) { + this(0); + } + + public DataSourceFilesNode() { + this(0); + } + + public DataSourceFilesNode(long dsObjId) { + super(Children.create(new DataSourcesNodeChildren(dsObjId), true), 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 { + + private static final Logger logger = Logger.getLogger(DataSourcesNodeChildren.class.getName()); + private final long datasourceObjId; + + List 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 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() { + @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 accept(DisplayableItemNodeVisitor 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; + } +} diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DataSourceGroupingNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/DataSourceGroupingNode.java index 28ad25fe59..8e99aa2172 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DataSourceGroupingNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DataSourceGroupingNode.java @@ -80,8 +80,7 @@ class DataSourceGroupingNode extends DisplayableItemNode { new DataArtifacts(dsObjId), new AnalysisResults(dsObjId), new OsAccounts(Case.getCurrentCaseThrows().getSleuthkitCase(), dsObjId), - new Tags(dsObjId), - new Reports() + new Tags(dsObjId) )); } catch (NoCurrentCaseException ex) { diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DataSources.java b/Core/src/org/sleuthkit/autopsy/datamodel/DataSources.java index 52ca52e89f..4f23327401 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DataSources.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DataSources.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011 Basis Technology Corp. + * Copyright 2011-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,7 +19,7 @@ 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 { diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DataSourcesByTypeNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/DataSourcesByTypeNode.java deleted file mode 100644 index 1fab7774c7..0000000000 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DataSourcesByTypeNode.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2021 Basis Technology Corp. - * Contact: carrier sleuthkit org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may 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 { - - private static final Set 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 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 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 accept(DisplayableItemNodeVisitor 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; - } -} diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DataSourcesNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/DataSourcesNode.java index 033f14fc04..e735eca3d9 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DataSourcesNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DataSourcesNode.java @@ -1,15 +1,15 @@ /* * Autopsy Forensic Browser - * - * Copyright 2011-2018 Basis Technology Corp. + * + * Copyright 2021 Basis Technology Corp. * Contact: carrier sleuthkit org - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may 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. @@ -20,60 +20,116 @@ 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.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.WeakListeners; 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; /** - * 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 { - private static final String NAME = NbBundle.getMessage(DataSourcesNode.class, "DataSourcesNode.name"); - + /* + * Custom Keys implementation that listens for new data sources being added. + */ + public static class DataSourcesByTypeChildren extends ChildFactory.Detachable { + + private static final Set UPDATE_EVTS = EnumSet.of(Case.Events.DATA_SOURCE_ADDED, + Case.Events.HOSTS_ADDED, + Case.Events.HOSTS_DELETED, + Case.Events.HOSTS_UPDATED); + + private static final Set 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); + } + } + }; + + private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null); + + @Override + protected void addNotify() { + Case.addEventTypeSubscriber(UPDATE_EVTS, weakPcl); + } + + @Override + protected void finalize() throws Throwable{ + Case.removeEventTypeSubscriber(UPDATE_EVTS, weakPcl); + super.finalize(); + } + + @Override + protected boolean createKeys(List 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; } - - private final String displayName; - // NOTE: The images passed in via argument will be ignored. - @Deprecated - public DataSourcesNode(List 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() { + /** + * Main constructor. + */ + DataSourcesNode() { + super(Children.create(new DataSourcesByTypeChildren(), true), Lookups.singleton(NAME)); setName(NAME); - setDisplayName(displayName); - this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/image.png"); //NON-NLS + setDisplayName(NAME); + this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/image.png"); } @Override @@ -81,76 +137,6 @@ public class DataSourcesNode extends DisplayableItemNode { return getClass().getName(); } - /* - * Custom Keys implementation that listens for new data sources being added. - */ - public static class DataSourcesNodeChildren extends AbstractContentChildren { - - private static final Logger logger = Logger.getLogger(DataSourcesNodeChildren.class.getName()); - private final long datasourceObjId; - - List 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 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() { - @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; @@ -176,4 +162,4 @@ public class DataSourcesNode extends DisplayableItemNode { NAME)); return sheet; } -} \ No newline at end of file +} diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java index 715f9aecd9..47db7732ea 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011 - 2018 Basis Technology Corp. + * Copyright 2011 - 2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -42,7 +42,7 @@ public interface DisplayableItemNodeVisitor { /* * Data Sources Area */ - T visit(DataSourcesNode in); + T visit(DataSourceFilesNode in); T visit(LayoutFileNode lfn); @@ -192,16 +192,18 @@ public interface DisplayableItemNodeVisitor { T visit(OsAccounts.OsAccountListNode node); - T visit(PersonGroupingNode node); + T visit(PersonNode node); T visit(HostNode node); - T visit(DataSourcesByTypeNode node); + T visit(DataSourcesNode node); /* * Unsupported node */ T visit(UnsupportedContentNode ucn); + + T visit(LocalFilesDataSourceNode lfdsn); /** * Visitor with an implementable default behavior for all types. Override @@ -406,7 +408,7 @@ public interface DisplayableItemNodeVisitor { } @Override - public T visit(DataSourcesNode in) { + public T visit(DataSourceFilesNode in) { return defaultVisit(in); } @@ -561,12 +563,12 @@ public interface DisplayableItemNodeVisitor { } @Override - public T visit(DataSourcesByTypeNode node) { + public T visit(DataSourcesNode node) { return defaultVisit(node); } @Override - public T visit(PersonGroupingNode node) { + public T visit(PersonNode node) { return defaultVisit(node); } @@ -574,5 +576,10 @@ public interface DisplayableItemNodeVisitor { public T visit(UnsupportedContentNode node) { return defaultVisit(node); } + + @Override + public T visit(LocalFilesDataSourceNode node) { + return defaultVisit(node); + } } } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java b/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java index 0acd6a8bf3..00d941b714 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/EmailExtracted.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2012-2020 Basis Technology Corp. + * Copyright 2012-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -37,6 +37,7 @@ import org.openide.nodes.Children; import org.openide.nodes.Node; import org.openide.nodes.Sheet; import org.openide.util.NbBundle; +import org.openide.util.WeakListeners; import org.openide.util.lookup.Lookups; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; @@ -314,20 +315,23 @@ public class EmailExtracted implements AutopsyVisitableItem { } }; + private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null); + @Override protected void addNotify() { - IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); - IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl); - Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl); + IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakPcl); + Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); emailResults.update(); emailResults.addObserver(this); } @Override - protected void removeNotify() { - IngestManager.getInstance().removeIngestJobEventListener(pcl); - IngestManager.getInstance().removeIngestModuleEventListener(pcl); - Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); + protected void finalize() throws Throwable { + super.finalize(); + IngestManager.getInstance().removeIngestJobEventListener(weakPcl); + IngestManager.getInstance().removeIngestModuleEventListener(weakPcl); + Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); emailResults.deleteObserver(this); } @@ -436,6 +440,23 @@ public class EmailExtracted implements AutopsyVisitableItem { } } + /** + * Ensures that the key for the parent node and child factory is the same to + * ensure that the BaseChildFactory registered listener node name + * (BaseChildFactory.register and DataResultViewerTable.setNode with event + * registration) is the same as the factory name that will post events from + * BaseChildFactory.post called in BaseChildFactory.makeKeys. See JIRA-7752 + * for more details. + * + * @param accountName The account name. + * @param folderName The folder name. + * + * @return The generated key. + */ + private static String getFolderKey(String accountName, String folderName) { + return accountName + "_" + folderName; + } + /** * Node representing mail folder */ @@ -446,7 +467,7 @@ public class EmailExtracted implements AutopsyVisitableItem { public FolderNode(String accountName, String folderName) { super(Children.create(new MessageFactory(accountName, folderName), true), Lookups.singleton(accountName)); - super.setName(folderName); + super.setName(getFolderKey(accountName, folderName)); this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/folder-icon-16.png"); //NON-NLS this.accountName = accountName; this.folderName = folderName; @@ -506,7 +527,7 @@ public class EmailExtracted implements AutopsyVisitableItem { private final String folderName; private MessageFactory(String accountName, String folderName) { - super(accountName + "_" + folderName); + super(getFolderKey(accountName, folderName)); this.accountName = accountName; this.folderName = folderName; emailResults.addObserver(this); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypes.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypes.java index e5d374f6f0..9404362218 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypes.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypes.java @@ -397,6 +397,11 @@ public final class FileTypes implements AutopsyVisitableItem { return content.newDataArtifact(artifactType, attributesList, osAccountId); } + @Override + public DataArtifact newDataArtifact(BlackboardArtifact.Type artifactType, Collection attributesList, Long osAccountId, long dataSourceId) throws TskCoreException { + return content.newDataArtifact(artifactType, attributesList, osAccountId, dataSourceId); + } + @Override public DataArtifact newDataArtifact(BlackboardArtifact.Type artifactType, Collection attributesList) throws TskCoreException { return content.newDataArtifact(artifactType, attributesList); @@ -467,6 +472,11 @@ public final class FileTypes implements AutopsyVisitableItem { return content.newAnalysisResult(type, score, string, string1, string2, clctn); } + @Override + public AnalysisResultAdded newAnalysisResult(BlackboardArtifact.Type type, Score score, String string, String string1, String string2, Collection clctn, long dataSourceId) throws TskCoreException { + return content.newAnalysisResult(type, score, string, string1, string2, clctn, dataSourceId); + } + @Override public Score getAggregateScore() throws TskCoreException { return content.getAggregateScore(); @@ -481,5 +491,10 @@ public final class FileTypes implements AutopsyVisitableItem { public List getAllAnalysisResults() throws TskCoreException { return content.getAllAnalysisResults(); } + + @Override + public List getAllDataArtifacts() throws TskCoreException { + return content.getAllDataArtifacts(); + } } } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java b/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java index e98b154ff0..970e546f98 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/HashsetHits.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2020 Basis Technology Corp. + * Copyright 2011-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -39,6 +39,7 @@ import org.openide.nodes.Children; import org.openide.nodes.Node; import org.openide.nodes.Sheet; import org.openide.util.NbBundle; +import org.openide.util.WeakListeners; import org.openide.util.lookup.Lookups; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; @@ -278,21 +279,24 @@ public class HashsetHits implements AutopsyVisitableItem { } } }; + + private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null); @Override protected void addNotify() { - IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); - IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl); - Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl); + IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakPcl); + Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); hashsetResults.update(); hashsetResults.addObserver(this); } @Override - protected void removeNotify() { - IngestManager.getInstance().removeIngestJobEventListener(pcl); - IngestManager.getInstance().removeIngestModuleEventListener(pcl); - Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); + protected void finalize() throws Throwable { + super.finalize(); + IngestManager.getInstance().removeIngestJobEventListener(weakPcl); + IngestManager.getInstance().removeIngestModuleEventListener(weakPcl); + Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); hashsetResults.deleteObserver(this); } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/HostNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/HostNode.java index 94256255b9..95e6254510 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/HostNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/HostNode.java @@ -39,7 +39,7 @@ import org.openide.util.WeakListeners; import org.openide.util.lookup.Lookups; import org.sleuthkit.autopsy.casemodule.Case; 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.datamodel.hosts.AssociatePersonsMenuAction; import org.sleuthkit.autopsy.datamodel.hosts.MergeHostMenuAction; @@ -66,7 +66,7 @@ public class HostNode extends DisplayableItemNode { private final Host host; private final Function dataSourceToNode; - + /** * Main constructor. * @@ -77,7 +77,7 @@ public class HostNode extends DisplayableItemNode { this.host = host; this.dataSourceToNode = dataSourceToNode; } - + /** * Listener for handling DATA_SOURCE_ADDED / HOST_DELETED events. * A host may have been deleted as part of a merge, which means its data sources could @@ -93,15 +93,19 @@ public class HostNode extends DisplayableItemNode { } } }; - + + private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(dataSourceAddedPcl, null); + @Override protected void addNotify() { - Case.addEventTypeSubscriber(EnumSet.of(Case.Events.DATA_SOURCE_ADDED, Case.Events.HOSTS_DELETED), dataSourceAddedPcl); + super.addNotify(); + Case.addEventTypeSubscriber(EnumSet.of(Case.Events.DATA_SOURCE_ADDED, Case.Events.HOSTS_DELETED), weakPcl); } @Override - protected void removeNotify() { - Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.DATA_SOURCE_ADDED, Case.Events.HOSTS_DELETED), dataSourceAddedPcl); + protected void finalize() throws Throwable { + super.finalize(); + Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.DATA_SOURCE_ADDED, Case.Events.HOSTS_DELETED), weakPcl); } @Override @@ -178,8 +182,8 @@ public class HostNode extends DisplayableItemNode { @Override public void propertyChange(PropertyChangeEvent evt) { String eventType = evt.getPropertyName(); - if (hostId != null && eventType.equals(Case.Events.HOSTS_CHANGED.toString()) && evt instanceof HostsChangedEvent) { - ((HostsChangedEvent) evt).getNewValue().stream() + if (hostId != null && eventType.equals(Case.Events.HOSTS_UPDATED.toString()) && evt instanceof HostsUpdatedEvent) { + ((HostsUpdatedEvent) evt).getHosts().stream() .filter(h -> h != null && h.getHostId() == hostId) .findFirst() .ifPresent((newHost) -> { @@ -189,6 +193,8 @@ public class HostNode extends DisplayableItemNode { } } }; + + private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(hostChangePcl, null); /* * Get the host name or 'unknown host' if null. @@ -212,7 +218,7 @@ public class HostNode extends DisplayableItemNode { * @param hosts The HostDataSources key. */ HostNode(HostDataSources hosts) { - this(Children.create(new HostGroupingChildren(HOST_DATA_SOURCES, hosts.getHost()), false), hosts.getHost()); + this(Children.create(new HostGroupingChildren(HOST_DATA_SOURCES, hosts.getHost()), true), hosts.getHost()); } /** @@ -222,7 +228,7 @@ public class HostNode extends DisplayableItemNode { * @param hostGrouping The HostGrouping key. */ HostNode(HostGrouping hostGrouping) { - this(Children.create(new HostGroupingChildren(HOST_GROUPING_CONVERTER, hostGrouping.getHost()), false), hostGrouping.getHost()); + this(Children.create(new HostGroupingChildren(HOST_GROUPING_CONVERTER, hostGrouping.getHost()), true), hostGrouping.getHost()); } /** @@ -247,8 +253,7 @@ public class HostNode extends DisplayableItemNode { host == null ? Lookups.fixed(displayName) : Lookups.fixed(host, displayName)); hostId = host == null ? null : host.getHostId(); - Case.addEventTypeSubscriber(EnumSet.of(Case.Events.HOSTS_CHANGED), - WeakListeners.propertyChange(hostChangePcl, this)); + Case.addEventTypeSubscriber(EnumSet.of(Case.Events.HOSTS_UPDATED), weakPcl); super.setName(displayName); super.setDisplayName(displayName); this.setIconBaseWithExtension(ICON_PATH); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ImageNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/ImageNode.java index ea0e2bb347..5df888052b 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ImageNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/ImageNode.java @@ -20,8 +20,6 @@ package org.sleuthkit.autopsy.datamodel; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; -import java.sql.ResultSet; -import java.sql.SQLException; import java.util.ArrayList; import java.util.Collections; import java.util.EnumSet; @@ -35,7 +33,6 @@ import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.DeleteDataSourceAction; -import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.datasourcesummary.ui.ViewSummaryInformationAction; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance; import org.sleuthkit.autopsy.corecomponents.DataResultViewerTable; @@ -48,7 +45,6 @@ import org.sleuthkit.autopsy.ingest.ModuleContentEvent; import org.sleuthkit.autopsy.ingest.runIngestModuleWizard.RunIngestModulesAction; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Image; -import org.sleuthkit.datamodel.SleuthkitCase.CaseDbQuery; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.VirtualDirectory; import org.sleuthkit.autopsy.datamodel.BaseChildFactory.NoSuchEventBusException; @@ -171,17 +167,10 @@ public class ImageNode extends AbstractContentNode { Bundle.ImageNode_createSheet_timezone_desc(), this.content.getTimeZone())); - try (CaseDbQuery query = Case.getCurrentCaseThrows().getSleuthkitCase().executeQuery("SELECT device_id FROM data_source_info WHERE obj_id = " + this.content.getId());) { - ResultSet deviceIdSet = query.getResultSet(); - if (deviceIdSet.next()) { - sheetSet.put(new NodeProperty<>(Bundle.ImageNode_createSheet_deviceId_name(), + sheetSet.put(new NodeProperty<>(Bundle.ImageNode_createSheet_deviceId_name(), Bundle.ImageNode_createSheet_deviceId_displayName(), Bundle.ImageNode_createSheet_deviceId_desc(), - deviceIdSet.getString("device_id"))); - } - } catch (SQLException | TskCoreException | NoCurrentCaseException ex) { - logger.log(Level.SEVERE, "Failed to get device id for the following image: " + this.content.getId(), ex); - } + content.getDeviceId())); return sheet; } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/InterestingHits.java b/Core/src/org/sleuthkit/autopsy/datamodel/InterestingHits.java index 57f2524ff9..f636264082 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/InterestingHits.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/InterestingHits.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2020 Basis Technology Corp. + * Copyright 2011-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -39,6 +39,7 @@ import org.openide.nodes.Children; import org.openide.nodes.Node; import org.openide.nodes.Sheet; import org.openide.util.NbBundle; +import org.openide.util.WeakListeners; import org.openide.util.lookup.Lookups; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; @@ -271,21 +272,24 @@ public class InterestingHits implements AutopsyVisitableItem { } } }; - + + private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null); + @Override protected void addNotify() { - IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); - IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl); - Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl); + IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakPcl); + Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); interestingResults.update(); interestingResults.addObserver(this); } @Override - protected void removeNotify() { - IngestManager.getInstance().removeIngestJobEventListener(pcl); - IngestManager.getInstance().removeIngestModuleEventListener(pcl); - Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); + protected void finalize() throws Throwable { + super.finalize(); + IngestManager.getInstance().removeIngestJobEventListener(weakPcl); + IngestManager.getInstance().removeIngestModuleEventListener(weakPcl); + Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); interestingResults.deleteObserver(this); } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java b/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java index a129e3ff30..4406944fa3 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/KeywordHits.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2020 Basis Technology Corp. + * Copyright 2011-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -42,10 +42,12 @@ import org.openide.nodes.Node; import org.openide.nodes.Sheet; import org.openide.util.Lookup; import org.openide.util.NbBundle; +import org.openide.util.WeakListeners; 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.autopsy.coreutils.TimeZoneUtils; import static org.sleuthkit.autopsy.datamodel.Bundle.*; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.ModuleDataEvent; @@ -436,7 +438,8 @@ public class KeywordHits implements AutopsyVisitableItem { } @Override - protected void removeNotify() { + protected void finalize() throws Throwable { + super.finalize(); keywordResults.deleteObserver(this); } @@ -503,22 +506,24 @@ public class KeywordHits implements AutopsyVisitableItem { } }; + + private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null); @Override protected void addNotify() { - IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); - IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl); - Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl); + IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakPcl); + Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); keywordResults.update(); super.addNotify(); } @Override - protected void removeNotify() { - IngestManager.getInstance().removeIngestJobEventListener(pcl); - IngestManager.getInstance().removeIngestModuleEventListener(pcl); - Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); - super.removeNotify(); + protected void finalize() throws Throwable{ + IngestManager.getInstance().removeIngestJobEventListener(weakPcl); + IngestManager.getInstance().removeIngestModuleEventListener(weakPcl); + Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); + super.finalize(); } @Override @@ -889,17 +894,17 @@ public class KeywordHits implements AutopsyVisitableItem { KeywordHits_createNodeForKey_modTime_name(), KeywordHits_createNodeForKey_modTime_displayName(), KeywordHits_createNodeForKey_modTime_desc(), - ContentUtils.getStringTime(file.getMtime(), file))); + TimeZoneUtils.getFormattedTime(file.getMtime()))); n.addNodeProperty(new NodeProperty<>( KeywordHits_createNodeForKey_accessTime_name(), KeywordHits_createNodeForKey_accessTime_displayName(), KeywordHits_createNodeForKey_accessTime_desc(), - ContentUtils.getStringTime(file.getAtime(), file))); + TimeZoneUtils.getFormattedTime(file.getAtime()))); n.addNodeProperty(new NodeProperty<>( KeywordHits_createNodeForKey_chgTime_name(), KeywordHits_createNodeForKey_chgTime_displayName(), KeywordHits_createNodeForKey_chgTime_desc(), - ContentUtils.getStringTime(file.getCtime(), file))); + TimeZoneUtils.getFormattedTime(file.getCtime()))); return n; } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/LocalFilesDataSourceNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/LocalFilesDataSourceNode.java new file mode 100755 index 0000000000..cd011898e9 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/datamodel/LocalFilesDataSourceNode.java @@ -0,0 +1,99 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2021 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may 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 org.openide.nodes.Sheet; +import org.openide.util.NbBundle; +import org.sleuthkit.datamodel.LocalFilesDataSource; + +/** + * + * + */ +public class LocalFilesDataSourceNode extends VirtualDirectoryNode { + + private final LocalFilesDataSource localFileDataSource; + + public LocalFilesDataSourceNode(LocalFilesDataSource ld) { + super(ld); + localFileDataSource = ld; + this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/fileset-icon-16.png"); //NON-NLS + } + + @Override + @NbBundle.Messages({"LocalFilesDataSourceNode.createSheet.size.name=Size (Bytes)", + "LocalFilesDataSourceNode.createSheet.size.displayName=Size (Bytes)", + "LocalFilesDataSourceNode.createSheet.size.desc=Size of the data source in bytes.", + "LocalFilesDataSourceNode.createSheet.type.name=Type", + "LocalFilesDataSourceNode.createSheet.type.displayName=Type", + "LocalFilesDataSourceNode.createSheet.type.desc=Type of the image.", + "LocalFilesDataSourceNode.createSheet.type.text=Logical File Set", + "LocalFilesDataSourceNode.createSheet.timezone.name=Timezone", + "LocalFilesDataSourceNode.createSheet.timezone.displayName=Timezone", + "LocalFilesDataSourceNode.createSheet.timezone.desc=Timezone of the image", + "LocalFilesDataSourceNode.createSheet.deviceId.name=Device ID", + "LocalFilesDataSourceNode.createSheet.deviceId.displayName=Device ID", + "LocalFilesDataSourceNode.createSheet.deviceId.desc=Device ID of the image", + "LocalFilesDataSourceNode.createSheet.name.name=Name", + "LocalFilesDataSourceNode.createSheet.name.displayName=Name", + "LocalFilesDataSourceNode.createSheet.name.desc=no description", + "LocalFilesDataSourceNode.createSheet.noDesc=no description",}) + protected Sheet createSheet() { + Sheet sheet = new Sheet(); + Sheet.Set sheetSet = Sheet.createPropertiesSet(); + sheet.put(sheetSet); + + sheetSet.put(new NodeProperty<>(Bundle.LocalFilesDataSourceNode_createSheet_name_name(), + Bundle.LocalFilesDataSourceNode_createSheet_name_displayName(), + Bundle.LocalFilesDataSourceNode_createSheet_name_desc(), + getName())); + + sheetSet.put(new NodeProperty<>(Bundle.LocalFilesDataSourceNode_createSheet_type_name(), + Bundle.LocalFilesDataSourceNode_createSheet_type_displayName(), + Bundle.LocalFilesDataSourceNode_createSheet_type_desc(), + Bundle.LocalFilesDataSourceNode_createSheet_type_text())); + + sheetSet.put(new NodeProperty<>(Bundle.LocalFilesDataSourceNode_createSheet_size_name(), + Bundle.LocalFilesDataSourceNode_createSheet_size_displayName(), + Bundle.LocalFilesDataSourceNode_createSheet_size_desc(), + this.content.getSize())); + + sheetSet.put(new NodeProperty<>(Bundle.LocalFilesDataSourceNode_createSheet_timezone_name(), + Bundle.LocalFilesDataSourceNode_createSheet_timezone_displayName(), + Bundle.LocalFilesDataSourceNode_createSheet_timezone_desc(), + "")); + + sheetSet.put(new NodeProperty<>(Bundle.LocalFilesDataSourceNode_createSheet_deviceId_name(), + Bundle.LocalFilesDataSourceNode_createSheet_deviceId_displayName(), + Bundle.LocalFilesDataSourceNode_createSheet_deviceId_desc(), + localFileDataSource.getDeviceId())); + + return sheet; + } + + @Override + public T accept(ContentNodeVisitor visitor) { + return visitor.visit(this); + } + + @Override + public T accept(DisplayableItemNodeVisitor visitor) { + return visitor.visit(this); + } +} diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/OsAccounts.java b/Core/src/org/sleuthkit/autopsy/datamodel/OsAccounts.java index be36f0a062..ade29e2cfa 100755 --- a/Core/src/org/sleuthkit/autopsy/datamodel/OsAccounts.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/OsAccounts.java @@ -39,10 +39,11 @@ import org.openide.util.Exceptions; import org.openide.util.NbBundle.Messages; import org.openide.util.WeakListeners; 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.corecomponents.DataResultViewerTable; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.TimeZoneUtils; import static org.sleuthkit.autopsy.datamodel.AbstractContentNode.backgroundTasksPool; import org.sleuthkit.autopsy.events.AutopsyEvent; import org.sleuthkit.datamodel.Host; @@ -124,8 +125,8 @@ public final class OsAccounts implements AutopsyVisitableItem { @Override public void propertyChange(PropertyChangeEvent evt) { String eventType = evt.getPropertyName(); - if (eventType.equals(Case.Events.OS_ACCOUNT_ADDED.toString()) - || eventType.equals(Case.Events.OS_ACCOUNT_REMOVED.toString())) { + if (eventType.equals(Case.Events.OS_ACCOUNTS_ADDED.toString()) + || eventType.equals(Case.Events.OS_ACCOUNTS_DELETED.toString())) { refresh(true); } 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 @@ -136,19 +137,22 @@ public final class OsAccounts implements AutopsyVisitableItem { } } }; + + private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(listener, null); + @Override + protected void finalize() throws Throwable { + super.finalize(); + Case.removeEventTypeSubscriber(Collections.singleton(Case.Events.OS_ACCOUNTS_ADDED), weakPcl); + Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); + } + @Override 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); } - @Override - protected void removeNotify() { - Case.removeEventTypeSubscriber(Collections.singleton(Case.Events.OS_ACCOUNT_ADDED), listener); - Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), listener); - } - @Override protected boolean createKeys(List list) { if (skCase != null) { @@ -183,11 +187,14 @@ public final class OsAccounts implements AutopsyVisitableItem { private final PropertyChangeListener listener = new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { - if (evt.getPropertyName().equals(Case.Events.OS_ACCOUNT_CHANGED.name())) { - if (((OsAccountChangedEvent) evt).getOsAccount().getId() == account.getId()) { - // Update the account node to the new one - account = ((OsAccountChangedEvent) evt).getOsAccount(); - updateSheet(); + if (evt.getPropertyName().equals(Case.Events.OS_ACCOUNTS_UPDATED.name())) { + OsAccountsUpdatedEvent updateEvent = (OsAccountsUpdatedEvent) evt; + for (OsAccount acct : updateEvent.getOsAccounts()) { + if (acct.getId() == account.getId()) { + account = acct; + updateSheet(); + break; + } } } else if (evt.getPropertyName().equals(REALM_DATA_AVAILABLE_EVENT)) { OsAccountRealm realm = (OsAccountRealm) evt.getNewValue(); @@ -200,7 +207,7 @@ public final class OsAccounts implements AutopsyVisitableItem { Bundle.OsAccounts_accountRealmNameProperty_name(), Bundle.OsAccounts_accountRealmNameProperty_displayName(), Bundle.OsAccounts_accountRealmNameProperty_desc(), - "")); + realmNames.get(0))); } } } @@ -221,7 +228,7 @@ public final class OsAccounts implements AutopsyVisitableItem { setDisplayName(account.getName()); setIconBaseWithExtension(ICON_PATH); - Case.addEventTypeSubscriber(Collections.singleton(Case.Events.OS_ACCOUNT_CHANGED), weakListener); + Case.addEventTypeSubscriber(Collections.singleton(Case.Events.OS_ACCOUNTS_UPDATED), weakListener); } @Override @@ -301,7 +308,7 @@ public final class OsAccounts implements AutopsyVisitableItem { Optional creationTimeValue = account.getCreationTime(); String timeDisplayStr - = creationTimeValue.isPresent() ? DATE_FORMATTER.format(new java.util.Date(creationTimeValue.get() * 1000)) : ""; + = creationTimeValue.isPresent() ? TimeZoneUtils.getFormattedTime(creationTimeValue.get()) : ""; propertiesSet.put(new NodeProperty<>( Bundle.OsAccounts_createdTimeProperty_name(), diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/PersonGroupingNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/PersonNode.java similarity index 70% rename from Core/src/org/sleuthkit/autopsy/datamodel/PersonGroupingNode.java rename to Core/src/org/sleuthkit/autopsy/datamodel/PersonNode.java index 27c5b9f555..310fe7a350 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/PersonGroupingNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/PersonNode.java @@ -1,15 +1,15 @@ /* * Autopsy Forensic Browser - * + * * Copyright 2021 Basis Technology Corp. * Contact: carrier sleuthkit org - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may 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. @@ -36,7 +36,7 @@ import org.openide.util.WeakListeners; import org.openide.util.lookup.Lookups; import org.sleuthkit.autopsy.casemodule.Case; 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.datamodel.persons.DeletePersonAction; import org.sleuthkit.autopsy.datamodel.persons.EditPersonAction; @@ -45,16 +45,21 @@ import org.sleuthkit.datamodel.Person; import org.sleuthkit.datamodel.TskCoreException; /** - * A node to be displayed in the UI tree for a person and persons grouped in - * this host. + * A main tree view node that represents a person in a case. Its child nodes, if + * 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"}) -public class PersonGroupingNode extends DisplayableItemNode { +public class PersonNode extends DisplayableItemNode { 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. */ 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 Set CHILD_EVENTS = EnumSet.of( - Case.Events.HOSTS_ADDED, - Case.Events.HOSTS_DELETED, - Case.Events.PERSONS_CHANGED); - - private static final Set CHILD_EVENTS_STR = CHILD_EVENTS.stream() + private static final Set HOST_EVENTS_OF_INTEREST = EnumSet.of(Case.Events.HOSTS_ADDED, + Case.Events.HOSTS_ADDED, + Case.Events.HOSTS_DELETED, + Case.Events.HOSTS_ADDED_TO_PERSON, + Case.Events.HOSTS_REMOVED_FROM_PERSON); + + private static final Set HOST_EVENTS_OF_INTEREST_NAMES = HOST_EVENTS_OF_INTEREST.stream() .map(ev -> ev.name()) .collect(Collectors.toSet()); @@ -86,31 +92,40 @@ public class PersonGroupingNode extends DisplayableItemNode { */ PersonChildren(Person person) { this.person = person; + } /** - * 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() { @Override public void propertyChange(PropertyChangeEvent evt) { String eventType = evt.getPropertyName(); - if (eventType != null && CHILD_EVENTS_STR.contains(eventType)) { + if (eventType != null && HOST_EVENTS_OF_INTEREST_NAMES.contains(eventType)) { refresh(true); } } }; + + private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(hostAddedDeletedPcl, null); @Override protected void addNotify() { - Case.addEventTypeSubscriber(CHILD_EVENTS, hostAddedDeletedPcl); + Case.addEventTypeSubscriber(HOST_EVENTS_OF_INTEREST, weakPcl); } - + @Override - protected void removeNotify() { - Case.removeEventTypeSubscriber(CHILD_EVENTS, hostAddedDeletedPcl); + protected void finalize() throws Throwable { + super.finalize(); + Case.removeEventTypeSubscriber(HOST_EVENTS_OF_INTEREST, weakPcl); } - + @Override protected HostNode createNodeForKey(HostGrouping key) { return key == null ? null : new HostNode(key); @@ -120,7 +135,12 @@ public class PersonGroupingNode extends DisplayableItemNode { protected boolean createKeys(List toPopulate) { List hosts = Collections.emptyList(); 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) { String personName = person == null || person.getName() == null ? "" : person.getName(); logger.log(Level.WARNING, String.format("Unable to get data sources for host: %s", personName), ex); @@ -139,14 +159,15 @@ public class PersonGroupingNode extends DisplayableItemNode { 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() { @Override public void propertyChange(PropertyChangeEvent evt) { String eventType = evt.getPropertyName(); - if (personId != null && eventType.equals(Case.Events.PERSONS_CHANGED.toString()) && evt instanceof PersonsChangedEvent) { - ((PersonsChangedEvent) evt).getNewValue().stream() + if (personId != null && eventType.equals(Case.Events.PERSONS_UPDATED.toString()) && evt instanceof PersonsUpdatedEvent) { + ((PersonsUpdatedEvent) evt).getNewValue().stream() .filter(p -> p != null && p.getPersonId() == personId) .findFirst() .ifPresent((newPerson) -> { @@ -156,11 +177,14 @@ public class PersonGroupingNode extends DisplayableItemNode { } } }; + + private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(personChangePcl, null); /** * Gets the display name for this person or "Unknown Persons". * * @param person The person. + * * @return The non-empty string for the display name. */ private static String getDisplayName(Person person) { @@ -174,26 +198,25 @@ public class PersonGroupingNode extends DisplayableItemNode { * * @param person The person record to be represented. */ - PersonGroupingNode(Person person) { + PersonNode(Person person) { this(person, getDisplayName(person)); } /** * Constructor. * - * @param person The person. + * @param person The person. * @param displayName The display name for the person. */ - private PersonGroupingNode(Person person, String displayName) { - super(Children.create(new PersonChildren(person), false), + private PersonNode(Person person, String displayName) { + super(Children.create(new PersonChildren(person), true), person == null ? Lookups.fixed(displayName) : Lookups.fixed(person, displayName)); super.setName(displayName); super.setDisplayName(displayName); this.setIconBaseWithExtension(ICON_PATH); this.person = person; this.personId = person == null ? null : person.getPersonId(); - Case.addEventTypeSubscriber(EnumSet.of(Case.Events.PERSONS_CHANGED), - WeakListeners.propertyChange(personChangePcl, this)); + Case.addEventTypeSubscriber(EnumSet.of(Case.Events.PERSONS_UPDATED), weakPcl); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/RootContentChildren.java b/Core/src/org/sleuthkit/autopsy/datamodel/RootContentChildren.java index 24d077b5fa..694d583cdf 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/RootContentChildren.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/RootContentChildren.java @@ -130,7 +130,7 @@ public class RootContentChildren extends Children.Keys { @Override public AbstractNode visit(DataSources i) { - return new DataSourcesNode(i.filteringDataSourceObjId()); + return new DataSourceFilesNode(i.filteringDataSourceObjId()); } @Override @@ -177,7 +177,7 @@ public class RootContentChildren extends Children.Keys { @Override public AbstractNode visit(PersonGrouping personGrouping) { - return new PersonGroupingNode(personGrouping.getPerson()); + return new PersonNode(personGrouping.getPerson()); } @Override @@ -192,7 +192,7 @@ public class RootContentChildren extends Children.Keys { @Override public AbstractNode visit(DataSourcesByType dataSourceHosts) { - return new DataSourcesByTypeNode(); + return new DataSourcesNode(); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java index 6fa6487b5e..8154d5a884 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2019 Basis Technology Corp. + * Copyright 2011-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -33,6 +33,7 @@ import org.openide.nodes.Children; import org.openide.nodes.Node; import org.openide.nodes.Sheet; import org.openide.util.NbBundle; +import org.openide.util.WeakListeners; import org.openide.util.lookup.Lookups; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; @@ -213,6 +214,8 @@ public class Tags implements AutopsyVisitableItem { } } }; + + private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null); /** * Constructor @@ -221,21 +224,21 @@ public class Tags implements AutopsyVisitableItem { */ TagNameNodeFactory(long objId) { this.filteringDSObjId = objId; - } - + @Override protected void addNotify() { - IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); - Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, pcl); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl); + Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, weakPcl); tagResults.update(); tagResults.addObserver(this); } @Override - protected void removeNotify() { - IngestManager.getInstance().removeIngestJobEventListener(pcl); - Case.removeEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, pcl); + protected void finalize() throws Throwable { + super.finalize(); + IngestManager.getInstance().removeIngestJobEventListener(weakPcl); + Case.removeEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, weakPcl); tagResults.deleteObserver(this); } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/VirtualDirectoryNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/VirtualDirectoryNode.java index 86aedbd0af..4092dc599f 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/VirtualDirectoryNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/VirtualDirectoryNode.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2019 Basis Technology Corp. + * Copyright 2011-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,16 +18,9 @@ */ package org.sleuthkit.autopsy.datamodel; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.logging.Level; import org.openide.nodes.Sheet; import org.openide.util.NbBundle; -import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.datamodel.SleuthkitCase; -import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.VirtualDirectory; /** @@ -47,76 +40,12 @@ public class VirtualDirectoryNode extends SpecialDirectoryNode { super(ld); this.setDisplayName(nameForVirtualDirectory(ld)); - - //set icon for name, special case for logical file set - if (ld.isDataSource()) { - this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/fileset-icon-16.png"); //NON-NLS - } else { - this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/folder-icon-virtual.png"); //TODO NON-NLS - } + + this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/folder-icon-virtual.png"); //TODO NON-NLS } @Override - @NbBundle.Messages({"VirtualDirectoryNode.createSheet.size.name=Size (Bytes)", - "VirtualDirectoryNode.createSheet.size.displayName=Size (Bytes)", - "VirtualDirectoryNode.createSheet.size.desc=Size of the data source in bytes.", - "VirtualDirectoryNode.createSheet.type.name=Type", - "VirtualDirectoryNode.createSheet.type.displayName=Type", - "VirtualDirectoryNode.createSheet.type.desc=Type of the image.", - "VirtualDirectoryNode.createSheet.type.text=Logical File Set", - "VirtualDirectoryNode.createSheet.timezone.name=Timezone", - "VirtualDirectoryNode.createSheet.timezone.displayName=Timezone", - "VirtualDirectoryNode.createSheet.timezone.desc=Timezone of the image", - "VirtualDirectoryNode.createSheet.deviceId.name=Device ID", - "VirtualDirectoryNode.createSheet.deviceId.displayName=Device ID", - "VirtualDirectoryNode.createSheet.deviceId.desc=Device ID of the image"}) protected Sheet createSheet() { - //Do a special strategy for virtual directories.. - if(this.content.isDataSource()){ - Sheet sheet = new Sheet(); - Sheet.Set sheetSet = Sheet.createPropertiesSet(); - sheet.put(sheetSet); - - sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "VirtualDirectoryNode.createSheet.name.name"), - NbBundle.getMessage(this.getClass(), - "VirtualDirectoryNode.createSheet.name.displayName"), - NbBundle.getMessage(this.getClass(), "VirtualDirectoryNode.createSheet.name.desc"), - getName())); - - sheetSet.put(new NodeProperty<>(Bundle.VirtualDirectoryNode_createSheet_type_name(), - Bundle.VirtualDirectoryNode_createSheet_type_displayName(), - Bundle.VirtualDirectoryNode_createSheet_type_desc(), - Bundle.VirtualDirectoryNode_createSheet_type_text())); - sheetSet.put(new NodeProperty<>(Bundle.VirtualDirectoryNode_createSheet_size_name(), - Bundle.VirtualDirectoryNode_createSheet_size_displayName(), - Bundle.VirtualDirectoryNode_createSheet_size_desc(), - this.content.getSize())); - try (SleuthkitCase.CaseDbQuery query = Case.getCurrentCaseThrows().getSleuthkitCase().executeQuery("SELECT time_zone FROM data_source_info WHERE obj_id = " + this.content.getId())) { - ResultSet timeZoneSet = query.getResultSet(); - if (timeZoneSet.next()) { - sheetSet.put(new NodeProperty<>(Bundle.VirtualDirectoryNode_createSheet_timezone_name(), - Bundle.VirtualDirectoryNode_createSheet_timezone_displayName(), - Bundle.VirtualDirectoryNode_createSheet_timezone_desc(), - timeZoneSet.getString("time_zone"))); - } - } catch (SQLException | TskCoreException | NoCurrentCaseException ex) { - logger.log(Level.SEVERE, "Failed to get time zone for the following image: " + this.content.getId(), ex); - } - try (SleuthkitCase.CaseDbQuery query = Case.getCurrentCaseThrows().getSleuthkitCase().executeQuery("SELECT device_id FROM data_source_info WHERE obj_id = " + this.content.getId());) { - ResultSet deviceIdSet = query.getResultSet(); - if (deviceIdSet.next()) { - sheetSet.put(new NodeProperty<>(Bundle.VirtualDirectoryNode_createSheet_deviceId_name(), - Bundle.VirtualDirectoryNode_createSheet_deviceId_displayName(), - Bundle.VirtualDirectoryNode_createSheet_deviceId_desc(), - deviceIdSet.getString("device_id"))); - } - } catch (SQLException | TskCoreException | NoCurrentCaseException ex) { - logger.log(Level.SEVERE, "Failed to get device id for the following image: " + this.content.getId(), ex); - } - return sheet; - } - - //Otherwise default to the AAFN createSheet method. Sheet defaultSheet = super.createSheet(); Sheet.Set defaultSheetSet = defaultSheet.get(Sheet.PROPERTIES); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/accounts/Accounts.java b/Core/src/org/sleuthkit/autopsy/datamodel/accounts/Accounts.java index 901ab4aeb8..bf7ee1caba 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/accounts/Accounts.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/accounts/Accounts.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2019 Basis Technology Corp. + * Copyright 2011-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -57,6 +57,7 @@ import org.openide.nodes.NodeOp; import org.openide.nodes.Sheet; import org.openide.util.NbBundle; import org.openide.util.Utilities; +import org.openide.util.WeakListeners; import org.openide.util.lookup.Lookups; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; @@ -218,8 +219,8 @@ final public class Accounts implements AutopsyVisitableItem { abstract void handleDataAdded(ModuleDataEvent event); @Override - protected void removeNotify() { - super.removeNotify(); + protected void finalize() throws Throwable { + super.finalize(); reviewStatusBus.unregister(ObservingChildren.this); } @@ -415,6 +416,8 @@ final public class Accounts implements AutopsyVisitableItem { } } }; + + private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null); @Subscribe @Override @@ -473,18 +476,18 @@ final public class Accounts implements AutopsyVisitableItem { } @Override - protected void removeNotify() { - IngestManager.getInstance().removeIngestJobEventListener(pcl); - IngestManager.getInstance().removeIngestModuleEventListener(pcl); - Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); - super.removeNotify(); + protected void finalize() throws Throwable { + IngestManager.getInstance().removeIngestJobEventListener(weakPcl); + IngestManager.getInstance().removeIngestModuleEventListener(weakPcl); + Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); + super.finalize(); } @Override protected void addNotify() { - IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); - IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl); - Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl); + IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakPcl); + Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); super.addNotify(); refresh(true); } @@ -550,21 +553,22 @@ final public class Accounts implements AutopsyVisitableItem { } } }; - + + private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null); + @Override protected void addNotify() { - IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); - IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl); - Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); - super.addNotify(); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl); + IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakPcl); + Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); } @Override - protected void removeNotify() { - IngestManager.getInstance().removeIngestJobEventListener(pcl); - IngestManager.getInstance().removeIngestModuleEventListener(pcl); - Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); - super.removeNotify(); + protected void finalize() throws Throwable { + super.finalize(); + IngestManager.getInstance().removeIngestJobEventListener(weakPcl); + IngestManager.getInstance().removeIngestModuleEventListener(weakPcl); + Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); } @Override @@ -727,6 +731,9 @@ final public class Accounts implements AutopsyVisitableItem { } } }; + + private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null); + @Subscribe @Override @@ -739,20 +746,21 @@ final public class Accounts implements AutopsyVisitableItem { void handleDataAdded(ModuleDataEvent event) { refresh(true); } - + @Override protected void addNotify() { - IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); - IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl); - Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl); + IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakPcl); + Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); super.addNotify(); } @Override - protected void removeNotify() { - IngestManager.getInstance().removeIngestJobEventListener(pcl); - IngestManager.getInstance().removeIngestModuleEventListener(pcl); - Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); + protected void finalize() throws Throwable { + super.finalize(); + IngestManager.getInstance().removeIngestJobEventListener(weakPcl); + IngestManager.getInstance().removeIngestModuleEventListener(weakPcl); + Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); super.removeNotify(); } @@ -881,21 +889,23 @@ final public class Accounts implements AutopsyVisitableItem { } } }; + + private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null); @Override protected void addNotify() { - IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); - IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl); - Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl); + IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakPcl); + Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); super.addNotify(); } @Override - protected void removeNotify() { - IngestManager.getInstance().removeIngestJobEventListener(pcl); - IngestManager.getInstance().removeIngestModuleEventListener(pcl); - Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); - super.removeNotify(); + protected void finalize() throws Throwable { + super.finalize(); + IngestManager.getInstance().removeIngestJobEventListener(weakPcl); + IngestManager.getInstance().removeIngestModuleEventListener(weakPcl); + Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); } @Subscribe @@ -1095,21 +1105,23 @@ final public class Accounts implements AutopsyVisitableItem { } } }; + + private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null); @Override protected void addNotify() { - IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, pcl); - IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, pcl); - Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); + IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl); + IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakPcl); + Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); super.addNotify(); } @Override - protected void removeNotify() { - IngestManager.getInstance().removeIngestJobEventListener(pcl); - IngestManager.getInstance().removeIngestModuleEventListener(pcl); - Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl); - super.removeNotify(); + protected void finalize() throws Throwable{ + super.finalize(); + IngestManager.getInstance().removeIngestJobEventListener(weakPcl); + IngestManager.getInstance().removeIngestModuleEventListener(weakPcl); + Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl); } @Subscribe diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/accounts/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/datamodel/accounts/Bundle_ja.properties index 1e28a40973..8f5ee273fb 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/accounts/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/datamodel/accounts/Bundle_ja.properties @@ -1,7 +1,8 @@ +#Thu Jul 01 11:56:41 UTC 2021 Accounts.BINNode.accountsProperty.displayName=\u30a2\u30ab\u30a6\u30f3\u30c8 Accounts.BINNode.bankCityProperty.displayName=\u9280\u884c\u6240\u5728\u5730\u5e02\u753a\u6751\u533a Accounts.BINNode.bankCountryProperty.displayName=\u9280\u884c\u6240\u5728\u56fd -Accounts.BINNode.bankPhoneProperty.displayName=\u9280\u884c\u96fb\u8a71\u756a\u53f7# +Accounts.BINNode.bankPhoneProperty.displayName=\u9280\u884c\u96fb\u8a71\u756a\u53f7\# Accounts.BINNode.bankProperty.displayName=\u9280\u884c Accounts.BINNode.bankURLProperty.displayName=\u9280\u884cURL Accounts.BINNode.binProperty.displayName=\u9280\u884c\u8b58\u5225\u756a\u53f7 @@ -9,19 +10,15 @@ Accounts.BINNode.brandProperty.displayName=\u30d6\u30e9\u30f3\u30c9 Accounts.BINNode.cardTypeProperty.displayName=\u652f\u6255\u3044\u30ab\u30fc\u30c9\u306e\u7a2e\u985e Accounts.BINNode.noDescription=\u8aac\u660e\u306a\u3057 Accounts.BINNode.schemeProperty.displayName=\u30af\u30ec\u30b8\u30c3\u30c8\u30ab\u30fc\u30c9\u30b9\u30ad\u30fc\u30e0 -# {0} - \u5b50\u306e\u6570 Accounts.ByBINNode.displayName=BIN\u5225 ({0}) Accounts.ByBINNode.name=BIN\u5225 -# {0} - \u5b50\u306e\u6570 Accounts.ByFileNode.displayName=\u30d5\u30a1\u30a4\u30eb\u5225 ({0}) Accounts.FileWithCCNNode.accountsProperty.displayName=\u30a2\u30ab\u30a6\u30f3\u30c8 Accounts.FileWithCCNNode.nameProperty.displayName=\u30d5\u30a1\u30a4\u30eb Accounts.FileWithCCNNode.noDescription=\u8aac\u660e\u306a\u3057 Accounts.FileWithCCNNode.statusProperty.displayName=\u30b9\u30c6\u30fc\u30bf\u30b9 -# {0} - \u30ed\u30fc\u30d5\u30a1\u30a4\u30eb\u540d -# {1} - Solr\u30c1\u30e3\u30f3\u30afID Accounts.FileWithCCNNode.unallocatedSpaceFile.displayName={0}_\u30c1\u30e3\u30f3\u30af_{1} -Accounts.RootNode.displayName=\u30a2\u30ab\u30a6\u30f3\u30c8 +Accounts.RootNode.displayName=\u901a\u4fe1\u30a2\u30ab\u30a6\u30f3\u30c8 AccountsRootNode.name=\u30a2\u30ab\u30a6\u30f3\u30c8 ApproveAccountsAction.name=\u30a2\u30ab\u30a6\u30f3\u30c8\u3092\u627f\u8a8d RejectAccountsAction.name=\u30a2\u30ab\u30a6\u30f3\u30c8\u3092\u62d2\u5426 diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/hosts/AssociateNewPersonAction.java b/Core/src/org/sleuthkit/autopsy/datamodel/hosts/AssociateNewPersonAction.java index 2cb89995c6..ff86ea65db 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/hosts/AssociateNewPersonAction.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/hosts/AssociateNewPersonAction.java @@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.datamodel.hosts; import java.awt.Frame; import java.awt.event.ActionEvent; +import java.util.Collections; import java.util.logging.Level; import javax.swing.AbstractAction; import javax.swing.JOptionPane; @@ -66,7 +67,7 @@ public class AssociateNewPersonAction extends AbstractAction { newPersonName = getAddDialogName(); if (StringUtils.isNotBlank(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) { String hostName = this.host == null || this.host.getName() == null ? "" : this.host.getName(); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/hosts/AssociatePersonAction.java b/Core/src/org/sleuthkit/autopsy/datamodel/hosts/AssociatePersonAction.java index 70b31a1ac7..e9ca92791e 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/hosts/AssociatePersonAction.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/hosts/AssociatePersonAction.java @@ -19,6 +19,7 @@ package org.sleuthkit.autopsy.datamodel.hosts; import java.awt.event.ActionEvent; +import java.util.Collections; import java.util.logging.Level; import javax.swing.AbstractAction; import javax.swing.JOptionPane; @@ -65,7 +66,7 @@ public class AssociatePersonAction extends AbstractAction { @Override public void actionPerformed(ActionEvent e) { try { - Case.getCurrentCaseThrows().getSleuthkitCase().getPersonManager().setPerson(host, person); + Case.getCurrentCaseThrows().getSleuthkitCase().getPersonManager().addHostsToPerson(person, Collections.singletonList(host)); } catch (NoCurrentCaseException | TskCoreException ex) { String hostName = this.host == null || this.host.getName() == null ? "" : this.host.getName(); String personName = this.person == null || this.person.getName() == null ? "" : this.person.getName(); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/hosts/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/datamodel/hosts/Bundle.properties-MERGED index cec3355913..53aeebac4e 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/hosts/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/datamodel/hosts/Bundle.properties-MERGED @@ -15,6 +15,14 @@ CTL_OpenHosts=Manage Hosts HostNameValidator_getValidationMessage_onDuplicate=Another host already has the same name. Please choose a different name. HostNameValidator_getValidationMessage_onEmpty=Please provide some text for the host name. HostNameValidator_getValidationMessage_sameAsOriginal=Please provide a new name for this host. +# {0} - hostname +ManageHostsDialog.failureToAdd.txt=Unable to add new host {0} at this time. +# {0} - hostname +ManageHostsDialog.failureToDelete.txt=Unable to delete host {0} at this time. +# {0} - hostname +# {1} - hostId +ManageHostsDialog.failureToEdit.txt=Unable to update host {0} with id: {1} at this time. +ManageHostsDialog.failureToGetHosts.txt=There was an error while fetching hosts for current case. # To change this license header, choose License Headers in Project Properties. # To change this template file, choose Tools | Templates # and open the template in the editor. @@ -30,6 +38,7 @@ AddEditHostDialog.nameLabel.text=Name: AddEditHostDialog.okButton.text=OK AddEditHostDialog.cancelButton.text=Cancel AddEditHostDialog.inputTextField.text=jTextField1 +ManageHostsDialog.seeLog.txt=\ See log for more information. ManageHostsDialog_title_text=Manage Hosts # {0} - sourceHost # {1} - destHost diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/hosts/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/datamodel/hosts/Bundle_ja.properties new file mode 100644 index 0000000000..2798b41330 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/datamodel/hosts/Bundle_ja.properties @@ -0,0 +1,41 @@ +#Mon Jun 14 12:23:19 UTC 2021 +AddEditHostDialog.cancelButton.text=\u30ad\u30e3\u30f3\u30bb\u30eb +AddEditHostDialog.inputTextField.text=jTextField1 +AddEditHostDialog.nameLabel.text=\u540d\u524d\uff1a +AddEditHostDialog.okButton.text=OK +AddEditHostDialog_addHost_title=\u30db\u30b9\u30c8\u3092\u8ffd\u52a0 +AddEditHostDialog_editHost_title=\u30db\u30b9\u30c8\u306e\u7de8\u96c6 +AssociateNewPersonAction_menuTitle=\u65b0\u3057\u3044\u4eba... +AssociateNewPersonAction_onError_description=\u30db\u30b9\u30c8{0}\u3092\u65b0\u3057\u3044\u4eba{1}\u306b\u95a2\u9023\u4ed8\u3051\u308b\u3068\u304d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +AssociateNewPersonAction_onError_title=\u65b0\u3057\u3044\u4eba\u306e\u95a2\u9023\u4ed8\u3051\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +AssociatePersonAction_onError_description=\u30db\u30b9\u30c8{0}\u3068\u500b\u4eba{1}\u306e\u95a2\u9023\u4ed8\u3051\u3067\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +AssociatePersonAction_onError_title=\u30db\u30b9\u30c8\u3068\u500b\u4eba\u306e\u95a2\u9023\u4ed8\u3051\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +AssociatePersonAction_unknownPerson=\u5931\u540d\u6c0f +AssociatePersonsMenuAction_menuTitle=\u4eba\u3068\u95a2\u9023\u4ed8\u3051\u308b +CTL_OpenHosts=\u30db\u30b9\u30c8\u306e\u7ba1\u7406 +HostNameValidator_getValidationMessage_onDuplicate=\u5225\u306e\u30db\u30b9\u30c8\u306f\u3059\u3067\u306b\u540c\u3058\u540d\u524d\u3092\u6301\u3063\u3066\u3044\u307e\u3059\u3002 \u5225\u306e\u540d\u524d\u306b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 +HostNameValidator_getValidationMessage_onEmpty=\u30db\u30b9\u30c8\u540d\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 +HostNameValidator_getValidationMessage_sameAsOriginal=\u3053\u306e\u30db\u30b9\u30c8\u306e\u65b0\u3057\u3044\u540d\u524d\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 +ManageHostsDialog.closeButton.text=\u9589\u3058\u308b +ManageHostsDialog.deleteButton.text=\u524a\u9664 +ManageHostsDialog.editButton.text=\u7de8\u96c6 +ManageHostsDialog.hostDescriptionTextArea.text=\u30db\u30b9\u30c8\u306f\u3001\u8907\u6570\u306e\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u6301\u3064\u53ef\u80fd\u6027\u306e\u3042\u308b\u500b\u3005\u306e\u30c7\u30d0\u30a4\u30b9\u3092\u8868\u3057\u307e\u3059\u3002 +ManageHostsDialog.hostDetailsLabel.text=\u30db\u30b9\u30c8\u306e\u8a73\u7d30 +ManageHostsDialog.hostListLabel.text=\u30db\u30b9\u30c8 +ManageHostsDialog.hostNameLabel.text=\u30db\u30b9\u30c8\u540d\uff1a +ManageHostsDialog.newButton.text=\u65b0 +ManageHostsDialog_title_text=\u30db\u30b9\u30c8\u306e\u7ba1\u7406 +MergeHostAction.confirmText={0}\u3092{1}\u306b\u30de\u30fc\u30b8\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b\uff1f\n\u3053\u308c\u306b\u306fOS\u30a2\u30ab\u30a6\u30f3\u30c8\u306e\u30de\u30fc\u30b8\u304c\u542b\u307e\u308c\u308b\u5834\u5408\u304c\u3042\u308a\u3001\u5143\u306b\u623b\u3059\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093\u3002 +MergeHostAction.confirmTitle=\u78ba\u8a8d +MergeHostAction.errorText=\u30db\u30b9\u30c8\u306e\u30de\u30fc\u30b8\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002\n\u6570\u5206\u5f8c\u306b\u3082\u3046\u4e00\u5ea6\u8a66\u3059\u304b\u3001\u30ed\u30b0\u3067\u8a73\u7d30\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002 +MergeHostAction.errorTitle=\u30db\u30b9\u30c8\u306e\u30de\u30fc\u30b8\u30a8\u30e9\u30fc +MergeHostAction.progressIndicatorName=\u30db\u30b9\u30c8\u306e\u30de\u30fc\u30b8 +MergeHostAction.progressText={0}\u3092{1}\u306b\u30de\u30fc\u30b8\u3057\u3066\u3044\u307e\u3059... +MergeHostAction_onError_description=\u30db\u30b9\u30c8{0}\u3092\u30db\u30b9\u30c8{1}\u306b\u30de\u30fc\u30b8\u3059\u308b\u3068\u304d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +MergeHostAction_onError_title=\u30db\u30b9\u30c8\u306e\u30de\u30fc\u30b8\u30a8\u30e9\u30fc +MergeHostMenuAction_menuTitle=\u4ed6\u306e\u30db\u30b9\u30c8\u306b\u30de\u30fc\u30b8\u3059\u308b +OpenHostsAction_displayName=\u30db\u30b9\u30c8 +RemoveParentPersonAction_menuTitle=\u4eba\u304b\u3089\u524a\u9664\uff08{0}\uff09 +RemoveParentPersonAction_onError_description=\u30db\u30b9\u30c8\u304b\u3089\u4eba\u3092\u524a\u9664\u3059\u308b\u3068\u304d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\uff1a{0}\u3002 +RemoveParentPersonAction_onError_title=\u500b\u4eba\u304b\u3089\u30db\u30b9\u30c8\u3092\u524a\u9664\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +RemoveParentPersonAction_unknownPerson=\u5931\u540d\u6c0f diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/hosts/ManageHostsDialog.java b/Core/src/org/sleuthkit/autopsy/datamodel/hosts/ManageHostsDialog.java index 6cb4220a7a..bbb1f40251 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/hosts/ManageHostsDialog.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/hosts/ManageHostsDialog.java @@ -31,10 +31,12 @@ import java.util.stream.Collectors; import javax.swing.JFrame; import javax.swing.ListModel; import org.apache.commons.collections4.CollectionUtils; +import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.Host; import org.sleuthkit.datamodel.SleuthkitCase; @@ -59,7 +61,7 @@ public class ManageHostsDialog extends javax.swing.JDialog { /** * Main constructor. * - * @param host The host. + * @param host The host. * @param dataSources The data sources that are children of this host. */ HostListItem(Host host, List dataSources) { @@ -152,7 +154,7 @@ public class ManageHostsDialog extends javax.swing.JDialog { /** * @return The currently selected host in the list or null if no host is - * selected. + * selected. */ Host getSelectedHost() { return (hostList.getSelectedValue() == null) ? null : hostList.getSelectedValue().getHost(); @@ -161,6 +163,9 @@ public class ManageHostsDialog extends javax.swing.JDialog { /** * Shows add/edit dialog, and if a value is returned, creates a new Host. */ + @NbBundle.Messages({"# {0} - hostname", + "ManageHostsDialog.failureToAdd.txt=Unable to add new host {0} at this time.", + "ManageHostsDialog.seeLog.txt= See log for more information."}) private void addHost() { String newHostName = getAddEditDialogName(null); if (newHostName != null) { @@ -169,7 +174,8 @@ public class ManageHostsDialog extends javax.swing.JDialog { Host newHost = Case.getCurrentCaseThrows().getSleuthkitCase().getHostManager().newHost(newHostName); selectedId = newHost == null ? null : newHost.getHostId(); } catch (NoCurrentCaseException | TskCoreException e) { - logger.log(Level.WARNING, String.format("Unable to add new host '%s' at this time.", newHostName), e); + logger.log(Level.WARNING, Bundle.ManageHostsDialog_failureToAdd_txt(newHostName), e); + MessageNotifyUtil.Message.warn(Bundle.ManageHostsDialog_failureToAdd_txt(newHostName) + Bundle.ManageHostsDialog_seeLog_txt()); } refresh(); setSelectedHostById(selectedId); @@ -181,12 +187,15 @@ public class ManageHostsDialog extends javax.swing.JDialog { * * @param selectedHost */ + @NbBundle.Messages({"# {0} - hostname", + "ManageHostsDialog.failureToDelete.txt=Unable to delete host {0} at this time."}) private void deleteHost(Host selectedHost) { if (selectedHost != null && selectedHost.getName() != null) { try { Case.getCurrentCaseThrows().getSleuthkitCase().getHostManager().deleteHost(selectedHost.getName()); } catch (NoCurrentCaseException | TskCoreException e) { - logger.log(Level.WARNING, String.format("Unable to delete host '%s' at this time.", selectedHost.getName()), e); + logger.log(Level.WARNING, Bundle.ManageHostsDialog_failureToDelete_txt(selectedHost.getName()), e); + MessageNotifyUtil.Message.error(Bundle.ManageHostsDialog_failureToDelete_txt(selectedHost.getName()) + Bundle.ManageHostsDialog_seeLog_txt()); } refresh(); } @@ -229,6 +238,9 @@ public class ManageHostsDialog extends javax.swing.JDialog { * * @param selectedHost The selected host. */ + @NbBundle.Messages({"# {0} - hostname", + "# {1} - hostId", + "ManageHostsDialog.failureToEdit.txt=Unable to update host {0} with id: {1} at this time."}) private void editHost(Host selectedHost) { if (selectedHost != null) { @@ -237,7 +249,8 @@ public class ManageHostsDialog extends javax.swing.JDialog { try { Case.getCurrentCaseThrows().getSleuthkitCase().getHostManager().updateHostName(selectedHost, newHostName); } catch (NoCurrentCaseException | TskCoreException e) { - logger.log(Level.WARNING, String.format("Unable to update host '%s' with id: %d at this time.", selectedHost.getName(), selectedHost.getHostId()), e); + logger.log(Level.WARNING, Bundle.ManageHostsDialog_failureToEdit_txt(selectedHost.getName(), selectedHost.getHostId()), e); + MessageNotifyUtil.Message.warn(Bundle.ManageHostsDialog_failureToEdit_txt(selectedHost.getName(), selectedHost.getHostId()) + Bundle.ManageHostsDialog_seeLog_txt()); } HostListItem selectedItem = hostList.getSelectedValue(); @@ -254,7 +267,8 @@ public class ManageHostsDialog extends javax.swing.JDialog { * Shows the dialog to add or edit the name of a host. * * @param origValue The original values for the host or null if adding a - * host. + * host. + * * @return The new name for the host or null if operation was cancelled. */ private String getAddEditDialogName(Host origValue) { @@ -305,6 +319,7 @@ public class ManageHostsDialog extends javax.swing.JDialog { * host is null. * * @param h The host. + * * @return The name of the host or empty string. */ private String getNameOrEmpty(Host h) { @@ -315,8 +330,9 @@ public class ManageHostsDialog extends javax.swing.JDialog { * Retrieves the current list of hosts for the case. * * @return The list of hosts to be displayed in the list (sorted - * alphabetically). + * alphabetically). */ + @NbBundle.Messages({"ManageHostsDialog.failureToGetHosts.txt=There was an error while fetching hosts for current case."}) private Map> getHostListData() { Map> hostMapping = new HashMap<>(); try { @@ -339,7 +355,8 @@ public class ManageHostsDialog extends javax.swing.JDialog { } } catch (TskCoreException | NoCurrentCaseException ex) { - logger.log(Level.WARNING, "There was an error while fetching hosts for current case.", ex); + logger.log(Level.WARNING, Bundle.ManageHostsDialog_failureToGetHosts_txt(), ex); + MessageNotifyUtil.Message.warn(Bundle.ManageHostsDialog_failureToGetHosts_txt() + Bundle.ManageHostsDialog_seeLog_txt()); } return hostMapping; diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/hosts/RemoveParentPersonAction.java b/Core/src/org/sleuthkit/autopsy/datamodel/hosts/RemoveParentPersonAction.java index c8ae974bb0..f83d3bd874 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/hosts/RemoveParentPersonAction.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/hosts/RemoveParentPersonAction.java @@ -19,6 +19,7 @@ package org.sleuthkit.autopsy.datamodel.hosts; import java.awt.event.ActionEvent; +import java.util.Collections; import java.util.logging.Level; import javax.swing.AbstractAction; import javax.swing.JOptionPane; @@ -46,6 +47,7 @@ public class RemoveParentPersonAction extends AbstractAction { private static final Logger logger = Logger.getLogger(RemoveParentPersonAction.class.getName()); + private final Person person; private final Host host; /** @@ -59,12 +61,13 @@ public class RemoveParentPersonAction extends AbstractAction { person == null || person.getName() == null ? Bundle.RemoveParentPersonAction_unknownPerson() : person.getName())); this.host = host; + this.person = person; } @Override public void actionPerformed(ActionEvent e) { try { - Case.getCurrentCaseThrows().getSleuthkitCase().getPersonManager().setPerson(host, null); + Case.getCurrentCaseThrows().getSleuthkitCase().getPersonManager().removeHostsFromPerson(person, Collections.singletonList(host)); } catch (NoCurrentCaseException | TskCoreException ex) { 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); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/persons/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/datamodel/persons/Bundle_ja.properties new file mode 100644 index 0000000000..5e808b7db7 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/datamodel/persons/Bundle_ja.properties @@ -0,0 +1,19 @@ +#Mon Jun 14 12:23:19 UTC 2021 +AddEditPersonDialog.cancelButton.text=\u30ad\u30e3\u30f3\u30bb\u30eb +AddEditPersonDialog.cancelButton.text_1=\u30ad\u30e3\u30f3\u30bb\u30eb +AddEditPersonDialog.inputTextField.text_1=jTextField1 +AddEditPersonDialog.nameLabel.text=\u540d\u524d\uff1a +AddEditPersonDialog.nameLabel.text_1=\u540d\u524d\uff1a +AddEditPersonDialog.okButton.text=OK +AddEditPersonDialog.okButton.text_1=OK +AddEditPersonDialog_addPerson_title=\u4eba\u3092\u8ffd\u52a0 +AddEditPersonDialog_editPerson_title=\u4eba\u306e\u7de8\u96c6 +DeletePersonAction_menuTitle=\u4eba\u306e\u524a\u9664 +DeletePersonAction_onError_description=\u4eba\u306e\u524a\u9664\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\uff1a{0}\u3002 +DeletePersonAction_onError_title=\u500b\u4eba\u304b\u3089\u30db\u30b9\u30c8\u3092\u524a\u9664\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +EditPersonAction_menuTitle=\u4eba\u306e\u7de8\u96c6\u3002\u3002\u3002 +EditPersonAction_onError_description=\u4eba\u306e\u7de8\u96c6\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\uff1a{0}\u3002 +EditPersonAction_onError_title=\u4eba\u306e\u7de8\u96c6\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +PersonNameValidator_getValidationMessage_onDuplicate=\u540c\u3058\u540d\u524d\u304c\u65e2\u306b\u5b58\u5728\u3057\u3066\u3044\u307e\u3059\u3002 \u5225\u306e\u540d\u524d\u3092\u9078\u3093\u3067\u304f\u3060\u3055\u3044\u3002 +PersonNameValidator_getValidationMessage_onEmpty=\u540d\u524d\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 +PersonNameValidator_getValidationMessage_sameAsOriginal=\u3053\u306e\u4eba\u306e\u65b0\u3057\u3044\u540d\u524d\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 diff --git a/Core/src/org/sleuthkit/autopsy/datasourceprocessors/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/datasourceprocessors/Bundle_ja.properties index 7086b898db..4290084c96 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourceprocessors/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/datasourceprocessors/Bundle_ja.properties @@ -1,21 +1,18 @@ -# \u3053\u306e\u30e9\u30a4\u30bb\u30f3\u30b9\u30d8\u30c3\u30c0\u30fc\u3092\u5909\u66f4\u3059\u308b\u306b\u306f\u3001[\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u30d7\u30ed\u30d1\u30c6\u30a3] \u3067 [\u30e9\u30a4\u30bb\u30f3\u30b9\u30d8\u30c3\u30c0\u30fc] \u3092\u9078\u629e\u3057\u307e\u3059\u3002 -# \u3053\u306e\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u30d5\u30a1\u30a4\u30eb\u3092\u5909\u66f4\u3059\u308b\u306b\u306f\u3001[\u30c4\u30fc\u30eb | \u30c6\u30f3\u30d7\u30ec\u30fc\u30c8] \u3092\u9078\u629e\u3057\u3001 -# \u30a8\u30c7\u30a3\u30bf\u30fc\u3067\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u3092\u958b\u304d\u307e\u3059\u3002 - +#Mon Jul 12 13:21:59 UTC 2021 AddRawImageTask.for.device=\u30c7\u30d0\u30a4\u30b9\u7528 -AddRawImageTask.image.critical.error.adding=\u8ffd\u52a0\u4e2d\u306e\u91cd\u5927\u306a\u30a8\u30e9\u30fc AddRawImageTask.image.critical.error.adding=\u8ffd\u52a0\u4e2d\u306e\u91cd\u5927\u3067\u306f\u306a\u3044\u30a8\u30e9\u30fc +AddRawImageTask.image.noncritical.error.adding=\u91cd\u5927\u3067\u306f\u306a\u3044\u30a8\u30e9\u30fc\u306e\u8ffd\u52a0 AddRawImageTask.image.notExisting=\u304c\u5b58\u5728\u3057\u307e\u305b\u3093\u3002 AddRawImageTask.noOpenCase.errMsg=\u958b\u3044\u3066\u3044\u308b\u30b1\u30fc\u30b9\u306f\u3042\u308a\u307e\u305b\u3093\u3002 -AddRawImageTask.progress.add.text=\u6b21\u306e\u30ed\u30fc\u30a4\u30e1\u30fc\u30b8\u3092\u8ffd\u52a0\u4e2d\u3067\u3059: -RawDSInputPanel.error.text=\u30de\u30eb\u30c1\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u306e\u30d1\u30b9\u306f "C:" \u30c9\u30e9\u30a4\u30d6\u306b\u3042\u308a\u307e\u3059 -RawDSInputPanel.noOpenCase.errMsg=\u958b\u3044\u3066\u3044\u308b\u30b1\u30fc\u30b9\u306e\u53d6\u5f97\u4e2d\u306b\u4f8b\u5916\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 -RawDSInputPanel.pathLabel.text=\u672a\u4f7f\u7528\u9818\u57df\u306e\u30a4\u30e1\u30fc\u30b8\u30d5\u30a1\u30a4\u30eb\u3092\u53c2\u7167: -RawDSInputPanel.errorLabel.text=\u30a8\u30e9\u30fc\u30e9\u30d9\u30eb +AddRawImageTask.progress.add.text=\u6b21\u306e\u30ed\u30fc\u30a4\u30e1\u30fc\u30b8\u3092\u8ffd\u52a0\u4e2d\u3067\u3059\: RawDSInputPanel.browseButton.text=\u53c2\u7167 -RawDSInputPanel.pathTextField.text= -RawDSInputPanel.jBreakFileUpLabel.text=\u6b21\u307e\u3067\u30a4\u30e1\u30fc\u30b8\u3092\u7d30\u5206\u5316: -RawDSInputPanel.jNoBreakupRadioButton.text=\u7d30\u5206\u5316\u3057\u306a\u3044 +RawDSInputPanel.error.text=\u30de\u30eb\u30c1\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u306e\u30d1\u30b9\u306f "C\:" \u30c9\u30e9\u30a4\u30d6\u306b\u3042\u308a\u307e\u3059 +RawDSInputPanel.errorLabel.text=\u30a8\u30e9\u30fc\u30e9\u30d9\u30eb RawDSInputPanel.j2GBBreakupRadioButton.text=2GB\u30c1\u30e3\u30f3\u30af -RawDSInputPanel.timeZoneLabel.text=\u5165\u529b\u30bf\u30a4\u30e0\u30be\u30fc\u30f3\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044: +RawDSInputPanel.jBreakFileUpLabel.text=\u6b21\u307e\u3067\u30a4\u30e1\u30fc\u30b8\u3092\u7d30\u5206\u5316\: +RawDSInputPanel.jNoBreakupRadioButton.text=\u7d30\u5206\u5316\u3057\u306a\u3044 +RawDSInputPanel.noOpenCase.errMsg=\u958b\u3044\u3066\u3044\u308b\u30b1\u30fc\u30b9\u306e\u53d6\u5f97\u4e2d\u306b\u4f8b\u5916\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +RawDSInputPanel.pathLabel.text=\u672a\u4f7f\u7528\u9818\u57df\u306e\u30a4\u30e1\u30fc\u30b8\u30d5\u30a1\u30a4\u30eb\u3092\u53c2\u7167\: +RawDSInputPanel.pathTextField.text= +RawDSInputPanel.timeZoneLabel.text=\u5165\u529b\u30bf\u30a4\u30e0\u30be\u30fc\u30f3\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\: RawDSProcessor.dataSourceType=\u672a\u4f7f\u7528\u9818\u57df\u306e\u30a4\u30e1\u30fc\u30b8\u30d5\u30a1\u30a4\u30eb diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/Bundle_ja.properties index 5873c044cc..a8185f73ff 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/Bundle_ja.properties @@ -1,4 +1,3 @@ -#Fri Feb 12 16:56:28 UTC 2021 +#Mon Jun 14 12:23:19 UTC 2021 DataSourceUserActivitySummary_getRecentAccounts_calllogMessage=\u901a\u8a71\u8a18\u9332 DataSourceUserActivitySummary_getRecentAccounts_emailMessage=\u30e1\u30fc\u30eb\u30e1\u30c3\u30bb\u30fc\u30b8 -IngestModuleCheckUtil_recentActivityModuleName=\u6700\u8fd1\u306e\u6d3b\u52d5 diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle_ja.properties index 2b4d2c7dc2..053ceb7450 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/Bundle_ja.properties @@ -1,11 +1,13 @@ -#Fri Feb 12 16:56:28 UTC 2021 +#Mon Jun 14 12:23:19 UTC 2021 AnalysisPanel.hashsetHitsLabel.text=\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u30d2\u30c3\u30c8 AnalysisPanel.interestingItemLabel.text=\u8208\u5473\u6df1\u3044\u30a2\u30a4\u30c6\u30e0\u306e\u30d2\u30c3\u30c8 AnalysisPanel.keywordHitsLabel.text=\u30ad\u30fc\u30ef\u30fc\u30c9\u30d2\u30c3\u30c8 AnalysisPanel_countColumn_title=\u30ab\u30a6\u30f3\u30c8 +AnalysisPanel_hashsetHits_tabName=\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u30fb\u30d2\u30c3\u30c8 +AnalysisPanel_interestingItemHits_tabName=\u8208\u5473\u6df1\u3044\u30a2\u30a4\u30c6\u30e0\u306e\u30d2\u30c3\u30c8 AnalysisPanel_keyColumn_title=\u540d\u524d +AnalysisPanel_keywordHits_tabName=\u30ad\u30fc\u30ef\u30fc\u30c9\u30fb\u30d2\u30c3\u30c8 AnalysisPanel_keywordSearchModuleName=\u30ad\u30fc\u30ef\u30fc\u30c9\u691c\u7d22 -BaseDataSourceSummaryPanel_defaultNotIngestMessage={0}\u53d6\u8fbc\u307f\u30e2\u30b8\u30e5\u30fc\u30eb\u306f\u3053\u306e\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3067\u306f\u5b9f\u884c\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002 BaseDataSourceSummaryPanel_goToArtifact=\u30bd\u30fc\u30b9\u7d50\u679c\u306e\u8868\u793a BaseDataSourceSummaryPanel_goToFile=\u30d5\u30a9\u30eb\u30c0\u30fc\u5185\u306e\u30bd\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb\u3092\u8868\u793a CTL_DataSourceSummaryAction=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u306e\u6982\u8981 @@ -30,7 +32,21 @@ ContainerPanel.units.kilobytes=\ kB ContainerPanel.units.megabytes=\ MB ContainerPanel.units.petabytes=\ PB ContainerPanel.units.terabytes=\ TB +ContainerPanel_export_acquisitionDetails=\u8aad\u8fbc\u306e\u8a73\u7d30\uff1a +ContainerPanel_export_deviceId=\u30c7\u30d0\u30a4\u30b9ID\uff1a +ContainerPanel_export_displayName=\u8868\u793a\u540d\uff1a +ContainerPanel_export_filePaths=\u30d5\u30a1\u30a4\u30eb\u30d1\u30b9\uff1a +ContainerPanel_export_imageType=\u753b\u50cf\u30bf\u30a4\u30d7\uff1a +ContainerPanel_export_md5=MD5\: +ContainerPanel_export_originalName=\u540d\u524d\uff1a +ContainerPanel_export_sectorSize=\u30bb\u30af\u30bf\u30fc\u30b5\u30a4\u30ba\uff1a +ContainerPanel_export_sha1=SHA1\: +ContainerPanel_export_sha256=SHA256\: +ContainerPanel_export_size=\u30b5\u30a4\u30ba\uff1a +ContainerPanel_export_timeZone=\u30bf\u30a4\u30e0\u30be\u30fc\u30f3\uff1a +ContainerPanel_export_unallocatedSize=\u672a\u5272\u308a\u5f53\u3066\u9818\u57df\uff1a ContainerPanel_setFieldsForNonImageDataSource_na=\u8a72\u5f53\u306a\u3057 +ContainerPanel_tabName=\u30b3\u30f3\u30c6\u30ca DataSourceSummaryCountsPanel.FilesByCategoryTableModel.all.row=\u3059\u3079\u3066 DataSourceSummaryCountsPanel.FilesByCategoryTableModel.allocated.row=\u5272\u308a\u5f53\u3066\u6e08\u307f DataSourceSummaryCountsPanel.FilesByCategoryTableModel.count.header=\u30ab\u30a6\u30f3\u30c8 @@ -63,6 +79,7 @@ DataSourceSummaryNode.viewDataSourceAction.text=\u30c7\u30fc\u30bf\u30bd\u30fc\u DataSourceSummaryTabbedPane.noDataSourceLabel.text=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u304c\u9078\u629e\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002 DataSourceSummaryTabbedPane_analysisTab_title=\u5206\u6790 DataSourceSummaryTabbedPane_detailsTab_title=\u30b3\u30f3\u30c6\u30ca +DataSourceSummaryTabbedPane_exportTab_title=\u30a8\u30af\u30b9\u30dd\u30fc\u30c8 DataSourceSummaryTabbedPane_geolocationTab_title=\u30b8\u30aa\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3 DataSourceSummaryTabbedPane_ingestHistoryTab_title=\u53d6\u8fbc\u5c65\u6b74 DataSourceSummaryTabbedPane_pastCasesTab_title=\u904e\u53bb\u306e\u30b1\u30fc\u30b9 @@ -70,21 +87,46 @@ DataSourceSummaryTabbedPane_recentFileTab_title=\u6700\u8fd1\u4f7f\u7528\u3057\u DataSourceSummaryTabbedPane_timelineTab_title=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3 DataSourceSummaryTabbedPane_typesTab_title=\u30bf\u30a4\u30d7 DataSourceSummaryTabbedPane_userActivityTab_title=\u30e6\u30fc\u30b6\u30fc\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3 +ExcelExportAction_exportToXLSX_beginExport=\u30a8\u30af\u30b9\u30dd\u30fc\u30c8\u3092\u958b\u59cb\u3057\u3066\u3044\u307e\u3059... +ExcelExportAction_exportToXLSX_gatheringTabData={0}\u30bf\u30d6\u306e\u30c7\u30fc\u30bf\u3092\u53d6\u5f97\u3057\u3066\u3044\u307e\u3059... +ExcelExportAction_exportToXLSX_writingToFile=\u30d5\u30a1\u30a4\u30eb\u3078\u306e\u66f8\u51fa\u3057\u4e2d... +ExcelExportAction_getXLSXPath_directory=DataSourceSummary +ExcelExportAction_moduleName=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u306e\u6982\u8981 +ExcelExportAction_runXLSXExport_errorMessage=\u30a8\u30af\u30b9\u30dd\u30fc\u30c8\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +ExcelExportAction_runXLSXExport_errorTitle=\u30a8\u30af\u30b9\u30dd\u30fc\u30c8\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +ExcelExportAction_runXLSXExport_progressCancelActionTitle=\u30ad\u30e3\u30f3\u30bb\u30eb... +ExcelExportAction_runXLSXExport_progressCancelTitle=\u30ad\u30e3\u30f3\u30bb\u30eb +ExcelExportAction_runXLSXExport_progressTitle={0}\u3092XLSX\u306b\u30a8\u30af\u30b9\u30dd\u30fc\u30c8\u3057\u3066\u3044\u307e\u3059 +ExcelExportDialog.okButton.text=OK +ExcelExportDialog.titleLabel.text=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u306e\u6982\u8981\u306f\u6b21\u306e\u5834\u6240\u306b\u30a8\u30af\u30b9\u30dd\u30fc\u30c8\u3055\u308c\u307e\u3057\u305f\uff1a +ExcelExportDialog_title=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u306e\u6982\u8981\u304c\u30a8\u30af\u30b9\u30dd\u30fc\u30c8\u3055\u308c\u307e\u3057\u305f +ExportPanel.xlsxExportButton.text=\u8981\u7d04\u30c7\u30fc\u30bf\u306e\u30a8\u30af\u30b9\u30dd\u30fc\u30c8 +ExportPanel.xlsxExportMessage.text=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u30b5\u30de\u30ea\u30fc\u304b\u3089Excel\u30d5\u30a1\u30a4\u30eb\u306b\u30c7\u30fc\u30bf\u3092\u30a8\u30af\u30b9\u30dd\u30fc\u30c8\u3057\u307e\u3059\u3002 GeolocationPanel.commonViewInGeolocationBtn.text=\u5730\u56f3\u3067\u898b\u308b -GeolocationPanel.mostCommonLabel.text=\u30b8\u30aa\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3\u304b\u3089\u306e\u6700\u3082\u4e00\u822c\u7684\u306a\u90fd\u5e02 -GeolocationPanel.mostRecentLabel.text=\u30b8\u30aa\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u304b\u3089\u306e\u6700\u8fd1\u306e\u90fd\u5e02 +GeolocationPanel.mostCommonLabel.text=\u30b8\u30aa\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u7d50\u679c\u304b\u3089\u6700\u3082\u4e00\u822c\u7684\u306a\u90fd\u5e02 +GeolocationPanel.mostRecentLabel.text=\u30b8\u30aa\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u7d50\u679c\u3067\u306e\u6700\u8fd1\u306e\u90fd\u5e02 GeolocationPanel.recentViewInGeolocationBtn.text=\u5730\u56f3\u3067\u898b\u308b GeolocationPanel.withinDistanceLabel.text=\u90fd\u5e02\u304b\u3089150km\u4ee5\u4e0a\u96e2\u308c\u305f\u5834\u6240\u306f\u3001\u300c\u4e0d\u660e\u300d\u3068\u3057\u3066\u8868\u793a\u3055\u308c\u307e\u3059 GeolocationPanel.withinDistanceLabel1.text=\u90fd\u5e02\u304b\u3089150km\u4ee5\u4e0a\u96e2\u308c\u305f\u5834\u6240\u306f\u3001\u300c\u4e0d\u660e\u300d\u3068\u3057\u3066\u8868\u793a\u3055\u308c\u307e\u3059 GeolocationPanel_cityColumn_title=\u6700\u3082\u8fd1\u3044\u90fd\u5e02 GeolocationPanel_countColumn_title=\u30ab\u30a6\u30f3\u30c8 +GeolocationPanel_mostCommon_tabName=\u6700\u3082\u4e00\u822c\u7684\u306a\u90fd\u5e02 +GeolocationPanel_mostRecent_tabName=\u6700\u8fd1\u4f7f\u7528\u3055\u308c\u305f\u90fd\u5e02 GeolocationPanel_onNoCrIngest_message=GPX\u30d1\u30fc\u30b5\u30fc\u304c\u5b9f\u884c\u3055\u308c\u306a\u304b\u3063\u305f\u305f\u3081\u3001\u7d50\u679c\u306f\u8868\u793a\u3055\u308c\u307e\u305b\u3093\u3002 GeolocationPanel_unknownRow_title=\u4e0d\u660e +IngestJobExcelExport_endTimeColumn=\u7d42\u4e86\u6642\u9593 +IngestJobExcelExport_ingestStatusTimeColumn=\u53d6\u8fbc\u307f\u72b6\u6cc1 +IngestJobExcelExport_moduleNameTimeColumn=\u30e2\u30b8\u30e5\u30fc\u30eb\u540d +IngestJobExcelExport_sheetName=\u53d6\u8fbc\u307f\u6b74\u53f2 +IngestJobExcelExport_startTimeColumn=\u30b9\u30bf\u30fc\u30c8\u6642\u9593 +IngestJobExcelExport_versionColumn=\u30e2\u30b8\u30e5\u30fc\u30eb\u30d0\u30fc\u30b8\u30e7\u30f3 PastCasesPanel.notableFileLabel.text=\u300c\u6ce8\u76ee\u300d\u3068\u30bf\u30b0\u4ed8\u3051\u3055\u308c\u305f\u4e00\u822c\u7684\u306a\u30b1\u30fc\u30b9 PastCasesPanel.sameIdLabel.text=\u540c\u3058\u30c7\u30d0\u30a4\u30b9ID\u3092\u6301\u3064\u904e\u53bb\u306e\u30b1\u30fc\u30b9 PastCasesPanel_caseColumn_title=\u30b1\u30fc\u30b9 PastCasesPanel_countColumn_title=\u30ab\u30a6\u30f3\u30c8 +PastCasesPanel_notableFileTable_tabName=\u4e00\u822c\u7684\u306b\u6ce8\u76ee\u3059\u3079\u304d\u4e8b\u4f8b PastCasesPanel_onNoCrIngest_message=\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u5b9f\u884c\u3055\u308c\u306a\u304b\u3063\u305f\u305f\u3081\u3001\u7d50\u679c\u306f\u8868\u793a\u3055\u308c\u307e\u305b\u3093\u3002 +PastCasesPanel_sameIdsTable_tabName=\u540c\u3058\u30c7\u30d0\u30a4\u30b9\u3067\u306e\u904e\u53bb\u306e\u30b1\u30fc\u30b9 RecentFilePanel_col_header_domain=\u30c9\u30e1\u30a4\u30f3 RecentFilePanel_col_header_path=\u30d1\u30b9 RecentFilePanel_col_header_sender=\u9001\u4fe1\u8005 @@ -96,21 +138,31 @@ RecentFilesPanel.openDocsLabel.text=\u6700\u8fd1\u958b\u3044\u305f\u30c9\u30ad\u RecentFilesPanel.rightClickForMoreOptions1.text=\u305d\u306e\u4ed6\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u306b\u3064\u3044\u3066\u306f\u3001\u884c\u3092\u53f3\u30af\u30ea\u30c3\u30af\u3057\u3066\u304f\u3060\u3055\u3044 RecentFilesPanel.rightClickForMoreOptions2.text=\u305d\u306e\u4ed6\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u306b\u3064\u3044\u3066\u306f\u3001\u884c\u3092\u53f3\u30af\u30ea\u30c3\u30af\u3057\u3066\u304f\u3060\u3055\u3044 RecentFilesPanel.rightClickForMoreOptions3.text=\u305d\u306e\u4ed6\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u306b\u3064\u3044\u3066\u306f\u3001\u884c\u3092\u53f3\u30af\u30ea\u30c3\u30af\u3057\u3066\u304f\u3060\u3055\u3044 +RecentFilesPanel_attachmentsTable_tabName=\u6700\u8fd1\u306e\u6dfb\u4ed8\u30d5\u30a1\u30a4\u30eb RecentFilesPanel_col_head_date=\u65e5\u4ed8 +RecentFilesPanel_docsTable_tabName=\u6700\u8fd1\u958b\u3044\u305f\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8 +RecentFilesPanel_downloadsTable_tabName=\u6700\u8fd1\u306e\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9 SizeRepresentationUtil_units_bytes=\u30d0\u30a4\u30c8 -SizeRepresentationUtil_units_gigabytes=\ GB -SizeRepresentationUtil_units_kilobytes=\ kB -SizeRepresentationUtil_units_megabytes=\ MB -SizeRepresentationUtil_units_petabytes=\ PB -SizeRepresentationUtil_units_terabytes=\ TB +SizeRepresentationUtil_units_gigabytes=GB +SizeRepresentationUtil_units_kilobytes=KB +SizeRepresentationUtil_units_megabytes=MB +SizeRepresentationUtil_units_petabytes=PB +SizeRepresentationUtil_units_terabytes=TB TimelinePanel.activityRangeLabel.text=\u6d3b\u52d5\u7bc4\u56f2 TimelinePanel.viewInTimelineBtn.text=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u3067\u8868\u793a TimelinePanel_earliestLabel_title=\u6700\u53e4 +TimelinePanel_getExports_activityRange=\u6d3b\u52d5\u7bc4\u56f2 +TimelinePanel_getExports_chartName=\u904e\u53bb30\u65e5\u9593 +TimelinePanel_getExports_dateColumnHeader=\u65e5\u4ed8 +TimelinePanel_getExports_earliest=\u6700\u53e4\uff1a +TimelinePanel_getExports_latest=\u6700\u8fd1\uff1a +TimelinePanel_getExports_sheetName=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3 TimelinePanel_latestLabel_title=\u6700\u65b0 TimlinePanel_last30DaysChart_artifactEvts_title=\u7d50\u679c\u30a4\u30d9\u30f3\u30c8 TimlinePanel_last30DaysChart_fileEvts_title=\u30d5\u30a1\u30a4\u30eb\u30a4\u30d9\u30f3\u30c8 TimlinePanel_last30DaysChart_title=\u904e\u53bb30\u65e5\u9593 TypesPanel_artifactsTypesPieChart_title=\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u30bf\u30a4\u30d7 +TypesPanel_excelTabName=\u30bf\u30a4\u30d7 TypesPanel_fileMimeTypesChart_audio_title=\u30aa\u30fc\u30c7\u30a3\u30aa TypesPanel_fileMimeTypesChart_documents_title=\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8 TypesPanel_fileMimeTypesChart_executables_title=\u5b9f\u884c\u53ef\u80fd\u30d5\u30a1\u30a4\u30eb @@ -119,6 +171,7 @@ TypesPanel_fileMimeTypesChart_notAnalyzed_title=\u5206\u6790\u3055\u308c\u3066\u TypesPanel_fileMimeTypesChart_other_title=\u305d\u306e\u4ed6 TypesPanel_fileMimeTypesChart_title=\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7 TypesPanel_fileMimeTypesChart_unknown_title=\u4e0d\u660e +TypesPanel_fileMimeTypesChart_valueLabel=\u30ab\u30a6\u30f3\u30c8 TypesPanel_fileMimeTypesChart_videos_title=\u30d3\u30c7\u30aa TypesPanel_filesByCategoryTable_allocatedRow_title=\u5272\u308a\u5f53\u3066\u3089\u308c\u305f\u30d5\u30a1\u30a4\u30eb TypesPanel_filesByCategoryTable_directoryRow_title=\u30d5\u30a9\u30eb\u30c0 @@ -139,18 +192,23 @@ UserActivityPanel.topDevicesAttachedLabel.text=\u6700\u8fd1\u63a5\u7d9a\u3055\u3 UserActivityPanel.topWebSearchLabel.text=\u6700\u8fd1\u306eWeb\u691c\u7d22 UserActivityPanel_TopAccountTableModel_accountType_header=\u30a2\u30ab\u30f3\u30c8\u30bf\u30a4\u30d7 UserActivityPanel_TopAccountTableModel_lastAccess_header=\u6700\u7d42\u30a2\u30af\u30bb\u30b9\u65e5 +UserActivityPanel_TopAccountTableModel_tabName=\u6700\u8fd1\u4f7f\u7528\u3055\u308c\u305f\u30a2\u30ab\u30a6\u30f3\u30c8\u30bf\u30a4\u30d7 UserActivityPanel_TopDeviceAttachedTableModel_dateAccessed_header=\u6700\u7d42\u30a2\u30af\u30bb\u30b9\u65e5 UserActivityPanel_TopDeviceAttachedTableModel_deviceId_header=\u30c7\u30d0\u30a4\u30b9ID UserActivityPanel_TopDeviceAttachedTableModel_makeModel_header=\u30e1\u30fc\u30ab\u30fc\u3068\u30e2\u30c7\u30eb +UserActivityPanel_TopDeviceAttachedTableModel_tabName=\u6700\u8fd1\u63a5\u7d9a\u3055\u308c\u305f\u30c7\u30d0\u30a4\u30b9 UserActivityPanel_TopDomainsTableModel_count_header=\u53c2\u89b3 UserActivityPanel_TopDomainsTableModel_domain_header=\u30c9\u30e1\u30a4\u30f3 UserActivityPanel_TopDomainsTableModel_lastAccess_header=\u6700\u7d42\u30a2\u30af\u30bb\u30b9\u65e5 +UserActivityPanel_TopDomainsTableModel_tabName=\u6700\u8fd1\u306e\u30c9\u30e1\u30a4\u30f3 UserActivityPanel_TopProgramsTableModel_count_header=\u5b9f\u884c\u6642\u9593 UserActivityPanel_TopProgramsTableModel_folder_header=\u30d5\u30a9\u30eb\u30c0 UserActivityPanel_TopProgramsTableModel_lastrun_header=\u524d\u56de\u5b9f\u884c UserActivityPanel_TopProgramsTableModel_name_header=\u30d7\u30ed\u30b0\u30e9\u30e0 +UserActivityPanel_TopProgramsTableModel_tabName=\u6700\u8fd1\u306e\u30d7\u30ed\u30b0\u30e9\u30e0 UserActivityPanel_TopWebSearchTableModel_dateAccessed_header=\u30a2\u30af\u30bb\u30b9\u65e5 UserActivityPanel_TopWebSearchTableModel_searchString_header=\u691c\u7d22\u6587\u5b57\u5217 +UserActivityPanel_TopWebSearchTableModel_tabName=\u6700\u8fd1\u306eWeb\u691c\u7d22 UserActivityPanel_TopWebSearchTableModel_translatedResult_header=\u7ffb\u8a33\u6e08\u307f UserActivityPanel_noDataExists=\u901a\u4fe1\u30c7\u30fc\u30bf\u304c\u3042\u308a\u307e\u305b\u3093 UserActivityPanel_tab_title=\u30e6\u30fc\u30b6\u30fc\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3 diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceBrowser.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceBrowser.java index 98522e5071..51433534e4 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceBrowser.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceBrowser.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2019 Basis Technology Corp. + * Copyright 2019-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.datasourcesummary.ui; +import java.awt.Cursor; import org.sleuthkit.autopsy.datasourcesummary.uiutils.RightAlignedTableCellRenderer; import java.awt.EventQueue; import java.beans.PropertyVetoException; @@ -39,6 +40,7 @@ import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.datasourcesummary.ui.DataSourceSummaryNode.DataSourceSummaryEntryNode; import static javax.swing.SwingConstants.RIGHT; import javax.swing.SwingUtilities; +import javax.swing.SwingWorker; import javax.swing.table.TableColumn; import org.sleuthkit.autopsy.datasourcesummary.datamodel.CaseDataSourcesSummary; import org.sleuthkit.datamodel.DataSource; @@ -63,11 +65,12 @@ final class DataSourceBrowser extends javax.swing.JPanel implements ExplorerMana private final ExplorerManager explorerManager; private final List dataSourceSummaryList; private final RightAlignedTableCellRenderer rightAlignedRenderer = new RightAlignedTableCellRenderer(); + private SwingWorker rootNodeWorker = null; /** * Creates new form DataSourceBrowser */ - DataSourceBrowser(Map usageMap, Map fileCountsMap) { + DataSourceBrowser() { initComponents(); rightAlignedRenderer.setHorizontalAlignment(RIGHT); explorerManager = new ExplorerManager(); @@ -80,13 +83,10 @@ final class DataSourceBrowser extends javax.swing.JPanel implements ExplorerMana Bundle.DataSourceSummaryNode_column_results_header(), Bundle.DataSourceSummaryNode_column_results_header(), Bundle.DataSourceSummaryNode_column_tags_header(), Bundle.DataSourceSummaryNode_column_tags_header()); outline = outlineView.getOutline(); - outline.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - - dataSourceSummaryList = getDataSourceSummaryList(usageMap, fileCountsMap); + dataSourceSummaryList = new ArrayList<>(); outline.setRootVisible(false); add(outlineView, java.awt.BorderLayout.CENTER); - explorerManager.setRootContext(new DataSourceSummaryNode(dataSourceSummaryList)); ((DefaultOutlineModel) outline.getOutlineModel()).setNodesColumnLabel(Bundle.DataSourceSummaryNode_column_dataSourceName_header()); for (TableColumn column : Collections.list(outline.getColumnModel().getColumns())) { if (column.getHeaderValue().toString().equals(Bundle.DataSourceSummaryNode_column_files_header()) @@ -248,6 +248,52 @@ final class DataSourceBrowser extends javax.swing.JPanel implements ExplorerMana return explorerManager; } + /** + * Populate the data source browser with an updated list of the data sources + * and information about them. + * + * @param dsSummaryDialog The dialog which contains this data source + * browser panel. + * @param selectedDataSourceId The object id for the data source which + * should be selected. + */ + void populateBrowser(DataSourceSummaryDialog dsSummaryDialog, Long selectedDataSourceId) { + dsSummaryDialog.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + if (rootNodeWorker != null && !rootNodeWorker.isDone()) { + rootNodeWorker.cancel(true); + } + + dataSourceSummaryList.clear(); + rootNodeWorker = new SwingWorker() { + @Override + protected Void doInBackground() throws Exception { + Map usageMap = CaseDataSourcesSummary.getDataSourceTypes(); + Map fileCountsMap = CaseDataSourcesSummary.getCountsOfFiles(); + dataSourceSummaryList.addAll(getDataSourceSummaryList(usageMap, fileCountsMap)); + return null; + } + + @Override + protected void done() { + explorerManager.setRootContext(new DataSourceSummaryNode(dataSourceSummaryList)); + selectDataSource(selectedDataSourceId); + addObserver(dsSummaryDialog); + dsSummaryDialog.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } + }; + rootNodeWorker.execute(); + } + + /** + * Cancel the worker that updates the data source summary list and updates + * the data source summary browser. + */ + void cancel() { + if (rootNodeWorker != null && !rootNodeWorker.isDone()) { + rootNodeWorker.cancel(true); + } + } + // Variables declaration - do not modify//GEN-BEGIN:variables // End of variables declaration//GEN-END:variables } diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryDialog.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryDialog.java index 97ca3cc6f2..2dccdf1bd9 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryDialog.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryDialog.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2019 Basis Technology Corp. + * Copyright 2019-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,14 +22,12 @@ import java.awt.Frame; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.EnumSet; -import java.util.Map; import java.util.Observable; import java.util.Observer; import java.util.Set; import javax.swing.WindowConstants; import javax.swing.event.ListSelectionEvent; import org.openide.util.NbBundle.Messages; -import org.sleuthkit.autopsy.datasourcesummary.datamodel.CaseDataSourcesSummary; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.events.DataSourceAnalysisCompletedEvent; import org.sleuthkit.autopsy.ingest.events.DataSourceAnalysisCompletedEvent.Reason; @@ -57,9 +55,8 @@ final class DataSourceSummaryDialog extends javax.swing.JDialog implements Obser }) DataSourceSummaryDialog(Frame owner) { super(owner, Bundle.DataSourceSummaryDialog_window_title(), true); - Map usageMap = CaseDataSourcesSummary.getDataSourceTypes(); - Map fileCountsMap = CaseDataSourcesSummary.getCountsOfFiles(); - dataSourcesPanel = new DataSourceBrowser(usageMap, fileCountsMap); + + dataSourcesPanel = new DataSourceBrowser(); dataSourceSummaryTabbedPane = new DataSourceSummaryTabbedPane(); dataSourceSummaryTabbedPane.setParentCloseListener(() -> DataSourceSummaryDialog.this.dispose()); initComponents(); @@ -99,13 +96,6 @@ final class DataSourceSummaryDialog extends javax.swing.JDialog implements Obser super.dispose(); } - /** - * Make this dialog an observer of the DataSourcesPanel. - */ - void enableObserver() { - dataSourcesPanel.addObserver(this); - } - @Override public void update(Observable o, Object arg) { this.dispose(); @@ -162,22 +152,21 @@ final class DataSourceSummaryDialog extends javax.swing.JDialog implements Obser }// //GEN-END:initComponents private void closeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_closeButtonActionPerformed + dataSourcesPanel.cancel(); this.dispose(); }//GEN-LAST:event_closeButtonActionPerformed - /** - * Select the data source with the specicied data source id. If no data - * source matches the dataSourceID it will select the first datasource. - * - * @param dataSourceID the ID of the datasource to select, null will cause - * the first datasource to be selected - */ - void selectDataSource(Long dataSourceId) { - dataSourcesPanel.selectDataSource(dataSourceId); - } - // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton closeButton; private javax.swing.JSplitPane dataSourceSummarySplitPane; // End of variables declaration//GEN-END:variables + + /** + * Populate the data source browser with the specified data source selected. + * + * @param selectedDataSource The data source which should be selected in the data source browser. + */ + void populatePanel(Long selectedDataSource) { + dataSourcesPanel.populateBrowser(this, selectedDataSource); + } } diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryNode.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryNode.java index a4c48e7adf..4aa3cf1be3 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryNode.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/DataSourceSummaryNode.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2019 Basis Technology Corp. + * Copyright 2019-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -30,7 +30,6 @@ import org.openide.nodes.Children; import org.openide.nodes.Node; import org.openide.nodes.Sheet; import org.openide.util.NbBundle.Messages; -import org.sleuthkit.autopsy.datasourcesummary.ui.Bundle; import org.sleuthkit.autopsy.datamodel.NodeProperty; import org.sleuthkit.autopsy.directorytree.ViewContextAction; import org.sleuthkit.datamodel.DataSource; @@ -59,7 +58,7 @@ final class DataSourceSummaryNode extends AbstractNode { * DataSources which are this nodes children */ DataSourceSummaryNode(List dataSourceList) { - super(Children.create(new DataSourceSummaryChildren(dataSourceList), false)); + super(Children.create(new DataSourceSummaryChildren(dataSourceList), true)); } /** diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ViewSummaryInformationAction.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ViewSummaryInformationAction.java index c62cb8c214..2dda445ae1 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ViewSummaryInformationAction.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/ViewSummaryInformationAction.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2019 Basis Technology Corp. + * Copyright 2019-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,7 +24,6 @@ import javax.swing.AbstractAction; import javax.swing.SwingUtilities; import org.openide.util.NbBundle.Messages; import org.openide.windows.WindowManager; -import org.sleuthkit.autopsy.datasourcesummary.ui.Bundle; /** * ViewSummaryInformationAction action for opening a Data Sources Summary Dialog @@ -40,8 +39,8 @@ public final class ViewSummaryInformationAction extends AbstractAction { * Create a ViewSummaryInformationAction for the selected datasource. * * @param selectedDataSource - the data source which is currently selected - and will be selected initially when the - DataSourceSummaryDialog opens. + * and will be selected initially when the + * DataSourceSummaryDialog opens. */ @Messages({"ViewSummaryInformationAction.name.text=View Summary Information"}) public ViewSummaryInformationAction(Long selectedDataSource) { @@ -54,10 +53,7 @@ public final class ViewSummaryInformationAction extends AbstractAction { SwingUtilities.invokeLater(() -> { Frame mainWindow = WindowManager.getDefault().getMainWindow(); dataSourceSummaryDialog = new DataSourceSummaryDialog(mainWindow); - //allow dialog to be closed when actions performed - dataSourceSummaryDialog.enableObserver(); - //select the specifed data source - dataSourceSummaryDialog.selectDataSource(selectDataSource); + dataSourceSummaryDialog.populatePanel(selectDataSource); dataSourceSummaryDialog.setResizable(true); dataSourceSummaryDialog.setLocationRelativeTo(mainWindow); dataSourceSummaryDialog.setVisible(true); diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/BaseMessageOverlay.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/BaseMessageOverlay.java index 8e90945eb7..597cd01682 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/BaseMessageOverlay.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/BaseMessageOverlay.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2019 Basis Technology Corp. + * Copyright 2019-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -26,7 +26,6 @@ import javax.swing.JLabel; * painting a JLabel using a java.awt.Graphics object. */ public class BaseMessageOverlay { - private final JLabel label; private boolean visible = false; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/Bundle_ja.properties index 25a7ef2e76..1807aad546 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/Bundle_ja.properties @@ -1,6 +1,7 @@ -#Fri Feb 12 16:56:28 UTC 2021 +#Mon Jun 14 12:23:19 UTC 2021 AbstractLoadableComponent_errorMessage_defaultText=\u7d50\u679c\u306e\u8aad\u8fbc\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 AbstractLoadableComponent_loadingMessage_defaultText=\u7d50\u679c\u3092\u8aad\u8fbc\u4e2d... AbstractLoadableComponent_noDataExists_defaultText=\u30c7\u30fc\u30bf\u306f\u5b58\u5728\u3057\u307e\u305b\u3093\u3002 +ExcelExport_writeExcel_noSheetName=\u30b7\u30fc\u30c8{0} IngestRunningLabel_defaultMessage=\u53d6\u8fbc\u307f\u5b9f\u884c\u4e2d\u3067\u3059\u3002 PieChartPanel_noDataLabel=\u30c7\u30fc\u30bf\u7121\u3057 diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/CellModelTableCellRenderer.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/CellModelTableCellRenderer.java index 2638ce1f56..cad654e40e 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/CellModelTableCellRenderer.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/CellModelTableCellRenderer.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2020 Basis Technology Corp. + * Copyright 2020-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,7 +19,6 @@ package org.sleuthkit.autopsy.datasourcesummary.uiutils; import java.awt.Component; -import java.awt.Insets; import java.awt.event.MouseEvent; import java.util.List; import javax.swing.BorderFactory; @@ -30,7 +29,6 @@ import javax.swing.JTable; import javax.swing.border.Border; import javax.swing.table.DefaultTableCellRenderer; import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.lang3.StringUtils; import org.sleuthkit.autopsy.datasourcesummary.uiutils.GuiCellModel.MenuItem; import org.sleuthkit.autopsy.datasourcesummary.uiutils.JTablePanel.CellMouseEvent; import org.sleuthkit.autopsy.datasourcesummary.uiutils.JTablePanel.CellMouseListener; @@ -43,7 +41,7 @@ public class CellModelTableCellRenderer extends DefaultTableCellRenderer { private static final long serialVersionUID = 1L; private static final int DEFAULT_ALIGNMENT = JLabel.LEFT; - private static final Border DEFAULT_BORDER = BorderFactory.createEmptyBorder(1, 5, 1, 5); + private static final Border DEFAULT_BORDER = BorderFactory.createEmptyBorder(2, 4, 2, 4); @Override public Component getTableCellRendererComponent(JTable table, Object value, @@ -62,43 +60,21 @@ public class CellModelTableCellRenderer extends DefaultTableCellRenderer { * Customizes the jlabel to match the column model and cell model provided. * * @param defaultCell The cell to customize that will be displayed in the - * jtable. - * @param cellModel The cell model for this cell. + * jtable. + * @param cellModel The cell model for this cell. * * @return The provided defaultCell. */ protected Component getTableCellRendererComponent(JLabel defaultCell, GuiCellModel cellModel) { - // sets the text for the cell or null if not present. - String text = cellModel.getText(); - if (StringUtils.isNotBlank(text)) { - defaultCell.setText(text); - } else { - defaultCell.setText(null); - } - - // sets the tooltip for the cell if present. - String tooltip = cellModel.getTooltip(); - if (StringUtils.isNotBlank(tooltip)) { - defaultCell.setToolTipText(tooltip); - } else { - defaultCell.setToolTipText(null); - } - - // sets the padding for cell text within the cell. - Insets insets = cellModel.getInsets(); - if (insets != null) { - defaultCell.setBorder(BorderFactory.createEmptyBorder(insets.top, insets.left, insets.bottom, insets.right)); - } else { - defaultCell.setBorder(DEFAULT_BORDER); - } - + defaultCell.setText(cellModel.getText()); + defaultCell.setToolTipText(cellModel.getTooltip()); // sets the JLabel alignment (left, center, right) or default alignment // if no alignment is specified int alignment = (cellModel.getHorizontalAlignment() == null) ? DEFAULT_ALIGNMENT : cellModel.getHorizontalAlignment().getJLabelAlignment(); defaultCell.setHorizontalAlignment(alignment); - + defaultCell.setBorder(DEFAULT_BORDER); return defaultCell; } @@ -134,7 +110,7 @@ public class CellModelTableCellRenderer extends DefaultTableCellRenderer { /** * @return The default cell mouse listener that triggers popups for - * non-primary button events. + * non-primary button events. */ public static CellMouseListener getMouseListener() { return DEFAULT_CELL_MOUSE_LISTENER; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/DefaultCellModel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/DefaultCellModel.java index 06165a3023..215f71469e 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/DefaultCellModel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/DefaultCellModel.java @@ -18,27 +18,24 @@ */ package org.sleuthkit.autopsy.datasourcesummary.uiutils; -import java.awt.Insets; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.function.Function; import java.util.function.Supplier; -import org.sleuthkit.autopsy.datasourcesummary.uiutils.ExcelCellModel; /** * The default cell model. */ public class DefaultCellModel implements GuiCellModel, ExcelCellModel { - final T data; - final Function stringConverter; - String tooltip; - CellModel.HorizontalAlign horizontalAlignment; - Insets insets; - List popupMenu; - Supplier> menuItemSupplier; - final String excelFormatString; + private final T data; + private final String text; + private String tooltip; + private CellModel.HorizontalAlign horizontalAlignment; + private List popupMenu; + private Supplier> menuItemSupplier; + private final String excelFormatString; /** * Main constructor. @@ -52,9 +49,9 @@ public class DefaultCellModel implements GuiCellModel, ExcelCellModel { /** * Constructor. * - * @param data The data to be displayed in the cell. + * @param data The data to be displayed in the cell. * @param stringConverter The means of converting that data to a string or - * null to use .toString method on object. + * null to use .toString method on object. */ public DefaultCellModel(T data, Function stringConverter) { this(data, stringConverter, null); @@ -63,20 +60,25 @@ public class DefaultCellModel implements GuiCellModel, ExcelCellModel { /** * Constructor. * - * @param data The data to be displayed in the cell. - * @param stringConverter The means of converting that data to a string or - * null to use .toString method on object. + * @param data The data to be displayed in the cell. + * @param stringConverter The means of converting that data to a string or + * null to use .toString method on object. * @param excelFormatString The apache poi excel format string to use with - * the data. + * the data. * * NOTE: Only certain data types can be exported. See * ExcelTableExport.createCell() for types. */ public DefaultCellModel(T data, Function stringConverter, String excelFormatString) { this.data = data; - this.stringConverter = stringConverter; this.excelFormatString = excelFormatString; - this.tooltip = getText(); + + if (stringConverter == null) { + text = this.data == null ? "" : this.data.toString(); + } else { + text = stringConverter.apply(this.data); + } + this.tooltip = text; } @Override @@ -91,11 +93,7 @@ public class DefaultCellModel implements GuiCellModel, ExcelCellModel { @Override public String getText() { - if (this.stringConverter == null) { - return this.data == null ? "" : this.data.toString(); - } else { - return this.stringConverter.apply(this.data); - } + return text; } @Override @@ -132,33 +130,14 @@ public class DefaultCellModel implements GuiCellModel, ExcelCellModel { return this; } - @Override - public Insets getInsets() { - return insets; - } - - /** - * Sets the insets for the text within the cell - * - * @param insets The insets. - * - * @return As a utility, returns this. - */ - public DefaultCellModel setInsets(Insets insets) { - this.insets = insets; - return this; - } - @Override public List getPopupMenu() { if (popupMenu != null) { return Collections.unmodifiableList(popupMenu); } - if (menuItemSupplier != null) { return this.menuItemSupplier.get(); } - return null; } @@ -166,6 +145,7 @@ public class DefaultCellModel implements GuiCellModel, ExcelCellModel { * Sets a function to lazy load the popup menu items. * * @param menuItemSupplier The lazy load function for popup items. + * * @return */ public DefaultCellModel setPopupMenuRetriever(Supplier> menuItemSupplier) { @@ -177,6 +157,7 @@ public class DefaultCellModel implements GuiCellModel, ExcelCellModel { * Sets the list of items for a popup menu * * @param popupMenu + * * @return As a utility, returns this. */ public DefaultCellModel setPopupMenu(List popupMenu) { diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/GuiCellModel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/GuiCellModel.java index e1c7fa0944..bac74d8fd5 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/GuiCellModel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/GuiCellModel.java @@ -18,7 +18,6 @@ */ package org.sleuthkit.autopsy.datasourcesummary.uiutils; -import java.awt.Insets; import java.util.List; /** @@ -72,11 +71,6 @@ public interface GuiCellModel extends CellModel { } } - /** - * @return The insets for the cell text. - */ - Insets getInsets(); - /** * @return The popup menu associated with this cell or null if no popup menu * should be shown for this cell. diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/JTablePanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/JTablePanel.java index be814d23a9..89cf39eb0b 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/JTablePanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/JTablePanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2020 Basis Technology Corp. + * Copyright 2020-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -41,6 +41,8 @@ import javax.swing.table.TableColumnModel; */ public class JTablePanel extends AbstractLoadableComponent> { + private static final int EXTRA_ROW_HEIGHT = 4; + /** * An event that wraps a swing MouseEvent also providing context within the * table cell. @@ -56,10 +58,10 @@ public class JTablePanel extends AbstractLoadableComponent> { /** * Main constructor. * - * @param e The underlying mouse event. - * @param table The table that was the target of the mouse event. - * @param row The row within the table that the event occurs. - * @param col The column within the table that the event occurs. + * @param e The underlying mouse event. + * @param table The table that was the target of the mouse event. + * @param row The row within the table that the event occurs. + * @param col The column within the table that the event occurs. * @param cellValue The value within the cell. */ public CellMouseEvent(MouseEvent e, JTable table, int row, int col, Object cellValue) { @@ -115,15 +117,14 @@ public class JTablePanel extends AbstractLoadableComponent> { * Handles mouse events at a cell level for the table. * * @param e The event containing information about the cell, the mouse - * event, and the table. + * event, and the table. */ void mouseClicked(CellMouseEvent e); } /** - * JTables don't allow displaying messages. So this LayerUI is used to - * display the contents of a child JLabel. Inspired by TableWaitLayerTest - * (Animating a Busy Indicator): + * This LayerUI is used to display the contents of a child JLabel. Inspired + * by TableWaitLayerTest (Animating a Busy Indicator): * https://docs.oracle.com/javase/tutorial/uiswing/misc/jlayer.html. */ private static class Overlay extends LayerUI { @@ -205,7 +206,7 @@ public class JTablePanel extends AbstractLoadableComponent> { .map((colModel) -> colModel.getCellRenderer()) .collect(Collectors.toList()); - return new DefaultListTableModel(columnRenderers); + return new DefaultListTableModel<>(columnRenderers); } /** @@ -225,7 +226,6 @@ public class JTablePanel extends AbstractLoadableComponent> { return resultTable; } - private JScrollPane tableScrollPane; private Overlay overlayLayer; private ListTableModel tableModel; @@ -241,6 +241,7 @@ public class JTablePanel extends AbstractLoadableComponent> { public JTablePanel(ListTableModel tableModel) { this(); setModel(tableModel); + table.setRowHeight(table.getRowHeight() + EXTRA_ROW_HEIGHT); } /** @@ -268,6 +269,7 @@ public class JTablePanel extends AbstractLoadableComponent> { } } }); + table.setGridColor(javax.swing.UIManager.getDefaults().getColor("InternalFrame.borderColor")); } /** @@ -290,7 +292,7 @@ public class JTablePanel extends AbstractLoadableComponent> { /** * @return The current listener for mouse events. The events provided to - * this listener will have cell and table context. + * this listener will have cell and table context. */ public CellMouseListener getCellListener() { return cellListener; @@ -300,7 +302,8 @@ public class JTablePanel extends AbstractLoadableComponent> { * Sets the current listener for mouse events. * * @param cellListener The event listener that will receive these events - * with cell and table context. + * with cell and table context. + * * @return */ public JTablePanel setCellListener(CellMouseListener cellListener) { @@ -329,7 +332,8 @@ public class JTablePanel extends AbstractLoadableComponent> { /** * @return The function for determining the key for a data row. This key is - * used to maintain current selection in the table despite changing rows. + * used to maintain current selection in the table despite changing + * rows. */ public Function getKeyFunction() { return keyFunction; @@ -351,9 +355,10 @@ public class JTablePanel extends AbstractLoadableComponent> { this.keyFunction = keyFunction; return this; } - + /** * Returns the selected items or null if no item is selected. + * * @return The selected items or null if no item is selected. */ public List getSelectedItems() { diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/directorytree/Bundle_ja.properties index d9ae2561f4..3c3896abb9 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/directorytree/Bundle_ja.properties @@ -1,4 +1,4 @@ -#Fri Feb 12 16:56:28 UTC 2021 +#Thu Jul 01 11:56:41 UTC 2021 AddExternalViewerRuleDialog.cancelButton.title=\u53d6\u308a\u6d88\u3057 AddExternalViewerRuleDialog.saveButton.title=\u4fdd\u5b58 AddExternalViewerRuleDialog.title=\u5916\u90e8\u30d3\u30e5\u30fc\u30ef\u30fc\u30eb\u30fc\u30eb @@ -152,6 +152,7 @@ SelectionContext.views=\u30d3\u30e5\u30fc ViewContextAction.errorMessage.cannotFindDirectory=\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u30fc\u3092\u898b\u3064\u3051\u3089\u308c\u307e\u305b\u3093\u3067\u3057\u305f\u3002 ViewContextAction.errorMessage.cannotFindNode=\u30c4\u30ea\u30fc\u5185\u306e\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u30ce\u30fc\u30c9\u3092\u898b\u3064\u3051\u3089\u308c\u307e\u305b\u3093\u3067\u3057\u305f\u3002 ViewContextAction.errorMessage.cannotSelectDirectory=\u30c4\u30ea\u30fc\u5185\u306e\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u30fc\u3092\u9078\u629e\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +ViewContextAction.errorMessage.unsupportedParent=\u3053\u306e\u30ea\u30ea\u30fc\u30b9\u3067\u30b5\u30dd\u30fc\u30c8\u5916\u306e\u30b3\u30f3\u30c6\u30f3\u30c4\u306b\u306f\u79fb\u52d5\u3067\u304d\u307e\u305b\u3093\u3002 VolumeDetailsPanel.OKButton.text=OK VolumeDetailsPanel.descLabel.text=\u8a18\u8ff0\: VolumeDetailsPanel.descValue.text=... diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java index bf99de6183..51fffee37f 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java @@ -79,6 +79,7 @@ import org.sleuthkit.datamodel.SlackFile; import org.sleuthkit.datamodel.TskException; import org.sleuthkit.datamodel.VirtualDirectory; import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; +import org.sleuthkit.datamodel.DataArtifact; import org.sleuthkit.datamodel.Report; import org.sleuthkit.datamodel.TskCoreException; @@ -290,11 +291,18 @@ public class DataResultFilterNode extends FilterNode { NbBundle.getMessage(this.getClass(), "DataResultFilterNode.action.viewFileInDir.text"), ban)); } } else if (artifactTypeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID()) { - //action to go to the source artifact - actionsList.add(new ViewSourceArtifactAction(DataResultFilterNode_viewSourceArtifact_text(), ba)); - // action to go to the source file of the artifact - actionsList.add(new ViewContextAction( - NbBundle.getMessage(this.getClass(), "DataResultFilterNode.action.viewSrcFileInDir.text"), ban)); + try { + if (ba.getAttribute(BlackboardAttribute.Type.TSK_ASSOCIATED_ARTIFACT) != null) { + //action to go to the source artifact + actionsList.add(new ViewSourceArtifactAction(DataResultFilterNode_viewSourceArtifact_text(), ba)); + + // action to go to the source file of the artifact + actionsList.add(new ViewContextAction( + NbBundle.getMessage(this.getClass(), "DataResultFilterNode.action.viewSrcFileInDir.text"), ban)); + } + } catch (TskCoreException ex) { + LOGGER.log(Level.WARNING, "Error looking up attributes for artifact with ID=" + ba.getId()); + } } else { // if the artifact links to another file, add an action to go to // that file @@ -358,10 +366,16 @@ public class DataResultFilterNode extends FilterNode { actionsList.add(ExtractAction.getInstance()); actionsList.add(ExportCSVAction.getInstance()); actionsList.add(null); // creates a menu separator - actionsList.add(AddContentTagAction.getInstance()); + + // don't show AddContentTagAction for data artifacts. + if (!(ban.getArtifact() instanceof DataArtifact)) { + actionsList.add(AddContentTagAction.getInstance()); + } + actionsList.add(AddBlackboardArtifactTagAction.getInstance()); - if (selectedFilesList.size() == 1) { + // don't show DeleteFileContentTagAction for data artifacts. + if ((!(ban.getArtifact() instanceof DataArtifact)) && (selectedFilesList.size() == 1)) { actionsList.add(DeleteFileContentTagAction.getInstance()); } } else { diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java index 3d3aa4939a..975a659aa7 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java @@ -33,6 +33,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; +import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.logging.Level; import java.util.prefs.PreferenceChangeEvent; @@ -44,14 +45,11 @@ import javax.swing.SwingUtilities; import javax.swing.SwingWorker; import javax.swing.event.PopupMenuEvent; import javax.swing.event.PopupMenuListener; -import javax.swing.event.TreeExpansionEvent; -import javax.swing.event.TreeExpansionListener; import javax.swing.tree.TreeSelectionModel; import org.apache.commons.lang3.StringUtils; import org.openide.explorer.ExplorerManager; import org.openide.explorer.ExplorerUtils; import org.openide.explorer.view.BeanTreeView; -import org.openide.explorer.view.Visualizer; import org.openide.nodes.AbstractNode; import org.openide.nodes.Children; import org.openide.nodes.Node; @@ -85,7 +83,7 @@ import org.sleuthkit.autopsy.datamodel.InterestingHits; import org.sleuthkit.autopsy.datamodel.KeywordHits; import org.sleuthkit.autopsy.datamodel.AutopsyTreeChildFactory; 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.ViewsNode; import org.sleuthkit.autopsy.datamodel.accounts.Accounts; @@ -126,6 +124,10 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat private static final String GROUPING_THRESHOLD_NAME = "GroupDataSourceThreshold"; private static final String SETTINGS_FILE = "CasePreferences.properties"; //NON-NLS + // nodes to be opened if present at top level + private static final Set NODES_TO_EXPAND = Stream.of(AnalysisResults.getName(), DataArtifacts.getName(), ViewsNode.NAME) + .collect(Collectors.toSet()); + /** * the constructor */ @@ -134,31 +136,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat // only allow one item to be selected at a time getTree().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); - //Hook into the JTree and pre-expand the Views Node and Results node when a user - //expands an item in the tree that makes these nodes visible. - ((ExpansionBeanTreeView) getTree()).addTreeExpansionListener(new TreeExpansionListener() { - @Override - public void treeExpanded(TreeExpansionEvent event) { - //Bail immediately if we are not in the Group By view. - //Assumption here is that the views are already expanded. - if (!CasePreferences.getGroupItemsInTreeByDataSource()) { - return; - } - Node expandedNode = Visualizer.findNode(event.getPath().getLastPathComponent()); - for (Node child : em.getRootContext().getChildren().getNodes()) { - if (child.equals(expandedNode)) { - preExpandNodes(child.getChildren()); - } - } - } - - @Override - public void treeCollapsed(TreeExpansionEvent event) { - //Do nothing - } - - }); // remove the close button putClientProperty(TopComponent.PROP_CLOSING_DISABLED, Boolean.TRUE); setName(NbBundle.getMessage(DirectoryTreeTopComponent.class, "CTL_DirectoryTreeTopComponent")); @@ -201,30 +179,23 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat */ private void preExpandNodes(Children rootChildren) { BeanTreeView tree = getTree(); - for (String categoryKey : new String[]{AnalysisResults.getName(), DataArtifacts.getName()}) { - Node categoryNode = rootChildren.findChild(categoryKey); - if (!Objects.isNull(categoryNode)) { - tree.expandNode(categoryNode); - Children resultsChildren = categoryNode.getChildren(); - Arrays.stream(resultsChildren.getNodes()).forEach(tree::expandNode); - } - } - - Node views = rootChildren.findChild(ViewsNode.NAME); - if (!Objects.isNull(views)) { - tree.expandNode(views); + // using getNodes(true) to fetch children so that async nodes are loaded + Node[] rootChildrenNodes = rootChildren.getNodes(true); + if (rootChildrenNodes == null || rootChildrenNodes.length < 1) { + return; } // expand all nodes parents of and including hosts if group by host/person if (Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true)) { - Node[] rootNodes = rootChildren.getNodes(); - if (rootNodes != null) { - Stream.of(rootNodes) - .flatMap((n) -> getHostNodesAndParents(n).stream()) - .filter((n) -> n != null) - .forEach((n) -> tree.expandNode(n)); - } + Stream.of(rootChildrenNodes) + .flatMap((n) -> getHostNodesAndParents(n).stream()) + .filter((n) -> n != null) + .forEach(tree::expandNode); + } else { + Stream.of(rootChildrenNodes) + .filter(n -> n != null && NODES_TO_EXPAND.contains(n.getName())) + .forEach(tree::expandNode); } } @@ -240,7 +211,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat if (node == null) { return Collections.emptyList(); } 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(); Node[] childNodes = children == null ? null : children.getNodes(); if (childNodes != null) { @@ -1192,7 +1163,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat return Optional.empty(); } else if (node.getLookup().lookup(Host.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. Children children = node.getChildren(); @@ -1546,9 +1517,8 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat * Returns the credit card artifact's parent node or null if cannot be * found. * - * @param typesChildren The children object of the same category as credit - * card. - * @param art The artifact. + * @param accountRootChildren + * @param ccNumberName * * @return The credit card artifact's parent node or null if cannot be * found. diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/SelectionContext.java b/Core/src/org/sleuthkit/autopsy/directorytree/SelectionContext.java index de84a49e85..6c3c546018 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/SelectionContext.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/SelectionContext.java @@ -18,8 +18,12 @@ */ package org.sleuthkit.autopsy.directorytree; +import java.util.Objects; import org.openide.nodes.Node; import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.casemodule.CasePreferences; +import org.sleuthkit.autopsy.datamodel.DataSourceFilesNode; +import org.sleuthkit.autopsy.datamodel.DataSourcesNode; import static org.sleuthkit.autopsy.directorytree.Bundle.*; @NbBundle.Messages({"SelectionContext.dataSources=Data Sources", @@ -28,12 +32,12 @@ import static org.sleuthkit.autopsy.directorytree.Bundle.*; enum SelectionContext { DATA_SOURCES(SelectionContext_dataSources()), VIEWS(SelectionContext_views()), - OTHER(""), // Subnode of another node. - DATA_SOURCE_FILES(SelectionContext_dataSourceFiles()); + OTHER(""), // Subnode of another node. + DATA_SOURCE_FILES(SelectionContext_dataSourceFiles()); private final String displayName; - private SelectionContext(String displayName) { + private SelectionContext(String displayName) { this.displayName = displayName; } @@ -62,6 +66,12 @@ enum SelectionContext { if (n == null || n.getParentNode() == null) { // Parent of root node or root node. Occurs during case open / close. return SelectionContext.OTHER; + } else if ((!Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true) && DataSourcesNode.getNameIdentifier().equals(n.getParentNode().getName())) + || (Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true) && DataSourceFilesNode.getNameIdentifier().equals(n.getParentNode().getName()))) { + // if group by data type and root is the DataSourcesNode or + // if group by persons/hosts and parent of DataSourceFilesNode + // then it is a data source node + return SelectionContext.DATA_SOURCES; } else if (n.getParentNode().getParentNode() == null) { // One level below root node. Should be one of DataSources, Views, or Results return SelectionContext.getContextFromName(n.getDisplayName()); @@ -75,7 +85,7 @@ enum SelectionContext { return context; } } - + return getSelectionContext(n.getParentNode()); } } diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ViewContextAction.java b/Core/src/org/sleuthkit/autopsy/directorytree/ViewContextAction.java index 6fb134ceec..323b340c7f 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/ViewContextAction.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/ViewContextAction.java @@ -31,6 +31,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import org.sleuthkit.autopsy.coreutils.Logger; import javax.swing.AbstractAction; +import org.apache.commons.lang3.StringUtils; import org.openide.nodes.AbstractNode; import org.openide.explorer.ExplorerManager; import org.openide.explorer.view.TreeView; @@ -46,10 +47,10 @@ import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode; import org.sleuthkit.autopsy.datamodel.AbstractFsContentNode; import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode; import org.sleuthkit.autopsy.datamodel.ContentNodeSelectionInfo; -import org.sleuthkit.autopsy.datamodel.DataSourcesByTypeNode; import org.sleuthkit.autopsy.datamodel.DataSourcesNode; +import org.sleuthkit.autopsy.datamodel.DataSourceFilesNode; 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.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; @@ -84,7 +85,7 @@ public class ViewContextAction extends AbstractAction { * parent of the content, selecting the parent in the tree view, then * selecting the content in the results view. * - * @param displayName The display name for the action. + * @param displayName The display name for the action. * @param artifactNode The artifact node for the artifact. */ public ViewContextAction(String displayName, BlackboardArtifactNode artifactNode) { @@ -106,9 +107,9 @@ public class ViewContextAction extends AbstractAction { * parent of the content, selecting the parent in the tree view, then * selecting the content in the results view. * - * @param displayName The display name for the action. + * @param displayName The display name for the action. * @param fileSystemContentNode The file system content node for the - * content. + * content. */ public ViewContextAction(String displayName, AbstractFsContentNode fileSystemContentNode) { super(displayName); @@ -121,9 +122,9 @@ public class ViewContextAction extends AbstractAction { * content, selecting the parent in the tree view, then selecting the * content in the results view. * - * @param displayName The display name for the action. + * @param displayName The display name for the action. * @param abstractAbstractFileNode The AbstractAbstractFileNode node for the - * content. + * content. */ public ViewContextAction(String displayName, AbstractAbstractFileNode abstractAbstractFileNode) { super(displayName); @@ -137,7 +138,7 @@ public class ViewContextAction extends AbstractAction { * content in the results view. * * @param displayName The display name for the action. - * @param content The content. + * @param content The content. */ public ViewContextAction(String displayName, Content content) { super(displayName); @@ -149,7 +150,7 @@ public class ViewContextAction extends AbstractAction { * branch of the tree view to the level of the parent of the content, * selecting the parent in the tree view, then selecting the content in the * results view. - * + * * NOTE: This code will likely need updating in the event that the structure * of the nodes is changed (i.e. adding parent levels). Places to look when * changing node structure include: @@ -168,176 +169,224 @@ public class ViewContextAction extends AbstractAction { public void actionPerformed(ActionEvent event) { EventQueue.invokeLater(() -> { - /* - * Get the parent content for the content to be selected in the - * results view. If the parent content is null, then the specified - * content is a data source, and the parent tree view node is the - * "Data Sources" node. Otherwise, the tree view needs to be - * searched to find the parent treeview node. - */ - Content parentContent = null; - try { - parentContent = content.getParent(); - } catch (TskCoreException ex) { - MessageNotifyUtil.Message.error(Bundle.ViewContextAction_errorMessage_cannotFindDirectory()); - logger.log(Level.SEVERE, String.format("Could not get parent of Content object: %s", content), ex); //NON-NLS - return; - } - - if ((parentContent != null) - && (parentContent instanceof UnsupportedContent)) { + Content parentContent = getParentContent(this.content); + + if ((parentContent != null) && (parentContent instanceof UnsupportedContent)) { MessageNotifyUtil.Message.error(Bundle.ViewContextAction_errorMessage_unsupportedParent()); logger.log(Level.WARNING, String.format("Could not navigate to unsupported content with id: %d", parentContent.getId())); //NON-NLS return; } - /* - * Get the "Data Sources" node from the tree view. - */ + // Get the "Data Sources" node from the tree view. DirectoryTreeTopComponent treeViewTopComponent = DirectoryTreeTopComponent.findInstance(); ExplorerManager treeViewExplorerMgr = treeViewTopComponent.getExplorerManager(); + Node parentTreeViewNode = null; - if (Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true)) { // 'Group by Data Source' view - - SleuthkitCase skCase; - String dsname; - try { - // get the objid/name of the datasource of the selected content. - skCase = Case.getCurrentCaseThrows().getSleuthkitCase(); - long contentDSObjid = content.getDataSource().getId(); - DataSource datasource = skCase.getDataSource(contentDSObjid); - dsname = datasource.getName(); - Children rootChildren = treeViewExplorerMgr.getRootContext().getChildren(); - - if (null != parentContent) { - // the tree view needs to be searched to find the parent treeview node. - /* NOTE: we can't do a lookup by data source name here, becase if there - are multiple data sources with the same name, then "getChildren().findChild(dsname)" - simply returns the first one that it finds. Instead we have to loop over all - data sources with that name, and make sure we find the correct one. - */ - List dataSourceLevelNodes = Stream.of(rootChildren.getNodes()) - .flatMap(rootNode -> getDataSourceLevelNodes(rootNode).stream()) - .collect(Collectors.toList()); - - for (Node treeNode : dataSourceLevelNodes) { - // in the root, look for a data source node with the name of interest - if (!(treeNode.getName().equals(dsname))) { - continue; - } - - // for this data source, get the "Data Sources" child node - Node datasourceGroupingNode = treeNode.getChildren().findChild(DataSourcesNode.getNameIdentifier()); - - // check whether this is the data source we are looking for - parentTreeViewNode = findParentNodeInTree(parentContent, datasourceGroupingNode); - if (parentTreeViewNode != null) { - // found the data source node - break; - } - } - } else { - /* If the parent content is null, then the specified - * content is a data source, and the parent tree view node is the - * "Data Sources" node. */ - Node datasourceGroupingNode = rootChildren.findChild(dsname); - if (!Objects.isNull(datasourceGroupingNode)) { - Children dsChildren = datasourceGroupingNode.getChildren(); - parentTreeViewNode = dsChildren.findChild(DataSourcesNode.getNameIdentifier()); - } - } - - if (parentTreeViewNode == null) { - MessageNotifyUtil.Message.error(Bundle.ViewContextAction_errorMessage_cannotFindNode()); - logger.log(Level.SEVERE, "Failed to locate data source node in tree."); //NON-NLS - return; - } - } catch (NoCurrentCaseException | TskDataException | TskCoreException ex) { - MessageNotifyUtil.Message.error(Bundle.ViewContextAction_errorMessage_cannotFindNode()); - logger.log(Level.SEVERE, "Failed to locate data source node in tree.", ex); //NON-NLS - return; - } - } else { // Classic view - // Start the search at the DataSourcesNode - Children rootChildren = treeViewExplorerMgr.getRootContext().getChildren(); - Node rootDsNode = rootChildren == null ? null : rootChildren.findChild(DataSourcesByTypeNode.getNameIdentifier()); - if (rootDsNode != null) { - for (Node dataSourceLevelNode : getDataSourceLevelNodes(rootDsNode)) { - DataSource dataSource = dataSourceLevelNode.getLookup().lookup(DataSource.class); - if (dataSource != null) { - // the tree view needs to be searched to find the parent treeview node. - Node potentialParentTreeViewNode = findParentNodeInTree(parentContent, dataSourceLevelNode); - if (potentialParentTreeViewNode != null) { - parentTreeViewNode = potentialParentTreeViewNode; - break; - } - } - } + if (parentContent != null) { + if (Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true)) { + parentTreeViewNode = getParentNodeGroupedByPersonHost(treeViewExplorerMgr, parentContent); + } else { + parentTreeViewNode = getParentNodeGroupedByDataSource(treeViewExplorerMgr, parentContent); } } - /* - * Set the child selection info of the parent tree node, then select - * the parent node in the tree view. The results view will retrieve - * this selection info and use it to complete this action when the - * tree view top component responds to the selection of the parent - * node by pushing it into the results view top component. - */ - DisplayableItemNode undecoratedParentNode = (DisplayableItemNode) ((DirectoryTreeFilterNode) parentTreeViewNode).getOriginal(); - undecoratedParentNode.setChildNodeSelectionInfo(new ContentNodeSelectionInfo(content)); - if (content instanceof BlackboardArtifact) { - BlackboardArtifact artifact = ((BlackboardArtifact) content); - long associatedId = artifact.getObjectID(); - try { - Content associatedFileContent = artifact.getSleuthkitCase().getContentById(associatedId); - undecoratedParentNode.setChildNodeSelectionInfo(new ContentNodeSelectionInfo(associatedFileContent)); - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Could not find associated content from artifact with id %d", artifact.getId()); - } + // if no node is found, report error and do nothing + if (parentTreeViewNode == null) { + MessageNotifyUtil.Message.error(Bundle.ViewContextAction_errorMessage_cannotFindNode()); + logger.log(Level.SEVERE, "Failed to locate data source node in tree."); //NON-NLS + return; } - TreeView treeView = treeViewTopComponent.getTree(); - treeView.expandNode(parentTreeViewNode); - if (treeViewTopComponent.getSelectedNode().equals(parentTreeViewNode)) { - //In the case where our tree view already has the destination directory selected - //due to an optimization in the ExplorerManager.setExploredContextAndSelection method - //the property change we listen for to call DirectoryTreeTopComponent.respondSelection - //will not be sent so we call it manually ourselves after making - //the directory listing the active tab. - treeViewTopComponent.setDirectoryListingActive(); - treeViewTopComponent.respondSelection(treeViewExplorerMgr.getSelectedNodes(), new Node[]{parentTreeViewNode}); - } else { - try { - treeViewExplorerMgr.setExploredContextAndSelection(parentTreeViewNode, new Node[]{parentTreeViewNode}); - } catch (PropertyVetoException ex) { - MessageNotifyUtil.Message.error(Bundle.ViewContextAction_errorMessage_cannotSelectDirectory()); - logger.log(Level.SEVERE, "Failed to select the parent node in the tree view", ex); //NON-NLS - } - } + setNodeSelection(this.content, parentTreeViewNode, treeViewTopComponent, treeViewExplorerMgr); }); } + /** + * Get the parent content for the content to be selected in the results + * view. If the parent content is null, then the specified content is a data + * source, and the parent tree view node is the "Data Sources" node. + * Otherwise, the tree view needs to be searched to find the parent treeview + * node. + * + * @param content The content whose parent will be returned. If this item is + * a datasource, it will be returned. + * + * @return The content if content is a data source or the parent of this + * content. + */ + private Content getParentContent(Content content) { + + try { + return (content instanceof DataSource) + ? content + : content.getParent(); + } catch (TskCoreException ex) { + MessageNotifyUtil.Message.error(Bundle.ViewContextAction_errorMessage_cannotFindDirectory()); + logger.log(Level.SEVERE, String.format("Could not get parent of Content object: %s", content), ex); //NON-NLS + return null; + } + } + + /** + * Returns the node in the tree related to the parentContent or null if + * can't be found. This method should be used when view is grouped by data + * source. + * + * @param treeViewExplorerMgr The explorer manager. + * @param parentContent The content whose equivalent node will be + * returned if found. + * + * @return The node if found or null. + */ + private Node getParentNodeGroupedByDataSource(ExplorerManager treeViewExplorerMgr, Content parentContent) { + // Classic view + // Start the search at the DataSourcesNode + Children rootChildren = treeViewExplorerMgr.getRootContext().getChildren(); + Node rootDsNode = rootChildren == null ? null : rootChildren.findChild(DataSourcesNode.getNameIdentifier()); + if (rootDsNode != null) { + for (Node dataSourceLevelNode : getDataSourceLevelNodes(rootDsNode)) { + DataSource dataSource = dataSourceLevelNode.getLookup().lookup(DataSource.class); + if (dataSource != null) { + // the tree view needs to be searched to find the parent treeview node. + Node potentialParentTreeViewNode = findParentNodeInTree(parentContent, dataSourceLevelNode); + if (potentialParentTreeViewNode != null) { + return potentialParentTreeViewNode; + } + } + } + } + + return null; + } + + /** + * Returns the node in the tree related to the parentContent or null if + * can't be found. This method should be used when view is grouped by + * hosts/persons. + * + * @param treeViewExplorerMgr The explorer manager. + * @param parentContent The content whose equivalent node will be + * returned if found. + * + * @return The node if found or null. + */ + private Node getParentNodeGroupedByPersonHost(ExplorerManager treeViewExplorerMgr, Content parentContent) { + // 'Group by Data Source' view + + SleuthkitCase skCase; + String dsname; + try { + // get the objid/name of the datasource of the selected content. + skCase = Case.getCurrentCaseThrows().getSleuthkitCase(); + long contentDSObjid = parentContent.getDataSource().getId(); + DataSource datasource = skCase.getDataSource(contentDSObjid); + dsname = datasource.getName(); + Children rootChildren = treeViewExplorerMgr.getRootContext().getChildren(); + + // the tree view needs to be searched to find the parent treeview node. + /* NOTE: we can't do a lookup by data source name here, becase if there + are multiple data sources with the same name, then "getChildren().findChild(dsname)" + simply returns the first one that it finds. Instead we have to loop over all + data sources with that name, and make sure we find the correct one. + */ + List dataSourceLevelNodes = Stream.of(rootChildren.getNodes(true)) + .flatMap(rootNode -> getDataSourceLevelNodes(rootNode).stream()) + .collect(Collectors.toList()); + + for (Node treeNode : dataSourceLevelNodes) { + // in the root, look for a data source node with the name of interest + if (!(treeNode.getName().equals(dsname))) { + continue; + } + + // for this data source, get the "Data Sources" child node + Node datasourceGroupingNode = treeNode.getChildren().findChild(DataSourceFilesNode.getNameIdentifier()); + + // check whether this is the data source we are looking for + Node parentTreeViewNode = findParentNodeInTree(parentContent, datasourceGroupingNode); + if (parentTreeViewNode != null) { + // found the data source node + return parentTreeViewNode; + } + } + } catch (NoCurrentCaseException | TskDataException | TskCoreException ex) { + MessageNotifyUtil.Message.error(Bundle.ViewContextAction_errorMessage_cannotFindNode()); + logger.log(Level.SEVERE, "Failed to locate data source node in tree.", ex); //NON-NLS + } + + return null; + } + + /** + * Set the node selection in the tree. + * @param content The content to select. + * @param parentTreeViewNode The node that is the parent of the content. + * @param treeViewTopComponent The DirectoryTreeTopComponent. + * @param treeViewExplorerMgr The ExplorerManager. + */ + private void setNodeSelection(Content content, Node parentTreeViewNode, DirectoryTreeTopComponent treeViewTopComponent, ExplorerManager treeViewExplorerMgr) { + /* + * Set the child selection info of the parent tree node, then select + * the parent node in the tree view. The results view will retrieve + * this selection info and use it to complete this action when the + * tree view top component responds to the selection of the parent + * node by pushing it into the results view top component. + */ + DisplayableItemNode undecoratedParentNode = (DisplayableItemNode) ((DirectoryTreeFilterNode) parentTreeViewNode).getOriginal(); + undecoratedParentNode.setChildNodeSelectionInfo(new ContentNodeSelectionInfo(content)); + if (content instanceof BlackboardArtifact) { + BlackboardArtifact artifact = ((BlackboardArtifact) content); + long associatedId = artifact.getObjectID(); + try { + Content associatedFileContent = artifact.getSleuthkitCase().getContentById(associatedId); + undecoratedParentNode.setChildNodeSelectionInfo(new ContentNodeSelectionInfo(associatedFileContent)); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Could not find associated content from artifact with id %d", artifact.getId()); + } + } + + TreeView treeView = treeViewTopComponent.getTree(); + treeView.expandNode(parentTreeViewNode); + if (treeViewTopComponent.getSelectedNode().equals(parentTreeViewNode)) { + //In the case where our tree view already has the destination directory selected + //due to an optimization in the ExplorerManager.setExploredContextAndSelection method + //the property change we listen for to call DirectoryTreeTopComponent.respondSelection + //will not be sent so we call it manually ourselves after making + //the directory listing the active tab. + treeViewTopComponent.setDirectoryListingActive(); + treeViewTopComponent.respondSelection(treeViewExplorerMgr.getSelectedNodes(), new Node[]{parentTreeViewNode}); + } else { + try { + treeViewExplorerMgr.setExploredContextAndSelection(parentTreeViewNode, new Node[]{parentTreeViewNode}); + } catch (PropertyVetoException ex) { + MessageNotifyUtil.Message.error(Bundle.ViewContextAction_errorMessage_cannotSelectDirectory()); + logger.log(Level.SEVERE, "Failed to select the parent node in the tree view", ex); //NON-NLS + } + } + } + /** * If the node has lookup of host or person, returns children. If not, just * returns itself. * * @param node The node. + * * @return The child nodes that are at the data source level. */ private List getDataSourceLevelNodes(Node node) { if (node == null) { return Collections.emptyList(); - } else if (node.getLookup().lookup(Host.class) != null || - node.getLookup().lookup(Person.class) != null || - DataSourcesByTypeNode.getNameIdentifier().equals(node.getLookup().lookup(String.class)) || - PersonGroupingNode.getUnknownPersonId().equals(node.getLookup().lookup(String.class))) { + } else if (node.getLookup().lookup(Host.class) != null + || node.getLookup().lookup(Person.class) != null + || DataSourcesNode.getNameIdentifier().equals(node.getLookup().lookup(String.class)) + || PersonNode.getUnknownPersonId().equals(node.getLookup().lookup(String.class))) { Children children = node.getChildren(); - Node[] childNodes = children == null ? null : children.getNodes(); + Node[] childNodes = children == null ? null : children.getNodes(true); if (childNodes == null) { return Collections.emptyList(); } - return Stream.of(node.getChildren().getNodes()) + return Stream.of(node.getChildren().getNodes(true)) .flatMap(parent -> getDataSourceLevelNodes(parent).stream()) .collect(Collectors.toList()); } else { @@ -350,7 +399,8 @@ public class ViewContextAction extends AbstractAction { * of the specified content. * * @param parentContent parent content for the content to be searched for - * @param node Node tree to search + * @param node Node tree to search + * * @return Node object of the matching parent, NULL if not found */ private Node findParentNodeInTree(Content parentContent, Node node) { @@ -377,6 +427,11 @@ public class ViewContextAction extends AbstractAction { Node dummyRootNode = new DirectoryTreeFilterNode(new AbstractNode(new RootContentChildren(contentBranch)), true); Children ancestorChildren = dummyRootNode.getChildren(); + // if content is the data source provided, return that. + if (ancestorChildren.getNodesCount() == 1 && StringUtils.equals(ancestorChildren.getNodeAt(0).getName(), node.getName())) { + return node; + } + /* * Search the tree for the parent node. Note that this algorithm * simply discards "extra" ancestor nodes not shown in the tree, @@ -387,8 +442,9 @@ public class ViewContextAction extends AbstractAction { Node parentTreeViewNode = null; for (int i = 0; i < ancestorChildren.getNodesCount(); i++) { Node ancestorNode = ancestorChildren.getNodeAt(i); - for (int j = 0; j < treeNodeChildren.getNodesCount(); j++) { - Node treeNode = treeNodeChildren.getNodeAt(j); + Node[] treeNodeChilds = treeNodeChildren.getNodes(true); + for (int j = 0; j < treeNodeChilds.length; j++) { + Node treeNode = treeNodeChilds[j]; if (ancestorNode.getName().equals(treeNode.getName())) { parentTreeViewNode = treeNode; treeNodeChildren = treeNode.getChildren(); diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/actionhelpers/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/directorytree/actionhelpers/Bundle_ja.properties index 3d4329c552..445ee61aa5 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/actionhelpers/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/directorytree/actionhelpers/Bundle_ja.properties @@ -1,3 +1,11 @@ -#Fri Feb 12 16:56:28 UTC 2021 +#Mon Jul 12 13:21:59 UTC 2021 +ExtractActionHelper.confDlg.destFileExist.msg=\u5b9b\u5148\u30d5\u30a1\u30a4\u30eb{0}\u306f\u3059\u3067\u306b\u5b58\u5728\u3057\u307e\u3059\u3001\u4e0a\u66f8\u304d\u3057\u307e\u3059\u304b\uff1f +ExtractActionHelper.confDlg.destFileExist.title=\u30d5\u30a1\u30a4\u30eb\u304c\u5b58\u5728\u3057\u3066\u3044\u307e\u3059 +ExtractActionHelper.done.notifyMsg.fileExtr.text=\u30d5\u30a1\u30a4\u30eb\u304c\u62bd\u51fa\u3055\u308c\u307e\u3057\u305f\u3002 +ExtractActionHelper.extractFiles.cantCreateFolderErr.msg=\u9078\u629e\u3057\u305f\u30d5\u30a9\u30eb\u30c0\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +ExtractActionHelper.msgDlg.cantOverwriteFile.msg=\u65e2\u5b58\u306e\u30d5\u30a1\u30a4\u30eb{0}\u3092\u4e0a\u66f8\u304d\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f +ExtractActionHelper.noOpenCase.errMsg=\u30aa\u30fc\u30d7\u30f3\u30b1\u30fc\u30b9\u306f\u3042\u308a\u307e\u305b\u3093\u3002 +ExtractActionHelper.notifyDlg.noFileToExtr.msg=\u62bd\u51fa\u3059\u308b\u30d5\u30a1\u30a4\u30eb\u304c\u3042\u308a\u307e\u305b\u3093\u3002 +ExtractActionHelper.progress.cancellingExtraction={0}\uff08\u30ad\u30e3\u30f3\u30bb\u30eb\u4e2d...\uff09 ExtractActionHelper.progress.extracting={0}\u3078\u306e\u62bd\u51fa ExtractActionHelper.progress.fileExtracting=\u30d5\u30a1\u30a4\u30eb\u306e\u62bd\u51fa\uff1a{0} diff --git a/Core/src/org/sleuthkit/autopsy/discovery/search/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/discovery/search/Bundle_ja.properties index 13b93f98f2..60c4858289 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/search/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/discovery/search/Bundle_ja.properties @@ -1,4 +1,4 @@ -#Fri Feb 12 16:56:28 UTC 2021 +#Thu Jul 01 11:56:41 UTC 2021 DiscoveryAttributes.ActivityDateGroupKey.getDisplayNameTemplate={0}{1}\u3001{2}\u306e\u9031 DiscoveryAttributes.GroupingAttributeType.datasource.displayName=\u30c7\u30fc\u30bf\u5143 DiscoveryAttributes.GroupingAttributeType.fileType.displayName=\u30d5\u30a1\u30a4\u30eb\u306e\u7a2e\u985e @@ -48,10 +48,8 @@ FileSorter.SortingMethod.fullPath.displayName=\u30d5\u30eb\u30d1\u30b9 FileSorter.SortingMethod.keywordlist.displayName=\u30ad\u30fc\u30ef\u30fc\u30c9\u30ea\u30b9\u30c8\u540d FileSorter.SortingMethod.pageViews.displayName=\u30da\u30fc\u30b8\u30d3\u30e5\u30fc ResultDomain_getDefaultCategory=\u672a\u5206\u985e -ResultFile.score.interestingResult.description=1\u3064\u4ee5\u4e0a\u306e\u30d5\u30a1\u30a4\u30eb\u306b\u8208\u5473\u6df1\u3044\u7d50\u679c\u304c\u95a2\u9023\u4ed8\u3051\u3089\u308c\u3066\u3044\u307e\u3059\u3002 -ResultFile.score.notableFile.description=1\u3064\u4ee5\u4e0a\u306e\u30d5\u30a1\u30a4\u30eb\u304c\u6ce8\u76ee\u3059\u3079\u304d\u3082\u306e\u3068\u3057\u3066\u8a8d\u8b58\u3055\u308c\u307e\u3057\u305f\u3002 -ResultFile.score.notableTaggedFile.description=1\u3064\u4ee5\u4e0a\u306e\u30d5\u30a1\u30a4\u30eb\u304c\u6ce8\u76ee\u3059\u3079\u304d\u30bf\u30b0\u4ed8\u3051\u3055\u308c\u3066\u3044\u307e\u3059\u3002 -ResultFile.score.taggedFile.description=1\u3064\u4ee5\u4e0a\u306e\u30d5\u30a1\u30a4\u30eb\u304c\u30bf\u30b0\u4ed8\u3051\u3055\u308c\u3066\u3044\u307e\u3059\u3002 +ResultDomain_noAccountTypes=\u4e0d\u660e +ResultFile_updateScoreAndDescription_description={0}\u5206\u6790\u7d50\u679c\u30b9\u30b3\u30a2\u304c\u3042\u308a\u307e\u3059 SearchData.AttributeType.Domain.displayName=\u30c9\u30e1\u30a4\u30f3 SearchData.FileSize.100kbto1mb=\: 100KB-1MB SearchData.FileSize.100mbto1gb=\: 100MB-1GB diff --git a/Core/src/org/sleuthkit/autopsy/discovery/search/DiscoveryKeyUtils.java b/Core/src/org/sleuthkit/autopsy/discovery/search/DiscoveryKeyUtils.java index 39b3c1b80c..c201414199 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/search/DiscoveryKeyUtils.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/search/DiscoveryKeyUtils.java @@ -1,7 +1,7 @@ /* * Autopsy * - * Copyright 2020 Basis Technology Corp. + * Copyright 2020-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -32,7 +32,7 @@ import java.util.logging.Level; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.datamodel.ContentUtils; +import org.sleuthkit.autopsy.coreutils.TimeZoneUtils; import org.sleuthkit.autopsy.discovery.search.SearchData.PageViews; import org.sleuthkit.autopsy.discovery.ui.MonthAbbreviation; import org.sleuthkit.datamodel.AbstractFile; @@ -1217,7 +1217,7 @@ public class DiscoveryKeyUtils { Instant startActivityAsInsant = Instant.ofEpochSecond(epochSeconds); // Determines the timezone using the settings panel or value parsed from the // parent data source - TimeZone currentTimeZone = ContentUtils.getTimeZone(domainResult.getDataSource()); + TimeZone currentTimeZone = TimeZoneUtils.getTimeZone(); // Convert to a datetime using epoch and timezone. ZonedDateTime startActivityAsDateTime = ZonedDateTime.ofInstant(startActivityAsInsant, currentTimeZone.toZoneId()); // Get the closest Sunday, which is the cut off for the current week. diff --git a/Core/src/org/sleuthkit/autopsy/discovery/search/DomainSearch.java b/Core/src/org/sleuthkit/autopsy/discovery/search/DomainSearch.java index 497d622b1c..eb52327d45 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/search/DomainSearch.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/search/DomainSearch.java @@ -1,7 +1,7 @@ /* * Autopsy * - * Copyright 2020 Basis Technology Corp. + * Copyright 2020-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,15 +24,13 @@ import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import java.util.TimeZone; import org.apache.commons.lang3.StringUtils; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; -import org.sleuthkit.autopsy.datamodel.ContentUtils; +import org.sleuthkit.autopsy.coreutils.TimeZoneUtils; import org.sleuthkit.autopsy.discovery.search.DiscoveryKeyUtils.GroupKey; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.SleuthkitCase; -import org.sleuthkit.datamodel.TimeUtilities; import org.sleuthkit.datamodel.TskCoreException; /** @@ -246,8 +244,7 @@ public class DomainSearch { private String getDate(BlackboardArtifact artifact) throws TskCoreException { for (BlackboardAttribute attribute : artifact.getAttributes()) { if (attribute.getAttributeType().getTypeName().startsWith("TSK_DATETIME")) { - TimeZone timeZone = ContentUtils.getTimeZone(artifact); - String dateString = TimeUtilities.epochToTime(attribute.getValueLong(), timeZone); + String dateString = TimeZoneUtils.getFormattedTime(attribute.getValueLong()); if (dateString.length() >= 10) { return dateString.substring(0, 10); } diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java index cbf38d7453..dac2668c50 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/ArtifactsListPanel.java @@ -1,7 +1,7 @@ /* * Autopsy * - * Copyright 2020 Basis Technology Corp. + * Copyright 2020-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -33,11 +33,10 @@ import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.ThreadConfined; -import org.sleuthkit.autopsy.datamodel.ContentUtils; +import org.sleuthkit.autopsy.coreutils.TimeZoneUtils; import org.sleuthkit.autopsy.guiutils.SimpleTableCellRenderer; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; -import org.sleuthkit.datamodel.TimeUtilities; import org.sleuthkit.datamodel.TskCoreException; /** @@ -303,7 +302,7 @@ final class ArtifactsListPanel extends AbstractArtifactListPanel { @ThreadConfined(type = ThreadConfined.ThreadType.AWT) private String getStringForColumn(BlackboardArtifact artifact, BlackboardAttribute bba, int columnIndex) throws TskCoreException { if (columnIndex == 0 && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID()) { - return TimeUtilities.epochToTime(bba.getValueLong(), ContentUtils.getTimeZone(artifact)); + return TimeZoneUtils.getFormattedTime(bba.getValueLong()); } else if (columnIndex == 1) { if (artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD || artifactType == BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CACHE) { if (bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID()) { @@ -339,7 +338,7 @@ final class ArtifactsListPanel extends AbstractArtifactListPanel { final BlackboardArtifact artifact = getArtifactByRow(rowIndex); for (BlackboardAttribute bba : artifact.getAttributes()) { if (columnIndex == 0 && bba.getAttributeType().getTypeName().startsWith("TSK_DATETIME") && !StringUtils.isBlank(bba.getDisplayString())) { - return TimeUtilities.epochToTime(bba.getValueLong(), ContentUtils.getTimeZone(artifact)); + return TimeZoneUtils.getFormattedTime(bba.getValueLong()); } else if (columnIndex == 1 && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL.getTypeID() && !StringUtils.isBlank(bba.getDisplayString())) { return bba.getDisplayString(); } else if (columnIndex == 1 && bba.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME.getTypeID() && !StringUtils.isBlank(bba.getDisplayString())) { diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED index e9f767cffe..e5e9f22a46 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle.properties-MERGED @@ -24,6 +24,7 @@ DateFilterPanel.invalidRange.text=Range or Only Last must be selected. DateFilterPanel.startAfterEnd.text=Start date should be before the end date when both are enabled. DateFilterPanel.startOrEndNeeded.text=A start or end date must be specified to use the range filter. DiscoveryDialog.name.text=Discovery +DiscoveryExtractAction.title.extractFiles.text=Extract File DiscoveryTopComponent.additionalFilters.text=; DiscoveryTopComponent.cancelButton.text=Cancel Search DiscoveryTopComponent.domainSearch.text=Type: Domain diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle_ja.properties index f8235ab6e3..54e640b4b9 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/Bundle_ja.properties @@ -1,4 +1,5 @@ -#Fri Feb 12 16:56:28 UTC 2021 +#Mon Jun 14 12:23:19 UTC 2021 +ArtifactMenuMouseAdapter.noFile.text=\u30d5\u30a1\u30a4\u30eb\u304c\u5b58\u5728\u3057\u307e\u305b\u3093\u3002 ArtifactMenuMouseAdapter_ExternalViewer_label=\u5916\u90e8\u30d3\u30e5\u30fc\u30a2\u3067\u958b\u304f ArtifactMenuMouseAdapter_label=\u30d5\u30a1\u30a4\u30eb\u306e\u62bd\u51fa ArtifactTypeFilterPanel.artifactTypeCheckbox.text=\u7d50\u679c\u30bf\u30a4\u30d7\uff1a @@ -23,7 +24,7 @@ DateFilterPanel.dateRange.text=\u65e5\u4ed8\u7bc4\u56f2\uff08{0}\uff09\uff1a DateFilterPanel.daysLabel.text=\u6d3b\u52d5\u65e5 DateFilterPanel.endCheckBox.text=\u7d42\u4e86\uff1a DateFilterPanel.invalidRange.text=\u7bc4\u56f2\u307e\u305f\u306f\u6700\u5f8c\u3092\u9078\u629e\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002 -DateFilterPanel.mostRecentRadioButton.text=\u6700\u5f8c\u306e\u307f\uff1a +DateFilterPanel.mostRecentRadioButton.text=\u6700\u7d42\u306e\u307f\uff1a DateFilterPanel.startAfterEnd.text=\u4e21\u65b9\u304c\u6709\u52b9\u306a\u5834\u5408\u3001\u958b\u59cb\u65e5\u306f\u7d42\u4e86\u65e5\u3088\u308a\u524d\u3067\u3042\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002 DateFilterPanel.startCheckBox.text=\u30b9\u30bf\u30fc\u30c8\uff1a DateFilterPanel.startOrEndNeeded.text=\u7bc4\u56f2\u30d5\u30a3\u30eb\u30bf\u30fc\u3092\u4f7f\u7528\u3059\u308b\u306b\u306f\u3001\u958b\u59cb\u65e5\u307e\u305f\u306f\u7d42\u4e86\u65e5\u3092\u6307\u5b9a\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002 @@ -63,12 +64,18 @@ DocumentPanel.numberOfImages.noImages=\u753b\u50cf\u306a\u3057 DocumentPanel.numberOfImages.text={0}\u753b\u50cf\u306e1\u3064 DocumentWrapper.previewInitialValue=\u30d7\u30ec\u30d3\u30e5\u30fc\u306f\u307e\u3060\u751f\u6210\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002 DomainDetailsPanel.miniTimelineTitle.text=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3 +DomainDetailsPanel.otherOccurrencesTab.title=\u305d\u306e\u4ed6\u306e\u767a\u751f DomainFilterPanel.domainFiltersSplitPane.border.title=\u30b9\u30c6\u30c3\u30d72\uff1a\u8868\u793a\u3059\u308b\u30c9\u30e1\u30a4\u30f3\u306e\u30d5\u30a3\u30eb\u30bf\u30ea\u30f3\u30b0 DomainSummaryPanel.activity.text=\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3\uff1a{0}\u304b\u3089{1} +DomainSummaryPanel.category.text=\u30ab\u30c6\u30b4\u30ea\uff1a DomainSummaryPanel.downloads.text=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3057\u305f\u30d5\u30a1\u30a4\u30eb\uff1a DomainSummaryPanel.loadingImages.text=\u30b5\u30e0\u30cd\u30a4\u30eb\u3092\u8aad\u307f\u8fbc\u3093\u3067\u3044\u307e\u3059... -DomainSummaryPanel.pages.text=\u904e\u53bb60\u65e5\u9593\u306e\u30da\u30fc\u30b8\u30d3\u30e5\u30fc\uff1a +DomainSummaryPanel.no.text=\u3044\u3044\u3048 +DomainSummaryPanel.notability.text=\u4ee5\u524d\u306b\u6ce8\u76ee\u3059\u3079\u304d\u306b\u30bf\u30b0\u4ed8\u3051\uff1a +DomainSummaryPanel.pages.text=\u6700\u8fd160\u65e5\u9593\u306e\u30da\u30fc\u30b8\u30d3\u30e5\u30fc\uff1a DomainSummaryPanel.totalPages.text=\u5168\u30da\u30fc\u30b8\u30d3\u30e5\u30fc\uff1a +DomainSummaryPanel.userRole.text=\u30a2\u30ab\u30a6\u30f3\u30c8\u30bf\u30a4\u30d7 +DomainSummaryPanel.yes.text=\u306f\u3044 FileDetailsPanel.instancesList.border.title=\u4f8b GroupListPanel.groupKeyList.border.title=\u30b0\u30eb\u30fc\u30d7 GroupsListPanel.noDomainResults.message.text=\u9078\u629e\u3057\u305f\u30d5\u30a3\u30eb\u30bf\u30fc\u3067\u306e\u30c9\u30e1\u30a4\u30f3\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f\u3002\n\n\u30ea\u30de\u30a4\u30f3\u30c0\u30fc\uff1a\n -\u6700\u8fd1\u306e\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3\u30e2\u30b8\u30e5\u30fc\u30eb\u3067\u7d50\u679c\u3092\u691c\u7d22\u3059\u308b\u306b\u306f\u5404\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3067\u5b9f\u884c\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002\n -\u904e\u53bb\u306e\u767a\u751f\u3067\u30d5\u30a3\u30eb\u30bf\u30ea\u30f3\u30b0\u307e\u305f\u306f\u30bd\u30fc\u30c8\u3059\u308b\u5834\u5408\u306f\u3001\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ea\u30dd\u30b8\u30c8\u30ea\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u5404\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3067\u5b9f\u884c\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002\n -iOS\u30a2\u30ca\u30e9\u30a4\u30b6\u30fc\uff08iLEAPP\uff09\u30e2\u30b8\u30e5\u30fc\u30eb\u3092iOS\u30c7\u30d0\u30a4\u30b9\u306e\u30c7\u30fc\u30bf\u3092\u542b\u3080\u5404\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3067\u5b9f\u884c\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002 diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryExtractAction.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryExtractAction.java index 7965878017..59ff07b86b 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryExtractAction.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DiscoveryExtractAction.java @@ -1,7 +1,7 @@ /* * Autopsy * - * Copyright 2019 Basis Technology Corp. + * Copyright 2019-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -40,8 +40,9 @@ final class DiscoveryExtractAction extends AbstractAction { * * @param selectedFiles The files to extract from the current case. */ + @NbBundle.Messages({"DiscoveryExtractAction.title.extractFiles.text=Extract File"}) DiscoveryExtractAction(Collection selectedFiles) { - super(NbBundle.getMessage(DiscoveryExtractAction.class, "DiscoveryExtractAction.title.extractFiles.text")); + super(Bundle.DiscoveryExtractAction_title_extractFiles_text()); files.addAll(selectedFiles); } diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java index 18ea417423..85afe380a2 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainDetailsPanel.java @@ -96,6 +96,17 @@ final class DomainDetailsPanel extends JPanel { runDomainWorker((DomainArtifactsTabPanel) selectedComponent, true); } else if (!StringUtils.isBlank(domain) && selectedComponent instanceof MiniTimelinePanel) { runMiniTimelineWorker((MiniTimelinePanel) selectedComponent, true); + } else if (selectedComponent instanceof OtherOccurrencesPanel) { + if (CentralRepository.isEnabled()) { + try { + ((OtherOccurrencesPanel) selectedComponent).populateTableForOneType(CentralRepository.getInstance().getCorrelationTypeById(CorrelationAttributeInstance.DOMAIN_TYPE_ID), domain); + } catch (CentralRepoException ex) { + logger.log(Level.INFO, "Central repository exception while trying to get instances by type and value for domain: " + domain, ex); + ((OtherOccurrencesPanel) selectedComponent).reset(); + } + } else { + ((OtherOccurrencesPanel) selectedComponent).reset(); + } } } } diff --git a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainSummaryPanel.java b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainSummaryPanel.java index d78cb5e2f3..661ba0edca 100644 --- a/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainSummaryPanel.java +++ b/Core/src/org/sleuthkit/autopsy/discovery/ui/DomainSummaryPanel.java @@ -33,7 +33,7 @@ import javax.swing.JList; import javax.swing.ListCellRenderer; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.coreutils.ThreadConfined; -import org.sleuthkit.autopsy.datamodel.ContentUtils; +import org.sleuthkit.autopsy.coreutils.TimeZoneUtils; import org.sleuthkit.autopsy.discovery.search.SearchData; /** @@ -180,7 +180,7 @@ class DomainSummaryPanel extends javax.swing.JPanel implements ListCellRenderer< @Override public Component getListCellRendererComponent(JList list, DomainWrapper value, int index, boolean isSelected, boolean cellHasFocus) { domainNameLabel.setText(value.getResultDomain().getDomain()); - TimeZone timeZone = ContentUtils.getTimeZone(value.getResultDomain().getDataSource()); + TimeZone timeZone = TimeZoneUtils.getTimeZone(); String startDate = formatDate(value.getResultDomain().getActivityStart(), timeZone); String endDate = formatDate(value.getResultDomain().getActivityEnd(), timeZone); String notability = Bundle.DomainSummaryPanel_notability_text(); diff --git a/Core/src/org/sleuthkit/autopsy/events/AutopsyEvent.java b/Core/src/org/sleuthkit/autopsy/events/AutopsyEvent.java index c329a03549..7c3a16e5a3 100644 --- a/Core/src/org/sleuthkit/autopsy/events/AutopsyEvent.java +++ b/Core/src/org/sleuthkit/autopsy/events/AutopsyEvent.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2015 Basis Technology Corp. + * Copyright 2015-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,12 +22,18 @@ import java.beans.PropertyChangeEvent; import java.io.Serializable; /** - * A base class for events to be published to registered subscribers on both - * this Autopsy node and other Autopsy nodes. The class extends - * PropertyChangeEvent to integrate with legacy use of JavaBeans - * PropertyChangeEvents and PropertyChangeListeners as an application event - * system, and implements Serializable to allow it to be published over a - * network in serialized form. + * A base class for application events that can be published to registered + * subscribers on both this Autopsy node and other Autopsy nodes. + * + * The 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. + * + * This class implements Serializable to allow it to be published over a network + * in serialized form. */ 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 - * 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 { - LOCAL, REMOTE }; /** - * Constructs an event that can be published to registered subscribers on - * both this Autopsy node and other Autopsy nodes. + * Constructs the base class part of an application event that can be + * published to registered subscribers on both this Autopsy node and other + * Autopsy nodes. * * @param eventName The event name. * @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. */ @@ -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 - * 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). + * Gets the event source type (local or remote) as a string. * - * @return A string, either "LOCAL" or "REMOTE", as an Object. + * @return A string, either "LOCAL" or "REMOTE." */ @Override 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 - * to allow an event to be published both locally and remotely without - * requiring the construction of two separate objects. It is for use by the - * event publishing classes within this package only. + * Sets the source type (local or remote). This field is mutable to allow an + * event to be published both locally and remotely without requiring the + * construction of two separate objects. It is for use by the event + * publishing classes within this package only. * * @param sourceType The source type of the event, local or remote. */ diff --git a/Core/src/org/sleuthkit/autopsy/examples/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/examples/Bundle_ja.properties index 8fc0db1332..d3d8be36fc 100644 --- a/Core/src/org/sleuthkit/autopsy/examples/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/examples/Bundle_ja.properties @@ -1,6 +1,7 @@ +#Mon Jul 12 13:21:59 UTC 2021 SampleContentViewer.jLabel1.text=jLabel1 -SampleIngestModuleFactory.moduleName=\u30b5\u30f3\u30d7\u30eb\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb -SampleIngestModuleFactory.moduleDescription=\u3053\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u306f\u30bd\u30d5\u30c8\u30a6\u30a7\u30a2\u958b\u767a\u8005\u306e\u30b5\u30f3\u30d7\u30eb\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u3068\u3057\u3066\u6a5f\u80fd\u3057\u307e\u3059\u3002 -SampleIngestModuleIngestJobSettingsPanel.skipKnownFilesCheckBox.text=\u65e2\u77e5\u30d5\u30a1\u30a4\u30eb(NSRL)\u3092\u30b9\u30ad\u30c3\u30d7 -SampleIngestModuleFactory.moduleName=\u30b5\u30f3\u30d7\u30eb\u5b9f\u884c\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb SampleExecutableIngestModuleFactory.moduleDescription=\u3053\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u306f\u30bd\u30d5\u30c8\u30a6\u30a7\u30a2\u958b\u767a\u8005\u306e\u30b5\u30f3\u30d7\u30eb\u5b9f\u884c\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u3068\u3057\u3066\u6a5f\u80fd\u3057\u307e\u3059\u3002 +SampleExecutableIngestModuleFactory.moduleName=\u5b9f\u884c\u306a\u53d6\u8fbc\u307f\u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u30b5\u30f3\u30d7\u30eb +SampleIngestModuleFactory.moduleDescription=\u3053\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u306f\u30bd\u30d5\u30c8\u30a6\u30a7\u30a2\u958b\u767a\u8005\u306e\u30b5\u30f3\u30d7\u30eb\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u3068\u3057\u3066\u6a5f\u80fd\u3057\u307e\u3059\u3002 +SampleIngestModuleFactory.moduleName=\u30b5\u30f3\u30d7\u30eb\u5b9f\u884c\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb +SampleIngestModuleIngestJobSettingsPanel.skipKnownFilesCheckBox.text=\u65e2\u77e5\u30d5\u30a1\u30a4\u30eb(NSRL)\u3092\u30b9\u30ad\u30c3\u30d7 diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/filesearch/Bundle.properties-MERGED index 93c5ed7987..4f0fdfbb56 100755 --- a/Core/src/org/sleuthkit/autopsy/filesearch/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/filesearch/Bundle.properties-MERGED @@ -16,7 +16,7 @@ KnownStatusSearchPanel.knownCheckBox.text=Known Status: KnownStatusSearchPanel.knownBadOptionCheckBox.text=Notable KnownStatusSearchPanel.knownOptionCheckBox.text=Known (NSRL or other) 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.jLabel4.text=Timezone: 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.validationErr.msg=Validation Error: {0} 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. SizeSearchPanel.sizeCompareComboBox.equalTo=equal to SizeSearchPanel.sizeCompareComboBox.greaterThan=greater than diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/filesearch/Bundle_ja.properties index fdcdd76516..fc9aafb082 100644 --- a/Core/src/org/sleuthkit/autopsy/filesearch/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/filesearch/Bundle_ja.properties @@ -1,10 +1,11 @@ -#Fri Feb 12 16:56:28 UTC 2021 +#Mon Jul 12 13:21:59 UTC 2021 DataSourceFilter.errorMessage.emptyDataSource=\u5c11\u306a\u304f\u3068\u30821\u3064\u306e\u30c7\u30fc\u30bf\u30bf\u30a4\u30d7\u306e\u30c1\u30a7\u30c3\u30af\u30dc\u30c3\u30af\u30b9\u3092\u9078\u629e\u3057\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002 DataSourcePanel.dataSourceCheckBox.actionCommand=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\: DataSourcePanel.dataSourceCheckBox.label=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\: DataSourcePanel.dataSourceCheckBox.text=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\: DataSourcePanel.dataSourceNoteLabel.text=*\u6ce8\: \u8907\u6570\u306e\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u9078\u629e\u3067\u304d\u307e\u3059 DateSearchFilter.errorMessage.endDateBeforeStartDate=\u7d42\u4e86\u65e5\u306f\u958b\u59cb\u65e5\u3088\u308a\u5f8c\u306e\u65e5\u4ed8\u3067\u3042\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002 +DateSearchFilter.errorMessage.noCheckboxSelected=1\u3064\u4ee5\u4e0a\u306e\u65e5\u4ed8\u30bf\u30a4\u30d7\u30c1\u30a7\u30c3\u30af\u30dc\u30c3\u30af\u30b9\u3092\u9078\u629e\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002 DateSearchFilter.noneSelectedMsg.text=\u5c11\u306a\u304f\u3068\u30821\u3064\u306e\u30c7\u30fc\u30bf\u30bf\u30a4\u30d7\u3092\u9078\u629e\u3057\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\! DateSearchPanel.accessedCheckBox.text=\u30a2\u30af\u30bb\u30b9\u6e08\u307f DateSearchPanel.changedCheckBox.text=\u5909\u66f4\u6e08\u307f diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/geolocation/Bundle_ja.properties index 9dd5146a27..2fddebc176 100644 --- a/Core/src/org/sleuthkit/autopsy/geolocation/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/geolocation/Bundle_ja.properties @@ -1,16 +1,29 @@ -#Fri Feb 12 16:56:28 UTC 2021 +#Mon Jul 12 13:21:59 UTC 2021 +CTL_GeolocationTopComponent=\u30b8\u30aa\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3 +CTL_GeolocationTopComponentAction=GeolocationTopComponent +CTL_OpenGeolocation=\u30b8\u30aa\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3 GLTopComponent_No_dataSource_Title=\u30b8\u30aa\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3\u30fb\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u306f\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f GLTopComponent_No_dataSource_message=\u30b8\u30aa\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u3092\u542b\u3080\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u306f\u3042\u308a\u307e\u305b\u3093\u3002 GLTopComponent_initilzation_error=\u30a6\u30a7\u30a4\u30dd\u30a4\u30f3\u30c8\u306e\u521d\u671f\u5316\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 \u4f4d\u7f6e\u60c5\u5831\u30c7\u30fc\u30bf\u304c\u4e0d\u5b8c\u5168\u3067\u3042\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 +GLTopComponent_name=\u30b8\u30aa\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3 GeoFilterPanel.allButton.text=\u5168\u3066 +GeoFilterPanel.applyButton.text=\u9069\u7528\u3059\u308b +GeoFilterPanel.daysLabel.text=\u6d3b\u52d5\u306e\u65e5\u6570 GeoFilterPanel.mostRecentButton.text=\u6700\u5f8c\u306e\u307f GeoFilterPanel.optionsLabel.text=\u65e5\u4ed8 GeoFilterPanel.showLabel.text=\u8868\u793a\uff1a GeoFilterPanel.showLabel.toolTipText=\u8868\u793a\uff1a +GeoFilterPanel.showWaypointsWOTSCheckBox.text=\u30bf\u30a4\u30e0\u30b9\u30bf\u30f3\u30d7\u306e\u306a\u3044\u30a6\u30a7\u30a4\u30dd\u30a4\u30f3\u30c8\u3092\u542b\u3081\u308b GeoFilterPanel_ArtifactType_List_Title=\u30bf\u30a4\u30d7 +GeoFilterPanel_DataSource_List_Title=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9 GeoFilterPanel_empty_artifactType=\u30d5\u30a3\u30eb\u30bf\u30fc\u3092\u9069\u7528\u3067\u304d\u307e\u305b\u3093\u30021\u3064\u4ee5\u4e0a\u306e\u6848\u4ef6\u30bf\u30a4\u30d7\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002 GeoFilterPanel_empty_dataSource=\u30d5\u30a3\u30eb\u30bf\u3092\u9069\u7528\u3067\u304d\u307e\u305b\u3093\u30021\u3064\u4ee5\u4e0a\u306e\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002 +GeoTopComponent_filer_data_invalid_Title=\u30d5\u30a3\u30eb\u30bf\u30fc\u30a8\u30e9\u30fc +GeoTopComponent_filer_data_invalid_msg=\u30a6\u30a7\u30a4\u30dd\u30a4\u30f3\u30c8\u30d5\u30a3\u30eb\u30bf\u30fc\u3092\u5b9f\u884c\u3067\u304d\u307e\u305b\u3093\u3002\n1\u3064\u4ee5\u4e0a\u306e\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002 +GeoTopComponent_filter_exception_Title=\u30d5\u30a3\u30eb\u30bf\u30fc\u30a8\u30e9\u30fc GeoTopComponent_filter_exception_msg=\u30a6\u30a7\u30a4\u30dd\u30a4\u30f3\u30c8\u306e\u30d5\u30a3\u30eb\u30bf\u30ea\u30f3\u30b0\u4e2d\u306b\u4f8b\u5916\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +GeoTopComponent_no_waypoints_returned_Title=\u30a6\u30a7\u30a4\u30dd\u30a4\u30f3\u30c8\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093 +GeoTopComponent_no_waypoints_returned_mgs=\u9069\u7528\u3055\u308c\u305f\u30d5\u30a3\u30eb\u30bf\u30fc\u306f\u3001\u57fa\u6e96\u306b\u4e00\u81f4\u3059\u308b\u30a6\u30a7\u30a4\u30dd\u30a4\u30f3\u30c8\u3092\u898b\u3064\u3051\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002\n\u30d5\u30a3\u30eb\u30bf\u30aa\u30d7\u30b7\u30e7\u30f3\u3092\u4fee\u6b63\u3057\u3066\u3001\u518d\u8a66\u884c\u3057\u3066\u304f\u3060\u3055\u3044\u3002 GeolocationSettingsPanel.defaultDataSource.text=\u30c7\u30d5\u30a9\u30eb\u30c8\u306e\u30aa\u30f3\u30e9\u30a4\u30f3\u30fb\u30bf\u30a4\u30eb\u30b5\u30fc\u30d0\u30fc\uff08bing.com/maps\uff09 GeolocationSettingsPanel.mbtileTestBtn.text=\u30c6\u30b9\u30c8 GeolocationSettingsPanel.mbtilesBrowseBtn.text=\u30d6\u30e9\u30a6\u30ba @@ -22,7 +35,11 @@ GeolocationSettingsPanel.zipFileBrowseBnt.text=\u30d6\u30e9\u30a6\u30ba GeolocationSettingsPanel.zipFileRBnt.actionCommand=OpenStreetMap\u30bf\u30a4\u30eb\u306eZIP\u30d5\u30a1\u30a4\u30eb GeolocationSettingsPanel.zipFileRBnt.text=OpenStreetMap zip\u30d5\u30a1\u30a4\u30eb GeolocationSettingsPanel_malformed_url_message=\u300c\u6307\u5b9a\u3055\u308c\u305fOSM\u30bf\u30a4\u30eb\u30b5\u30fc\u30d0\u30fc\u30a2\u30c9\u30ec\u30b9\u306f\u7121\u52b9\u3067\u3059\u3002\n\u5148\u982d\u306bhttp\uff1a//\u304c\u4ed8\u3044\u305f\u5f62\u5f0f\u306eURL\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044 +GeolocationSettingsPanel_malformed_url_message_tile=\u4e0d\u6b63\u5f62\u5f0f\u306eURL +GeolocationSettingsPanel_osm_server_test_fail_message=OSM\u30bf\u30a4\u30eb\u30b5\u30fc\u30d0\u30fc\u306e\u30c6\u30b9\u30c8\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002\n\u30b5\u30fc\u30d0\u30fc\u306b\u63a5\u7d9a\u3067\u304d\u307e\u305b\u3093\u3002 +GeolocationSettingsPanel_osm_server_test_fail_message_title=\u30a8\u30e9\u30fc GeolocationSettingsPanel_osm_server_test_success_message=\u6307\u5b9a\u3055\u308c\u305fOSM\u30bf\u30a4\u30eb\u30b5\u30fc\u30d0\u30fc\u30a2\u30c9\u30ec\u30b9\u306f\u6709\u52b9\u3067\u3059\u3002 +GeolocationSettingsPanel_osm_server_test_success_message_title=\u6210\u529f GeolocationSettings_mbtile_does_not_exist_message=\u63d0\u4f9b\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb\u306f\u5b58\u5728\u3057\u307e\u305b\u3093\u3002\n\u30d5\u30a1\u30a4\u30eb\u304c\u5b58\u5728\u3059\u308b\u3053\u3068\u3092\u78ba\u8a8d\u3057\u3066\u3001\u3082\u3046\u4e00\u5ea6\u304a\u8a66\u3057\u304f\u3060\u3055\u3044\u3002 GeolocationSettings_mbtile_does_not_exist_title=\u30d5\u30a1\u30a4\u30eb\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093 GeolocationSettings_mbtile_not_valid_message=\u63d0\u4f9b\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb\u306fraster tile\u30d5\u30a1\u30a4\u30eb\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002 @@ -32,8 +49,21 @@ GeolocationSettings_mbtile_test_success_title=\u6210\u529f GeolocationSettings_path_not_valid_message=\u63d0\u4f9b\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb\u30d1\u30b9\u306f\u7a7a\u3067\u3059\u3002\n\u6709\u52b9\u306a\u30d5\u30a1\u30a4\u30eb\u30d1\u30b9\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 GeolocationSettings_path_not_valid_title=\u30d5\u30a1\u30a4\u30eb\u304c\u7121\u52b9\u3067\u3059 GeolocationTC_KML_report_title=KML\u30ec\u30dd\u30fc\u30c8 +GeolocationTC_connection_failure_message=\u30de\u30c3\u30d7\u30bf\u30a4\u30c8\u30eb\u30bd\u30fc\u30b9\u3078\u306e\u63a5\u7d9a\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002\n\u300c\u30aa\u30d7\u30b7\u30e7\u30f3\u300d\u30c0\u30a4\u30a2\u30ed\u30b0\u3067\u30de\u30c3\u30d7\u30bd\u30fc\u30b9\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002 +GeolocationTC_connection_failure_message_title=\u63a5\u7d9a\u30a8\u30e9\u30fc GeolocationTC_empty_waypoint_message=\u30a6\u30a7\u30a4\u30dd\u30a4\u30f3\u30c8\u304c\u306a\u3044\u305f\u3081\u3001KML\u30ec\u30dd\u30fc\u30c8\u3092\u751f\u6210\u3067\u304d\u307e\u305b\u3093\u3002\nKML\u30ec\u30dd\u30fc\u30c8\u3092\u751f\u6210\u3059\u308b\u524d\u306b\u30a6\u30a7\u30a4\u30dd\u30a4\u30f3\u30c8\u304c\u8868\u793a\u3055\u308c\u3066\u3044\u308b\u3053\u3068\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044 GeolocationTC_report_progress_title=KML\u30ec\u30dd\u30fc\u30c8\u306e\u9032\u884c\u72b6\u6cc1 GeolocationTopComponent.WaypointFetcher.onErrorDescription=\u4e00\u90e8\u306eGPS\u30c8\u30e9\u30c3\u30af\u30c7\u30fc\u30bf\u306e\u53ce\u96c6\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u305f\u306e\u3067\u305d\u306e\u7d50\u679c\u306f\u9664\u5916\u3055\u308c\u307e\u3057\u305f\u3002 GeolocationTopComponent.WaypointFetcher.onErrorTitle=GPS\u30c8\u30e9\u30c3\u30af\u30c7\u30fc\u30bf\u306e\u53ce\u96c6\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f GeolocationTopComponent.reportButton.text=KML\u30ec\u30dd\u30fc\u30c8 +HidingPane_default_title=\u30d5\u30a3\u30eb\u30bf\u30fc +MapPanel_connection_failure_message=\u65b0\u3057\u3044\u30b8\u30aa\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3\u30fb\u30de\u30c3\u30d7\u30bf\u30a4\u30eb\u30bd\u30fc\u30b9\u3078\u306e\u63a5\u7d9a\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 +MapPanel_connection_failure_message_title=\u63a5\u7d9a\u30a8\u30e9\u30fc +MayWaypoint_ExternalViewer_label=ExternalViewer\u3067\u958b\u304f +OpenGeolocationAction_displayName=\u30b8\u30aa\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3 +OpenGeolocationAction_name=\u30b8\u30aa\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3 +OptionsCategory_Keywords_Geolocation=\u30b8\u30aa\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3 +OptionsCategory_Name_Geolocation=\u30b8\u30aa\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3 +RefreshPanel.refreshButton.text=\u30d3\u30e5\u30fc\u3092\u66f4\u65b0 +RefreshPanel.refreshLabel.text=\u30b8\u30aa\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3\u30c7\u30fc\u30bf\u304c\u66f4\u65b0\u3055\u308c\u307e\u3057\u305f\u3002\u8868\u793a\u304c\u53e4\u304f\u306a\u3063\u3066\u3044\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 +WaypointExtractAction_label=\u30d5\u30a1\u30a4\u30eb\u3092\u62bd\u51fa diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Bundle_ja.properties index 8e7c6dfdc5..1f6f9209c9 100644 --- a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Bundle_ja.properties @@ -1,6 +1,12 @@ -#Fri Feb 12 16:56:28 UTC 2021 +#Mon Jul 12 13:21:59 UTC 2021 GEOArea_point_label_header=\u30a8\u30ea\u30a2{0}\u306e\u30a2\u30a6\u30c8\u30e9\u30a4\u30f3\u30dd\u30a4\u30f3\u30c8 GEOTrack_point_label_header=\u30c8\u30e9\u30c3\u30af\u306e\u30c8\u30e9\u30c3\u30af\u30dd\u30a4\u30f3\u30c8\uff1a{0} +LastKnownWaypoint_Label=\u6700\u7d42\u306b\u8a8d\u8b58\u3055\u308c\u305f\u4f4d\u7f6e +Route_End_Label=\u7d42\u4e86 +Route_Label=\u76f4\u7dda\u30eb\u30fc\u30c8 +Route_Start_Label=\u30b9\u30bf\u30fc\u30c8 Route_point_label=\u30eb\u30fc\u30c8\u306e\u30a6\u30a7\u30a4\u30dd\u30a4\u30f3\u30c8 +SearchWaypoint_DisplayLabel=GPS\u691c\u7d22 Track_distanceFromHome_displayName=\u539f\u70b9\u304b\u3089\u306e\u8ddd\u96e2 Track_distanceTraveled_displayName=\u8d70\u884c\u8ddd\u96e2 +TrackpointWaypoint_DisplayLabel=GPS\u30c8\u30e9\u30c3\u30af\u30dd\u30a4\u30f3\u30c8 diff --git a/Core/src/org/sleuthkit/autopsy/healthmonitor/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/healthmonitor/Bundle_ja.properties index 3d4b8de948..5d3d334a63 100644 --- a/Core/src/org/sleuthkit/autopsy/healthmonitor/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/healthmonitor/Bundle_ja.properties @@ -1,4 +1,4 @@ -#Fri Feb 12 16:56:28 UTC 2021 +#Mon Jul 12 13:21:59 UTC 2021 HealthMonitorDashboard.DateRange.oneDay=1\u65e5 HealthMonitorDashboard.DateRange.oneMonth=1\u30f5\u6708 HealthMonitorDashboard.DateRange.oneWeek=1\u9031\u9593 @@ -22,6 +22,7 @@ HealthMonitorDashboard.display.errorCreatingDashboard=\u6b63\u5e38\u6027\u30e2\u HealthMonitorDashboard.updateTimingMetricGraphs.noData=\u8868\u793a\u3059\u308b\u30c7\u30fc\u30bf\u304c\u3042\u308a\u307e\u305b\u3093 HealthMonitorDashboard.updateUserMetricGraphs.noData=\u8868\u793a\u3059\u308b\u30c7\u30fc\u30bf\u304c\u3042\u308a\u307e\u305b\u3093 TimeZonePanel.title=\u6b21\u306e\u5358\u4f4d\u3067\u6642\u523b\u3092\u8868\u793a\: +TimingMetricGraphPanel.paintComponent.displayingTime=\u8868\u793a\u3059\u308b\u6642\u9593\u306f TimingMetricGraphPanel.paintComponent.hours=\u6642 TimingMetricGraphPanel.paintComponent.microseconds=\u30de\u30a4\u30af\u30ed\u79d2 TimingMetricGraphPanel.paintComponent.milliseconds=\u30df\u30ea\u79d2 diff --git a/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties-MERGED index 65d3ba064d..621713dfdf 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties-MERGED @@ -142,7 +142,7 @@ IngestJob.cancelReason.outOfDiskSpace.text=Out of disk space IngestJob.cancelReason.servicesDown.text=Services Down IngestJob.cancelReason.caseClosed.text=Case closed IngestJobSettingsPanel.globalSettingsButton.text=Global Settings -gest +gest= IngestJobSettingsPanel.globalSettingsButton.actionCommand=Advanced IngestJobSettingsPanel.globalSettingsButton.text=Global Settings IngestJobSettingsPanel.pastJobsButton.text=History diff --git a/Core/src/org/sleuthkit/autopsy/ingest/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/ingest/Bundle_ja.properties index 57e96f90d4..1456e6922a 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/ingest/Bundle_ja.properties @@ -1,4 +1,4 @@ -#Fri Feb 12 16:56:28 UTC 2021 +#Mon Jul 12 13:22:00 UTC 2021 CTL_IngestMessageTopComponent=\u30e1\u30c3\u30bb\u30fc\u30b8 CTL_RunIngestAction=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u3092\u5b9f\u884c DataSourceIngestCancellationPanel.cancelAllModulesRadioButton.text=\u3059\u3079\u3066\u306e\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u53d6\u308a\u6d88\u3059 @@ -7,6 +7,7 @@ DataSourceIngestPipeline.moduleError.title.text={0} \u30a8\u30e9\u30fc FileIngestCancellationPanel.cancelFileIngestRadioButton.text=\u30d5\u30a1\u30a4\u30eb\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u306e\u307f\u3092\u53d6\u308a\u6d88\u3059 FileIngestCancellationPanel.cancelIngestJobRadioButton.text=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u3068\u30d5\u30a1\u30a4\u30eb\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u3092\u53d6\u308a\u6d88\u3059 FileIngestPipeline.moduleError.title.text={0} \u30a8\u30e9\u30fc +FileIngestPipeline_SaveResults_Activity=\u7d50\u679c\u306e\u4fdd\u5b58 HINT_IngestMessageTopComponent=\u30e1\u30c3\u30bb\u30fc\u30b8\u30a6\u30a3\u30f3\u30c9\u30a6 IngestDialog.closeButton.title=\u7d42\u4e86 IngestDialog.startButton.title=\u958b\u59cb @@ -66,6 +67,7 @@ IngestManager.startupErr.dlgTitle=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30 IngestMessage.exception.srcSubjDetailsDataNotNull.msg=\u30bd\u30fc\u30b9\u3001\u4ef6\u540d\u3001\u8a73\u7d30\u304a\u3088\u3073\u30c7\u30fc\u30bf\u3092null\u306b\u3059\u308b\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093 IngestMessage.exception.srcSubjNotNull.msg=\u30bd\u30fc\u30b9\u3068\u4ef6\u540d\u3092null\u306b\u3059\u308b\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093 IngestMessage.exception.typeSrcSubjNotNull.msg=\u30e1\u30c3\u30bb\u30fc\u30b8\u30bf\u30a4\u30d7\u3001\u30bd\u30fc\u30b9\u304a\u3088\u3073\u4ef6\u540d\u3092null\u306b\u3059\u308b\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093 +IngestMessage.toString.data.text=\u30c7\u30fc\u30bf\uff1a{0} IngestMessage.toString.date.text=\ \u30c7\u30fc\u30bf\: {0} IngestMessage.toString.details.text=\ \u8a73\u7d30\: {0} IngestMessage.toString.subject.text=\ \u4ef6\u540d\: {0} diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestJobPipeline.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobPipeline.java index 384f5c63c5..392789a33e 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestJobPipeline.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobPipeline.java @@ -21,9 +21,11 @@ package org.sleuthkit.autopsy.ingest; import java.util.ArrayList; import java.util.Collections; import java.util.Date; +import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.atomic.AtomicLong; @@ -31,6 +33,7 @@ import java.util.logging.Level; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Stream; +import javax.annotation.concurrent.GuardedBy; import javax.swing.JOptionPane; import org.netbeans.api.progress.ProgressHandle; import org.openide.util.Cancellable; @@ -188,6 +191,16 @@ final class IngestJobPipeline { */ private final long createTime; + /* + * An ingest pipeline allows ingest module pipelines to register and + * unregister the ingest thread they are running in when a scheduled ingest + * pause occurs and the threads are made to sleep. This allows interruption + * of these threads if the ingest job is canceled. + */ + private final Object threadRegistrationLock = new Object(); + @GuardedBy("threadRegistrationLock") + private final Set pausedIngestThreads = new HashSet<>(); + /** * Constructs an object that encapsulates a data source and the ingest * module pipelines used to analyze it. @@ -582,8 +595,7 @@ final class IngestJobPipeline { break; } } - } - + } return errors; } @@ -1275,6 +1287,13 @@ final class IngestJobPipeline { } } + synchronized (threadRegistrationLock) { + for (Thread thread : pausedIngestThreads) { + thread.interrupt(); + } + pausedIngestThreads.clear(); + } + // If a data source had no tasks in progress it may now be complete. checkForStageCompleted(); } @@ -1410,4 +1429,29 @@ final class IngestJobPipeline { cancelled, cancellationReason, cancelledDataSourceIngestModules, processedFilesCount, estimatedFilesToProcessCount, snapShotTime, tasksSnapshot); } + + /** + * Registers a sleeping ingest thread so that it can be interrupted if the + * ingest job is cancelled. + * + * @param thread The ingest thread. + */ + void registerPausedIngestThread(Thread thread) { + synchronized (threadRegistrationLock) { + pausedIngestThreads.add(thread); + } + } + + /** + * Unregisters a sleeping ingest thread that was registered so that it could + * be interrupted if the ingest job was cancelled. + * + * @param thread The ingest thread. + */ + void unregisterPausedIngestThread(Thread thread) { + synchronized (threadRegistrationLock) { + pausedIngestThreads.remove(thread); + } + } + } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestTaskPipeline.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestTaskPipeline.java index 8264c4fcc9..aafbdb14fa 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestTaskPipeline.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestTaskPipeline.java @@ -18,11 +18,18 @@ */ package org.sleuthkit.autopsy.ingest; +import static java.lang.Thread.sleep; +import java.time.DayOfWeek; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Optional; +import java.util.concurrent.TimeUnit; +import java.util.logging.Level; import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; /** @@ -36,6 +43,7 @@ import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; */ abstract class IngestTaskPipeline { + private static final Logger logger = Logger.getLogger(IngestTaskPipeline.class.getName()); private final IngestJobPipeline ingestJobPipeline; private final List moduleTemplates; private final List> modules; @@ -171,6 +179,10 @@ abstract class IngestTaskPipeline { List performTask(T task) { List errors = new ArrayList<>(); if (!this.ingestJobPipeline.isCancelled()) { + pauseIfScheduled(); + if (ingestJobPipeline.isCancelled()) { + return errors; + } try { prepareTask(task); } catch (IngestTaskPipelineException ex) { @@ -178,6 +190,10 @@ abstract class IngestTaskPipeline { return errors; } for (PipelineModule module : modules) { + pauseIfScheduled(); + if (ingestJobPipeline.isCancelled()) { + break; + } try { currentModule = module; currentModule.setProcessingStartTime(); @@ -199,6 +215,55 @@ abstract class IngestTaskPipeline { return errors; } + /** + * Pauses task execution if ingest has been configured to be paused weekly + * at a specified time for a specified duration. + */ + private void pauseIfScheduled() { + if (ScheduledIngestPauseSettings.getPauseEnabled() == true) { + /* + * Calculate the date/time for the scheduled pause start by + * "normalizing" the day of week to the current week and then + * adjusting the hour and minute to match the scheduled hour and + * minute. + */ + LocalDateTime pauseStart = LocalDateTime.now(); + DayOfWeek pauseDayOfWeek = ScheduledIngestPauseSettings.getPauseDayOfWeek(); + while (pauseStart.getDayOfWeek() != pauseDayOfWeek) { + pauseStart = pauseStart.minusDays(1); + } + pauseStart = pauseStart.withHour(ScheduledIngestPauseSettings.getPauseStartTimeHour()); + pauseStart = pauseStart.withMinute(ScheduledIngestPauseSettings.getPauseStartTimeMinute()); + pauseStart = pauseStart.withSecond(0); + + /* + * Calculate the pause end date/time. + */ + LocalDateTime pauseEnd = pauseStart.plusMinutes(ScheduledIngestPauseSettings.getPauseDurationMinutes()); + + /* + * Check whether the current date/time is in the pause interval. If + * it is, register the ingest thread this code is running in so it + * can be interrupted if the job is canceled, and sleep until + * whatever time remains in the pause interval has expired. + */ + LocalDateTime timeNow = LocalDateTime.now(); + if ((timeNow.equals(pauseStart) || timeNow.isAfter(pauseStart)) && timeNow.isBefore(pauseEnd)) { + ingestJobPipeline.registerPausedIngestThread(Thread.currentThread()); + try { + long timeRemainingMillis = ChronoUnit.MILLIS.between(timeNow, pauseEnd); + logger.log(Level.INFO, String.format("%s pausing at %s for ~%d minutes", Thread.currentThread().getName(), LocalDateTime.now(), TimeUnit.MILLISECONDS.toMinutes(timeRemainingMillis))); + sleep(timeRemainingMillis); + logger.log(Level.INFO, String.format("%s resuming at %s", Thread.currentThread().getName(), LocalDateTime.now())); + } catch (InterruptedException notLogged) { + logger.log(Level.INFO, String.format("%s resuming at %s due to sleep interrupt (ingest job canceled)", Thread.currentThread().getName(), LocalDateTime.now())); + } finally { + ingestJobPipeline.unregisterPausedIngestThread(Thread.currentThread()); + } + } + } + } + /** * Gets the currently running module. * @@ -246,6 +311,7 @@ abstract class IngestTaskPipeline { } running = false; return errors; + } /** diff --git a/Core/src/org/sleuthkit/autopsy/ingest/ScheduledIngestPauseSettings.java b/Core/src/org/sleuthkit/autopsy/ingest/ScheduledIngestPauseSettings.java new file mode 100755 index 0000000000..b85bc00de0 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/ingest/ScheduledIngestPauseSettings.java @@ -0,0 +1,187 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2014-2021 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may 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.ingest; + +import com.google.common.annotations.Beta; +import java.time.DayOfWeek; +import java.util.prefs.Preferences; +import org.openide.util.NbPreferences; + +/** + * Settings that allow ingest jobs in progress to be paused weekly at a + * specified time for a specified duration. Because ingest job execution is a + * variable time activity, it is also possible to specify a window after the + * specified pause time in which the pause should still occur. + * + * THIS IS A BETA CLASS AND IS SUBJECT TO CHANGE OR DELETION. + */ +@Beta +public class ScheduledIngestPauseSettings { + + /* + * These properties are stored in the core.properties file in the user's + * config\Preferences\org\sleuthkit\autopsy directory. + */ + private static final Preferences preferences = NbPreferences.forModule(ScheduledIngestPauseSettings.class); + private static final String PAUSE_ENABLED_KEY = "IngestPauseEnabled"; + private static final boolean DEFAULT_ENABLED_VALUE = false; + private static final String PAUSE_DAY_OF_WEEK_KEY = "IngestPauseDayOfWeek"; + private static final String PAUSE_TIME_HOUR_KEY = "IngestPauseTimeHour"; + private static final String PAUSE_TIME_MINUTES_KEY = "IngestPauseTimeMinutes"; + private static final String PAUSE_DURATION_MINUTES_KEY = "IngestPauseDurationMinutes"; + private static final int DEFAULT_TIME_VALUE = 0; + private static final int DEFAULT_PAUSE_DURATION_VALUE = 60; + + /** + * Gets whether or not a scheduled ingest pause is enabled. + * + * @return True or false. The default value is false. + * + * THIS IS A BETA METHOD AND IS SUBJECT TO CHANGE OR DELETION. + */ + public static boolean getPauseEnabled() { + return preferences.getBoolean(PAUSE_ENABLED_KEY, DEFAULT_ENABLED_VALUE); + } + + /** + * Sets whether or not a scheduled ingest pause is enabled. + * + * @param enabled True or false. + * + * THIS IS A BETA METHOD AND IS SUBJECT TO CHANGE OR DELETION. + */ + public static void setPauseEnabled(boolean enabled) { + preferences.putBoolean(PAUSE_ENABLED_KEY, enabled); + } + + /** + * Gets the day of the week when ingest should pause. + * + * @return The day of the week. The default value is Sunday. + * + * THIS IS A BETA METHOD AND IS SUBJECT TO CHANGE OR DELETION. + */ + @Beta + public static DayOfWeek getPauseDayOfWeek() { + int dayOfWeek = preferences.getInt(PAUSE_DAY_OF_WEEK_KEY, DayOfWeek.SUNDAY.getValue()); + return DayOfWeek.of(dayOfWeek); + } + + /** + * Sets the day of the week when ingest should pause. + * + * @param dayOfWeek The day of the week as an integer in the range 1-7. + * + * THIS IS A BETA METHOD AND IS SUBJECT TO CHANGE OR DELETION. + */ + @Beta + public static void setPauseDayOfWeek(DayOfWeek dayOfWeek) { + preferences.putInt(PAUSE_DAY_OF_WEEK_KEY, dayOfWeek.getValue()); + } + + /** + * Gets the hour of the time of day when ingest should pause. + * + * @return The hour as an integer in the range of 0-23. The default value is + * zero. + * + * THIS IS A BETA METHOD AND IS SUBJECT TO CHANGE OR DELETION. + */ + @Beta + public static int getPauseStartTimeHour() { + return preferences.getInt(PAUSE_TIME_HOUR_KEY, DEFAULT_TIME_VALUE); + } + + /** + * Sets the hour of the time of day when ingest should pause. + * + * @param hour The hour of the time of day as an integer in the range of + * 0-23. + * + * THIS IS A BETA METHOD AND IS SUBJECT TO CHANGE OR DELETION. + */ + @Beta + public static void setPauseStartTimeHour(int hour) { + if (hour < 0 || hour > 23) { + throw new IllegalArgumentException("hour must be 0-23"); + } + preferences.putInt(PAUSE_TIME_HOUR_KEY, hour); + } + + /** + * Gets the minutes of the time of day when ingest should pause. + * + * @return The minutes of the time of day as an integer in the range of + * 0-59. The default value is zero. + * + * THIS IS A BETA METHOD AND IS SUBJECT TO CHANGE OR DELETION. + */ + @Beta + public static int getPauseStartTimeMinute() { + return preferences.getInt(PAUSE_TIME_MINUTES_KEY, DEFAULT_TIME_VALUE); + } + + /** + * Sets the minutes of the time of day when ingest should pause. + * + * @param timeInMinutes The minutes of the time of day as an integer in the + * range of 0-59. + * + * THIS IS A BETA METHOD AND IS SUBJECT TO CHANGE OR DELETION. + */ + @Beta + public static void setPauseStartTimeMinute(int timeInMinutes) { + if (timeInMinutes < 0 || timeInMinutes > 59) { + throw new IllegalArgumentException("timeInMinutes must be 0-59"); + } + preferences.putInt(PAUSE_TIME_MINUTES_KEY, timeInMinutes); + } + + /** + * Gets the duration of the ingest pause in minutes. + * + * @return The duration in minutes. The default value is 60. + * + * THIS IS A BETA METHOD AND IS SUBJECT TO CHANGE OR DELETION. + */ + @Beta + public static int getPauseDurationMinutes() { + return preferences.getInt(PAUSE_DURATION_MINUTES_KEY, DEFAULT_PAUSE_DURATION_VALUE); + } + + /** + * Sets the duration of the ingest pause in minutes. + * + * @param durationInMinutes The duration in minutes. + * + * THIS IS A BETA METHOD AND IS SUBJECT TO CHANGE OR DELETION. + */ + @Beta + public static void setPauseDurationMinutes(int durationInMinutes) { + preferences.putInt(PAUSE_DURATION_MINUTES_KEY, durationInMinutes); + } + + /** + * Private constructor to prevent utilit bclass instantiation. + */ + @Beta + private ScheduledIngestPauseSettings() { + } + +} diff --git a/Core/src/org/sleuthkit/autopsy/keywordsearchservice/KeywordSearchService.java b/Core/src/org/sleuthkit/autopsy/keywordsearchservice/KeywordSearchService.java index 981abe05de..6c2997ccec 100644 --- a/Core/src/org/sleuthkit/autopsy/keywordsearchservice/KeywordSearchService.java +++ b/Core/src/org/sleuthkit/autopsy/keywordsearchservice/KeywordSearchService.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2015-2019 Basis Technology Corp. + * Copyright 2015-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.keywordsearchservice; +import com.google.common.annotations.Beta; import java.io.Closeable; import java.io.IOException; import org.sleuthkit.autopsy.casemodule.CaseMetadata; @@ -105,5 +106,4 @@ public interface KeywordSearchService extends Closeable { * @throws KeywordSearchServiceException if unable to delete. */ void deleteDataSource(Long dataSourceId) throws KeywordSearchServiceException; - } diff --git a/Core/src/org/sleuthkit/autopsy/livetriage/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/livetriage/Bundle_ja.properties index 7697652315..49a39a0fcd 100644 --- a/Core/src/org/sleuthkit/autopsy/livetriage/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/livetriage/Bundle_ja.properties @@ -1,3 +1,26 @@ -#Fri Feb 12 16:56:28 UTC 2021 +#Mon Jul 12 13:22:00 UTC 2021 +CTL_CreateLiveTriageDriveAction=\u30e9\u30a4\u30d6\u30fb\u30c8\u30ea\u30a2\u30fc\u30b8\u30fb\u30c9\u30e9\u30a4\u30d6\u3092\u4f5c\u6210\u3059\u308b +CopyFilesWorker.done.text=\u30e9\u30a4\u30d6\u30fb\u30c8\u30ea\u30a2\u30fc\u30b8\u30fb\u30c7\u30a3\u30b9\u30af\u306e\u4f5c\u6210\u304c\u5b8c\u4e86\u3057\u307e\u3057\u305f +CopyFilesWorker.error.text=\u30e9\u30a4\u30d6\u30fb\u30c8\u30ea\u30a2\u30fc\u30b8\u30fb\u30d5\u30a1\u30a4\u30eb\u306e\u30b3\u30d4\u30fc\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +CreateLiveTriageDriveAction.appPathError.message=\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u30fb\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093 +CreateLiveTriageDriveAction.batchFileError.message=\u30d0\u30c3\u30c1\u30d5\u30a1\u30a4\u30eb\u306e\u4f5c\u6210\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +CreateLiveTriageDriveAction.copyError.message=\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3092\u30b3\u30d4\u30fc\u3067\u304d\u307e\u305b\u3093\u3002 \u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3055\u308c\u305f\u30d0\u30fc\u30b8\u30e7\u30f3\u306e\u307f\u3067\u6a5f\u80fd\u3057\u307e\u3059\u3002 +CreateLiveTriageDriveAction.error.title=\u30e9\u30a4\u30d6\u30fb\u30c8\u30ea\u30a2\u30fc\u30b8\u30fb\u30c7\u30a3\u30b9\u30af\u306e\u4f5c\u6210\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +CreateLiveTriageDriveAction.exenotfound.message=\u5b9f\u884c\u30d5\u30a1\u30a4\u30eb\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093 +CreateLiveTriageDriveAction.progressBar.text=\u30e9\u30a4\u30d6\u30fb\u30c8\u30ea\u30a2\u30fc\u30b8\u30fb\u30d5\u30a1\u30a4\u30eb\u3092{0}\u306b\u30b3\u30d4\u30fc\u4e2d +CreateLiveTriageDriveAction.progressBar.title=\u304a\u5f85\u3061\u304f\u3060\u3055\u3044 +CreateLiveTriageDriveAction.success.message=\u30e9\u30a4\u30d6\u30fb\u30c8\u30ea\u30a2\u30fc\u30b8\u30fb\u30c9\u30e9\u30a4\u30d6\u304c\u4f5c\u6210\u3055\u308c\u307e\u3057\u305f\u3002 RunFromUSB.bat\u3092\u4f7f\u7528\u3057\u3066\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3092\u5b9f\u884c\u3057\u3066\u4e0b\u3055\u3044 +CreateLiveTriageDriveAction.success.title=\u6210\u529f +SelectDriveDialog.bnCancel.text=\u30ad\u30e3\u30f3\u30bb\u30eb +SelectDriveDialog.bnOk.text=Ok +SelectDriveDialog.bnRefresh.text=\u66f4\u65b0 SelectDriveDialog.descriptionTextArea.text=\u3053\u306e\u6a5f\u80fd\u306f\u3001\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3068\u30d0\u30c3\u30c1\u30d5\u30a1\u30a4\u30eb\u3092\u30ea\u30e0\u30fc\u30d0\u30d6\u30eb\u30c9\u30e9\u30a4\u30d6\u306b\u30b3\u30d4\u30fc\u3057\u307e\u3059\u3002\n\u30bd\u30d5\u30c8\u30a6\u30a7\u30a2\u3092\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u305b\u305a\u306b\u30b7\u30b9\u30c6\u30e0\u3092\u5206\u6790\u304b\u30c9\u30e9\u30a4\u30d6\u306e\u30a4\u30e1\u30fc\u30b8\u30f3\u30b0\u3092\u4f5c\u6210\u3057\u307e\u3059\u3002\n\n\u30b7\u30b9\u30c6\u30e0\u3092\u5206\u6790\u3059\u308b\u306b\u306f\u3001\u30c9\u30e9\u30a4\u30d6\u3092\u633f\u5165\u3057\u3001\u300cRunFromUSB.bat\u300d\u3092\u7ba1\u7406\u8005\u3067\u5b9f\u884c\u3057\u3066\u3001\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u306e\u8ffd\u52a0\u30d1\u30cd\u30eb\u3067\u300c\u30ed\u30fc\u30ab\u30eb\u30c7\u30a3\u30b9\u30af\u300d\u30aa\u30d7\u30b7\u30e7\u30f3\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002 +SelectDriveDialog.diskTable.column1.title=\u30c7\u30a3\u30b9\u30af\u540d +SelectDriveDialog.diskTable.column2.title=\u30c7\u30a3\u30b9\u30af\u30b5\u30a4\u30ba +SelectDriveDialog.errLabel.disksNotDetected.text=\u30c7\u30a3\u30b9\u30af\u306f\u691c\u51fa\u3055\u308c\u307e\u305b\u3093\u3067\u3057\u305f\u3002 \u7ba1\u7406\u8005\u6a29\u9650\u304c\u5fc5\u8981\u306a\u5834\u5408\u304c\u3042\u308a\u307e\u3059 +SelectDriveDialog.errLabel.disksNotDetected.toolTipText=\u30c7\u30a3\u30b9\u30af\u306f\u691c\u51fa\u3055\u308c\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +SelectDriveDialog.errorLabel.text=jLabel2 +SelectDriveDialog.lbSelectDrive.text=\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3068\u30b9\u30af\u30ea\u30d7\u30c8\u3092\u30b3\u30d4\u30fc\u3059\u308b\u30c9\u30e9\u30a4\u30d6\u3092\u9078\u629e\u3057\u3066\u4e0b\u3055\u3044\u3002 +SelectDriveDialog.localDiskModel.nodrives.msg=\u5b9f\u884c\u30d5\u30a1\u30a4\u30eb\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f SelectDriveDialog.selectDriveLabel.text=\u30e9\u30a4\u30d6\u30c8\u30ea\u30a2\u30fc\u30b8\u306b\u4f7f\u7528\u3059\u308b\u30c9\u30e9\u30a4\u30d6\u3092\u9078\u629e\u3057\u307e\u3059\uff08\u8aad\u8fbc\u306b\u6642\u9593\u304c\u304b\u304b\u308b\u5834\u5408\u304c\u3042\u308a\u307e\u3059\uff09\u3002 +SelectDriveDialog.title=\u30e9\u30a4\u30d6\u30fb\u30c8\u30ea\u30a2\u30fc\u30b8\u30fb\u30c9\u30e9\u30a4\u30d6\u3092\u4f5c\u6210\u3059\u308b diff --git a/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/AddLogicalImageTask.java b/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/AddLogicalImageTask.java index 3d78ec2a08..eb52c88baf 100644 --- a/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/AddLogicalImageTask.java +++ b/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/AddLogicalImageTask.java @@ -29,7 +29,6 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -37,7 +36,6 @@ import java.util.Map; import java.util.logging.Level; import javax.annotation.concurrent.GuardedBy; import org.apache.commons.io.FileUtils; -import org.openide.util.Exceptions; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; @@ -101,7 +99,7 @@ final class AddLogicalImageTask implements Runnable { return fileId; } } - + 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 USERS_TXT = "_users.txt"; //NON-NLS @@ -445,13 +443,9 @@ final class AddLogicalImageTask implements Runnable { BlackboardArtifact artifact; try { artifact = this.blackboard.newAnalysisResult( - BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT, - fileId, - dataSourceId, - Score.SCORE_UNKNOWN, - null, - null, - null, + BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT, fileId, dataSourceId, + Score.SCORE_LIKELY_NOTABLE, + null, ruleSetName, null, Arrays.asList( new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME, MODULE_NAME, ruleSetName), new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CATEGORY, MODULE_NAME, ruleName) diff --git a/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/Bundle_ja.properties index 477e2b12a4..cec2a3e452 100644 --- a/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/logicalimager/dsp/Bundle_ja.properties @@ -1,2 +1,58 @@ -#Fri Feb 12 16:56:28 UTC 2021 +#Mon Jul 12 13:22:00 UTC 2021 +AddLogicalImageTask.addImageCancelled=\u753b\u50cf\u306e\u8ffd\u52a0\u304c\u30ad\u30e3\u30f3\u30bb\u30eb\u3055\u308c\u307e\u3057\u305f +AddLogicalImageTask.addingExtractedFile=\u62bd\u51fa\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb\u306e\u8ffd\u52a0\uff08{0} / {1}\uff09 +AddLogicalImageTask.addingExtractedFiles=\u62bd\u51fa\u3057\u305f\u30d5\u30a1\u30a4\u30eb\u306e\u8ffd\u52a0 +AddLogicalImageTask.addingInterestingFile=\u8208\u5473\u6df1\u3044\u30d5\u30a1\u30a4\u30eb\u306e\u8ffd\u52a0\uff08{0} / {1}\uff09 +AddLogicalImageTask.addingInterestingFiles=\u691c\u7d22\u7d50\u679c\u3092\u8208\u5473\u6df1\u3044\u30d5\u30a1\u30a4\u30eb\u3068\u3057\u3066\u8ffd\u52a0\u3057\u307e\u3059 +AddLogicalImageTask.addingToReport=\u30ec\u30dd\u30fc\u30c8\u306b{0}\u3092\u8ffd\u52a0 +AddLogicalImageTask.cannotFindDataSourceObjId={0}\u306etsk_image_names\u306bobj_id\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093 +AddLogicalImageTask.cannotFindFiles={1}\u306b{0}\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093 +AddLogicalImageTask.copyingImageFromTo=\u753b\u50cf\u3092{0}\u304b\u3089{1}\u306b\u30b3\u30d4\u30fc\u4e2d +AddLogicalImageTask.directoryDoesNotContainSparseImage=\u30c7\u30a3\u30ec\u30af\u30c8\u30ea{0}\u306b\u306f\u753b\u50cf\u304c\u542b\u307e\u308c\u3066\u3044\u307e\u305b\u3093 +AddLogicalImageTask.doneAddingExtractedFiles=\u62bd\u51fa\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb\u306e\u8ffd\u52a0\u304c\u5b8c\u4e86\u3057\u307e\u3057\u305f +AddLogicalImageTask.doneAddingInterestingFiles=\u691c\u7d22\u7d50\u679c\u3092\u8208\u5473\u6df1\u3044\u30d5\u30a1\u30a4\u30eb\u3068\u3057\u3066\u8ffd\u52a0\u3057\u307e\u3057\u305f +AddLogicalImageTask.doneAddingToReport={0}\u3092\u30ec\u30dd\u30fc\u30c8\u306b\u8ffd\u52a0\u3057\u307e\u3057\u305f +AddLogicalImageTask.doneCopying=\u30b3\u30d4\u30fc\u5b8c\u4e86 +AddLogicalImageTask.failToGetCanonicalPath={0}\u306e\u6b63\u898f\u30d1\u30b9\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093 +AddLogicalImageTask.failedToAddInterestingFiles=\u8208\u5473\u6df1\u3044\u30d5\u30a1\u30a4\u30eb\u306e\u8ffd\u52a0\u306b\u5931\u6557\u3057\u307e\u3057\u305f\uff1a{0} +AddLogicalImageTask.failedToAddReport=\u30ec\u30dd\u30fc\u30c8{0}\u306e\u8ffd\u52a0\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 \u7406\u7531\= {1} +AddLogicalImageTask.failedToCopyDirectory=\u30c7\u30a3\u30ec\u30af\u30c8\u30ea{0}\u3092{1}\u306b\u30b3\u30d4\u30fc\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f +AddLogicalImageTask.failedToGetTotalFilesCount=\u5408\u8a08\u30d5\u30a1\u30a4\u30eb\u6570\u306e\u53d6\u5f97\u306b\u5931\u6557\u3057\u307e\u3057\u305f\uff1a{0} +AddLogicalImageTask.ingestionCancelled=\u53d6\u8fbc\u307f\u304c\u30ad\u30e3\u30f3\u30bb\u30eb\u3055\u308c\u307e\u3057\u305f +AddLogicalImageTask.logicalImagerResults=\u8ad6\u7406\u30a4\u30e1\u30fc\u30b8\u30e3\u306e\u7d50\u679c +AddLogicalImageTask.noCurrentCase=\u73fe\u5728\u306e\u30b1\u30fc\u30b9\u306f\u3042\u308a\u307e\u305b\u3093 +AddLogicalImageTask.notEnoughFields=\u30d5\u30a1\u30a4\u30eb\u306e\u884c{0}\u306b\u30d5\u30a3\u30fc\u30eb\u30c9\u304c\u8db3\u308a\u307e\u305b\u3093\u3002{1}\u3092\u53d6\u5f97\u3057\u307e\u3057\u305f\u3002{2}\u304c\u5fc5\u8981\u3067\u3059\u3002 +AddLogicalImageTask.searchingInterestingFile=\u8208\u5473\u6df1\u3044\u30d5\u30a1\u30a4\u30eb\u306e\u691c\u7d22\uff08{0} / {1}\uff09 +AddMultipleImagesTask.adding=\u8ffd\u52a0\uff1a{0} +AddMultipleImagesTask.addingFileAsLogicalFile=\u672a\u5272\u308a\u5f53\u3066\u30d5\u30a1\u30a4\u30eb\u3068\u3057\u3066\u8ffd\u52a0\uff1a{0}\u3002 +AddMultipleImagesTask.cancelled=\u30ad\u30e3\u30f3\u30bb\u30eb\uff1a\u753b\u50cf\u51e6\u7406\u306e\u8ffd\u52a0\u3092\u5143\u306b\u623b\u3057\u307e\u3057\u305f +AddMultipleImagesTask.criticalErrorAdding=\u30c7\u30d0\u30a4\u30b9{1}\u306b{0}\u3092\u8ffd\u52a0\u4e2d\u306b\u91cd\u5927\u306a\u30a8\u30e9\u30fc\uff1a{2} +AddMultipleImagesTask.criticalErrorReverting=\u30c7\u30d0\u30a4\u30b9{1}\u306e\u753b\u50cf\u8ffd\u52a0\u30d7\u30ed\u30bb\u30b9{0}\u3092\u5143\u306b\u623b\u3059\u6642\u306b\u91cd\u5927\u306a\u30a8\u30e9\u30fc\uff1a{2} +AddMultipleImagesTask.errorAddingImgWithoutFileSystem=\u30d5\u30a1\u30a4\u30eb\u30b7\u30b9\u30c6\u30e0\u7121\u3057\u306e\u30c7\u30d0\u30a4\u30b9{0}\u3067\u753b\u50cf\u3092\u8ffd\u52a0\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\uff1a{1} +AddMultipleImagesTask.fsTypeUnknownErr=\u30d5\u30a1\u30a4\u30eb\u30b7\u30b9\u30c6\u30e0\u306e\u7a2e\u985e\u3092\u5224\u5225\u3067\u304d\u307e\u305b\u3093 AddMultipleImagesTask.imageError=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3078\u753b\u50cf{0}\u306e\u8ffd\u52a0\u306b\u5931\u6557\u3057\u307e\u3057\u305f +AddMultipleImagesTask.nonCriticalErrorAdding=\u30c7\u30d0\u30a4\u30b9{1}\u306b{0}\u3092\u8ffd\u52a0\u4e2d\u306b\u30de\u30a4\u30ca\u30fc\u30a8\u30e9\u30fc\uff1a{2} +LogicalImagerDSProcessor.dataSourceType=Autopsy\u8ad6\u7406\u30a4\u30e1\u30fc\u30b8\u30e3\u306e\u7d50\u679c +LogicalImagerDSProcessor.destinationDirectoryConfirmation=\u5b9b\u5148\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u306e\u78ba\u8a8d +LogicalImagerDSProcessor.destinationDirectoryConfirmationMsg=\u8ad6\u7406\u30a4\u30e1\u30fc\u30b8\u30e3\u30d5\u30a9\u30eb\u30c0{0}\u306f\u3059\u3067\u306b\u5b58\u5728\u3057\u307e\u3059\u3002\n\u65b0\u305f\u306a\u30d5\u30a9\u30eb\u30c0\u540d\u3067\u518d\u5ea6\u8ffd\u52a0\u3057\u307e\u3059\u304b\uff1f +LogicalImagerDSProcessor.directoryAlreadyExists=\u30c7\u30a3\u30ec\u30af\u30c8\u30ea{0}\u306f\u3059\u3067\u306b\u5b58\u5728\u3057\u307e\u3059 +LogicalImagerDSProcessor.failToCreateDirectory=\u30c7\u30a3\u30ec\u30af\u30c8\u30ea{0}\u306e\u4f5c\u6210\u306b\u5931\u6557\u3057\u307e\u3057\u305f +LogicalImagerDSProcessor.imageDirPathNotFound={0}\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3002\nUSB\u30c9\u30e9\u30a4\u30d6\u304c\u53d6\u308a\u51fa\u3055\u308c\u307e\u3057\u305f\u3002 +LogicalImagerDSProcessor.noCurrentCase=\u73fe\u5728\u306e\u30b1\u30fc\u30b9\u306f\u3042\u308a\u307e\u305b\u3093 +LogicalImagerPanel.browseButton.text=\u30d6\u30e9\u30a6\u30ba +LogicalImagerPanel.imageTable.columnModel.title0=\u30db\u30b9\u30c8\u540d +LogicalImagerPanel.imageTable.columnModel.title1=\u62bd\u51fa\u65e5\uff08GMT\uff09 +LogicalImagerPanel.imageTable.columnModel.title2=\u30d1\u30b9 +LogicalImagerPanel.importRadioButton.text=\u5916\u4ed8\u3051\u30c9\u30e9\u30a4\u30d6\u304b\u3089\u30a4\u30f3\u30dd\u30fc\u30c8 +LogicalImagerPanel.manualRadioButton.text=\u624b\u52d5\u3067\u30d5\u30a9\u30eb\u30c0\u3092\u9078\u629e +LogicalImagerPanel.messageLabel.directoryDoesNotContainSparseImage=\u30c7\u30a3\u30ec\u30af\u30c8\u30ea{0}\u306b\u306f\u753b\u50cf\u304c\u542b\u307e\u308c\u3066\u3044\u307e\u305b\u3093 +LogicalImagerPanel.messageLabel.directoryFormatInvalid=\u30c7\u30a3\u30ec\u30af\u30c8\u30ea{0}\u306f\u30d5\u30a9\u30fc\u30de\u30c3\u30c8Logical_Imager_HOSTNAME_yyyymmdd_HH_MM_SS\u3068\u4e00\u81f4\u3057\u307e\u305b\u3093 +LogicalImagerPanel.messageLabel.driveHasNoImages=\u30c9\u30e9\u30a4\u30d6\u306b\u753b\u50cf\u304c\u3042\u308a\u307e\u305b\u3093 +LogicalImagerPanel.messageLabel.noExternalDriveFound=\u30c9\u30e9\u30a4\u30d6\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093 +LogicalImagerPanel.messageLabel.noImageSelected=\u753b\u50cf\u304c\u9078\u629e\u3055\u308c\u3066\u3044\u307e\u305b\u3093 +LogicalImagerPanel.messageLabel.scanningExternalDrives=\u5916\u4ed8\u3051\u30c9\u30e9\u30a4\u30d6\u306e\u753b\u50cf\u3092\u30b9\u30ad\u30e3\u30f3\u3057\u3066\u3044\u307e\u3059..\u3002 +LogicalImagerPanel.refreshButton.text=\u66f4\u65b0 +LogicalImagerPanel.selectAcquisitionFromDriveLabel.text=\u30c9\u30e9\u30a4\u30d6\u304b\u3089\u53d6\u5f97\u3092\u9078\u3093\u3067\u4e0b\u3055\u3044\u3002 +LogicalImagerPanel.selectDriveLabel.text=\u30c9\u30e9\u30a4\u30d6\u3092\u9078\u629e +LogicalImagerPanel.selectFolderLabel.text=\u9078\u629e\u3057\u305f\u30d5\u30a9\u30eb\u30c0\uff1a +LogicalImagerPanel.selectFromDriveLabel.text=\u30c9\u30e9\u30a4\u30d6\u304b\u3089\u306e\u53d6\u5f97\u3092\u9078\u629e diff --git a/Core/src/org/sleuthkit/autopsy/menuactions/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/menuactions/Bundle_ja.properties index 76dff54faf..bb215c5e11 100644 --- a/Core/src/org/sleuthkit/autopsy/menuactions/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/menuactions/Bundle_ja.properties @@ -1,7 +1,11 @@ -OpenIDE-Module-Name=\u30e1\u30cb\u30e5\u30fc\u30a2\u30af\u30b7\u30e7\u30f3 +#Thu Jul 01 11:56:41 UTC 2021 +DataContentDynamicMenu.contentViewers.text=\u30b3\u30f3\u30c6\u30f3\u30c4\u30d3\u30e5\u30fc\u30a2 +DataContentDynamicMenu.mainContentViewer.name=\u4e3b\u8981 DataContentDynamicMenu.menu.dataContentWin.text=\u30c7\u30fc\u30bf\u30b3\u30f3\u30c6\u30f3\u30c4\u30a6\u30a3\u30f3\u30c9\u30a6 DataContentMenu.getName.text=\u30c7\u30fc\u30bf\u30b3\u30f3\u30c6\u30f3\u30c4\u30e1\u30cb\u30e5\u30fc DataExplorerMenu.getName.text=\u30c7\u30fc\u30bf\u30a8\u30af\u30b9\u30d7\u30ed\u30fc\u30e9\u30c4\u30fc\u30eb -DataResultMenu.menu.dataResWin.text=\u30c7\u30fc\u30bf\u7d50\u679c\u30a6\u30a3\u30f3\u30c9\u30a6 DataResultMenu.getName.text=\u30c7\u30fc\u30bf\u7d50\u679c\u30e1\u30cb\u30e5\u30fc +DataResultMenu.menu.dataResWin.text=\u30c7\u30fc\u30bf\u7d50\u679c\u30a6\u30a3\u30f3\u30c9\u30a6 +OpenIDE-Module-Name=\u30e1\u30cb\u30e5\u30fc\u30a2\u30af\u30b7\u30e7\u30f3 SearchResultMenu.menu.dataRes.text=\u30c7\u30fc\u30bf\u7d50\u679c +SearchResultMenu.resultViewers.text=\u7d50\u679c\u30d3\u30e5\u30fc\u30a2 diff --git a/Core/src/org/sleuthkit/autopsy/modules/dataSourceIntegrity/DataSourceIntegrityIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/dataSourceIntegrity/DataSourceIntegrityIngestModule.java index 82a917ce7e..ec614e56b0 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/dataSourceIntegrity/DataSourceIntegrityIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/dataSourceIntegrity/DataSourceIntegrityIngestModule.java @@ -294,10 +294,10 @@ public class DataSourceIntegrityIngestModule implements DataSourceIngestModule { if (!verified) { try { BlackboardArtifact verificationFailedArtifact = Case.getCurrentCase().getSleuthkitCase().getBlackboard().newAnalysisResult( - new BlackboardArtifact.Type(BlackboardArtifact.ARTIFACT_TYPE.TSK_VERIFICATION_FAILED), + BlackboardArtifact.Type.TSK_VERIFICATION_FAILED, img.getId(), img.getId(), - Score.SCORE_UNKNOWN, - null, null, null, + Score.SCORE_NOTABLE, + null, null, artifactComment, Arrays.asList(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT, DataSourceIntegrityModuleFactory.getModuleName(), artifactComment))) .getAnalysisResult(); diff --git a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/Bundle.properties-MERGED index efee783e8f..e8411caa04 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/Bundle.properties-MERGED @@ -12,12 +12,7 @@ ExtractArchiveWithPasswordAction.progress.text=Unpacking contents of archive: {0 ExtractArchiveWithPasswordAction.prompt.text=Enter Password ExtractArchiveWithPasswordAction.prompt.title=Enter Password OpenIDE-Module-Display-Category=Ingest Module -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).\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-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. OpenIDE-Module-Name=Embedded File Extraction OpenIDE-Module-Short-Description=Embedded File Extraction Ingest Module EmbeddedFileExtractorIngestModule.SevenZipContentReadStream.seek.exception.invalidOrigin=Invalid seek origin: {0} diff --git a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/SevenZipExtractor.java b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/SevenZipExtractor.java index da046d729b..0a44614765 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/SevenZipExtractor.java +++ b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/SevenZipExtractor.java @@ -46,6 +46,7 @@ import net.sf.sevenzipjbinding.PropID; import net.sf.sevenzipjbinding.SevenZip; import net.sf.sevenzipjbinding.SevenZipException; import net.sf.sevenzipjbinding.SevenZipNativeInitializationException; +import org.apache.tika.Tika; import org.apache.tika.parser.txt.CharsetDetector; import org.apache.tika.parser.txt.CharsetMatch; import org.netbeans.api.progress.ProgressHandle; @@ -77,6 +78,7 @@ import org.sleuthkit.datamodel.DerivedFile; import org.sleuthkit.datamodel.EncodedFileOutputStream; import org.sleuthkit.datamodel.ReadContentInputStream; import org.sleuthkit.datamodel.Score; +import org.sleuthkit.datamodel.SleuthkitCase.CaseDbTransaction; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; @@ -89,7 +91,7 @@ class SevenZipExtractor { private static final Logger logger = Logger.getLogger(SevenZipExtractor.class.getName()); private static final String MODULE_NAME = EmbeddedFileExtractorModuleFactory.getModuleName(); - + //encryption type strings private static final String ENCRYPTION_FILE_LEVEL = NbBundle.getMessage(EmbeddedFileExtractorIngestModule.class, "EmbeddedFileExtractorIngestModule.ArchiveExtractor.encryptionFileLevel"); @@ -194,6 +196,15 @@ class SevenZipExtractor { } return false; } + + boolean isSevenZipExtractionSupported(String mimeType) { + for (SupportedArchiveExtractionFormats supportedMimeType : SupportedArchiveExtractionFormats.values()) { + if (mimeType.contains(supportedMimeType.toString())) { + return true; + } + } + return false; + } /** * Private helper method to standardize the cancellation check that is @@ -302,11 +313,13 @@ class SevenZipExtractor { private void flagRootArchiveAsZipBomb(Archive rootArchive, AbstractFile archiveFile, String details, String escapedFilePath) { rootArchive.flagAsZipBomb(); logger.log(Level.INFO, details); + + String setName = "Possible Zip Bomb"; try { Collection attributes = Arrays.asList( new BlackboardAttribute( TSK_SET_NAME, MODULE_NAME, - "Possible Zip Bomb"), + setName), new BlackboardAttribute( TSK_DESCRIPTION, MODULE_NAME, Bundle.SevenZipExtractor_zipBombArtifactCreation_text(archiveFile.getName())), @@ -315,9 +328,13 @@ class SevenZipExtractor { details)); if (!blackboard.artifactExists(archiveFile, TSK_INTERESTING_FILE_HIT, attributes)) { + BlackboardArtifact artifact = rootArchive.getArchiveFile().newAnalysisResult( - new BlackboardArtifact.Type(TSK_INTERESTING_FILE_HIT), Score.SCORE_UNKNOWN, null, null, null, attributes) + BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT, Score.SCORE_LIKELY_NOTABLE, + null, setName, null, + attributes) .getAnalysisResult(); + try { /* * post the artifact which will index the artifact for @@ -783,34 +800,20 @@ class SevenZipExtractor { // add them to the DB. We wait until the end so that we have the metadata on all of the // intermediate nodes since the order is not guaranteed try { - unpackedTree.updateOrAddFileToCaseRec(statusMap, archiveFilePath); - if (checkForIngestCancellation(archiveFile)) { - return false; - } - unpackedFiles = unpackedTree.getAllFileObjects(); - //check if children are archives, update archive depth tracking - for (int i = 0; i < unpackedFiles.size(); i++) { - if (checkForIngestCancellation(archiveFile)) { - return false; - } - progress.progress(String.format("%s: Searching for nested archives (%d of %d)", currentArchiveName, i + 1, unpackedFiles.size())); - AbstractFile unpackedFile = unpackedFiles.get(i); - if (unpackedFile == null) { - continue; - } - if (isSevenZipExtractionSupported(unpackedFile)) { - Archive child = new Archive(parentAr.getDepth() + 1, parentAr.getRootArchiveId(), archiveFile); - parentAr.addChild(child); - depthMap.put(unpackedFile.getId(), child); - } - unpackedFile.close(); - } - - } catch (TskCoreException | NoCurrentCaseException e) { - logger.log(Level.SEVERE, "Error populating complete derived file hierarchy from the unpacked dir structure", e); //NON-NLS - //TODO decide if anything to cleanup, for now bailing + unpackedTree.updateOrAddFileToCaseRec(statusMap, archiveFilePath, parentAr, archiveFile, depthMap); + unpackedTree.commitCurrentTransaction(); + } catch (TskCoreException | NoCurrentCaseException ex) { + logger.log(Level.SEVERE, "Error populating complete derived file hierarchy from the unpacked dir structure", ex); //NON-NLS + //TODO decide if anything to cleanup, for now bailing + unpackedTree.rollbackCurrentTransaction(); } - + + if (checkForIngestCancellation(archiveFile)) { + return false; + } + + // Get the new files to be added to the case. + unpackedFiles = unpackedTree.getAllFileObjects(); } catch (SevenZipException | IllegalArgumentException ex) { logger.log(Level.WARNING, "Error unpacking file: " + archiveFile, ex); //NON-NLS //inbox message @@ -855,8 +858,9 @@ class SevenZipExtractor { String encryptionType = fullEncryption ? ENCRYPTION_FULL : ENCRYPTION_FILE_LEVEL; try { BlackboardArtifact artifact = archiveFile.newAnalysisResult( - new BlackboardArtifact.Type(BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_DETECTED), Score.SCORE_UNKNOWN, - null, null, null, + new BlackboardArtifact.Type(BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_DETECTED), + Score.SCORE_NOTABLE, + null, null, encryptionType, Arrays.asList(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT, MODULE_NAME, encryptionType))) .getAnalysisResult(); @@ -984,6 +988,8 @@ class SevenZipExtractor { private EncodedFileOutputStream output; private String localAbsPath; private int bytesWritten; + private static final Tika tika = new Tika(); + private String mimeType = ""; UnpackStream(String localAbsPath) throws IOException { this.output = new EncodedFileOutputStream(new FileOutputStream(localAbsPath), TskData.EncodingType.XOR1); @@ -996,6 +1002,7 @@ class SevenZipExtractor { this.output = new EncodedFileOutputStream(new FileOutputStream(localAbsPath), TskData.EncodingType.XOR1); this.localAbsPath = localAbsPath; this.bytesWritten = 0; + this.mimeType = ""; } public int getSize() { @@ -1005,6 +1012,10 @@ class SevenZipExtractor { @Override public int write(byte[] bytes) throws SevenZipException { try { + // Detect MIME type now while the file is in memory + if (bytesWritten == 0) { + mimeType = tika.detect(bytes); + } output.write(bytes); this.bytesWritten += bytes.length; } catch (IOException ex) { @@ -1016,6 +1027,10 @@ class SevenZipExtractor { return bytes.length; } + public String getMIMEType() { + return mimeType; + } + public void close() throws IOException { try (EncodedFileOutputStream out = output) { out.flush(); @@ -1189,6 +1204,8 @@ class SevenZipExtractor { 0L, createTimeInSeconds, accessTimeInSeconds, modTimeInSeconds, localRelPath); return; + } else { + unpackedNode.setMimeType(unpackStream.getMIMEType()); } final String localAbsPath = archiveDetailsMap.get( @@ -1254,6 +1271,15 @@ class SevenZipExtractor { final UnpackedNode rootNode; private int nodesProcessed = 0; + + // It is significantly faster to add the DerivedFiles to the case on a transaction, + // but we don't want to hold the transaction (and case write lock) for the entire + // stage. Instead, we use the same transaction for MAX_TRANSACTION_SIZE database operations + // and then commit that transaction and start a new one, giving at least a short window + // for other processes. + private CaseDbTransaction currentTransaction = null; + private long transactionCounter = 0; + private final static long MAX_TRANSACTION_SIZE = 1000; /** * @@ -1406,10 +1432,10 @@ class SevenZipExtractor { * Traverse the tree top-down after unzipping is done and create derived * files for the entire hierarchy */ - void updateOrAddFileToCaseRec(HashMap statusMap, String archiveFilePath) throws TskCoreException, NoCurrentCaseException { + void updateOrAddFileToCaseRec(HashMap statusMap, String archiveFilePath, Archive parentAr, AbstractFile archiveFile, ConcurrentHashMap depthMap) throws TskCoreException, NoCurrentCaseException { final FileManager fileManager = Case.getCurrentCaseThrows().getServices().getFileManager(); for (UnpackedNode child : rootNode.getChildren()) { - updateOrAddFileToCaseRec(child, fileManager, statusMap, archiveFilePath); + updateOrAddFileToCaseRec(child, fileManager, statusMap, archiveFilePath, parentAr, archiveFile, depthMap); } } @@ -1424,20 +1450,23 @@ class SevenZipExtractor { * updating * @param statusMap - the map of existing files and their status * @param archiveFilePath - the archive file path for the unpacked node + * @param parentAr - the parent archive as an Archive object + * @param archiveFile - the parent archive as an AbstractFile + * @param depthMap - the depth map (to prevent zip bombs) * * @throws TskCoreException */ - private void updateOrAddFileToCaseRec(UnpackedNode node, FileManager fileManager, HashMap statusMap, String archiveFilePath) throws TskCoreException { + private void updateOrAddFileToCaseRec(UnpackedNode node, FileManager fileManager, HashMap statusMap, String archiveFilePath, Archive parentAr, AbstractFile archiveFile, ConcurrentHashMap depthMap) throws TskCoreException { DerivedFile df; progress.progress(String.format("%s: Adding/updating files in case database (%d of %d)", currentArchiveName, ++nodesProcessed, numItems)); try { String nameInDatabase = getKeyFromUnpackedNode(node, archiveFilePath); ZipFileStatusWrapper existingFile = nameInDatabase == null ? null : statusMap.get(nameInDatabase); if (existingFile == null) { - df = fileManager.addDerivedFile(node.getFileName(), node.getLocalRelPath(), node.getSize(), + df = Case.getCurrentCaseThrows().getSleuthkitCase().addDerivedFile(node.getFileName(), node.getLocalRelPath(), node.getSize(), node.getCtime(), node.getCrtime(), node.getAtime(), node.getMtime(), node.isIsFile(), node.getParent().getFile(), "", MODULE_NAME, - "", "", TskData.EncodingType.XOR1); + "", "", TskData.EncodingType.XOR1, getCurrentTransaction()); statusMap.put(getKeyAbstractFile(df), new ZipFileStatusWrapper(df, ZipFileStatus.EXISTS)); } else { String key = getKeyAbstractFile(existingFile.getFile()); @@ -1448,10 +1477,10 @@ class SevenZipExtractor { if (existingFile.getStatus() == ZipFileStatus.UPDATE) { //if the we are updating a file and its mime type was octet-stream we want to re-type it String mimeType = existingFile.getFile().getMIMEType().equalsIgnoreCase("application/octet-stream") ? null : existingFile.getFile().getMIMEType(); - df = fileManager.updateDerivedFile((DerivedFile) existingFile.getFile(), node.getLocalRelPath(), node.getSize(), + df = Case.getCurrentCaseThrows().getSleuthkitCase().updateDerivedFile((DerivedFile) existingFile.getFile(), node.getLocalRelPath(), node.getSize(), node.getCtime(), node.getCrtime(), node.getAtime(), node.getMtime(), node.isIsFile(), mimeType, "", MODULE_NAME, - "", "", TskData.EncodingType.XOR1); + "", "", TskData.EncodingType.XOR1, existingFile.getFile().getParent(), getCurrentTransaction()); } else { //ALREADY CURRENT - SKIP statusMap.put(key, new ZipFileStatusWrapper(existingFile.getFile(), ZipFileStatus.SKIP)); @@ -1459,7 +1488,7 @@ class SevenZipExtractor { } } node.setFile(df); - } catch (TskCoreException ex) { + } catch (TskCoreException | NoCurrentCaseException ex) { logger.log(Level.SEVERE, "Error adding a derived file to db:" + node.getFileName(), ex); //NON-NLS throw new TskCoreException( NbBundle.getMessage(SevenZipExtractor.class, "EmbeddedFileExtractorIngestModule.ArchiveExtractor.UnpackedTree.exception.msg", @@ -1490,10 +1519,82 @@ class SevenZipExtractor { } } } + + // Check for zip bombs + if (isSevenZipExtractionSupported(node.getMimeType())) { + Archive child = new Archive(parentAr.getDepth() + 1, parentAr.getRootArchiveId(), archiveFile); + parentAr.addChild(child); + depthMap.put(node.getFile().getId(), child); + } //recurse adding the children if this file was incomplete the children presumably need to be added for (UnpackedNode child : node.getChildren()) { - updateOrAddFileToCaseRec(child, fileManager, statusMap, getKeyFromUnpackedNode(node, archiveFilePath)); + updateOrAddFileToCaseRec(child, fileManager, statusMap, getKeyFromUnpackedNode(node, archiveFilePath), parentAr, archiveFile, depthMap); + } + } + + /** + * Get the current transaction being used in updateOrAddFileToCaseRec(). + * If there is no transaction, one will be started. After the + * transaction has been used MAX_TRANSACTION_SIZE, it will be committed and a + * new transaction will be opened. + * + * @return The open transaction. + * + * @throws TskCoreException + */ + private CaseDbTransaction getCurrentTransaction() throws TskCoreException { + + if (currentTransaction == null) { + startTransaction(); + } + + if (transactionCounter > MAX_TRANSACTION_SIZE) { + commitCurrentTransaction(); + startTransaction(); + } + + transactionCounter++; + return currentTransaction; + } + + /** + * Open a transaction. + * + * @throws TskCoreException + */ + private void startTransaction() throws TskCoreException { + try { + currentTransaction = Case.getCurrentCaseThrows().getSleuthkitCase().beginTransaction(); + transactionCounter = 0; + } catch (NoCurrentCaseException ex) { + throw new TskCoreException("Case is closed"); + } + } + + /** + * Commit the current transaction. + * + * @throws TskCoreException + */ + private void commitCurrentTransaction() throws TskCoreException { + if (currentTransaction != null) { + currentTransaction.commit(); + currentTransaction = null; + } + } + + /** + * Rollback the current transaction. + */ + private void rollbackCurrentTransaction() { + if (currentTransaction != null) { + try { + currentTransaction.rollback(); + currentTransaction = null; + } catch (TskCoreException ex) { + // Ignored + } } } @@ -1510,6 +1611,7 @@ class SevenZipExtractor { private long size; private long ctime, crtime, atime, mtime; private boolean isFile; + private String mimeType = ""; private UnpackedNode parent; //root constructor @@ -1586,6 +1688,14 @@ class SevenZipExtractor { void setFile(AbstractFile file) { this.file = file; } + + void setMimeType(String mimeType) { + this.mimeType = mimeType; + } + + String getMimeType() { + return mimeType; + } /** * get child by name or null if it doesn't exist diff --git a/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionDataSourceIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionDataSourceIngestModule.java index ccc19843db..5eb6f91e12 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionDataSourceIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionDataSourceIngestModule.java @@ -104,14 +104,16 @@ final class EncryptionDetectionDataSourceIngestModule implements DataSourceInges return ProcessResult.OK; } if (BitlockerDetection.isBitlockerVolume(volume)) { - return flagVolume(volume, BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_DETECTED, Bundle.EncryptionDetectionDataSourceIngestModule_artifactComment_bitlocker()); + return flagVolume(volume, BlackboardArtifact.Type.TSK_ENCRYPTION_DETECTED, Score.SCORE_NOTABLE, + Bundle.EncryptionDetectionDataSourceIngestModule_artifactComment_bitlocker()); } if (context.dataSourceIngestIsCancelled()) { return ProcessResult.OK; } if (isVolumeEncrypted(volume)) { - return flagVolume(volume, BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_SUSPECTED, String.format(Bundle.EncryptionDetectionDataSourceIngestModule_artifactComment_suspected(), calculatedEntropy)); + return flagVolume(volume, BlackboardArtifact.Type.TSK_ENCRYPTION_SUSPECTED, Score.SCORE_LIKELY_NOTABLE, + String.format(Bundle.EncryptionDetectionDataSourceIngestModule_artifactComment_suspected(), calculatedEntropy)); } } // Update progress bar @@ -148,19 +150,20 @@ final class EncryptionDetectionDataSourceIngestModule implements DataSourceInges * @param volume The volume to be processed. * @param artifactType The type of artifact to create. This is assumed to be * an analysis result type. + * @param score The score of the analysis result. * @param comment A comment to be attached to the artifact. * * @return 'OK' if the volume was processed successfully, or 'ERROR' if * there was a problem. */ - private IngestModule.ProcessResult flagVolume(Volume volume, BlackboardArtifact.ARTIFACT_TYPE artifactType, String comment) { + private IngestModule.ProcessResult flagVolume(Volume volume, BlackboardArtifact.Type artifactType, Score score, String comment) { if (context.dataSourceIngestIsCancelled()) { return ProcessResult.OK; } try { - BlackboardArtifact artifact = volume.newAnalysisResult(new BlackboardArtifact.Type(artifactType), Score.SCORE_UNKNOWN, null, null, null, + BlackboardArtifact artifact = volume.newAnalysisResult(artifactType, score, null, null, comment, Arrays.asList(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT, EncryptionDetectionModuleFactory.getModuleName(), comment))) .getAnalysisResult(); diff --git a/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionFileIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionFileIngestModule.java index 1609e4a5a6..ff773cf8ef 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionFileIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionFileIngestModule.java @@ -28,7 +28,6 @@ import com.healthmarketscience.jackcess.util.MemFileChannel; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; -import java.nio.BufferUnderflowException; import java.util.Arrays; import java.util.logging.Level; import org.apache.tika.exception.EncryptedDocumentException; @@ -65,7 +64,7 @@ import org.xml.sax.SAXException; final class EncryptionDetectionFileIngestModule extends FileIngestModuleAdapter { private static final int FILE_SIZE_MODULUS = 512; - + private static final String DATABASE_FILE_EXTENSION = "db"; private static final int MINIMUM_DATABASE_FILE_SIZE = 65536; //64 KB @@ -157,10 +156,11 @@ final class EncryptionDetectionFileIngestModule extends FileIngestModuleAdapter */ String mimeType = fileTypeDetector.getMIMEType(file); if (mimeType.equals("application/octet-stream") && isFileEncryptionSuspected(file)) { - return flagFile(file, BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_SUSPECTED, + return flagFile(file, BlackboardArtifact.Type.TSK_ENCRYPTION_SUSPECTED, Score.SCORE_LIKELY_NOTABLE, String.format(Bundle.EncryptionDetectionFileIngestModule_artifactComment_suspected(), calculatedEntropy)); } else if (isFilePasswordProtected(file)) { - return flagFile(file, BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_DETECTED, Bundle.EncryptionDetectionFileIngestModule_artifactComment_password()); + return flagFile(file, BlackboardArtifact.Type.TSK_ENCRYPTION_DETECTED, Score.SCORE_NOTABLE, + Bundle.EncryptionDetectionFileIngestModule_artifactComment_password()); } } } catch (ReadContentInputStreamException | SAXException | TikaException | UnsupportedCodecException ex) { @@ -191,18 +191,19 @@ final class EncryptionDetectionFileIngestModule extends FileIngestModuleAdapter * @param file The file to be processed. * @param artifactType The type of artifact to create. Assumed to be an * analysis result type. + * @param score The score of the analysis result. * @param comment A comment to be attached to the artifact. * * @return 'OK' if the file was processed successfully, or 'ERROR' if there * was a problem. */ - private IngestModule.ProcessResult flagFile(AbstractFile file, BlackboardArtifact.ARTIFACT_TYPE artifactType, String comment) { + private IngestModule.ProcessResult flagFile(AbstractFile file, BlackboardArtifact.Type artifactType, Score score, String comment) { try { if (context.fileIngestIsCancelled()) { return IngestModule.ProcessResult.OK; } - BlackboardArtifact artifact = file.newAnalysisResult(new BlackboardArtifact.Type(artifactType), Score.SCORE_UNKNOWN, null, null, null, + BlackboardArtifact artifact = file.newAnalysisResult(artifactType, score, null, null, comment, Arrays.asList(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT, EncryptionDetectionModuleFactory.getModuleName(), comment))) .getAnalysisResult(); diff --git a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties-MERGED index cfaadf1635..5063bd55fa 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties-MERGED @@ -36,27 +36,27 @@ FileExtMismatchSettingsPanel.jLabel1.text=File Types: FileExtMismatchSettingsPanel.newExtButton.text=New Extension FileExtMismatchSettingsPanel.newMimePrompt.message=Add a new MIME file type: 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.mimeTypeNotSupported.message=MIME type not supported\! +FileExtMismatchSettingsPanel.newMimePrompt.mimeTypeNotSupported.message=MIME 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.mimeTypeNotDetectable.message=MIME type is not detectable by this module. 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.newExtPrompt.message=Add an 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.noMimeType.message=No MIME type selected\! +FileExtMismatchSettingsPanel.newExtPrompt.noMimeType.message=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.removeExtButton.noneSelected.message=No extension selected\! +FileExtMismatchSettingsPanel.removeExtButton.noneSelected.message=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.removeTypeButton.toolTipText= FileExtMismatchModuleSettingsPanel.checkAllRadioButton.text=Check all file types diff --git a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchIngestModule.java index b17523c69a..586543c003 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/FileExtMismatchIngestModule.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.modules.fileextmismatch; +import java.text.MessageFormat; import java.util.Collections; import java.util.HashMap; import java.util.Set; @@ -38,7 +39,6 @@ import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Blackboard; import org.sleuthkit.datamodel.BlackboardArtifact; -import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; import org.sleuthkit.datamodel.Score; import org.sleuthkit.datamodel.TskData; import org.sleuthkit.datamodel.TskData.FileKnown; @@ -52,7 +52,7 @@ import org.sleuthkit.datamodel.TskException; "FileExtMismatchIngestModule.readError.message=Could not read settings." }) public class FileExtMismatchIngestModule implements FileIngestModule { - + private static final Logger logger = Logger.getLogger(FileExtMismatchIngestModule.class.getName()); private final IngestServices services = IngestServices.getInstance(); private final FileExtMismatchDetectorModuleSettings settings; @@ -141,9 +141,12 @@ public class FileExtMismatchIngestModule implements FileIngestModule { addToTotals(jobId, System.currentTimeMillis() - startTime); if (mismatchDetected) { + String justification = MessageFormat.format("File has MIME type of {0}", detector.getMIMEType(abstractFile)); + // add artifact BlackboardArtifact bart = abstractFile.newAnalysisResult( - new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_EXT_MISMATCH_DETECTED), Score.SCORE_UNKNOWN, null, null, null, Collections.emptyList()) + BlackboardArtifact.Type.TSK_EXT_MISMATCH_DETECTED, Score.SCORE_LIKELY_NOTABLE, + null, null, justification, Collections.emptyList()) .getAnalysisResult(); try { diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileType.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileType.java index acad818f09..2d8119b809 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileType.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileType.java @@ -133,9 +133,9 @@ class FileType implements Serializable { * * @return True or false. */ - boolean matches(final AbstractFile file) { + boolean matches(final AbstractFile file, byte[] startOfFileBuffer, int bufLen) { for (Signature sig : this.signatures) { - if (!sig.containedIn(file)) { + if (!sig.containedIn(file, startOfFileBuffer, bufLen)) { return false; } } @@ -327,7 +327,7 @@ class FileType implements Serializable { * * @return True or false. */ - boolean containedIn(final AbstractFile file) { + boolean containedIn(final AbstractFile file, byte[] startOfFileBuffer, int bufLen) { if (offset >= file.getSize()) { return false; // File is too small, offset lies outside file. } @@ -340,7 +340,17 @@ class FileType implements Serializable { } try { byte[] buffer = new byte[signatureBytes.length]; - int bytesRead = file.read(buffer, actualOffset, signatureBytes.length); + int bytesRead; + if (actualOffset + signatureBytes.length < bufLen) { + // The signature is contained in the buffer we've already read, so + // just copy the appropriate section. + for (int i = 0; i < signatureBytes.length;i++) { + buffer[i] = startOfFileBuffer[(int)actualOffset + i]; + } + bytesRead = signatureBytes.length; + } else { + bytesRead = file.read(buffer, actualOffset, signatureBytes.length); + } return ((bytesRead == signatureBytes.length) && (Arrays.equals(buffer, signatureBytes))); } catch (TskCoreException ex) { /** diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java index edd61eb4d1..bc3359a785 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java @@ -51,7 +51,8 @@ public class FileTypeDetector { private final List userDefinedFileTypes; private final List autopsyDefinedFileTypes; private static SortedSet tikaDetectedTypes; - + private final int defaultBufferSize = 600; // Number of bytes to initially read from the file. Should cover most signatures. + /** * Gets a sorted set of the file types that can be detected: the MIME types * detected by Tika (without optional parameters), the custom MIME types @@ -189,7 +190,6 @@ public class FileTypeDetector { // optional parameter attached. return removeOptionalParameter(mimeType); } - /* * Mark non-regular files (refer to TskData.TSK_FS_META_TYPE_ENUM), * zero-sized files, unallocated space, and unused blocks (refer to @@ -203,12 +203,24 @@ public class FileTypeDetector { mimeType = MimeTypes.OCTET_STREAM; } + /* + * Read in the beginning of the file and store it. + */ + byte[] buf = new byte[defaultBufferSize]; + int bufLen; + try { + bufLen = file.read(buf, 0, defaultBufferSize); + } catch (TskCoreException ex) { + // Proceed for now - the error will likely get logged next time the file is read. + bufLen = 0; + } + /* * If the file is a regular file, give precedence to user-defined custom * file types. */ if (null == mimeType) { - mimeType = detectUserDefinedType(file); + mimeType = detectUserDefinedType(file, buf, bufLen); } /* @@ -216,7 +228,7 @@ public class FileTypeDetector { * custom file types defined by Autopsy. */ if (null == mimeType) { - mimeType = detectAutopsyDefinedType(file); + mimeType = detectAutopsyDefinedType(file, buf, bufLen); } /* @@ -296,7 +308,7 @@ public class FileTypeDetector { * Documented side effect: write the result to the AbstractFile object. */ file.setMIMEType(mimeType); - + return mimeType; } @@ -349,14 +361,16 @@ public class FileTypeDetector { * Determines whether or not a file matches a user-defined custom file type. * * @param file The file to test. + * @param startOfFileBuffer The beginning of the file data. + * @param bufLen The length of startOfFileBuffer. * * @return The MIME type as a string if a match is found; otherwise null. */ - private String detectUserDefinedType(AbstractFile file) { + private String detectUserDefinedType(AbstractFile file, byte[] startOfFileBuffer, int bufLen) { String retValue = null; for (FileType fileType : userDefinedFileTypes) { - if (fileType.matches(file)) { + if (fileType.matches(file, startOfFileBuffer, bufLen)) { retValue = fileType.getMimeType(); break; } @@ -369,12 +383,14 @@ public class FileTypeDetector { * Autopsy. * * @param file The file to test. - * + * @param startOfFileBuffer The beginning of the file data. + * @param bufLen The length of startOfFileBuffer. + * * @return The MIME type as a string if a match is found; otherwise null. */ - private String detectAutopsyDefinedType(AbstractFile file) { + private String detectAutopsyDefinedType(AbstractFile file, byte[] startOfFileBuffer, int bufLen) { for (FileType fileType : autopsyDefinedFileTypes) { - if (fileType.matches(file)) { + if (fileType.matches(file, startOfFileBuffer, bufLen)) { return fileType.getMimeType(); } } diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdIngestModule.java index 644cc0aede..0288d5b463 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeIdIngestModule.java @@ -49,7 +49,7 @@ import org.sleuthkit.datamodel.TskCoreException; */ @NbBundle.Messages({"CannotRunFileTypeDetection=Unable to run file type detection."}) public class FileTypeIdIngestModule implements FileIngestModule { - + private static final Logger logger = Logger.getLogger(FileTypeIdIngestModule.class.getName()); private static final HashMap totalsForIngestJobs = new HashMap<>(); private static final IngestModuleReferenceCounter refCounter = new IngestModuleReferenceCounter(); @@ -128,12 +128,44 @@ public class FileTypeIdIngestModule implements FileIngestModule { * of CustomFileTypesManager. */ private FileType detectUserDefinedFileType(AbstractFile file) throws CustomFileTypesManager.CustomFileTypesException { + + if (CustomFileTypesManager.getInstance().getUserDefinedFileTypes().isEmpty()) { + return null; + } + + /* + * Read in the beginning of the file once. + */ + byte[] buf = new byte[1024]; + int bufLen; + try { + bufLen = file.read(buf, 0, 1024); + } catch (TskCoreException ex) { + // Proceed for now - the error will likely get logged next time the file is read. + bufLen = 0; + } + return detectUserDefinedFileType(file, buf, bufLen); + } + + /** + * Determines whether or not a file matches a user-defined custom file type. + * + * @param file The file to test. + * @param startOfFileBuffer The beginning of the file data. + * @param bufLen The length of startOfFileBuffer. + * + * @return The file type if a match is found; otherwise null. + * + * @throws CustomFileTypesException If there is an issue getting an instance + * of CustomFileTypesManager. + */ + private FileType detectUserDefinedFileType(AbstractFile file, byte[] startOfFileBuffer, int bufLen) throws CustomFileTypesManager.CustomFileTypesException { FileType retValue = null; CustomFileTypesManager customFileTypesManager = CustomFileTypesManager.getInstance(); List fileTypesList = customFileTypesManager.getUserDefinedFileTypes(); for (FileType fileType : fileTypesList) { - if (fileType.matches(file)) { + if (fileType.matches(file, startOfFileBuffer, bufLen)) { retValue = fileType; break; } @@ -164,9 +196,10 @@ public class FileTypeIdIngestModule implements FileIngestModule { // Create artifact if it doesn't already exist. if (!tskBlackboard.artifactExists(file, TSK_INTERESTING_FILE_HIT, attributes)) { BlackboardArtifact artifact = file.newAnalysisResult( - new BlackboardArtifact.Type(TSK_INTERESTING_FILE_HIT), Score.SCORE_UNKNOWN, null, null, null, attributes) + BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT, Score.SCORE_LIKELY_NOTABLE, + null, fileType.getInterestingFilesSetName(), null, + attributes) .getAnalysisResult(); - try { /* * post the artifact which will index the artifact for diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties-MERGED index dd5aa258cc..8dbb55e35f 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties-MERGED @@ -61,10 +61,7 @@ ImportCentralRepoDbProgressDialog.errorParsingFile.message=Error parsing hash se ImportCentralRepoDbProgressDialog.linesProcessed.message=\ hashes processed ImportCentralRepoDbProgressDialog.title.text=Central Repository Import Progress OpenIDE-Module-Display-Category=Ingest Module -OpenIDE-Module-Long-Description=\ - 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-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. OpenIDE-Module-Name=HashDatabases OptionsCategory_Name_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. ModalNoButtons.indexingDbsTitle=Indexing hash sets ModalNoButtons.indexingDbTitle=Indexing hash set -ModalNoButtons.exitHashDbIndexingMsg=You are about to exit out of indexing your hash sets. \n\ -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.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? ModalNoButtons.dlgTitle.unfinishedIndexing=Unfinished Indexing ModalNoButtons.indexThis.currentlyIndexing1Db=Currently indexing 1 hash set ModalNoButtons.indexThese.currentlyIndexing1OfNDbs=Currently indexing 1 of {0} diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle_ja.properties index 057e60b7ef..af159ecd1c 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle_ja.properties @@ -1,4 +1,4 @@ -#Fri Feb 12 16:56:29 UTC 2021 +#Mon Jul 12 13:22:00 UTC 2021 AddContentToHashDbAction.ContentMenu.createDbItem=\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u3092\u4f5c\u6210... AddContentToHashDbAction.ContentMenu.noHashDbsConfigd=\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u304c\u69cb\u6210\u3055\u308c\u3066\u3044\u307e\u305b\u3093 AddContentToHashDbAction.addFilesToHashSet.addToHashDbErr1.text=\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u30a8\u30e9\u30fc\u306b\u8ffd\u52a0 @@ -47,6 +47,7 @@ HashDbConfigPanel.indexButtonText.indexing=\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\ HashDbConfigPanel.indexButtonText.reIndex=\u518d\u30a4\u30f3\u30c7\u30c3\u30af\u30b9 HashDbConfigPanel.indexStatusText.indexGen=\u73fe\u5728\u7d22\u5f15\u3092\u751f\u6210\u4e2d\u3067\u3059 HashDbConfigPanel.indexStatusText.indexOnly=\u7d22\u5f15\u306e\u307f +HashDbConfigPanel.indexStatusText.indexed=\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u6e08\u307f HashDbConfigPanel.indexStatusText.noIndex=\u7d22\u5f15\u304c\u3042\u308a\u307e\u305b\u3093 HashDbConfigPanel.nameColLbl=\u540d\u524d HashDbConfigPanel.noSelectionText= diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbContextMenuActionsProvider.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbContextMenuActionsProvider.java index 22f1c445c9..178cd8978a 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbContextMenuActionsProvider.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbContextMenuActionsProvider.java @@ -26,6 +26,7 @@ import org.openide.util.Utilities; import org.openide.util.lookup.ServiceProvider; import org.sleuthkit.autopsy.corecomponentinterfaces.ContextMenuActionsProvider; import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.DataArtifact; @ServiceProvider(service = ContextMenuActionsProvider.class) public class HashDbContextMenuActionsProvider implements ContextMenuActionsProvider { @@ -34,7 +35,9 @@ public class HashDbContextMenuActionsProvider implements ContextMenuActionsProvi public List getActions() { ArrayList actions = new ArrayList<>(); Collection selectedFiles = Utilities.actionsGlobalContext().lookupAll(AbstractFile.class); - if (!selectedFiles.isEmpty()) { + Collection dataArtifacts = Utilities.actionsGlobalContext().lookupAll(DataArtifact.class); + // don't show AddContentToHashDbAction for data artifacts but do if related abstract file + if (!selectedFiles.isEmpty() && dataArtifacts.isEmpty()) { actions.add(AddContentToHashDbAction.getInstance()); } return actions; diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java index ecb2574149..8b6cc47d79 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java @@ -49,6 +49,7 @@ import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE; import org.sleuthkit.datamodel.HashHitInfo; import org.sleuthkit.datamodel.HashUtility; import org.sleuthkit.datamodel.Score; +import org.sleuthkit.datamodel.Score.Significance; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; @@ -382,9 +383,8 @@ public class HashDbIngestModule implements FileIngestModule { totalCount.incrementAndGet(); file.setKnown(statusIfFound); - String hashSetName = db.getDisplayName(); String comment = generateComment(hashInfo); - if (!createArtifactIfNotExists(hashSetName, file, comment, db)) { + if (!createArtifactIfNotExists(file, comment, db)) { wasError = true; } } @@ -427,24 +427,23 @@ public class HashDbIngestModule implements FileIngestModule { /** * Creates a BlackboardArtifact if artifact does not already exist. * - * @param hashSetName The name of the hashset found. * @param file The file that had a hash hit. * @param comment The comment to associate with this artifact. * @param db the database in which this file was found. * * @return True if the operation occurred successfully and without error. */ - private boolean createArtifactIfNotExists(String hashSetName, AbstractFile file, String comment, HashDb db) { + private boolean createArtifactIfNotExists(AbstractFile file, String comment, HashDb db) { /* * We have a match. Now create an artifact if it is determined that one * hasn't been created yet. */ List attributesList = new ArrayList<>(); - attributesList.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_SET_NAME, HashLookupModuleFactory.getModuleName(), hashSetName)); + attributesList.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_SET_NAME, HashLookupModuleFactory.getModuleName(), db.getDisplayName())); try { Blackboard tskBlackboard = skCase.getBlackboard(); if (tskBlackboard.artifactExists(file, BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT, attributesList) == false) { - postHashSetHitToBlackboard(file, file.getMd5Hash(), hashSetName, comment, db.getSendIngestMessages()); + postHashSetHitToBlackboard(file, file.getMd5Hash(), db, comment); } } catch (TskCoreException ex) { logger.log(Level.SEVERE, String.format( @@ -501,33 +500,53 @@ public class HashDbIngestModule implements FileIngestModule { totals.totalCalctime.addAndGet(delta); } + /** + * Converts HashDb.KnownFilesType to a Score to be used to create an analysis result. + * @param knownFilesType The HashDb KnownFilesType to convert. + * @return The Score to use when creating an AnalysisResult. + */ + private Score getScore(HashDb.KnownFilesType knownFilesType) { + if (knownFilesType == null) { + return Score.SCORE_UNKNOWN; + } + switch (knownFilesType) { + case KNOWN: + return Score.SCORE_NONE; + case KNOWN_BAD: + return Score.SCORE_NOTABLE; + default: + case NO_CHANGE: + return Score.SCORE_UNKNOWN; + } + } /** * Post a hash set hit to the blackboard. * * @param abstractFile The file to be processed. * @param md5Hash The MD5 hash value of the file. - * @param hashSetName The name of the hash set with which to associate - * the hit. + * @param db The database in which this file was found. * @param comment A comment to be attached to the artifact. - * @param showInboxMessage Show a message in the inbox? */ @Messages({ "HashDbIngestModule.indexError.message=Failed to index hashset hit artifact for keyword search." }) - private void postHashSetHitToBlackboard(AbstractFile abstractFile, String md5Hash, String hashSetName, String comment, boolean showInboxMessage) { + private void postHashSetHitToBlackboard(AbstractFile abstractFile, String md5Hash, HashDb db, String comment) { try { String moduleName = HashLookupModuleFactory.getModuleName(); - Collection attributes = new ArrayList<>(); - //TODO Revisit usage of deprecated constructor as per TSK-583 - //BlackboardAttribute att2 = new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID(), MODULE_NAME, "Known Bad", hashSetName); - attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_SET_NAME, moduleName, hashSetName)); - attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_HASH_MD5, moduleName, md5Hash)); - attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COMMENT, moduleName, comment)); + List attributes = Arrays.asList( + new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_SET_NAME, moduleName, db.getDisplayName()), + new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_HASH_MD5, moduleName, md5Hash), + new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COMMENT, moduleName, comment) + ); + // BlackboardArtifact.Type artifactType, Score score, String conclusion, String configuration, String justification, Collection attributesList BlackboardArtifact badFile = abstractFile.newAnalysisResult( - new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_HASHSET_HIT), Score.SCORE_UNKNOWN, null, null, null, attributes) - .getAnalysisResult(); + BlackboardArtifact.Type.TSK_HASHSET_HIT, getScore(db.getKnownFilesType()), + null, db.getDisplayName(), null, + attributes + ).getAnalysisResult(); + try { /* * post the artifact which will index the artifact for keyword @@ -540,7 +559,7 @@ public class HashDbIngestModule implements FileIngestModule { Bundle.HashDbIngestModule_indexError_message(), badFile.getDisplayName()); } - if (showInboxMessage) { + if (db.getSendIngestMessages()) { StringBuilder detailsSb = new StringBuilder(); //details detailsSb.append(""); //NON-NLS @@ -565,7 +584,7 @@ public class HashDbIngestModule implements FileIngestModule { detailsSb.append(""); //NON-NLS - detailsSb.append(""); //NON-NLS + detailsSb.append(""); //NON-NLS detailsSb.append(""); //NON-NLS detailsSb.append("
") //NON-NLS .append(NbBundle.getMessage(this.getClass(), "HashDbIngestModule.postToBB.hashsetName")) .append("").append(hashSetName).append("").append(db.getDisplayName()).append("
"); //NON-NLS diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/Bundle.properties-MERGED index 6fb258f014..cccbcc1b57 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/Bundle.properties-MERGED @@ -2,7 +2,6 @@ FilesIdentifierIngestJobSettingsPanel.getError=Error getting interesting files s FilesIdentifierIngestJobSettingsPanel.updateError=Error updating interesting files sets settings file. FilesIdentifierIngestModule.getFilesError=Error getting interesting files sets from file. FilesIdentifierIngestModule.indexError.message=Failed to index interesting file hit artifact for keyword search. -# {0} - daysIncluded FilesSet.rule.dateRule.toString=(modified within {0} day(s)) FilesSetDefsPanel.bytes=Bytes FilesSetDefsPanel.cancelImportMsg=Cancel import @@ -122,8 +121,8 @@ FilesSetRulePanel.nameTextField.text= FilesSetRulePanel.ruleNameLabel.text=Rule Name (Optional): 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.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.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.invalidPathRegex=The path regular expression is not valid:\n\n{0} 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 diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/Bundle_ja.properties index 1496bd4c1f..6c61d90e3b 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/Bundle_ja.properties @@ -1,4 +1,4 @@ -#Fri Feb 12 16:56:29 UTC 2021 +#Mon Jul 12 13:22:00 UTC 2021 FilesIdentifierIngestJobSettingsPanel.border.title=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u4e2d\u306b\u6709\u52b9\u5316\u3059\u308b\u8208\u5473\u6df1\u3044\u30d5\u30a1\u30a4\u30eb\u30bb\u30c3\u30c8\u3092\u9078\u629e\: FilesIdentifierIngestJobSettingsPanel.getError=\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb\u304b\u3089\u8208\u5473\u6df1\u3044\u30d5\u30a1\u30a4\u30eb\u30bb\u30c3\u30c8\u3092\u53d6\u5f97\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 FilesIdentifierIngestJobSettingsPanel.updateError=\u8208\u5473\u6df1\u3044\u30d5\u30a1\u30a4\u30eb\u30bb\u30c3\u30c8\u306e\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb\u3092\u66f4\u65b0\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 @@ -92,6 +92,7 @@ FilesSetPanel.messages.filesSetsReservedName=\u30bd\u30d5\u30c8\u30a6\u30a7\u30a FilesSetPanel.rule.title=\u30d5\u30a1\u30a4\u30eb\u30d5\u30a3\u30eb\u30bf\u30fc\u30eb\u30fc\u30eb FilesSetRulePanel.CommaInRegexWarning=\u8b66\u544a\: \u30d5\u30a1\u30a4\u30eb\u62e1\u5f35\u5b50\u30d5\u30a3\u30fc\u30eb\u30c9\u306e\u30ab\u30f3\u30de\u306f\u6b63\u898f\u8868\u73fe\u306e\u4e00\u90e8\u3068\u3057\u3066\u89e3\u91c8\u3055\u308c\u3001\u8907\u6570\u306e\u62e1\u5f35\u5b50 (\u5165\u529b\u6570\: "{0}") \u306b\u5165\u529b\u3092\u5206\u5272\u3057\u307e\u305b\u3093\u3002 FilesSetRulePanel.DaysIncludedEmptyError=\u542b\u307e\u308c\u308b\u65e5\u6570\u306f\u6b63\u306e\u6574\u6570\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002 +FilesSetRulePanel.DaysIncludedInvalidError=\u542b\u307e\u308c\u308b\u65e5\u6570\u306f1\u4ee5\u4e0a\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002 FilesSetRulePanel.NoConditionError=\u30eb\u30fc\u30eb\u3092\u4f5c\u308b\u305f\u3081\u306e\u6761\u4ef6\u304c\u5c11\u306a\u304f\u3068\u30821\u3064\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002 FilesSetRulePanel.NoMimeTypeError=\u6709\u52b9\u306aMIME\u30bf\u30a4\u30d7\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002 FilesSetRulePanel.NoNameError=\u540d\u524d\u306f\u7a7a(\u672a\u5165\u529b)\u306b\u3067\u304d\u307e\u305b\u3093 diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesIdentifierIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesIdentifierIngestModule.java index 84d2737034..d447f204d5 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesIdentifierIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesIdentifierIngestModule.java @@ -53,7 +53,7 @@ import org.sleuthkit.datamodel.TskData; */ @NbBundle.Messages({"FilesIdentifierIngestModule.getFilesError=Error getting interesting files sets from file."}) final class FilesIdentifierIngestModule implements FileIngestModule { - + private static final Object sharedResourcesLock = new Object(); private static final Logger logger = Logger.getLogger(FilesIdentifierIngestModule.class.getName()); private static final IngestModuleReferenceCounter refCounter = new IngestModuleReferenceCounter(); @@ -144,9 +144,10 @@ final class FilesIdentifierIngestModule implements FileIngestModule { // Create artifact if it doesn't already exist. if (!blackboard.artifactExists(file, TSK_INTERESTING_FILE_HIT, attributes)) { BlackboardArtifact artifact = file.newAnalysisResult( - new BlackboardArtifact.Type(TSK_INTERESTING_FILE_HIT), Score.SCORE_UNKNOWN, null, null, null, attributes) + BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT, Score.SCORE_LIKELY_NOTABLE, + null, filesSet.getName(), null, + attributes) .getAnalysisResult(); - try { // Post thet artifact to the blackboard. diff --git a/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/Bundle_ja.properties index 984ae6bb6f..95faffcb64 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/Bundle_ja.properties @@ -1,4 +1,4 @@ -#Fri Feb 12 16:56:29 UTC 2021 +#Thu Jul 01 11:56:41 UTC 2021 ALeappAnalyzerIngestModule.aLeapp.cancelled=aLeapp\u5b9f\u884c\u304c\u30ad\u30e3\u30f3\u30bb\u30eb\u3055\u308c\u307e\u3057\u305f ALeappAnalyzerIngestModule.completed=aLeapp\u51e6\u7406\u304c\u5b8c\u4e86\u3057\u307e\u3057\u305f ALeappAnalyzerIngestModule.error.creating.output.dir=aLeapp\u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u51fa\u529b\u30d5\u30a9\u30eb\u30c0\u30fc\u306e\u4f5c\u6210\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 @@ -16,6 +16,7 @@ ALeappAnalyzerIngestModule.running.aLeapp=aLeapp\u5b9f\u884c\u4e2d ALeappAnalyzerIngestModule.starting.aLeapp=aLeapp\u306e\u958b\u59cb ALeappAnalyzerModuleFactory_moduleDesc=aLEAPP\u3092\u4f7f\u7528\u3057\u3066\u3001Android\u30c7\u30d0\u30a4\u30b9\u306e\u8ad6\u7406\u7684\u306a\u53d6\u5f97\u3092\u5206\u6790\u3057\u307e\u3059\u3002 ALeappAnalyzerModuleFactory_moduleName=Android\u30a2\u30ca\u30e9\u30a4\u30b6\u30fc\uff08aLEAPP\uff09 +AleappAnalyzerIngestModule.not.64.bit.os=aLeapp\u306f32\u30d3\u30c3\u30c8\u30aa\u30da\u30ec\u30fc\u30c6\u30a3\u30f3\u30b0\u30b7\u30b9\u30c6\u30e0\u3067\u306f\u5b9f\u884c\u3055\u308c\u307e\u305b\u3093 ILeappAnalyzerIngestModule.completed=iLeapp\u51e6\u7406\u304c\u5b8c\u4e86\u3057\u307e\u3057\u305f ILeappAnalyzerIngestModule.error.creating.output.dir=iLeapp\u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u51fa\u529b\u30d5\u30a9\u30eb\u30c0\u30fc\u306e\u4f5c\u6210\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 ILeappAnalyzerIngestModule.error.ileapp.file.processor.init=ILeappProcessFile\u306e\u521d\u671f\u5316\u306b\u5931\u6557\u3057\u307e\u3057\u305f @@ -33,8 +34,14 @@ ILeappAnalyzerIngestModule.running.iLeapp=iLeapp\u5b9f\u884c\u4e2d ILeappAnalyzerIngestModule.starting.iLeapp=iLeapp\u306e\u958b\u59cb ILeappAnalyzerModuleFactory_moduleDesc=iLEAPP\u3092\u4f7f\u7528\u3057\u3066\u3001iOS\u30c7\u30d0\u30a4\u30b9\u306e\u8ad6\u7406\u7684\u306a\u53d6\u5f97\u3092\u5206\u6790\u3057\u307e\u3059\u3002 ILeappAnalyzerModuleFactory_moduleName=iOS\u30a2\u30ca\u30e9\u30a4\u30b6\u30fc\uff08iLEAPP\uff09 +IleappAnalyzerIngestModule.not.64.bit.os=iLeapp\u306f32\u30d3\u30c3\u30c8\u30aa\u30da\u30ec\u30fc\u30c6\u30a3\u30f3\u30b0\u30b7\u30b9\u30c6\u30e0\u3067\u306f\u5b9f\u884c\u3055\u308c\u307e\u305b\u3093 LeappFileProcessor.Leapp.cancelled=Leapp\u5b9f\u884c\u304c\u30ad\u30e3\u30f3\u30bb\u30eb\u3055\u308c\u307e\u3057\u305f -LeappFileProcessor.cannot.load.artifact.xml=xml\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u30d5\u30a1\u30a4\u30eb\u3092\u8aad\u307f\u8fbc\u3081\u307e\u305b\u3093\u3002 +LeappFileProcessor.cannot.create.calllog.relationship=TSK_CALLLOG\u95a2\u4fc2\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\u3002 +LeappFileProcessor.cannot.create.contact.relationship=TSK_CONTACT\u95a2\u4fc2\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\u3002 +LeappFileProcessor.cannot.create.message.relationship=TSK_MESSAGE\u95a2\u4fc2\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\u3002 +LeappFileProcessor.cannot.create.trackpoint.relationship=TSK_TRACK_POINT\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\u3002 +LeappFileProcessor.cannot.create.waypoint.relationship=TSK_WAYPOINT\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\u3002 +LeappFileProcessor.cannot.load.artifact.xml=xml\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u30fb\u30d5\u30a1\u30a4\u30eb\u3092\u8aad\u307f\u8fbc\u3081\u307e\u305b\u3093\u3002 LeappFileProcessor.cannotBuildXmlParser=XML\u30d1\u30fc\u30b5\u30fc\u3092\u69cb\u7bc9\u3067\u304d\u307e\u305b\u3093\u3002 LeappFileProcessor.completed=Leapp\u51e6\u7406\u304c\u5b8c\u4e86\u3057\u307e\u3057\u305f LeappFileProcessor.error.creating.new.artifacts=\u65b0\u3057\u3044\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u306e\u4f5c\u6210\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 diff --git a/Core/src/org/sleuthkit/autopsy/modules/photoreccarver/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/modules/photoreccarver/Bundle.properties-MERGED index 1d07988e4c..f5dd54dc50 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/photoreccarver/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/modules/photoreccarver/Bundle.properties-MERGED @@ -24,7 +24,7 @@ PhotoRecIngestModule.complete.totalParsetime=Total Parsing Time: 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.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.complete.numberOfErrors=Number of Errors while Carving: PhotoRecCarverIngestJobSettingsPanel.detectionSettingsLabel.text=PhotoRec Settings diff --git a/Core/src/org/sleuthkit/autopsy/modules/pictureanalyzer/impls/EXIFProcessor.java b/Core/src/org/sleuthkit/autopsy/modules/pictureanalyzer/impls/EXIFProcessor.java index 12872f69c1..99a1920818 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/pictureanalyzer/impls/EXIFProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/modules/pictureanalyzer/impls/EXIFProcessor.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2020 Basis Technology Corp. + * Copyright 2011-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -49,7 +49,6 @@ import org.sleuthkit.autopsy.modules.pictureanalyzer.PictureAnalyzerIngestModule import org.sleuthkit.datamodel.Blackboard; import org.sleuthkit.datamodel.BlackboardArtifact; import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_METADATA_EXIF; -import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_USER_CONTENT_SUSPECTED; import org.sleuthkit.datamodel.BlackboardAttribute; import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE; import org.sleuthkit.datamodel.Content; @@ -150,10 +149,14 @@ public class EXIFProcessor implements PictureProcessor { if (!attributes.isEmpty() && !blackboard.artifactExists(file, TSK_METADATA_EXIF, attributes)) { - final BlackboardArtifact exifArtifact = file.newDataArtifact(new BlackboardArtifact.Type(TSK_METADATA_EXIF), attributes); + final BlackboardArtifact exifArtifact = (file.newAnalysisResult( + BlackboardArtifact.Type.TSK_METADATA_EXIF, + Score.SCORE_NONE, + null, null, null, + attributes)).getAnalysisResult(); final BlackboardArtifact userSuspectedArtifact = file.newAnalysisResult( - new BlackboardArtifact.Type(TSK_USER_CONTENT_SUSPECTED), Score.SCORE_UNKNOWN, null, null, null, + BlackboardArtifact.Type.TSK_USER_CONTENT_SUSPECTED, Score.SCORE_UNKNOWN, null, null, null, Arrays.asList(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT, MODULE_NAME, Bundle.ExifProcessor_userContent_description()))) .getAnalysisResult(); diff --git a/Core/src/org/sleuthkit/autopsy/modules/plaso/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/modules/plaso/Bundle_ja.properties index 4049f253b3..76fefdfd60 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/plaso/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/plaso/Bundle_ja.properties @@ -1,3 +1,28 @@ -#Tue Aug 18 18:09:21 UTC 2020 +#Mon Jul 12 13:22:00 UTC 2021 +PlasoIngestModule.artifact.progress=\u30b1\u30fc\u30b9\u306b\u30a4\u30d9\u30f3\u30c8\u3092\u8ffd\u52a0\uff1a{0} +PlasoIngestModule.bad.imageFile=\u753b\u50cf\u30d5\u30a1\u30a4\u30eb\u306e\u540d\u524d\u3068\u30d1\u30b9\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093 +PlasoIngestModule.completed=Plaso\u51e6\u7406\u304c\u5b8c\u4e86\u3057\u307e\u3057\u305f +PlasoIngestModule.create.artifacts.cancelled=Plaso\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u306e\u4f5c\u6210\u3092\u30ad\u30e3\u30f3\u30bb\u30eb\u3057\u307e\u3057\u305f PlasoIngestModule.dataSource.not.an.image=\u975e\u30c7\u30a3\u30b9\u30af\u30a4\u30e1\u30fc\u30b8\u30fb\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u30b9\u30ad\u30c3\u30d7\u3057\u307e\u3059 +PlasoIngestModule.error.creating.output.dir=Plaso\u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u51fa\u529b\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u306e\u4f5c\u6210\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +PlasoIngestModule.error.running.log2timeline=Plaso\u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u51fa\u529b\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u306e\u4f5c\u6210\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +PlasoIngestModule.error.running.psort=log2timeline\u5b9f\u884c\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3001\u30ed\u30b0\u30d5\u30a1\u30a4\u30eb\u3092\u53c2\u7167\u3057\u3066\u304f\u3060\u3055\u3044\u3002 +PlasoIngestModule.event.datetime=\u30a4\u30d9\u30f3\u30c8\u65e5\u6642 +PlasoIngestModule.event.description=\u30a4\u30d9\u30f3\u30c8\u306e\u8aac\u660e +PlasoIngestModule.exception.posting.artifact=\u4f8b\u5916\u6295\u7a3f\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u3002 +PlasoIngestModule.executable.not.found=Plaso\u5b9f\u884c\u30d5\u30a1\u30a4\u30eb\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3002 PlasoIngestModule.has.run=Plaso +PlasoIngestModule.info.empty.database=Plaso\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304c\u7a7a\u3067\u3057\u305f\u3002 +PlasoIngestModule.log2timeline.cancelled=Log2timeline\u306e\u5b9f\u884c\u304c\u30ad\u30e3\u30f3\u30bb\u30eb\u3055\u308c\u307e\u3057\u305f +PlasoIngestModule.psort.fail=Plaso\u306f\u3001\u30a4\u30d9\u30f3\u30c8\u4e26\u66ff\u3048\u6642\u306b\u30a8\u30e9\u30fc\u767a\u751f\u3001\u7d50\u679c\u306f\u5b8c\u5168\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002 +PlasoIngestModule.requires.windows=Plaso\u30e2\u30b8\u30e5\u30fc\u30eb\u306b\u306f\u30a6\u30a3\u30f3\u30c9\u30a6\u304c\u5fc5\u8981\u3067\u3059\u3002 +PlasoIngestModule.running.psort=Psort\u5b9f\u884c\u4e2d +PlasoIngestModule.starting.log2timeline=Log2timeline\u3092\u958b\u59cb\u3057\u307e\u3059 +PlasoModuleFactory.ingestJobSettings.exception.msg=\u8a2d\u5b9a\u5f15\u6570\u306fPlasoModuleSettings\u3092\u60f3\u5b9a\u3057\u3066\u3044\u307e\u3057\u305f +PlasoModuleFactory_moduleDesc=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u306b\u5bfe\u3057\u3066Plaso\u3092\u5b9f\u884c\u3057\u307e\u3059\u3002 +PlasoModuleFactory_moduleName=Plaso +PlasoModuleSettingsPanel.disabledNoteLabel.text=*\u65e2\u5b58\u306eAutopsy\u30e2\u30b8\u30e5\u30fc\u30eb\u3068\u91cd\u8907\u3057\u3066\u3044\u308b\u305f\u3081\u7121\u52b9\u306b\u306a\u3063\u3066\u3044\u307e\u3059\u3002 +PlasoModuleSettingsPanel.noteLabel.text=\u6ce8\uff1a\u3053\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u5b9f\u884c\u306b\u306f\u6642\u9593\u304c\u304b\u304b\u308b\u5834\u5408\u304c\u3042\u308a\u307e\u3059\u3002 +PlasoModuleSettingsPanel.peCheckBox.text=pe\uff1aPortable Executable\uff08PE\uff09\u30d5\u30a1\u30a4\u30eb\u306e\u30d1\u30fc\u30b5\u30fc\u3002 +PlasoModuleSettingsPanel.plasoParserInfoTextArea.text=chrome_cache*\u3068\u4e0b\u8a18\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u4ee5\u5916\u306f\u6709\u52b9\u306b\u306a\u308a\u307e\u3059\u3002 \u3053\u308c\u3089\u3092\u6709\u52b9\u306b\u3059\u308b\u3068\u3001Plaso\u306e\u5b9f\u884c\u901f\u5ea6\u304c\u4f4e\u4e0b\u3057\u307e\u3059\u3002 +PlasoModuleSettingsPanel.winRegCheckBox.text=winreg\uff1aWindows NT\u30ec\u30b8\u30b9\u30c8\u30ea\uff08REGF\uff09\u30d5\u30a1\u30a4\u30eb\u306e\u30d1\u30fc\u30b5\u30fc\u3002 diff --git a/Core/src/org/sleuthkit/autopsy/modules/yara/YaraIngestHelper.java b/Core/src/org/sleuthkit/autopsy/modules/yara/YaraIngestHelper.java index cdc1e3f02e..f096882520 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/yara/YaraIngestHelper.java +++ b/Core/src/org/sleuthkit/autopsy/modules/yara/YaraIngestHelper.java @@ -35,7 +35,6 @@ import org.sleuthkit.autopsy.yara.YaraJNIWrapper; import org.sleuthkit.autopsy.yara.YaraWrapperException; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; -import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_YARA_HIT; import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME; import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_RULE; import org.sleuthkit.datamodel.BlackboardAttribute; @@ -46,7 +45,7 @@ import org.sleuthkit.datamodel.TskCoreException; * Methods for scanning files for yara rule matches. */ final class YaraIngestHelper { - + private static final String YARA_DIR = "yara"; private static final String YARA_C_EXE = "yarac64.exe"; private static final String MODULE_NAME = YaraIngestModuleFactory.getModuleName(); @@ -207,7 +206,7 @@ final class YaraIngestHelper { attributes.add(new BlackboardAttribute(TSK_SET_NAME, MODULE_NAME, ruleSetName)); attributes.add(new BlackboardAttribute(TSK_RULE, MODULE_NAME, rule)); - BlackboardArtifact artifact = abstractFile.newAnalysisResult(new BlackboardArtifact.Type(TSK_YARA_HIT), Score.SCORE_UNKNOWN, null, null, null, attributes) + BlackboardArtifact artifact = abstractFile.newAnalysisResult(BlackboardArtifact.Type.TSK_YARA_HIT, Score.SCORE_NOTABLE, null, ruleSetName, rule, attributes) .getAnalysisResult(); artifacts.add(artifact); diff --git a/Core/src/org/sleuthkit/autopsy/python/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/python/Bundle_ja.properties index fdbd43efd7..6bdaf64a9a 100644 --- a/Core/src/org/sleuthkit/autopsy/python/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/python/Bundle_ja.properties @@ -1,2 +1,5 @@ -JythonModuleLoader.errorMessages.failedToOpenModule={0}\u304c\u958b\u3051\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u8a73\u7d30\u306f\u30ed\u30b0\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002 +#Mon Jul 12 13:22:00 UTC 2021 JythonModuleLoader.errorMessages.failedToLoadModule={0}. {1}. \u304c\u958b\u3051\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u8a73\u7d30\u306f\u30ed\u30b0\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002 +JythonModuleLoader.errorMessages.failedToOpenModule={0}\u304c\u958b\u3051\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u8a73\u7d30\u306f\u30ed\u30b0\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002 +JythonModuleLoader.pythonInterpreterError.msg=Python\u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u30ed\u30fc\u30c9\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002\u8a73\u7d30\u306b\u3064\u3044\u3066\u306f\u30ed\u30b0\u3092\u53c2\u7167\u3057\u3066\u304f\u3060\u3055\u3044 +JythonModuleLoader.pythonInterpreterError.title=Python\u30e2\u30b8\u30e5\u30fc\u30eb diff --git a/Core/src/org/sleuthkit/autopsy/rejview/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/rejview/Bundle_ja.properties new file mode 100644 index 0000000000..af5b58d908 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/rejview/Bundle_ja.properties @@ -0,0 +1,2 @@ +#Thu Jul 01 11:56:41 UTC 2021 +RejTreeKeyView.template.dateTime=\u5909\u66f4\u6642\u9593\uff1a diff --git a/Core/src/org/sleuthkit/autopsy/report/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/report/Bundle_ja.properties index 8dc01dddb4..3fce60a776 100644 --- a/Core/src/org/sleuthkit/autopsy/report/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/report/Bundle_ja.properties @@ -1,28 +1,52 @@ -OpenIDE-Module-Name=\u30ec\u30dd\u30fc\u30c8 -CTL_ReportWizardAction=\u30ec\u30dd\u30fc\u30c8\u3092\u5b9f\u884c -ArtifactSelectionDialog.titleLabel.text=\u30ec\u30dd\u30fc\u30c8\u4f5c\u6210\u5bfe\u8c61\u306e\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u3092\u9078\u629e: +#Mon Jul 12 13:22:00 UTC 2021 +ArtifactSelectionDialog.deselectAllButton.text=\u3059\u3079\u3066\u9078\u629e\u89e3\u9664 +ArtifactSelectionDialog.dlgTitle.text=\u9ad8\u5ea6\u306a\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u9078\u629e ArtifactSelectionDialog.okButton.text=OK +ArtifactSelectionDialog.selectAllButton.text=\u3059\u3079\u3066\u9078\u629e +ArtifactSelectionDialog.titleLabel.text=\u30ec\u30dd\u30fc\u30c8\u4f5c\u6210\u5bfe\u8c61\u306e\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u3092\u9078\u629e\: +CTL_ReportWizardAction=\u30ec\u30dd\u30fc\u30c8\u3092\u5b9f\u884c +CreatePortableCasePanel.chooseOutputFolderButton.text=\u30d5\u30a9\u30eb\u30c0\u30fc\u3092\u9078\u629e +CreatePortableCasePanel.deselectAllButton.text=\u3059\u3079\u3066\u9078\u629e\u89e3\u9664 +CreatePortableCasePanel.errorLabel.text_1=Windows\u306e\u307f +CreatePortableCasePanel.jLabel1.text=\u6b21\u3068\u3057\u3066\u30bf\u30b0\u4ed8\u3051\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb\u3092\u30a8\u30af\u30b9\u30dd\u30fc\u30c8\: +CreatePortableCasePanel.jLabel2.text=\u51fa\u529b\u30d5\u30a9\u30eb\u30c0\u30fc\u3092\u9078\u629e\: +CreatePortableCasePanel.outputFolderTextField.text=jTextField1 +CreatePortableCasePanel.selectAllButton.text=\u3059\u3079\u3066\u9078\u629e +DefaultReportConfigurationPanel.infoLabel.text=\u3053\u306e\u30ec\u30dd\u30fc\u30c8\u306f\u6b21\u306e\u753b\u9762\u3067\u69cb\u6210\u3055\u308c\u307e\u3059\u3002 +FileReportDataTypes.aTime.text=\u6700\u7d42\u30a2\u30af\u30bb\u30b9\u65e5 +FileReportDataTypes.address.text=\u30a2\u30c9\u30ec\u30b9 +FileReportDataTypes.crTime.text=\u4f5c\u6210\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb +FileReportDataTypes.fileExt.text=\u30d5\u30a1\u30a4\u30eb\u62e1\u5f35\u5b50 +FileReportDataTypes.fileType.text=\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7 +FileReportDataTypes.filename.text=\u540d\u524d +FileReportDataTypes.hash.text=\u30cf\u30c3\u30b7\u30e5\u5024 +FileReportDataTypes.isDel.text=\u524a\u9664\u3055\u308c\u3066\u3044\u307e\u3059 +FileReportDataTypes.knownStatus.text=\u65e2\u77e5\u306e\u30b9\u30c6\u30fc\u30bf\u30b9 +FileReportDataTypes.mTime.text=\u6700\u7d42\u66f4\u65b0\u65e5 +FileReportDataTypes.path.text=\u5b8c\u5168\u306a\u30d1\u30b9 +FileReportDataTypes.perms.text=\u30a2\u30af\u30bb\u30b9\u6a29 +FileReportDataTypes.size.text=\u30b5\u30a4\u30ba +FileReportText.getDesc.text=\u30b1\u30fc\u30b9\u306e\u500b\u3005\u306e\u30d5\u30a1\u30a4\u30eb\u306b\u95a2\u3059\u308b\u60c5\u5831\u3092\u542b\u3080\u533a\u5207\u308a\u30c6\u30ad\u30b9\u30c8\u30d5\u30a1\u30a4\u30eb\u3067\u3059\u3002 +FileReportText.getName.text=\u30d5\u30a1\u30a4\u30eb - \u30c6\u30ad\u30b9\u30c8 +OpenIDE-Module-Name=\u30ec\u30dd\u30fc\u30c8 +PortableCaseInterestingItemsListPanel.descLabel.text=\u3053\u308c\u3089\u306e\u30bb\u30c3\u30c8\u306e\u8208\u5473\u6df1\u3044\u9805\u76ee\u3092\u542b\u3080\: +PortableCaseInterestingItemsListPanel.deselectButton.text=\u3059\u3079\u3066\u9078\u629e\u89e3\u9664 PortableCaseInterestingItemsListPanel.error.errorLoadingTags=\u8208\u5473\u6df1\u3044\u9805\u76ee\u30bb\u30c3\u30c8\u540d\u306e\u8aad\u307f\u8fbc\u307f\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f PortableCaseInterestingItemsListPanel.error.errorTitle=\u30b1\u30fc\u30b9\u306e\u8208\u5473\u6df1\u3044\u9805\u76ee\u30bb\u30c3\u30c8\u540d\u306e\u53d6\u5f97\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f PortableCaseInterestingItemsListPanel.error.noOpenCase=\u958b\u3044\u3066\u3044\u308b\u30b1\u30fc\u30b9\u304c\u3042\u308a\u307e\u305b\u3093 +PortableCaseInterestingItemsListPanel.selectButton.text=\u3059\u3079\u3066\u9078\u629e PortableCaseReportModule.compressCase.canceled=\u30e6\u30fc\u30b6\u30fc\u306b\u3088\u3063\u3066\u5727\u7e2e\u304c\u53d6\u308a\u6d88\u3055\u308c\u307e\u3057\u305f PortableCaseReportModule.compressCase.errorCompressingCase=\u30b1\u30fc\u30b9\u306e\u5727\u7e2e\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f -# {0} - \u4e00\u6642\u30d5\u30a9\u30eb\u30c0\u30fc\u30d1\u30b9 PortableCaseReportModule.compressCase.errorCreatingTempFolder=\u4e00\u6642\u30d5\u30a9\u30eb\u30c0\u30fc {0} \u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f PortableCaseReportModule.compressCase.errorFinding7zip=7-Zip\u5b9f\u884c\u53ef\u80fd\u30d5\u30a1\u30a4\u30eb\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f -# {0} - \u30d5\u30a1\u30a4\u30eb\u540d PortableCaseReportModule.copyContentToPortableCase.copyingFile={0} \u30d5\u30a1\u30a4\u30eb\u306e\u30b3\u30d4\u30fc\u4e2d\u3067\u3059 -# {0} - \u30b1\u30fc\u30b9\u30d5\u30a9\u30eb\u30c0\u30fc PortableCaseReportModule.createCase.caseDirExists=\u30b1\u30fc\u30b9\u30d5\u30a9\u30eb\u30c0\u30fc {0} \u304c\u3059\u3067\u306b\u5b58\u5728\u3057\u307e\u3059 PortableCaseReportModule.createCase.errorCreatingCase=\u30b1\u30fc\u30b9\u306e\u4f5c\u6210\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f -# {0} - \u30d5\u30a9\u30eb\u30c0\u30fc PortableCaseReportModule.createCase.errorCreatingFolder=Error creating \u30d5\u30a9\u30eb\u30c0\u30fc {0} \u306e\u4f5c\u6210\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f PortableCaseReportModule.createCase.errorStoringMaxIds=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9ID\u306e\u6700\u5927\u6570\u3092\u4fdd\u5b58\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f PortableCaseReportModule.generateReport.caseClosed=\u73fe\u5728\u306e\u30b1\u30fc\u30b9\u304c\u9589\u3058\u3089\u308c\u307e\u3057\u305f\u3002 PortableCaseReportModule.generateReport.compressingCase=\u30b1\u30fc\u30b9\u3092\u5727\u7e2e\u4e2d\u3067\u3059... -# {0} - \u30bf\u30b0\u540d PortableCaseReportModule.generateReport.copyingArtifacts={0} \u3068\u3057\u3066\u30bf\u30b0\u4ed8\u3051\u3055\u308c\u305f\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u3092\u30b3\u30d4\u30fc\u4e2d\u3067\u3059... -# {0} - \u30bf\u30b0\u540d PortableCaseReportModule.generateReport.copyingFiles={0} \u3068\u3057\u3066\u30bf\u30b0\u4ed8\u3051\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb\u3092\u30b3\u30d4\u30fc\u4e2d\u3067\u3059... PortableCaseReportModule.generateReport.copyingTags=\u30bf\u30b0\u3092\u30b3\u30d4\u30fc\u4e2d\u3067\u3059... PortableCaseReportModule.generateReport.creatingCase=\u30dd\u30fc\u30bf\u30d6\u30eb\u30b1\u30fc\u30b9\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u4f5c\u6210\u4e2d\u3067\u3059... @@ -31,303 +55,265 @@ PortableCaseReportModule.generateReport.errorCopyingFiles=\u30bf\u30b0\u4ed8\u30 PortableCaseReportModule.generateReport.errorCopyingInterestingFiles=\u8208\u5473\u6df1\u3044\u30d5\u30a1\u30a4\u30eb\u306e\u30b3\u30d4\u30fc\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f PortableCaseReportModule.generateReport.errorCopyingInterestingResults=\u8208\u5473\u6df1\u3044\u7d50\u679c\u306e\u30b3\u30d4\u30fc\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f PortableCaseReportModule.generateReport.errorCopyingTags=\u30bf\u30b0\u306e\u30b3\u30d4\u30fc\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f -# {0} - \u5c5e\u6027\u30bf\u30a4\u30d7\u540d PortableCaseReportModule.generateReport.errorLookingUpAttrType=\u5c5e\u6027\u30bf\u30a4\u30d7 {0} \u306e\u691c\u7d22\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f PortableCaseReportModule.generateReport.interestingItemError=\u8208\u5473\u6df1\u3044\u9805\u76ee\u306e\u8aad\u307f\u8fbc\u307f\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f PortableCaseReportModule.generateReport.noContentToCopy=\u30b3\u30d4\u30fc\u3059\u308b\u8208\u5473\u6df1\u3044\u30d5\u30a1\u30a4\u30eb\u3001\u7d50\u679c\u3001\u307e\u305f\u306f\u30bf\u30b0\u4ed8\u304d\u9805\u76ee\u304c\u3042\u308a\u307e\u305b\u3093 -# {0} - \u51fa\u529b\u30d5\u30a9\u30eb\u30c0\u30fc PortableCaseReportModule.generateReport.outputDirDoesNotExist=\u51fa\u529b\u30d5\u30a9\u30eb\u30c0\u30fc {0} \u304c\u5b58\u5728\u3057\u307e\u305b\u3093 -# {0} - \u51fa\u529b\u30d5\u30a9\u30eb\u30c0\u30fc PortableCaseReportModule.generateReport.outputDirIsNotDir=\u51fa\u529b\u30d5\u30a9\u30eb\u30c0\u30fc {0} \u306f\u30d5\u30a9\u30eb\u30c0\u30fc\u3067\u306f\u3042\u308a\u307e\u305b\u3093 PortableCaseReportModule.generateReport.verifying=\u9078\u629e\u3057\u305f\u30d1\u30e9\u30e1\u30fc\u30bf\u30fc\u3092\u691c\u8a3c\u4e2d\u3067\u3059... PortableCaseReportModule.getDescription.description=\u9078\u629e\u3057\u305f\u9805\u76ee\u3092\u7c21\u5358\u306b\u5171\u6709\u53ef\u80fd\u306a\u65b0\u898f\u30b7\u30f3\u30b0\u30eb\u30e6\u30fc\u30b6\u30fc\u30b1\u30fc\u30b9\u306b\u30b3\u30d4\u30fc\u3057\u307e\u3059 PortableCaseReportModule.getName.name=\u30dd\u30fc\u30bf\u30d6\u30eb\u30b1\u30fc\u30b9 +PortableCaseTagsListPanel.descLabel.text=\u6b21\u306e\u30bf\u30b0\u3092\u542b\u3080\: +PortableCaseTagsListPanel.deselectButton.text=\u3059\u3079\u3066\u9078\u629e\u89e3\u9664 PortableCaseTagsListPanel.error.errorLoadingTags=\u30bf\u30b0\u306e\u8aad\u307f\u8fbc\u307f\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f PortableCaseTagsListPanel.error.errorTitle=\u30b1\u30fc\u30b9\u306e\u30bf\u30b0\u540d\u3092\u53d6\u5f97\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f PortableCaseTagsListPanel.error.noOpenCase=\u958b\u3044\u3066\u3044\u308b\u30b1\u30fc\u30b9\u304c\u3042\u308a\u307e\u305b\u3093 -ReportExcel.exceptionMessage.dataTooLarge=\u5024\u304c\u9577\u3059\u304e\u3066Excel\u306e\u30bb\u30eb\u5185\u306b\u53ce\u307e\u308a\u307e\u305b\u3093\u3002 -ReportExcel.exceptionMessage.errorText=Excel\u306e\u30bb\u30eb\u5185\u3067\u30c7\u30fc\u30bf\u3092\u8868\u793a\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 -ReportExcel.writeSummary.caseName=\u30b1\u30fc\u30b9\u540d: -ReportExcel.writeSummary.caseNotes=\u30b1\u30fc\u30b9\u5099\u8003: -ReportExcel.writeSummary.caseNum=\u30b1\u30fc\u30b9\u756a\u53f7: -ReportExcel.writeSummary.examiner=\u8abf\u67fb\u54e1: -ReportExcel.writeSummary.numImages=\u30a4\u30e1\u30fc\u30b8\u6570: -ReportExcel.writeSummary.sheetName=\u30b5\u30de\u30ea\u30fc -ReportExcel.writeSummary.summary=\u30b5\u30de\u30ea\u30fc -ReportGenerator.artTableColHdr.comment=\u30b3\u30e1\u30f3\u30c8 -ReportGenerator.errList.noOpenCase=\u958b\u3044\u3066\u3044\u308b\u30b1\u30fc\u30b9\u306f\u3042\u308a\u307e\u305b\u3093\u3002 -ReportGenerator.tagTable.header.userName=\u30e6\u30fc\u30b6\u30fc\u540d -ReportHTML.writeSum.case=\u30b1\u30fc\u30b9: -ReportHTML.writeSum.caseNotes=\u5099\u8003: -ReportHTML.writeSum.caseNumber=\u30b1\u30fc\u30b9\u756a\u53f7: -ReportHTML.writeSum.caseNumImages=\u30a4\u30e1\u30fc\u30b8\u6570: -ReportHTML.writeSum.examiner=\u8abf\u67fb\u54e1: -ReportVisualPanel1.reportModulesLabel.text=\u30ec\u30dd\u30fc\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb: -ReportVisualPanel1.invalidModuleWarning=\u7121\u52b9\u306a\u30ec\u30dd\u30fc\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb ({0}) \u306b\u906d\u9047\u3057\u307e\u3057\u305f -DefaultReportConfigurationPanel.infoLabel.text=\u3053\u306e\u30ec\u30dd\u30fc\u30c8\u306f\u6b21\u306e\u753b\u9762\u3067\u69cb\u6210\u3055\u308c\u307e\u3059\u3002 -ReportVisualPanel2.dataLabel.text=\u30ec\u30dd\u30fc\u30c8\u4f5c\u6210\u5bfe\u8c61\u306e\u30c7\u30fc\u30bf\u3092\u9078\u629e: -ReportVisualPanel2.deselectAllButton.text=\u3059\u3079\u3066\u9078\u629e\u89e3\u9664 -ReportVisualPanel2.selectAllButton.text=\u3059\u3079\u3066\u9078\u629e -ReportVisualPanel2.advancedButton.text=\u30c7\u30fc\u30bf\u30bf\u30a4\u30d7 -ArtifactSelectionDialog.deselectAllButton.text=\u3059\u3079\u3066\u9078\u629e\u89e3\u9664 -ArtifactSelectionDialog.selectAllButton.text=\u3059\u3079\u3066\u9078\u629e -ReportGenerationPanel.closeButton.text=\u9589\u3058\u308b -ReportProgressPanel.reportLabel.text=reportLabel -ReportProgressPanel.pathLabel.text=pathLabel -ReportProgressPanel.separationLabel.text=: -ReportProgressPanel.statusMessageLabel.text=processingLabel -ReportGenerationPanel.titleLabel.text=\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u9032\u6357\u72b6\u6cc1 -ReportVisualPanel2.taggedResultsRadioButton.text=\u30bf\u30b0\u4ed8\u304d\u7d50\u679c -ReportVisualPanel2.allResultsRadioButton.text=\u3059\u3079\u3066\u306e\u7d50\u679c -ReportWizardFileOptionsVisualPanel.selectAllButton.text=\u3059\u3079\u3066\u9078\u629e -ReportWizardFileOptionsVisualPanel.deselectAllButton.text=\u3059\u3079\u3066\u9078\u629e\u89e3\u9664 -ReportWizardFileOptionsVisualPanel.jLabel1.text=\u6b21\u306e\u30d5\u30a1\u30a4\u30eb\u30ec\u30dd\u30fc\u30c8\u306b\u542b\u3081\u308b\u9805\u76ee\u3092\u9078\u629e: -ArtifactSelectionDialog.dlgTitle.text=\u9ad8\u5ea6\u306a\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u9078\u629e -FileReportDataTypes.filename.text=\u540d\u524d -FileReportDataTypes.fileExt.text=\u30d5\u30a1\u30a4\u30eb\u62e1\u5f35\u5b50 -FileReportDataTypes.fileType.text=\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7 -FileReportDataTypes.isDel.text=\u524a\u9664\u3055\u308c\u3066\u3044\u307e\u3059 -FileReportDataTypes.aTime.text=\u6700\u7d42\u30a2\u30af\u30bb\u30b9\u65e5 -FileReportDataTypes.crTime.text=\u4f5c\u6210\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb -FileReportDataTypes.mTime.text=\u6700\u7d42\u66f4\u65b0\u65e5 -FileReportDataTypes.size.text=\u30b5\u30a4\u30ba -FileReportDataTypes.address.text=\u30a2\u30c9\u30ec\u30b9 -FileReportDataTypes.hash.text=\u30cf\u30c3\u30b7\u30e5\u5024 -FileReportDataTypes.knownStatus.text=\u65e2\u77e5\u306e\u30b9\u30c6\u30fc\u30bf\u30b9 -FileReportDataTypes.perms.text=\u30a2\u30af\u30bb\u30b9\u6a29 -FileReportDataTypes.path.text=\u5b8c\u5168\u306a\u30d1\u30b9 -FileReportText.getName.text=\u30d5\u30a1\u30a4\u30eb - \u30c6\u30ad\u30b9\u30c8 -FileReportText.getDesc.text=\u30b1\u30fc\u30b9\u306e\u500b\u3005\u306e\u30d5\u30a1\u30a4\u30eb\u306b\u95a2\u3059\u308b\u60c5\u5831\u3092\u542b\u3080\u533a\u5207\u308a\u30c6\u30ad\u30b9\u30c8\u30d5\u30a1\u30a4\u30eb\u3067\u3059\u3002 -ReportBodyFile.progress.querying=\u30d5\u30a1\u30a4\u30eb\u3092\u30af\u30a8\u30ea\u4e2d\u3067\u3059... -ReportBodyFile.ingestWarning.text=\u8b66\u544a: \u3053\u306e\u30ec\u30dd\u30fc\u30c8\u306f\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30b5\u30fc\u30d3\u30b9\u306e\u5b8c\u4e86\u524d\u306b\u5b9f\u884c\u3055\u308c\u307e\u3057\u305f\\uff01 -ReportBodyFile.progress.loading=\u30d5\u30a1\u30a4\u30eb\u306e\u8aad\u307f\u8fbc\u307f\u4e2d\u3067\u3059... -ReportBodyFile.progress.processing={0} \u3092\u73fe\u5728\u51e6\u7406\u4e2d\u3067\u3059... -ReportBodyFile.getName.text=TSK Body\u30d5\u30a1\u30a4\u30eb +PortableCaseTagsListPanel.selectButton.text=\u3059\u3079\u3066\u9078\u629e +ReportBodyFile.generateReport.srcModuleName.text=TSK Body\u30d5\u30a1\u30a4\u30eb ReportBodyFile.getDesc.text=\u3059\u3079\u3066\u306e\u30d5\u30a1\u30a4\u30eb\u306b\u5bfe\u5fdc\u3057\u305f\u3001MAC\u56de\u6570\u3092\u6301\u3064Body\u30d5\u30a1\u30a4\u30eb\u5f62\u5f0f\u3067\u3059\u3002\u3053\u306e\u5f62\u5f0f\u306f\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u30d3\u30e5\u30fc\u306b\u4f7f\u7528\u3067\u304d\u307e\u3059\u3002 ReportBodyFile.getFilePath.text=BodyFile.txt -ReportKML.progress.querying=\u30d5\u30a1\u30a4\u30eb\u3092\u30af\u30a8\u30ea\u4e2d\u3067\u3059... -ReportKML.progress.loading=\u30d5\u30a1\u30a4\u30eb\u306e\u8aad\u307f\u8fbc\u307f\u4e2d\u3067\u3059... -ReportKML.getName.text=Google Earth KML -ReportKML.getDesc.text=\u95a2\u9023\u30d5\u30a1\u30a4\u30eb\u306e\u5ea7\u6a19\u3092\u6301\u3064KML\u5f62\u5f0f\u30ec\u30dd\u30fc\u30c8\u3067\u3059\u3002\u3053\u306e\u5f62\u5f0f\u306fGoogle Earth\u30d3\u30e5\u30fc\u306b\u4f7f\u7528\u3067\u304d\u307e\u3059\u3002 -ReportKML.getFilePath.text=ReportKML.kml -ReportBranding.defaultReportTitle.text=Autopsy\u30d5\u30a9\u30ec\u30f3\u30b8\u30c3\u30af\u30ec\u30dd\u30fc\u30c8 +ReportBodyFile.getName.text=TSK Body\u30d5\u30a1\u30a4\u30eb +ReportBodyFile.ingestWarning.text=\u8b66\u544a\: \u3053\u306e\u30ec\u30dd\u30fc\u30c8\u306f\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30b5\u30fc\u30d3\u30b9\u306e\u5b8c\u4e86\u524d\u306b\u5b9f\u884c\u3055\u308c\u307e\u3057\u305f\\uff01 +ReportBodyFile.progress.loading=\u30d5\u30a1\u30a4\u30eb\u306e\u8aad\u307f\u8fbc\u307f\u4e2d\u3067\u3059... +ReportBodyFile.progress.processing={0} \u3092\u73fe\u5728\u51e6\u7406\u4e2d\u3067\u3059... +ReportBodyFile.progress.querying=\u30d5\u30a1\u30a4\u30eb\u3092\u30af\u30a8\u30ea\u4e2d\u3067\u3059... ReportBranding.defaultReportFooter.text=Autopsy\u30aa\u30fc\u30d7\u30f3\u30bd\u30fc\u30b9\u30c7\u30b8\u30bf\u30eb\u30d5\u30a9\u30ec\u30f3\u30b8\u30c3\u30af\u30d7\u30e9\u30c3\u30c8\u30d5\u30a9\u30fc\u30e0\u4f7f\u7528 - www.sleuthkit.org -ReportExcel.numAartifacts.text=\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u6570: -ReportExcel.getName.text=Excel\u30ec\u30dd\u30fc\u30c8 -ReportExcel.getDesc.text=\u7d50\u679c\u3068\u30bf\u30b0\u4ed8\u304d\u9805\u76ee\u306b\u95a2\u3059\u308bExcel (XLS)\u5f62\u5f0f\u306e\u30ec\u30dd\u30fc\u30c8\u3067\u3059\u3002 -ReportExcel.sheetName.text=\u30b5\u30de\u30ea\u30fc +ReportBranding.defaultReportTitle.text=Autopsy\u30d5\u30a9\u30ec\u30f3\u30b8\u30c3\u30af\u30ec\u30dd\u30fc\u30c8 +ReportExcel.cellVal.caseName=\u30b1\u30fc\u30b9\u540d\: +ReportExcel.cellVal.caseNum=\u30b1\u30fc\u30b9\u756a\u53f7\: +ReportExcel.cellVal.examiner=\u8abf\u67fb\u54e1\: +ReportExcel.cellVal.numImages=\u30a4\u30e1\u30fc\u30b8\u6570\: ReportExcel.cellVal.summary=\u30b5\u30de\u30ea\u30fc -ReportExcel.cellVal.caseName=\u30b1\u30fc\u30b9\u540d: -ReportExcel.cellVal.caseNum=\u30b1\u30fc\u30b9\u756a\u53f7: -ReportExcel.cellVal.examiner=\u8abf\u67fb\u54e1: -ReportExcel.cellVal.numImages=\u30a4\u30e1\u30fc\u30b8\u6570: +ReportExcel.endReport.srcModuleName.text=Excel\u30ec\u30dd\u30fc\u30c8 +ReportExcel.exceptionMessage.dataTooLarge=\u5024\u304c\u9577\u3059\u304e\u3066Excel\u306e\u30bb\u30eb\u5185\u306b\u53ce\u307e\u308a\u307e\u305b\u3093\u3002 +ReportExcel.exceptionMessage.errorText=Excel\u306e\u30bb\u30eb\u5185\u3067\u30c7\u30fc\u30bf\u3092\u8868\u793a\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +ReportExcel.getDesc.text=\u7d50\u679c\u3068\u30bf\u30b0\u4ed8\u304d\u9805\u76ee\u306b\u95a2\u3059\u308bExcel (XLS)\u5f62\u5f0f\u306e\u30ec\u30dd\u30fc\u30c8\u3067\u3059\u3002 +ReportExcel.getName.text=Excel\u30ec\u30dd\u30fc\u30c8 +ReportExcel.numAartifacts.text=\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u6570\: +ReportExcel.sheetName.text=\u30b5\u30de\u30ea\u30fc +ReportExcel.writeSummary.caseName=\u30b1\u30fc\u30b9\u540d\: +ReportExcel.writeSummary.caseNotes=\u30b1\u30fc\u30b9\u5099\u8003\: +ReportExcel.writeSummary.caseNum=\u30b1\u30fc\u30b9\u756a\u53f7\: +ReportExcel.writeSummary.examiner=\u8abf\u67fb\u54e1\: +ReportExcel.writeSummary.numImages=\u30a4\u30e1\u30fc\u30b8\u6570\: +ReportExcel.writeSummary.sheetName=\u30b5\u30de\u30ea\u30fc +ReportExcel.writeSummary.summary=\u30b5\u30de\u30ea\u30fc +ReportFileTextConfigurationPanel.commaDelimitedButton.text=\u533a\u5207\u308a\u30ab\u30f3\u30de +ReportFileTextConfigurationPanel.tabDelimitedButton.text=\u533a\u5207\u308a\u30bf\u30d6 +ReportGenerationPanel.cancelButton.actionCommand=\u53d6\u308a\u6d88\u3057 +ReportGenerationPanel.cancelButton.text=\u53d6\u308a\u6d88\u3057 +ReportGenerationPanel.closeButton.text=\u9589\u3058\u308b +ReportGenerationPanel.confDlg.cancelReport.msg=\u30ec\u30dd\u30fc\u30c8\u3092\u53d6\u308a\u6d88\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? ReportGenerationPanel.confDlg.sureToClose.msg=\u30c0\u30a4\u30a2\u30ed\u30b0\u3092\u9589\u3058\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b?\n\u3059\u3079\u3066\u306e\u30ec\u30dd\u30fc\u30c8\u304c\u53d6\u308a\u6d88\u3055\u308c\u307e\u3059\u3002 ReportGenerationPanel.confDlg.title.closing=\u9589\u3058\u3066\u3044\u307e\u3059 -ReportGenerationPanel.confDlg.cancelReport.msg=\u30ec\u30dd\u30fc\u30c8\u3092\u53d6\u308a\u6d88\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? -ReportGenerator.displayProgress.title.text=\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u9032\u6357\u72b6\u6cc1... -ReportGenerator.progress.queryingDb.text=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30af\u30a8\u30ea\u4e2d\u3067\u3059... -ReportGenerator.progress.processingFile.text={0} \u3092\u73fe\u5728\u51e6\u7406\u4e2d\u3067\u3059... -ReportGenerator.artifactTable.taggedResults.text=\u6b21\u306e\u3044\u305a\u308c\u304b\u3067\u30bf\u30b0\u4ed8\u3051\u3055\u308c\u305f\u7d50\u679c\u3092\u542b\u307f\u307e\u3059: -ReportGenerator.progress.processing={0} \u3092\u73fe\u5728\u51e6\u7406\u4e2d\u3067\u3059...\u3002 -ReportGenerator.msgShow.skippingArtType.title=\u30ec\u30dd\u30fc\u30c8\u5185\u306e\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u30bf\u30a4\u30d7 {0} \u306e\u30b9\u30ad\u30c3\u30d7\u4e2d\u3067\u3059 -ReportGenerator.msgShow.skippingArtType.msg=\u4e0d\u660e\u306a\u30ec\u30dd\u30fc\u30c8\u4f5c\u6210\u5bfe\u8c61\u306e\u5217 -ReportGenerator.makeContTagTab.taggedFiles.msg=\u6b21\u306e\u3044\u305a\u308c\u304b\u3067\u30bf\u30b0\u4ed8\u3051\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb\u3092\u542b\u307f\u307e\u3059: -ReportGenerator.makeBbArtTagTab.taggedRes.msg=\u3053\u306e\u30ec\u30dd\u30fc\u30c8\u306f\u6b21\u3067\u30bf\u30b0\u4ed8\u3051\u3055\u308c\u305f\u7d50\u679c\u306e\u307f\u3092\u542b\u307f\u307e\u3059: -ReportGenerator.tagTable.header.resultType=\u7d50\u679c\u30bf\u30a4\u30d7 -ReportGenerator.tagTable.header.tag=\u30bf\u30b0 -ReportGenerator.tagTable.header.comment=\u30b3\u30e1\u30f3\u30c8 -ReportGenerator.tagTable.header.srcFile=\u30bd\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb -ReportGenerator.progress.createdThumb.text=\u30b5\u30e0\u30cd\u30a4\u30eb\u306e\u4f5c\u6210\u4e2d\u3067\u3059... -ReportGenerator.htmlOutput.header.file=\u30d5\u30a1\u30a4\u30eb -ReportGenerator.htmlOutput.header.tag=\u30bf\u30b0 -ReportGenerator.htmlOutput.header.comment=\u30b3\u30e1\u30f3\u30c8 -ReportGenerator.htmlOutput.header.timeModified=\u66f4\u65b0\u65e5\u6642 -ReportGenerator.htmlOutput.header.timeChanged=\u30a8\u30f3\u30c8\u30ea\u66f4\u65b0\u65e5\u6642 -ReportGenerator.htmlOutput.header.timeAccessed=\u30a2\u30af\u30bb\u30b9\u65e5\u6642 -ReportGenerator.htmlOutput.header.timeCreated=\u4f5c\u6210\u65e5\u6642 -ReportGenerator.htmlOutput.header.size=\u30b5\u30a4\u30ba(\u30d0\u30a4\u30c8) -ReportGenerator.htmlOutput.header.hash=\u30cf\u30c3\u30b7\u30e5 -ReportGenerator.thumbnailTable.name=\u30bf\u30b0\u4ed8\u304d\u30a4\u30e1\u30fc\u30b8 -ReportGenerator.thumbnailTable.desc=\u30bf\u30b0\u4ed8\u304d\u306e\u30d5\u30a1\u30a4\u30eb\u3068\u7d50\u679c\u306b\u95a2\u9023\u4ed8\u3051\u3089\u308c\u3066\u3044\u308b\u30a4\u30e1\u30fc\u30b8\u306e\u30b5\u30e0\u30cd\u30a4\u30eb\u3092\u542b\u307f\u307e\u3059\u3002 -ReportGenerator.writeKwHits.userSrchs=\u30e6\u30fc\u30b6\u30fc\u691c\u7d22 -ReportGenerator.progress.processing={0} ({1}) \u3092\u73fe\u5728\u51e6\u7406\u4e2d\u3067\u3059... -ReportGenerator.artTableColHdr.url=URL -ReportGenerator.artTableColHdr.title=\u30bf\u30a4\u30c8\u30eb -ReportGenerator.artTableColHdr.dateCreated=\u4f5c\u6210\u3055\u308c\u305f\u30c7\u30fc\u30bf -ReportGenerator.artTableColHdr.program=\u30d7\u30ed\u30b0\u30e9\u30e0 -ReportGenerator.artTableColHdr.urlDomainDecoded=URL\u30c9\u30e1\u30a4\u30f3 -ReportGenerator.artTableColHdr.srcFile=\u30bd\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb -ReportGenerator.artTableColHdr.dateTime=\u65e5\u6642 -ReportGenerator.artTableColHdr.name=\u540d\u524d -ReportGenerator.artTableColHdr.value=\u5024 -ReportGenerator.artTableColHdr.dateAccessed=\u30a2\u30af\u30bb\u30b9\u3055\u308c\u305f\u30c7\u30fc\u30bf -ReportGenerator.artTableColHdr.referrer=\u30ea\u30d5\u30a1\u30e9\u30fc -ReportGenerator.artTableColHdr.dest=\u5b9b\u5148 -ReportGenerator.artTableColHdr.sourceUrl=\u30bd\u30fc\u30b9URL -ReportGenerator.artTableColHdr.path=\u30d1\u30b9 -ReportGenerator.artTableColHdr.progName=\u30d7\u30ed\u30b0\u30e9\u30e0\u540d -ReportGenerator.artTableColHdr.dateTime=\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u65e5\u6642 -ReportGenerator.artTableColHdr.preview=\u30d7\u30ec\u30d3\u30e5\u30fc -ReportGenerator.artTableColHdr.file=\u30d5\u30a1\u30a4\u30eb -ReportGenerator.artTableColHdr.size=\u30b5\u30a4\u30ba -ReportGenerator.artTableColHdr.deviceId=\u30c7\u30d0\u30a4\u30b9ID -ReportGenerator.artTableColHdr.text=\u30c6\u30ad\u30b9\u30c8 -ReportGenerator.artTableColHdr.domain=\u30c9\u30e1\u30a4\u30f3 -ReportGenerator.artTableColHdr.dateTaken=\u53d6\u5f97\u65e5 -ReportGenerator.artTableColHdr.devManufacturer=\u30c7\u30d0\u30a4\u30b9\u30e1\u30fc\u30ab\u30fc -ReportGenerator.artTableColHdr.devMake=\u30c7\u30d0\u30a4\u30b9\u30e1\u30fc\u30ab\u30fc -ReportGenerator.artTableColHdr.devModel=\u30c7\u30d0\u30a4\u30b9\u578b\u5f0f -ReportGenerator.artTableColHdr.latitude=\u7def\u5ea6 -ReportGenerator.artTableColHdr.longitude=\u7d4c\u5ea6 -ReportGenerator.artTableColHdr.latitudeStart=\u958b\u59cb\u7def\u5ea6 -ReportGenerator.artTableColHdr.longitudeStart=\u958b\u59cb\u7d4c\u5ea6 -ReportGenerator.artTableColHdr.latitudeEnd=\u7d42\u4e86\u7def\u5ea6 -ReportGenerator.artTableColHdr.longitudeEnd=\u7d42\u4e86\u7d4c\u5ea6 -ReportGenerator.artTableColHdr.associatedArtifact=\u95a2\u9023\u4ed8\u3051\u3089\u308c\u3066\u3044\u308b\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8 -ReportGenerator.artTableColHdr.count=\u30ab\u30a6\u30f3\u30c8 -ReportGenerator.artTableColHdr.personName=\u4eba\u540d -ReportGenerator.artTableColHdr.phoneNumber=\u96fb\u8a71\u756a\u53f7 -ReportGenerator.artTableColHdr.phoneNumHome=\u96fb\u8a71\u756a\u53f7(\u81ea\u5b85) -ReportGenerator.artTableColHdr.phoneNumOffice=\u96fb\u8a71\u756a\u53f7(\u4f1a\u793e) -ReportGenerator.artTableColHdr.phoneNumMobile=\u96fb\u8a71\u756a\u53f7(\u643a\u5e2f) -ReportGenerator.artTableColHdr.email=\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9 -ReportGenerator.artTableColHdr.msgType=\u30e1\u30c3\u30bb\u30fc\u30b8\u30bf\u30a4\u30d7 -ReportGenerator.artTableColHdr.direction=\u65b9\u5411 -ReportGenerator.artTableColHdr.readStatus=\u8aad\u307f\u53d6\u308a\u30b9\u30c6\u30fc\u30bf\u30b9 -ReportGenerator.artTableColHdr.fromPhoneNum=\u767a\u4fe1\u5143\u96fb\u8a71\u756a\u53f7 -ReportGenerator.artTableColHdr.fromEmail=\u9001\u4fe1\u5143\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9 -ReportGenerator.artTableColHdr.toPhoneNum=\u76f8\u624b\u5148\u96fb\u8a71\u756a\u53f7 -ReportGenerator.artTableColHdr.toEmail=\u9001\u4fe1\u5148\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9 -ReportGenerator.artTableColHdr.subject=\u4ef6\u540d -ReportGenerator.artTableColHdr.tskEmailTo=To\u306e\u5b9b\u5148\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9 -ReportGenerator.artTableColHdr.tskEmailTo=CC\u306e\u5b9b\u5148\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9 -ReportGenerator.artTableColHdr.tskEmailTo=BCC\u306e\u5b9b\u5148\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9 -ReportGenerator.artTableColHdr.tskEmailTo=\u5dee\u51fa\u4eba\u306e\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9 -ReportGenerator.artTableColHdr.tskMsgId=\u30e1\u30c3\u30bb\u30fc\u30b8ID -ReportGenerator.artTableColHdr.tskDateTimeRcvd=\u53d7\u4fe1\u65e5 -ReportGenerator.artTableColHdr.tskDateTimeSent=\u9001\u4fe1\u65e5 -ReportGenerator.artTableColHdr.tskSubject=\u4ef6\u540d -ReportGenerator.artTableColHdr.tskSetName=\u30bb\u30c3\u30c8\u540d -ReportGenerator.artTableColHdr.tskInterestingFilesCategory=\u30eb\u30fc\u30eb -ReportGenerator.artTableColHdr.tskGpsRouteCategory=\u30ab\u30c6\u30b4\u30ea\u30fc -ReportGenerator.artTableColHdr.tskPath=\u30d1\u30b9 -ReportGenerator.artTableColHdr.calendarEntryType=\u30ab\u30ec\u30f3\u30c0\u30fc\u5165\u529b\u30bf\u30a4\u30d7 -ReportGenerator.artTableColHdr.description=\u8aac\u660e -ReportGenerator.artTableColHdr.startDateTime=\u958b\u59cb\u65e5\u6642 -ReportGenerator.artTableColHdr.endDateTime=\u7d42\u4e86\u65e5\u6642 -ReportGenerator.artTableColHdr.location=\u5834\u6240 -ReportGenerator.artTableColHdr.shortCut=\u30b7\u30e7\u30fc\u30c8\u30ab\u30c3\u30c8 -ReportGenerator.artTableColHdr.deviceName=\u30c7\u30d0\u30a4\u30b9\u540d -ReportGenerator.artTableColHdr.deviceAddress=\u30c7\u30d0\u30a4\u30b9\u30a2\u30c9\u30ec\u30b9 +ReportGenerationPanel.titleLabel.text=\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u9032\u6357\u72b6\u6cc1 ReportGenerator.artTableColHdr.altitude=\u6a19\u9ad8 -ReportGenerator.artTableColHdr.locationAddress=\u6240\u5728\u5730\u30a2\u30c9\u30ec\u30b9 -ReportGenerator.artTableColHdr.category=\u30ab\u30c6\u30b4\u30ea\u30fc -ReportGenerator.artTableColHdr.userId=\u30e6\u30fc\u30b6\u30fcID -ReportGenerator.artTableColHdr.userName=\u30e6\u30fc\u30b6\u30fc\u540d -ReportGenerator.artTableColHdr.password=\u30d1\u30b9\u30ef\u30fc\u30c9 ReportGenerator.artTableColHdr.appName=\u30a2\u30d7\u30ea\u540d ReportGenerator.artTableColHdr.appPath=\u30a2\u30d7\u30ea\u30d1\u30b9 -ReportGenerator.artTableColHdr.replytoAddress=\u8fd4\u4fe1\u5148\u30a2\u30c9\u30ec\u30b9 -ReportGenerator.artTableColHdr.mailServer=\u30e1\u30fc\u30eb\u30b5\u30fc\u30d0\u30fc -ReportGenerator.artTableColHdr.tags=\u30bf\u30b0 +ReportGenerator.artTableColHdr.associatedArtifact=\u95a2\u9023\u4ed8\u3051\u3089\u308c\u3066\u3044\u308b\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8 +ReportGenerator.artTableColHdr.calendarEntryType=\u30ab\u30ec\u30f3\u30c0\u30fc\u5165\u529b\u30bf\u30a4\u30d7 +ReportGenerator.artTableColHdr.category=\u30ab\u30c6\u30b4\u30ea\u30fc +ReportGenerator.artTableColHdr.comment=\u30b3\u30e1\u30f3\u30c8 +ReportGenerator.artTableColHdr.count=\u30ab\u30a6\u30f3\u30c8 +ReportGenerator.artTableColHdr.dateAccessed=\u30a2\u30af\u30bb\u30b9\u3055\u308c\u305f\u30c7\u30fc\u30bf +ReportGenerator.artTableColHdr.dateCreated=\u4f5c\u6210\u3055\u308c\u305f\u30c7\u30fc\u30bf +ReportGenerator.artTableColHdr.dateTaken=\u53d6\u5f97\u65e5 +ReportGenerator.artTableColHdr.dateTime=\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u65e5\u6642 +ReportGenerator.artTableColHdr.description=\u8aac\u660e +ReportGenerator.artTableColHdr.dest=\u5b9b\u5148 +ReportGenerator.artTableColHdr.devMake=\u30c7\u30d0\u30a4\u30b9\u30e1\u30fc\u30ab\u30fc +ReportGenerator.artTableColHdr.devManufacturer=\u30c7\u30d0\u30a4\u30b9\u30e1\u30fc\u30ab\u30fc +ReportGenerator.artTableColHdr.devModel=\u30c7\u30d0\u30a4\u30b9\u578b\u5f0f +ReportGenerator.artTableColHdr.deviceAddress=\u30c7\u30d0\u30a4\u30b9\u30a2\u30c9\u30ec\u30b9 +ReportGenerator.artTableColHdr.deviceId=\u30c7\u30d0\u30a4\u30b9ID +ReportGenerator.artTableColHdr.deviceName=\u30c7\u30d0\u30a4\u30b9\u540d +ReportGenerator.artTableColHdr.direction=\u65b9\u5411 +ReportGenerator.artTableColHdr.domain=\u30c9\u30e1\u30a4\u30f3 +ReportGenerator.artTableColHdr.email=\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9 +ReportGenerator.artTableColHdr.endDateTime=\u7d42\u4e86\u65e5\u6642 +ReportGenerator.artTableColHdr.extension.text=\u62e1\u5f35\u5b50 +ReportGenerator.artTableColHdr.file=\u30d5\u30a1\u30a4\u30eb +ReportGenerator.artTableColHdr.fromEmail=\u9001\u4fe1\u5143\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9 +ReportGenerator.artTableColHdr.fromPhoneNum=\u767a\u4fe1\u5143\u96fb\u8a71\u756a\u53f7 +ReportGenerator.artTableColHdr.latitude=\u7def\u5ea6 +ReportGenerator.artTableColHdr.latitudeEnd=\u7d42\u4e86\u7def\u5ea6 +ReportGenerator.artTableColHdr.latitudeStart=\u958b\u59cb\u7def\u5ea6 ReportGenerator.artTableColHdr.localPath=\u30ed\u30fc\u30ab\u30eb\u30d1\u30b9 +ReportGenerator.artTableColHdr.location=\u5834\u6240 +ReportGenerator.artTableColHdr.locationAddress=\u6240\u5728\u5730\u30a2\u30c9\u30ec\u30b9 +ReportGenerator.artTableColHdr.longitude=\u7d4c\u5ea6 +ReportGenerator.artTableColHdr.longitudeEnd=\u7d42\u4e86\u7d4c\u5ea6 +ReportGenerator.artTableColHdr.longitudeStart=\u958b\u59cb\u7d4c\u5ea6 +ReportGenerator.artTableColHdr.mailServer=\u30e1\u30fc\u30eb\u30b5\u30fc\u30d0\u30fc +ReportGenerator.artTableColHdr.mimeType.text=MIME\u30bf\u30a4\u30d7 +ReportGenerator.artTableColHdr.msgType=\u30e1\u30c3\u30bb\u30fc\u30b8\u30bf\u30a4\u30d7 +ReportGenerator.artTableColHdr.name=\u540d\u524d +ReportGenerator.artTableColHdr.osInstallDate.text=\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u65e5 +ReportGenerator.artTableColHdr.osName.text=\u30aa\u30da\u30ec\u30fc\u30c6\u30a3\u30f3\u30b0\u30b7\u30b9\u30c6\u30e0\u540d +ReportGenerator.artTableColHdr.password=\u30d1\u30b9\u30ef\u30fc\u30c9 +ReportGenerator.artTableColHdr.path=\u30d1\u30b9 +ReportGenerator.artTableColHdr.personName=\u4eba\u540d +ReportGenerator.artTableColHdr.phoneNumHome=\u96fb\u8a71\u756a\u53f7(\u81ea\u5b85) +ReportGenerator.artTableColHdr.phoneNumMobile=\u96fb\u8a71\u756a\u53f7(\u643a\u5e2f) +ReportGenerator.artTableColHdr.phoneNumOffice=\u96fb\u8a71\u756a\u53f7(\u4f1a\u793e) +ReportGenerator.artTableColHdr.phoneNumber=\u96fb\u8a71\u756a\u53f7 +ReportGenerator.artTableColHdr.preview=\u30d7\u30ec\u30d3\u30e5\u30fc +ReportGenerator.artTableColHdr.processorArchitecture.text=\u30d7\u30ed\u30bb\u30c3\u30b5\u30fc\u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3 +ReportGenerator.artTableColHdr.progName=\u30d7\u30ed\u30b0\u30e9\u30e0\u540d +ReportGenerator.artTableColHdr.program=\u30d7\u30ed\u30b0\u30e9\u30e0 +ReportGenerator.artTableColHdr.readStatus=\u8aad\u307f\u53d6\u308a\u30b9\u30c6\u30fc\u30bf\u30b9 +ReportGenerator.artTableColHdr.referrer=\u30ea\u30d5\u30a1\u30e9\u30fc ReportGenerator.artTableColHdr.remotePath=\u30ea\u30e2\u30fc\u30c8\u30d1\u30b9 +ReportGenerator.artTableColHdr.replytoAddress=\u8fd4\u4fe1\u5148\u30a2\u30c9\u30ec\u30b9 +ReportGenerator.artTableColHdr.shortCut=\u30b7\u30e7\u30fc\u30c8\u30ab\u30c3\u30c8 +ReportGenerator.artTableColHdr.size=\u30b5\u30a4\u30ba +ReportGenerator.artTableColHdr.sourceUrl=\u30bd\u30fc\u30b9URL +ReportGenerator.artTableColHdr.srcFile=\u30bd\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb +ReportGenerator.artTableColHdr.startDateTime=\u958b\u59cb\u65e5\u6642 +ReportGenerator.artTableColHdr.subject=\u4ef6\u540d +ReportGenerator.artTableColHdr.tags=\u30bf\u30b0 +ReportGenerator.artTableColHdr.text=\u30c6\u30ad\u30b9\u30c8 +ReportGenerator.artTableColHdr.title=\u30bf\u30a4\u30c8\u30eb +ReportGenerator.artTableColHdr.toEmail=\u9001\u4fe1\u5148\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9 +ReportGenerator.artTableColHdr.toPhoneNum=\u76f8\u624b\u5148\u96fb\u8a71\u756a\u53f7 +ReportGenerator.artTableColHdr.tskDateTimeRcvd=\u53d7\u4fe1\u65e5 +ReportGenerator.artTableColHdr.tskDateTimeSent=\u9001\u4fe1\u65e5 +ReportGenerator.artTableColHdr.tskEmailTo=\u5dee\u51fa\u4eba\u306e\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9 +ReportGenerator.artTableColHdr.tskGpsRouteCategory=\u30ab\u30c6\u30b4\u30ea\u30fc +ReportGenerator.artTableColHdr.tskInterestingFilesCategory=\u30eb\u30fc\u30eb +ReportGenerator.artTableColHdr.tskMsgId=\u30e1\u30c3\u30bb\u30fc\u30b8ID +ReportGenerator.artTableColHdr.tskPath=\u30d1\u30b9 +ReportGenerator.artTableColHdr.tskSetName=\u30bb\u30c3\u30c8\u540d +ReportGenerator.artTableColHdr.tskSubject=\u4ef6\u540d +ReportGenerator.artTableColHdr.url=URL +ReportGenerator.artTableColHdr.urlDomainDecoded=URL\u30c9\u30e1\u30a4\u30f3 +ReportGenerator.artTableColHdr.userId=\u30e6\u30fc\u30b6\u30fcID +ReportGenerator.artTableColHdr.userName=\u30e6\u30fc\u30b6\u30fc\u540d +ReportGenerator.artTableColHdr.value=\u5024 +ReportGenerator.artifactTable.taggedResults.text=\u6b21\u306e\u3044\u305a\u308c\u304b\u3067\u30bf\u30b0\u4ed8\u3051\u3055\u308c\u305f\u7d50\u679c\u3092\u542b\u307f\u307e\u3059\: +ReportGenerator.displayProgress.title.text=\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u9032\u6357\u72b6\u6cc1... +ReportGenerator.errList.coreExceptionWhileGenRptRow=\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u30ec\u30dd\u30fc\u30c8\u306e\u5217\u30c7\u30fc\u30bf\u306e\u751f\u6210\u4e2d\u306b\u30b3\u30a2\u4f8b\u5916\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +ReportGenerator.errList.errGetContentFromBBArtifact=\u30ec\u30dd\u30fc\u30c8\u4f5c\u6210\u5bfe\u8c61\u306e\u30d6\u30e9\u30c3\u30af\u30dc\u30fc\u30c9\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u306e\u30b3\u30f3\u30c6\u30f3\u30c4\u3092\u53d6\u5f97\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +ReportGenerator.errList.failedGetAbstractFileByID=ID\u5225\u306b\u62bd\u8c61\u30d5\u30a1\u30a4\u30eb\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +ReportGenerator.errList.failedGetAbstractFileFromID=ID\u304b\u3089\u62bd\u8c61\u30d5\u30a1\u30a4\u30eb\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +ReportGenerator.errList.failedGetBBArtifacts=\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u4e2d\u306b\u30d6\u30e9\u30c3\u30af\u30dc\u30fc\u30c9\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +ReportGenerator.errList.failedGetBBAttribs=\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u4e2d\u306b\u30d6\u30e9\u30c3\u30af\u30dc\u30fc\u30c9\u5c5e\u6027\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +ReportGenerator.errList.failedGetContentTags=\u30b3\u30f3\u30c6\u30f3\u30c4\u30bf\u30b0\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +ReportGenerator.errList.failedMakeRptFolder=\u30ec\u30dd\u30fc\u30c8\u30d5\u30a9\u30eb\u30c0\u30fc\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u30ec\u30dd\u30fc\u30c8\u3092\u751f\u6210\u3067\u304d\u306a\u3044\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 +ReportGenerator.errList.failedQueryHashsetHits=\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u30d2\u30c3\u30c8\u3092\u30af\u30a8\u30ea\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +ReportGenerator.errList.failedQueryHashsetLists=\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u30ea\u30b9\u30c8\u3092\u30af\u30a8\u30ea\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +ReportGenerator.errList.failedQueryKWLists=\u30ad\u30fc\u30ef\u30fc\u30c9\u30ea\u30b9\u30c8\u3092\u30af\u30a8\u30ea\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +ReportGenerator.errList.failedQueryKWs=\u30ad\u30fc\u30ef\u30fc\u30c9\u3092\u30af\u30a8\u30ea\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +ReportGenerator.errList.noOpenCase=\u958b\u3044\u3066\u3044\u308b\u30b1\u30fc\u30b9\u306f\u3042\u308a\u307e\u305b\u3093\u3002 +ReportGenerator.errors.reportErrorText=\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\: ReportGenerator.errors.reportErrorTitle=\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f -ReportGenerator.errors.reportErrorText=\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f: -ReportHTML.addThumbRows.dataType.title=\u30bf\u30b0\u4ed8\u3051\u30a4\u30e1\u30fc\u30b8 - {0} +ReportGenerator.htmlOutput.header.comment=\u30b3\u30e1\u30f3\u30c8 +ReportGenerator.htmlOutput.header.file=\u30d5\u30a1\u30a4\u30eb +ReportGenerator.htmlOutput.header.hash=\u30cf\u30c3\u30b7\u30e5 +ReportGenerator.htmlOutput.header.size=\u30b5\u30a4\u30ba(\u30d0\u30a4\u30c8) +ReportGenerator.htmlOutput.header.tag=\u30bf\u30b0 +ReportGenerator.htmlOutput.header.timeAccessed=\u30a2\u30af\u30bb\u30b9\u65e5\u6642 +ReportGenerator.htmlOutput.header.timeChanged=\u30a8\u30f3\u30c8\u30ea\u66f4\u65b0\u65e5\u6642 +ReportGenerator.htmlOutput.header.timeCreated=\u4f5c\u6210\u65e5\u6642 +ReportGenerator.htmlOutput.header.timeModified=\u66f4\u65b0\u65e5\u6642 +ReportGenerator.makeBbArtTagTab.taggedRes.msg=\u3053\u306e\u30ec\u30dd\u30fc\u30c8\u306f\u6b21\u3067\u30bf\u30b0\u4ed8\u3051\u3055\u308c\u305f\u7d50\u679c\u306e\u307f\u3092\u542b\u307f\u307e\u3059\: +ReportGenerator.makeContTagTab.taggedFiles.msg=\u6b21\u306e\u3044\u305a\u308c\u304b\u3067\u30bf\u30b0\u4ed8\u3051\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb\u3092\u542b\u307f\u307e\u3059\: +ReportGenerator.msgShow.skippingArtType.msg=\u4e0d\u660e\u306a\u30ec\u30dd\u30fc\u30c8\u4f5c\u6210\u5bfe\u8c61\u306e\u5217 +ReportGenerator.msgShow.skippingArtType.title=\u30ec\u30dd\u30fc\u30c8\u5185\u306e\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u30bf\u30a4\u30d7 {0} \u306e\u30b9\u30ad\u30c3\u30d7\u4e2d\u3067\u3059 +ReportGenerator.notifyErr.errsDuringRptGen=\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\: +ReportGenerator.progress.createdThumb.text=\u30b5\u30e0\u30cd\u30a4\u30eb\u306e\u4f5c\u6210\u4e2d\u3067\u3059... +ReportGenerator.progress.processing={0} ({1}) \u3092\u73fe\u5728\u51e6\u7406\u4e2d\u3067\u3059... +ReportGenerator.progress.processingFile.text={0} \u3092\u73fe\u5728\u51e6\u7406\u4e2d\u3067\u3059... +ReportGenerator.progress.queryingDb.text=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30af\u30a8\u30ea\u4e2d\u3067\u3059... +ReportGenerator.tagTable.header.comment=\u30b3\u30e1\u30f3\u30c8 +ReportGenerator.tagTable.header.resultType=\u7d50\u679c\u30bf\u30a4\u30d7 +ReportGenerator.tagTable.header.srcFile=\u30bd\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb +ReportGenerator.tagTable.header.tag=\u30bf\u30b0 +ReportGenerator.tagTable.header.userName=\u30e6\u30fc\u30b6\u30fc\u540d +ReportGenerator.thumbnailTable.desc=\u30bf\u30b0\u4ed8\u304d\u306e\u30d5\u30a1\u30a4\u30eb\u3068\u7d50\u679c\u306b\u95a2\u9023\u4ed8\u3051\u3089\u308c\u3066\u3044\u308b\u30a4\u30e1\u30fc\u30b8\u306e\u30b5\u30e0\u30cd\u30a4\u30eb\u3092\u542b\u307f\u307e\u3059\u3002 +ReportGenerator.thumbnailTable.name=\u30bf\u30b0\u4ed8\u304d\u30a4\u30e1\u30fc\u30b8 +ReportGenerator.writeKwHits.userSrchs=\u30e6\u30fc\u30b6\u30fc\u691c\u7d22 ReportHTML.addThumbRows.dataType.msg=\u30a4\u30e1\u30fc\u30b8\u3092\u542b\u3080\u30bf\u30b0\u4ed8\u3051\u3055\u308c\u305f\u7d50\u679c\u3068\u30b3\u30f3\u30c6\u30f3\u30c4 -ReportHTML.thumbLink.tags=\u30bf\u30b0: -ReportHTML.getName.text=HTML\u30ec\u30dd\u30fc\u30c8 +ReportHTML.addThumbRows.dataType.title=\u30bf\u30b0\u4ed8\u3051\u30a4\u30e1\u30fc\u30b8 - {0} ReportHTML.getDesc.text=\u7d50\u679c\u3068\u30bf\u30b0\u4ed8\u304d\u9805\u76ee\u306b\u95a2\u3059\u308bHTML\u5f62\u5f0f\u306e\u30ec\u30dd\u30fc\u30c8\u3067\u3059\u3002 -ReportHTML.writeIndex.title=\u30b1\u30fc\u30b9 {0} \u306e +ReportHTML.getName.text=HTML\u30ec\u30dd\u30fc\u30c8 +ReportHTML.thumbLink.tags=\u30bf\u30b0\: ReportHTML.writeIndex.noFrames.msg=\u304a\u4f7f\u3044\u306e\u30d6\u30e9\u30a6\u30b6\u30fc\u306f\u5f53\u793e\u306e\u30d5\u30ec\u30fc\u30e0\u30bb\u30c3\u30c8\u30a2\u30c3\u30d7\u3068\u4e92\u63db\u6027\u304c\u3042\u308a\u307e\u305b\u3093\u3002 ReportHTML.writeIndex.noFrames.seeNav=\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u306e\u30ea\u30f3\u30af\u306f\u3001the navigation page \u3092\u53c2\u7167\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -ReportHTML.writeIndex.seeSum=and \u30b1\u30fc\u30b9\u30b5\u30de\u30ea\u30fc\u306e \u30b5\u30de\u30ea\u30fc\u30da\u30fc\u30b8\u3067\u3059\u3002 -ReportHTML.writeNav.title=\u30ec\u30dd\u30fc\u30c8\u30ca\u30d3\u30b2\u30fc\u30b7\u30e7\u30f3 +ReportHTML.writeIndex.seeSum=and \u30b1\u30fc\u30b9\u30b5\u30de\u30ea\u30fc\u306e \u30b5\u30de\u30ea\u30fc\u30da\u30fc\u30b8\u3067\u3059\u3002 +ReportHTML.writeIndex.srcModuleName.text=HTML\u30ec\u30dd\u30fc\u30c8 +ReportHTML.writeIndex.title=\u30b1\u30fc\u30b9 {0} \u306e ReportHTML.writeNav.h1=\u30ec\u30dd\u30fc\u30c8\u30ca\u30d3\u30b2\u30fc\u30b7\u30e7\u30f3 ReportHTML.writeNav.summary=\u30b1\u30fc\u30b9\u30b5\u30de\u30ea\u30fc -ReportHTML.writeSum.title=\u30b1\u30fc\u30b9\u30b5\u30de\u30ea\u30fc -ReportHTML.writeSum.warningMsg=\u8b66\u544a: \u3053\u306e\u30ec\u30dd\u30fc\u30c8\u306f\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30b5\u30fc\u30d3\u30b9\u306e\u5b8c\u4e86\u524d\u306b\u5b9f\u884c\u3055\u308c\u307e\u3057\u305f\! -# -# autopsy/test/scripts/regression.py._html_report_diff()\u306f reportGenOn.text\u3001caseName\u3001caseNum\u3001 -# examiner\u3092\u6b63\u898f\u8868\u73fe\u30b7\u30b0\u30cd\u30c1\u30e3\u30fc\u3068\u3057\u3066\u4f7f\u7528\u3057\u3001report.html\u3068summary.html\u3092\u30b9\u30ad\u30c3\u30d7\u3057\u307e\u3059\u3002 -# +ReportHTML.writeNav.title=\u30ec\u30dd\u30fc\u30c8\u30ca\u30d3\u30b2\u30fc\u30b7\u30e7\u30f3 +ReportHTML.writeSum.autopsyVersion=Autopsy\u30d0\u30fc\u30b8\u30e7\u30f3\: +ReportHTML.writeSum.case=\u30b1\u30fc\u30b9\: +ReportHTML.writeSum.caseNotes=\u5099\u8003\: +ReportHTML.writeSum.caseNumImages=\u30a4\u30e1\u30fc\u30b8\u6570\: +ReportHTML.writeSum.caseNumber=\u30b1\u30fc\u30b9\u756a\u53f7\: +ReportHTML.writeSum.examiner=\u8abf\u67fb\u54e1\: +ReportHTML.writeSum.imageInfoHeading=

\u30a4\u30e1\u30fc\u30b8\u60c5\u5831\:

+ReportHTML.writeSum.ingestHistoryHeading=

\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u5c65\u6b74\:

+ReportHTML.writeSum.modulesEnabledHeading=\u6709\u52b9\u5316\u3055\u308c\u305f\u30e2\u30b8\u30e5\u30fc\u30eb\: +ReportHTML.writeSum.path=\u30d1\u30b9\: ReportHTML.writeSum.reportGenOn.text={0} \u3067\u751f\u6210\u3055\u308c\u305fHTML\u30ec\u30dd\u30fc\u30c8 -ReportHTML.writeSum.imageInfoHeading=

\u30a4\u30e1\u30fc\u30b8\u60c5\u5831:

-ReportHTML.writeSum.softwareInfoHeading=

\u30bd\u30d5\u30c8\u30a6\u30a7\u30a2\u60c5\u5831:

-ReportHTML.writeSum.ingestHistoryHeading=

\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u5c65\u6b74:

-ReportHTML.writeSum.modulesEnabledHeading=\u6709\u52b9\u5316\u3055\u308c\u305f\u30e2\u30b8\u30e5\u30fc\u30eb: -ReportHTML.writeSum.autopsyVersion=Autopsy\u30d0\u30fc\u30b8\u30e7\u30f3: -ReportHTML.writeSum.timezone=\u30bf\u30a4\u30e0\u30be\u30fc\u30f3: -ReportHTML.writeSum.path=\u30d1\u30b9: -ReportProgressPanel.progress.queuing=\u30ad\u30e5\u30fc\u30a4\u30f3\u30b0\u4e2d\u3067\u3059... -ReportProgressPanel.initPathLabel.noFile=\u30ec\u30dd\u30fc\u30c8\u30d5\u30a1\u30a4\u30eb\u304c\u3042\u308a\u307e\u305b\u3093 -ReportProgressPanel.start.cancelButton.text=\u53d6\u308a\u6d88\u3057 -ReportProgressPanel.start.progress.text=\u30ec\u30dd\u30fc\u30c8\u3092\u958b\u59cb\u4e2d\u3067\u3059... -ReportProgressPanel.complete.processLbl.text=\u5b8c\u4e86 -ReportProgressPanel.complete.processLb2.text=\u30a8\u30e9\u30fc\u3067\u5b8c\u4e86\u3057\u307e\u3057\u305f -ReportProgressPanel.complete.cancelButton.text=\u5b8c\u4e86 +ReportHTML.writeSum.softwareInfoHeading=

\u30bd\u30d5\u30c8\u30a6\u30a7\u30a2\u60c5\u5831\:

+ReportHTML.writeSum.timezone=\u30bf\u30a4\u30e0\u30be\u30fc\u30f3\: +ReportHTML.writeSum.title=\u30b1\u30fc\u30b9\u30b5\u30de\u30ea\u30fc +ReportHTML.writeSum.warningMsg=\u8b66\u544a\: \u3053\u306e\u30ec\u30dd\u30fc\u30c8\u306f\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30b5\u30fc\u30d3\u30b9\u306e\u5b8c\u4e86\u524d\u306b\u5b9f\u884c\u3055\u308c\u307e\u3057\u305f\! +ReportHTMLConfigurationPanel.footerLabel.text=\u30d5\u30c3\u30bf\u30fc\: +ReportHTMLConfigurationPanel.footerTextField.text= +ReportHTMLConfigurationPanel.headerLabel.text=\u30d8\u30c3\u30c0\u30fc\: +ReportHTMLConfigurationPanel.headerTextField.text= +ReportKML.genReport.reportName=KML\u30ec\u30dd\u30fc\u30c8 +ReportKML.genReport.srcModuleName.text=\u5730\u7406\u7a7a\u9593\u30c7\u30fc\u30bf +ReportKML.getDesc.text=\u95a2\u9023\u30d5\u30a1\u30a4\u30eb\u306e\u5ea7\u6a19\u3092\u6301\u3064KML\u5f62\u5f0f\u30ec\u30dd\u30fc\u30c8\u3067\u3059\u3002\u3053\u306e\u5f62\u5f0f\u306fGoogle Earth\u30d3\u30e5\u30fc\u306b\u4f7f\u7528\u3067\u304d\u307e\u3059\u3002 +ReportKML.getFilePath.text=ReportKML.kml +ReportKML.getName.text=Google Earth KML +ReportKML.latLongEndPoint={0};{1};;{2} (\u7d42\u4e86)\n +ReportKML.latLongStartPoint={0};{1};;{2} (\u958b\u59cb)\n +ReportKML.progress.loading=\u30d5\u30a1\u30a4\u30eb\u306e\u8aad\u307f\u8fbc\u307f\u4e2d\u3067\u3059... +ReportKML.progress.querying=\u30d5\u30a1\u30a4\u30eb\u3092\u30af\u30a8\u30ea\u4e2d\u3067\u3059... ReportProgressPanel.cancel.cancelButton.toolTipText=\u53d6\u308a\u6d88\u3057\u6e08\u307f ReportProgressPanel.cancel.procLbl.text=\u53d6\u308a\u6d88\u3057\u6e08\u307f +ReportProgressPanel.complete.cancelButton.text=\u5b8c\u4e86 +ReportProgressPanel.complete.processLb2.text=\u30a8\u30e9\u30fc\u3067\u5b8c\u4e86\u3057\u307e\u3057\u305f +ReportProgressPanel.complete.processLbl.text=\u5b8c\u4e86 +ReportProgressPanel.initPathLabel.noFile=\u30ec\u30dd\u30fc\u30c8\u30d5\u30a1\u30a4\u30eb\u304c\u3042\u308a\u307e\u305b\u3093 +ReportProgressPanel.pathLabel.text=pathLabel +ReportProgressPanel.progress.canceled=\u30ad\u30e3\u30f3\u30bb\u30eb +ReportProgressPanel.progress.complete=\u5b8c\u4e86 +ReportProgressPanel.progress.error=\u30a8\u30e9\u30fc +ReportProgressPanel.progress.queuing=\u30ad\u30e5\u30fc\u30a4\u30f3\u30b0\u4e2d\u3067\u3059... +ReportProgressPanel.progress.running=\u5b9f\u884c\u4e2d... +ReportProgressPanel.reportLabel.text=reportLabel +ReportProgressPanel.separationLabel.text=\: +ReportProgressPanel.start.cancelButton.text=\u53d6\u308a\u6d88\u3057 +ReportProgressPanel.start.progress.text=\u30ec\u30dd\u30fc\u30c8\u3092\u958b\u59cb\u4e2d\u3067\u3059... ReportVisualPanel1.getName.text=\u30ec\u30dd\u30fc\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u9078\u629e\u3057\u3066\u69cb\u6210 +ReportVisualPanel1.invalidModuleWarning=\u7121\u52b9\u306a\u30ec\u30dd\u30fc\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb ({0}) \u306b\u906d\u9047\u3057\u307e\u3057\u305f +ReportVisualPanel1.reportModulesLabel.text=\u30ec\u30dd\u30fc\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\: +ReportVisualPanel2.advancedButton.text=\u30c7\u30fc\u30bf\u30bf\u30a4\u30d7 +ReportVisualPanel2.allResultsRadioButton.text=\u3059\u3079\u3066\u306e\u7d50\u679c +ReportVisualPanel2.dataLabel.text=\u30ec\u30dd\u30fc\u30c8\u4f5c\u6210\u5bfe\u8c61\u306e\u30c7\u30fc\u30bf\u3092\u9078\u629e\: +ReportVisualPanel2.deselectAllButton.text=\u3059\u3079\u3066\u9078\u629e\u89e3\u9664 ReportVisualPanel2.getName.text=\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u30ec\u30dd\u30fc\u30c8\u3092\u69cb\u6210 +ReportVisualPanel2.selectAllButton.text=\u3059\u3079\u3066\u9078\u629e +ReportVisualPanel2.taggedResultsRadioButton.text=\u30bf\u30b0\u4ed8\u304d\u7d50\u679c ReportWizardAction.actionName.text=\u30ec\u30dd\u30fc\u30c8\u751f\u6210 ReportWizardAction.reportWiz.title=\u30ec\u30dd\u30fc\u30c8\u751f\u6210 ReportWizardAction.toolBarButton.text=\u30ec\u30dd\u30fc\u30c8\u751f\u6210 ReportWizardFileOptionsPanel.finishButton.text=\u5b8c\u4e86 +ReportWizardFileOptionsVisualPanel.deselectAllButton.text=\u3059\u3079\u3066\u9078\u629e\u89e3\u9664 ReportWizardFileOptionsVisualPanel.getName.text=\u30d5\u30a1\u30a4\u30eb\u30ec\u30dd\u30fc\u30c8\u3092\u69cb\u6210 -ReportWizardPanel1.nextButton.text=\u6b21\u3078 > +ReportWizardFileOptionsVisualPanel.jLabel1.text=\u6b21\u306e\u30d5\u30a1\u30a4\u30eb\u30ec\u30dd\u30fc\u30c8\u306b\u542b\u3081\u308b\u9805\u76ee\u3092\u9078\u629e\: +ReportWizardFileOptionsVisualPanel.selectAllButton.text=\u3059\u3079\u3066\u9078\u629e ReportWizardPanel1.finishButton.text=\u5b8c\u4e86 +ReportWizardPanel1.nextButton.text=\u6b21\u3078 > ReportWizardPanel2.finishButton.text=\u5b8c\u4e86 ReportWizardPanel2.nextButton.text=\u6b21\u3078 > -ReportBodyFile.generateReport.srcModuleName.text=TSK Body\u30d5\u30a1\u30a4\u30eb -ReportExcel.endReport.srcModuleName.text=Excel\u30ec\u30dd\u30fc\u30c8 -ReportHTML.writeIndex.srcModuleName.text=HTML\u30ec\u30dd\u30fc\u30c8 -ReportKML.genReport.srcModuleName.text=\u5730\u7406\u7a7a\u9593\u30c7\u30fc\u30bf -ReportKML.genReport.reportName=KML\u30ec\u30dd\u30fc\u30c8 -ReportGenerator.artTableColHdr.extension.text=\u62e1\u5f35\u5b50 -ReportGenerator.artTableColHdr.mimeType.text=MIME\u30bf\u30a4\u30d7 -ReportGenerator.artTableColHdr.processorArchitecture.text=\u30d7\u30ed\u30bb\u30c3\u30b5\u30fc\u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3 -ReportGenerator.artTableColHdr.osName.text=\u30aa\u30da\u30ec\u30fc\u30c6\u30a3\u30f3\u30b0\u30b7\u30b9\u30c6\u30e0\u540d -ReportGenerator.artTableColHdr.osInstallDate.text=\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u65e5 -ReportGenerator.errList.failedMakeRptFolder=\u30ec\u30dd\u30fc\u30c8\u30d5\u30a9\u30eb\u30c0\u30fc\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u30ec\u30dd\u30fc\u30c8\u3092\u751f\u6210\u3067\u304d\u306a\u3044\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 -ReportGenerator.notifyErr.errsDuringRptGen=\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f: -ReportGenerator.errList.failedGetContentTags=\u30b3\u30f3\u30c6\u30f3\u30c4\u30bf\u30b0\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 -ReportGenerator.errList.errGetContentFromBBArtifact=\u30ec\u30dd\u30fc\u30c8\u4f5c\u6210\u5bfe\u8c61\u306e\u30d6\u30e9\u30c3\u30af\u30dc\u30fc\u30c9\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u306e\u30b3\u30f3\u30c6\u30f3\u30c4\u3092\u53d6\u5f97\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 -ReportGenerator.errList.failedGetBBAttribs=\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u4e2d\u306b\u30d6\u30e9\u30c3\u30af\u30dc\u30fc\u30c9\u5c5e\u6027\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 -ReportGenerator.errList.failedGetBBArtifacts=\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u4e2d\u306b\u30d6\u30e9\u30c3\u30af\u30dc\u30fc\u30c9\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 -ReportGenerator.errList.failedQueryKWLists=\u30ad\u30fc\u30ef\u30fc\u30c9\u30ea\u30b9\u30c8\u3092\u30af\u30a8\u30ea\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 -ReportGenerator.errList.failedGetAbstractFileByID=ID\u5225\u306b\u62bd\u8c61\u30d5\u30a1\u30a4\u30eb\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 -ReportGenerator.errList.failedQueryKWs=\u30ad\u30fc\u30ef\u30fc\u30c9\u3092\u30af\u30a8\u30ea\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 -ReportGenerator.errList.failedQueryHashsetLists=\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u30ea\u30b9\u30c8\u3092\u30af\u30a8\u30ea\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 -ReportGenerator.errList.failedGetAbstractFileFromID=ID\u304b\u3089\u62bd\u8c61\u30d5\u30a1\u30a4\u30eb\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 -ReportGenerator.errList.failedQueryHashsetHits=\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u30d2\u30c3\u30c8\u3092\u30af\u30a8\u30ea\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 -ReportGenerator.errList.coreExceptionWhileGenRptRow=\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u30ec\u30dd\u30fc\u30c8\u306e\u5217\u30c7\u30fc\u30bf\u306e\u751f\u6210\u4e2d\u306b\u30b3\u30a2\u4f8b\u5916\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 -ReportKML.latLongStartPoint={0};{1};;{2} (\u958b\u59cb)\n -ReportKML.latLongEndPoint={0};{1};;{2} (\u7d42\u4e86)\n -ReportGenerationPanel.cancelButton.actionCommand=\u53d6\u308a\u6d88\u3057 -ReportGenerationPanel.cancelButton.text=\u53d6\u308a\u6d88\u3057 -ReportHTMLConfigurationPanel.headerTextField.text= -ReportHTMLConfigurationPanel.footerTextField.text= -ReportHTMLConfigurationPanel.headerLabel.text=\u30d8\u30c3\u30c0\u30fc: -ReportHTMLConfigurationPanel.footerLabel.text=\u30d5\u30c3\u30bf\u30fc: -CreatePortableCasePanel.selectAllButton.text=\u3059\u3079\u3066\u9078\u629e -CreatePortableCasePanel.deselectAllButton.text=\u3059\u3079\u3066\u9078\u629e\u89e3\u9664 -CreatePortableCasePanel.outputFolderTextField.text=jTextField1 -CreatePortableCasePanel.chooseOutputFolderButton.text=\u30d5\u30a9\u30eb\u30c0\u30fc\u3092\u9078\u629e -CreatePortableCasePanel.jLabel1.text=\u6b21\u3068\u3057\u3066\u30bf\u30b0\u4ed8\u3051\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb\u3092\u30a8\u30af\u30b9\u30dd\u30fc\u30c8: -CreatePortableCasePanel.jLabel2.text=\u51fa\u529b\u30d5\u30a9\u30eb\u30c0\u30fc\u3092\u9078\u629e: -CreatePortableCasePanel.errorLabel.text_1=Windows\u306e\u307f -ReportWizardPortableCaseOptionsVisualPanel.errorLabel.text=Windows\u306e\u307f -ReportWizardPortableCaseOptionsVisualPanel.compressCheckbox.text=\u30b1\u30fc\u30b9\u3092\u30a2\u30fc\u30ab\u30a4\u30d6\u5185\u306b\u30d1\u30c3\u30b1\u30fc\u30b8\u5316: -PortableCaseTagsListPanel.deselectButton.text=\u3059\u3079\u3066\u9078\u629e\u89e3\u9664 -PortableCaseTagsListPanel.selectButton.text=\u3059\u3079\u3066\u9078\u629e -PortableCaseInterestingItemsListPanel.selectButton.text=\u3059\u3079\u3066\u9078\u629e -PortableCaseInterestingItemsListPanel.deselectButton.text=\u3059\u3079\u3066\u9078\u629e\u89e3\u9664 -ReportFileTextConfigurationPanel.tabDelimitedButton.text=\u533a\u5207\u308a\u30bf\u30d6 -ReportFileTextConfigurationPanel.commaDelimitedButton.text=\u533a\u5207\u308a\u30ab\u30f3\u30de -PortableCaseTagsListPanel.descLabel.text=\u6b21\u306e\u30bf\u30b0\u3092\u542b\u3080: -PortableCaseInterestingItemsListPanel.descLabel.text=\u3053\u308c\u3089\u306e\u30bb\u30c3\u30c8\u306e\u8208\u5473\u6df1\u3044\u9805\u76ee\u3092\u542b\u3080: +ReportWizardPortableCaseOptionsVisualPanel.compressCheckbox.text=\u30b1\u30fc\u30b9\u3092\u30a2\u30fc\u30ab\u30a4\u30d6\u5185\u306b\u30d1\u30c3\u30b1\u30fc\u30b8\u5316\: ReportWizardPortableCaseOptionsVisualPanel.compressCheckbox.toolTipText= +ReportWizardPortableCaseOptionsVisualPanel.errorLabel.text=Windows\u306e\u307f ReportWizardPortableCaseOptionsVisualPanel.getName.title=\u30dd\u30fc\u30bf\u30d6\u30eb\u30b1\u30fc\u30b9\u8a2d\u5b9a\u3092\u9078\u629e TableReportGenerator.StatusColumn.Header=\u30ec\u30d3\u30e5\u30fc\u30b9\u30c6\u30fc\u30bf\u30b9 diff --git a/Core/src/org/sleuthkit/autopsy/report/infrastructure/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/report/infrastructure/Bundle_ja.properties index e501eff39e..91805a8244 100644 --- a/Core/src/org/sleuthkit/autopsy/report/infrastructure/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/report/infrastructure/Bundle_ja.properties @@ -1,10 +1,17 @@ -#Fri Feb 12 16:56:29 UTC 2021 +#Mon Jul 12 13:22:00 UTC 2021 ArtifactSelectionDialog.deselectAllButton.text=\u5168\u3066\u9078\u629e\u89e3\u9664 ArtifactSelectionDialog.dlgTitle.text=\u30a2\u30c9\u30d0\u30f3\u30b9\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u9078\u629e ArtifactSelectionDialog.okButton.text=OK ArtifactSelectionDialog.selectAllButton.text=\u5168\u3066\u9078\u629e ArtifactSelectionDialog.titleLabel.text=\u3069\u306e\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u306b\u3064\u3044\u3066\u30ec\u30dd\u30fc\u30c8\u3059\u308b\u304b\u9078\u629e\u3057\u3066\u4e0b\u3055\u3044\uff1a CTL_ReportWizardAction=\u30ec\u30dd\u30fc\u30c8\u3092\u5b9f\u884c +CreatePortableCasePanel.chooseOutputFolderButton.text=\u30d5\u30a9\u30eb\u30c0\u3092\u9078\u629e +CreatePortableCasePanel.deselectAllButton.text=\u3059\u3079\u3066\u306e\u9078\u629e\u3092\u89e3\u9664 +CreatePortableCasePanel.errorLabel.text_1=Windows\u306e\u307f +CreatePortableCasePanel.jLabel1.text=\u4e0b\u8a18\u306e\u30bf\u30b0\u4ed8\u3051\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb\u3092\u30a8\u30af\u30b9\u30dd\u30fc\u30c8\uff1a +CreatePortableCasePanel.jLabel2.text=\u51fa\u529b\u30d5\u30a9\u30eb\u30c0\u3092\u9078\u629e\u3057\u307e\u3059\uff1a +CreatePortableCasePanel.outputFolderTextField.text=jTextField1 +CreatePortableCasePanel.selectAllButton.text=\u3059\u3079\u3066\u9078\u629e FileReportDataTypes.aTime.text=\u6700\u5f8c\u306e\u30a2\u30af\u30bb\u30b9 FileReportDataTypes.address.text=\u30a2\u30c9\u30ec\u30b9 FileReportDataTypes.crTime.text=\u4f5c\u6210\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb @@ -18,6 +25,21 @@ FileReportDataTypes.mTime.text=\u6700\u5f8c\u306e\u4fee\u6b63 FileReportDataTypes.path.text=\u30d5\u30eb\u30d1\u30b9 FileReportDataTypes.perms.text=\u30d1\u30fc\u30df\u30c3\u30b7\u30e7\u30f3 FileReportDataTypes.size.text=\u30b5\u30a4\u30ba +OpenIDE-Module-Name=\u30ec\u30dd\u30fc\u30c8 +PortableCaseInterestingItemsListPanel.descLabel.text=\u3053\u308c\u3089\u306e\u30bb\u30c3\u30c8\u304b\u3089\u8208\u5473\u6df1\u3044\u30a2\u30a4\u30c6\u30e0\u3092\u542b\u3081\u307e\u3059\u3002 +PortableCaseInterestingItemsListPanel.deselectButton.text=\u3059\u3079\u3066\u306e\u9078\u629e\u3092\u89e3\u9664 +PortableCaseInterestingItemsListPanel.error.errorLoadingTags=\u8208\u5473\u6df1\u3044\u30a2\u30a4\u30c6\u30e0\u30bb\u30c3\u30c8\u540d\u306e\u8aad\u8fbc\u307f\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +PortableCaseInterestingItemsListPanel.error.errorTitle=\u30b1\u30fc\u30b9\u306e\u8208\u5473\u6df1\u3044\u30a2\u30a4\u30c6\u30e0\u30bb\u30c3\u30c8\u540d\u306e\u53d6\u5f97\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +PortableCaseInterestingItemsListPanel.error.noOpenCase=\u30aa\u30fc\u30d7\u30f3\u30b1\u30fc\u30b9\u306f\u3042\u308a\u307e\u305b\u3093 +PortableCaseInterestingItemsListPanel.jAllSetsCheckBox.text=\u3059\u3079\u3066\u306e\u8208\u5473\u6df1\u3044\u30a2\u30a4\u30c6\u30e0 +PortableCaseInterestingItemsListPanel.selectButton.text=\u3059\u3079\u3066\u9078\u629e +PortableCaseTagsListPanel.descLabel.text=\u6b21\u306e\u30bf\u30b0\u3092\u542b\u3081\u308b\uff1a +PortableCaseTagsListPanel.deselectButton.text=\u3059\u3079\u3066\u306e\u9078\u629e\u3092\u89e3\u9664 +PortableCaseTagsListPanel.error.errorLoadingTags=\u30bf\u30b0\u306e\u8aad\u8fbc\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +PortableCaseTagsListPanel.error.errorTitle=\u30b1\u30fc\u30b9\u306e\u30bf\u30b0\u540d\u306e\u53d6\u5f97\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +PortableCaseTagsListPanel.error.noOpenCase=\u30aa\u30fc\u30d7\u30f3\u30b1\u30fc\u30b9\u304c\u3042\u308a\u307e\u305b\u3093 +PortableCaseTagsListPanel.jAllTagsCheckBox.text=\u30bf\u30b0\u4ed8\u3051\u3055\u308c\u305f\u3059\u3079\u3066\u306e\u7d50\u679c +PortableCaseTagsListPanel.selectButton.text=\u3059\u3079\u3066\u9078\u629e ReportGenerationPanel.cancelButton.actionCommand=\u30ad\u30e3\u30f3\u30bb\u30eb ReportGenerationPanel.cancelButton.text=\u30ad\u30e3\u30f3\u30bb\u30eb ReportGenerationPanel.closeButton.text=\u9589\u3058\u308b @@ -31,6 +53,7 @@ ReportGenerator.artTableColHdr.appPath=\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e ReportGenerator.artTableColHdr.associatedArtifact=\u95a2\u4fc2\u3059\u308b\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8 ReportGenerator.artTableColHdr.calendarEntryType=\u30ab\u30ec\u30f3\u30c0\u30fc\u30a8\u30f3\u30c8\u30ea\u30bf\u30a4\u30d7 ReportGenerator.artTableColHdr.category=\u30ab\u30c6\u30b4\u30ea\u30fc +ReportGenerator.artTableColHdr.comment=\u30b3\u30e1\u30f3\u30c8 ReportGenerator.artTableColHdr.count=\u30ab\u30a6\u30f3\u30c8 ReportGenerator.artTableColHdr.dateAccessed=\u30a2\u30af\u30bb\u30b9\u65e5\u4ed8 ReportGenerator.artTableColHdr.dateCreated=\u4f5c\u6210\u65e5\u4ed8 @@ -117,6 +140,7 @@ ReportGenerator.errList.coreExceptionWhileGenRptRow=\u30a2\u30fc\u30c6\u30a3\u30 ReportGenerator.errList.errGetContentFromBBArtifact=Blackboard\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u304b\u3089\u30ec\u30dd\u30fc\u30c8\u7528\u306e\u30b3\u30f3\u30c6\u30f3\u30c4\u3092\u53d6\u5f97\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 ReportGenerator.errList.failedGetAbstractFileByID=ID\u306b\u57fa\u3065\u304d\u30a2\u30d6\u30b9\u30c8\u30e9\u30af\u30c8\u30d5\u30a1\u30a4\u30eb\u3092\u53d6\u5f97\u3059\u308b\u306e\u3092\u5931\u6557\u3057\u307e\u3057\u305f ReportGenerator.errList.failedGetAbstractFileFromID=ID\u306b\u57fa\u3065\u304d\u30a2\u30d6\u30b9\u30c8\u30e9\u30af\u30c8\u30d5\u30a1\u30a4\u30eb\u3092\u53d6\u5f97\u3059\u308b\u306e\u3092\u5931\u6557\u3057\u307e\u3057\u305f +ReportGenerator.errList.failedGetAllTagsArtifacts=\u3059\u3079\u3066\u306e\u30bf\u30b0\u540d\u3068\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u30bf\u30a4\u30d7\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 ReportGenerator.errList.failedGetBBArtifactTags=\u7d50\u679c\u30bf\u30b0\u306e\u53d6\u5f97\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 ReportGenerator.errList.failedGetBBArtifacts=\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u4e2d\u306bBlackboard\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u306e\u53d6\u5f97\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 ReportGenerator.errList.failedGetBBAttribs=\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u4e2d\u306bBlackboard\u5c5e\u6027\u306e\u53d6\u5f97\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 @@ -126,6 +150,8 @@ ReportGenerator.errList.failedQueryHashsetHits=\u30cf\u30c3\u30b7\u30e5\u30bb\u3 ReportGenerator.errList.failedQueryHashsetLists=\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u30ea\u30b9\u30c8\u3092\u30af\u30a8\u30ea\u3059\u308b\u306e\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 ReportGenerator.errList.failedQueryKWLists=\u30ad\u30fc\u30ef\u30fc\u30c9\u30ea\u30b9\u30c8\u3092\u30af\u30a8\u30ea\u3059\u308b\u306e\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 ReportGenerator.errList.failedQueryKWs=\u30ad\u30fc\u30ef\u30fc\u30c9\u3092\u30af\u30a8\u30ea\u3059\u308b\u306e\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 +ReportGenerator.errList.noOpenCase=\u30aa\u30fc\u30d7\u30f3\u30b1\u30fc\u30b9\u306f\u3042\u308a\u307e\u305b\u3093\u3002 +ReportGenerator.errList.noReportSettings=\u30ec\u30dd\u30fc\u30c8\u8a2d\u5b9a\u304c\u69cb\u6210\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002 ReportGenerator.errors.reportErrorText=\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\uff1a ReportGenerator.errors.reportErrorTitle=\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f ReportGenerator.htmlOutput.header.comment=\u30b3\u30e1\u30f3\u30c8 @@ -134,6 +160,7 @@ ReportGenerator.htmlOutput.header.hash=\u30cf\u30c3\u30b7\u30e5 ReportGenerator.htmlOutput.header.size=\u30b5\u30a4\u30ba\uff08\u30d0\u30a4\u30c8\uff09 ReportGenerator.htmlOutput.header.tag=\u30bf\u30b0 ReportGenerator.htmlOutput.header.timeAccessed=\u30a2\u30af\u30bb\u30b9\u65e5\u6642 +ReportGenerator.htmlOutput.header.timeChanged=\u5909\u66f4\u3055\u308c\u305f\u6642\u9593 ReportGenerator.htmlOutput.header.timeCreated=\u4f5c\u6210\u65e5\u6642 ReportGenerator.htmlOutput.header.timeModified=\u4fee\u6b63\u65e5\u6642 ReportGenerator.makeBbArtTagTab.taggedRes.msg=\u3053\u306e\u30ec\u30dd\u30fc\u30c8\u306b\u306f\u6b21\u3067\u30bf\u30b0\u3055\u308c\u305f\u7d50\u679c\u3057\u304b\u542b\u307e\u308c\u307e\u305b\u3093\uff1a @@ -148,13 +175,21 @@ ReportGenerator.progress.processing={0}\u3092\u51e6\u7406\u4e2d\u2026 ReportGenerator.progress.processingFile.text={0}\u3092\u51e6\u7406\u4e2d ReportGenerator.progress.processingList={0} ({1})\u3092\u51e6\u7406\u4e2d\u2026 ReportGenerator.progress.queryingDb.text=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30af\u30a8\u30ea\u3092\u5b9f\u884c\u4e2d\u2026 +ReportGenerator.progress.readingTagsArtifacts.text=\u30b1\u30fc\u30b9\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304b\u3089\u306e\u30bf\u30b0\u3068\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u306e\u8aad\u53d6\u308a ReportGenerator.tagTable.header.comment=\u30b3\u30e1\u30f3\u30c8 ReportGenerator.tagTable.header.resultType=\u7d50\u679c\u30bf\u30a4\u30d7 ReportGenerator.tagTable.header.srcFile=\u30bd\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb ReportGenerator.tagTable.header.tag=\u30bf\u30b0 +ReportGenerator.tagTable.header.userName=\u30e6\u30fc\u30b6\u30fc\u540d ReportGenerator.thumbnailTable.desc=\u30bf\u30b0\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb\u3084\u7d50\u679c\u306b\u95a2\u9023\u3059\u308b\u30a4\u30e1\u30fc\u30b8\u306e\u30b5\u30e0\u30cd\u30a4\u30eb\u304c\u542b\u307e\u308c\u307e\u3059\u3002 ReportGenerator.thumbnailTable.name=\u30b5\u30e0\u30cd\u30a4\u30eb ReportGenerator.writeKwHits.userSrchs=\u30e6\u30fc\u30b6\u691c\u7d22 +ReportProgressIndicator.cancelledMessage=\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u304c\u30ad\u30e3\u30f3\u30bb\u30eb\u3055\u308c\u307e\u3057\u305f +ReportProgressIndicator.completedMessage=\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u304c\u5b8c\u4e86\u3057\u307e\u3057\u305f +ReportProgressIndicator.completedWithErrorsMessage=\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u304c\u30a8\u30e9\u30fc\u3067\u5b8c\u4e86\u3057\u307e\u3057\u305f +ReportProgressIndicator.startMessage=\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u3092\u958b\u59cb\u3057\u307e\u3057\u305f +ReportProgressIndicator.switchToDeterminateMessage=\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u306e\u9032\u884c\u72b6\u6cc1\u304c\u78ba\u5b9a\u306b\u5207\u66ff\u308f\u308a\u307e\u3057\u305f +ReportProgressIndicator.switchToIndeterminateMessage=\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u306e\u9032\u884c\u72b6\u6cc1\u304c\u4e0d\u78ba\u5b9a\u306b\u5207\u66ff\u308f\u308a\u307e\u3057\u305f ReportProgressPanel.cancel.cancelButton.toolTipText=\u30ad\u30e3\u30f3\u30bb\u30eb\u3055\u308c\u307e\u3057\u305f ReportProgressPanel.cancel.procLbl.text=\u30ad\u30e3\u30f3\u30bb\u30eb\u3055\u308c\u307e\u3057\u305f ReportProgressPanel.complete.cancelButton.text=\u5b8c\u4e86 @@ -169,13 +204,16 @@ ReportVisualPanel1.invalidModuleWarning=\u7121\u52b9\u306a\u30ec\u30dd\u30fc\u30 ReportVisualPanel1.reportModulesLabel.text=\u30ec\u30dd\u30fc\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\uff1a ReportVisualPanel2.advancedButton.text=\u7d50\u679c\u30bf\u30a4\u30d7\u306e\u9078\u629e... ReportVisualPanel2.allResultsRadioButton.text=\u5168\u3066\u306e\u7d50\u679c +ReportVisualPanel2.allTaggedResultsRadioButton.text=\u30bf\u30b0\u4ed8\u3051\u3055\u308c\u305f\u3059\u3079\u3066\u306e\u7d50\u679c ReportVisualPanel2.dataLabel.text=\u3069\u306e\u30c7\u30fc\u30bf\u306b\u3064\u3044\u3066\u30ec\u30dd\u30fc\u30c8\u3059\u308b\u304b\u9078\u629e\u3057\u3066\u4e0b\u3055\u3044\uff1a ReportVisualPanel2.deselectAllButton.text=\u5168\u3066\u9078\u629e\u89e3\u9664 ReportVisualPanel2.getName.text=\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u30ec\u30dd\u30fc\u30c8\u3092\u8a2d\u5b9a ReportVisualPanel2.selectAllButton.text=\u5168\u3066\u9078\u629e +ReportVisualPanel2.specificTaggedResultsRadioButton.text=\u7279\u5b9a\u306e\u30bf\u30b0\u4ed8\u304d\u7d50\u679c ReportWizardAction.actionName.text=\u30ec\u30dd\u30fc\u30c8\u3092\u751f\u6210 ReportWizardAction.reportWiz.title=\u30ec\u30dd\u30fc\u30c8\u3092\u751f\u6210 ReportWizardAction.toolBarButton.text=\u30ec\u30dd\u30fc\u30c8\u3092\u751f\u6210 +ReportWizardAction.unableToSaveConfig.errorLabel.text=\u30ec\u30dd\u30fc\u30c8\u69cb\u6210\u306e\u4fdd\u5b58\u306b\u5931\u6557\u3057\u307e\u3057\u305f ReportWizardDataSourceSelectionPanel.confirmEmptySelection=\u9078\u629e\u305b\u305a\u306b\u7d9a\u884c\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b\uff1f ReportWizardDataSourceSelectionPanel.finishButton.text=\u7d42\u4e86 ReportWizardDataSourceSelectionPanel.nextButton.text=\u6b21 @@ -189,4 +227,8 @@ ReportWizardPanel1.finishButton.text=\u7d42\u4e86 ReportWizardPanel1.nextButton.text=\u6b21 > ReportWizardPanel2.finishButton.text=\u7d42\u4e86 ReportWizardPanel2.nextButton.text=\u6b21 > +ReportWizardPortableCaseOptionsVisualPanel.compressCheckbox.text=\u30b1\u30fc\u30b9\u3092\u30a2\u30fc\u30ab\u30a4\u30d6\u306b\u30d1\u30c3\u30b1\u30fc\u30b8\u5316\u3057\u307e\u3059\u3002 +ReportWizardPortableCaseOptionsVisualPanel.errorLabel.text=Windows\u306e\u307f +ReportWizardPortableCaseOptionsVisualPanel.getName.title=\u30dd\u30fc\u30bf\u30d6\u30eb\u30b1\u30fc\u30b9\u8a2d\u5b9a\u3092\u9078\u629e\u3057\u3066\u4e0b\u3055\u3044 ReportWizardPortableCaseOptionsVisualPanel.includeAppCheckbox.text=\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3092\u30d5\u30a9\u30eb\u30c0\u30fc\u306b\u542b\u3081\u307e\u3059\uff08\u7dcf\u54081GB\u307e\u3067\u306e\u30d5\u30a1\u30a4\u30eb\u306e\u8ffd\u52a0\u304c\u53ef\u80fd\u3067\u3059\uff09 +TableReportGenerator.StatusColumn.Header=\u30b9\u30c6\u30fc\u30bf\u30b9\u306e\u78ba\u8a8d diff --git a/Core/src/org/sleuthkit/autopsy/report/infrastructure/PortableCaseInterestingItemsListPanel.form b/Core/src/org/sleuthkit/autopsy/report/infrastructure/PortableCaseInterestingItemsListPanel.form index 9fbe01c27b..3b851901ba 100644 --- a/Core/src/org/sleuthkit/autopsy/report/infrastructure/PortableCaseInterestingItemsListPanel.form +++ b/Core/src/org/sleuthkit/autopsy/report/infrastructure/PortableCaseInterestingItemsListPanel.form @@ -57,11 +57,11 @@ - + - - - + + + diff --git a/Core/src/org/sleuthkit/autopsy/report/infrastructure/PortableCaseInterestingItemsListPanel.java b/Core/src/org/sleuthkit/autopsy/report/infrastructure/PortableCaseInterestingItemsListPanel.java index dd11137a0a..7de12c20da 100644 --- a/Core/src/org/sleuthkit/autopsy/report/infrastructure/PortableCaseInterestingItemsListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/report/infrastructure/PortableCaseInterestingItemsListPanel.java @@ -299,10 +299,10 @@ class PortableCaseInterestingItemsListPanel extends javax.swing.JPanel { .addGroup(jPanel1Layout.createSequentialGroup() .addGap(6, 6, 6) .addComponent(descLabel) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(jAllSetsCheckBox) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 164, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 159, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(selectButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) diff --git a/Core/src/org/sleuthkit/autopsy/report/infrastructure/PortableCaseTagsListPanel.form b/Core/src/org/sleuthkit/autopsy/report/infrastructure/PortableCaseTagsListPanel.form index 0757f14756..7828a13fd3 100644 --- a/Core/src/org/sleuthkit/autopsy/report/infrastructure/PortableCaseTagsListPanel.form +++ b/Core/src/org/sleuthkit/autopsy/report/infrastructure/PortableCaseTagsListPanel.form @@ -56,11 +56,11 @@ - + - - - + + + diff --git a/Core/src/org/sleuthkit/autopsy/report/infrastructure/PortableCaseTagsListPanel.java b/Core/src/org/sleuthkit/autopsy/report/infrastructure/PortableCaseTagsListPanel.java index 2e4a8c98cd..9b65cd3c93 100644 --- a/Core/src/org/sleuthkit/autopsy/report/infrastructure/PortableCaseTagsListPanel.java +++ b/Core/src/org/sleuthkit/autopsy/report/infrastructure/PortableCaseTagsListPanel.java @@ -331,10 +331,10 @@ class PortableCaseTagsListPanel extends javax.swing.JPanel { jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel1Layout.createSequentialGroup() .addComponent(descLabel) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(jAllTagsCheckBox) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 168, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 163, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(selectButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) diff --git a/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportVisualPanel1.form b/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportVisualPanel1.form index 7728350704..4337e14246 100644 --- a/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportVisualPanel1.form +++ b/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportVisualPanel1.form @@ -3,7 +3,7 @@ - + @@ -24,13 +24,11 @@ - - - - - - - + + + + + @@ -42,14 +40,7 @@ - - - - - - - - + @@ -63,78 +54,140 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportVisualPanel1.java b/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportVisualPanel1.java index e98f0b7984..5c1dcc38ac 100644 --- a/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportVisualPanel1.java +++ b/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportVisualPanel1.java @@ -36,6 +36,7 @@ import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.ListCellRenderer; import javax.swing.ListSelectionModel; +import javax.swing.border.Border; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import org.openide.DialogDisplayer; @@ -271,16 +272,35 @@ final class ReportVisualPanel1 extends JPanel implements ListSelectionListener { private void initComponents() { reportModulesLabel = new javax.swing.JLabel(); + javax.swing.JSplitPane modulesSplitPane = new javax.swing.JSplitPane(); + javax.swing.JPanel detailsPanel = new javax.swing.JPanel(); configurationPanel = new javax.swing.JPanel(); descriptionScrollPane = new javax.swing.JScrollPane(); descriptionTextPane = new javax.swing.JTextPane(); modulesScrollPane = new javax.swing.JScrollPane(); modulesJList = new javax.swing.JList<>(); - setPreferredSize(new java.awt.Dimension(650, 250)); + setPreferredSize(new java.awt.Dimension(834, 374)); org.openide.awt.Mnemonics.setLocalizedText(reportModulesLabel, org.openide.util.NbBundle.getMessage(ReportVisualPanel1.class, "ReportVisualPanel1.reportModulesLabel.text")); // NOI18N + //Make border on split pane invisible to maintain previous style + modulesSplitPane.setUI(new javax.swing.plaf.basic.BasicSplitPaneUI() { + @Override + public javax.swing.plaf.basic.BasicSplitPaneDivider createDefaultDivider() { + javax.swing.plaf.basic.BasicSplitPaneDivider divider = new javax.swing.plaf.basic.BasicSplitPaneDivider(this) { + @Override + public void setBorder(Border border){ + //do nothing so border is not visible + } + }; + return divider; + } + }); + modulesSplitPane.setBorder(null); + modulesSplitPane.setDividerSize(8); + modulesSplitPane.setResizeWeight(0.5); + configurationPanel.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(125, 125, 125))); configurationPanel.setOpaque(false); @@ -288,11 +308,11 @@ final class ReportVisualPanel1 extends JPanel implements ListSelectionListener { configurationPanel.setLayout(configurationPanelLayout); configurationPanelLayout.setHorizontalGroup( configurationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 432, Short.MAX_VALUE) + .addGap(0, 546, Short.MAX_VALUE) ); configurationPanelLayout.setVerticalGroup( configurationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 168, Short.MAX_VALUE) + .addGap(0, 290, Short.MAX_VALUE) ); descriptionScrollPane.setBorder(null); @@ -302,6 +322,29 @@ final class ReportVisualPanel1 extends JPanel implements ListSelectionListener { descriptionTextPane.setOpaque(false); descriptionScrollPane.setViewportView(descriptionTextPane); + javax.swing.GroupLayout detailsPanelLayout = new javax.swing.GroupLayout(detailsPanel); + detailsPanel.setLayout(detailsPanelLayout); + detailsPanelLayout.setHorizontalGroup( + detailsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(detailsPanelLayout.createSequentialGroup() + .addGap(0, 0, 0) + .addGroup(detailsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(descriptionScrollPane) + .addComponent(configurationPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGap(0, 0, 0)) + ); + detailsPanelLayout.setVerticalGroup( + detailsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(detailsPanelLayout.createSequentialGroup() + .addGap(0, 0, 0) + .addComponent(descriptionScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(configurationPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGap(0, 0, 0)) + ); + + modulesSplitPane.setRightComponent(detailsPanel); + modulesJList.setBackground(new java.awt.Color(240, 240, 240)); modulesJList.setModel(new javax.swing.AbstractListModel() { ReportModule[] modules = {}; @@ -311,6 +354,8 @@ final class ReportVisualPanel1 extends JPanel implements ListSelectionListener { modulesJList.setOpaque(false); modulesScrollPane.setViewportView(modulesJList); + modulesSplitPane.setLeftComponent(modulesScrollPane); + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( @@ -318,12 +363,10 @@ final class ReportVisualPanel1 extends JPanel implements ListSelectionListener { .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(reportModulesLabel) - .addComponent(modulesScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 190, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(configurationPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(descriptionScrollPane)) + .addGroup(layout.createSequentialGroup() + .addComponent(reportModulesLabel) + .addGap(0, 0, Short.MAX_VALUE)) + .addComponent(modulesSplitPane)) .addContainerGap()) ); layout.setVerticalGroup( @@ -332,12 +375,7 @@ final class ReportVisualPanel1 extends JPanel implements ListSelectionListener { .addContainerGap() .addComponent(reportModulesLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addComponent(descriptionScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(configurationPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addComponent(modulesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 208, Short.MAX_VALUE)) + .addComponent(modulesSplitPane) .addContainerGap()) ); }// //GEN-END:initComponents diff --git a/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportVisualPanel2.form b/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportVisualPanel2.form index b54495fb20..1a6fcfb696 100644 --- a/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportVisualPanel2.form +++ b/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportVisualPanel2.form @@ -7,7 +7,7 @@ - + @@ -26,26 +26,25 @@ - + + + + + - - - - - - - - - + - - - - - + + + + + + + + + - @@ -55,15 +54,15 @@ - + - + - + - + - + @@ -72,12 +71,13 @@ - + + - + diff --git a/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportVisualPanel2.java b/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportVisualPanel2.java index a596eb6c38..9a43174ae7 100644 --- a/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportVisualPanel2.java +++ b/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportVisualPanel2.java @@ -311,7 +311,7 @@ final class ReportVisualPanel2 extends JPanel { advancedButton = new javax.swing.JButton(); allTaggedResultsRadioButton = new javax.swing.JRadioButton(); - setPreferredSize(new java.awt.Dimension(650, 275)); + setPreferredSize(new java.awt.Dimension(834, 374)); optionsButtonGroup.add(specificTaggedResultsRadioButton); org.openide.awt.Mnemonics.setLocalizedText(specificTaggedResultsRadioButton, org.openide.util.NbBundle.getMessage(ReportVisualPanel2.class, "ReportVisualPanel2.specificTaggedResultsRadioButton.text")); // NOI18N @@ -366,21 +366,20 @@ final class ReportVisualPanel2 extends JPanel { .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(allTaggedResultsRadioButton) + .addComponent(dataLabel) + .addComponent(allResultsRadioButton) + .addComponent(specificTaggedResultsRadioButton) .addGroup(layout.createSequentialGroup() - .addGap(27, 27, 27) - .addComponent(tagsScrollPane) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addComponent(deselectAllButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(selectAllButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) - .addGroup(layout.createSequentialGroup() + .addGap(10, 10, 10) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(allTaggedResultsRadioButton) - .addComponent(dataLabel) - .addComponent(allResultsRadioButton) - .addComponent(specificTaggedResultsRadioButton) - .addComponent(advancedButton)) - .addGap(0, 454, Short.MAX_VALUE))) + .addComponent(advancedButton) + .addGroup(layout.createSequentialGroup() + .addComponent(tagsScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 699, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(deselectAllButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(selectAllButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))))) .addContainerGap()) ); @@ -397,7 +396,7 @@ final class ReportVisualPanel2 extends JPanel { .addComponent(allTaggedResultsRadioButton) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(specificTaggedResultsRadioButton) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGap(18, 18, 18) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addComponent(selectAllButton) @@ -405,10 +404,11 @@ final class ReportVisualPanel2 extends JPanel { .addComponent(deselectAllButton) .addGap(136, 136, 136)) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addComponent(tagsScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 150, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(1, 1, 1) + .addComponent(tagsScrollPane) .addGap(5, 5, 5) - .addComponent(advancedButton) - .addContainerGap()))) + .addComponent(advancedButton))) + .addContainerGap()) ); }// //GEN-END:initComponents diff --git a/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportWizardPortableCaseOptionsVisualPanel.form b/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportWizardPortableCaseOptionsVisualPanel.form index 4d404676e0..42a80761d7 100644 --- a/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportWizardPortableCaseOptionsVisualPanel.form +++ b/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportWizardPortableCaseOptionsVisualPanel.form @@ -1,6 +1,11 @@ + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportWizardPortableCaseOptionsVisualPanel.java b/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportWizardPortableCaseOptionsVisualPanel.java index 4967431884..3e5a76b90e 100644 --- a/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportWizardPortableCaseOptionsVisualPanel.java +++ b/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportWizardPortableCaseOptionsVisualPanel.java @@ -155,6 +155,8 @@ class ReportWizardPortableCaseOptionsVisualPanel extends javax.swing.JPanel { listPanel = new javax.swing.JPanel(); includeAppCheckbox = new javax.swing.JCheckBox(); + setPreferredSize(new java.awt.Dimension(834, 374)); + chunkSizeComboBox.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { chunkSizeComboBoxActionPerformed(evt); diff --git a/Core/src/org/sleuthkit/autopsy/report/infrastructure/TableReportGenerator.java b/Core/src/org/sleuthkit/autopsy/report/infrastructure/TableReportGenerator.java index 34186c13b2..93f7f406d2 100644 --- a/Core/src/org/sleuthkit/autopsy/report/infrastructure/TableReportGenerator.java +++ b/Core/src/org/sleuthkit/autopsy/report/infrastructure/TableReportGenerator.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013-2020 Basis Technology Corp. + * Copyright 2013-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -48,6 +48,7 @@ import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.datamodel.ContentUtils; import org.sleuthkit.autopsy.report.ReportProgressPanel; import static org.sleuthkit.autopsy.casemodule.services.TagsManager.getNotableTagLabel; +import org.sleuthkit.autopsy.coreutils.TimeZoneUtils; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Account; import org.sleuthkit.datamodel.BlackboardArtifact; @@ -1919,7 +1920,7 @@ class TableReportGenerator { if (attribute.getAttributeType().getValueType() != BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME) { return attribute.getDisplayString(); } else { - return ContentUtils.getStringTime(attribute.getValueLong(), artData.getContent()); + return TimeZoneUtils.getFormattedTime(attribute.getValueLong()); } } } diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/caseuco/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/report/modules/caseuco/Bundle_ja.properties index a6c430b198..c9e627fd63 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/caseuco/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/report/modules/caseuco/Bundle_ja.properties @@ -1,4 +1,4 @@ -#Tue Aug 18 18:09:21 UTC 2020 +#Mon Jul 12 13:22:00 UTC 2021 CaseUcoReportModule.getDesc.text=\u3059\u3079\u3066\u306e\u30d5\u30a1\u30a4\u30eb\u306e\u57fa\u672c\u7684\u306a\u30d7\u30ed\u30d1\u30c6\u30a3\u30d5\u30a3\u30fc\u30eb\u30c9\u3092\u542b\u3080CASE-UCO\u5f62\u5f0f\u306e\u30ec\u30dd\u30fc\u30c8\u3002 CaseUcoReportModule.getName.text=CASE-UCO CaseUcoReportModule.ingestWarning=\u8b66\u544a\u3001\u3053\u306e\u30ec\u30dd\u30fc\u30c8\u306f\u53d6\u308a\u8fbc\u307f\u30b5\u30fc\u30d3\u30b9\u304c\u5b8c\u4e86\u3059\u308b\u524d\u306b\u4f5c\u6210\u3055\u308c\u307e\u3059 @@ -10,3 +10,5 @@ CaseUcoReportModule.processingDataSource=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3 CaseUcoReportModule.srcModuleName=CASE-UCO\u30ec\u30dd\u30fc\u30c8 CaseUcoReportModule.tskCoreException=\u30ec\u30dd\u30fc\u30c8\u306e\u751f\u6210\u4e2d\u306bTskCoreException [%s]\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 \u8a73\u7d30\u306b\u3064\u3044\u3066\u306f\u3001\u30ed\u30b0\u3092\u53c2\u7167\u3057\u3066\u304f\u3060\u3055\u3044\u3002 CaseUcoReportModule.unableToCreateDirectories=CASE-UCO\u30ec\u30dd\u30fc\u30c8\u7528\u306e\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093 +OpenIDE-Module-Name=CaseUcoModule +ReportCaseUcoConfigPanel.jLabelSelectDataSource.text=CASE-UCO\u30ec\u30dd\u30fc\u30c8\u306e\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u9078\u629e\u3057\u3066\u4e0b\u3055\u3044 diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/excel/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/report/modules/excel/Bundle_ja.properties index c709b35d02..af92670df3 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/excel/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/report/modules/excel/Bundle_ja.properties @@ -1,12 +1,20 @@ -#Fri Feb 12 16:56:29 UTC 2021 +#Mon Jul 12 13:22:00 UTC 2021 ReportExcel.cellVal.caseName=\u30b1\u30fc\u30b9\u540d\uff1a ReportExcel.cellVal.caseNum=\u30b1\u30fc\u30b9\u756a\u53f7\uff1a ReportExcel.cellVal.examiner=\u8abf\u67fb\u62c5\u5f53\u8005\uff1a ReportExcel.cellVal.numImages=\u30a4\u30e1\u30fc\u30b8\u6570\uff1a ReportExcel.cellVal.summary=\u30b5\u30de\u30ea\u30fc ReportExcel.endReport.srcModuleName.text=Excel\u30ec\u30dd\u30fc\u30c8 +ReportExcel.exceptionMessage.dataTooLarge=\u5024\u304c\u9577\u3059\u304e\u3066Excel\u306e\u30bb\u30eb\u306b\u53ce\u307e\u308a\u307e\u305b\u3093\u3002 +ReportExcel.exceptionMessage.errorText=Excel\u306e\u30bb\u30eb\u306b\u30c7\u30fc\u30bf\u3092\u8868\u793a\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 ReportExcel.getDesc.text=\u7d50\u679c\u306b\u95a2\u3059\u308b\u30ec\u30dd\u30fc\u30c8\u3002Excel(XLS)\u30d5\u30a9\u30fc\u30de\u30c3\u30c8\u3067\u30a2\u30a4\u30c6\u30e0\u306e\u30bf\u30b0\u4ed8\u3051\u304c\u3055\u308c\u3066\u3044\u307e\u3059\u3002 ReportExcel.getName.text=\u7d50\u679c - Excel ReportExcel.numAartifacts.text=\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u6570\uff1a ReportExcel.sheetName.text=\u30b5\u30de\u30ea\u30fc +ReportExcel.writeSummary.caseName=\u30b1\u30fc\u30b9\u540d\uff1a +ReportExcel.writeSummary.caseNotes=\u30b1\u30fc\u30b9\u30ce\u30fc\u30c8\uff1a +ReportExcel.writeSummary.caseNum=\u30b1\u30fc\u30b9\u756a\u53f7\uff1a +ReportExcel.writeSummary.examiner=\u5be9\u67fb\u5b98\uff1a ReportExcel.writeSummary.numImages=\u30b1\u30fc\u30b9\u5185\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u306e\u6570\uff1a +ReportExcel.writeSummary.sheetName=\u6982\u8981 +ReportExcel.writeSummary.summary=\u6982\u8981 diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/file/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/report/modules/file/Bundle_ja.properties index 1db247bda6..15769efbb0 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/file/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/report/modules/file/Bundle_ja.properties @@ -1,2 +1,5 @@ -FileReportText.getName.text=\u30d5\u30a1\u30a4\u30eb - \u30c6\u30ad\u30b9\u30c8 +#Mon Jul 12 13:22:00 UTC 2021 FileReportText.getDesc.text=\u30b1\u30fc\u30b9\u306e\u500b\u5225\u30d5\u30a1\u30a4\u30eb\u306b\u3064\u3044\u3066\u306e\u60c5\u5831\u3092\u6301\u3064\u3001\u30bf\u30d6\u533a\u5207\u308a\u30c6\u30ad\u30b9\u30c8\u30d5\u30a1\u30a4\u30eb\u3002 +FileReportText.getName.text=\u30d5\u30a1\u30a4\u30eb - \u30c6\u30ad\u30b9\u30c8 +ReportFileTextConfigurationPanel.commaDelimitedButton.text=\u30ab\u30f3\u30de\u533a\u5207\u308a +ReportFileTextConfigurationPanel.tabDelimitedButton.text=\u30bf\u30d6\u533a\u5207\u308a diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/html/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/report/modules/html/Bundle_ja.properties index 8ca83a242d..ad08f429f8 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/html/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/report/modules/html/Bundle_ja.properties @@ -1,4 +1,6 @@ -#Fri Feb 12 16:56:29 UTC 2021 +#Mon Jul 12 13:22:00 UTC 2021 +HTMLReportConfigurationPanel.footerLabel.text=\u30d5\u30c3\u30bf\u30fc\uff1a +HTMLReportConfigurationPanel.headerLabel.text=\u30d8\u30c3\u30c0\u30fc\uff1a ReportHTML.addThumbRows.dataType.msg=\u30a4\u30e1\u30fc\u30b8\u3092\u542b\u3080\u30bf\u30b0\u4ed8\u3051\u3055\u308c\u305f\u7d50\u679c\u304a\u3088\u3073\u30b3\u30f3\u30c6\u30f3\u30c4\u3002 ReportHTML.addThumbRows.dataType.title=\u30bf\u30b0\u4ed8\u3051\u3055\u308c\u305f\u30a4\u30e1\u30fc\u30b8 - {0} ReportHTML.getDesc.text=HTML\u5f62\u5f0f\u306e\u7d50\u679c\u304a\u3088\u3073\u30bf\u30b0\u4ed8\u3051\u3055\u308c\u305f\u30a2\u30a4\u30c6\u30e0\u306e\u30ec\u30dd\u30fc\u30c8 @@ -12,16 +14,23 @@ ReportHTML.writeIndex.title=\u30b1\u30fc\u30b9{0}\u306eAutopsy\u30ec\u30dd\u30fc ReportHTML.writeNav.h1=\u30ec\u30dd\u30fc\u30c8\u30ca\u30d3\u30b2\u30fc\u30b7\u30e7\u30f3 ReportHTML.writeNav.summary=\u30b1\u30fc\u30b9\u30b5\u30de\u30ea\u30fc ReportHTML.writeNav.title=\u30ec\u30dd\u30fc\u30c8\u30ca\u30d3\u30b2\u30fc\u30b7\u30e7\u30f3 +ReportHTML.writeSum.autopsyVersion=Autopsy\u30d0\u30fc\u30b8\u30e7\u30f3\uff1a +ReportHTML.writeSum.case=\u30b1\u30fc\u30b9\uff1a ReportHTML.writeSum.caseName=\u30b1\u30fc\u30b9\uff1a +ReportHTML.writeSum.caseNotes=\u30ce\u30fc\u30c8\uff1a ReportHTML.writeSum.caseNum=\u30b1\u30fc\u30b9\u756a\u53f7\uff1a ReportHTML.writeSum.caseNumImages=\u30b1\u30fc\u30b9\u5185\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u306e\u6570\uff1a +ReportHTML.writeSum.caseNumber=\u30b1\u30fc\u30b9\u756a\u53f7\uff1a ReportHTML.writeSum.examiner=\u8abf\u67fb\u62c5\u5f53\u8005\uff1a ReportHTML.writeSum.imageInfoHeading=

\u30a4\u30e1\u30fc\u30b8\u60c5\u5831\uff1a

+ReportHTML.writeSum.ingestHistoryHeading=

\u53d6\u8fbc\u307f\u5c65\u6b74\uff1a +ReportHTML.writeSum.modulesEnabledHeading=\u6709\u52b9\u306a\u30e2\u30b8\u30e5\u30fc\u30eb\uff1a ReportHTML.writeSum.noCaseNum=\u30b1\u30fc\u30b9\u756a\u53f7\u304c\u3042\u308a\u307e\u305b\u3093 ReportHTML.writeSum.noExaminer=\u8abf\u67fb\u62c5\u5f53\u8005\u7121\u3057 ReportHTML.writeSum.numImages=\u30a4\u30e1\u30fc\u30b8\u6570\uff1a ReportHTML.writeSum.path=\u30d1\u30b9\uff1a ReportHTML.writeSum.reportGenOn.text={0}\u306bHTML\u30ec\u30dd\u30fc\u30c8\u306f\u751f\u6210\u3055\u308c\u307e\u3057\u305f +ReportHTML.writeSum.softwareInfoHeading=

\u30bd\u30d5\u30c8\u30a6\u30a7\u30a2\u60c5\u5831\uff1a ReportHTML.writeSum.timezone=\u30bf\u30a4\u30e0\u30be\u30fc\u30f3\uff1a ReportHTML.writeSum.title=\u30b1\u30fc\u30b9\u30b5\u30de\u30ea\u30fc ReportHTML.writeSum.warningMsg=\u8b66\u544a\u3001\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30b5\u30fc\u30d3\u30b9\u304c\u5b8c\u4e86\u3059\u308b\u524d\u306b\u30ec\u30dd\u30fc\u30c8\u304c\u5b9f\u884c\u3055\u308c\u307e\u3057\u305f\uff01 diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/kml/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/report/modules/kml/Bundle_ja.properties index ed22795edb..60563ed853 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/kml/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/report/modules/kml/Bundle_ja.properties @@ -1,13 +1,38 @@ -#Fri Feb 12 16:56:29 UTC 2021 +#Mon Jul 12 13:22:00 UTC 2021 +KMLReport.bookmarkError=\u30d6\u30c3\u30af\u30de\u30fc\u30af\u60c5\u5831\u3092\u62bd\u51fa\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +KMLReport.errorGeneratingReport=\u30ec\u30dd\u30fc\u30c8\u3068\u3057\u3066\u30b1\u30fc\u30b9\u306b{0}\u3092\u8ffd\u52a0\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +KMLReport.exifPhotoError=EXIF\u30e1\u30bf\u30c7\u30fc\u30bf\u3092\u542b\u3080\u5199\u771f\u3092\u62bd\u51fa\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 KMLReport.failedToCompleteReport=\u30ec\u30dd\u30fc\u30c8\u3092\u5b8c\u6210\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +KMLReport.gpsBookmarkError=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304b\u3089GPS\u30d6\u30c3\u30af\u30de\u30fc\u30af\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +KMLReport.gpsRouteDatabaseError=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304b\u3089GPS\u30eb\u30fc\u30c8\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +KMLReport.gpsRouteError=GPS\u30eb\u30fc\u30c8\u60c5\u5831\u3092\u62bd\u51fa\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +KMLReport.gpsSearchDatabaseError=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304b\u3089GPS\u691c\u7d22\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +KMLReport.kmlFileWriteError=KML\u30d5\u30a1\u30a4\u30eb\u3092\u66f8\u304d\u8fbc\u3081\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +KMLReport.locationDatabaseError=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304b\u3089GPS\u306e\u6700\u5f8c\u5834\u6240\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +KMLReport.locationError=\u6700\u5f8c\u5834\u6240\u306e\u60c5\u5831\u3092\u62bd\u51fa\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 KMLReport.partialFailure=\u30ec\u30dd\u30fc\u30c8\u306e\u4f5c\u6210\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 \u4e00\u90e8\u306e\u30a2\u30a4\u30c6\u30e0\u306f\u51fa\u529b\u3055\u308c\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +KMLReport.stylesheetError=KML\u30b9\u30bf\u30a4\u30eb\u30b7\u30fc\u30c8\u306e\u914d\u7f6e\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 .KML\u30d5\u30a1\u30a4\u30eb\u306f\u6b63\u3057\u304f\u6a5f\u80fd\u3057\u307e\u305b\u3093\u3002 +KMLReport.trackpointDatabaseError=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304b\u3089GPS\u30c8\u30e9\u30c3\u30af\u30dd\u30a4\u30f3\u30c8\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +KMLReport.trackpointError=\u30c8\u30e9\u30c3\u30af\u30dd\u30a4\u30f3\u30c8\u60c5\u5831\u3092\u62bd\u51fa\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +KMLReport.unableToExtractPhotos=\u5199\u771f\u60c5\u5831\u3092\u62bd\u51fa\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +KMLReport.unableToOpenCase=\u30aa\u30fc\u30d7\u30f3\u30b1\u30fc\u30b9\u53d6\u5f97\u4e2d\u306e\u4f8b\u5916\u3002 ReportBodyFile.ingestWarning.text=\u8aad\u8fbc\u8b66\u544a\u30e1\u30c3\u30bb\u30fc\u30b8 ReportKML.genReport.reportName=KML\u30ec\u30dd\u30fc\u30c8 +ReportKML.genReport.srcModuleName.text=\u5730\u7406\u7a7a\u9593\u30c7\u30fc\u30bf ReportKML.getDesc.text=\u95a2\u9023\u30d5\u30a1\u30a4\u30eb\u306e\u5ea7\u6a19\u3092\u542b\u3080KML\u30d5\u30a9\u30fc\u30de\u30c3\u30c8\u306e\u30ec\u30dd\u30fc\u30c8\u3002\u3053\u306e\u30d5\u30a9\u30fc\u30de\u30c3\u30c8\u306fGoogle Earth\u30d3\u30e5\u30fc\u306b\u4f7f\u7528\u3067\u304d\u307e\u3059\u3002 ReportKML.getFilePath.text=\u30ec\u30dd\u30fc\u30c8KML.kml ReportKML.getName.text=Google Earth/KML +ReportKML.latLongEndPoint={0}; {1} ;; {2}\uff08\u7d42\u4e86\uff09\n +ReportKML.latLongStartPoint={0}; {1} ;; {2}\uff08\u958b\u59cb\uff09\n ReportKML.progress.loading=\u30d5\u30a1\u30a4\u30eb\u306e\u8aad\u307f\u8fbc\u307f\u4e2d\u2026 ReportKML.progress.querying=\u30d5\u30a1\u30a4\u30eb\u306e\u30af\u30a8\u30ea\u3092\u5b9f\u884c\u4e2d\u2026 +Route_Details_Header=GPS\u30eb\u30fc\u30c8 Waypoint_Area_Point_Display_String=GPS\u7bc4\u56f2\u5916\u6bbb\u30dd\u30a4\u30f3\u30c8 +Waypoint_Bookmark_Display_String=GPS\u30d6\u30c3\u30af\u30de\u30fc\u30af +Waypoint_EXIF_Display_String=\u5834\u6240\u3092\u542b\u3080EXIF\u30e1\u30bf\u30c7\u30fc\u30bf +Waypoint_Last_Known_Display_String=GPS\u306e\u6700\u5f8c\u5834\u6240 +Waypoint_Route_Point_Display_String=GPS\u500b\u5225\u30eb\u30fc\u30c8\u30dd\u30a4\u30f3\u30c8 +Waypoint_Search_Display_String=GPS\u691c\u7d22 Waypoint_Track_Display_String=GPS\u30c8\u30e9\u30c3\u30af Waypoint_Track_Point_Display_String=GPS\u500b\u5225\u30c8\u30e9\u30c3\u30af\u30dd\u30a4\u30f3\u30c8 +Waypoint_Trackpoint_Display_String=GPS\u30c8\u30e9\u30c3\u30af\u30dd\u30a4\u30f3\u30c8 diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/portablecase/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/report/modules/portablecase/Bundle_ja.properties index a51568f861..6880f3226a 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/portablecase/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/report/modules/portablecase/Bundle_ja.properties @@ -1,7 +1,38 @@ -#Fri Feb 12 16:56:29 UTC 2021 +#Mon Jul 12 13:22:00 UTC 2021 +PortableCaseReportModule.compressCase.canceled=\u30e6\u30fc\u30b6\u30fc\u304c\u5727\u7e2e\u3092\u30ad\u30e3\u30f3\u30bb\u30eb\u3057\u307e\u3057\u305f +PortableCaseReportModule.compressCase.errorCompressingCase=\u30b1\u30fc\u30b9\u306e\u5727\u7e2e\u30a8\u30e9\u30fc +PortableCaseReportModule.compressCase.errorCreatingTempFolder=\u4e00\u6642\u30d5\u30a9\u30eb\u30c0{0}\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f +PortableCaseReportModule.compressCase.errorFinding7zip=7-Zip\u5b9f\u884c\u30d5\u30a1\u30a4\u30eb\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f +PortableCaseReportModule.copyContentToPortableCase.copyingFile=\u30d5\u30a1\u30a4\u30eb{0}\u3092\u30b3\u30d4\u30fc\u4e2d +PortableCaseReportModule.createCase.caseDirExists=\u30b1\u30fc\u30b9\u30d5\u30a9\u30eb\u30c0{0}\u306f\u3059\u3067\u306b\u5b58\u5728\u3057\u307e\u3059 +PortableCaseReportModule.createCase.errorCreatingCase=\u30b1\u30fc\u30b9\u306e\u4f5c\u6210\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +PortableCaseReportModule.createCase.errorCreatingFolder=\u30d5\u30a9\u30eb\u30c0{0}\u306e\u4f5c\u6210\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +PortableCaseReportModule.createCase.errorStoringMaxIds=\u6700\u5927\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9ID\u306e\u4fdd\u5b58\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f PortableCaseReportModule.generateCaseUcoReport.errorCreatingReportFolder=\u30ec\u30dd\u30fc\u30c8\u30d5\u30a9\u30eb\u30c0\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f PortableCaseReportModule.generateCaseUcoReport.errorGeneratingCaseUcoReport=CASE-UCO\u30ec\u30dd\u30fc\u30c8\u306e\u751f\u6210\u4e2d\u306e\u554f\u984c\u304c\u767a\u751f\u3057\u307e\u3057\u305f PortableCaseReportModule.generateCaseUcoReport.startCaseUcoReportGeneration=\u643a\u5e2f\u7528\u30b1\u30fc\u30b9\u306eCASE-UCO\u30ec\u30dd\u30fc\u30c8\u306e\u4f5c\u6210\u4e2d PortableCaseReportModule.generateCaseUcoReport.successCaseUcoReportGeneration=\u30dd\u30fc\u30bf\u30d6\u30eb\u30b1\u30fc\u30b9\u306eCASE-UCO\u30ec\u30dd\u30fc\u30c8\u3092\u4f5c\u6210\u3057\u307e\u3057\u305f +PortableCaseReportModule.generateReport.caseClosed=\u73fe\u5728\u306e\u30b1\u30fc\u30b9\u306f\u30af\u30ed\u30fc\u30ba\u3055\u308c\u307e\u3057\u305f +PortableCaseReportModule.generateReport.compressingCase=\u30b1\u30fc\u30b9\u3092\u5727\u7e2e\u4e2d... +PortableCaseReportModule.generateReport.copyingArtifacts={0}\u3068\u3057\u3066\u30bf\u30b0\u4ed8\u3051\u3055\u308c\u305f\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u3092\u30b3\u30d4\u30fc\u4e2d... +PortableCaseReportModule.generateReport.copyingFiles={0}\u3068\u3057\u3066\u30bf\u30b0\u4ed8\u3051\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb\u3092\u30b3\u30d4\u30fc\u4e2d... +PortableCaseReportModule.generateReport.copyingTags=\u30bf\u30b0\u3092\u30b3\u30d4\u30fc\u4e2d... +PortableCaseReportModule.generateReport.creatingCase=\u30dd\u30fc\u30bf\u30d6\u30eb\u30b1\u30fc\u30b9\u30fb\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u4f5c\u6210\u4e2d... +PortableCaseReportModule.generateReport.errorCopyingArtifacts=\u30bf\u30b0\u4ed8\u304d\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u306e\u30b3\u30d4\u30fc\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f PortableCaseReportModule.generateReport.errorCopyingAutopsy=\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u30b3\u30d4\u30fc\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +PortableCaseReportModule.generateReport.errorCopyingFiles=\u30bf\u30b0\u4ed8\u304d\u30d5\u30a1\u30a4\u30eb\u306e\u30b3\u30d4\u30fc\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +PortableCaseReportModule.generateReport.errorCopyingInterestingFiles=\u8208\u5473\u6df1\u3044\u30d5\u30a1\u30a4\u30eb\u306e\u30b3\u30d4\u30fc\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +PortableCaseReportModule.generateReport.errorCopyingInterestingResults=\u8208\u5473\u6df1\u3044\u7d50\u679c\u306e\u30b3\u30d4\u30fc\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +PortableCaseReportModule.generateReport.errorCopyingTags=\u30bf\u30b0\u306e\u30b3\u30d4\u30fc\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +PortableCaseReportModule.generateReport.errorCreatingImageTagTable=\u753b\u50cf\u30bf\u30b0\u30c6\u30fc\u30d6\u30eb\u306e\u4f5c\u6210\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +PortableCaseReportModule.generateReport.errorLookingUpAttrType=\u5c5e\u6027\u30bf\u30a4\u30d7{0}\u306e\u691c\u7d22\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +PortableCaseReportModule.generateReport.errorReadingSets=\u30b1\u30fc\u30b9\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304b\u3089\u8208\u5473\u6df1\u3044\u30a2\u30a4\u30c6\u30e0\u30bb\u30c3\u30c8\u3092\u8aad\u53d6\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +PortableCaseReportModule.generateReport.errorReadingTags=\u30b1\u30fc\u30b9\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304b\u3089\u30bf\u30b0\u3092\u8aad\u53d6\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +PortableCaseReportModule.generateReport.interestingItemError=\u8208\u5473\u6df1\u3044\u30a2\u30a4\u30c6\u30e0\u306e\u8aad\u8fbc\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +PortableCaseReportModule.generateReport.noContentToCopy=\u30b3\u30d4\u30fc\u3059\u308b\u8208\u5473\u6df1\u3044\u30d5\u30a1\u30a4\u30eb\u3001\u7d50\u679c\u3001\u307e\u305f\u306f\u30bf\u30b0\u4ed8\u3051\u3055\u308c\u305f\u30a2\u30a4\u30c6\u30e0\u306f\u3042\u308a\u307e\u305b\u3093 +PortableCaseReportModule.generateReport.outputDirDoesNotExist=\u51fa\u529b\u30d5\u30a9\u30eb\u30c0\u30fc{0}\u306f\u5b58\u5728\u3057\u307e\u305b\u3093 +PortableCaseReportModule.generateReport.outputDirIsNotDir=\u51fa\u529b\u30d5\u30a9\u30eb\u30c0{0}\u306f\u30d5\u30a9\u30eb\u30c0\u3067\u306f\u3042\u308a\u307e\u305b\u3093 +PortableCaseReportModule.generateReport.verifying=\u9078\u629e\u3057\u305f\u30d1\u30e9\u30e1\u30fc\u30bf\u3092\u78ba\u8a8d\u3057\u3066\u3044\u307e\u3059... +PortableCaseReportModule.getDescription.description=\u9078\u629e\u3057\u305f\u30a2\u30a4\u30c6\u30e0\u3092\u3001\u7c21\u5358\u306b\u5171\u6709\u3067\u304d\u308b\u30b7\u30f3\u30b0\u30eb\u30e6\u30fc\u30b6\u30fc\u30b1\u30fc\u30b9\u306b\u30b3\u30d4\u30fc\u3057\u307e\u3059 +PortableCaseReportModule.getName.name=\u30dd\u30fc\u30bf\u30d6\u30eb\u30b1\u30fc\u30b9 PortableCaseReportModule_generateReport_copyingAutopsy=\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u30b3\u30d4\u30fc... diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/portablecase/PortableCaseReportModule.java b/Core/src/org/sleuthkit/autopsy/report/modules/portablecase/PortableCaseReportModule.java index f8dbebe224..12412aae20 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/portablecase/PortableCaseReportModule.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/portablecase/PortableCaseReportModule.java @@ -62,6 +62,7 @@ import org.sleuthkit.autopsy.report.ReportProgressPanel; import org.sleuthkit.caseuco.CaseUcoExporter; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Account; +import org.sleuthkit.datamodel.AnalysisResult; import org.sleuthkit.datamodel.Blackboard.BlackboardException; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifactTag; @@ -69,12 +70,19 @@ import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.CaseDbAccessManager; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.ContentTag; +import org.sleuthkit.datamodel.DataArtifact; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.FileSystem; import org.sleuthkit.datamodel.Host; import org.sleuthkit.datamodel.Image; import org.sleuthkit.datamodel.LocalFilesDataSource; +import org.sleuthkit.datamodel.OsAccount; +import org.sleuthkit.datamodel.OsAccountManager; +import org.sleuthkit.datamodel.OsAccountManager.NotUserSIDException; +import org.sleuthkit.datamodel.OsAccountRealm; +import org.sleuthkit.datamodel.OsAccountRealmManager; import org.sleuthkit.datamodel.Pool; +import org.sleuthkit.datamodel.Score; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.SleuthkitCase.CaseDbTransaction; import org.sleuthkit.datamodel.TagName; @@ -132,6 +140,12 @@ public class PortableCaseReportModule implements ReportModule { // Map of old artifact ID to new artifact private final Map oldArtifactIdToNewArtifact = new HashMap<>(); + + // Map of old OS account id to new OS account id + private final Map oldOsAccountIdToNewOsAccountId = new HashMap<>(); + + // Map of old OS account realm id to new OS account ream id + private final Map oldRealmIdToNewRealm = new HashMap<>(); public PortableCaseReportModule() { } @@ -392,8 +406,8 @@ public class PortableCaseReportModule implements ReportModule { // Copy interesting files and results if (!setNames.isEmpty()) { try { - List interestingFiles = currentCase.getSleuthkitCase().getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT); - for (BlackboardArtifact art : interestingFiles) { + List interestingFiles = currentCase.getSleuthkitCase().getBlackboard().getAnalysisResultsByType(BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT.getTypeID()); + for (AnalysisResult art : interestingFiles) { // Check for cancellation if (progressPanel.getStatus() == ReportProgressPanel.ReportStatus.CANCELED) { handleCancellation(progressPanel); @@ -411,8 +425,8 @@ public class PortableCaseReportModule implements ReportModule { } try { - List interestingResults = currentCase.getSleuthkitCase().getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT); - for (BlackboardArtifact art : interestingResults) { + List interestingResults = currentCase.getSleuthkitCase().getBlackboard().getAnalysisResultsByType(BlackboardArtifact.Type.TSK_INTERESTING_ARTIFACT_HIT.getTypeID()); + for (AnalysisResult art : interestingResults) { // Check for cancellation if (progressPanel.getStatus() == ReportProgressPanel.ReportStatus.CANCELED) { handleCancellation(progressPanel); @@ -936,9 +950,6 @@ public class PortableCaseReportModule implements ReportModule { String.join(",", oldAssociatedAttribute.getSources()), newAssociatedArtifact.getArtifactID())); } - // Create the new artifact - int newArtifactTypeId = getNewArtifactTypeId(artifactToCopy); - BlackboardArtifact newArtifact = portableSkCase.newBlackboardArtifact(newArtifactTypeId, newContentId); List oldAttrs = artifactToCopy.getAttributes(); // Copy over each attribute, making sure the type is in the new case. @@ -977,8 +988,62 @@ public class PortableCaseReportModule implements ReportModule { throw new TskCoreException("Unexpected attribute value type found: " + oldAttr.getValueType().getLabel()); // NON-NLS } } - - newArtifact.addAttributes(newAttrs); + // Create the new artifact + int newArtifactTypeId = getNewArtifactTypeId(artifactToCopy); + BlackboardArtifact.Type newArtifactType = portableSkCase.getBlackboard().getArtifactType(newArtifactTypeId); + BlackboardArtifact newArtifact; + + // First, check if the artifact being copied is an AnalysisResult or a DataArtifact. If it + // is neither, attempt to reload it as the appropriate subclass. + if (!((artifactToCopy instanceof AnalysisResult) || (artifactToCopy instanceof DataArtifact))) { + try { + if (newArtifactType.getCategory().equals(BlackboardArtifact.Category.ANALYSIS_RESULT)) { + AnalysisResult ar = currentCase.getSleuthkitCase().getBlackboard().getAnalysisResultById(artifactToCopy.getId()); + if (ar != null) { + artifactToCopy = ar; + } + } else { + DataArtifact da = currentCase.getSleuthkitCase().getBlackboard().getDataArtifactById(artifactToCopy.getId()); + if (da != null) { + artifactToCopy = da; + } + } + } catch (TskCoreException ex) { + // If the lookup failed, just use the orginal BlackboardArtifact + } + } + + try { + if (artifactToCopy instanceof AnalysisResult) { + AnalysisResult analysisResultToCopy = (AnalysisResult) artifactToCopy; + newArtifact = portableSkCase.getBlackboard().newAnalysisResult(newArtifactType, newContentId, + newIdToContent.get(newContentId).getDataSource().getId(), analysisResultToCopy.getScore(), + analysisResultToCopy.getConclusion(), analysisResultToCopy.getConfiguration(), + analysisResultToCopy.getJustification(), newAttrs).getAnalysisResult(); + } else if (artifactToCopy instanceof DataArtifact) { + DataArtifact dataArtifactToCopy = (DataArtifact) artifactToCopy; + Long newOsAccountId = null; + if (dataArtifactToCopy.getOsAccountObjectId().isPresent()) { + copyOsAccount(dataArtifactToCopy.getOsAccountObjectId().get()); + newOsAccountId = oldOsAccountIdToNewOsAccountId.get((dataArtifactToCopy.getOsAccountObjectId().get())); + } + newArtifact = portableSkCase.getBlackboard().newDataArtifact(newArtifactType, newContentId, + newIdToContent.get(newContentId).getDataSource().getId(), + newAttrs, newOsAccountId); + } else { + if (newArtifactType.getCategory().equals(BlackboardArtifact.Category.ANALYSIS_RESULT)) { + newArtifact = portableSkCase.getBlackboard().newAnalysisResult(newArtifactType, newContentId, + newIdToContent.get(newContentId).getDataSource().getId(), Score.SCORE_NONE, + null, null, null, newAttrs).getAnalysisResult(); + } else { + newArtifact = portableSkCase.getBlackboard().newDataArtifact(newArtifactType, newContentId, + newIdToContent.get(newContentId).getDataSource().getId(), + newAttrs, null); + } + } + } catch (BlackboardException ex) { + throw new TskCoreException("Error copying artifact with ID: " + artifactToCopy.getId()); + } oldArtifactIdToNewArtifact.put(artifactToCopy.getArtifactID(), newArtifact); return newArtifact; @@ -1088,6 +1153,14 @@ public class PortableCaseReportModule implements ReportModule { newHost = portableSkCase.getHostManager().newHost(oldHost.getName()); } + // Copy the associated OS account (if needed) before beginning transaction. + if (content instanceof AbstractFile) { + AbstractFile file = (AbstractFile) content; + if (file.getOsAccountObjectId().isPresent()) { + copyOsAccount(file.getOsAccountObjectId().get()); + } + } + CaseDbTransaction trans = portableSkCase.beginTransaction(); try { if (content instanceof Image) { @@ -1140,10 +1213,16 @@ public class PortableCaseReportModule implements ReportModule { // Construct the relative path to the copied file String relativePath = FILE_FOLDER_NAME + File.separator + exportSubFolder + File.separator + fileName; + Long newOsAccountId = null; + if (abstractFile.getOsAccountObjectId().isPresent()) { + newOsAccountId = oldOsAccountIdToNewOsAccountId.get(abstractFile.getOsAccountObjectId().get()); + } + newContent = portableSkCase.addLocalFile(abstractFile.getName(), relativePath, abstractFile.getSize(), abstractFile.getCtime(), abstractFile.getCrtime(), abstractFile.getAtime(), abstractFile.getMtime(), abstractFile.getMd5Hash(), abstractFile.getSha256Hash(), abstractFile.getKnown(), abstractFile.getMIMEType(), - true, TskData.EncodingType.NONE, + true, TskData.EncodingType.NONE, + newOsAccountId, abstractFile.getOwnerUid().orElse(null), newParent, trans); } catch (IOException ex) { throw new TskCoreException("Error copying file " + abstractFile.getName() + " with original obj ID " @@ -1166,6 +1245,72 @@ public class PortableCaseReportModule implements ReportModule { newIdToContent.put(newContent.getId(), newContent); return oldIdToNewContent.get(content.getId()).getId(); } + + /** + * Copy an OS Account to the new case and add it to the oldOsAccountIdToNewOsAccountId map. + * Will also copy the associated realm. + * + * @param oldOsAccountId The OS account id in the current case. + */ + private void copyOsAccount(Long oldOsAccountId) throws TskCoreException { + // If it has already been copied, we're done. + if (oldOsAccountIdToNewOsAccountId.containsKey(oldOsAccountId)) { + return; + } + + // Load the OS account from the current case. + OsAccountManager oldOsAcctManager = currentCase.getSleuthkitCase().getOsAccountManager(); + OsAccount oldOsAccount = oldOsAcctManager.getOsAccountByObjectId(oldOsAccountId); + + // Load the realm associated with the OS account. + OsAccountRealmManager oldRealmManager = currentCase.getSleuthkitCase().getOsAccountRealmManager(); + OsAccountRealm oldRealm = oldRealmManager.getRealmByRealmId(oldOsAccount.getRealmId()); + + // Copy the realm to the portable case if necessary. + if (!oldRealmIdToNewRealm.containsKey(oldOsAccount.getRealmId())) { + OsAccountRealmManager newRealmManager = portableSkCase.getOsAccountRealmManager(); + + Host host = null; + if (oldRealm.getScopeHost().isPresent()) { + host = oldRealm.getScopeHost().get(); + } else { + if (oldRealm.getScope().equals(OsAccountRealm.RealmScope.DOMAIN)) { + // This is a workaround to get around needing a new method for copying the realm. + // The host won't be stored since it's a domain-scoped realm. + List hosts = portableSkCase.getHostManager().getAllHosts(); + if (hosts.isEmpty()) { + throw new TskCoreException("Failed to copy OsAccountRealm with ID=" + oldOsAccount.getRealmId() + " because there are no hosts in the case"); + } + host = hosts.get(0); + } else { + throw new TskCoreException("Failed to copy OsAccountRealm with ID=" + oldOsAccount.getRealmId() + " because it is non-domain scoped but has no scope host"); + } + } + + // We currently only support one realm name. + String realmName = null; + List names = oldRealm.getRealmNames(); + if (!names.isEmpty()) { + realmName = names.get(0); + } + + try { + OsAccountRealm newRealm = newRealmManager.newWindowsRealm(oldRealm.getRealmAddr().orElse(null), realmName, host, oldRealm.getScope()); + oldRealmIdToNewRealm.put(oldOsAccount.getRealmId(), newRealm); + } catch (NotUserSIDException ex) { + throw new TskCoreException("Failed to copy OsAccountRealm with ID=" + oldOsAccount.getRealmId(), ex); + } + } + + OsAccountManager newOsAcctManager = portableSkCase.getOsAccountManager(); + try { + OsAccount newOsAccount = newOsAcctManager.newWindowsOsAccount(oldOsAccount.getAddr().orElse(null), + oldOsAccount.getLoginName().orElse(null), oldRealmIdToNewRealm.get(oldOsAccount.getRealmId())); + oldOsAccountIdToNewOsAccountId.put(oldOsAccountId, newOsAccount.getId()); + } catch (NotUserSIDException ex) { + throw new TskCoreException("Failed to copy OsAccount with ID=" + oldOsAccount.getId(), ex); + } + } /** * Copy path ID attribute to new case along with the referenced file. @@ -1344,6 +1489,8 @@ public class PortableCaseReportModule implements ReportModule { oldArtTypeIdToNewArtTypeId.clear(); oldAttrTypeIdToNewAttrType.clear(); oldArtifactIdToNewArtifact.clear(); + oldOsAccountIdToNewOsAccountId.clear(); + oldRealmIdToNewRealm.clear(); closePortableCaseDatabase(); diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/stix/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/report/modules/stix/Bundle_ja.properties index b57761ac09..55895784e6 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/stix/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/report/modules/stix/Bundle_ja.properties @@ -1,13 +1,18 @@ +#Mon Jul 12 13:22:00 UTC 2021 OpenIDE-Module-Name=stix\u30e2\u30b8\u30e5\u30fc\u30eb STIXReportModule.getDesc.text=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u306b\u5bfe\u3057\u3066\u5e7e\u3064\u304b\u306eSTIX\uff08Structured Threat Information eXpression\uff1b\u8105\u5a01\u60c5\u5831\u69cb\u9020\u5316\u8a18\u8ff0\u5f62\u5f0f\uff09\u30d5\u30a1\u30a4\u30eb\u3092\u5b9f\u884c\u3057\u3001\u30ec\u30dd\u30fc\u30c8\u3092\u751f\u6210\u3057\u307e\u3059\u3002\u307e\u305f\u3001\u7591\u308f\u3057\u3044\u30d5\u30a1\u30a4\u30eb\u5185\u306b\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u3092\u4f5c\u6210\u3002 STIXReportModule.getName.text=STIX +STIXReportModule.notifyErr.noFildDirProvided=STIX\u30d5\u30a1\u30a4\u30eb\uff0f\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u304c\u63d0\u4f9b\u3055\u308c\u3066\u3044\u307e\u305b\u3093 STIXReportModule.notifyMsg.tooManyArtifactsgt1000="{0}"\u7528\u306b\u751f\u6210\u3055\u308c\u305fSTIX\u95a2\u9023\u306e\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u304c\u591a\u3059\u304e\u307e\u3059\u3002\u6700\u521d\u306e1000\u306e\u307f\u4fdd\u5b58\u3055\u308c\u307e\u3059\u3002 STIXReportModule.notifyMsg.unableToOpenFileDir=STIX\u30d5\u30a1\u30a4\u30eb\uff0f\u30c7\u30a3\u30ec\u30af\u30c8\u30ea{0}\u3092\u958b\u3051\u307e\u305b\u3093\u3067\u3057\u305f +STIXReportModule.notifyMsg.unableToOpenReportFile=STIX\u30ec\u30dd\u30fc\u30c8\u3092\u5b8c\u4e86\u3067\u304d\u307e\u305b\u3093\u3002 STIXReportModule.progress.completedWithErrors=\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u304c\u3001\u5b8c\u4e86\u3057\u307e\u3057\u305f STIXReportModule.progress.couldNotOpenFileDir=\u30d5\u30a1\u30a4\u30eb\uff0f\u30c7\u30a3\u30ec\u30af\u30c8\u30ea{0}\u3092\u958b\u3051\u307e\u305b\u3093\u3067\u3057\u305f +STIXReportModule.progress.noFildDirProvided=STIX\u30d5\u30a1\u30a4\u30eb\uff0f\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u304c\u63d0\u4f9b\u3055\u308c\u3066\u3044\u307e\u305b\u3093 STIXReportModule.progress.readSTIX=STIX\u30d5\u30a1\u30a4\u30eb\u3092\u30d1\u30fc\u30b9\u4e2d +STIXReportModule.srcModuleName.text=STIX\u30ec\u30dd\u30fc\u30c8 STIXReportModuleConfigPanel.jButton1.text=\u30d5\u30a1\u30a4\u30eb\u3092\u9078\u629e STIXReportModuleConfigPanel.jCheckBox1.text=\u30a2\u30a6\u30c8\u30d7\u30c3\u30c8\u30d5\u30a1\u30a4\u30eb\u306e\u8aa4\u3063\u305f\u30a4\u30f3\u30b8\u30b1\u30fc\u30bf\u30fc\u306e\u7d50\u679c\u3082\u542b\u3080 STIXReportModuleConfigPanel.jLabel2.text=STIX\u30d5\u30a1\u30a4\u30eb\u307e\u305f\u306fSTIX\u30d5\u30a1\u30a4\u30eb\u306e\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3092\u9078\u629e -STIXReportModule.notifyErr.noFildDirProvided=STIX\u30d5\u30a1\u30a4\u30eb\uff0f\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u304c\u63d0\u4f9b\u3055\u308c\u3066\u3044\u307e\u305b\u3093 -STIXReportModule.progress.noFildDirProvided=STIX\u30d5\u30a1\u30a4\u30eb\uff0f\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u304c\u63d0\u4f9b\u3055\u308c\u3066\u3044\u307e\u305b\u3093 +StixArtifactData.indexError.message=\u30ad\u30fc\u30ef\u30fc\u30c9\u691c\u7d22\u7528\u306eSTIX\u8208\u5473\u6df1\u3044\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u306e\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u4f5c\u6210\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 +StixArtifactData.noOpenCase.errMsg=\u30aa\u30fc\u30d7\u30f3\u30b1\u30fc\u30b9\u306f\u3042\u308a\u307e\u305b\u3093\u3002 diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/stix/StixArtifactData.java b/Core/src/org/sleuthkit/autopsy/report/modules/stix/StixArtifactData.java index 91822de3b8..3d354663b0 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/stix/StixArtifactData.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/stix/StixArtifactData.java @@ -42,7 +42,6 @@ import org.sleuthkit.datamodel.TskCoreException; * */ class StixArtifactData { - private static final String MODULE_NAME = "Stix"; private AbstractFile file; @@ -89,8 +88,10 @@ class StixArtifactData { // Create artifact if it doesn't already exist. if (!blackboard.artifactExists(file, TSK_INTERESTING_FILE_HIT, attributes)) { BlackboardArtifact bba = file.newAnalysisResult( - new BlackboardArtifact.Type(TSK_INTERESTING_FILE_HIT), - Score.SCORE_UNKNOWN, null, null, null, attributes).getAnalysisResult(); + BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT, Score.SCORE_LIKELY_NOTABLE, + null, setName, null, + attributes) + .getAnalysisResult(); try { /* diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/taggedhashes/SaveTaggedHashesToHashDb.java b/Core/src/org/sleuthkit/autopsy/report/modules/taggedhashes/SaveTaggedHashesToHashDb.java index 269350b288..9b37ff7edd 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/taggedhashes/SaveTaggedHashesToHashDb.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/taggedhashes/SaveTaggedHashesToHashDb.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2020 Basis Technology Corp. + * Copyright 2011-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -67,7 +67,7 @@ public class SaveTaggedHashesToHashDb implements GeneralReportModule { public String getRelativeFilePath() { return null; } - + /** * Get default configuration for this report module. * @@ -101,14 +101,14 @@ public class SaveTaggedHashesToHashDb implements GeneralReportModule { configPanel.setConfiguration((HashesReportModuleSettings) getDefaultConfiguration()); return; } - + if (settings instanceof HashesReportModuleSettings) { configPanel.setConfiguration((HashesReportModuleSettings) settings); return; } throw new IllegalArgumentException("Expected settings argument to be an instance of HashesReportModuleSettings"); - } + } @Messages({ "AddTaggedHashesToHashDb.error.noHashSetsSelected=No hash set selected for export.", @@ -136,7 +136,7 @@ public class SaveTaggedHashesToHashDb implements GeneralReportModule { progressPanel.complete(ReportProgressPanel.ReportStatus.ERROR, Bundle.AddTaggedHashesToHashDb_error_noHashSetsSelected()); return; } - + progressPanel.updateStatusLabel("Adding hashes to " + hashSet.getHashSetName() + " hash set..."); TagsManager tagsManager = openCase.getServices().getTagsManager(); @@ -147,54 +147,52 @@ public class SaveTaggedHashesToHashDb implements GeneralReportModule { progressPanel.complete(ReportProgressPanel.ReportStatus.ERROR, Bundle.AddTaggedHashesToHashDb_error_noTagsSelected()); return; } - + ArrayList failedExports = new ArrayList<>(); + int notAddedCount = 0; + int addedCount = 0; for (TagName tagName : tagNames) { if (progressPanel.getStatus() == ReportProgressPanel.ReportStatus.CANCELED) { break; } progressPanel.updateStatusLabel("Adding " + tagName.getDisplayName() + " hashes to " + hashSet.getHashSetName() + " hash set..."); + List tags = new ArrayList<>(); try { - List tags = tagsManager.getContentTagsByTagName(tagName); - for (ContentTag tag : tags) { - // TODO: Currently only AbstractFiles have md5 hashes. Here only files matter. - Content content = tag.getContent(); - if (content instanceof AbstractFile) { - if (null != ((AbstractFile) content).getMd5Hash()) { - try { - hashSet.addHashes(tag.getContent(), openCase.getDisplayName()); - } catch (TskCoreException ex) { - Logger.getLogger(SaveTaggedHashesToHashDb.class.getName()).log(Level.SEVERE, "Error adding hash for obj_id = " + tag.getContent().getId() + " to hash set " + hashSet.getHashSetName(), ex); - failedExports.add(tag.getContent().getName()); - } - } else { - progressPanel.updateStatusLabel("Unable to add the " + (tags.size() > 1 ? "files" : "file") + " to the hash set. Hashes have not been calculated. Please configure and run an appropriate ingest module."); - break; - } - } - } + tags.addAll(tagsManager.getContentTagsByTagName(tagName)); + } catch (TskCoreException ex) { Logger.getLogger(SaveTaggedHashesToHashDb.class.getName()).log(Level.SEVERE, "Error adding to hash set", ex); progressPanel.updateStatusLabel("Error getting selected tags for case."); } - } - if (!failedExports.isEmpty()) { - StringBuilder errorMessage = new StringBuilder("Failed to export hashes for the following files: "); - for (int i = 0; i < failedExports.size(); ++i) { - errorMessage.append(failedExports.get(i)); - if (failedExports.size() > 1 && i < failedExports.size() - 1) { - errorMessage.append(","); - } - if (i == failedExports.size() - 1) { - errorMessage.append("."); + for (ContentTag tag : tags) { + // TODO: Currently only AbstractFiles have md5 hashes. Here only files matter. + Content content = tag.getContent(); + if (content instanceof AbstractFile) { + if (null != ((AbstractFile) content).getMd5Hash()) { + //if there is a failure to add the file for a reason other than missing an md5 keep going but take note + try { + hashSet.addHashes(content, openCase.getDisplayName()); + addedCount++; + } catch (TskCoreException ex) { + Logger.getLogger(SaveTaggedHashesToHashDb.class.getName()).log(Level.SEVERE, "Error adding hash for obj_id = " + content.getId() + " to hash set " + hashSet.getHashSetName(), ex); + failedExports.add(content.getName()); + } + } else { + notAddedCount++; + } } } - progressPanel.updateStatusLabel(errorMessage.toString()); } - progressPanel.setIndeterminate(false); - progressPanel.complete(ReportProgressPanel.ReportStatus.COMPLETE); + //if the failed exports indicate the report had an issue note the files and indicate an error otherwise if there was no error indicate it is complete + if (!failedExports.isEmpty()) { + StringBuilder errorMessage = new StringBuilder("Failed to export hashes for the following file" + (failedExports.size() > 1 ? " and " + (failedExports.size() - 1) + " others: " : ": ")); + errorMessage.append(failedExports.get(0)); + progressPanel.complete(ReportProgressPanel.ReportStatus.ERROR, errorMessage.toString()); + } else if (progressPanel.getStatus() != ReportProgressPanel.ReportStatus.ERROR) { + progressPanel.complete(ReportProgressPanel.ReportStatus.COMPLETE, addedCount + " file(s) added to hash set. " + notAddedCount + " file(s) without a hash skipped."); + } } @Override @@ -202,7 +200,7 @@ public class SaveTaggedHashesToHashDb implements GeneralReportModule { initializePanel(); return configPanel; } - + private void initializePanel() { if (configPanel == null) { configPanel = new SaveTaggedHashesToHashDbConfigPanel(); diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/taggedhashes/SaveTaggedHashesToHashDbConfigPanel.form b/Core/src/org/sleuthkit/autopsy/report/modules/taggedhashes/SaveTaggedHashesToHashDbConfigPanel.form index 6047a7a789..cbec9b572d 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/taggedhashes/SaveTaggedHashesToHashDbConfigPanel.form +++ b/Core/src/org/sleuthkit/autopsy/report/modules/taggedhashes/SaveTaggedHashesToHashDbConfigPanel.form @@ -49,18 +49,18 @@ - + - + - + - + @@ -87,7 +87,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/taggedhashes/SaveTaggedHashesToHashDbConfigPanel.java b/Core/src/org/sleuthkit/autopsy/report/modules/taggedhashes/SaveTaggedHashesToHashDbConfigPanel.java index 081aa03b61..afa511657d 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/taggedhashes/SaveTaggedHashesToHashDbConfigPanel.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/taggedhashes/SaveTaggedHashesToHashDbConfigPanel.java @@ -322,7 +322,7 @@ class SaveTaggedHashesToHashDbConfigPanel extends javax.swing.JPanel { layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addComponent(jLabel1) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(jAllTagsCheckBox) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -330,7 +330,7 @@ class SaveTaggedHashesToHashDbConfigPanel extends javax.swing.JPanel { .addComponent(selectAllButton) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(deselectAllButton)) - .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 112, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 112, Short.MAX_VALUE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jLabel2) .addGap(4, 4, 4) diff --git a/Core/src/org/sleuthkit/autopsy/textextractors/ArtifactTextExtractor.java b/Core/src/org/sleuthkit/autopsy/textextractors/ArtifactTextExtractor.java index 43c0112f1a..184cd064b6 100644 --- a/Core/src/org/sleuthkit/autopsy/textextractors/ArtifactTextExtractor.java +++ b/Core/src/org/sleuthkit/autopsy/textextractors/ArtifactTextExtractor.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2018 Basis Technology Corp. + * Copyright 2011-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,10 +22,9 @@ import java.io.InputStreamReader; import java.io.Reader; import java.nio.charset.StandardCharsets; import org.apache.commons.io.IOUtils; -import org.sleuthkit.autopsy.datamodel.ContentUtils; +import org.sleuthkit.autopsy.coreutils.TimeZoneUtils; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; -import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.TskCoreException; /** @@ -57,7 +56,7 @@ class ArtifactTextExtractor implements TextExtractor { // in the Autopsy datamodel. switch (attribute.getValueType()) { case DATETIME: - artifactContents.append(ContentUtils.getStringTime(attribute.getValueLong(), artifact)); + artifactContents.append(TimeZoneUtils.getFormattedTime(attribute.getValueLong())); break; default: artifactContents.append(attribute.getDisplayString()); diff --git a/Core/src/org/sleuthkit/autopsy/textextractors/TextExtractor.java b/Core/src/org/sleuthkit/autopsy/textextractors/TextExtractor.java index 69b98cdd12..e6c0ddcaba 100644 --- a/Core/src/org/sleuthkit/autopsy/textextractors/TextExtractor.java +++ b/Core/src/org/sleuthkit/autopsy/textextractors/TextExtractor.java @@ -22,6 +22,8 @@ import java.io.Reader; import java.util.Collections; import java.util.Map; import org.openide.util.Lookup; +import org.sleuthkit.autopsy.textextractors.configs.ImageConfig; +import org.sleuthkit.datamodel.AbstractFile; /** * Extracts the text out of Content instances and exposes them as a Reader. @@ -63,10 +65,10 @@ public interface TextExtractor { default void setExtractionSettings(Lookup context) { //no-op by default } - + /** * Retrieves content metadata, if any. - * + * * @return Metadata as key -> value map */ default Map getMetadata() { @@ -74,7 +76,17 @@ public interface TextExtractor { } /** - * System level exception for reader initialization. + * Returns true if this text extractor, based on the provided settings, will + * perform ocr. + * + * @return True if will perform OCR. + */ + default boolean willUseOCR() { + return false; + } + + /** + * System level exception for reader initialization. */ public class InitReaderException extends Exception { diff --git a/Core/src/org/sleuthkit/autopsy/textextractors/TikaTextExtractor.java b/Core/src/org/sleuthkit/autopsy/textextractors/TikaTextExtractor.java index f2e7654908..470c0f8cf4 100644 --- a/Core/src/org/sleuthkit/autopsy/textextractors/TikaTextExtractor.java +++ b/Core/src/org/sleuthkit/autopsy/textextractors/TikaTextExtractor.java @@ -18,7 +18,6 @@ */ package org.sleuthkit.autopsy.textextractors; -import com.google.common.collect.ImmutableList; import com.google.common.io.CharSource; import com.google.common.util.concurrent.ThreadFactoryBuilder; import java.io.File; @@ -71,12 +70,15 @@ import org.xml.sax.ContentHandler; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; import java.io.InputStreamReader; import java.nio.charset.Charset; import java.util.ArrayList; +import java.util.Set; +import org.apache.tika.mime.MimeTypes; import org.apache.tika.parser.pdf.PDFParserConfig.OCR_STRATEGY; import org.sleuthkit.autopsy.coreutils.ExecUtil.HybridTerminator; -import org.sleuthkit.datamodel.TskData; +import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; /** * Extracts text from Tika supported content. Protects against Tika parser hangs @@ -86,8 +88,8 @@ final class TikaTextExtractor implements TextExtractor { //Mimetype groups to aassist extractor implementations in ignoring binary and //archive files. - private static final List BINARY_MIME_TYPES - = ImmutableList.of( + private static final Set BINARY_MIME_TYPES + = ImmutableSet.of( //ignore binary blob data, for which string extraction will be used "application/octet-stream", //NON-NLS "application/x-msdownload"); //NON-NLS @@ -96,8 +98,8 @@ final class TikaTextExtractor implements TextExtractor { * generally text extractors should ignore archives and let unpacking * modules take care of them */ - private static final List ARCHIVE_MIME_TYPES - = ImmutableList.of( + private static final Set ARCHIVE_MIME_TYPES + = ImmutableSet.of( //ignore unstructured binary and compressed data, for which string extraction or unzipper works better "application/x-7z-compressed", //NON-NLS "application/x-ace-compressed", //NON-NLS @@ -134,22 +136,36 @@ final class TikaTextExtractor implements TextExtractor { // Used to log to the tika file that is why it uses the java.util.logging.logger class instead of the Autopsy one private static final java.util.logging.Logger TIKA_LOGGER = java.util.logging.Logger.getLogger("Tika"); //NON-NLS private static final Logger AUTOPSY_LOGGER = Logger.getLogger(TikaTextExtractor.class.getName()); - private static final int LIMITED_OCR_SIZE_MIN = 100 * 1024; + private final ThreadFactory tikaThreadFactory = new ThreadFactoryBuilder().setNameFormat("tika-reader-%d").build(); private final ExecutorService executorService = Executors.newSingleThreadExecutor(tikaThreadFactory); private static final String SQLITE_MIMETYPE = "application/x-sqlite3"; private final AutoDetectParser parser = new AutoDetectParser(); + private final FileTypeDetector fileTypeDetector; private final Content content; private boolean tesseractOCREnabled; - private boolean limitedOCREnabled; private static final String TESSERACT_DIR_NAME = "Tesseract-OCR"; //NON-NLS private static final String TESSERACT_EXECUTABLE = "tesseract.exe"; //NON-NLS private static final File TESSERACT_PATH = locateTesseractExecutable(); private String languagePacks = formatLanguagePacks(PlatformUtil.getOcrLanguagePacks()); private static final String TESSERACT_OUTPUT_FILE_NAME = "tess_output"; //NON-NLS + + // documents where OCR is performed + private static final ImmutableSet OCR_DOCUMENTS = ImmutableSet.of( + "application/pdf", + "application/msword", + "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + "application/vnd.ms-powerpoint", + "application/vnd.openxmlformats-officedocument.presentationml.presentation", + "application/vnd.ms-excel", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" + ); + + private static final String IMAGE_MIME_TYPE_PREFIX = "image/"; + private Map metadataMap; private ProcessTerminator processTerminator; @@ -162,18 +178,62 @@ final class TikaTextExtractor implements TextExtractor { TikaTextExtractor(Content content) { this.content = content; + + FileTypeDetector detector = null; + try { + detector = new FileTypeDetector(); + } catch (FileTypeDetector.FileTypeDetectorInitException ex) { + TIKA_LOGGER.log(Level.SEVERE, "Unable to instantiate a file type detector", ex); + } + this.fileTypeDetector = detector; } /** - * If Tesseract has been installed and is set to be used through - * configuration, then ocr is enabled. OCR can only currently be run on 64 - * bit Windows OS. + * Obtains the mime type of the file using a FileTypeDetector with the + * file's mime type as fallback if the FileTypeDetector is not instantiated. + * If no mime type present, MimeTypes.OCTET_STREAM is returned. * - * @return Flag indicating if OCR is set to be used. + * @param file The abstract file instance. + * + * @return The mime type or MimeTypes.OCTET_STREAM if the mime type cannot + * be determined. */ - private boolean ocrEnabled() { - return TESSERACT_PATH != null && tesseractOCREnabled - && PlatformUtil.isWindowsOS() == true && PlatformUtil.is64BitOS(); + private String getMimeType(AbstractFile file) { + String mimeType = MimeTypes.OCTET_STREAM; + if (fileTypeDetector != null) { + mimeType = fileTypeDetector.getMIMEType(file); + } else if (file.getMIMEType() != null) { + mimeType = file.getMIMEType(); + } + + return mimeType.trim().toLowerCase(); + } + + @Override + public boolean willUseOCR() { + if (!isOcrSupported() || (!(content instanceof AbstractFile))) { + return false; + } + + String mimeType = getMimeType((AbstractFile) content); + // in order to ocr, it needs to either be an image or a document with embedded content + return mimeType.startsWith(IMAGE_MIME_TYPE_PREFIX) || OCR_DOCUMENTS.contains(mimeType); + } + + /** + * Whether or not OCR is supported in environment. + * + * @return True if OCR is supported. + */ + private boolean isOcrSupported() { + // If Tesseract has been installed and is set to be used through + // configuration, then ocr is enabled. OCR can only currently be run on 64 + // bit Windows OS. + return TESSERACT_PATH != null + && tesseractOCREnabled + && PlatformUtil.isWindowsOS() + && PlatformUtil.is64BitOS() + && isSupported(); } /** @@ -195,33 +255,31 @@ final class TikaTextExtractor implements TextExtractor { // Only abstract files are supported, see isSupported() final AbstractFile file = ((AbstractFile) content); - // This mime type must be non-null, see isSupported() - final String mimeType = file.getMIMEType(); + + String mimeType = getMimeType(file); // Handle images seperately so the OCR task can be cancelled. // See JIRA-4519 for the need to have cancellation in the UI and ingest. - if (ocrEnabled() && mimeType.toLowerCase().startsWith("image/") && useOcrOnFile(file)) { + if (isOcrSupported() && mimeType.startsWith(IMAGE_MIME_TYPE_PREFIX)) { InputStream imageOcrStream = performOCR(file); return new InputStreamReader(imageOcrStream, Charset.forName("UTF-8")); } // Set up Tika final InputStream stream = new ReadContentInputStream(content); - final ParseContext parseContext = new ParseContext(); + final ParseContext parseContext = new ParseContext(); // Documents can contain other documents. By adding // the parser back into the context, Tika will recursively // parse embedded documents. parseContext.set(Parser.class, parser); - // Use the more memory efficient Tika SAX parsers for DOCX and // PPTX files (it already uses SAX for XLSX). OfficeParserConfig officeParserConfig = new OfficeParserConfig(); officeParserConfig.setUseSAXPptxExtractor(true); officeParserConfig.setUseSAXDocxExtractor(true); parseContext.set(OfficeParserConfig.class, officeParserConfig); - - if (ocrEnabled() && useOcrOnFile(file)) { + if (isOcrSupported()) { // Configure OCR for Tika if it chooses to run OCR // during extraction TesseractOCRConfig ocrConfig = new TesseractOCRConfig(); @@ -234,10 +292,10 @@ final class TikaTextExtractor implements TextExtractor { // Configure how Tika handles OCRing PDFs PDFParserConfig pdfConfig = new PDFParserConfig(); - // This stategy tries to pick between OCRing a page in the + // This stategy tries to pick between OCRing a page in the // PDF and doing text extraction. It makes this choice by // first running text extraction and then counting characters. - // If there are too few characters or too many unmapped + // If there are too few characters or too many unmapped // unicode characters, it'll run the entire page through OCR // and take that output instead. See JIRA-6938 pdfConfig.setOcrStrategy(OCR_STRATEGY.AUTO); @@ -347,22 +405,6 @@ final class TikaTextExtractor implements TextExtractor { } } - /** - * Method to indicate if OCR should be performed on this image file. Checks - * to see if the limited OCR setting is enabled. If it is it will also check - * that one of the limiting factors is true. - * - * @param file The AbstractFile which OCR might be performed on. - * @param boolean The configuration setting which indicates if limited OCR - * is enabled in Keyword Search. - * - * @return True if limited OCR is not enabled or the image is greater than - * 100KB in size or the image is a derived file. - */ - private boolean useOcrOnFile(AbstractFile file) { - return !limitedOCREnabled || file.getSize() > LIMITED_OCR_SIZE_MIN || file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.DERIVED; - } - /** * Wraps the creation of a TikaReader into a Future so that it can be * cancelled. @@ -551,12 +593,8 @@ final class TikaTextExtractor implements TextExtractor { List terminators = new ArrayList<>(); ImageConfig configInstance = context.lookup(ImageConfig.class); if (configInstance != null) { - if (Objects.nonNull(configInstance.getOCREnabled())) { - this.tesseractOCREnabled = configInstance.getOCREnabled(); - } - if (Objects.nonNull(configInstance.getLimitedOCREnabled())) { - this.limitedOCREnabled = configInstance.getLimitedOCREnabled(); - } + this.tesseractOCREnabled = configInstance.getOCREnabled(); + if (Objects.nonNull(configInstance.getOCRLanguages())) { this.languagePacks = formatLanguagePacks(configInstance.getOCRLanguages()); } diff --git a/Core/src/org/sleuthkit/autopsy/textextractors/configs/ImageConfig.java b/Core/src/org/sleuthkit/autopsy/textextractors/configs/ImageConfig.java index 6c501a7bdf..39fb7db959 100755 --- a/Core/src/org/sleuthkit/autopsy/textextractors/configs/ImageConfig.java +++ b/Core/src/org/sleuthkit/autopsy/textextractors/configs/ImageConfig.java @@ -18,6 +18,8 @@ */ package org.sleuthkit.autopsy.textextractors.configs; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; import org.sleuthkit.autopsy.coreutils.ExecUtil.ProcessTerminator; import org.sleuthkit.autopsy.coreutils.ExecUtil.TimedProcessTerminator; @@ -32,9 +34,8 @@ public class ImageConfig { private static final int OCR_TIMEOUT_SECONDS = 30 * 60; - private Boolean OCREnabled; - private Boolean limitedOCREnabled; - private List ocrLanguages; + private boolean OCREnabled = false; + private List ocrLanguages = null; private final TimedProcessTerminator ocrTimedTerminator = new TimedProcessTerminator(OCR_TIMEOUT_SECONDS); /** @@ -47,16 +48,6 @@ public class ImageConfig { this.OCREnabled = enabled; } - /** - * Enables the limiting OCR to be run on larger images and images which were - * extracted from documents. - * - * @param enabled Flag indicating if OCR is enabled. - */ - public void setLimitedOCREnabled(boolean enabled) { - this.limitedOCREnabled = enabled; - } - /** * Gets the OCR flag that has been set. By default this flag is turned off. * @@ -65,20 +56,22 @@ public class ImageConfig { public boolean getOCREnabled() { return this.OCREnabled; } - + /** - * Sets languages for OCR. + * Sets languages for OCR. Can be null. * * See PlatformUtil for list of installed language packs. * * @param languages List of languages to use */ public void setOCRLanguages(List languages) { - this.ocrLanguages = languages; + this.ocrLanguages = languages == null ? + null : + Collections.unmodifiableList(new ArrayList<>(languages)); } /** - * Gets the list of languages OCR should perform. + * Gets the list of languages OCR should perform. Can be null. * * @return Collection of OCR languages */ @@ -94,15 +87,4 @@ public class ImageConfig { public ProcessTerminator getOCRTimeoutTerminator() { return ocrTimedTerminator; } - - /** - * Gets the limited OCR flag to indicate if OCR should be limited to larger - * images and images which were extracted from documents. - * - * @return Flag indicating if limited OCR is enabled. True if OCR should be - * limited, false otherwise.. - */ - public boolean getLimitedOCREnabled() { - return limitedOCREnabled; - } } diff --git a/Core/src/org/sleuthkit/autopsy/texttranslation/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/texttranslation/Bundle_ja.properties index 940f9aaa48..8ed6ca5ce6 100644 --- a/Core/src/org/sleuthkit/autopsy/texttranslation/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/texttranslation/Bundle_ja.properties @@ -1,9 +1,10 @@ -#Fri Feb 12 16:56:29 UTC 2021 +#Mon Jul 12 13:22:00 UTC 2021 OptionsCategory_Keywords_Machine_Translation_Settings=\u6a5f\u68b0\u7ffb\u8a33\u8a2d\u5b9a OptionsCategory_Name_Machine_Translation=\u6a5f\u68b0\u7ffb\u8a33 TranslationContentPanel.ocrLabel.text=OCR\: TranslationContentPanel.showLabel.text=\u8868\u793a\: TranslationOptionsPanel.enableOcrCheckBox.text=\u7ffb\u8a33\u30b3\u30f3\u30c6\u30f3\u30c4\u30d3\u30e5\u30fc\u30a2\u3067OCR\u6587\u5b57\u8a8d\u8b58\u3092\u6709\u52b9\u306b\u3059\u308b +TranslationOptionsPanel.noTextTranslatorSelected.text=\u30c6\u30ad\u30b9\u30c8\u7ffb\u8a33\u6a5f\u304c\u9078\u629e\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002\u7ffb\u8a33\u306f\u7121\u52b9\u306b\u306a\u3063\u3066\u3044\u307e\u3059\u3002 TranslationOptionsPanel.noTextTranslators.text=\u30c6\u30ad\u30b9\u30c8\u7ffb\u8a33\u30c4\u30fc\u30eb\u304c\u9078\u629e\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002\u7ffb\u8a33\u304c\u7121\u52b9\u306b\u306a\u3063\u3066\u3044\u307e\u3059\u3002 TranslationOptionsPanel.textTranslatorsUnavailable.text=\u9078\u629e\u3057\u305f\u30c6\u30ad\u30b9\u30c8\u7ffb\u8a33\u30c4\u30fc\u30eb\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3002\u7ffb\u8a33\u304c\u7121\u52b9\u306b\u306a\u3063\u3066\u3044\u307e\u3059\u3002 TranslationOptionsPanel.translationDisabled.text=\u7ffb\u8a33\u304c\u7121\u52b9\u306b\u306a\u3063\u3066\u3044\u307e\u3059 diff --git a/Core/src/org/sleuthkit/autopsy/texttranslation/ui/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/texttranslation/ui/Bundle_ja.properties index 9dcea73218..5e5de66d53 100644 --- a/Core/src/org/sleuthkit/autopsy/texttranslation/ui/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/texttranslation/ui/Bundle_ja.properties @@ -1,4 +1,4 @@ -#Fri Feb 12 16:56:29 UTC 2021 +#Mon Jul 12 13:22:00 UTC 2021 OptionsCategory_Keywords_Machine_Translation_Settings=\u6a5f\u68b0\u7ffb\u8a33\u8a2d\u5b9a OptionsCategory_Name_Machine_Translation=\u6a5f\u68b0\u7ffb\u8a33 TranslatedContentPanel.comboBoxOption.originalText=\u30aa\u30ea\u30b8\u30ca\u30eb\u30c6\u30ad\u30b9\u30c8(\u6700\u592725KB) @@ -8,6 +8,8 @@ TranslatedContentViewer.errorExtractingText=\u30d5\u30a1\u30a4\u30eb\u304b\u3089 TranslatedContentViewer.errorMsg=\u30d5\u30a1\u30a4\u30eb\u306e\u30c6\u30ad\u30b9\u30c8\u3092\u53d6\u5f97\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 TranslatedContentViewer.extractingFileText=\u30d5\u30a1\u30a4\u30eb\u304b\u3089\u30c6\u30ad\u30b9\u30c8\u3092\u62bd\u51fa\u4e2d\u3067\u3059\u3002\u304a\u5f85\u3061\u304f\u3060\u3055\u3044... TranslatedContentViewer.extractingImageText=\u30a4\u30e1\u30fc\u30b8\u304b\u3089\u30c6\u30ad\u30b9\u30c8\u3092\u62bd\u51fa\u4e2d\u3067\u3059\u3002\u304a\u5f85\u3061\u304f\u3060\u3055\u3044... +TranslatedContentViewer.extractingText=\u30c6\u30ad\u30b9\u30c8\u3092\u62bd\u51fa\u3057\u3066\u3044\u307e\u3059\u3002\u3057\u3070\u3089\u304f\u304a\u5f85\u3061\u304f\u3060\u3055\u3044... +TranslatedContentViewer.fileHasNoText=\u30d5\u30a1\u30a4\u30eb\u306b\u30c6\u30ad\u30b9\u30c8\u304c\u3042\u308a\u307e\u305b\u3093\u3002 TranslatedContentViewer.noIndexedTextMsg=\u30ad\u30fc\u30ef\u30fc\u30c9\u691c\u7d22\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u5b9f\u884c\u3057\u3001\u7ffb\u8a33\u30c6\u30ad\u30b9\u30c8\u3092\u53d6\u5f97\u3057\u307e\u3059\u3002 TranslatedContentViewer.noServiceProvider=\u6a5f\u68b0\u7ffb\u8a33\u30bd\u30d5\u30c8\u30a6\u30a7\u30a2\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f\u3002 TranslatedContentViewer.ocrNotEnabled=OCR\u304c\u6709\u52b9\u306b\u306a\u3063\u3066\u3044\u307e\u305b\u3093\u3002 \u5909\u66f4\u3059\u308b\u306b\u306f\u3001[\u30c4\u30fc\u30eb]-> [\u30aa\u30d7\u30b7\u30e7\u30f3]-> [\u6a5f\u68b0\u7ffb\u8a33]\u3092\u9078\u3093\u3067\u4e0b\u3055\u3044 diff --git a/Core/src/org/sleuthkit/autopsy/timeline/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/timeline/Bundle_ja.properties index 918ab67c66..29083e3cd2 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/timeline/Bundle_ja.properties @@ -1,10 +1,13 @@ +#Mon Jul 12 13:22:00 UTC 2021 CTL_MakeTimeline=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3 -CTL_TimeLineTopComponentAction=TimeLineTopComponent CTL_TimeLineTopComponent=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3 - -OpenTimelineAction.displayName=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3 +CTL_TimeLineTopComponentAction=TimeLineTopComponent +FilteredEventsModel.timeRangeProperty.errorMessage=\u30b9\u30d1\u30f3\u9593\u9694\u306e\u53d6\u5f97\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +FilteredEventsModel.timeRangeProperty.errorTitle=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3 OpenTimeLineAction.msgdlg.text=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u304c\u3042\u308a\u307e\u305b\u3093\u3002 +OpenTimelineAction.displayName=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3 OpenTimelineAction.settingsErrorMessage=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u8a2d\u5b9a\u3092\u521d\u671f\u5316\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +ProgressWindow.progressHeader.text=\ PrompDialogManager.buttonType.continueNoUpdate=\u66f4\u65b0\u305b\u305a\u306b\u7d9a\u884c PrompDialogManager.buttonType.showTimeline=\u7d9a\u884c PrompDialogManager.buttonType.update=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u66f4\u65b0 @@ -20,47 +23,43 @@ PromptDialogManager.showTooManyFiles.headerText= ShowInTimelineDialog.amountValidator.message=\u5165\u529b\u3059\u308b\u91cf\u306b\u306f\u6570\u5b57\u306e\u307f\u304c\u542b\u307e\u308c\u3066\u3044\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002 ShowInTimelineDialog.artifactTitle=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u306b\u7d50\u679c\u3092\u8868\u793a\u3057\u307e\u3059\u3002 ShowInTimelineDialog.eventSelectionValidator.message=\u30a4\u30d9\u30f3\u30c8\u3092\u9078\u629e\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002 -# {0} - \u30d5\u30a1\u30a4\u30eb\u30d1\u30b9 ShowInTimelineDialog.fileTitle=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u306b {0} \u3092\u8868\u793a\u3057\u307e\u3059\u3002 ShowInTimelineDialog.showTimelineButtonType.text=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u3092\u8868\u793a -Timeline.dialogs.title=\ \u30bf\u30a4\u30e0\u30e9\u30a4\u30f3 -Timeline.frameName.text={0} - Autopsy\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3 -Timeline.resultsPanel.title=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u7d50\u679c -Timeline.runJavaFxThread.progress.creating=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u3092\u4f5c\u6210\u4e2d\u3067\u3059 ... -Timeline.zoomOutButton.text=\u30ba\u30fc\u30e0\u30a2\u30a6\u30c8 -Timeline.goToButton.text=\u79fb\u52d5: -Timeline.yearBarChart.x.years=\u5e74 -Timeline.resultPanel.loading=\u8aad\u307f\u8fbc\u307f\u4e2d... - TimeLineController.errorTitle=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u30a8\u30e9\u30fc\u3067\u3059\u3002 TimeLineController.outOfDate.errorMessage=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u304c\u6700\u65b0\u306e\u60c5\u5831\u3067\u306f\u306a\u3044\u304b\u3069\u3046\u304b\u3092\u5224\u65ad\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 \u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u3092\u66f4\u65b0\u3059\u308b\u5fc5\u8981\u304c\u3042\u308b\u3068\u4eee\u5b9a\u3057\u307e\u3059\u3002 \u30ed\u30b0\u3092\u8868\u793a\u3057\u3066\u8a73\u7d30\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -TimeLineController.rebuildReasons.incompleteOldSchema=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u306e\u30a4\u30d9\u30f3\u30c8\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306f\u4ee5\u524d\u306b\u4e0d\u5b8c\u5168\u306a\u60c5\u5831\u3067\u5165\u529b\u3055\u308c\u307e\u3057\u305f: \u30a4\u30d9\u30f3\u30c8\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u66f4\u65b0\u3057\u306a\u3044\u9650\u308a\u3001\u4e00\u90e8\u306e\u6a5f\u80fd\u304c\u5229\u7528\u3067\u304d\u306a\u3044\u304b\u6a5f\u80fd\u3057\u306a\u3044\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 -TimeLineController.rebuildReasons.ingestWasRunning=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u306e\u30a4\u30d9\u30f3\u30c8\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306f\u4ee5\u524d\u306b\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u5b9f\u884c\u4e2d\u306b\u5165\u529b\u3055\u308c\u307e\u3057\u305f: \u4e00\u90e8\u306e\u30a4\u30d9\u30f3\u30c8\u304c\u898b\u3064\u304b\u3089\u306a\u3044\u304b\u3001\u4e0d\u5b8c\u5168\u304b\u3001\u6b63\u78ba\u3067\u306f\u306a\u3044\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 -TimeLineController.rebuildReasons.outOfDate=\u30a4\u30d9\u30f3\u30c8\u30c7\u30fc\u30bf\u306f\u6700\u65b0\u3067\u306f\u3042\u308a\u307e\u305b\u3093: \u3059\u3079\u3066\u306e\u30c7\u30fc\u30bf\u3092\u8868\u793a\u3067\u304d\u307e\u305b\u3093\u3002 +TimeLineController.rebuildReasons.incompleteOldSchema=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u306e\u30a4\u30d9\u30f3\u30c8\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306f\u4ee5\u524d\u306b\u4e0d\u5b8c\u5168\u306a\u60c5\u5831\u3067\u5165\u529b\u3055\u308c\u307e\u3057\u305f\: \u30a4\u30d9\u30f3\u30c8\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u66f4\u65b0\u3057\u306a\u3044\u9650\u308a\u3001\u4e00\u90e8\u306e\u6a5f\u80fd\u304c\u5229\u7528\u3067\u304d\u306a\u3044\u304b\u6a5f\u80fd\u3057\u306a\u3044\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 +TimeLineController.rebuildReasons.ingestWasRunning=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u306e\u30a4\u30d9\u30f3\u30c8\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306f\u4ee5\u524d\u306b\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u5b9f\u884c\u4e2d\u306b\u5165\u529b\u3055\u308c\u307e\u3057\u305f\: \u4e00\u90e8\u306e\u30a4\u30d9\u30f3\u30c8\u304c\u898b\u3064\u304b\u3089\u306a\u3044\u304b\u3001\u4e0d\u5b8c\u5168\u304b\u3001\u6b63\u78ba\u3067\u306f\u306a\u3044\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 +TimeLineController.rebuildReasons.outOfDate=\u30a4\u30d9\u30f3\u30c8\u30c7\u30fc\u30bf\u306f\u6700\u65b0\u3067\u306f\u3042\u308a\u307e\u305b\u3093\: \u3059\u3079\u3066\u306e\u30c7\u30fc\u30bf\u3092\u8868\u793a\u3067\u304d\u307e\u305b\u3093\u3002 TimeLineController.rebuildReasons.outOfDateError=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u30c7\u30fc\u30bf\u304c\u6700\u65b0\u306e\u60c5\u5831\u3067\u306f\u306a\u3044\u304b\u3069\u3046\u304b\u3092\u5224\u65ad\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 TimeLineController.setEventsDBStale.errMsgNotStale=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u53e4\u3044\u3082\u306e\u3068\u3057\u3066\u30de\u30fc\u30af\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u4e00\u90e8\u306e\u7d50\u679c\u304c\u6700\u65b0\u3067\u306f\u306a\u3044\u304b\u898b\u3064\u304b\u3089\u306a\u3044\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 TimeLineController.setEventsDBStale.errMsgStale=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u53e4\u3044\u3082\u306e\u3068\u3057\u3066\u30de\u30fc\u30af\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u4e00\u90e8\u306e\u7d50\u679c\u304c\u6700\u65b0\u3067\u306f\u306a\u3044\u304b\u898b\u3064\u304b\u3089\u306a\u3044\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 -TimeLinecontroller.setIngestRunning.errMsgNotRunning=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u304c\u5b9f\u884c\u3057\u3066\u3044\u306a\u3044\u9593\u306b\u3001\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u5165\u529b\u6e08\u307f\u3068\u3057\u3066\u30de\u30fc\u30af\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u4e00\u90e8\u306e\u7d50\u679c\u304c\u6700\u65b0\u3067\u306f\u306a\u3044\u304b\u898b\u3064\u304b\u3089\u306a\u3044\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 TimeLineController.setIngestRunning.errMsgRunning=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u5b9f\u884c\u4e2d\u306b\u3001\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u5165\u529b\u6e08\u307f\u3068\u3057\u3066\u30de\u30fc\u30af\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u4e00\u90e8\u306e\u7d50\u679c\u304c\u6700\u65b0\u3067\u306f\u306a\u3044\u304b\u898b\u3064\u304b\u3089\u306a\u3044\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 -TimeLinecontroller.updateNowQuestion=\u4eca\u3059\u3050\u30a4\u30d9\u30f3\u30c8\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u66f4\u65b0\u3057\u307e\u3059\u304b? -TimelineFrame.title=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3 -TimelinePanel.jButton1.text=6m -TimelinePanel.jButton13.text=\u3059\u3079\u3066 -TimelinePanel.jButton10.text=1h -TimelinePanel.jButton9.text=12h -TimelinePanel.jButton11.text=5y -TimelinePanel.jButton12.text=10y -TimelinePanel.jButton6.text=1w -TimelinePanel.jButton5.text=1y -TimelinePanel.jButton8.text=1d -TimelinePanel.jButton7.text=3d -TimelinePanel.jButton2.text=1m -TimelinePanel.jButton3.text=3m -TimelinePanel.jButton4.text=2w -ProgressWindow.progressHeader.text=\ -# {0} - \u65e5\u4ed8\u7bc4\u56f2\u306e\u958b\u59cb -# {1} - \u65e5\u4ed8\u7bc4\u56f2\u306e\u7d42\u4e86 TimeLineResultView.startDateToEndDate.text={0} ~ {1} TimeLineTopComponent.eventsTab.name=\u30a4\u30d9\u30f3\u30c8 TimeLineTopComponent.filterTab.name=\u30d5\u30a3\u30eb\u30bf\u30fc +TimeLinecontroller.setIngestRunning.errMsgNotRunning=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u304c\u5b9f\u884c\u3057\u3066\u3044\u306a\u3044\u9593\u306b\u3001\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u5165\u529b\u6e08\u307f\u3068\u3057\u3066\u30de\u30fc\u30af\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u4e00\u90e8\u306e\u7d50\u679c\u304c\u6700\u65b0\u3067\u306f\u306a\u3044\u304b\u898b\u3064\u304b\u3089\u306a\u3044\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 +TimeLinecontroller.updateNowQuestion=\u4eca\u3059\u3050\u30a4\u30d9\u30f3\u30c8\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u66f4\u65b0\u3057\u307e\u3059\u304b? +Timeline.dialogs.title=\ \u30bf\u30a4\u30e0\u30e9\u30a4\u30f3 +Timeline.frameName.text={0} - Autopsy\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3 +Timeline.goToButton.text=\u79fb\u52d5\: +Timeline.old.version=\u3053\u306e\u30b1\u30fc\u30b9\u306f\u3001\u53e4\u3044\u30d0\u30fc\u30b8\u30e7\u30f3\u306eAutopsy\u3067\u4f5c\u6210\u3055\u308c\u307e\u3057\u305f\u3002\n\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u306b\u306f\u53e4\u3044\u30d0\u30fc\u30b8\u30e7\u30f3\u306eAutopsy\u3067\u8ffd\u52a0\u3055\u308c\u305f\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u304b\u3089\u306e\u30a4\u30d9\u30f3\u30c8\u306f\u8868\u793a\u3055\u308c\u307e\u305b\u3093 +Timeline.resultPanel.loading=\u8aad\u307f\u8fbc\u307f\u4e2d... +Timeline.resultsPanel.title=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u7d50\u679c +Timeline.runJavaFxThread.progress.creating=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u3092\u4f5c\u6210\u4e2d\u3067\u3059 ... +Timeline.yearBarChart.x.years=\u5e74 +Timeline.zoomOutButton.text=\u30ba\u30fc\u30e0\u30a2\u30a6\u30c8 +TimelineFrame.title=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3 +TimelinePanel.jButton1.text=6m +TimelinePanel.jButton10.text=1h +TimelinePanel.jButton11.text=5y +TimelinePanel.jButton12.text=10y +TimelinePanel.jButton13.text=\u3059\u3079\u3066 +TimelinePanel.jButton2.text=1m +TimelinePanel.jButton3.text=3m +TimelinePanel.jButton4.text=2w +TimelinePanel.jButton5.text=1y +TimelinePanel.jButton6.text=1w +TimelinePanel.jButton7.text=3d +TimelinePanel.jButton8.text=1d +TimelinePanel.jButton9.text=12h TimelineTopComponent.selectedEventListener.errorMsg=\u9078\u629e\u3057\u305f\u30a4\u30d9\u30f3\u30c8\u306e\u30b3\u30f3\u30c6\u30f3\u30c4\u3092\u53d6\u5f97\u4e2d\u306b\u554f\u984c\u304c\u3042\u308a\u307e\u3057\u305f\u3002 diff --git a/Core/src/org/sleuthkit/autopsy/timeline/actions/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/timeline/actions/Bundle_ja.properties index ae83b8c4ac..0ea333e163 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/actions/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/timeline/actions/Bundle_ja.properties @@ -1,8 +1,17 @@ -# {0} - \u30a2\u30af\u30b7\u30e7\u30f3\u30fb\u30a2\u30af\u30bb\u30e9\u30ec\u30fc\u30bf\u30fb\u30ad\u30fc -Back.longText=\u623b\u308b: {0}\n\u524d\u306e\u30d3\u30e5\u30fc\u8a2d\u5b9a\u306b\u623b\u308a\u307e\u3059\u3002 +#Mon Jul 12 13:22:00 UTC 2021 +AddManualEvent.EventCreationDialogPane.dataSourceStringConverter.template={0} (ID\: {1}) +AddManualEvent.EventCreationDialogPane.initialize.dataSourcesError=\u30b1\u30fc\u30b9\u304b\u3089\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u306e\u53d6\u5f97\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +AddManualEvent.createArtifactFailed=\u30a4\u30d9\u30f3\u30c8\u306e\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u306e\u4f5c\u6210\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 +AddManualEvent.longText=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u306b\u30a4\u30d9\u30f3\u30c8\u3092\u624b\u52d5\u3067\u8ffd\u52a0\u3057\u307e\u3059\u3002 +AddManualEvent.postArtifactFailed=\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u3092\u9ed2\u677f\u306b\u6295\u7a3f\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +AddManualEvent.text=\u30a4\u30d9\u30f3\u30c8\u3092\u8ffd\u52a0 +AddManualEvent.validation.datetime=\u65e5\u6642\u304c\u7121\u52b9\u3067\u3059 +AddManualEvent.validation.description=\u8aac\u660e\u304c\u5fc5\u8981\u3067\u3059\u3002 +AddManualEvent.validation.timezone=\u7121\u52b9\u306a\u30bf\u30a4\u30e0\u30be\u30fc\u30f3 +Back.longText=\u623b\u308b\: {0}\n\u524d\u306e\u30d3\u30e5\u30fc\u8a2d\u5b9a\u306b\u623b\u308a\u307e\u3059\u3002 Back.text=\u623b\u308b -# {0} - \u30a2\u30af\u30b7\u30e7\u30f3\u30fb\u30a2\u30af\u30bb\u30e9\u30ec\u30fc\u30bf\u30fb\u30ad\u30fc -Forward.longText=\u9032\u3080: {0}\n\u6b21\u306e\u30d3\u30e5\u30fc\u8a2d\u5b9a\u306b\u9032\u307f\u307e\u3059\u3002 +DataResultFilterNode.action.viewSrcFileInDir.text=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u306b\u30bd\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb\u3092\u8868\u793a... +Forward.longText=\u9032\u3080\: {0}\n\u6b21\u306e\u30d3\u30e5\u30fc\u8a2d\u5b9a\u306b\u9032\u307f\u307e\u3059\u3002 Forward.text=\u9032\u3080 OpenReportAction.DisplayName=\u30ec\u30dd\u30fc\u30c8\u3092\u958b\u304f OpenReportAction.MessageBoxTitle=\u30ec\u30dd\u30fc\u30c8\u30aa\u30fc\u30d7\u30f3\u5931\u6557 @@ -14,26 +23,32 @@ RebuildDataBase.longText=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u66f4\u65b0\ RebuildDataBase.text=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u66f4\u65b0 ResetFilters.text=\u3059\u3079\u3066\u306e\u30d5\u30a3\u30eb\u30bf\u30fc\u3092\u30ea\u30bb\u30c3\u30c8 RestFilters.longText=\u3059\u3079\u3066\u306e\u30d5\u30a3\u30eb\u30bf\u30fc\u3092\u30c7\u30d5\u30a9\u30eb\u30c8\u306e\u72b6\u614b\u306b\u30ea\u30bb\u30c3\u30c8\u3057\u307e\u3059\u3002 +SaveSnapShotAsReport.ErrorWritingReport={0} \u306b\u3042\u308b\u30c7\u30a3\u30b9\u30af\u306b\u30ec\u30dd\u30fc\u30c8\u3092\u66f8\u8fbc\u307f\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +SaveSnapShotAsReport.FailedToAddReport=\u30b9\u30ca\u30c3\u30d7\u30b7\u30e7\u30c3\u30c8\u3092\u30b1\u30fc\u30b9\u3068\u3057\u3066\u8ffd\u52a0\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +SaveSnapShotAsReport.ReportSavedAt=[{0}] \u306b\u30ec\u30dd\u30fc\u30c8\u304c\u4fdd\u5b58\u3055\u308c\u307e\u3057\u305f +SaveSnapShotAsReport.Success=\u6210\u529f SaveSnapShotAsReport.action.dialogs.title=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3 SaveSnapShotAsReport.action.longText=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u306e\u73fe\u5728\u306e\u30d3\u30e5\u30fc\u306e\u30b9\u30af\u30ea\u30fc\u30f3\u30ad\u30e3\u30d7\u30c1\u30e3\u30fc\u3092\u30ec\u30dd\u30fc\u30c8\u3068\u3057\u3066\u4fdd\u5b58\u3057\u307e\u3059\u3002 SaveSnapShotAsReport.action.name.text=\u30b9\u30ca\u30c3\u30d7\u30b7\u30e7\u30c3\u30c8\u30fb\u30ec\u30dd\u30fc\u30c8 SaveSnapShotAsReport.duplicateReportNameError.text=\u305d\u306e\u540d\u524d\u306e\u30ec\u30dd\u30fc\u30c8\u306f\u3059\u3067\u306b\u5b58\u5728\u3057\u307e\u3059\u3002 -# {0} - \u30ec\u30dd\u30fc\u30c8\u30d1\u30b9 -SaveSnapShotAsReport.ErrorWritingReport={0} \u306b\u3042\u308b\u30c7\u30a3\u30b9\u30af\u306b\u30ec\u30dd\u30fc\u30c8\u3092\u66f8\u8fbc\u307f\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 -SaveSnapShotAsReport.FailedToAddReport=\u30b9\u30ca\u30c3\u30d7\u30b7\u30e7\u30c3\u30c8\u3092\u30b1\u30fc\u30b9\u3068\u3057\u3066\u8ffd\u52a0\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 SaveSnapShotAsReport.reportName.header=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u306e\u30b9\u30ca\u30c3\u30d7\u30b7\u30e7\u30c3\u30c8\u30fb\u30ec\u30dd\u30fc\u30c8\u306e\u30ec\u30dd\u30fc\u30c8\u540d\u3092\u5165\u529b\u3057\u307e\u3059\u3002 -# {0} - \u751f\u6210\u3055\u308c\u305f\u30c7\u30d5\u30a9\u30eb\u30c8\u30ec\u30dd\u30fc\u30c8\u540d -SaveSnapShotAsReport.reportName.prompt=\u6b21\u306e\u30c7\u30d5\u30a9\u30eb\u30c8\u30ec\u30dd\u30fc\u30c8\u540d\u3092\u7a7a(\u672a\u5165\u529b)\u306e\u307e\u307e\u306b\u3059\u308b: {0}\u3002 -# {0} - \u30ec\u30dd\u30fc\u30c8\u30d5\u30a1\u30a4\u30eb\u30d1\u30b9 -SaveSnapShotAsReport.ReportSavedAt=[{0}] \u306b\u30ec\u30dd\u30fc\u30c8\u304c\u4fdd\u5b58\u3055\u308c\u307e\u3057\u305f -SaveSnapShotAsReport.Success=\u6210\u529f +SaveSnapShotAsReport.reportName.prompt=\u6b21\u306e\u30c7\u30d5\u30a9\u30eb\u30c8\u30ec\u30dd\u30fc\u30c8\u540d\u3092\u7a7a(\u672a\u5165\u529b)\u306e\u307e\u307e\u306b\u3059\u308b\: {0}\u3002 +SaveSnapShotAsReport_OK_Button=OK +SaveSnapShotAsReport_Open_Button=\u30ec\u30dd\u30fc\u30c8\u3092\u958b\u304f +SaveSnapShotAsReport_Path_Failure_Report=\u30ec\u30dd\u30fc\u30c8\u306e\u4f5c\u6210\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 \u63d0\u4f9b\u3055\u308c\u305f\u30ec\u30dd\u30fc\u30c8\u540d\u306b\u7121\u52b9\u306a\u6587\u5b57\u304c\u542b\u307e\u308c\u3066\u3044\u307e\u3059\uff1a{0} +SaveSnapShotAsReport_Report_Failed=\u30ec\u30dd\u30fc\u30c8\u306b\u5931\u6557\u3057\u307e\u3057\u305f +SaveSnapShotAsReport_success_message=\u30b9\u30ca\u30c3\u30d7\u30b7\u30e7\u30c3\u30c8\u30ec\u30dd\u30fc\u30c8\u304c\u6b21\u306e\u5834\u6240\u3067\u6b63\u5e38\u306b\u4f5c\u6210\u3055\u308c\u307e\u3057\u305f\uff1a\n {0} Timeline.ModuleName=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3 ViewArtifactInTimelineAction.displayName=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u306b\u7d50\u679c\u3092\u8868\u793a... ViewFileInTimelineAction.viewFile.displayName=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u306b\u30d5\u30a1\u30a4\u30eb\u3092\u8868\u793a... -DataResultFilterNode.action.viewSrcFileInDir.text=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u306b\u30bd\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb\u3092\u8868\u793a... +ViewFileInTimelineAction.viewSourceFile.displayName=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u3067\u30bd\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb\u3092\u8868\u793a... ZoomIn.action.text=\u30ba\u30fc\u30e0\u30a4\u30f3 +ZoomIn.errorMessage=\u30ba\u30fc\u30e0\u30a4\u30f3\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 ZoomIn.longText=\u30ba\u30fc\u30e0\u30a4\u30f3\u3057\u3066\u7d04\u534a\u5206\u306e\u6642\u9593\u3092\u8868\u793a\u3057\u307e\u3059\u3002 ZoomOut.action.text=\u30ba\u30fc\u30e0\u30a2\u30a6\u30c8 +ZoomOut.disabledProperty.errorMessage=\u30b9\u30d1\u30f3\u9593\u9694\u306e\u53d6\u5f97\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +ZoomOut.errorMessage=\u30ba\u30fc\u30e0\u30a2\u30a6\u30c8\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 ZoomOut.longText=\u30ba\u30fc\u30e0\u30a2\u30a6\u30c8\u3057\u3066\u7d0450%\u4ee5\u4e0a\u306e\u6642\u9593\u3092\u8868\u793a\u3057\u307e\u3059\u3002 ZoomToEvents.action.text=\u30a4\u30d9\u30f3\u30c8\u306b\u30ba\u30fc\u30e0 +ZoomToEvents.disabledProperty.errorMessage=\u30b9\u30d1\u30f3\u9593\u9694\u306e\u53d6\u5f97\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 ZoomToEvents.longText=\u30ba\u30fc\u30e0\u30a2\u30a6\u30c8\u3057\u3066\u6700\u3082\u6700\u8fd1\u306e\u30a4\u30d9\u30f3\u30c8\u3092\u8868\u793a\u3057\u307e\u3059\u3002 diff --git a/Core/src/org/sleuthkit/autopsy/timeline/explorernodes/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/timeline/explorernodes/Bundle_ja.properties index 8e1199be05..8eab050ecf 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/explorernodes/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/timeline/explorernodes/Bundle_ja.properties @@ -1,11 +1,11 @@ +#Mon Jul 12 13:22:00 UTC 2021 EventNode.getAction.errorTitle=\u30a2\u30af\u30b7\u30e7\u30f3\u306e\u53d6\u5f97\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f EventNode.getAction.linkedFileMessage=\u9078\u629e\u3057\u305f\u7d50\u679c\u306e\u30a2\u30af\u30b7\u30e7\u30f3\u3092\u53d6\u5f97\u4e2d\u306b\u554f\u984c\u304c\u3042\u308a\u307e\u3057\u305f\u3002 [\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u306b\u30d5\u30a1\u30a4\u30eb\u3092\u8868\u793a] \u30a2\u30af\u30b7\u30e7\u30f3\u3092\u5229\u7528\u3067\u304d\u307e\u305b\u3093\u3002 -# {0} - \u8868\u793a\u53ef\u80fd\u306a\u6700\u5927\u30a4\u30d9\u30f3\u30c8\u6570 -# {1} - \u591a\u3059\u304e\u308b\u30a4\u30d9\u30f3\u30c8\u6570 -EventRoodNode.tooManyNode.displayName=\u30a4\u30d9\u30f3\u30c8\u304c\u591a\u3059\u304e\u3066\u8868\u793a\u3067\u304d\u307e\u305b\u3093\u3002 \u6700\u5927 = {0} \u3067\u3059\u3002\u305f\u3060\u3057\u3001{1} \u3092\u8868\u793a\u3067\u304d\u307e\u3059\u3002 +EventRoodNode.tooManyNode.displayName=\u30a4\u30d9\u30f3\u30c8\u304c\u591a\u3059\u304e\u3066\u8868\u793a\u3067\u304d\u307e\u305b\u3093\u3002 \u6700\u5927 \= {0} \u3067\u3059\u3002\u305f\u3060\u3057\u3001{1} \u3092\u8868\u793a\u3067\u304d\u307e\u3059\u3002 NodeProperty.displayName.baseType=\u57fa\u672c\u30bf\u30a4\u30d7 NodeProperty.displayName.dateTime=\u65e5/\u6642\u9593 NodeProperty.displayName.description=\u8a18\u8ff0 +NodeProperty.displayName.eventType=\u30a4\u30d9\u30f3\u30c8\u30bf\u30a4\u30d7 NodeProperty.displayName.icon=\u30a2\u30a4\u30b3\u30f3 NodeProperty.displayName.known=\u65e2\u77e5 NodeProperty.displayName.subType=\u30b5\u30d6\u30bf\u30a4\u30d7 diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/timeline/ui/Bundle_ja.properties index 2be73fcb0d..2c011c2a25 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/Bundle_ja.properties @@ -1,72 +1,61 @@ -/* - * Autopsy\u30d5\u30a9\u30ec\u30f3\u30b8\u30c3\u30af\u30fb\u30d6\u30e9\u30a6\u30b6\u30fc - * - * Copyright 2013-15 Basis Technology Corp. - * \u9023\u7d61\u5148: carrier sleuthkit org - * - * Apache License, Version 2.0 (\u4ee5\u4e0b\u300c\u30e9\u30a4\u30bb\u30f3\u30b9\u300d\u3068\u3044\u3044\u307e\u3059)\u306b\u304a\u3044\u3066\u4f7f\u7528\u8a31\u8afe\u3055\u308c\u3066\u3044\u307e\u3059\u3002 - * \u672c\u30e9\u30a4\u30bb\u30f3\u30b9\u3092\u9075\u5b88\u3059\u308b\u3053\u3068\u306a\u304f\u3057\u3066\u3001\u3053\u306e\u30d5\u30a1\u30a4\u30eb\u3092\u4f7f\u7528\u3067\u304d\u307e\u305b\u3093\u3002 - * \u672c\u30e9\u30a4\u30bb\u30f3\u30b9\u306e\u30b3\u30d4\u30fc\u306f\u6b21\u306e\u30b5\u30a4\u30c8\u3067\u53d6\u5f97\u3067\u304d\u307e\u3059\u3002 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * \u9069\u7528\u6cd5\u4ee4\u306b\u3088\u3063\u3066\u7fa9\u52d9\u4ed8\u3051\u3089\u308c\u308b\u5834\u5408\u307e\u305f\u306f\u66f8\u9762\u306b\u3066\u5408\u610f\u3055\u308c\u3066\u3044\u308b\u5834\u5408\u3092\u9664\u304d\u3001\u30bd\u30d5\u30c8\u30a6\u30a7\u30a2\u306f - * \u660e\u793a\u7684\u3067\u3042\u308c\u9ed9\u793a\u7684\u3067\u3042\u308c\u3001\u3044\u304b\u306a\u308b\u985e\u306e\u4fdd\u8a3c\u307e\u305f\u306f\u6761\u4ef6\u306a\u3057\u306b\u3001 - * \u672c\u30e9\u30a4\u30bb\u30f3\u30b9\u306b\u304a\u3044\u3066\u300c\u73fe\u72b6\u300d\u306e\u307e\u307e\u3067\u914d\u5e03\u3055\u308c\u307e\u3059\u3002 - * \u672c\u30e9\u30a4\u30bb\u30f3\u30b9\u306b\u304a\u3051\u308b\u30a2\u30af\u30bb\u30b9\u6a29\u304a\u3088\u3073\u5236\u9650\u4e8b\u9805\u3092\u898f\u5b9a\u3059\u308b - * \u7279\u5b9a\u306e\u8a00\u8a9e\u306b\u3064\u3044\u3066\u306f\u3001\u300c\u30e9\u30a4\u30bb\u30f3\u30b9\u300d\u3092\u53c2\u7167\u3057\u3066\u304f\u3060\u3055\u3044\u3002 - */ - +#Mon Jul 12 13:22:00 UTC 2021 +*=\u7279\u5b9a\u306e\u8a00\u8a9e\u306b\u3064\u3044\u3066\u306f\u3001\u300c\u30e9\u30a4\u30bb\u30f3\u30b9\u300d\u3092\u53c2\u7167\u3057\u3066\u304f\u3060\u3055\u3044\u3002 +*/= +/*= AbstractTimelineChart.defaultTooltip.text=\u30de\u30a6\u30b9\u3092\u30c9\u30e9\u30c3\u30b0\u3057\u3001\u30ba\u30fc\u30e0\u30a4\u30f3\u3059\u308b\u6642\u9593\u9593\u9694\u3092\u9078\u629e\u3057\u307e\u3059\u3002\n\u53f3\u30af\u30ea\u30c3\u30af\u3057\u3001\u3055\u3089\u306a\u308b\u30a2\u30af\u30b7\u30e7\u30f3\u3092\u8868\u793a\u3057\u307e\u3059\u3002 HistoryToolBar.historyLabel.text=\u5c65\u6b74 IntervalSelector.ClearSelectedIntervalAction.tooltTipText=\u9078\u629e\u3057\u305f\u9593\u9694\u3092\u6d88\u53bb IntervalSelector.ZoomAction.name=\u30ba\u30fc\u30e0 +IntervalSelector.zoomToSelectedInterval.errorMessage=\u9078\u629e\u3057\u305f\u9593\u9694\u306b\u30ba\u30fc\u30e0\u30a4\u30f3\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 NoEventsDialog.titledPane.text=\u8868\u793a\u53ef\u80fd\u306a\u30a4\u30d9\u30f3\u30c8\u306f\u3042\u308a\u307e\u305b\u3093 -Timeline.node.root=\u30eb\u30fc\u30c8 -# {0} - \u958b\u59cb\u30bf\u30a4\u30e0\u30b9\u30bf\u30f3\u30d7 -# {1} - \u7d42\u4e86\u30bf\u30a4\u30e0\u30b9\u30bf\u30f3\u30d7 -Timeline.ui.TimeLineChart.tooltip.text=\u30c0\u30d6\u30eb\u30af\u30ea\u30c3\u30af\u3057\u3066\u7bc4\u56f2\u306b\u30ba\u30fc\u30e0\u30a4\u30f3:\n{0} to {1}.\n\n\u53f3\u30af\u30ea\u30c3\u30af\u3057\u3066\u9589\u3058\u307e\u3059\u3002 -Timeline.ui.ZoomRanges.onemin.text=1\u5206 -Timeline.ui.ZoomRanges.fifteenmin.text=15\u5206 -Timeline.ui.ZoomRanges.onehour.text=1\u6642\u9593 -Timeline.ui.ZoomRanges.sixhours.text=6\u6642\u9593 -Timeline.ui.ZoomRanges.twelvehours.text=12\u6642\u9593 -Timeline.ui.ZoomRanges.oneday.text=1\u65e5 -Timeline.ui.ZoomRanges.threedays.text=3\u65e5 -Timeline.ui.ZoomRanges.oneweek.text=1\u9031\u9593 -Timeline.ui.ZoomRanges.twoweeks.text=2\u9031\u9593 -Timeline.ui.ZoomRanges.onemonth.text=1\u30f5\u6708 -Timeline.ui.ZoomRanges.threemonths.text=3\u30f5\u6708 -Timeline.ui.ZoomRanges.sixmonths.text=6\u30f5\u6708 -Timeline.ui.ZoomRanges.oneyear.text=1\u5e74 -Timeline.ui.ZoomRanges.threeyears.text=3\u5e74 -Timeline.ui.ZoomRanges.fiveyears.text=5\u5e74 -Timeline.ui.ZoomRanges.tenyears.text=10\u5e74 -Timeline.ui.ZoomRanges.all.text=\u3059\u3079\u3066 TimeLineChart.zoomHistoryActionGroup.name=\u30ba\u30fc\u30e0\u5c65\u6b74 -TimeZonePanel.title=\u6b21\u306b\u6642\u9593\u3092\u8868\u793a: +TimeZonePanel.localRadio.text=\u30ed\u30fc\u30ab\u30eb\u30bf\u30a4\u30e0\u30be\u30fc\u30f3 +TimeZonePanel.otherRadio.text=GMT / UTC +TimeZonePanel.title=\u6b21\u306b\u6642\u9593\u3092\u8868\u793a\: +Timeline.node.root=\u30eb\u30fc\u30c8 +Timeline.ui.TimeLineChart.tooltip.text=\u30c0\u30d6\u30eb\u30af\u30ea\u30c3\u30af\u3057\u3066\u7bc4\u56f2\u306b\u30ba\u30fc\u30e0\u30a4\u30f3\:\n{0} to {1}.\n\n\u53f3\u30af\u30ea\u30c3\u30af\u3057\u3066\u9589\u3058\u307e\u3059\u3002 +Timeline.ui.ZoomRanges.all.text=\u3059\u3079\u3066 +Timeline.ui.ZoomRanges.fifteenmin.text=15\u5206 +Timeline.ui.ZoomRanges.fiveyears.text=5\u5e74 +Timeline.ui.ZoomRanges.oneday.text=1\u65e5 +Timeline.ui.ZoomRanges.onehour.text=1\u6642\u9593 +Timeline.ui.ZoomRanges.onemin.text=1\u5206 +Timeline.ui.ZoomRanges.onemonth.text=1\u30f5\u6708 +Timeline.ui.ZoomRanges.oneweek.text=1\u9031\u9593 +Timeline.ui.ZoomRanges.oneyear.text=1\u5e74 +Timeline.ui.ZoomRanges.sixhours.text=6\u6642\u9593 +Timeline.ui.ZoomRanges.sixmonths.text=6\u30f5\u6708 +Timeline.ui.ZoomRanges.tenyears.text=10\u5e74 +Timeline.ui.ZoomRanges.threedays.text=3\u65e5 +Timeline.ui.ZoomRanges.threemonths.text=3\u30f5\u6708 +Timeline.ui.ZoomRanges.threeyears.text=3\u5e74 +Timeline.ui.ZoomRanges.twelvehours.text=12\u6642\u9593 +Timeline.ui.ZoomRanges.twoweeks.text=2\u9031\u9593 ViewFrame.countsToggle.text=\u30ab\u30a6\u30f3\u30c8 +ViewFrame.dateTimeValidator.errorMessage=\u30b9\u30d1\u30f3\u9593\u9694\u306e\u53d6\u5f97\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 ViewFrame.detailsToggle.text=\u8a73\u7d30 -ViewFrame.endLabel.text=\u7d42\u4e86: +ViewFrame.endLabel.text=\u7d42\u4e86\: ViewFrame.histogramTask.preparing=\u6e96\u5099\u4e2d ViewFrame.histogramTask.queryDb=FB\u3092\u30af\u30a8\u30ea\u4e2d\u3067\u3059 ViewFrame.histogramTask.resetUI=UI\u3092\u30ea\u30bb\u30c3\u30c8\u4e2d\u3067\u3059 ViewFrame.histogramTask.title=\u30d2\u30b9\u30c8\u30b0\u30e9\u30e0\u306e\u518d\u69cb\u7bc9\u4e2d\u3067\u3059 ViewFrame.histogramTask.updateUI2=UI\u3092\u66f4\u65b0\u4e2d\u3067\u3059 ViewFrame.listToggle.text=\u30ea\u30b9\u30c8 +ViewFrame.localDateDisabler.errorMessage=\u30b9\u30d1\u30f3\u9593\u9694\u306e\u53d6\u5f97\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 ViewFrame.noEventsDialogLabel.text=\u73fe\u5728\u306e\u30ba\u30fc\u30e0 / \u30d5\u30a3\u30eb\u30bf\u30fc\u8a2d\u5b9a\u3067\u8868\u793a\u53ef\u80fd\u306a\u30a4\u30d9\u30f3\u30c8\u306f\u3042\u308a\u307e\u305b\u3093\u3002 -# {0} - \u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u540d ViewFrame.notification.analysisComplete={0} \u306e\u5206\u6790\u306f\u5b8c\u4e86\u3057\u307e\u3057\u305f\u3002 \u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u306e\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304c\u6700\u65b0\u3067\u306f\u306a\u3044\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 -# {0} - \u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u540d +ViewFrame.notification.cacheInvalidated=\u30a4\u30d9\u30f3\u30c8\u30c7\u30fc\u30bf\u304c\u66f4\u65b0\u3055\u308c\u307e\u3057\u305f\u3002\u8868\u793a\u304c\u53e4\u304f\u306a\u3063\u3066\u3044\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 ViewFrame.notification.newDataSource={0} \u304c\u65b0\u3057\u3044\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3068\u3057\u3066\u8ffd\u52a0\u3055\u308c\u307e\u3057\u305f\u3002 \u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u306e\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304c\u6700\u65b0\u3067\u306f\u306a\u3044\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 +ViewFrame.pickerListener.errorMessage=\u65e5\u4ed8/\u6642\u523b\u30d4\u30c3\u30ab\u30fc\u306e\u5909\u66f4\u3078\u306e\u5fdc\u7b54\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +ViewFrame.rangeSliderListener.errorMessage=\u30ec\u30f3\u30b8\u30fb\u30b9\u30e9\u30a4\u30c0\u30fc\u3078\u306e\u5fdc\u7b54\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 ViewFrame.refresh.longText=\u30d3\u30e5\u30fc\u3092\u66f4\u65b0\u3057\u3001\u65b0\u305f\u306b\u66f4\u65b0\u3055\u308c\u305f\u30bf\u30b0\u306a\u3069\u3001\u8868\u793a\u3055\u308c\u3066\u3044\u306a\u3044\u3082\u306e\u306e\u3001\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u5185\u306b\u3042\u308b\u60c5\u5831\u3092\u542b\u3081\u307e\u3059\u3002 ViewFrame.refresh.text=\u30d3\u30e5\u30fc\u3092\u66f4\u65b0 -ViewFrame.startLabel.text=\u958b\u59cb: -ViewFrame.tagsAddedOrDeleted=\u30bf\u30b0\u304c\u4f5c\u6210\u304a\u3088\u3073/\u307e\u305f\u306f\u524a\u9664\u3055\u308c\u307e\u3057\u305f\u3002 \u30d3\u30e5\u30fc\u304c\u6700\u65b0\u3067\u306f\u306a\u3044\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 -ViewFrame.viewModeLabel.text=\u30d3\u30e5\u30fc\u30e2\u30fc\u30c9: -ViewFrame.zoomButton.text=\u30a4\u30d9\u30f3\u30c8\u306b\u30ba\u30fc\u30e0 -TimeZonePanel.localRadio.text=\u30ed\u30fc\u30ab\u30eb\u30bf\u30a4\u30e0\u30be\u30fc\u30f3 -TimeZonePanel.otherRadio.text=GMT / UTC +ViewFrame.refreshTimeUI.errorMessage=\u30b9\u30d1\u30f3\u9593\u9694\u306e\u53d6\u5f97\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 ViewFrame.resetFiltersButton.text=\u3059\u3079\u3066\u306e\u30d5\u30a3\u30eb\u30bf\u30fc\u3092\u30ea\u30bb\u30c3\u30c8 +ViewFrame.startLabel.text=\u958b\u59cb\: +ViewFrame.tagsAddedOrDeleted=\u30bf\u30b0\u304c\u4f5c\u6210\u304a\u3088\u3073/\u307e\u305f\u306f\u524a\u9664\u3055\u308c\u307e\u3057\u305f\u3002 \u30d3\u30e5\u30fc\u304c\u6700\u65b0\u3067\u306f\u306a\u3044\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 +ViewFrame.viewModeLabel.text=\u30d3\u30e5\u30fc\u30e2\u30fc\u30c9\: +ViewFrame.zoomButton.text=\u30a4\u30d9\u30f3\u30c8\u306b\u30ba\u30fc\u30e0 +ViewFrame.zoomMenuButton.errorMessage=\u6642\u9593\u7bc4\u56f2\u306e\u30d7\u30c3\u30b7\u30e5\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 ViewFrame.zoomMenuButton.text=\u30ba\u30fc\u30e0\u30a4\u30f3/\u30a2\u30a6\u30c8 ViewRefreshTask.preparing=\u30ba\u30fc\u30e0\u8a2d\u5b9a\u3068\u30d5\u30a3\u30eb\u30bf\u30fc\u8a2d\u5b9a\u3092\u5206\u6790\u4e2d\u3067\u3059 diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/countsview/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/timeline/ui/countsview/Bundle_ja.properties index 138bb42bfe..578c5c3fce 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/countsview/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/countsview/Bundle_ja.properties @@ -1,25 +1,27 @@ +#Mon Jul 12 13:22:00 UTC 2021 +BarClickHandler.selectTimeAndType.errorMessage=\u6642\u9593\u3068\u30bf\u30a4\u30d7\u306e\u9078\u629e\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +BarClickHandler_zoomIn_errorMessage=\u30ba\u30fc\u30e0\u30a4\u30f3\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 CountsViewPane.detailSwitchMessage=\u79d2\u3088\u308a\u3082\u5c0f\u3055\u3044\u6642\u9593\u5206\u89e3\u80fd\u306f\u3042\u308a\u307e\u305b\u3093\u3002\n\u4ee3\u308f\u308a\u306b\u8a73\u7d30\u30d3\u30e5\u30fc\u306b\u5207\u308a\u66ff\u3048\u307e\u3059\u304b? CountsViewPane.detailSwitchTitle=\u8a73\u7d30\u30d3\u30e5\u30fc\u306b\u5207\u308a\u66ff\u3048\u307e\u3059\u304b? CountsViewPane.linearRadio.text=\u7dda\u5f62 +CountsViewPane.logRadio.text=\u5bfe\u6570 CountsViewPane.loggedTask.name=\u30ab\u30a6\u30f3\u30c8\u30d3\u30e5\u30fc\u306e\u66f4\u65b0\u4e2d\u3067\u3059 CountsViewPane.loggedTask.updatingCounts=\u30d3\u30e5\u30fc\u306e\u5165\u529b\u4e2d\u3067\u3059 -CountsViewPane.logRadio.text=\u5bfe\u6570 -# {0} - \u76ee\u76db\u540d CountsViewPane.numberOfEvents=\u30a4\u30d9\u30f3\u30c8\u6570 ({0}) -CountsViewPane.scaleHelp.label.text=\u76ee\u76db: -CountsViewPane.scaleHelpLinear=\u7dda\u5f62\u76ee\u76db\u306f\u591a\u304f\u306e\u4f7f\u7528\u4e8b\u4f8b\u306b\u9069\u3057\u3066\u3044\u307e\u3059\u3002 \u3053\u306e\u76ee\u76db\u3092\u9078\u629e\u3059\u308b\u3068\u3001\u30d0\u30fc\u306e\u9ad8\u3055\u304c1\u5bfe1\u306e\u7dda\u5f62\u3067\u30ab\u30a6\u30f3\u30c8\u3092\u8868\u3057\u3001y\u8ef8\u306b\u5024\u30e9\u30d9\u30eb\u304c\u4ed8\u304d\u307e\u3059\u3002\u5024\u306e\u7bc4\u56f2\u304c\u975e\u5e38\u306b\u5927\u304d\u3044\u3068\u3001\u30ab\u30a6\u30f3\u30c8\u306e\u5c11\u306a\u3044\u6642\u9593\u5468\u671f\u306b\u5c0f\u3055\u3059\u304e\u3066\u8868\u793a\u3067\u304d\u306a\u3044\u30d0\u30fc\u304c\u3042\u308b\u3053\u3068\u304c\u3042\u308a\u307e\u3059\u3002 \u30e6\u30fc\u30b6\u30fc\u304c\u3053\u308c\u3092\u5224\u5225\u3067\u304d\u308b\u3088\u3046\u306b\u3001\u30a4\u30d9\u30f3\u30c8\u306e\u3042\u308b\u30c7\u30fc\u30bf\u7bc4\u56f2\u306e\u30e9\u30d9\u30eb\u304c\u592a\u5b57\u3067\u8868\u793a\u3055\u308c\u307e\u3059\u3002 \u5c0f\u3055\u3059\u304e\u308b\u30d0\u30fc\u3092\u8868\u793a\u3059\u308b\u9078\u629e\u80a2\u306f\u6b21\u306e3\u3064\u3067\u3059: \u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u306e\u7e26\u9818\u57df\u3092\u5e83\u3052\u308b\u305f\u3081\u306b\u30a6\u30a3\u30f3\u30c9\u30a6\u30b5\u30a4\u30ba\u3092\u8abf\u6574\u3001\u3088\u308a\u5927\u304d\u3044\u30d0\u30fc\u306e\u3042\u308b\u6642\u9593\u5468\u671f\u304c\u9664\u5916\u3055\u308c\u308b\u3088\u3046\u6642\u9593\u7bc4\u56f2\u3092\u8abf\u6574\u3001\u3082\u3057\u304f\u306f\u76ee\u76db\u8a2d\u5b9a\u3092\u5bfe\u6570\u306b\u8abf\u6574 -CountsViewPane.scaleHelpLog=\u5bfe\u6570\u76ee\u76db\u306f\u3001\u5927\u304d\u3044\u6570\u5b57\u3068\u5c0f\u3055\u3044\u6570\u5b57\u306e\u5dee\u3092\u5727\u7e2e\u3059\u308b\u975e\u7dda\u5f62\u306a\u65b9\u6cd5\u3067\u30a4\u30d9\u30f3\u30c8\u6570\u3092\u8868\u3057\u307e\u3059\u3002\u5bfe\u6570\u76ee\u76db\u3092\u7528\u3044\u3066\u3082\u3001\u6975\u7aef\u306b\u5927\u304d\u3044\u30ab\u30a6\u30f3\u30c8\u5dee\u306b\u3088\u3063\u3066\u5c0f\u3055\u3059\u304e\u3066\u8868\u793a\u3067\u304d\u306a\u3044\u30d0\u30fc\u304c\u751f\u6210\u3055\u308c\u308b\u3053\u3068\u304c\u3042\u308a\u307e\u3059\u3002 \u3053\u306e\u5834\u5408\u3001\u30a4\u30d9\u30f3\u30c8\u3092\u30d5\u30a3\u30eb\u30bf\u30fc\u3057\u3066\u30ab\u30a6\u30f3\u30c8\u5dee\u3092\u7e2e\u3081\u308b\u3053\u3068\u304c\u552f\u4e00\u306e\u9078\u629e\u80a2\u3067\u3042\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 \u6ce8: \u5bfe\u6570\u76ee\u76db\u306f\u30a4\u30d9\u30f3\u30c8\u30bf\u30a4\u30d7\u3054\u3068\u306b\u500b\u5225\u306b\u9069\u7528\u3055\u308c\u308b\u305f\u3081\u3001\u8907\u5408\u30d0\u30fc\u306e\u9ad8\u3055\u306e\u610f\u5473\u306f\u76f4\u611f\u7684\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002\u307e\u305f\u3001\u3053\u308c\u3092\u5f37\u8abf\u3059\u308b\u305f\u3081\u306b\u3001\u5bfe\u6570\u76ee\u76db\u3092\u7528\u3044\u305fy\u8ef8\u4e0a\u306b\u30e9\u30d9\u30eb\u3092\u8868\u793a\u3057\u307e\u305b\u3093\u3002\u5bfe\u6570\u76ee\u76db\u306f\u30011\u3064\u306e\u30bf\u30a4\u30d7\u5185\u306e\u6642\u9593\u5168\u57df\u3001\u307e\u305f\u306f1\u3064\u306e\u6642\u9593\u5468\u671f\u306e\u30bf\u30a4\u30d7\u5168\u57df\u3067 +CountsViewPane.scaleHelp.label.text=\u76ee\u76db\: +CountsViewPane.scaleHelpLinear=\u7dda\u5f62\u76ee\u76db\u306f\u591a\u304f\u306e\u4f7f\u7528\u4e8b\u4f8b\u306b\u9069\u3057\u3066\u3044\u307e\u3059\u3002 \u3053\u306e\u76ee\u76db\u3092\u9078\u629e\u3059\u308b\u3068\u3001\u30d0\u30fc\u306e\u9ad8\u3055\u304c1\u5bfe1\u306e\u7dda\u5f62\u3067\u30ab\u30a6\u30f3\u30c8\u3092\u8868\u3057\u3001y\u8ef8\u306b\u5024\u30e9\u30d9\u30eb\u304c\u4ed8\u304d\u307e\u3059\u3002\u5024\u306e\u7bc4\u56f2\u304c\u975e\u5e38\u306b\u5927\u304d\u3044\u3068\u3001\u30ab\u30a6\u30f3\u30c8\u306e\u5c11\u306a\u3044\u6642\u9593\u5468\u671f\u306b\u5c0f\u3055\u3059\u304e\u3066\u8868\u793a\u3067\u304d\u306a\u3044\u30d0\u30fc\u304c\u3042\u308b\u3053\u3068\u304c\u3042\u308a\u307e\u3059\u3002 \u30e6\u30fc\u30b6\u30fc\u304c\u3053\u308c\u3092\u5224\u5225\u3067\u304d\u308b\u3088\u3046\u306b\u3001\u30a4\u30d9\u30f3\u30c8\u306e\u3042\u308b\u30c7\u30fc\u30bf\u7bc4\u56f2\u306e\u30e9\u30d9\u30eb\u304c\u592a\u5b57\u3067\u8868\u793a\u3055\u308c\u307e\u3059\u3002 \u5c0f\u3055\u3059\u304e\u308b\u30d0\u30fc\u3092\u8868\u793a\u3059\u308b\u9078\u629e\u80a2\u306f\u6b21\u306e3\u3064\u3067\u3059\: \u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u306e\u7e26\u9818\u57df\u3092\u5e83\u3052\u308b\u305f\u3081\u306b\u30a6\u30a3\u30f3\u30c9\u30a6\u30b5\u30a4\u30ba\u3092\u8abf\u6574\u3001\u3088\u308a\u5927\u304d\u3044\u30d0\u30fc\u306e\u3042\u308b\u6642\u9593\u5468\u671f\u304c\u9664\u5916\u3055\u308c\u308b\u3088\u3046\u6642\u9593\u7bc4\u56f2\u3092\u8abf\u6574\u3001\u3082\u3057\u304f\u306f\u76ee\u76db\u8a2d\u5b9a\u3092\u5bfe\u6570\u306b\u8abf\u6574 +CountsViewPane.scaleHelpLog=\u5bfe\u6570\u76ee\u76db\u306f\u3001\u5927\u304d\u3044\u6570\u5b57\u3068\u5c0f\u3055\u3044\u6570\u5b57\u306e\u5dee\u3092\u5727\u7e2e\u3059\u308b\u975e\u7dda\u5f62\u306a\u65b9\u6cd5\u3067\u30a4\u30d9\u30f3\u30c8\u6570\u3092\u8868\u3057\u307e\u3059\u3002\u5bfe\u6570\u76ee\u76db\u3092\u7528\u3044\u3066\u3082\u3001\u6975\u7aef\u306b\u5927\u304d\u3044\u30ab\u30a6\u30f3\u30c8\u5dee\u306b\u3088\u3063\u3066\u5c0f\u3055\u3059\u304e\u3066\u8868\u793a\u3067\u304d\u306a\u3044\u30d0\u30fc\u304c\u751f\u6210\u3055\u308c\u308b\u3053\u3068\u304c\u3042\u308a\u307e\u3059\u3002 \u3053\u306e\u5834\u5408\u3001\u30a4\u30d9\u30f3\u30c8\u3092\u30d5\u30a3\u30eb\u30bf\u30fc\u3057\u3066\u30ab\u30a6\u30f3\u30c8\u5dee\u3092\u7e2e\u3081\u308b\u3053\u3068\u304c\u552f\u4e00\u306e\u9078\u629e\u80a2\u3067\u3042\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 \u6ce8\: \u5bfe\u6570\u76ee\u76db\u306f\u30a4\u30d9\u30f3\u30c8\u30bf\u30a4\u30d7\u3054\u3068\u306b\u500b\u5225\u306b\u9069\u7528\u3055\u308c\u308b\u305f\u3081\u3001\u8907\u5408\u30d0\u30fc\u306e\u9ad8\u3055\u306e\u610f\u5473\u306f\u76f4\u611f\u7684\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002\u307e\u305f\u3001\u3053\u308c\u3092\u5f37\u8abf\u3059\u308b\u305f\u3081\u306b\u3001\u5bfe\u6570\u76ee\u76db\u3092\u7528\u3044\u305fy\u8ef8\u4e0a\u306b\u30e9\u30d9\u30eb\u3092\u8868\u793a\u3057\u307e\u305b\u3093\u3002\u5bfe\u6570\u76ee\u76db\u306f\u30011\u3064\u306e\u30bf\u30a4\u30d7\u5185\u306e\u6642\u9593\u5168\u57df\u3001\u307e\u305f\u306f1\u3064\u306e\u6642\u9593\u5468\u671f\u306e\u30bf\u30a4\u30d7\u5168\u57df\u3067 CountsViewPane.scaleHelpLog2=\u30ab\u30a6\u30f3\u30c8\u3092\u8fc5\u901f\u306b\u6bd4\u8f03\u3059\u308b\u305f\u3081\u306b\u4f7f\u7528\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002\u305f\u3060\u3057\u4e21\u65b9\u4e00\u5ea6\u306b\u4f7f\u7528\u3067\u304d\u307e\u305b\u3093\u3002 CountsViewPane.scaleHelpLog3=\ \u5b9f\u969b\u306e\u30ab\u30a6\u30f3\u30c8(\u30c4\u30fc\u30eb\u30c1\u30c3\u30d7\u307e\u305f\u306f\u7d50\u679c\u30d3\u30e5\u30fc\u3067\u5229\u7528\u53ef\u80fd)\u306f\u7d76\u5bfe\u6bd4\u8f03\u306b\u4f7f\u7528\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002 \u614e\u91cd\u306b\u5bfe\u6570\u76ee\u76db\u3092\u4f7f\u7528\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -CountsViewPane.scaleLabel.text=\u76ee\u76db: -# {0} - \u30ab\u30a6\u30f3\u30c8 -# {1} - \u30a4\u30d9\u30f3\u30c8\u30bf\u30a4\u30d7\u306e\u8868\u793a\u540d -# {2} - \u958b\u59cb\u65e5\u6642 -# {3} - \u7d42\u4e86\u65e5\u6642 +CountsViewPane.scaleLabel.text=\u76ee\u76db\: CountsViewPane.tooltip.text={2}\n\u3068 {3}\n\u9593\u306e {0} {1} \u30a4\u30d9\u30f3\u30c8 ScaleType.Linear=\u7dda\u5f62 ScaleType.Logarithmic=\u5bfe\u6570 +SelectIntervalAction.errorMessage=\u9593\u9694\u306e\u9078\u629e\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +SelectIntervalAndTypeAction.errorMessage=\u9593\u9694\u3068\u30bf\u30a4\u30d7\u306e\u9078\u629e\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +SelectTypeAction.errorMessage=\u30bf\u30a4\u30d7\u306e\u9078\u629e\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 Timeline.ui.countsview.menuItem.selectEventType=\u30a4\u30d9\u30f3\u30c8\u30bf\u30a4\u30d7\u3092\u9078\u629e -Timeline.ui.countsview.menuItem.selectTimeandType=\u6642\u9593\u3068\u30bf\u30a4\u30d7\u3092\u9078\u629e Timeline.ui.countsview.menuItem.selectTimeRange=\u6642\u9593\u7bc4\u56f2\u3092\u9078\u629e +Timeline.ui.countsview.menuItem.selectTimeandType=\u6642\u9593\u3068\u30bf\u30a4\u30d7\u3092\u9078\u629e Timeline.ui.countsview.menuItem.zoomIntoTimeRange=\u6642\u9593\u7bc4\u56f2\u306b\u30ba\u30fc\u30e0\u30a4\u30f3 +ZoomToIntervalAction.errorMessage=\u9593\u9694\u3078\u306e\u30ba\u30fc\u30e0\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/Bundle_ja.properties index d7ee0e7dd5..792d2c136f 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/detailview/Bundle_ja.properties @@ -1,3 +1,4 @@ +#Mon Jul 12 13:22:00 UTC 2021 CollapseClusterAction.text=\u6298\u308a\u305f\u305f\u3080 DetailViewPane.advancedLayoutOptionsButtonLabel.text=\u9ad8\u5ea6\u306a\u30ec\u30a4\u30a2\u30a6\u30c8\u30aa\u30d7\u30b7\u30e7\u30f3 DetailViewPane.bandByTypeBox.text=\u30bf\u30a4\u30d7\u5225\u306b\u7d50\u5408 @@ -6,8 +7,7 @@ DetailViewPane.hiddenRadio.text=\u8a18\u8ff0\u3092\u975e\u8868\u793a DetailViewPane.loggedTask.backButton=\u623b\u308b(\u53d6\u308a\u6d88\u3057) DetailViewPane.loggedTask.continueButton=\u7d9a\u884c DetailViewPane.loggedTask.name=\u8a73\u7d30\u30d3\u30e5\u30fc\u306e\u66f4\u65b0\u4e2d\u3067\u3059 -# {0} - \u30a4\u30d9\u30f3\u30c8\u6570 -DetailViewPane.loggedTask.prompt= {0} \u30a4\u30d9\u30f3\u30c8\u306e\u8a73\u7d30\u3092\u8868\u793a\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307e\u3059\u3002 \u3053\u308c\u306b\u306f\u6642\u9593\u304c\u304b\u304b\u308a\u3001\u4f7f\u7528\u53ef\u80fd\u306a\u30e1\u30e2\u30ea\u30fc\u304c\u6d88\u8cbb\u3055\u308c\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002\n\n\u7d9a\u884c\u3057\u307e\u3059\u304b? +DetailViewPane.loggedTask.prompt={0} \u30a4\u30d9\u30f3\u30c8\u306e\u8a73\u7d30\u3092\u8868\u793a\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307e\u3059\u3002 \u3053\u308c\u306b\u306f\u6642\u9593\u304c\u304b\u304b\u308a\u3001\u4f7f\u7528\u53ef\u80fd\u306a\u30e1\u30e2\u30ea\u30fc\u304c\u6d88\u8cbb\u3055\u308c\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002\n\n\u7d9a\u884c\u3057\u307e\u3059\u304b? DetailViewPane.loggedTask.queryDb=\u30a4\u30d9\u30f3\u30c8\u30c7\u30fc\u30bf\u306e\u691c\u7d22\u4e2d\u3067\u3059 DetailViewPane.loggedTask.updateUI=\u30d3\u30e5\u30fc\u306e\u5165\u529b\u4e2d\u3067\u3059 DetailViewPane.oneEventPerRowBox.text=1\u5217\u306b\u3064\u304d1\u3064 @@ -15,26 +15,20 @@ DetailViewPane.pinnedLaneLabel.text=\u30d4\u30f3\u7559\u3081\u3057\u305f\u30a4\u DetailViewPane.primaryLaneLabel.text=\u3059\u3079\u3066\u306e\u30a4\u30d9\u30f3\u30c8(\u30d5\u30a3\u30eb\u30bf\u30fc\u6e08\u307f) DetailViewPane.showRadio.text=\u5b8c\u5168\u306a\u8a18\u8ff0\u3092\u8868\u793a DetailViewPane.truncateAllBox.text=\u8a18\u8ff0\u3092\u4e00\u62ec\u524a\u9664 -DetailViewPane.truncateSliderLabel.text=\u6700\u5927\u8a18\u8ff0\u5e45(px): +DetailViewPane.truncateSliderLabel.text=\u6700\u5927\u8a18\u8ff0\u5e45(px)\: EventBundleNodeBase.toolTip.loading=\u8aad\u307f\u8fbc\u307f\u4e2d... EventClusterNode.loggedTask.name=\u30b5\u30d6\u30a4\u30d9\u30f3\u30c8\u3092\u8aad\u307f\u8fbc\u3080 -# {0} - \u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u30ab\u30a6\u30f3\u30c8\u6587\u5b57\u5217 EventNodeBase.toolTip.hashSetHits=\n\n\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u306e\u30d2\u30c3\u30c8\n{0} EventNodeBase.toolTip.loading2=\u30c4\u30fc\u30eb\u30c1\u30c3\u30d7\u306e\u8aad\u307f\u8fbc\u307f\u4e2d\u3067\u3059 -# {0} - \u30bf\u30b0\u30ab\u30a6\u30f3\u30c8\u6587\u5b57\u5217 EventNodeBase.toolTip.tags=\n\n\u30bf\u30b0\n{0} -# {0} - \u30ab\u30a6\u30f3\u30c8 -# {1} - \u30a4\u30d9\u30f3\u30c8\u30bf\u30a4\u30d7 -# {2} - \u8a18\u8ff0 -# {3} - \u958b\u59cb\u65e5/\u6642\u9593 -# {4} - \u7d42\u4e86\u65e5/\u6642\u9593 EventNodeBase.tooltip.text=\t{3}\n\u3068 \t{4}\n{2}\n\u9593\u306e {0} {1} \u30a4\u30d9\u30f3\u30c8 ExpandClusterAction.text=\u5c55\u958b -# {0} - \u30ac\u30a4\u30c9\u30e9\u30a4\u30f3\u4f4d\u7f6e\u306e\u65e5\u4ed8/\u6642\u9593 GuideLine.tooltip.text={0}\n\u53f3\u30af\u30ea\u30c3\u30af\u3057\u3066\u524a\u9664\u3057\u307e\u3059\u3002\n\u30c9\u30e9\u30c3\u30b0\u3057\u3066\u518d\u914d\u7f6e\u3057\u307e\u3059\u3002 HideDescriptionAction.displayMsg=\u3053\u306e\u30b0\u30eb\u30fc\u30d7\u3092\u8a73\u7d30\u30d3\u30e5\u30fc\u304b\u3089\u975e\u8868\u793a\u306b\u3057\u307e\u3059\u3002 HideDescriptionAction.displayName=\u975e\u8868\u793a PinEventAction.text=\u30d4\u30f3\u7559\u3081\u3059\u308b +PinnedChartLane.pinnedEventsListener.errorMessage=\u56fa\u5b9a\u3055\u308c\u305f\u30a4\u30d9\u30f3\u30c8\u3092\u30ec\u30fc\u30f3\u306b\u8ffd\u52a0\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 PlaceMArkerAction.name=\u5834\u6240\u30de\u30fc\u30ab\u30fc -UnhideDescriptionAction.displayName=\u518d\u8868\u793a +PrimaryDetailsChartLane.stripeChangeListener.errorMessage=\u30c1\u30e3\u30fc\u30c8\u30ec\u30fc\u30f3\u306b\u30b9\u30c8\u30e9\u30a4\u30d7\u3092\u8ffd\u52a0\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 UnPinEventAction.text=\u30d4\u30f3\u7559\u3081\u3092\u5916\u3059 +UnhideDescriptionAction.displayName=\u518d\u8868\u793a diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/listvew/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/timeline/ui/listvew/Bundle_ja.properties index 7b5a853206..34233f49cf 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/ui/listvew/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/listvew/Bundle_ja.properties @@ -1,12 +1,12 @@ +#Mon Jul 12 13:22:00 UTC 2021 +EventRow.updateItem.errorMessage=ID\u3067\u30a4\u30d9\u30f3\u30c8\u306e\u53d6\u5f97\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +EventTableCell.updateItem.errorMessage=ID\u3067\u30a4\u30d9\u30f3\u30c8\u306e\u53d6\u5f97\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 ListChart.errorMsg=\u9078\u629e\u3057\u305f\u30a4\u30d9\u30f3\u30c8\u306e\u30b3\u30f3\u30c6\u30f3\u30c4\u3092\u53d6\u5f97\u4e2d\u306b\u554f\u984c\u304c\u3042\u308a\u307e\u3057\u305f\u3002 -# {0} - \u30a4\u30d9\u30f3\u30c8\u6570 ListTimeline.eventCountLabel.text={0} \u30a4\u30d9\u30f3\u30c8 ListTimeline.hashHitTooltip.error=\u9078\u629e\u3057\u305f\u30a4\u30d9\u30f3\u30c8\u306e\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u540d\u3092\u53d6\u5f97\u4e2d\u306b\u554f\u984c\u304c\u3042\u308a\u307e\u3057\u305f\u3002 -# {0} - \u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u540d -ListTimeline.hashHitTooltip.text=\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8:\n{0} +ListTimeline.hashHitTooltip.text=\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\:\n{0} ListTimeline.taggedTooltip.error=\u9078\u629e\u3057\u305f\u30a4\u30d9\u30f3\u30c8\u306e\u30bf\u30b0\u540d\u3092\u53d6\u5f97\u4e2d\u306b\u554f\u984c\u304c\u3042\u308a\u307e\u3057\u305f\u3002 -# {0} - \u30bf\u30b0\u540d -ListTimeline.taggedTooltip.text=\u30bf\u30b0:\n{0} +ListTimeline.taggedTooltip.text=\u30bf\u30b0\:\n{0} ListView.EventTypeCell.accessedTooltip=\u30a2\u30af\u30bb\u30b9\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb( A ) ListView.EventTypeCell.changedTooltip=\u5909\u66f4\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb( C ) ListView.EventTypeCell.createdTooltip=\u4f5c\u6210\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb( B, for Born ) diff --git a/Core/src/org/sleuthkit/autopsy/timeline/zooming/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/timeline/zooming/Bundle_ja.properties index 16cb968d63..74051b100f 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/zooming/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/timeline/zooming/Bundle_ja.properties @@ -1,11 +1,12 @@ -DescriptionLOD.short=\u77ed -DescriptionLOD.medium=\u4e2d +#Mon Jul 12 13:22:00 UTC 2021 DescriptionLOD.full=\u9577 - +DescriptionLOD.medium=\u4e2d +DescriptionLOD.short=\u77ed EventTypeZoomLevel.baseType=\u57fa\u672c\u30bf\u30a4\u30d7 EventTypeZoomLevel.rootType=\u30eb\u30fc\u30c8\u30bf\u30a4\u30d7 EventTypeZoomLevel.subType=\u30b5\u30d6\u30bf\u30a4\u30d7 -ZoomSettingsPane.descrLODLabel.text=\u8aac\u660e\u306e\u8a73\u7d30: -ZoomSettingsPane.timeUnitLabel.text=\u6642\u9593\u5358\u4f4d: -ZoomSettingsPane.typeZoomLabel.text=\u30a4\u30d9\u30f3\u30c8\u30bf\u30a4\u30d7: +ZoomSettingsPane.descrLODLabel.text=\u8aac\u660e\u306e\u8a73\u7d30\: +ZoomSettingsPane.sliderChange.errorText=\u30b9\u30e9\u30a4\u30c0\u30fc\u5024\u306e\u5909\u66f4\u3078\u306e\u5fdc\u7b54\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +ZoomSettingsPane.timeUnitLabel.text=\u6642\u9593\u5358\u4f4d\: +ZoomSettingsPane.typeZoomLabel.text=\u30a4\u30d9\u30f3\u30c8\u30bf\u30a4\u30d7\: ZoomSettingsPane.zoomLabel.text=\u30ba\u30fc\u30e0 diff --git a/Core/src/org/sleuthkit/autopsy/url/analytics/domaincategorization/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/url/analytics/domaincategorization/Bundle_ja.properties new file mode 100644 index 0000000000..a670858371 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/url/analytics/domaincategorization/Bundle_ja.properties @@ -0,0 +1,35 @@ +#Mon Jun 14 12:23:19 UTC 2021 +AddEditCategoryDialog.cancelButton.text=\u30ad\u30e3\u30f3\u30bb\u30eb +AddEditCategoryDialog.categoryLabel.text=\u30ab\u30c6\u30b4\u30ea\u30fc\uff1a +AddEditCategoryDialog.domainSuffixLabel.text=\u30c9\u30e1\u30a4\u30f3\u30fb\u30b5\u30d5\u30a3\u30c3\u30af\u30b9\uff1a +AddEditCategoryDialog.saveButton.text=\u4fdd\u5168 +AddEditCategoryDialog_Add=\u30a8\u30f3\u30c8\u30ea\u3092\u8ffd\u52a0 +AddEditCategoryDialog_Edit=\u30a8\u30f3\u30c8\u30ea\u306e\u7de8\u96c6 +AddEditCategoryDialog_onValueUpdate_badCategory={0}\u6587\u5b57\u4ee5\u4e0b\u306e\u30ab\u30c6\u30b4\u30ea\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 +AddEditCategoryDialog_onValueUpdate_badSuffix=1\u3064\u4ee5\u4e0a\u306e\u30d4\u30ea\u30aa\u30c9\u3092\u542b\u3080{0}\u6587\u5b57\u4ee5\u4e0b\u306e\u30c9\u30e1\u30a4\u30f3\u30b5\u30d5\u30a3\u30c3\u30af\u30b9\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 +AddEditCategoryDialog_onValueUpdate_sameCategory=\u3053\u306e\u30c9\u30e1\u30a4\u30f3\u30b5\u30d5\u30a3\u30c3\u30af\u30b9\u306e\u65b0\u3057\u3044\u30ab\u30c6\u30b4\u30ea\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 +AddEditCategoryDialog_onValueUpdate_suffixRepeat=\u30e6\u30cb\u30fc\u30af\u306e\u30c9\u30e1\u30a4\u30f3\u30fb\u30b5\u30d5\u30a3\u30c3\u30af\u30b9\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u30fb +WebCategoriesOptionsPanel.categoriesTitle.text=\u30ab\u30c6\u30b4\u30ea\uff1a +WebCategoriesOptionsPanel.deleteEntryButton.text=\u30a8\u30f3\u30c8\u30ea\u3092\u524a\u9664 +WebCategoriesOptionsPanel.editEntryButton.text=\u30a8\u30f3\u30c8\u30ea\u306e\u7de8\u96c6 +WebCategoriesOptionsPanel.exportSetButton.text=\u30a8\u30af\u30b9\u30dd\u30fc\u30c8\u30fb\u30bb\u30c3\u30c8 +WebCategoriesOptionsPanel.importSetButton.text=\u30a4\u30f3\u30dd\u30fc\u30c8\u30fb\u30bb\u30c3\u30c8 +WebCategoriesOptionsPanel.ingestRunningWarning.text=\u53d6\u8fbc\u307f\u306f\u73fe\u5728\u5b9f\u884c\u4e2d\u3067\u3059\u3002 \u4eca\u306f\u7de8\u96c6\u306f\u3067\u304d\u307e\u305b\u3093\u3002 +WebCategoriesOptionsPanel.newEntryButton.text=\u65b0\u898f\u30a8\u30f3\u30c8\u30ea\u30fc +WebCategoriesOptionsPanel.panelDescription.text=\u3053\u306e\u6a5f\u80fd\u3092\u4f7f\u7528\u3059\u308b\u3068\u3001\u6700\u8fd1\u306e\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3\u306e\u53d6\u8fbc\u307f\u30e2\u30b8\u30e5\u30fc\u30eb\u3067\u3001\u30c9\u30e1\u30a4\u30f3\u306e\u30b5\u30d5\u30a3\u30c3\u30af\u30b9\u306b\u57fa\u3065\u3044\u3066Web\u30b5\u30a4\u30c8\u306e\u30ab\u30b9\u30bf\u30e0\u5206\u985e\u3092\u5b9f\u884c\u3067\u304d\u307e\u3059\u3002 +WebCategoriesOptionsPanel_categoryTable_categoryColumnName=\u30ab\u30c6\u30b4\u30ea\uff1a +WebCategoriesOptionsPanel_categoryTable_suffixColumnName=\u30c9\u30e1\u30a4\u30f3\u30fb\u30b5\u30d5\u30a3\u30c3\u30af\u30b9 +WebCategoriesOptionsPanel_exportSetButtonActionPerformed_defaultFileName=\u30ab\u30b9\u30bf\u30e0\u30fb\u30ab\u30c6\u30b4\u30ea\u306e\u30a8\u30af\u30b9\u30dd\u30fc\u30c8 +WebCategoriesOptionsPanel_exportSetButtonActionPerformed_duplicateMessage=\u9078\u629e\u3057\u305f\u30d1\u30b9\u306b\u30d5\u30a1\u30a4\u30eb\u304c\u65e2\u306b\u5b58\u5728\u3057\u307e\u3059\u3002 \u30ab\u30c6\u30b4\u30ea\u306f\u30a8\u30af\u30b9\u30dd\u30fc\u30c8\u3055\u308c\u307e\u305b\u3093\u3002 +WebCategoriesOptionsPanel_exportSetButtonActionPerformed_duplicateTitle=\u30d5\u30a1\u30a4\u30eb\u304c\u65e2\u306b\u5b58\u5728\u3057\u307e\u3059 +WebCategoriesOptionsPanel_exportSetButtonActionPerformed_errorMessage=\u30a8\u30af\u30b9\u30dd\u30fc\u30c8\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +WebCategoriesOptionsPanel_exportSetButtonActionPerformed_errorTitle=\u30a8\u30af\u30b9\u30dd\u30fc\u30c8\u30a8\u30e9\u30fc +WebCategoriesOptionsPanel_importSetButtonActionPerformed_errorMessage=json\u30d5\u30a1\u30a4\u30eb\u306e\u30a4\u30f3\u30dd\u30fc\u30c8\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +WebCategoriesOptionsPanel_importSetButtonActionPerformed_errorTitle=\u30a4\u30f3\u30dd\u30fc\u30c8\u30a8\u30e9\u30fc +WebCategoriesOptionsPanel_importSetButtonActionPerformed_onConflictCancel=\u30ad\u30e3\u30f3\u30bb\u30eb +WebCategoriesOptionsPanel_importSetButtonActionPerformed_onConflictMessage=\u30c9\u30e1\u30a4\u30f3\u30b5\u30d5\u30a3\u30c3\u30af\u30b9{0}\u306f\u3059\u3067\u306b\u5b58\u5728\u3057\u307e\u3059\u3002 \u4f55\u3092\u3057\u307e\u3059\u304b\uff1f +WebCategoriesOptionsPanel_importSetButtonActionPerformed_onConflictOverwrite=\u4e0a\u66f8\u304d\u3059\u308b +WebCategoriesOptionsPanel_importSetButtonActionPerformed_onConflictSkip=\u7121\u8996 +WebCategoriesOptionsPanel_importSetButtonActionPerformed_onConflictTitle=\u30c9\u30e1\u30a4\u30f3\u30fb\u30b5\u30d5\u30a3\u30c3\u30af\u30b9\u306f\u3059\u3067\u306b\u5b58\u5728\u3057\u307e\u3059 +WebCategoryOptionsController_keywords=\u30ab\u30b9\u30bf\u30e0Web\u30ab\u30c6\u30b4\u30ea +WebCategoryOptionsController_title=\u30ab\u30b9\u30bf\u30e0Web\u30ab\u30c6\u30b4\u30ea diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java index 3d4a55447a..b5424d55a0 100755 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java @@ -1258,7 +1258,7 @@ public class CentralRepoDatamodelTest extends TestCase { // We expect 11 total - 10 default and the custom one made earlier // Note: this test will need to be updated based on the current default items defined in the correlation_types table - assertTrue("getDefinedCorrelationTypes returned " + types.size() + " entries - expected 28", types.size() == 28); + assertTrue("getDefinedCorrelationTypes returned " + types.size() + " entries - expected 30", types.size() == 30); } catch (CentralRepoException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); @@ -1270,7 +1270,7 @@ public class CentralRepoDatamodelTest extends TestCase { // We expect 10 - the custom type is disabled // Note: this test will need to be updated based on the current default items defined in the correlation_types table - assertTrue("getDefinedCorrelationTypes returned " + types.size() + " enabled entries - expected 27", types.size() == 27); + assertTrue("getDefinedCorrelationTypes returned " + types.size() + " enabled entries - expected 29", types.size() == 29); } catch (CentralRepoException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); @@ -1282,7 +1282,7 @@ public class CentralRepoDatamodelTest extends TestCase { // We expect 10 - the custom type is not supported // Note: this test will need to be updated based on the current default items defined in the correlation_types table - assertTrue("getDefinedCorrelationTypes returned " + types.size() + " supported entries - expected 27", types.size() == 27); + assertTrue("getDefinedCorrelationTypes returned " + types.size() + " supported entries - expected 29", types.size() == 29); } catch (CentralRepoException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); diff --git a/Experimental/nbproject/project.xml b/Experimental/nbproject/project.xml index 41343b8d23..34734e4954 100644 --- a/Experimental/nbproject/project.xml +++ b/Experimental/nbproject/project.xml @@ -144,7 +144,7 @@ 10 - 10.23 + 10.24 diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AinStatusNode.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AinStatusNode.java index 8c7ba7cdd9..9d72539841 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AinStatusNode.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AinStatusNode.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2018 Basis Technology Corp. + * Copyright 2018-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -40,7 +40,7 @@ final class AinStatusNode extends AbstractNode { * Construct a new AinStatusNode. */ AinStatusNode(AutoIngestMonitor monitor) { - super(Children.create(new AinStatusChildren(monitor), false)); + super(Children.create(new AinStatusChildren(monitor), true)); } /** diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestAdminActions.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestAdminActions.java index a881a96fb2..6680074a17 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestAdminActions.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestAdminActions.java @@ -157,6 +157,102 @@ final class AutoIngestAdminActions { } } } + + @NbBundle.Messages({"AutoIngestAdminActions.enableOCR.title=Enable OCR For This Case", + "AutoIngestAdminActions.enableOCR.error=Failed to enable OCR for case \"%s\"."}) + static final class EnableOCR extends AbstractAction { + + private static final long serialVersionUID = 1L; + private final AutoIngestJob job; + + EnableOCR(AutoIngestJob job) { + super(Bundle.AutoIngestAdminActions_enableOCR_title()); + this.job = job; + } + + @Override + public void actionPerformed(ActionEvent e) { + + if (job == null) { + return; + } + + final AutoIngestDashboardTopComponent tc = (AutoIngestDashboardTopComponent) WindowManager.getDefault().findTopComponent(AutoIngestDashboardTopComponent.PREFERRED_ID); + if (tc == null) { + return; + } + + AutoIngestDashboard dashboard = tc.getAutoIngestDashboard(); + if (dashboard != null) { + dashboard.getPendingJobsPanel().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + EventQueue.invokeLater(() -> { + try { + dashboard.getMonitor().changeOcrStateForCase(job.getManifest().getCaseName(), true); + dashboard.getPendingJobsPanel().refresh(new AutoIngestNodeRefreshEvents.RefreshCaseEvent(dashboard.getMonitor(), job.getManifest().getCaseName())); + } catch (AutoIngestMonitor.AutoIngestMonitorException ex) { + String errorMessage = String.format(Bundle.AutoIngestAdminActions_enableOCR_error(), job.getManifest().getCaseName()); + logger.log(Level.SEVERE, errorMessage, ex); + MessageNotifyUtil.Message.error(errorMessage); + } finally { + dashboard.getPendingJobsPanel().setCursor(Cursor.getDefaultCursor()); + } + }); + } + } + + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); //To change body of generated methods, choose Tools | Templates. + } + } + + @NbBundle.Messages({"AutoIngestAdminActions.disableOCR.title=Disable OCR For This Case", + "AutoIngestAdminActions.disableOCR.error=Failed to disable OCR for case \"%s\"."}) + static final class DisableOCR extends AbstractAction { + + private static final long serialVersionUID = 1L; + private final AutoIngestJob job; + + DisableOCR(AutoIngestJob job) { + super(Bundle.AutoIngestAdminActions_disableOCR_title()); + this.job = job; + } + + @Override + public void actionPerformed(ActionEvent e) { + + if (job == null) { + return; + } + + final AutoIngestDashboardTopComponent tc = (AutoIngestDashboardTopComponent) WindowManager.getDefault().findTopComponent(AutoIngestDashboardTopComponent.PREFERRED_ID); + if (tc == null) { + return; + } + + AutoIngestDashboard dashboard = tc.getAutoIngestDashboard(); + if (dashboard != null) { + dashboard.getPendingJobsPanel().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + EventQueue.invokeLater(() -> { + try { + dashboard.getMonitor().changeOcrStateForCase(job.getManifest().getCaseName(), false); + dashboard.getPendingJobsPanel().refresh(new AutoIngestNodeRefreshEvents.RefreshCaseEvent(dashboard.getMonitor(), job.getManifest().getCaseName())); + } catch (AutoIngestMonitor.AutoIngestMonitorException ex) { + String errorMessage = String.format(Bundle.AutoIngestAdminActions_disableOCR_error(), job.getManifest().getCaseName()); + logger.log(Level.SEVERE, errorMessage, ex); + MessageNotifyUtil.Message.error(errorMessage); + } finally { + dashboard.getPendingJobsPanel().setCursor(Cursor.getDefaultCursor()); + } + }); + } + } + + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); //To change body of generated methods, choose Tools | Templates. + } + } @NbBundle.Messages({"AutoIngestAdminActions.progressDialogAction.title=Ingest Progress"}) static final class ProgressDialogAction extends AbstractAction { diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java index 0e25ca655f..656b98b278 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2015-2018 Basis Technology Corp. + * Copyright 2015-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -122,6 +122,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { private static final int RUNNING_TABLE_COL_PREFERRED_WIDTH = 175; private static final int PRIORITY_COLUMN_PREFERRED_WIDTH = 60; private static final int PRIORITY_COLUMN_MAX_WIDTH = 150; + private static final int OCR_COLUMN_PREFERRED_WIDTH = 50; + private static final int OCR_COLUMN_MAX_WIDTH = 150; private static final int ACTIVITY_TIME_COL_MIN_WIDTH = 250; private static final int ACTIVITY_TIME_COL_MAX_WIDTH = 450; private static final int TIME_COL_MIN_WIDTH = 30; @@ -133,9 +135,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { private static final int ACTIVITY_COL_MIN_WIDTH = 70; private static final int ACTIVITY_COL_MAX_WIDTH = 2000; private static final int ACTIVITY_COL_PREFERRED_WIDTH = 300; - private static final int STATUS_COL_MIN_WIDTH = 55; + private static final int STATUS_COL_MIN_WIDTH = 50; private static final int STATUS_COL_MAX_WIDTH = 250; - private static final int STATUS_COL_PREFERRED_WIDTH = 55; + private static final int STATUS_COL_PREFERRED_WIDTH = 50; private static final int COMPLETED_TIME_COL_MIN_WIDTH = 30; private static final int COMPLETED_TIME_COL_MAX_WIDTH = 2000; private static final int COMPLETED_TIME_COL_PREFERRED_WIDTH = 280; @@ -179,7 +181,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { "AutoIngestControlPanel.JobsTableModel.ColumnHeader.Status=Status", "AutoIngestControlPanel.JobsTableModel.ColumnHeader.CaseFolder=Case Folder", "AutoIngestControlPanel.JobsTableModel.ColumnHeader.LocalJob= Local Job?", - "AutoIngestControlPanel.JobsTableModel.ColumnHeader.ManifestFilePath= Manifest File Path" + "AutoIngestControlPanel.JobsTableModel.ColumnHeader.ManifestFilePath= Manifest File Path", + "AutoIngestControlPanel.JobsTableModel.ColumnHeader.OCR=OCR" }) private enum JobsTableModelColumns { @@ -195,7 +198,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { CASE_DIRECTORY_PATH(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.CaseFolder")), IS_LOCAL_JOB(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.LocalJob")), MANIFEST_FILE_PATH(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.ManifestFilePath")), - PRIORITY(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.Priority")); + PRIORITY(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.Priority")), + OCR(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.OCR")); private final String header; private JobsTableModelColumns(String header) { @@ -219,7 +223,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { CASE_DIRECTORY_PATH.getColumnHeader(), IS_LOCAL_JOB.getColumnHeader(), MANIFEST_FILE_PATH.getColumnHeader(), - PRIORITY.getColumnHeader()}; + PRIORITY.getColumnHeader(), + OCR.getColumnHeader()}; } /** @@ -406,6 +411,12 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { column.setMaxWidth(PRIORITY_COLUMN_MAX_WIDTH); column.setPreferredWidth(PRIORITY_COLUMN_PREFERRED_WIDTH); column.setWidth(PRIORITY_COLUMN_PREFERRED_WIDTH); + + column = pendingTable.getColumn(JobsTableModelColumns.OCR.getColumnHeader()); + column.setCellRenderer(new OcrIconCellRenderer()); + column.setMaxWidth(OCR_COLUMN_MAX_WIDTH); + column.setPreferredWidth(OCR_COLUMN_PREFERRED_WIDTH); + column.setWidth(OCR_COLUMN_PREFERRED_WIDTH); /** * Allow sorting when a column header is clicked. @@ -457,6 +468,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.IS_LOCAL_JOB.getColumnHeader())); runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.MANIFEST_FILE_PATH.getColumnHeader())); runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.PRIORITY.getColumnHeader())); + runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.OCR.getColumnHeader())); + /* * Set up a column to display the cases associated with the jobs. */ @@ -553,6 +566,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.CASE_DIRECTORY_PATH.getColumnHeader())); completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.MANIFEST_FILE_PATH.getColumnHeader())); completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.PRIORITY.getColumnHeader())); + /* * Set up a column to display the cases associated with the jobs. */ @@ -603,6 +617,15 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { column.setMaxWidth(STATUS_COL_MAX_WIDTH); column.setPreferredWidth(STATUS_COL_PREFERRED_WIDTH); column.setWidth(STATUS_COL_PREFERRED_WIDTH); + + /* + * Set up a column to display OCR enabled/disabled flag. + */ + column = completedTable.getColumn(JobsTableModelColumns.OCR.getColumnHeader()); + column.setCellRenderer(new OcrIconCellRenderer()); + column.setMaxWidth(OCR_COLUMN_MAX_WIDTH); + column.setPreferredWidth(OCR_COLUMN_PREFERRED_WIDTH); + column.setWidth(OCR_COLUMN_PREFERRED_WIDTH); /* * Allow sorting when a column header is clicked. @@ -856,6 +879,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { case JOB_COMPLETED: case CASE_DELETED: case REPROCESS_JOB: + case OCR_STATE_CHANGE: updateExecutor.submit(new UpdateAllJobsTablesTask()); break; case PAUSED_BY_USER_REQUEST: @@ -1193,7 +1217,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { job.getCaseDirectoryPath(), // CASE_DIRECTORY_PATH job.getProcessingHostName().equals(LOCAL_HOST_NAME), // IS_LOCAL_JOB job.getManifest().getFilePath(), // MANIFEST_FILE_PATH - job.getPriority()}); // PRIORITY + job.getPriority(), // PRIORITY + job.getOcrEnabled()}); // OCR FLAG } } catch (Exception ex) { sysLogger.log(Level.SEVERE, "Dashboard error refreshing table", ex); diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJob.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJob.java index 68487d0fcb..a1ce23b917 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJob.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJob.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2018 Basis Technology Corp. + * Copyright 2011-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -46,7 +46,7 @@ import org.sleuthkit.autopsy.ingest.IngestProgressSnapshotProvider; final class AutoIngestJob implements Comparable, IngestProgressSnapshotProvider, Serializable { private static final long serialVersionUID = 1L; - private static final int CURRENT_VERSION = 3; + private static final int CURRENT_VERSION = 4; private static final int DEFAULT_PRIORITY = 0; private static final String LOCAL_HOST_NAME = NetworkUtils.getLocalHostName(); @@ -100,6 +100,11 @@ final class AutoIngestJob implements Comparable, IngestProgressSn private List ingestThreadsSnapshot; private List ingestJobsSnapshot; private Map moduleRunTimesSnapshot; + + /* + * Version 4 fields. + */ + private boolean ocrEnabled; /** * Constructs a new automated ingest job. All job state not specified in the @@ -194,6 +199,11 @@ final class AutoIngestJob implements Comparable, IngestProgressSn this.ingestJobsSnapshot = Collections.emptyList(); this.moduleRunTimesSnapshot = Collections.emptyMap(); + /* + * Version 4 fields + */ + this.ocrEnabled = nodeData.getOcrEnabled(); + } catch (Exception ex) { throw new AutoIngestJobException(String.format("Error creating automated ingest job"), ex); } @@ -253,6 +263,24 @@ final class AutoIngestJob implements Comparable, IngestProgressSn synchronized Integer getPriority() { return this.priority; } + + /** + * Gets the OCR flag for the job. + * + * @return Flag whether OCR is enabled/disabled. + */ + synchronized boolean getOcrEnabled() { + return this.ocrEnabled; + } + + /** + * Sets the OCR enabled/disabled flag for the job. + * + * @param enabled Flag whether OCR is enabled/disabled. + */ + synchronized void setOcrEnabled(boolean enabled) { + this.ocrEnabled = enabled; + } /** * Sets the processing stage of the job. The start date/time for the stage diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobNodeData.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobNodeData.java index f367fdf553..5e9ab8955d 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobNodeData.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobNodeData.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2017 Basis Technology Corp. + * Copyright 2011-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -31,7 +31,7 @@ import javax.lang.model.type.TypeKind; */ final class AutoIngestJobNodeData { - private static final int CURRENT_VERSION = 2; + private static final int CURRENT_VERSION = 3; private static final int DEFAULT_PRIORITY = 0; /* @@ -47,7 +47,7 @@ final class AutoIngestJobNodeData { * data. This avoids the need to continuously enlarge the buffer. Once the * buffer has all the necessary data, it will be resized as appropriate. */ - private static final int MAX_POSSIBLE_NODE_DATA_SIZE = 131637; + private static final int MAX_POSSIBLE_NODE_DATA_SIZE = 131641; /* * Version 0 fields. @@ -78,6 +78,11 @@ final class AutoIngestJobNodeData { * Version 2 fields. */ private long dataSourceSize; + + /* + * Version 3 fields. + */ + private boolean ocrEnabled; /** * Gets the current version of the auto ingest job coordination service node @@ -115,6 +120,7 @@ final class AutoIngestJobNodeData { setProcessingStageStartDate(job.getProcessingStageStartDate()); setProcessingStageDetails(job.getProcessingStageDetails()); setDataSourceSize(job.getDataSourceSize()); + setOcrEnabled(job.getOcrEnabled()); } /** @@ -128,7 +134,7 @@ final class AutoIngestJobNodeData { if (null == nodeData || nodeData.length == 0) { throw new InvalidDataException(null == nodeData ? "Null nodeData byte array" : "Zero-length nodeData byte array"); } - + /* * Set default values for all fields. */ @@ -150,6 +156,7 @@ final class AutoIngestJobNodeData { this.processingStageDetailsDescription = ""; this.processingStageDetailsStartDate = 0L; this.dataSourceSize = 0L; + this.ocrEnabled = false; /* * Get fields from node data. @@ -192,6 +199,14 @@ final class AutoIngestJobNodeData { */ this.dataSourceSize = buffer.getLong(); } + + if (buffer.hasRemaining()) { + /* + * Get version 3 fields. + */ + int ocrFlag = buffer.getInt(); + this.ocrEnabled = (1 == ocrFlag); + } } catch (BufferUnderflowException ex) { throw new InvalidDataException("Node data is incomplete", ex); @@ -234,6 +249,24 @@ final class AutoIngestJobNodeData { void setPriority(int priority) { this.priority = priority; } + + /** + * Gets the OCR flag for the job. + * + * @return Flag whether OCR is enabled/disabled. + */ + boolean getOcrEnabled() { + return this.ocrEnabled; + } + + /** + * Sets the OCR enabled/disabled flag for the job. + * + * @param enabled Flag whether OCR is enabled/disabled. + */ + void setOcrEnabled(boolean enabled) { + this.ocrEnabled = enabled; + } /** * Gets the number of times the job has crashed during processing. @@ -567,6 +600,10 @@ final class AutoIngestJobNodeData { if (this.version >= 2) { buffer.putLong(this.dataSourceSize); } + + if (this.version >= 3) { + buffer.putInt(this.ocrEnabled ? 1 : 0); + } } // Prepare the array diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java index ffe8e19f01..415b3237b9 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsNode.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2018-2019 Basis Technology Corp. + * Copyright 2018-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -57,7 +57,8 @@ final class AutoIngestJobsNode extends AbstractNode { "AutoIngestJobsNode.jobCreated.text=Job Created", "AutoIngestJobsNode.jobCompleted.text=Job Completed", "AutoIngestJobsNode.priority.text=Prioritized", - "AutoIngestJobsNode.status.text=Status" + "AutoIngestJobsNode.status.text=Status", + "AutoIngestJobsNode.ocr.text=OCR" }) /** @@ -69,7 +70,7 @@ final class AutoIngestJobsNode extends AbstractNode { * refresh events */ AutoIngestJobsNode(AutoIngestMonitor monitor, AutoIngestJobStatus status, EventBus eventBus) { - super(Children.create(new AutoIngestNodeChildren(monitor, status, eventBus), false)); + super(Children.create(new AutoIngestNodeChildren(monitor, status, eventBus), true)); refreshChildrenEventBus = eventBus; } @@ -98,12 +99,14 @@ final class AutoIngestJobsNode extends AbstractNode { private final Stage jobStage; private final List jobSnapshot; private final Integer jobPriority; + private final Boolean ocrFlag; AutoIngestJobWrapper(AutoIngestJob job) { autoIngestJob = job; jobStage = job.getProcessingStage(); jobSnapshot = job.getIngestJobSnapshots(); jobPriority = job.getPriority(); + ocrFlag = job.getOcrEnabled(); } AutoIngestJob getJob() { @@ -123,11 +126,12 @@ final class AutoIngestJobsNode extends AbstractNode { AutoIngestJob thisJob = this.autoIngestJob; AutoIngestJob otherJob = ((AutoIngestJobWrapper) other).autoIngestJob; - // Only equal if the manifest paths and processing stage details are the same. + // Only equal if the manifest paths, processing stage details, priority, and OCR flag are the same. return thisJob.getManifest().getFilePath().equals(otherJob.getManifest().getFilePath()) && jobStage.equals(((AutoIngestJobWrapper) other).jobStage) && jobSnapshot.equals(((AutoIngestJobWrapper) other).jobSnapshot) - && jobPriority.equals(((AutoIngestJobWrapper) other).jobPriority); + && jobPriority.equals(((AutoIngestJobWrapper) other).jobPriority) + && ocrFlag.equals(((AutoIngestJobWrapper) other).ocrFlag); } @Override @@ -137,6 +141,7 @@ final class AutoIngestJobsNode extends AbstractNode { hash = 23 * hash + Objects.hashCode(this.jobStage); hash = 23 * hash + Objects.hashCode(this.jobSnapshot); hash = 23 * hash + Objects.hashCode(this.jobPriority); + hash = 23 * hash + Objects.hashCode(this.ocrFlag); return hash; } @@ -171,6 +176,10 @@ final class AutoIngestJobsNode extends AbstractNode { Integer getPriority() { return autoIngestJob.getPriority(); } + + boolean getOcrEnabled() { + return autoIngestJob.getOcrEnabled(); + } } /** @@ -327,6 +336,8 @@ final class AutoIngestJobsNode extends AbstractNode { jobWrapper.getManifest().getDateFileCreated())); ss.put(new NodeProperty<>(Bundle.AutoIngestJobsNode_priority_text(), Bundle.AutoIngestJobsNode_priority_text(), Bundle.AutoIngestJobsNode_priority_text(), jobWrapper.getPriority())); + ss.put(new NodeProperty<>(Bundle.AutoIngestJobsNode_ocr_text(), Bundle.AutoIngestJobsNode_ocr_text(), Bundle.AutoIngestJobsNode_ocr_text(), + jobWrapper.getOcrEnabled())); break; case RUNNING_JOB: AutoIngestJob.StageDetails status = jobWrapper.getProcessingStageDetails(); @@ -344,6 +355,8 @@ final class AutoIngestJobsNode extends AbstractNode { jobWrapper.getCompletedDate())); ss.put(new NodeProperty<>(Bundle.AutoIngestJobsNode_status_text(), Bundle.AutoIngestJobsNode_status_text(), Bundle.AutoIngestJobsNode_status_text(), jobWrapper.getErrorsOccurred() ? StatusIconCellRenderer.Status.WARNING : StatusIconCellRenderer.Status.OK)); + ss.put(new NodeProperty<>(Bundle.AutoIngestJobsNode_ocr_text(), Bundle.AutoIngestJobsNode_ocr_text(), Bundle.AutoIngestJobsNode_ocr_text(), + jobWrapper.getOcrEnabled())); break; default: } @@ -364,6 +377,11 @@ final class AutoIngestJobsNode extends AbstractNode { PrioritizationAction.DeprioritizeCaseAction deprioritizeCaseAction = new PrioritizationAction.DeprioritizeCaseAction(jobWrapper.getJob()); deprioritizeCaseAction.setEnabled(jobWrapper.getPriority() > 0); actions.add(deprioritizeCaseAction); + + actions.add(new AutoIngestAdminActions.EnableOCR(jobWrapper.getJob())); + AutoIngestAdminActions.DisableOCR disableOCRAction = new AutoIngestAdminActions.DisableOCR(jobWrapper.getJob()); + disableOCRAction.setEnabled(jobWrapper.getOcrEnabled() == true); + actions.add(disableOCRAction); break; case RUNNING_JOB: actions.add(new AutoIngestAdminActions.ProgressDialogAction(jobWrapper.getJob())); diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsPanel.java index 6962057541..d335a35430 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsPanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobsPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2018 Basis Technology Corp. + * Copyright 2018-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -43,6 +43,7 @@ final class AutoIngestJobsPanel extends javax.swing.JPanel implements ExplorerMa private static final int INITIAL_CASENAME_WIDTH = 170; private static final int INITIAL_DATASOURCE_WIDTH = 270; private static final int INITIAL_PRIORITIZED_WIDTH = 20; + private static final int INITIAL_OCR_WIDTH = 20; private static final int INITIAL_STATUS_WIDTH = 20; private static final int INVALID_INDEX = -1; private final org.openide.explorer.view.OutlineView outlineView; @@ -81,12 +82,18 @@ final class AutoIngestJobsPanel extends javax.swing.JPanel implements ExplorerMa case PENDING_JOB: outlineView.setPropertyColumns(Bundle.AutoIngestJobsNode_dataSource_text(), Bundle.AutoIngestJobsNode_dataSource_text(), Bundle.AutoIngestJobsNode_jobCreated_text(), Bundle.AutoIngestJobsNode_jobCreated_text(), - Bundle.AutoIngestJobsNode_priority_text(), Bundle.AutoIngestJobsNode_priority_text()); + Bundle.AutoIngestJobsNode_priority_text(), Bundle.AutoIngestJobsNode_priority_text(), + Bundle.AutoIngestJobsNode_ocr_text(), Bundle.AutoIngestJobsNode_ocr_text()); indexOfColumn = getColumnIndexByName(Bundle.AutoIngestJobsNode_priority_text()); if (indexOfColumn != INVALID_INDEX) { outline.getColumnModel().getColumn(indexOfColumn).setPreferredWidth(INITIAL_PRIORITIZED_WIDTH); outline.getColumnModel().getColumn(indexOfColumn).setCellRenderer(new PrioritizedIconCellRenderer()); } + indexOfColumn = getColumnIndexByName(Bundle.AutoIngestJobsNode_ocr_text()); + if (indexOfColumn != INVALID_INDEX) { + outline.getColumnModel().getColumn(indexOfColumn).setPreferredWidth(INITIAL_OCR_WIDTH); + outline.getColumnModel().getColumn(indexOfColumn).setCellRenderer(new OcrIconCellRenderer()); + } break; case RUNNING_JOB: outlineView.setPropertyColumns(Bundle.AutoIngestJobsNode_dataSource_text(), Bundle.AutoIngestJobsNode_dataSource_text(), @@ -102,7 +109,8 @@ final class AutoIngestJobsPanel extends javax.swing.JPanel implements ExplorerMa outlineView.setPropertyColumns(Bundle.AutoIngestJobsNode_dataSource_text(), Bundle.AutoIngestJobsNode_dataSource_text(), Bundle.AutoIngestJobsNode_jobCreated_text(), Bundle.AutoIngestJobsNode_jobCreated_text(), Bundle.AutoIngestJobsNode_jobCompleted_text(), Bundle.AutoIngestJobsNode_jobCompleted_text(), - Bundle.AutoIngestJobsNode_status_text(), Bundle.AutoIngestJobsNode_status_text()); + Bundle.AutoIngestJobsNode_status_text(), Bundle.AutoIngestJobsNode_status_text(), + Bundle.AutoIngestJobsNode_ocr_text(), Bundle.AutoIngestJobsNode_ocr_text()); indexOfColumn = getColumnIndexByName(Bundle.AutoIngestJobsNode_jobCompleted_text()); if (indexOfColumn != INVALID_INDEX) { outline.setColumnSorted(indexOfColumn, false, 1); @@ -112,6 +120,11 @@ final class AutoIngestJobsPanel extends javax.swing.JPanel implements ExplorerMa outline.getColumnModel().getColumn(indexOfColumn).setPreferredWidth(INITIAL_STATUS_WIDTH); outline.getColumnModel().getColumn(indexOfColumn).setCellRenderer(new StatusIconCellRenderer()); } + indexOfColumn = getColumnIndexByName(Bundle.AutoIngestJobsNode_ocr_text()); + if (indexOfColumn != INVALID_INDEX) { + outline.getColumnModel().getColumn(indexOfColumn).setPreferredWidth(INITIAL_OCR_WIDTH); + outline.getColumnModel().getColumn(indexOfColumn).setCellRenderer(new OcrIconCellRenderer()); + } break; default: } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java index e3cace62fc..361a071f0b 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java @@ -109,6 +109,7 @@ import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; +import org.sleuthkit.autopsy.keywordsearch.KeywordSearchJobSettings; /** * An auto ingest manager is responsible for processing auto ingest jobs defined @@ -144,7 +145,8 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen ControlEventType.SHUTDOWN.toString(), ControlEventType.GENERATE_THREAD_DUMP_REQUEST.toString(), Event.CANCEL_JOB.toString(), - Event.REPROCESS_JOB.toString()})); + Event.REPROCESS_JOB.toString(), + Event.OCR_STATE_CHANGE.toString()})); private static final Set INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED); private static final long JOB_STATUS_EVENT_INTERVAL_SECONDS = 10; private static final String JOB_STATUS_PUBLISHING_THREAD_NAME = "AIM-job-status-event-publisher-%d"; @@ -308,6 +310,8 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen handleRemoteJobCancelEvent((AutoIngestJobCancelEvent) event); } else if (event instanceof AutoIngestJobReprocessEvent) { handleRemoteJobReprocessEvent((AutoIngestJobReprocessEvent) event); + } else if (event instanceof AutoIngestOcrStateChangeEvent) { + handleRemoteOcrEvent((AutoIngestOcrStateChangeEvent) event); } } } @@ -466,10 +470,42 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen String hostName = event.getNodeName(); hostNamesToLastMsgTime.put(hostName, Instant.now()); + // currently the only way to the get latest ZK manifest node contents is to do an input directory scan scanInputDirsNow(); setChanged(); notifyObservers(Event.CASE_PRIORITIZED); } + + /** + * Processes a case OCR enabled/disabled event from another node. + * + * @param event OCR enabled/disabled event from another auto ingest node. + */ + private void handleRemoteOcrEvent(AutoIngestOcrStateChangeEvent event) { + switch (event.getEventType()) { + case OCR_ENABLED: + sysLogger.log(Level.INFO, "Received OCR enabled event for case {0} from user {1} on machine {2}", + new Object[]{event.getCaseName(), event.getUserName(), event.getNodeName()}); + break; + case OCR_DISABLED: + sysLogger.log(Level.INFO, "Received OCR disabled event for case {0} from user {1} on machine {2}", + new Object[]{event.getCaseName(), event.getUserName(), event.getNodeName()}); + break; + default: + sysLogger.log(Level.WARNING, "Received invalid OCR enabled/disabled event from user {0} on machine {1}", + new Object[]{event.getUserName(), event.getNodeName()}); + break; + } + + String hostName = event.getNodeName(); + hostNamesToLastMsgTime.put(hostName, Instant.now()); + + // currently the only way to the get latest ZK manifest node contents is to do an input directory scan + scanInputDirsNow(); + + setChanged(); + notifyObservers(Event.OCR_STATE_CHANGE); + } /** * Processes a case deletion event from another node by triggering an @@ -1123,7 +1159,6 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen private final List newPendingJobsList = new ArrayList<>(); private final List newCompletedJobsList = new ArrayList<>(); - private Lock currentDirLock; /** * Searches the input directories for manifest files. The search results @@ -1131,27 +1166,29 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen * list. */ private void scan() { - synchronized (jobsLock) { - if (Thread.currentThread().isInterrupted()) { - return; - } - try { - newPendingJobsList.clear(); - newCompletedJobsList.clear(); - Files.walkFileTree(rootInputDirectory, EnumSet.of(FOLLOW_LINKS), Integer.MAX_VALUE, this); - Collections.sort(newPendingJobsList); + + if (Thread.currentThread().isInterrupted()) { + return; + } + try { + newPendingJobsList.clear(); + newCompletedJobsList.clear(); + Files.walkFileTree(rootInputDirectory, EnumSet.of(FOLLOW_LINKS), Integer.MAX_VALUE, this); + Collections.sort(newPendingJobsList); + synchronized (jobsLock) { AutoIngestManager.this.pendingJobs = newPendingJobsList; AutoIngestManager.this.completedJobs = newCompletedJobsList; - - } catch (Exception ex) { - /* - * NOTE: Need to catch all unhandled exceptions here. - * Otherwise uncaught exceptions will propagate up to the - * calling thread and may stop it from running. - */ - sysLogger.log(Level.SEVERE, String.format("Error scanning the input directory %s", rootInputDirectory), ex); } + + } catch (Exception ex) { + /* + * NOTE: Need to catch all unhandled exceptions here. Otherwise + * uncaught exceptions will propagate up to the calling thread + * and may stop it from running. + */ + sysLogger.log(Level.SEVERE, String.format("Error scanning the input directory %s", rootInputDirectory), ex); } + synchronized (scanMonitor) { scanMonitor.notify(); } @@ -2056,10 +2093,11 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen } iterator.remove(); - currentJob = job; + // create a new job object based on latest ZK node data (i.e. instead of re-using potentially stale local pending AutoIngestJob object). + currentJob = new AutoIngestJob(nodeData); break; - } catch (AutoIngestJobNodeData.InvalidDataException ex) { + } catch (AutoIngestJobNodeData.InvalidDataException | AutoIngestJobException ex) { sysLogger.log(Level.WARNING, String.format("Unable to use node data for %s", manifestPath), ex); } } @@ -2214,21 +2252,20 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen * auto ingest job. */ private void attemptJob() throws CoordinationServiceException, SharedConfigurationException, ServicesMonitorException, DatabaseServerDownException, KeywordSearchServerDownException, CaseManagementException, AnalysisStartupException, FileExportException, AutoIngestJobLoggerException, InterruptedException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException, IOException, JobMetricsCollectionException { - updateConfiguration(); - if (currentJob.isCanceled() || jobProcessingTaskFuture.isCancelled()) { - return; - } verifyRequiredSevicesAreRunning(); if (currentJob.isCanceled() || jobProcessingTaskFuture.isCancelled()) { return; } Case caseForJob = openCase(); try { + if (currentJob.isCanceled() || jobProcessingTaskFuture.isCancelled()) { + return; + } + updateConfiguration(); if (currentJob.isCanceled() || jobProcessingTaskFuture.isCancelled()) { return; } runIngestForJob(caseForJob); - } finally { try { Case.closeCurrentCase(); @@ -2241,7 +2278,8 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen /** * Updates the ingest system settings by downloading the latest version - * of the settings if using shared configuration. + * of the settings if using shared configuration. Also updates the OCR + * setting. * * @throws SharedConfigurationException if there is an error downloading * shared configuration. @@ -2706,7 +2744,8 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen sysLogger.log(Level.WARNING, "Cancellation while waiting for data source processor for {0}", manifestPath); jobLogger.logDataSourceProcessorCancelled(); } - } + } + /** * Analyzes the data source content returned by the data source @@ -2751,6 +2790,20 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen throw new AnalysisStartupException("Error(s) in ingest job settings"); } + // update the OCR enabled/disabled setting + if (currentJob.getOcrEnabled()) { + sysLogger.log(Level.INFO, "Enabling OCR for job {0}", currentJob.getManifest().getFilePath()); + } else { + sysLogger.log(Level.INFO, "Disabling OCR for job {0}", currentJob.getManifest().getFilePath()); + } + + // find the KeywordSearchJobSettings instance in the templates, and if present, set ocr enabled + ingestJobSettings.getIngestModuleTemplates().stream() + .filter(template -> template.getModuleSettings() instanceof KeywordSearchJobSettings) + .map(template -> (KeywordSearchJobSettings) template.getModuleSettings()) + .findFirst() + .ifPresent((keywordJobSettings) -> keywordJobSettings.setOCREnabled(currentJob.getOcrEnabled())); + ingestJobStartResult = IngestManager.getInstance().beginIngestJob(dataSource.getContent(), ingestJobSettings); ingestJob = ingestJobStartResult.getJob(); @@ -2814,6 +2867,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen currentJob.setIngestJob(null); } } + /** * Gather metrics to store in auto ingest job nodes. A SleuthkitCase @@ -3150,7 +3204,8 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen REPORT_STATE, CANCEL_JOB, REPROCESS_JOB, - GENERATE_THREAD_DUMP_RESPONSE + GENERATE_THREAD_DUMP_RESPONSE, + OCR_STATE_CHANGE } /** diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java index fbca3f50ee..0022cf6609 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMonitor.java @@ -84,7 +84,8 @@ final class AutoIngestMonitor extends Observable implements PropertyChangeListen AutoIngestManager.Event.SHUTTING_DOWN.toString(), AutoIngestManager.Event.SHUTDOWN.toString(), AutoIngestManager.Event.RESUMED.toString(), - AutoIngestManager.Event.GENERATE_THREAD_DUMP_RESPONSE.toString()})); + AutoIngestManager.Event.GENERATE_THREAD_DUMP_RESPONSE.toString(), + AutoIngestManager.Event.OCR_STATE_CHANGE.toString()})); private final AutopsyEventPublisher eventPublisher; private CoordinationService coordinationService; private final ScheduledThreadPoolExecutor coordSvcQueryExecutor; @@ -166,6 +167,8 @@ final class AutoIngestMonitor extends Observable implements PropertyChangeListen handleAutoIngestNodeStateEvent((AutoIngestNodeStateEvent) event); } else if (event instanceof ThreadDumpResponseEvent) { handleRemoteThreadDumpResponseEvent((ThreadDumpResponseEvent) event); + } else if (event instanceof AutoIngestOcrStateChangeEvent) { + handleOcrStateChangeEvent((AutoIngestOcrStateChangeEvent) event); } } @@ -228,6 +231,15 @@ final class AutoIngestMonitor extends Observable implements PropertyChangeListen } } + /** + * Handles an OCR state change event. + * + * @param event OCR state change event. + */ + private void handleOcrStateChangeEvent(AutoIngestOcrStateChangeEvent event) { + coordSvcQueryExecutor.submit(new StateRefreshTask()); + } + /** * Handles an auto ingest job/case prioritization event. * @@ -427,6 +439,51 @@ final class AutoIngestMonitor extends Observable implements PropertyChangeListen return new JobsSnapshot(); } } + + /** + * Enables OCR for all pending ingest jobs for a specified case. + * + * @param caseName The name of the case to enable OCR. + * + * @throws AutoIngestMonitorException If there is an error enabling OCR for the jobs for the case. + * + */ + void changeOcrStateForCase(final String caseName, final boolean ocrState) throws AutoIngestMonitorException { + List jobsToPrioritize = new ArrayList<>(); + synchronized (jobsLock) { + for (AutoIngestJob pendingJob : getPendingJobs()) { + if (pendingJob.getManifest().getCaseName().equals(caseName)) { + jobsToPrioritize.add(pendingJob); + } + } + if (!jobsToPrioritize.isEmpty()) { + for (AutoIngestJob job : jobsToPrioritize) { + String manifestNodePath = job.getManifest().getFilePath().toString(); + try { + AutoIngestJobNodeData nodeData = new AutoIngestJobNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestNodePath)); + nodeData.setOcrEnabled(ocrState); + coordinationService.setNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestNodePath, nodeData.toArray()); + } catch (AutoIngestJobNodeData.InvalidDataException | CoordinationServiceException | InterruptedException ex) { + throw new AutoIngestMonitorException("Error enabling OCR for job " + job.toString(), ex); + } + job.setOcrEnabled(ocrState); + + /** + * Update job object in pending jobs queue + */ + jobsSnapshot.addOrReplacePendingJob(job); + } + + /* + * Publish the OCR enabled event. + */ + new Thread(() -> { + eventPublisher.publishRemotely(new AutoIngestOcrStateChangeEvent(LOCAL_HOST_NAME, caseName, + AutoIngestManager.getSystemUserNameProperty(), ocrState)); + }).start(); + } + } + } /** * Removes the priority (set to zero) of all pending ingest jobs for a diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestNodeRefreshEvents.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestNodeRefreshEvents.java index 338bce31c7..be7cc2408f 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestNodeRefreshEvents.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestNodeRefreshEvents.java @@ -69,7 +69,7 @@ class AutoIngestNodeRefreshEvents { private final String caseName; /** - * Contructs a RefreshCaseEvent + * Constructs a RefreshCaseEvent * * @param monitor The monitor that will provide access to the current state of the jobs lists. * @param name The name of the case whose nodes should be refreshed. diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestOcrStateChangeEvent.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestOcrStateChangeEvent.java new file mode 100755 index 0000000000..682ad711eb --- /dev/null +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestOcrStateChangeEvent.java @@ -0,0 +1,99 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2021 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may 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.experimental.autoingest; + +import java.io.Serializable; +import org.sleuthkit.autopsy.events.AutopsyEvent; + +/** + * Event published when an automated ingest manager enables or disables OCR on a case. + */ +public final class AutoIngestOcrStateChangeEvent extends AutopsyEvent implements Serializable { + + /** + * Possible event types + */ + enum EventType { + OCR_ENABLED, + OCR_DISABLED + } + + private static final long serialVersionUID = 1L; + private final String caseName; + private final String nodeName; + private final String userName; + private final EventType eventType; + + /** + * Constructs an event published when an automated ingest manager + * enables or disables OCR on a case. + * + * @param caseName The name of the case. + * @param nodeName The host name of the node that enabled/disabled OCR. + * @param userName The logged in user + * @param ocrState Flag whether OCR is enabled/disabled + */ + public AutoIngestOcrStateChangeEvent(String nodeName, String caseName, String userName, boolean ocrState) { + super(AutoIngestManager.Event.OCR_STATE_CHANGE.toString(), null, null); + this.caseName = caseName; + this.nodeName = nodeName; + this.userName = userName; + if (ocrState == true) { + this.eventType = EventType.OCR_ENABLED; + } else { + this.eventType = EventType.OCR_DISABLED; + } + } + + /** + * Gets the name of the prioritized case. + * + * @return The case name. + */ + public String getCaseName() { + return caseName; + } + + /** + * Gets the host name of the node that prioritized the case. + * + * @return The host name of the node. + */ + public String getNodeName() { + return nodeName; + } + + /** + * Gets the user logged in to the node that prioritized the case. + * + * @return The user name + */ + String getUserName() { + return userName; + } + + /** + * Gets the type of prioritization + * + * @return The type + */ + EventType getEventType() { + return eventType; + } +} diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutopsyManifestFileParser.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutopsyManifestFileParser.java index 99462f8084..908eaba500 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutopsyManifestFileParser.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutopsyManifestFileParser.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2015-2020 Basis Technology Corp. + * Copyright 2015-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,7 +19,6 @@ package org.sleuthkit.autopsy.experimental.autoingest; import java.io.BufferedReader; -import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.nio.file.Files; @@ -28,18 +27,16 @@ import java.nio.file.attribute.BasicFileAttributes; import java.util.Date; import java.util.HashMap; import java.util.UUID; +import java.util.logging.Level; import javax.annotation.concurrent.Immutable; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathFactory; import org.openide.util.lookup.ServiceProvider; +import org.sleuthkit.autopsy.coreutils.Logger; import org.w3c.dom.Document; import org.w3c.dom.Element; -import org.xml.sax.SAXException; @Immutable @ServiceProvider(service = ManifestFileParser.class) @@ -50,6 +47,7 @@ public final class AutopsyManifestFileParser implements ManifestFileParser { private static final String CASE_NAME_XPATH = "/AutopsyManifest/CaseName/text()"; private static final String DEVICE_ID_XPATH = "/AutopsyManifest/DeviceId/text()"; private static final String DATA_SOURCE_NAME_XPATH = "/AutopsyManifest/DataSource/text()"; + private static final Logger logger = Logger.getLogger(AutopsyManifestFileParser.class.getName()); @Override public boolean fileIsManifest(Path filePath) { @@ -78,6 +76,7 @@ public final class AutopsyManifestFileParser implements ManifestFileParser { } catch (Exception ex) { // If the above call to createManifestDOM threw an exception // try to fix the given XML file. + logger.log(Level.WARNING, String.format("Failed to create DOM for manifest at %s, attempting repair", filePath), ex); tempPath = ManifestFileParser.makeTidyManifestFile(filePath); doc = ManifestFileParser.createManifestDOM(tempPath); } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties-MERGED b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties-MERGED index d74f98b5a7..2a1e361537 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties-MERGED +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties-MERGED @@ -10,6 +10,10 @@ AinStatusNode.status.title=Status AinStatusNode.status.unknown=Unknown AutoIngestAdminActions.cancelJobAction.title=Cancel Job AutoIngestAdminActions.cancelModuleAction.title=Cancel Module +AutoIngestAdminActions.disableOCR.error=Failed to disable OCR for case "%s". +AutoIngestAdminActions.disableOCR.title=Disable OCR For This Case +AutoIngestAdminActions.enableOCR.error=Failed to enable OCR for case "%s". +AutoIngestAdminActions.enableOCR.title=Enable OCR For This Case AutoIngestAdminActions.getThreadDump.title=Generate Thread Dump AutoIngestAdminActions.pause.title=Pause Node AutoIngestAdminActions.progressDialogAction.title=Ingest Progress @@ -71,6 +75,7 @@ AutoIngestControlPanel.JobsTableModel.ColumnHeader.HostName=Host Name AutoIngestControlPanel.JobsTableModel.ColumnHeader.ImageFolder=Data Source AutoIngestControlPanel.JobsTableModel.ColumnHeader.LocalJob=\ Local Job? AutoIngestControlPanel.JobsTableModel.ColumnHeader.ManifestFilePath=\ Manifest File Path +AutoIngestControlPanel.JobsTableModel.ColumnHeader.OCR=OCR AutoIngestControlPanel.JobsTableModel.ColumnHeader.Priority=Prioritized AutoIngestControlPanel.JobsTableModel.ColumnHeader.Stage=Stage AutoIngestControlPanel.JobsTableModel.ColumnHeader.StageTime=Time in Stage @@ -130,6 +135,7 @@ AutoIngestJobsNode.dataSource.text=Data Source AutoIngestJobsNode.hostName.text=Host Name AutoIngestJobsNode.jobCompleted.text=Job Completed AutoIngestJobsNode.jobCreated.text=Job Created +AutoIngestJobsNode.ocr.text=OCR AutoIngestJobsNode.prioritized.false=No AutoIngestJobsNode.prioritized.true=Yes AutoIngestJobsNode.priority.text=Prioritized @@ -222,6 +228,8 @@ DeleteOrphanManifestNodesTask.progress.gettingManifestNodes=Querying the coordin DeleteOrphanManifestNodesTask.progress.lookingForOrphanedManifestFileZnodes=Looking for orphaned manifest file znodes DeleteOrphanManifestNodesTask.progress.startMessage=Starting orphaned manifest file znode cleanup HINT_CasesDashboardTopComponent=This is an adminstrative dashboard for multi-user cases +OcrIconCellRenderer.disabled.tooltiptext=This job does not have OCR enabled. +OcrIconCellRenderer.enabled.tooltiptext=This job has OCR enabled. OpenAutoIngestLogAction.deletedLogErrorMsg=The case auto ingest log has been deleted. OpenAutoIngestLogAction.logOpenFailedErrorMsg=Failed to open case auto ingest log. See application log for details. OpenAutoIngestLogAction.menuItemText=Open Auto Ingest Log File @@ -331,7 +339,7 @@ PrioritizationAction.deprioritizeCaseAction.error=Failed to deprioritize case "% PrioritizationAction.deprioritizeCaseAction.title=Deprioritize Case PrioritizationAction.deprioritizeJobAction.error=Failed to deprioritize job "%s". PrioritizationAction.deprioritizeJobAction.title=Deprioritize Job -PrioritizationAction.prioritizeCaseAction.error==Failed to prioritize case "%s". +PrioritizationAction.prioritizeCaseAction.error=Failed to prioritize case "%s". PrioritizationAction.prioritizeCaseAction.title=Prioritize Case PrioritizationAction.prioritizeJobAction.error=Failed to prioritize job "%s". PrioritizationAction.prioritizeJobAction.title=Prioritize Job diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle_ja.properties b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle_ja.properties index d751c3ed40..713caaf730 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle_ja.properties +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle_ja.properties @@ -1,7 +1,17 @@ -#Fri Feb 12 16:56:29 UTC 2021 +#Thu Jul 01 11:56:41 UTC 2021 +AutoIngestAdminActions.disableOCR.error=\u30b1\u30fc\u30b9 "\uff05s"\u306eOCR\u3092\u7121\u52b9\u306b\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +AutoIngestAdminActions.disableOCR.title=\u3053\u306e\u30b1\u30fc\u30b9\u3067\u306fOCR\u3092\u7121\u52b9\u53ef +AutoIngestAdminActions.enableOCR.error=\u30b1\u30fc\u30b9 "\uff05s"\u306eOCR\u3092\u6709\u52b9\u306b\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +AutoIngestAdminActions.enableOCR.title=\u3053\u306e\u30b1\u30fc\u30b9\u3067OCR\u3092\u6709\u52b9\u306b\u3059\u308b +AutoIngestAdminActions.getThreadDump.title=\u30b9\u30ec\u30c3\u30c9\u30c0\u30f3\u30d7\u306e\u751f\u6210 +AutoIngestControlPanel.JobsTableModel.ColumnHeader.OCR=OCR +AutoIngestJobsNode.ocr.text=OCR DeleteOrphanCaseNodesDialog.additionalInit.lblNodeCount.text=\u898b\u3064\u304b\u3063\u305fZnodes\uff1a{0} DeleteOrphanCaseNodesDialog.additionalInit.znodesTextArea.countMessage=\u898b\u3064\u304b\u3063\u305fZNODES\uff1a{0} DeleteOrphanCaseNodesDialog.cancelButton.text=\u30ad\u30e3\u30f3\u30bb\u30eb DeleteOrphanCaseNodesDialog.descriptionText.text=\u6b21\u306e\u30b1\u30fc\u30b9\u3067\u306f\u3001\u5b64\u7acb\u3057\u305fznode\u304c\u3042\u308a\u307e\u3059\u3002 \u305d\u308c\u3089\u3092\u524a\u9664\u3057\u307e\u3059\u304b\uff1f DeleteOrphanCaseNodesDialog.okButton.text=OK DeleteOrphanCaseNodesDialog.titleText.text=\u6b21\u306eZnode\u3092\u524a\u9664\u3057\u307e\u3059\u304b\uff1f +OcrIconCellRenderer.disabled.tooltiptext=\u3053\u306e\u30b8\u30e7\u30d6\u3067\u306fOCR\u304c\u6709\u52b9\u306b\u306a\u3063\u3066\u3044\u307e\u305b\u3093\u3002 +OcrIconCellRenderer.enabled.tooltiptext=\u3053\u306e\u30b8\u30e7\u30d6\u3067\u306fOCR\u304c\u6709\u52b9\u306b\u306a\u3063\u3066\u3044\u307e\u3059\u3002 +PrioritizationAction.prioritizeCaseAction.error=\u30b1\u30fc\u30b9\u300c\uff05s\u300d\u306e\u512a\u5148\u9806\u4f4d\u4ed8\u3051\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/OcrIconCellRenderer.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/OcrIconCellRenderer.java new file mode 100755 index 0000000000..e90754adf8 --- /dev/null +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/OcrIconCellRenderer.java @@ -0,0 +1,72 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2021 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may 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.experimental.autoingest; + +import java.awt.Component; +import java.lang.reflect.InvocationTargetException; +import javax.swing.ImageIcon; +import javax.swing.JTable; +import static javax.swing.SwingConstants.CENTER; +import org.openide.nodes.Node; +import org.openide.util.ImageUtilities; +import org.openide.util.NbBundle.Messages; +import org.sleuthkit.autopsy.guiutils.GrayableCellRenderer; +import org.sleuthkit.autopsy.datamodel.NodeProperty; + +/** + * A JTable and Outline view cell renderer that represents whether OCR is enabled for the job. + */ +class OcrIconCellRenderer extends GrayableCellRenderer { + + @Messages({ + "OcrIconCellRenderer.enabled.tooltiptext=This job has OCR enabled.", + "OcrIconCellRenderer.disabled.tooltiptext=This job does not have OCR enabled." + }) + private static final long serialVersionUID = 1L; + static final ImageIcon checkedIcon = new ImageIcon(ImageUtilities.loadImage("org/sleuthkit/autopsy/experimental/images/tick.png", false)); + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + setHorizontalAlignment(CENTER); + Object switchValue = null; + if ((value instanceof NodeProperty)) { + //The Outline view has properties in the cell, the value contained in the property is what we want + try { + switchValue = ((Node.Property) value).getValue(); + } catch (IllegalAccessException | InvocationTargetException ignored) { + //Unable to get the value from the NodeProperty no Icon will be displayed + } + } else { + //JTables contain the value we want directly in the cell + switchValue = value; + } + if (switchValue instanceof Boolean && (boolean) switchValue == true) { + setIcon(checkedIcon); + setToolTipText(org.openide.util.NbBundle.getMessage(OcrIconCellRenderer.class, "OcrIconCellRenderer.enabled.tooltiptext")); + } else { + setIcon(null); + if (switchValue instanceof Boolean) { + setToolTipText(org.openide.util.NbBundle.getMessage(OcrIconCellRenderer.class, "OcrIconCellRenderer.disabled.tooltiptext")); + } + } + grayCellIfTableNotEnabled(table, isSelected); + + return this; + } +} diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PrioritizationAction.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PrioritizationAction.java index 006dc3e580..97ad2cee63 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PrioritizationAction.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PrioritizationAction.java @@ -193,7 +193,7 @@ abstract class PrioritizationAction extends AbstractAction { * AutoIngestJob is a part of. */ @Messages({"PrioritizationAction.prioritizeCaseAction.title=Prioritize Case", - "PrioritizationAction.prioritizeCaseAction.error==Failed to prioritize case \"%s\"."}) + "PrioritizationAction.prioritizeCaseAction.error=Failed to prioritize case \"%s\"."}) static final class PrioritizeCaseAction extends PrioritizationAction { private static final long serialVersionUID = 1L; diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/AdvancedAutoIngestSettingsPanel.form b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/AdvancedAutoIngestSettingsPanel.form index 62091cea6f..6f00016f30 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/AdvancedAutoIngestSettingsPanel.form +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/AdvancedAutoIngestSettingsPanel.form @@ -11,43 +11,20 @@ + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + @@ -80,111 +57,13 @@ + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -195,6 +74,11 @@ + + + + + @@ -205,6 +89,11 @@ + + + + + @@ -215,6 +104,11 @@ + + + + + @@ -225,6 +119,11 @@ + + + + + @@ -235,6 +134,15 @@ + + + + + + + + + @@ -245,6 +153,15 @@ + + + + + + + + + @@ -259,6 +176,11 @@ + + + + + @@ -275,6 +197,11 @@ + + + + + @@ -285,6 +212,15 @@ + + + + + + + + + @@ -295,6 +231,11 @@ + + + + + @@ -310,6 +251,11 @@ + + + + + @@ -320,6 +266,11 @@ + + + + + @@ -330,6 +281,11 @@ + + + + + @@ -340,6 +296,11 @@ + + + + + @@ -347,6 +308,11 @@ + + + + + @@ -357,6 +323,11 @@ + + + + + @@ -367,6 +338,171 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/AdvancedAutoIngestSettingsPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/AdvancedAutoIngestSettingsPanel.java index 2ba02bdb99..3ea27b506b 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/AdvancedAutoIngestSettingsPanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/AdvancedAutoIngestSettingsPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2015-2018 Basis Technology Corp. + * Copyright 2015-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,8 +18,16 @@ */ package org.sleuthkit.autopsy.experimental.configuration; +import java.awt.Component; +import java.time.DayOfWeek; import javax.swing.DefaultComboBoxModel; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.ListCellRenderer; +import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.core.UserPreferences; +import org.sleuthkit.autopsy.ingest.ScheduledIngestPauseSettings; /** * Configuration panel for advanced settings, such as number of concurrent jobs, @@ -29,9 +37,17 @@ import org.sleuthkit.autopsy.core.UserPreferences; class AdvancedAutoIngestSettingsPanel extends javax.swing.JPanel { private static final long serialVersionUID = 1L; + private final DefaultComboBoxModel cbModel = new DefaultComboBoxModel<>(); AdvancedAutoIngestSettingsPanel(AutoIngestSettingsPanel.OptionsUiMode mode) { initComponents(); + // Set up the combo box model before calling load. + for (DayOfWeek day : DayOfWeek.values()) { + cbModel.addElement(day); + } + cbPauseDay.setModel(cbModel); + cbPauseDay.setRenderer(new DayOfTheWeekRenderer()); + tbWarning.setLineWrap(true); tbWarning.setWrapStyleWord(true); load(mode); @@ -78,6 +94,12 @@ class AdvancedAutoIngestSettingsPanel extends javax.swing.JPanel { int timeOutHrs = UserPreferences.getProcessTimeOutHrs(); spTimeoutHours.setValue(timeOutHrs); setCheckboxEnabledState(); + + setPauseEnabled(ScheduledIngestPauseSettings.getPauseEnabled()); + spPauseStartHour.setValue(ScheduledIngestPauseSettings.getPauseStartTimeHour()); + spPauseStartMinutes.setValue(ScheduledIngestPauseSettings.getPauseStartTimeMinute()); + spDuration.setValue(ScheduledIngestPauseSettings.getPauseDurationMinutes() / 60); + cbPauseDay.setSelectedItem(ScheduledIngestPauseSettings.getPauseDayOfWeek()); } void store() { @@ -93,6 +115,12 @@ class AdvancedAutoIngestSettingsPanel extends javax.swing.JPanel { int timeOutHrs = (int) spTimeoutHours.getValue(); UserPreferences.setProcessTimeOutHrs(timeOutHrs); } + + ScheduledIngestPauseSettings.setPauseEnabled(cbEnablePause.isSelected()); + ScheduledIngestPauseSettings.setPauseDayOfWeek((DayOfWeek) cbPauseDay.getSelectedItem()); + ScheduledIngestPauseSettings.setPauseStartTimeMinute((int) spPauseStartMinutes.getValue()); + ScheduledIngestPauseSettings.setPauseStartTimeHour((int) spPauseStartHour.getValue()); + ScheduledIngestPauseSettings.setPauseDurationMinutes((int) spDuration.getValue() * 60); } private void setCheckboxEnabledState() { @@ -106,6 +134,77 @@ class AdvancedAutoIngestSettingsPanel extends javax.swing.JPanel { } } + private void setPauseEnabled(boolean enabled) { + cbEnablePause.setSelected(enabled); + spPauseStartMinutes.setEnabled(enabled); + spPauseStartHour.setEnabled(enabled); + spDuration.setEnabled(enabled); + lbpauseDay.setEnabled(enabled); + lbDurationHours.setEnabled(enabled); + lbPauseDuration.setEnabled(enabled); + lbPauseTime.setEnabled(enabled); + cbPauseDay.setEnabled(enabled); + } + + @Messages({ + "DayOfTheWeekRenderer_Monday_Label=Monday", + "DayOfTheWeekRenderer_Tuesday_Label=Tuesday", + "DayOfTheWeekRenderer_Wednesday_Label=Wednesday", + "DayOfTheWeekRenderer_Thursday_Label=Thursday", + "DayOfTheWeekRenderer_Friday_Label=Friday", + "DayOfTheWeekRenderer_Saturday_Label=Saturday", + "DayOfTheWeekRenderer_Sunday_Label=Sunday",}) + /** + * Renderer for the Day of the week combo box. + */ + private final class DayOfTheWeekRenderer implements ListCellRenderer { + + private final ListCellRenderer delegate; + + /** + * Construct a new Renderer. + */ + DayOfTheWeekRenderer() { + JComboBox cb = new JComboBox<>(); + delegate = cb.getRenderer(); + } + + @Override + public Component getListCellRendererComponent(JList list, DayOfWeek value, int index, boolean isSelected, boolean cellHasFocus) { + Component comp = delegate.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + + String text = ""; + if (value != null) { + text = value.toString(); + switch (value) { + case MONDAY: + text = Bundle.DayOfTheWeekRenderer_Monday_Label(); + break; + case TUESDAY: + text = Bundle.DayOfTheWeekRenderer_Tuesday_Label(); + break; + case WEDNESDAY: + text = Bundle.DayOfTheWeekRenderer_Wednesday_Label(); + break; + case THURSDAY: + text = Bundle.DayOfTheWeekRenderer_Thursday_Label(); + break; + case FRIDAY: + text = Bundle.DayOfTheWeekRenderer_Friday_Label(); + break; + case SATURDAY: + text = Bundle.DayOfTheWeekRenderer_Saturday_Label(); + break; + case SUNDAY: + text = Bundle.DayOfTheWeekRenderer_Sunday_Label(); + break; + } + } + ((JLabel) comp).setText(text); + return comp; + } + } + /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always @@ -114,6 +213,7 @@ class AdvancedAutoIngestSettingsPanel extends javax.swing.JPanel { @SuppressWarnings("unchecked") // //GEN-BEGIN:initComponents private void initComponents() { + java.awt.GridBagConstraints gridBagConstraints; spMainScrollPane = new javax.swing.JScrollPane(); tbWarning = new javax.swing.JTextArea(); @@ -122,11 +222,11 @@ class AdvancedAutoIngestSettingsPanel extends javax.swing.JPanel { lbTimeoutText = new javax.swing.JLabel(); lbInputScanInterval = new javax.swing.JLabel(); lbRetriesAllowed = new javax.swing.JLabel(); - lbNumberOfThreads = new javax.swing.JLabel(); - lbConcurrentJobsPerCase = new javax.swing.JLabel(); + javax.swing.JLabel lbNumberOfThreads = new javax.swing.JLabel(); + javax.swing.JLabel lbConcurrentJobsPerCase = new javax.swing.JLabel(); cbTimeoutEnabled = new javax.swing.JCheckBox(); numberOfFileIngestThreadsComboBox = new javax.swing.JComboBox<>(); - lbRestartRequired = new javax.swing.JLabel(); + javax.swing.JLabel lbRestartRequired = new javax.swing.JLabel(); spConcurrentJobsPerCase = new javax.swing.JSpinner(); spMaximumRetryAttempts = new javax.swing.JSpinner(); spInputScanInterval = new javax.swing.JSpinner(); @@ -135,6 +235,20 @@ class AdvancedAutoIngestSettingsPanel extends javax.swing.JPanel { lbSecondsBetweenJobsSeconds = new javax.swing.JLabel(); lbTimeoutHours = new javax.swing.JLabel(); lbInputScanIntervalMinutes = new javax.swing.JLabel(); + pausePanel = new javax.swing.JPanel(); + lbpauseDay = new javax.swing.JLabel(); + lbPauseTime = new javax.swing.JLabel(); + lbPauseDuration = new javax.swing.JLabel(); + cbPauseDay = new javax.swing.JComboBox<>(); + spPauseStartHour = new javax.swing.JSpinner(); + javax.swing.JLabel lbColon = new javax.swing.JLabel(); + spPauseStartMinutes = new javax.swing.JSpinner(); + spDuration = new javax.swing.JSpinner(); + lbDurationHours = new javax.swing.JLabel(); + cbEnablePause = new javax.swing.JCheckBox(); + filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 32767)); + + setLayout(new java.awt.GridBagLayout()); tbWarning.setEditable(false); tbWarning.setColumns(20); @@ -144,26 +258,74 @@ class AdvancedAutoIngestSettingsPanel extends javax.swing.JPanel { tbWarning.setAutoscrolls(false); spMainScrollPane.setViewportView(tbWarning); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 0; + gridBagConstraints.gridwidth = 2; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + gridBagConstraints.insets = new java.awt.Insets(10, 16, 0, 16); + add(spMainScrollPane, gridBagConstraints); + jPanelAutoIngestJobSettings.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(AdvancedAutoIngestSettingsPanel.class, "AdvancedAutoIngestSettingsPanel.jPanelAutoIngestJobSettings.border.title"))); // NOI18N jPanelAutoIngestJobSettings.setName("Automated Ingest Job Settings"); // NOI18N + jPanelAutoIngestJobSettings.setLayout(new java.awt.GridBagLayout()); org.openide.awt.Mnemonics.setLocalizedText(lbSecondsBetweenJobs, org.openide.util.NbBundle.getMessage(AdvancedAutoIngestSettingsPanel.class, "AdvancedAutoIngestSettingsPanel.lbSecondsBetweenJobs.text")); // NOI18N lbSecondsBetweenJobs.setToolTipText(org.openide.util.NbBundle.getMessage(AdvancedAutoIngestSettingsPanel.class, "AdvancedAutoIngestSettingsPanel.lbSecondsBetweenJobs.toolTipText_1")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 0; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.insets = new java.awt.Insets(10, 0, 5, 0); + jPanelAutoIngestJobSettings.add(lbSecondsBetweenJobs, gridBagConstraints); org.openide.awt.Mnemonics.setLocalizedText(lbTimeoutText, org.openide.util.NbBundle.getMessage(AdvancedAutoIngestSettingsPanel.class, "AdvancedAutoIngestSettingsPanel.lbTimeoutText.text")); // NOI18N lbTimeoutText.setToolTipText(org.openide.util.NbBundle.getMessage(AdvancedAutoIngestSettingsPanel.class, "AdvancedAutoIngestSettingsPanel.lbTimeoutText.toolTipText")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 0); + jPanelAutoIngestJobSettings.add(lbTimeoutText, gridBagConstraints); org.openide.awt.Mnemonics.setLocalizedText(lbInputScanInterval, org.openide.util.NbBundle.getMessage(AdvancedAutoIngestSettingsPanel.class, "AdvancedAutoIngestSettingsPanel.lbInputScanInterval.text")); // NOI18N lbInputScanInterval.setToolTipText(org.openide.util.NbBundle.getMessage(AdvancedAutoIngestSettingsPanel.class, "AdvancedAutoIngestSettingsPanel.lbInputScanInterval.toolTipText_1")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 2; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 0); + jPanelAutoIngestJobSettings.add(lbInputScanInterval, gridBagConstraints); org.openide.awt.Mnemonics.setLocalizedText(lbRetriesAllowed, org.openide.util.NbBundle.getMessage(AdvancedAutoIngestSettingsPanel.class, "AdvancedAutoIngestSettingsPanel.lbRetriesAllowed.text")); // NOI18N lbRetriesAllowed.setToolTipText(org.openide.util.NbBundle.getMessage(AdvancedAutoIngestSettingsPanel.class, "AdvancedAutoIngestSettingsPanel.lbRetriesAllowed.toolTipText_1")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 3; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 0); + jPanelAutoIngestJobSettings.add(lbRetriesAllowed, gridBagConstraints); org.openide.awt.Mnemonics.setLocalizedText(lbNumberOfThreads, org.openide.util.NbBundle.getMessage(AdvancedAutoIngestSettingsPanel.class, "AdvancedAutoIngestSettingsPanel.lbNumberOfThreads.text")); // NOI18N lbNumberOfThreads.setToolTipText(org.openide.util.NbBundle.getMessage(AdvancedAutoIngestSettingsPanel.class, "AdvancedAutoIngestSettingsPanel.lbNumberOfThreads.toolTipText_1")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 5; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 0); + jPanelAutoIngestJobSettings.add(lbNumberOfThreads, gridBagConstraints); org.openide.awt.Mnemonics.setLocalizedText(lbConcurrentJobsPerCase, org.openide.util.NbBundle.getMessage(AdvancedAutoIngestSettingsPanel.class, "AdvancedAutoIngestSettingsPanel.lbConcurrentJobsPerCase.text")); // NOI18N lbConcurrentJobsPerCase.setToolTipText(org.openide.util.NbBundle.getMessage(AdvancedAutoIngestSettingsPanel.class, "AdvancedAutoIngestSettingsPanel.lbConcurrentJobsPerCase.toolTipText_1")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 4; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 0); + jPanelAutoIngestJobSettings.add(lbConcurrentJobsPerCase, gridBagConstraints); org.openide.awt.Mnemonics.setLocalizedText(cbTimeoutEnabled, org.openide.util.NbBundle.getMessage(AdvancedAutoIngestSettingsPanel.class, "AdvancedAutoIngestSettingsPanel.cbTimeoutEnabled.text")); // NOI18N cbTimeoutEnabled.setToolTipText(org.openide.util.NbBundle.getMessage(AdvancedAutoIngestSettingsPanel.class, "AdvancedAutoIngestSettingsPanel.cbTimeoutEnabled.toolTipText")); // NOI18N @@ -177,6 +339,13 @@ class AdvancedAutoIngestSettingsPanel extends javax.swing.JPanel { cbTimeoutEnabledActionPerformed(evt); } }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 0); + jPanelAutoIngestJobSettings.add(cbTimeoutEnabled, gridBagConstraints); numberOfFileIngestThreadsComboBox.setToolTipText(org.openide.util.NbBundle.getMessage(AdvancedAutoIngestSettingsPanel.class, "AdvancedAutoIngestSettingsPanel.numberOfFileIngestThreadsComboBox.toolTipText")); // NOI18N numberOfFileIngestThreadsComboBox.addActionListener(new java.awt.event.ActionListener() { @@ -184,139 +353,213 @@ class AdvancedAutoIngestSettingsPanel extends javax.swing.JPanel { numberOfFileIngestThreadsComboBoxActionPerformed(evt); } }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.gridy = 5; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 0); + jPanelAutoIngestJobSettings.add(numberOfFileIngestThreadsComboBox, gridBagConstraints); lbRestartRequired.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/warning16.png"))); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(lbRestartRequired, org.openide.util.NbBundle.getMessage(AdvancedAutoIngestSettingsPanel.class, "AdvancedAutoIngestSettingsPanel.lbRestartRequired.text")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 9; + gridBagConstraints.gridy = 5; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 0); + jPanelAutoIngestJobSettings.add(lbRestartRequired, gridBagConstraints); spConcurrentJobsPerCase.setModel(new javax.swing.SpinnerNumberModel(3, 1, 100, 1)); spConcurrentJobsPerCase.setToolTipText(org.openide.util.NbBundle.getMessage(AdvancedAutoIngestSettingsPanel.class, "AdvancedAutoIngestSettingsPanel.lbConcurrentJobsPerCase.toolTipText")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.gridy = 4; + gridBagConstraints.ipadx = 43; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 0); + jPanelAutoIngestJobSettings.add(spConcurrentJobsPerCase, gridBagConstraints); spMaximumRetryAttempts.setModel(new javax.swing.SpinnerNumberModel(2, 0, 9999999, 1)); spMaximumRetryAttempts.setToolTipText(org.openide.util.NbBundle.getMessage(AdvancedAutoIngestSettingsPanel.class, "AdvancedAutoIngestSettingsPanel.lbRetriesAllowed.toolTipText_2")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.gridy = 3; + gridBagConstraints.ipadx = -5; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 0); + jPanelAutoIngestJobSettings.add(spMaximumRetryAttempts, gridBagConstraints); + spMaximumRetryAttempts.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(AdvancedAutoIngestSettingsPanel.class, "AdvancedAutoIngestSettingsPanel.spMaximumRetryAttempts.AccessibleContext.accessibleDescription")); // NOI18N spInputScanInterval.setModel(new javax.swing.SpinnerNumberModel(60, 1, 100000, 1)); spInputScanInterval.setToolTipText(org.openide.util.NbBundle.getMessage(AdvancedAutoIngestSettingsPanel.class, "AdvancedAutoIngestSettingsPanel.spInputScanInterval.toolTipText")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.gridy = 2; + gridBagConstraints.ipadx = 11; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 0); + jPanelAutoIngestJobSettings.add(spInputScanInterval, gridBagConstraints); spTimeoutHours.setModel(new javax.swing.SpinnerNumberModel(60, 1, 100000, 1)); spTimeoutHours.setToolTipText(org.openide.util.NbBundle.getMessage(AdvancedAutoIngestSettingsPanel.class, "AdvancedAutoIngestSettingsPanel.spTimeoutHours.toolTipText")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.gridy = 1; + gridBagConstraints.ipadx = 11; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(0, 5, 0, 0); + jPanelAutoIngestJobSettings.add(spTimeoutHours, gridBagConstraints); spSecondsBetweenJobs.setModel(new javax.swing.SpinnerNumberModel(30, 30, 3600, 10)); spSecondsBetweenJobs.setToolTipText(org.openide.util.NbBundle.getMessage(AdvancedAutoIngestSettingsPanel.class, "AdvancedAutoIngestSettingsPanel.spSecondsBetweenJobs.toolTipText")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.gridy = 0; + gridBagConstraints.ipadx = 27; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.insets = new java.awt.Insets(10, 5, 5, 0); + jPanelAutoIngestJobSettings.add(spSecondsBetweenJobs, gridBagConstraints); org.openide.awt.Mnemonics.setLocalizedText(lbSecondsBetweenJobsSeconds, org.openide.util.NbBundle.getMessage(AdvancedAutoIngestSettingsPanel.class, "AdvancedAutoIngestSettingsPanel.lbSecondsBetweenJobsSeconds.text")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 9; + gridBagConstraints.gridy = 0; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(10, 5, 5, 0); + jPanelAutoIngestJobSettings.add(lbSecondsBetweenJobsSeconds, gridBagConstraints); org.openide.awt.Mnemonics.setLocalizedText(lbTimeoutHours, org.openide.util.NbBundle.getMessage(AdvancedAutoIngestSettingsPanel.class, "AdvancedAutoIngestSettingsPanel.lbTimeoutHours.text")); // NOI18N lbTimeoutHours.setToolTipText(org.openide.util.NbBundle.getMessage(AdvancedAutoIngestSettingsPanel.class, "AdvancedAutoIngestSettingsPanel.lbTimeoutHours.toolTipText")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 9; + gridBagConstraints.gridy = 1; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(0, 5, 0, 0); + jPanelAutoIngestJobSettings.add(lbTimeoutHours, gridBagConstraints); org.openide.awt.Mnemonics.setLocalizedText(lbInputScanIntervalMinutes, org.openide.util.NbBundle.getMessage(AdvancedAutoIngestSettingsPanel.class, "AdvancedAutoIngestSettingsPanel.lbInputScanIntervalMinutes.text")); // NOI18N lbInputScanIntervalMinutes.setToolTipText(org.openide.util.NbBundle.getMessage(AdvancedAutoIngestSettingsPanel.class, "AdvancedAutoIngestSettingsPanel.lbInputScanIntervalMinutes.toolTipText")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 9; + gridBagConstraints.gridy = 2; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 0); + jPanelAutoIngestJobSettings.add(lbInputScanIntervalMinutes, gridBagConstraints); - javax.swing.GroupLayout jPanelAutoIngestJobSettingsLayout = new javax.swing.GroupLayout(jPanelAutoIngestJobSettings); - jPanelAutoIngestJobSettings.setLayout(jPanelAutoIngestJobSettingsLayout); - jPanelAutoIngestJobSettingsLayout.setHorizontalGroup( - jPanelAutoIngestJobSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanelAutoIngestJobSettingsLayout.createSequentialGroup() - .addContainerGap() - .addComponent(cbTimeoutEnabled) - .addGap(5, 5, 5) - .addGroup(jPanelAutoIngestJobSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanelAutoIngestJobSettingsLayout.createSequentialGroup() - .addGroup(jPanelAutoIngestJobSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) - .addGroup(jPanelAutoIngestJobSettingsLayout.createSequentialGroup() - .addComponent(lbInputScanInterval) - .addGap(49, 49, 49)) - .addGroup(jPanelAutoIngestJobSettingsLayout.createSequentialGroup() - .addComponent(lbRetriesAllowed) - .addGap(54, 54, 54)) - .addComponent(lbConcurrentJobsPerCase, javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(lbNumberOfThreads, javax.swing.GroupLayout.Alignment.LEADING)) - .addGroup(jPanelAutoIngestJobSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanelAutoIngestJobSettingsLayout.createSequentialGroup() - .addGap(0, 0, Short.MAX_VALUE) - .addGroup(jPanelAutoIngestJobSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(spInputScanInterval, javax.swing.GroupLayout.PREFERRED_SIZE, 90, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(spMaximumRetryAttempts, javax.swing.GroupLayout.PREFERRED_SIZE, 90, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(spConcurrentJobsPerCase, javax.swing.GroupLayout.PREFERRED_SIZE, 90, javax.swing.GroupLayout.PREFERRED_SIZE))) - .addComponent(numberOfFileIngestThreadsComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 91, javax.swing.GroupLayout.PREFERRED_SIZE))) - .addGroup(jPanelAutoIngestJobSettingsLayout.createSequentialGroup() - .addComponent(lbSecondsBetweenJobs) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(spSecondsBetweenJobs, javax.swing.GroupLayout.PREFERRED_SIZE, 90, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanelAutoIngestJobSettingsLayout.createSequentialGroup() - .addComponent(lbTimeoutText) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(spTimeoutHours, javax.swing.GroupLayout.PREFERRED_SIZE, 90, javax.swing.GroupLayout.PREFERRED_SIZE))) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(jPanelAutoIngestJobSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(lbRestartRequired) - .addComponent(lbSecondsBetweenJobsSeconds) - .addComponent(lbTimeoutHours) - .addComponent(lbInputScanIntervalMinutes)) - .addContainerGap(70, Short.MAX_VALUE)) - ); - jPanelAutoIngestJobSettingsLayout.setVerticalGroup( - jPanelAutoIngestJobSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanelAutoIngestJobSettingsLayout.createSequentialGroup() - .addContainerGap() - .addGroup(jPanelAutoIngestJobSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(lbRestartRequired) - .addGroup(jPanelAutoIngestJobSettingsLayout.createSequentialGroup() - .addGroup(jPanelAutoIngestJobSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(lbSecondsBetweenJobs) - .addComponent(spSecondsBetweenJobs, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lbSecondsBetweenJobsSeconds)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(jPanelAutoIngestJobSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanelAutoIngestJobSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(lbTimeoutText) - .addComponent(spTimeoutHours, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lbTimeoutHours)) - .addComponent(cbTimeoutEnabled)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(jPanelAutoIngestJobSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(lbInputScanInterval) - .addComponent(spInputScanInterval, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lbInputScanIntervalMinutes)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(jPanelAutoIngestJobSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(lbRetriesAllowed) - .addComponent(spMaximumRetryAttempts, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(jPanelAutoIngestJobSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(lbConcurrentJobsPerCase) - .addComponent(spConcurrentJobsPerCase, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(jPanelAutoIngestJobSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(lbNumberOfThreads) - .addComponent(numberOfFileIngestThreadsComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - ); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(6, 5, 6, 10); + add(jPanelAutoIngestJobSettings, gridBagConstraints); - spMaximumRetryAttempts.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(AdvancedAutoIngestSettingsPanel.class, "AdvancedAutoIngestSettingsPanel.spMaximumRetryAttempts.AccessibleContext.accessibleDescription")); // NOI18N + pausePanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(AdvancedAutoIngestSettingsPanel.class, "AdvancedAutoIngestSettingsPanel.pausePanel.border.title"))); // NOI18N + pausePanel.setLayout(new java.awt.GridBagLayout()); - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); - this.setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() - .addContainerGap() - .addComponent(jPanelAutoIngestJobSettings, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() - .addGap(16, 16, 16) - .addComponent(spMainScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 640, Short.MAX_VALUE))) - .addGap(16, 16, 16)) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addGap(20, 20, 20) - .addComponent(spMainScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 106, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jPanelAutoIngestJobSettings, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGap(26, 26, 26)) - ); + org.openide.awt.Mnemonics.setLocalizedText(lbpauseDay, org.openide.util.NbBundle.getMessage(AdvancedAutoIngestSettingsPanel.class, "AdvancedAutoIngestSettingsPanel.lbpauseDay.text")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 1; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 0); + pausePanel.add(lbpauseDay, gridBagConstraints); + + org.openide.awt.Mnemonics.setLocalizedText(lbPauseTime, org.openide.util.NbBundle.getMessage(AdvancedAutoIngestSettingsPanel.class, "AdvancedAutoIngestSettingsPanel.lbPauseTime.text")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 2; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 0); + pausePanel.add(lbPauseTime, gridBagConstraints); + + org.openide.awt.Mnemonics.setLocalizedText(lbPauseDuration, org.openide.util.NbBundle.getMessage(AdvancedAutoIngestSettingsPanel.class, "AdvancedAutoIngestSettingsPanel.lbPauseDuration.text")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 3; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 0); + pausePanel.add(lbPauseDuration, gridBagConstraints); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.gridwidth = 3; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 0); + pausePanel.add(cbPauseDay, gridBagConstraints); + + spPauseStartHour.setModel(new javax.swing.SpinnerNumberModel(0, 0, 23, 1)); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 2; + gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 0); + pausePanel.add(spPauseStartHour, gridBagConstraints); + + org.openide.awt.Mnemonics.setLocalizedText(lbColon, org.openide.util.NbBundle.getMessage(AdvancedAutoIngestSettingsPanel.class, "AdvancedAutoIngestSettingsPanel.lbColon.text")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 2; + gridBagConstraints.gridy = 2; + gridBagConstraints.insets = new java.awt.Insets(0, 2, 5, 2); + pausePanel.add(lbColon, gridBagConstraints); + + spPauseStartMinutes.setModel(new javax.swing.SpinnerNumberModel(0, 0, 59, 1)); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 3; + gridBagConstraints.gridy = 2; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 0); + pausePanel.add(spPauseStartMinutes, gridBagConstraints); + + spDuration.setModel(new javax.swing.SpinnerNumberModel(1, 1, null, 1)); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 3; + gridBagConstraints.gridwidth = 3; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 0); + pausePanel.add(spDuration, gridBagConstraints); + + org.openide.awt.Mnemonics.setLocalizedText(lbDurationHours, org.openide.util.NbBundle.getMessage(AdvancedAutoIngestSettingsPanel.class, "AdvancedAutoIngestSettingsPanel.lbDurationHours.text")); // NOI18N + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 4; + gridBagConstraints.gridy = 3; + gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; + gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5); + pausePanel.add(lbDurationHours, gridBagConstraints); + + org.openide.awt.Mnemonics.setLocalizedText(cbEnablePause, org.openide.util.NbBundle.getMessage(AdvancedAutoIngestSettingsPanel.class, "AdvancedAutoIngestSettingsPanel.cbEnablePause.text")); // NOI18N + cbEnablePause.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + cbEnablePauseActionPerformed(evt); + } + }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridwidth = 5; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.insets = new java.awt.Insets(10, 0, 5, 0); + pausePanel.add(cbEnablePause, gridBagConstraints); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 5; + gridBagConstraints.gridwidth = 5; + gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL; + gridBagConstraints.weighty = 1.0; + pausePanel.add(filler1, gridBagConstraints); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints.insets = new java.awt.Insets(6, 10, 6, 0); + add(pausePanel, gridBagConstraints); }// //GEN-END:initComponents private void numberOfFileIngestThreadsComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_numberOfFileIngestThreadsComboBoxActionPerformed @@ -331,24 +574,36 @@ class AdvancedAutoIngestSettingsPanel extends javax.swing.JPanel { setCheckboxEnabledState(); }//GEN-LAST:event_cbTimeoutEnabledItemStateChanged + private void cbEnablePauseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbEnablePauseActionPerformed + setPauseEnabled(cbEnablePause.isSelected()); + }//GEN-LAST:event_cbEnablePauseActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JCheckBox cbEnablePause; + private javax.swing.JComboBox cbPauseDay; private javax.swing.JCheckBox cbTimeoutEnabled; + private javax.swing.Box.Filler filler1; private javax.swing.JPanel jPanelAutoIngestJobSettings; - private javax.swing.JLabel lbConcurrentJobsPerCase; + private javax.swing.JLabel lbDurationHours; private javax.swing.JLabel lbInputScanInterval; private javax.swing.JLabel lbInputScanIntervalMinutes; - private javax.swing.JLabel lbNumberOfThreads; - private javax.swing.JLabel lbRestartRequired; + private javax.swing.JLabel lbPauseDuration; + private javax.swing.JLabel lbPauseTime; private javax.swing.JLabel lbRetriesAllowed; private javax.swing.JLabel lbSecondsBetweenJobs; private javax.swing.JLabel lbSecondsBetweenJobsSeconds; private javax.swing.JLabel lbTimeoutHours; private javax.swing.JLabel lbTimeoutText; + private javax.swing.JLabel lbpauseDay; private javax.swing.JComboBox numberOfFileIngestThreadsComboBox; + private javax.swing.JPanel pausePanel; private javax.swing.JSpinner spConcurrentJobsPerCase; + private javax.swing.JSpinner spDuration; private javax.swing.JSpinner spInputScanInterval; private javax.swing.JScrollPane spMainScrollPane; private javax.swing.JSpinner spMaximumRetryAttempts; + private javax.swing.JSpinner spPauseStartHour; + private javax.swing.JSpinner spPauseStartMinutes; private javax.swing.JSpinner spSecondsBetweenJobs; private javax.swing.JSpinner spTimeoutHours; private javax.swing.JTextArea tbWarning; diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/Bundle.properties b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/Bundle.properties index bf4384ff93..74c645ab82 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/Bundle.properties +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/Bundle.properties @@ -140,3 +140,10 @@ AutoIngestSettingsPanel.bnFileExport.text=File Export Settings AutoIngestSettingsPanel.bnAdvancedSettings.text=Advanced Settings AutoIngestSettingsPanel.bnEditIngestSettings.toolTipText=Ingest job settings for the automated processing mode context. AutoIngestSettingsPanel.bnEditIngestSettings.text=Ingest Module Settings +AdvancedAutoIngestSettingsPanel.pausePanel.border.title=Automated Ingest Pause Settings +AdvancedAutoIngestSettingsPanel.lbpauseDay.text=Day Of Week: +AdvancedAutoIngestSettingsPanel.lbPauseTime.text=Start Time: +AdvancedAutoIngestSettingsPanel.lbPauseDuration.text=Duration: +AdvancedAutoIngestSettingsPanel.lbColon.text=: +AdvancedAutoIngestSettingsPanel.cbEnablePause.text=Enable Pause +AdvancedAutoIngestSettingsPanel.lbDurationHours.text=hours diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/Bundle.properties-MERGED b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/Bundle.properties-MERGED index aabcdf1c23..86fd175181 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/Bundle.properties-MERGED +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/Bundle.properties-MERGED @@ -56,21 +56,24 @@ AutoIngestSettingsPanel.CheckPermissions=Ensure that the user account {0} has wr AutoIngestSettingsPanel.Success=Success AutoIngestSettingsPanel.TestRunning=Test in progress... AutoIngestSettingsPanel.servicesDown=Some of the Multi User services are down +DayOfTheWeekRenderer_Friday_Label=Friday +DayOfTheWeekRenderer_Monday_Label=Monday +DayOfTheWeekRenderer_Saturday_Label=Saturday +DayOfTheWeekRenderer_Sunday_Label=Sunday +DayOfTheWeekRenderer_Thursday_Label=Thursday +DayOfTheWeekRenderer_Tuesday_Label=Tuesday +DayOfTheWeekRenderer_Wednesday_Label=Wednesday GeneralOptionsPanelController.moduleErr.msg=A module caused an error listening to GeneralOptionsPanelController updates. See log to determine which module. Some data could be incomplete. GeneralOptionsPanelController.moduleErr=Module Error -# {0} - errorMessage MultiUserTestTool.criticalError=Critical error running data source processor on test data source: {0} MultiUserTestTool.errorStartingIngestJob=Ingest manager error while starting ingest job -# {0} - cancellationReason MultiUserTestTool.ingestCancelled=Ingest cancelled due to {0} MultiUserTestTool.ingestSettingsError=Failed to analyze data source due to ingest settings errors MultiUserTestTool.noContent=Test data source failed to produce content -# {0} - serviceName MultiUserTestTool.serviceDown=Multi User service is down: {0} MultiUserTestTool.startupError=Failed to analyze data source due to ingest job startup error MultiUserTestTool.unableAddFileAsDataSource=Unable to add test file as data source to case MultiUserTestTool.unableCreatFile=Unable to create a file in case output directory -# {0} - serviceName MultiUserTestTool.unableToCheckService=Unable to check Multi User service state: {0} MultiUserTestTool.unableToCreateCase=Unable to create case MultiUserTestTool.unableToInitializeDatabase=Case database was not successfully initialized @@ -162,3 +165,10 @@ AutoIngestSettingsPanel.bnFileExport.text=File Export Settings AutoIngestSettingsPanel.bnAdvancedSettings.text=Advanced Settings AutoIngestSettingsPanel.bnEditIngestSettings.toolTipText=Ingest job settings for the automated processing mode context. AutoIngestSettingsPanel.bnEditIngestSettings.text=Ingest Module Settings +AdvancedAutoIngestSettingsPanel.pausePanel.border.title=Automated Ingest Pause Settings +AdvancedAutoIngestSettingsPanel.lbpauseDay.text=Day Of Week: +AdvancedAutoIngestSettingsPanel.lbPauseTime.text=Start Time: +AdvancedAutoIngestSettingsPanel.lbPauseDuration.text=Duration: +AdvancedAutoIngestSettingsPanel.lbColon.text=: +AdvancedAutoIngestSettingsPanel.cbEnablePause.text=Enable Pause +AdvancedAutoIngestSettingsPanel.lbDurationHours.text=hours diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/objectdetection/ObjectDetectectionFileIngestModule.java b/Experimental/src/org/sleuthkit/autopsy/experimental/objectdetection/ObjectDetectectionFileIngestModule.java index 1ac5a62d88..08a5be91d3 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/objectdetection/ObjectDetectectionFileIngestModule.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/objectdetection/ObjectDetectectionFileIngestModule.java @@ -47,7 +47,6 @@ import org.sleuthkit.autopsy.ingest.IngestServices; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Blackboard; import org.sleuthkit.datamodel.BlackboardArtifact; -import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_OBJECT_DETECTED; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.Score; import org.sleuthkit.datamodel.TskCoreException; @@ -171,7 +170,7 @@ public class ObjectDetectectionFileIngestModule extends FileIngestModuleAdapter ); BlackboardArtifact artifact = file.newAnalysisResult( - new BlackboardArtifact.Type(TSK_OBJECT_DETECTED), Score.SCORE_UNKNOWN, null, null, null, attributes) + BlackboardArtifact.Type.TSK_OBJECT_DETECTED, Score.SCORE_UNKNOWN, null, null, null, attributes) .getAnalysisResult(); try { diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/volatilityDSP/Bundle_ja.properties b/Experimental/src/org/sleuthkit/autopsy/experimental/volatilityDSP/Bundle_ja.properties new file mode 100644 index 0000000000..ac4a0e8259 --- /dev/null +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/volatilityDSP/Bundle_ja.properties @@ -0,0 +1,3 @@ +#Mon Jun 14 12:23:19 UTC 2021 +MemoryDSInputPanel.deselectAllButton.text=\u5168\u9078\u629e\u3092\u30af\u30ea\u30a2 +MemoryDSInputPanel.selectAllButton.text=\u3059\u3079\u3066\u9078\u629e diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/volatilityDSP/VolatilityProcessor.java b/Experimental/src/org/sleuthkit/autopsy/experimental/volatilityDSP/VolatilityProcessor.java index 83cf2666b3..5cd15156a1 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/volatilityDSP/VolatilityProcessor.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/volatilityDSP/VolatilityProcessor.java @@ -56,7 +56,7 @@ import org.sleuthkit.datamodel.TskData.TSK_DB_FILES_TYPE_ENUM; * artifacts. */ class VolatilityProcessor { - + private static final Logger logger = Logger.getLogger(VolatilityProcessor.class.getName()); private static final String VOLATILITY = "Volatility"; //NON-NLS private static final String VOLATILITY_EXECUTABLE = "volatility_2.6_win64_standalone.exe"; //NON-NLS @@ -377,17 +377,15 @@ class VolatilityProcessor { } try { - Collection attributes = singleton( - new BlackboardAttribute( - TSK_SET_NAME, VOLATILITY, - Bundle.VolatilityProcessor_artifactAttribute_interestingFileSet(pluginName)) - ); + String setName = Bundle.VolatilityProcessor_artifactAttribute_interestingFileSet(pluginName); + Collection attributes = singleton(new BlackboardAttribute(TSK_SET_NAME, VOLATILITY, setName)); // Create artifact if it doesn't already exist. if (!blackboard.artifactExists(resolvedFile, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT, attributes)) { BlackboardArtifact volArtifact = resolvedFile.newAnalysisResult( - new BlackboardArtifact.Type(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT), - Score.SCORE_UNKNOWN, null, null, null, attributes) + BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT, Score.SCORE_LIKELY_NOTABLE, + null, setName, null, + attributes) .getAnalysisResult(); try { diff --git a/ImageGallery/nbproject/project.xml b/ImageGallery/nbproject/project.xml index 61f94648d4..0c5fd31fca 100644 --- a/ImageGallery/nbproject/project.xml +++ b/ImageGallery/nbproject/project.xml @@ -127,7 +127,7 @@ 10 - 10.23 + 10.24 diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/Bundle_ja.properties b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/Bundle_ja.properties index 8e158e56e1..d4bdabc9c6 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/Bundle_ja.properties +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/Bundle_ja.properties @@ -1,12 +1,13 @@ -AddDrawableFilesTask.populatingDb.status=\u5206\u6790\u6e08\u307f\u30a4\u30e1\u30fc\u30b8/\u52d5\u753b\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u5165\u529b\u4e2d\u3067\u3059 -BulkDrawableFilesTask.committingDb.status=\u30a4\u30e1\u30fc\u30b8/\u52d5\u753b\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u30b3\u30df\u30c3\u30c8\u4e2d\u3067\u3059 -BulkDrawableFilesTask.errPopulating.errMsg=\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u306e\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u5165\u529b\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u3042\u308a\u307e\u3057\u305f\u3002 -BulkDrawableFilesTask.populatingDb.status=\u5206\u6790\u6e08\u307f\u30a4\u30e1\u30fc\u30b8/\u52d5\u753b\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u5165\u529b\u4e2d\u3067\u3059 -BulkDrawableFilesTask.stopCopy.status=\u63cf\u753b\u53ef\u80fd\u306a\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3078\u306e\u30b3\u30d4\u30fc\u4f5c\u696d\u3092\u4e2d\u6b62\u4e2d\u3067\u3059\u3002 +#Thu Jul 01 11:56:41 UTC 2021 CTL_ImageGalleryAction=\u30a4\u30e1\u30fc\u30b8/\u52d5\u753b\u30ae\u30e3\u30e9\u30ea\u30fc CTL_ImageGalleryTopComponent=\u30a4\u30e1\u30fc\u30b8/\u52d5\u753b\u30ae\u30e3\u30e9\u30ea\u30fc +CTL_OpenAction=\u30a4\u30e1\u30fc\u30b8/\u52d5\u753b\u3092\u958b\u304f DrawableDbTask.InnerTask.message.name=\u30b9\u30c6\u30fc\u30bf\u30b9 DrawableDbTask.InnerTask.progress.name=\u9032\u6357\u72b6\u6cc1 +DrawableFileUpdateTask_committingDb.status=\u30a4\u30e1\u30fc\u30b8/\u52d5\u753b\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u30b3\u30df\u30c3\u30c8\u4e2d\u3067\u3059 +DrawableFileUpdateTask_errPopulating_errMsg=\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u306e\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u5165\u529b\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u3042\u308a\u307e\u3057\u305f\u3002 +DrawableFileUpdateTask_populatingDb_status=\u5206\u6790\u6e08\u307f\u30a4\u30e1\u30fc\u30b8/\u52d5\u753b\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u5165\u529b\u4e2d\u3067\u3059 +DrawableFileUpdateTask_stopCopy_status=\u63cf\u753b\u53ef\u80fd\u306a\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3078\u306e\u30b3\u30d4\u30fc\u4f5c\u696d\u3092\u4e2d\u6b62\u4e2d\u3067\u3059\u3002 ImageGallery.dialogTitle=\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc ImageGallery.showTooManyFiles.contentText=\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30d5\u30a1\u30a4\u30eb\u6570\u304c\u591a\u3059\u304e\u3066\u3001\u76f8\u5fdc\u306e\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u3092\u4fdd\u8a3c\u3067\u304d\u307e\u305b\u3093\u3002 ImageGallery.showTooManyFiles.headerText= @@ -17,28 +18,24 @@ ImageGalleryController.noGroupsDlg.msg2=\u30b0\u30eb\u30fc\u30d7\u306f\u5b8c\u51 ImageGalleryController.noGroupsDlg.msg3=\u30b0\u30eb\u30fc\u30d7\u306f\u5b8c\u5168\u306b\u5206\u6790\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u304c\u3001\u30a4\u30e1\u30fc\u30b8/\u52d5\u753b\u30c7\u30fc\u30bf\u306f\u307e\u3060\u5165\u529b\u4e2d\u3067\u3059\u3002 \u304a\u5f85\u3061\u304f\u3060\u3055\u3044\u3002 ImageGalleryController.noGroupsDlg.msg4=\u8ffd\u52a0\u3057\u305f\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u304b\u3089\u5229\u7528\u3067\u304d\u308b\u30a4\u30e1\u30fc\u30b8/\u52d5\u753b\u306f\u3042\u308a\u307e\u305b\u3093\u304c\u3001\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u306e\u30ea\u30c3\u30b9\u30f3\u304c\u7121\u52b9\u306b\u306a\u3063\u3066\u3044\u307e\u3059\u3002 \u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u304c\u5b8c\u4e86\u3057\u3001\u30ea\u30c3\u30b9\u30f3\u304c\u518d\u6709\u52b9\u5316\u3055\u308c\u308b\u307e\u3067\u3001\u30b0\u30eb\u30fc\u30d7\u306f\u5229\u7528\u3067\u304d\u307e\u305b\u3093\u3002 ImageGalleryController.noGroupsDlg.msg5=\u8ffd\u52a0\u3057\u305f\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u306b\u30a4\u30e1\u30fc\u30b8/\u52d5\u753b\u304c\u3042\u308a\u307e\u305b\u3093\u3002 -ImageGalleryController.noGroupsDlg.msg6=\u8868\u793a\u5bfe\u8c61\u3068\u306a\u308b\u5b8c\u5168\u306b\u5206\u6790\u3055\u308c\u305f\u30b0\u30eb\u30fc\u30d7\u306f\u3042\u308a\u307e\u305b\u3093: \u73fe\u5728\u306e [\u6b21\u3067\u30b0\u30eb\u30fc\u30d7\u5316] \u8a2d\u5b9a\u3067\u30b0\u30eb\u30fc\u30d7\u304c\u751f\u6210\u3055\u308c\u306a\u304b\u3063\u305f\u304b\u3001\u30b0\u30eb\u30fc\u30d7\u306f\u5b8c\u5168\u306b\u5206\u6790\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u304c\u3001\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u306f\u5b9f\u884c\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002 +ImageGalleryController.noGroupsDlg.msg6=\u8868\u793a\u5bfe\u8c61\u3068\u306a\u308b\u5b8c\u5168\u306b\u5206\u6790\u3055\u308c\u305f\u30b0\u30eb\u30fc\u30d7\u306f\u3042\u308a\u307e\u305b\u3093\: \u73fe\u5728\u306e [\u6b21\u3067\u30b0\u30eb\u30fc\u30d7\u5316] \u8a2d\u5b9a\u3067\u30b0\u30eb\u30fc\u30d7\u304c\u751f\u6210\u3055\u308c\u306a\u304b\u3063\u305f\u304b\u3001\u30b0\u30eb\u30fc\u30d7\u306f\u5b8c\u5168\u306b\u5206\u6790\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u304c\u3001\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u306f\u5b9f\u884c\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002 ImageGalleryModule.moduleName=\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc +ImageGalleryOptionsPanel.descriptionLabel.text=\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u306e\u8d77\u52d5\u6642\u9593\u3092\u6700\u5c0f\u5316\u3059\u308b\u305f\u3081\u306b\u3001\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u306e\u5185\u90e8\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304c\u5e38\u6642\u66f4\u65b0\u3055\u308c\u307e\u3059\u3002
\u3053\u308c\u306b\u3088\u308a\u3001\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u306e\u6a5f\u80fd\u3092\u5fc5\u8981\u3068\u3057\u306a\u3044\u5834\u5408\u3001\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u306e\u5b9f\u884c\u304c\u9045\u304f\u306a\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002
\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u3092\u5fc5\u8981\u3068\u3057\u306a\u3044\u5834\u5408\u3001\u3053\u308c\u3089\u306e\u8a2d\u5b9a\u3092\u4f7f\u7528\u3057\u3066\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u3092\u7121\u52b9\u5316\u3057\u307e\u3059\u3002 +ImageGalleryOptionsPanel.enabledByDefaultBox.text=\u65b0\u3057\u3044\u30b1\u30fc\u30b9\u306e\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u3092\u30c7\u30d5\u30a9\u30eb\u30c8\u3067\u6709\u52b9\u5316\u3057\u307e\u3059\u3002 +ImageGalleryOptionsPanel.enabledForCaseBox.text=\u73fe\u5728\u306e\u30b1\u30fc\u30b9\u306e\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u306e\u66f4\u65b0\u3092\u6709\u52b9\u306b\u3057\u307e\u3059\u3002 +ImageGalleryOptionsPanel.enabledForCaseBox.toolTipText=\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u304c\u7121\u52b9\u306e\u5834\u5408\u3001\u66f4\u65b0\u304c\u5fc5\u8981\u3067\u3042\u308b\u3068\u3044\u3046\u4e8b\u5b9f\u3060\u3051\u304c\u8a18\u9332\u3055\u308c\u307e\u3059\u3002 \u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u5f8c\u306b\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u3092\u6709\u52b9\u5316\u3057\u305f\u5834\u5408\u3001\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u306e\u7d50\u679c\u306b\u57fa\u3065\u3044\u3066\u4e00\u62ec\u66f4\u65b0\u30921\u56de\u884c\u3044\u307e\u3059\u3002 \u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u304c\u7121\u52b9\u306e\u5834\u5408\u3001\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u306e\u30a6\u30a3\u30f3\u30c9\u30a6\u3092\u958b\u3053\u3046\u3068\u8a66\u307f\u308b\u3068\u3001\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u3092\u6709\u52b9\u5316\u3059\u308b\u3088\u3046\u4fc3\u3055\u308c\u307e\u3059\u3002 +ImageGalleryOptionsPanel.furtherDescriptionArea.text=\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u304c\u7121\u52b9\u306e\u5834\u5408\u3001\u66f4\u65b0\u304c\u5fc5\u8981\u3067\u3042\u308b\u3068\u3044\u3046\u4e8b\u5b9f\u3060\u3051\u304c\u8a18\u9332\u3055\u308c\u307e\u3059\u3002 \u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u5f8c\u306b\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u3092\u6709\u52b9\u5316\u3057\u305f\u5834\u5408\u3001\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u306e\u7d50\u679c\u306b\u57fa\u3065\u3044\u3066\u4e00\u62ec\u66f4\u65b0\u30921\u56de\u884c\u3044\u307e\u3059\u3002 \u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u304c\u7121\u52b9\u306e\u5834\u5408\u3001\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u306e\u30a6\u30a3\u30f3\u30c9\u30a6\u3092\u958b\u3053\u3046\u3068\u8a66\u307f\u308b\u3068\u3001\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u3092\u6709\u52b9\u5316\u3059\u308b\u3088\u3046\u4fc3\u3055\u308c\u307e\u3059\u3002 +ImageGalleryOptionsPanel.groupCategorizationWarningBox.text=\u30b0\u30eb\u30fc\u30d7\u5168\u4f53\u306b\u52b9\u529b\u3092\u6301\u305f\u305b\u308b\u3053\u3068\u3067\u3001\u30ab\u30c6\u30b4\u30ea\u30fc\u306e\u4e0a\u66f8\u304d\u4e2d\u306b\u8b66\u544a\u3092\u8868\u793a\u3057\u307e\u305b\u3093\u3002 +ImageGalleryOptionsPanel.unavailableDuringInjestLabel.text=\u3053\u306e\u8a2d\u5b9a\u306f\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u5b9f\u884c\u4e2d\u5229\u7528\u3067\u304d\u307e\u305b\u3093\u3002 ImageGalleryService.openCaseResources.progressMessage.finish=\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u306e\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u958b\u304d\u307e\u3057\u305f\u3002 ImageGalleryService.openCaseResources.progressMessage.start=\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u306e\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u958b\u3044\u3066\u3044\u307e\u3059... ImageGalleryService.serviceName=\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u66f4\u65b0\u30b5\u30fc\u30d3\u30b9 ImageGalleryTopComponent.chooseDataSourceDialog.all=\u3059\u3079\u3066 -ImageGalleryTopComponent.chooseDataSourceDialog.contentText=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9: +ImageGalleryTopComponent.chooseDataSourceDialog.contentText=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\: ImageGalleryTopComponent.chooseDataSourceDialog.headerText=\u8868\u793a\u3059\u308b\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u9078\u629e\u3057\u307e\u3059\u3002 ImageGalleryTopComponent.chooseDataSourceDialog.titleText=\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc -OpenIDE-Module-Long-Description=\ - \u30a4\u30e1\u30fc\u30b8\u96c6\u4e2d\u8abf\u67fb\u306e\u5b9f\u884c\u3092\u3088\u308a\u52b9\u7387\u7684\u306b\u3059\u308b\u3088\u3046\u306b\u8a2d\u8a08\u3055\u308c\u305f\u3001\u65b0\u3057\u3044\u30a4\u30e1\u30fc\u30b8\u3068\u52d5\u753b\u306e\u30ae\u30e3\u30e9\u30ea\u30fc\u3067\u3059\u3002 \ - \u3053\u306e\u4f5c\u54c1\u306fDHS S&T\u306e\u8cc7\u91d1\u63f4\u52a9\u3092\u53d7\u3051\u3066\u3044\u307e\u3059\u3002\u306a\u304a\u3001\u3053\u308c\u306f\u30d9\u30fc\u30bf\u30ea\u30ea\u30fc\u30b9\u3067\u3059\u3002\ - sleuthkit.org\u30b5\u30a4\u30c8\u304b\u3089\u5165\u624b\u3067\u304d\u307e\u305b\u3093\u3002\u9650\u5b9a\u30e6\u30fc\u30b6\u30fc\u306b\u914d\u5e03\u3055\u308c\u3066\u3044\u307e\u3059\u3002 +OpenIDE-Module-Long-Description=\u30a4\u30e1\u30fc\u30b8\u96c6\u4e2d\u8abf\u67fb\u306e\u5b9f\u884c\u3092\u3088\u308a\u52b9\u7387\u7684\u306b\u3059\u308b\u3088\u3046\u306b\u8a2d\u8a08\u3055\u308c\u305f\u3001\u65b0\u3057\u3044\u30a4\u30e1\u30fc\u30b8\u3068\u52d5\u753b\u306e\u30ae\u30e3\u30e9\u30ea\u30fc\u3067\u3059\u3002 \u3053\u306e\u4f5c\u54c1\u306fDHS S&T\u306e\u8cc7\u91d1\u63f4\u52a9\u3092\u53d7\u3051\u3066\u3044\u307e\u3059\u3002\u306a\u304a\u3001\u3053\u308c\u306f\u30d9\u30fc\u30bf\u30ea\u30ea\u30fc\u30b9\u3067\u3059\u3002sleuthkit.org\u30b5\u30a4\u30c8\u304b\u3089\u5165\u624b\u3067\u304d\u307e\u305b\u3093\u3002\u9650\u5b9a\u30e6\u30fc\u30b6\u30fc\u306b\u914d\u5e03\u3055\u308c\u3066\u3044\u307e\u3059\u3002 OpenIDE-Module-Name=ImageGallery OpenIDE-Module-Short-Description=\u9ad8\u5ea6\u306a\u30a4\u30e1\u30fc\u30b8\u3068\u52d5\u753b\u306e\u30ae\u30e3\u30e9\u30ea\u30fc -ImageGalleryOptionsPanel.enabledForCaseBox.text=\u73fe\u5728\u306e\u30b1\u30fc\u30b9\u306e\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u306e\u66f4\u65b0\u3092\u6709\u52b9\u306b\u3057\u307e\u3059\u3002 -ImageGalleryOptionsPanel.enabledByDefaultBox.text=\u65b0\u3057\u3044\u30b1\u30fc\u30b9\u306e\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u3092\u30c7\u30d5\u30a9\u30eb\u30c8\u3067\u6709\u52b9\u5316\u3057\u307e\u3059\u3002 -ImageGalleryOptionsPanel.enabledForCaseBox.toolTipText=\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u304c\u7121\u52b9\u306e\u5834\u5408\u3001\u66f4\u65b0\u304c\u5fc5\u8981\u3067\u3042\u308b\u3068\u3044\u3046\u4e8b\u5b9f\u3060\u3051\u304c\u8a18\u9332\u3055\u308c\u307e\u3059\u3002 \u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u5f8c\u306b\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u3092\u6709\u52b9\u5316\u3057\u305f\u5834\u5408\u3001\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u306e\u7d50\u679c\u306b\u57fa\u3065\u3044\u3066\u4e00\u62ec\u66f4\u65b0\u30921\u56de\u884c\u3044\u307e\u3059\u3002 \u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u304c\u7121\u52b9\u306e\u5834\u5408\u3001\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u306e\u30a6\u30a3\u30f3\u30c9\u30a6\u3092\u958b\u3053\u3046\u3068\u8a66\u307f\u308b\u3068\u3001\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u3092\u6709\u52b9\u5316\u3059\u308b\u3088\u3046\u4fc3\u3055\u308c\u307e\u3059\u3002 -ImageGalleryOptionsPanel.descriptionLabel.text=\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u306e\u8d77\u52d5\u6642\u9593\u3092\u6700\u5c0f\u5316\u3059\u308b\u305f\u3081\u306b\u3001\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u306e\u5185\u90e8\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304c\u5e38\u6642\u66f4\u65b0\u3055\u308c\u307e\u3059\u3002
\u3053\u308c\u306b\u3088\u308a\u3001\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u306e\u6a5f\u80fd\u3092\u5fc5\u8981\u3068\u3057\u306a\u3044\u5834\u5408\u3001\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u306e\u5b9f\u884c\u304c\u9045\u304f\u306a\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002
\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u3092\u5fc5\u8981\u3068\u3057\u306a\u3044\u5834\u5408\u3001\u3053\u308c\u3089\u306e\u8a2d\u5b9a\u3092\u4f7f\u7528\u3057\u3066\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u3092\u7121\u52b9\u5316\u3057\u307e\u3059\u3002 -ImageGalleryOptionsPanel.furtherDescriptionArea.text=\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u304c\u7121\u52b9\u306e\u5834\u5408\u3001\u66f4\u65b0\u304c\u5fc5\u8981\u3067\u3042\u308b\u3068\u3044\u3046\u4e8b\u5b9f\u3060\u3051\u304c\u8a18\u9332\u3055\u308c\u307e\u3059\u3002 \u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u5f8c\u306b\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u3092\u6709\u52b9\u5316\u3057\u305f\u5834\u5408\u3001\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u306e\u7d50\u679c\u306b\u57fa\u3065\u3044\u3066\u4e00\u62ec\u66f4\u65b0\u30921\u56de\u884c\u3044\u307e\u3059\u3002 \u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u304c\u7121\u52b9\u306e\u5834\u5408\u3001\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u306e\u30a6\u30a3\u30f3\u30c9\u30a6\u3092\u958b\u3053\u3046\u3068\u8a66\u307f\u308b\u3068\u3001\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u3092\u6709\u52b9\u5316\u3059\u308b\u3088\u3046\u4fc3\u3055\u308c\u307e\u3059\u3002 -ImageGalleryOptionsPanel.unavailableDuringInjestLabel.text=\u3053\u306e\u8a2d\u5b9a\u306f\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u5b9f\u884c\u4e2d\u5229\u7528\u3067\u304d\u307e\u305b\u3093\u3002 -ImageGalleryOptionsPanel.groupCategorizationWarningBox.text=\u30b0\u30eb\u30fc\u30d7\u5168\u4f53\u306b\u52b9\u529b\u3092\u6301\u305f\u305b\u308b\u3053\u3068\u3067\u3001\u30ab\u30c6\u30b4\u30ea\u30fc\u306e\u4e0a\u66f8\u304d\u4e2d\u306b\u8b66\u544a\u3092\u8868\u793a\u3057\u307e\u305b\u3093\u3002 -CTL_OpenAction=\u30a4\u30e1\u30fc\u30b8/\u52d5\u753b\u3092\u958b\u304f OptionsCategory_Keywords_Options=\u30a4\u30e1\u30fc\u30b8/\u52d5\u753b\u30ae\u30e3\u30e9\u30ea\u30fc\u306e\u30ab\u30c6\u30b4\u30ea\u30fc OptionsCategory_Name_Options=\u30a4\u30e1\u30fc\u30b8/\u52d5\u753b\u30ae\u30e3\u30e9\u30ea\u30fc diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/Bundle_ja.properties b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/Bundle_ja.properties index 06c4149dec..4b8aeb5a3e 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/Bundle_ja.properties +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/Bundle_ja.properties @@ -1,4 +1,4 @@ -# {0} - fileID +#Mon Jul 12 13:22:00 UTC 2021 AddDrawableTagAction.addTagsToFiles.alert=\u30d5\u30a1\u30a4\u30eb {0} \u3092\u30bf\u30b0\u4ed8\u3051\u3067\u304d\u307e\u305b\u3093\u3002 AddDrawableTagAction.displayName.plural=\u30d5\u30a1\u30a4\u30eb\u3092\u30bf\u30b0\u4ed8\u3051 AddDrawableTagAction.displayName.singular=\u30d5\u30a1\u30a4\u30eb\u3092\u30bf\u30b0\u4ed8\u3051 @@ -7,19 +7,15 @@ AddTagAction.menuItem.noTags=\u30bf\u30b0\u306a\u3057 AddTagAction.menuItem.quickTag=\u30af\u30a4\u30c3\u30af\u30bf\u30b0 AddTagAction.menuItem.tagAndComment=\u30bf\u30b0\u3068\u30b3\u30e1\u30f3\u30c8... Back_diplayName=\u623b\u308b -CategorizeAction.displayName=\u5206\u985e -# {0} - fileID\u756a\u53f7 -CategorizeDrawableFileTask.errorUnable.msg={0} \u3092\u5206\u985e\u3067\u304d\u307e\u305b\u3093\u3002 -CategorizeDrawableFileTask.errorUnable.title=\u30a8\u30e9\u30fc\u3092\u5206\u985e\u4e2d\u3067\u3059 -CategorizeGroupAction.dontShowAgain=\u3053\u306e\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u518d\u8868\u793a\u3057\u306a\u3044 -CategorizeGroupAction.fileCountHeader=\u6b21\u306e\u30ab\u30c6\u30b4\u30ea\u30fc\u306e\u30d5\u30a1\u30a4\u30eb\u306f\u81ea\u8eab\u306e\u30ab\u30c6\u30b4\u30ea\u30fc\u3092\u4e0a\u66f8\u304d\u3057\u307e\u3059: -# {0} - \u305d\u306e\u30ab\u30c6\u30b4\u30ea\u30fc\u3092\u6301\u3064\u30d5\u30a1\u30a4\u30eb\u6570 -# {1} - \u30ab\u30c6\u30b4\u30ea\u30fc\u540d -CategorizeGroupAction.fileCountMessage={1} \u3092\u6301\u3064 {0} -CategorizeGroupAction.OverwriteButton.text=\u4e0a\u66f8\u304d CTL_AddImage=\u30a4\u30e1\u30fc\u30b8/\u52d5\u753b\u3092\u8868\u793a CTL_OpenAction=\u30a4\u30e1\u30fc\u30b8/\u52d5\u753b -# {0} - fileID +CategorizeAction.displayName=\u5206\u985e +CategorizeDrawableFileTask.errorUnable.msg={0} \u3092\u5206\u985e\u3067\u304d\u307e\u305b\u3093\u3002 +CategorizeDrawableFileTask.errorUnable.title=\u30a8\u30e9\u30fc\u3092\u5206\u985e\u4e2d\u3067\u3059 +CategorizeGroupAction.OverwriteButton.text=\u4e0a\u66f8\u304d +CategorizeGroupAction.dontShowAgain=\u3053\u306e\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u518d\u8868\u793a\u3057\u306a\u3044 +CategorizeGroupAction.fileCountHeader=\u6b21\u306e\u30ab\u30c6\u30b4\u30ea\u30fc\u306e\u30d5\u30a1\u30a4\u30eb\u306f\u81ea\u8eab\u306e\u30ab\u30c6\u30b4\u30ea\u30fc\u3092\u4e0a\u66f8\u304d\u3057\u307e\u3059\: +CategorizeGroupAction.fileCountMessage={1} \u3092\u6301\u3064 {0} DeleteDrawableTagAction.deleteTag.alert=\u30d5\u30a1\u30a4\u30eb {0} \u3092\u30bf\u30b0\u306a\u3057\u306b\u3067\u304d\u307e\u305b\u3093\u3002 DeleteDrawableTagAction.displayName=\u30d5\u30a1\u30a4\u30eb\u30bf\u30b0\u3092\u524a\u9664 DeleteFollwUpTagAction.displayName=\u30d5\u30a9\u30ed\u30fc\u30a2\u30c3\u30d7\u30bf\u30b0\u3092\u524a\u9664 @@ -29,13 +25,15 @@ NextUnseenGroup.allGroupsSeen=\u3059\u3079\u3066\u306e\u30b0\u30eb\u30fc\u30d7\u NextUnseenGroup.markGroupSeen=\u8868\u793a\u3057\u305f\u30b0\u30eb\u30fc\u30d7\u3092\u30de\u30fc\u30af\u3059\u308b NextUnseenGroup.nextUnseenGroup=\u6b21\u306e\u975e\u8868\u793a\u30b0\u30eb\u30fc\u30d7 OpenAction.dialogTitle=\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc -OpenAction.multiUserDialog.checkBox.text=\u3053\u306e\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u518d\u8868\u793a\u3057\u307e\u305b\u3093\u3002 -OpenAction.multiUserDialog.ContentText=\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u306f\u30b7\u30f3\u30b0\u30eb\u30e6\u30fc\u30b6\u30fc\u30b1\u30fc\u30b9\u3068\u306f\u7570\u306a\u308b\u65b9\u6cd5\u3067\u30de\u30eb\u30c1\u30e6\u30fc\u30b6\u30fc\u30b1\u30fc\u30b9\u306b\u5bfe\u3057\u3066\u66f4\u65b0\u3057\u307e\u3059\u3002\u9855\u8457:\n\nIf \u304a\u4f7f\u3044\u306e\u30b3\u30f3\u30d4\u30e5\u30fc\u30bf\u30fc\u304c\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u5206\u6790\u4e2d\u3067\u3059\u3002\u30d5\u30a1\u30a4\u30eb\u304c\u5206\u6790\u3055\u308c\u308b\u3068(\u30cf\u30c3\u30b7\u30e5\u5316\u3001EXIF\u306a\u3069)\u3001\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u306e\u30ea\u30a2\u30eb\u30bf\u30a4\u30e0\u66f4\u65b0\u3092\u53d6\u5f97\u3057\u307e\u3059\u3002\u3053\u308c\u306f\u30b7\u30f3\u30b0\u30eb\u30e6\u30fc\u30b6\u30fc\u30b1\u30fc\u30b9\u3068\u540c\u3058\u6319\u52d5\u3067\u3059\u3002\n\nIf \u6240\u5c5e\u5148\u306e\u30de\u30eb\u30c1\u30e6\u30fc\u30b6\u30fc\u30af\u30e9\u30b9\u30bf\u30fc\u306e\u5225\u306e\u30b3\u30f3\u30d4\u30e5\u30fc\u30bf\u30fc\u304c\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u5206\u6790\u4e2d\u3067\u3059\u3002\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u3092\u8d77\u52d5\u3059\u308b\u3068\u3001\u305d\u306e\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u4e0a\u306e\u5225\u306e\u30d5\u30a1\u30a4\u30eb\u306e\u66f4\u65b0\u3092\u53d6\u5f97\u3057\u307e\u3059\u3002\u3053\u308c\u306b\u3088\u308a\u3001\u305d\u306e\u4ed6\u306e\u30ce\u30fc\u30c9\u306e\u7d50\u679c\u306b\u57fa\u3065\u3044\u3066\u30ed\u30fc\u30ab\u30eb\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304c\u518d\u69cb\u7bc9\u3055\u308c\u307e\u3059\u3002 +OpenAction.multiUserDialog.ContentText=\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u306f\u30b7\u30f3\u30b0\u30eb\u30e6\u30fc\u30b6\u30fc\u30b1\u30fc\u30b9\u3068\u306f\u7570\u306a\u308b\u65b9\u6cd5\u3067\u30de\u30eb\u30c1\u30e6\u30fc\u30b6\u30fc\u30b1\u30fc\u30b9\u306b\u5bfe\u3057\u3066\u66f4\u65b0\u3057\u307e\u3059\u3002\u9855\u8457\:\n\nIf \u304a\u4f7f\u3044\u306e\u30b3\u30f3\u30d4\u30e5\u30fc\u30bf\u30fc\u304c\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u5206\u6790\u4e2d\u3067\u3059\u3002\u30d5\u30a1\u30a4\u30eb\u304c\u5206\u6790\u3055\u308c\u308b\u3068(\u30cf\u30c3\u30b7\u30e5\u5316\u3001EXIF\u306a\u3069)\u3001\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u306e\u30ea\u30a2\u30eb\u30bf\u30a4\u30e0\u66f4\u65b0\u3092\u53d6\u5f97\u3057\u307e\u3059\u3002\u3053\u308c\u306f\u30b7\u30f3\u30b0\u30eb\u30e6\u30fc\u30b6\u30fc\u30b1\u30fc\u30b9\u3068\u540c\u3058\u6319\u52d5\u3067\u3059\u3002\n\nIf \u6240\u5c5e\u5148\u306e\u30de\u30eb\u30c1\u30e6\u30fc\u30b6\u30fc\u30af\u30e9\u30b9\u30bf\u30fc\u306e\u5225\u306e\u30b3\u30f3\u30d4\u30e5\u30fc\u30bf\u30fc\u304c\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u5206\u6790\u4e2d\u3067\u3059\u3002\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u3092\u8d77\u52d5\u3059\u308b\u3068\u3001\u305d\u306e\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u4e0a\u306e\u5225\u306e\u30d5\u30a1\u30a4\u30eb\u306e\u66f4\u65b0\u3092\u53d6\u5f97\u3057\u307e\u3059\u3002\u3053\u308c\u306b\u3088\u308a\u3001\u305d\u306e\u4ed6\u306e\u30ce\u30fc\u30c9\u306e\u7d50\u679c\u306b\u57fa\u3065\u3044\u3066\u30ed\u30fc\u30ab\u30eb\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304c\u518d\u69cb\u7bc9\u3055\u308c\u307e\u3059\u3002 OpenAction.multiUserDialog.Header=\u30de\u30eb\u30c1\u30e6\u30fc\u30b6\u30fc\u306e\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc +OpenAction.multiUserDialog.checkBox.text=\u3053\u306e\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u518d\u8868\u793a\u3057\u307e\u305b\u3093\u3002 OpenAction.noControllerDialog.header=\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc\u3092\u958b\u3051\u307e\u305b\u3093 OpenAction.noControllerDialog.text=\u521d\u671f\u5316\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002\n\u8a73\u7d30\u306f\u30ed\u30b0\u3092\u53c2\u7167\u3057\u3066\u304f\u3060\u3055\u3044\u3002 OpenAction.notAnalyzedDlg.msg=\u8868\u793a\u5bfe\u8c61\u3068\u306a\u308b\u30a4\u30e1\u30fc\u30b8/\u52d5\u753b\u30d5\u30a1\u30a4\u30eb\u304c\u307e\u3060\u3042\u308a\u307e\u305b\u3093\u3002\nFileType\u307e\u305f\u306fEXIF\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u5b9f\u884c\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -OpenAction.stale.confDlg.msg=\u30a4\u30e1\u30fc\u30b8/\u52d5\u753b\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304c\u6700\u65b0\u3067\u306f\u306a\u3044\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002\u66f4\u65b0\u3057\u3066\u3055\u3089\u306a\u308b\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u7d50\u679c\u3092\u30ea\u30c3\u30b9\u30f3\u3057\u307e\u3059\u304b?\n [\u306f\u3044] \u3092\u9078\u629e\u3059\u308b\u3068\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304c\u66f4\u65b0\u3055\u308c\u3001\u3055\u3089\u306a\u308b\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u3092\u30ea\u30c3\u30b9\u30f3\u3067\u304d\u308b\u3088\u3046\u306b\u306a\u308a\u307e\u3059\u3002 +OpenAction.openTopComponent.error.message=\u753b\u50cf\u30ae\u30e3\u30e9\u30ea\u30fc\u3092\u958b\u3053\u3046\u3068\u3057\u305f\u3068\u304d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +OpenAction.openTopComponent.error.title=\u753b\u50cf\u30ae\u30e3\u30e9\u30ea\u30fc\u3092\u958b\u304f\u3053\u3068\u304c\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f +OpenAction.stale.confDlg.msg=\u753b\u50cf/\u30d3\u30c7\u30aa\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304c\u53e4\u304f\u306a\u3063\u3066\u3044\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002\u66f4\u65b0\u3057\u3066\u3001\u53d6\u8fbc\u307f\u7d50\u679c\u3092\u89b3\u5bdf\u3057\u307e\u3059\u304b\uff1f\n\u300cyes\u300d\u3092\u9078\u629e\u3059\u308b\u3068\u3001\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304c\u66f4\u65b0\u3055\u308c\u3001\u4ee5\u5f8c\u306e\u53d6\u8fbc\u307f\u3092\u89b3\u5bdf\u3067\u304d\u308b\u3088\u3046\u306b\u306a\u308a\u307e\u3059\u3002\n\n\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u66f4\u65b0\u72b6\u6cc1\u306f\u3001\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u30a6\u30a3\u30f3\u30c9\u30a6\u306e\u53f3\u4e0b\u9685\u306b\u8868\u793a\u3055\u308c\u307e\u3059\u3002 OpenAction.stale.confDlg.title=\u30a4\u30e1\u30fc\u30b8\u30ae\u30e3\u30e9\u30ea\u30fc OpenExternalViewerAction.displayName=\u5916\u90e8\u30d3\u30e5\u30fc\u30ef\u30fc RedoAction.name=\u3084\u308a\u76f4\u3057 diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableAttribute.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableAttribute.java index 03ea2e3292..5bf810edcd 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableAttribute.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableAttribute.java @@ -33,6 +33,7 @@ import javafx.scene.image.ImageView; import org.apache.commons.lang3.StringUtils; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.TimeZoneUtils; import org.sleuthkit.autopsy.datamodel.ContentUtils; import org.sleuthkit.datamodel.TagName; @@ -118,13 +119,13 @@ public class DrawableAttribute> { = new DrawableAttribute<>(AttributeName.CREATED_TIME, Bundle.DrawableAttribute_createdTime(), true, "clock--plus.png", //NON-NLS - f -> Collections.singleton(ContentUtils.getStringTime(f.getCrtime(), f.getAbstractFile()))); + f -> Collections.singleton(TimeZoneUtils.getFormattedTime(f.getCrtime()))); public final static DrawableAttribute MODIFIED_TIME = new DrawableAttribute<>(AttributeName.MODIFIED_TIME, Bundle.DrawableAttribute_modifiedTime(), true, "clock--pencil.png", //NON-NLS - f -> Collections.singleton(ContentUtils.getStringTime(f.getMtime(), f.getAbstractFile()))); + f -> Collections.singleton(TimeZoneUtils.getFormattedTime(f.getMtime()))); public final static DrawableAttribute MAKE = new DrawableAttribute<>(AttributeName.MAKE, Bundle.DrawableAttribute_cameraMake(), diff --git a/KeywordSearch/manifest.mf b/KeywordSearch/manifest.mf index 608eaffd6c..0e947e073b 100644 --- a/KeywordSearch/manifest.mf +++ b/KeywordSearch/manifest.mf @@ -1,7 +1,7 @@ Manifest-Version: 1.0 AutoUpdate-Show-In-Client: true OpenIDE-Module: org.sleuthkit.autopsy.keywordsearch/6 -OpenIDE-Module-Implementation-Version: 22 +OpenIDE-Module-Implementation-Version: 23 OpenIDE-Module-Install: org/sleuthkit/autopsy/keywordsearch/Installer.class OpenIDE-Module-Layer: org/sleuthkit/autopsy/keywordsearch/layer.xml OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/keywordsearch/Bundle.properties diff --git a/KeywordSearch/nbproject/project.xml b/KeywordSearch/nbproject/project.xml index c94da5eb38..1a1760e572 100644 --- a/KeywordSearch/nbproject/project.xml +++ b/KeywordSearch/nbproject/project.xml @@ -128,7 +128,7 @@ 10 - 10.23 + 10.24
diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties index 7dfee92048..831379e537 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties @@ -319,5 +319,6 @@ ExtractedContentPanel.pageTotalLabel.text=- ExtractedContentPanel.pageOfLabel.text=of ExtractedContentPanel.pageCurLabel.text=- ExtractedContentPanel.pagesLabel.text=Page: -KeywordSearchGlobalSearchSettingsPanel.ocrCheckBox.text=Enable Optical Character Recognition (OCR) -KeywordSearchGlobalSearchSettingsPanel.limitedOcrCheckbox.text=Only process images which are over 100KB in size or extracted from a document (Beta) +KeywordSearchJobSettingsPanel.ocrCheckBox.text=Enable Optical Character Recognition (OCR) +KeywordSearchJobSettingsPanel.limitedOcrCheckbox.text=Only process PDFs, MS Office docs and images which are over 100KB in size or extracted from another file (Beta) +KeywordSearchJobSettingsPanel.ocrOnlyCheckbox.text=Only index text extracted using OCR diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED index c60c34bade..388f951276 100755 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED @@ -5,6 +5,7 @@ AccountsText.nextPage.exception.msg=No next page. AccountsText.previousItem.exception.msg=No previous item. AccountsText.previousPage.exception.msg=No previous page. 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 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 [ \\.,] @@ -51,7 +52,7 @@ KeywordSearchResultFactory.createNodeForKey.noResultsFound.text=No results found KeywordSearchResultFactory.query.exception.msg=Could not perform the query OpenIDE-Module-Display-Category=Ingest Module -OpenIDE-Module-Long-Description=Keyword Search ingest module.\n\nThe module indexes files found in the disk image at ingest time.\nIt then periodically runs the search on the indexed files using one or more keyword lists (containing pure words and/or regular expressions) and posts results.\n\n\The module also contains additional tools integrated in the main GUI, such as keyword list configuration, keyword search bar in the top-right corner, extracted text viewer and search results viewer showing highlighted keywords found. +OpenIDE-Module-Long-Description=Keyword Search ingest module.\n\nThe module indexes files found in the disk image at ingest time.\nIt then periodically runs the search on the indexed files using one or more keyword lists (containing pure words and/or regular expressions) and posts results.\n\nThe module also contains additional tools integrated in the main GUI, such as keyword list configuration, keyword search bar in the top-right corner, extracted text viewer and search results viewer showing highlighted keywords found. OpenIDE-Module-Name=KeywordSearch OptionsCategory_Name_KeywordSearchOptions=Keyword Search OptionsCategory_Keywords_KeywordSearchOptions=Keyword Search @@ -401,8 +402,9 @@ ExtractedContentPanel.pageTotalLabel.text=- ExtractedContentPanel.pageOfLabel.text=of ExtractedContentPanel.pageCurLabel.text=- ExtractedContentPanel.pagesLabel.text=Page: -KeywordSearchGlobalSearchSettingsPanel.ocrCheckBox.text=Enable Optical Character Recognition (OCR) -KeywordSearchGlobalSearchSettingsPanel.limitedOcrCheckbox.text=Only process images which are over 100KB in size or extracted from a document (Beta) +KeywordSearchJobSettingsPanel.ocrCheckBox.text=Enable Optical Character Recognition (OCR) +KeywordSearchJobSettingsPanel.limitedOcrCheckbox.text=Only process PDFs, MS Office docs and images which are over 100KB in size or extracted from another file (Beta) +KeywordSearchJobSettingsPanel.ocrOnlyCheckbox.text=Only index text extracted using OCR TextZoomPanel.zoomInButton.text= TextZoomPanel.zoomOutButton.text= TextZoomPanel.zoomResetButton.text=Reset diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle_ja.properties b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle_ja.properties index d43448a582..3fead9fe9c 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle_ja.properties +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle_ja.properties @@ -1,4 +1,4 @@ -#Fri Feb 12 16:56:29 UTC 2021 +#Mon Jul 12 13:22:00 UTC 2021 AbstractFileStringContentStream.getSize.exception.msg=\u6587\u5b57\u5217\u5168\u4f53\u304c\u5909\u63db\u3055\u308c\u308b\u307e\u3067\u3001\u5909\u63db\u3055\u308c\u305f\u6587\u5b57\u5217\u306e\u6587\u5b57\u6570\u306f\u308f\u304b\u308a\u307e\u305b\u3093 AbstractFileStringContentStream.getSrcInfo.text=\u30d5\u30a1\u30a4\u30eb\:{0} AbstractFileTikaTextExtract.index.exception.tikaParse.msg=\u4f8b\u5916\: \u6b21\u306e\u30d5\u30a1\u30a4\u30eb\u306eTika\u89e3\u6790\u30bf\u30b9\u30af\u5b9f\u884c\u6642\u306e\u4e88\u671f\u305b\u306c\u4f8b\u5916\: {0}\u3001{1} @@ -27,6 +27,7 @@ AddKeywordsDialog.regexRadioButton.text=\u6b63\u898f\u8868\u73fe AddKeywordsDialog.substringRadioButton.text=\u90e8\u5206\u4e00\u81f4 ByteContentStream.getSrcInfo.text=\u30d5\u30a1\u30a4\u30eb\:{0} CannotRunFileTypeDetection=\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7\u306e\u691c\u51fa\u3092\u5b9f\u884c\u3067\u304d\u307e\u305b\u3093\u3002 +Collection.unableToIndexData.error=\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u306b\u30c7\u30fc\u30bf\u3092\u8ffd\u52a0\u3067\u304d\u307e\u305b\u3093\u3002 \u73fe\u5728\u306e\u30b1\u30fc\u30b9\u306b\u4eca\u5f8c\u306e\u30c6\u30ad\u30b9\u30c8\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u306f\u3059\u3079\u3066\u30b9\u30ad\u30c3\u30d7\u3055\u308c\u307e\u3059\u3002 DropdownListSearchPanel.dataSourceCheckBox.text=\u9078\u629e\u3057\u305f\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u306b\u691c\u7d22\u3092\u5236\u9650\: DropdownListSearchPanel.jSaveSearchResults.text=\u691c\u7d22\u7d50\u679c\u3092\u4fdd\u5b58 DropdownListSearchPanel.jSaveSearchResults.toolTipText=\u30ad\u30fc\u30ef\u30fc\u30c9\u30d2\u30c3\u30c8\u306b\u3088\u308b\u904e\u53bb\u306e\u691c\u7d22\u7d50\u679c\u306e\u5f62\u3067\u7d50\u679c\u3092\u4fdd\u5b58\u305b\u305a\u306b\u30ad\u30fc\u30ef\u30fc\u30c9\u691c\u7d22\u3092\u5b9f\u884c @@ -47,6 +48,17 @@ DropdownSingleTermSearchPanel.jSaveSearchResults.toolTipText=\u30ad\u30fc\u30ef\ DropdownSingleTermSearchPanel.selected=\u30a2\u30c9\u30db\u30c3\u30af\u691c\u7d22\u30bd\u30fc\u30b9\u30d5\u30a3\u30eb\u30bf\u30fc\u304c\u9078\u629e\u3055\u308c\u3066\u3044\u307e\u3059 DropdownSingleTermSearchPanel.warning.text=\u5883\u754c\u6587\u5b57 ^ \u3068 $ \u304c\u5358\u8a9e\u9818\u57df\u3068\u4e00\u81f4\u3057\u307e\u305b\u3093\u3002[ \\.,] \u306a\u3069\u306e\u660e\u793a\u7684\u306a\u5883\u754c\u6587\u5b57\u30ea\u30b9\u30c8\u3068\u306e\u7f6e\u63db\u3092\n\u691c\u8a0e\u3057\u3066\u304f\u3060\u3055\u3044 DropdownSingleTermSearchPanel.warning.title=\u8b66\u544a +ExtractAllTermsReport.description.text=\u73fe\u5728\u306e\u30b1\u30fc\u30b9\u304b\u3089\u3059\u3079\u3066\u306e\u30e6\u30cb\u30fc\u30af\u306e\u5358\u8a9e\u3092\u62bd\u51fa\u3057\u307e\u3059\u3002 \u6ce8\uff1a\u62bd\u51fa\u3055\u308c\u305f\u5358\u8a9e\u306f\u5c0f\u6587\u5b57\u3067\u3059\u3002 +ExtractAllTermsReport.error.noOpenCase=\u73fe\u5728\u958b\u3044\u3066\u3044\u308b\u30b1\u30fc\u30b9\u306f\u3042\u308a\u307e\u305b\u3093\u3002 +ExtractAllTermsReport.export.error=\u30e6\u30cb\u30fc\u30af\u306e\u5358\u8a9e\u306e\u62bd\u51fa\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +ExtractAllTermsReport.exportComplete=\u30e6\u30cb\u30fc\u30af\u306a\u5358\u8a9e\u62bd\u51fa\u5b8c\u4e86 +ExtractAllTermsReport.getName.text=\u30e6\u30cb\u30fc\u30af\u306a\u5358\u8a9e\u3092\u62bd\u51fa\u3059\u308b +ExtractAllTermsReport.numberExtractedTerms={0}\u7528\u8a9e.\u304c\u62bd\u51fa\u3055\u308c\u307e\u3057\u305f.. +ExtractAllTermsReport.search.ingestInProgressBody=\u30ad\u30fc\u30ef\u30fc\u30c9\u691c\u7d22\u53d6\u8fbc\u307f\u306f\u73fe\u5728\u5b9f\u884c\u4e2d\u3067\u3059\u3002
\u5168\u3066\u306e\u30d5\u30a1\u30a4\u30eb\u304c\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u306b\u767b\u9332\u3055\u308c\u3066\u307e\u305b\u3093\u3001\u30e6\u30cb\u30fc\u30af\u306a\u5358\u8a9e\u3092\u62bd\u51fa\u3059\u308b\u3068\u4e0d\u5b8c\u5168\u306a\u7d50\u679c\u306b\u306a\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002
\u305d\u308c\u3067\u3082\u30e6\u30cb\u30fc\u30af\u306a\u5358\u8a9e\u306e\u62bd\u51fa\u3092\u7d9a\u884c\u3057\u307e\u3059\u304b\uff1f +ExtractAllTermsReport.search.noFilesInIdxMsg=\u307e\u3060\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u306b\u767b\u9332\u3055\u308c\u3066\u3044\u308b\u30d5\u30a1\u30a4\u30eb\u306f\u3042\u308a\u307e\u305b\u3093\u3002 \u3042\u3068\u3067\u3082\u3046\u4e00\u5ea6\u8a66\u3057\u3066\u304f\u3060\u3055\u3044\u3002 \u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u306f{0}\u5206\u3054\u3068\u306b\u66f4\u65b0\u3055\u308c\u307e\u3059\u3002 +ExtractAllTermsReport.search.noFilesInIdxMsg2=\u307e\u3060\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u306b\u767b\u9332\u3055\u308c\u3066\u3044\u308b\u30d5\u30a1\u30a4\u30eb\u306f\u3042\u308a\u307e\u305b\u3093\u3002 \u3042\u3068\u3067\u3082\u3046\u4e00\u5ea6\u8a66\u3057\u3066\u304f\u3060\u3055\u3044\u3002 +ExtractAllTermsReport.search.searchIngestInProgressTitle=\u30ad\u30fc\u30ef\u30fc\u30c9\u691c\u7d22\u306e\u53d6\u8fbc\u307f\u304c\u9032\u884c\u4e2d +ExtractAllTermsReport.startExport=\u30e6\u30cb\u30fc\u30af\u306a\u5358\u8a9e\u62bd\u51fa\u306e\u958b\u59cb ExtractedContentPanel.SetMarkup.progress.loading={0} \u306e\u30c6\u30ad\u30b9\u30c8\u3092\u8aad\u307f\u8fbc\u3093\u3067\u3044\u307e\u3059 ExtractedContentPanel.copyMenuItem.text=\u30b3\u30d4\u30fc ExtractedContentPanel.hitButtonsLabel.text=\u4e00\u81f4\u3059\u308b\u7d50\u679c @@ -186,6 +198,7 @@ KeywordSearchEditListPanel.selectAllMenuItem.text=\u3059\u3079\u3066\u9078\u629e KeywordSearchFilterNode.getFileActions.openExternViewActLbl=\u5916\u90e8\u30d3\u30e5\u30fc\u30ef\u30fc\u3067\u958b\u304f Ctrl+E KeywordSearchFilterNode.getFileActions.searchSameMd5=\u540c\u3058MD5\u30cf\u30c3\u30b7\u30e5\u3067\u30d5\u30a1\u30a4\u30eb\u3092\u691c\u7d22 KeywordSearchFilterNode.getFileActions.viewInNewWinActionLbl=\u65b0\u3057\u3044\u30a6\u30a3\u30f3\u30c9\u30a6\u3067\u8868\u793a +KeywordSearchGlobalLanguageSettingsPanel.enableOcrCheckbox.text=OCR\u3092\u6709\u52b9\u306b\u3059\u308b KeywordSearchGlobalLanguageSettingsPanel.enableUTF16Checkbox.text=UTF16LE\u304a\u3088\u3073UTF16BE\u6587\u5b57\u5217\u62bd\u51fa\u3092\u6709\u52b9\u5316 KeywordSearchGlobalLanguageSettingsPanel.enableUTF8Checkbox.text=UTF8\u30c6\u30ad\u30b9\u30c8\u62bd\u51fa\u3092\u6709\u52b9\u5316\u3059\u308b KeywordSearchGlobalLanguageSettingsPanel.ingestSettingsLabel.text=\u672a\u77e5\u306e\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7\u304b\u3089\u306e\u6587\u5b57\u5217\u62bd\u51fa\u306e\u305f\u3081\u306e\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u8a2d\u5b9a(\u5909\u66f4\u306f\u6b21\u306e\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u3067\u6709\u52b9\u306b\u306a\u308a\u307e\u3059)\: @@ -194,13 +207,13 @@ KeywordSearchGlobalLanguageSettingsPanel.languagesLabel.text=\u6709\u52b9\u5316\ KeywordSearchGlobalListSettingsPanel.component.featureName.text=\u30ad\u30fc\u30ef\u30fc\u30c9\u30ea\u30b9\u30c8\u3092\u4fdd\u5b58 KeywordSearchGlobalSearchSettingsPanel.chunksLabel.text=\u30ad\u30fc\u30ef\u30fc\u30c9\u7d22\u5f15\u5185\u306e\u30c1\u30e3\u30f3\u30af\: KeywordSearchGlobalSearchSettingsPanel.chunksValLabel.text=0 +KeywordSearchGlobalSearchSettingsPanel.customizeComponents.windowsLimitedOCR=\u91cd\u91cf\u304c100KB\u3092\u8d85\u3048\u308b\u753b\u50cf\u3001\u307e\u305f\u306f\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8\u304b\u3089\u62bd\u51fa\u3055\u308c\u305f\u753b\u50cf\u306e\u307f\u3092\u51e6\u7406\u3059\u308b\u3002 \uff08\u30d9\u30fc\u30bf\u7248\uff09\uff08Windows 64\u30d3\u30c3\u30c8\u304c\u5fc5\u8981\uff09 KeywordSearchGlobalSearchSettingsPanel.customizeComponents.windowsOCR=OCR\u6587\u5b57\u8a8d\u8b58\u3092\u6709\u52b9\u306b\u3059\u308b\uff08Windows 64\u30d3\u30c3\u30c8\u304c\u5fc5\u8981\uff09 KeywordSearchGlobalSearchSettingsPanel.filesIndexedLabel.text=\u30ad\u30fc\u30ef\u30fc\u30c9\u7d22\u5f15\u5185\u306e\u30d5\u30a1\u30a4\u30eb\: KeywordSearchGlobalSearchSettingsPanel.filesIndexedValue.text=0 KeywordSearchGlobalSearchSettingsPanel.frequencyLabel.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u4e2d\u306e\u7d50\u679c\u66f4\u65b0\u983b\u5ea6\: KeywordSearchGlobalSearchSettingsPanel.informationLabel.text=\u60c5\u5831 KeywordSearchGlobalSearchSettingsPanel.ingestWarningLabel.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u304c\u9032\u884c\u4e2d\u3067\u3059\u3002\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u304c\u5b8c\u4e86\u3059\u308b\u307e\u3067\u4e00\u90e8\u306e\u8a2d\u5b9a\u3092\u5229\u7528\u3067\u304d\u307e\u305b\u3093\u3002 -KeywordSearchGlobalSearchSettingsPanel.ocrCheckBox.text=OCR\u6587\u5b57\u8a8d\u8b58\u3092\u6709\u52b9\u306b\u3059\u308b KeywordSearchGlobalSearchSettingsPanel.settingsLabel.text=\u8a2d\u5b9a KeywordSearchGlobalSearchSettingsPanel.showSnippetsCB.text=\u30ad\u30fc\u30ef\u30fc\u30c9\u691c\u7d22\u7d50\u679c\u306b\u30ad\u30fc\u30ef\u30fc\u30c9\u30d7\u30ec\u30d3\u30e5\u30fc\u3092\u8868\u793a(\u691c\u7d22\u6642\u9593\u304c\u9577\u304f\u306a\u308a\u307e\u3059) KeywordSearchGlobalSearchSettingsPanel.skipNSRLCheckBox.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u4e2d\u306bNSRL(\u65e2\u77e5\u306e\u30d5\u30a1\u30a4\u30eb)\u306e\u30d5\u30a1\u30a4\u30eb\u3092\u30ad\u30fc\u30ef\u30fc\u30c9\u306b\u8ffd\u52a0\u3057\u306a\u3044\u3067\u304f\u3060\u3055\u3044 @@ -256,6 +269,9 @@ KeywordSearchJobSettingsPanel.languagesLabel.text=\u672a\u77e5\u306e\u30d5\u30a1 KeywordSearchJobSettingsPanel.languagesLabel.toolTipText=\u672a\u77e5\u306e\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7\u304b\u3089\u306e\u6587\u5b57\u5217\u62bd\u51fa\u306e\u305f\u3081\u306b\u6709\u52b9\u5316\u3055\u308c\u305f\u6587\u5b57\u5217\u3067\u3059\u3002\u8a73\u7d30\u8a2d\u5b9a\u3067\u5909\u66f4\u3092\u884c\u3048\u307e\u3059\u3002 KeywordSearchJobSettingsPanel.languagesValLabel.text=- KeywordSearchJobSettingsPanel.languagesValLabel.toolTipText= +KeywordSearchJobSettingsPanel.limitedOcrCheckbox.text=\u91cd\u91cf\u304c100KB\u3092\u8d85\u3048\u308b\u753b\u50cf\u3001\u307e\u305f\u306f\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8\u304b\u3089\u62bd\u51fa\u3055\u308c\u305f\u753b\u50cf\u306e\u307f\u3092\u51e6\u7406\u3057\u307e\u3059\uff08\u30d9\u30fc\u30bf\u7248\uff09 +KeywordSearchJobSettingsPanel.ocrCheckBox.text=OCR\u6587\u5b57\u8a8d\u8b58\u3092\u6709\u52b9\u306b\u3059\u308b +KeywordSearchJobSettingsPanel.ocrOnlyCheckbox.text=OCR\u3092\u4f7f\u7528\u3057\u3066\u62bd\u51fa\u3055\u308c\u305f\u30c6\u30ad\u30b9\u30c8\u306e\u307f\u3092\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u3059\u308b\u3002 KeywordSearchJobSettingsPanel.titleLabel.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u4e2d\u306b\u6709\u52b9\u5316\u3059\u308b\u30ad\u30fc\u30ef\u30fc\u30c9\u30ea\u30b9\u30c8\u3092\u9078\u629e\: KeywordSearchListsAbstract.addList.errMsg1.msg=KeywordSearchListsAbstract\u66f4\u65b0\u306e\u30ea\u30c3\u30b9\u30f3\u4e2d\u306b\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u30a8\u30e9\u30fc\u3092\u767a\u751f\u3055\u305b\u307e\u3057\u305f\u3002\u30ed\u30b0\u3092\u78ba\u8a8d\u3057\u3066\u3069\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u5224\u65ad\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u4e00\u90e8\u306e\u30c7\u30fc\u30bf\u304c\u4e0d\u5b8c\u5168\u3067\u3042\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 KeywordSearchListsAbstract.addList.errMsg2.msg=KeywordSearchListsAbstract\u66f4\u65b0\u306e\u30ea\u30c3\u30b9\u30f3\u4e2d\u306b\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u30a8\u30e9\u30fc\u3092\u767a\u751f\u3055\u305b\u307e\u3057\u305f\u3002\u30ed\u30b0\u3092\u78ba\u8a8d\u3057\u3066\u3069\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u5224\u65ad\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u4e00\u90e8\u306e\u30c7\u30fc\u30bf\u304c\u4e0d\u5b8c\u5168\u3067\u3042\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 @@ -333,11 +349,12 @@ Server.deleteCore.exception.msg=Solr\u30b3\u30ec\u30af\u30b7\u30e7\u30f3{0}\u306 Server.exceptionMessage.unableToBackupCollection=Solr\u30b3\u30ec\u30af\u30b7\u30e7\u30f3\u3092\u30d0\u30c3\u30af\u30a2\u30c3\u30d7\u3067\u304d\u307e\u305b\u3093 Server.exceptionMessage.unableToCreateCollection=Solr\u30b3\u30ec\u30af\u30b7\u30e7\u30f3\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093 Server.exceptionMessage.unableToRestoreCollection=Solr\u30b3\u30ec\u30af\u30b7\u30e7\u30f3\u3092\u5fa9\u5143\u3067\u304d\u307e\u305b\u3093 +Server.getAllTerms.error=\u5168\u3066\u306e\u30e6\u30cb\u30fc\u30af\u306aSolr\u7528\u8a9e\u306e\u62bd\u51fa\u306b\u5931\u6557\u3057\u307e\u3057\u305f\uff1a Server.isRunning.exception.errCheckSolrRunning.msg=Solr\u30b5\u30fc\u30d0\u30fc\u304c\u5b9f\u884c\u4e2d\u304b\u3069\u3046\u304b\u3092\u78ba\u8a8d\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f Server.isRunning.exception.errCheckSolrRunning.msg2=Solr\u30b5\u30fc\u30d0\u30fc\u304c\u5b9f\u884c\u4e2d\u304b\u3069\u3046\u304b\u3092\u78ba\u8a8d\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f Server.openCore.exception.alreadyOpen.msg=\u958b\u3044\u3066\u3044\u308bSolr\u306e\u30b3\u30a2\u304c\u3059\u3067\u306b\u3042\u308a\u307e\u3059\u3002\u6700\u521d\u306b\u30b3\u30a2\u3092\u660e\u793a\u7684\u306b\u9589\u3058\u3066\u304f\u3060\u3055\u3044\u3002 Server.openCore.exception.cantOpen.msg=\u7d22\u5f15\u3092\u4f5c\u6210\u307e\u305f\u306f\u958b\u3051\u307e\u305b\u3093\u3067\u3057\u305f -Server.openCore.exception.msg=\u30ad\u30fc\u30ef\u30fc\u30c9\u691c\u7d22\u30b5\u30fc\u30d3\u30b9\u306f\u307e\u3060\u5b9f\u884c\u3057\u3066\u3044\u307e\u305b\u3093 +Server.openCore.exception.msg=\u30ed\u30fc\u30ab\u30eb\u30ad\u30fc\u30ef\u30fc\u30c9\u691c\u7d22\u30b5\u30fc\u30d3\u30b9\u306f\u307e\u3060\u5b9f\u884c\u3055\u308c\u3066\u3044\u307e\u305b\u3093 Server.openCore.exception.noIndexDir.msg=\u7d22\u5f15\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u30fc\u3092\u4f5c\u6210\u3067\u304d\u306a\u304b\u3063\u305f\u304b\u3001\u898b\u3064\u304b\u308a\u307e\u305b\u3093 Server.query.exception.msg=\u6b21\u306e\u30af\u30a8\u30ea\u306e\u5b9f\u884c\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\: {0} Server.query2.exception.msg=\u6b21\u306e\u30af\u30a8\u30ea\u306e\u5b9f\u884c\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\: {0} @@ -352,6 +369,7 @@ Server.serverList.exception.msg=\u30b5\u30fc\u30d0\u30fc{0}\u304b\u3089Solr\u30b Server.solrServerNoPortException.msg=\u7d22\u5f15\u751f\u6210\u30b5\u30fc\u30d0\u30fc\u306f\u30dd\u30fc\u30c8 {0} \u306b\u30d0\u30a4\u30f3\u30c9\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u30c7\u30d5\u30a9\u30eb\u30c8\u306e {1} \u30dd\u30fc\u30c8\u306b\u5909\u66f4\u3059\u308b\u3053\u3068\u3092\u691c\u8a0e\u3057\u3066\u304f\u3060\u3055\u3044\u3002 Server.start.exception.cantStartSolr.msg=Solr\u30b5\u30fc\u30d0\u30fc\u30d7\u30ed\u30bb\u30b9\u3092\u958b\u59cb\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f Server.start.exception.cantStartSolr.msg2=Solr\u30b5\u30fc\u30d0\u30fc\u30d7\u30ed\u30bb\u30b9\u3092\u958b\u59cb\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f +Server.status.failed.msg=\u30ed\u30fc\u30ab\u30ebSolr\u30b5\u30fc\u30d0\u30fc\u304c\u30b9\u30c6\u30fc\u30bf\u30b9\u8981\u6c42\u306b\u5fdc\u7b54\u3057\u307e\u305b\u3093\u3067\u3057\u305f\u3002 \u3053\u308c\u306f\u3001\u30b5\u30fc\u30d0\u30fc\u306e\u8d77\u52d5\u306b\u5931\u6557\u3057\u305f\u304b\u3001\u521d\u671f\u5316\u306b\u6642\u9593\u304c\u304b\u304b\u308a\u3059\u304e\u3066\u3044\u308b\u3053\u3068\u304c\u539f\u56e0\u3067\u3042\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 SolrConnectionCheck.Hostname=\u7121\u52b9\u306a\u30db\u30b9\u30c8\u540d\u3067\u3059\u3002 SolrConnectionCheck.HostnameOrPort=\u7121\u52b9\u306a\u30db\u30b9\u30c8\u540d\u304a\u3088\u3073/\u307e\u305f\u306f\u30dd\u30fc\u30c8\u756a\u53f7\u3067\u3059\u3002 SolrConnectionCheck.MissingHostname=\u30db\u30b9\u30c8\u540d\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3002 @@ -360,13 +378,17 @@ SolrSearch.checkingForLatestIndex.msg=\u6700\u65b0\u306eSolr\u3068\u30b9\u30ad\u SolrSearch.complete.msg=\u30c6\u30ad\u30b9\u30c8\u7d22\u5f15\u304c\u6b63\u5e38\u306b\u958b\u304d\u307e\u3057\u305f SolrSearch.creatingNewIndex.msg=\u65b0\u898f\u30c6\u30ad\u30b9\u30c8\u7d22\u5f15\u3092\u751f\u6210\u4e2d\u3067\u3059 SolrSearch.findingIndexes.msg=\u65e2\u5b58\u306e\u30c6\u30ad\u30b9\u30c8\u7d22\u5f15\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u30fc\u3092\u691c\u7d22\u4e2d\u3067\u3059 +SolrSearch.futureIndexVersion.msg=\u30b1\u30fc\u30b9\u306e\u30c6\u30ad\u30b9\u30c8\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u306fSolr {0}\u7528\u3067\u3059\u3002 \u3053\u306e\u30d0\u30fc\u30b8\u30e7\u30f3\u306eAutopsy\u306f\u3001Solr {1}\u3068\u4e92\u63db\u6027\u304c\u3042\u308a\u307e\u3059\u3002 SolrSearch.indentifyingIndex.msg=\u4f7f\u7528\u3059\u308b\u30c6\u30ad\u30b9\u30c8\u7d22\u5f15\u3092\u7279\u5b9a\u4e2d\u3067\u3059 SolrSearch.lookingForMetadata.msg=\u30c6\u30ad\u30b9\u30c8\u7d22\u5f15\u306e\u30e1\u30bf\u30c7\u30fc\u30bf\u30d5\u30a1\u30a4\u30eb\u3092\u691c\u7d22\u4e2d\u3067\u3059 SolrSearch.openCore.msg=\u30c6\u30ad\u30b9\u30c8\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u3092\u958b\u304d\u307e\u3059\u3002 \u3053\u308c\u306b\u306f\u6570\u5206\u304b\u304b\u308b\u5834\u5408\u304c\u3042\u308a\u307e\u3059\u3002 SolrSearch.readingIndexes.msg=\u30c6\u30ad\u30b9\u30c8\u7d22\u5f15\u306e\u30e1\u30bf\u30c7\u30fc\u30bf\u30d5\u30a1\u30a4\u30eb\u3092\u8aad\u307f\u8fbc\u307f\u4e2d\u3067\u3059 +SolrSearch.unableToFindIndex.msg=\u30b1\u30fc\u30b9\u306b\u4f7f\u7528\u3067\u304d\u308b\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093 +SolrSearchService.DeleteDataSource.msg=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9ID {0}\u306eSolr\u30c7\u30fc\u30bf\u306e\u524a\u9664\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f SolrSearchService.ServiceName=Solr\u30ad\u30fc\u30ef\u30fc\u30c9\u691c\u7d22\u30b5\u30fc\u30d3\u30b9 SolrSearchService.exceptionMessage.failedToDeleteIndexFiles={0} \u306e\u30c6\u30ad\u30b9\u30c8\u7d22\u5f15\u30d5\u30a1\u30a4\u30eb\u3092\u524a\u9664\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f SolrSearchService.exceptionMessage.noCurrentSolrCore=IndexMetadata\u306b\u306f\u73fe\u5728\u306eSolr\u306e\u30b3\u30a2\u304c\u542b\u307e\u308c\u3066\u3044\u306a\u304b\u3063\u305f\u305f\u3081\u3001\u30b1\u30fc\u30b9\u3092\u524a\u9664\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f SolrSearchService.exceptionMessage.noIndexMetadata=\u30b1\u30fc\u30b9\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u30fc\u304b\u3089\u6b21\u306eIndexMetaData\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\: {0} SolrSearchService.exceptionMessage.unableToDeleteCollection=\u30b3\u30ec\u30af\u30b7\u30e7\u30f3{0}\u3092\u524a\u9664\u3067\u304d\u307e\u305b\u3093 +SolrSearchService.indexingError=\u9ed2\u677f\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u306b\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u3092\u4ed8\u3051\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u305b\u3093\u3002 TextZoomPanel.zoomResetButton.text=\u30ea\u30bb\u30c3\u30c8 diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractAllTermsReport.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractAllTermsReport.java index b3a754d6b8..88178b42ea 100755 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractAllTermsReport.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractAllTermsReport.java @@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.keywordsearch; import java.nio.file.Path; import java.nio.file.Paths; import java.util.logging.Level; +import javax.swing.JPanel; import org.openide.util.NbBundle; import org.openide.util.lookup.ServiceProvider; import org.sleuthkit.autopsy.casemodule.Case; @@ -29,6 +30,7 @@ import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.report.GeneralReportModule; import org.sleuthkit.autopsy.report.GeneralReportSettings; import org.sleuthkit.autopsy.report.ReportProgressPanel; +import org.sleuthkit.autopsy.keywordsearch.infastructure.NoReportConfigurationPanel; /** * Instances of this class plug in to the reporting infrastructure to provide a @@ -125,6 +127,10 @@ public class ExtractAllTermsReport implements GeneralReportModule { public String getDescription() { return Bundle.ExtractAllTermsReport_description_text(); } + @Override + public JPanel getConfigurationPanel() { + return new NoReportConfigurationPanel(); + } @Override public String getRelativeFilePath() { diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentPanel.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentPanel.java index 8ff9c0fdcc..c64cee2565 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentPanel.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2020 Basis Technology Corp. + * Copyright 2011-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -29,10 +29,10 @@ import java.util.List; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; import java.util.logging.Level; -import javax.swing.JLabel; import javax.swing.SizeRequirements; import javax.swing.SwingUtilities; import javax.swing.SwingWorker; +import javax.swing.UIManager; import javax.swing.text.Element; import javax.swing.text.View; import javax.swing.text.ViewFactory; @@ -59,7 +59,7 @@ class ExtractedContentPanel extends javax.swing.JPanel implements ResizableTextP private static final Logger logger = Logger.getLogger(ExtractedContentPanel.class.getName()); // set font as close as possible to default - private static final Font DEFAULT_FONT = new JLabel().getFont(); + private static final Font DEFAULT_FONT = UIManager.getDefaults().getFont("Label.font"); private static final long serialVersionUID = 1L; private String contentName; @@ -72,7 +72,6 @@ class ExtractedContentPanel extends javax.swing.JPanel implements ResizableTextP ExtractedContentPanel() { initComponents(); additionalInit(); - setSources("", new ArrayList<>()); hitPreviousButton.setEnabled(false); hitNextButton.setEnabled(false); @@ -135,7 +134,7 @@ class ExtractedContentPanel extends javax.swing.JPanel implements ResizableTextP }; } }; - // get the style sheet for editing font size + // set new style sheet to clear default styles styleSheet = editorKit.getStyleSheet(); sourceComboBox.addItemListener(itemEvent -> { @@ -144,6 +143,7 @@ class ExtractedContentPanel extends javax.swing.JPanel implements ResizableTextP } }); extractedTextPane.setComponentPopupMenu(rightClickMenu); + copyMenuItem.addActionListener(actionEvent -> extractedTextPane.copy()); selectAllMenuItem.addActionListener(actionEvent -> extractedTextPane.selectAll()); @@ -156,11 +156,16 @@ class ExtractedContentPanel extends javax.swing.JPanel implements ResizableTextP if (zoomPanel instanceof TextZoomPanel) ((TextZoomPanel) this.zoomPanel).resetSize(); }); + + setSources("", new ArrayList<>()); } private void setStyleSheetSize(StyleSheet styleSheet, int size) { - styleSheet.addRule("body {font-family:\"" + DEFAULT_FONT.getFamily() + "\"; font-size:" + size + "pt; } "); + styleSheet.addRule( + "body { font-family:\"" + DEFAULT_FONT.getFamily() + "\"; font-size:" + size + "pt; } " + + "pre { font-family:\"" + DEFAULT_FONT.getFamily() + "\"; font-size:" + size + "pt; } " + ); } @@ -499,6 +504,8 @@ class ExtractedContentPanel extends javax.swing.JPanel implements ResizableTextP extractedTextPane.applyComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT); } + // refresh style + setStyleSheetSize(styleSheet, curSize); extractedTextPane.setText(safeText); extractedTextPane.setCaretPosition(0); } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Ingester.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Ingester.java index 24a42041dd..052a0b0b16 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Ingester.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Ingester.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2018 Basis Technology Corp. + * Copyright 2011-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -30,6 +30,7 @@ import org.apache.solr.client.solrj.SolrServerException; import org.apache.solr.common.SolrInputDocument; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.TimeZoneUtils; import org.sleuthkit.autopsy.datamodel.ContentUtils; import org.sleuthkit.autopsy.healthmonitor.HealthMonitor; import org.sleuthkit.autopsy.healthmonitor.TimingMetric; @@ -63,6 +64,7 @@ class Ingester { private static Ingester instance; private final LanguageSpecificContentIndexingHelper languageSpecificContentIndexingHelper = new LanguageSpecificContentIndexingHelper(); + private static final int LANGUAGE_DETECTION_STRING_SIZE = 4096; private Ingester() { } @@ -197,6 +199,7 @@ class Ingester { int numChunks = 0; //unknown until chunking is done Map contentFields = Collections.unmodifiableMap(getContentFields(source)); + Optional language = Optional.empty(); //Get a reader for the content of the given source try (BufferedReader reader = new BufferedReader(sourceReader)) { Chunker chunker = new Chunker(reader); @@ -211,11 +214,15 @@ class Ingester { String chunkId = Server.getChunkIdString(sourceID, numChunks + 1); fields.put(Server.Schema.ID.toString(), chunkId); fields.put(Server.Schema.CHUNK_SIZE.toString(), String.valueOf(chunk.getBaseChunkLength())); - Optional language = Optional.empty(); + if (doLanguageDetection) { - language = languageSpecificContentIndexingHelper.detectLanguageIfNeeded(chunk); - language.ifPresent(lang -> languageSpecificContentIndexingHelper.updateLanguageSpecificFields(fields, chunk, lang)); + int size = Math.min(chunk.getBaseChunkLength(), LANGUAGE_DETECTION_STRING_SIZE); + language = languageSpecificContentIndexingHelper.detectLanguageIfNeeded(chunk.toString().substring(0, size)); + + // only do language detection on the first chunk of the document + doLanguageDetection = false; } + language.ifPresent(lang -> languageSpecificContentIndexingHelper.updateLanguageSpecificFields(fields, chunk, lang)); try { //add the chunk text to Solr index indexChunk(chunk.toString(), chunk.geLowerCasedChunk(), sourceName, fields); @@ -389,10 +396,10 @@ class Ingester { */ private Map getCommonAndMACTimeFields(AbstractFile file) { Map params = getCommonFields(file); - params.put(Server.Schema.CTIME.toString(), ContentUtils.getStringTimeISO8601(file.getCtime(), file)); - params.put(Server.Schema.ATIME.toString(), ContentUtils.getStringTimeISO8601(file.getAtime(), file)); - params.put(Server.Schema.MTIME.toString(), ContentUtils.getStringTimeISO8601(file.getMtime(), file)); - params.put(Server.Schema.CRTIME.toString(), ContentUtils.getStringTimeISO8601(file.getCrtime(), file)); + params.put(Server.Schema.CTIME.toString(), TimeZoneUtils.getFormattedTimeISO8601(file.getCtime())); + params.put(Server.Schema.ATIME.toString(), TimeZoneUtils.getFormattedTimeISO8601(file.getAtime())); + params.put(Server.Schema.MTIME.toString(), TimeZoneUtils.getFormattedTimeISO8601(file.getMtime())); + params.put(Server.Schema.CRTIME.toString(), TimeZoneUtils.getFormattedTimeISO8601(file.getCrtime())); return params; } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchGlobalSearchSettingsPanel.form b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchGlobalSearchSettingsPanel.form index 550ad5d442..4a0cadaefd 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchGlobalSearchSettingsPanel.form +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchGlobalSearchSettingsPanel.form @@ -23,25 +23,25 @@ - + - - - - - + + + + + + + + - + - - - @@ -49,7 +49,12 @@ - + + + + + + @@ -58,22 +63,18 @@ - - - - - - - - - - + + + + + + + - @@ -90,10 +91,6 @@ - - - - @@ -279,25 +276,5 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchGlobalSearchSettingsPanel.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchGlobalSearchSettingsPanel.java index b9687a32c2..ccd1de71da 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchGlobalSearchSettingsPanel.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchGlobalSearchSettingsPanel.java @@ -50,13 +50,9 @@ class KeywordSearchGlobalSearchSettingsPanel extends javax.swing.JPanel implemen private void activateWidgets() { skipNSRLCheckBox.setSelected(KeywordSearchSettings.getSkipKnown()); showSnippetsCB.setSelected(KeywordSearchSettings.getShowSnippets()); - ocrCheckBox.setSelected(KeywordSearchSettings.getOcrOption()); - limitedOcrCheckbox.setSelected(KeywordSearchSettings.getLimitedOcrOption()); boolean ingestRunning = IngestManager.getInstance().isIngestRunning(); ingestWarningLabel.setVisible(ingestRunning); skipNSRLCheckBox.setEnabled(!ingestRunning); - ocrCheckBox.setEnabled(!ingestRunning); - limitedOcrCheckbox.setEnabled(ocrCheckBox.isSelected() && !ingestRunning); setTimeSettingEnabled(!ingestRunning); final UpdateFrequency curFreq = KeywordSearchSettings.getUpdateFrequency(); @@ -111,8 +107,6 @@ class KeywordSearchGlobalSearchSettingsPanel extends javax.swing.JPanel implemen showSnippetsCB = new javax.swing.JCheckBox(); timeRadioButton5 = new javax.swing.JRadioButton(); ingestWarningLabel = new javax.swing.JLabel(); - ocrCheckBox = new javax.swing.JCheckBox(); - limitedOcrCheckbox = new javax.swing.JCheckBox(); skipNSRLCheckBox.setText(org.openide.util.NbBundle.getMessage(KeywordSearchGlobalSearchSettingsPanel.class, "KeywordSearchGlobalSearchSettingsPanel.skipNSRLCheckBox.text")); // NOI18N skipNSRLCheckBox.setToolTipText(org.openide.util.NbBundle.getMessage(KeywordSearchGlobalSearchSettingsPanel.class, "KeywordSearchGlobalSearchSettingsPanel.skipNSRLCheckBox.toolTipText")); // NOI18N @@ -186,20 +180,6 @@ class KeywordSearchGlobalSearchSettingsPanel extends javax.swing.JPanel implemen ingestWarningLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/modules/hashdatabase/warning16.png"))); // NOI18N ingestWarningLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchGlobalSearchSettingsPanel.class, "KeywordSearchGlobalSearchSettingsPanel.ingestWarningLabel.text")); // NOI18N - ocrCheckBox.setText(org.openide.util.NbBundle.getMessage(KeywordSearchGlobalSearchSettingsPanel.class, "KeywordSearchGlobalSearchSettingsPanel.ocrCheckBox.text")); // NOI18N - ocrCheckBox.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - ocrCheckBoxActionPerformed(evt); - } - }); - - limitedOcrCheckbox.setText(org.openide.util.NbBundle.getMessage(KeywordSearchGlobalSearchSettingsPanel.class, "KeywordSearchGlobalSearchSettingsPanel.limitedOcrCheckbox.text")); // NOI18N - limitedOcrCheckbox.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - limitedOcrCheckboxActionPerformed(evt); - } - }); - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( @@ -207,13 +187,15 @@ class KeywordSearchGlobalSearchSettingsPanel extends javax.swing.JPanel implemen .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(ingestWarningLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(layout.createSequentialGroup() + .addGap(16, 16, 16) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(skipNSRLCheckBox) + .addComponent(showSnippetsCB)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addGroup(layout.createSequentialGroup() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addComponent(settingsLabel) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(settingsSeparator, javax.swing.GroupLayout.PREFERRED_SIZE, 326, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(ingestWarningLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(layout.createSequentialGroup() .addComponent(informationLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) @@ -221,14 +203,15 @@ class KeywordSearchGlobalSearchSettingsPanel extends javax.swing.JPanel implemen .addGroup(layout.createSequentialGroup() .addGap(16, 16, 16) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(skipNSRLCheckBox) - .addComponent(showSnippetsCB) - .addComponent(ocrCheckBox) .addGroup(layout.createSequentialGroup() .addComponent(filesIndexedLabel) .addGap(18, 18, 18) .addComponent(filesIndexedValue)) .addComponent(frequencyLabel) + .addGroup(layout.createSequentialGroup() + .addComponent(chunksLabel) + .addGap(18, 18, 18) + .addComponent(chunksValLabel)) .addGroup(layout.createSequentialGroup() .addGap(16, 16, 16) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -236,16 +219,13 @@ class KeywordSearchGlobalSearchSettingsPanel extends javax.swing.JPanel implemen .addComponent(timeRadioButton1) .addComponent(timeRadioButton3) .addComponent(timeRadioButton4) - .addComponent(timeRadioButton5))) - .addGroup(layout.createSequentialGroup() - .addComponent(chunksLabel) - .addGap(18, 18, 18) - .addComponent(chunksValLabel)) - .addGroup(layout.createSequentialGroup() - .addGap(16, 16, 16) - .addComponent(limitedOcrCheckbox))))) - .addGap(0, 0, Short.MAX_VALUE))) - .addContainerGap()) + .addComponent(timeRadioButton5)))))) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGroup(layout.createSequentialGroup() + .addComponent(settingsLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(settingsSeparator, javax.swing.GroupLayout.PREFERRED_SIZE, 326, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))) ); layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {chunksLabel, filesIndexedLabel}); @@ -262,10 +242,6 @@ class KeywordSearchGlobalSearchSettingsPanel extends javax.swing.JPanel implemen .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(showSnippetsCB) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(ocrCheckBox) - .addGap(0, 0, 0) - .addComponent(limitedOcrCheckbox) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(frequencyLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(timeRadioButton1) @@ -323,15 +299,6 @@ class KeywordSearchGlobalSearchSettingsPanel extends javax.swing.JPanel implemen firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); }//GEN-LAST:event_timeRadioButton4ActionPerformed - private void ocrCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_ocrCheckBoxActionPerformed - limitedOcrCheckbox.setEnabled(ocrCheckBox.isSelected()); - firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); - }//GEN-LAST:event_ocrCheckBoxActionPerformed - - private void limitedOcrCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_limitedOcrCheckboxActionPerformed - firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); - }//GEN-LAST:event_limitedOcrCheckboxActionPerformed - // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JLabel chunksLabel; private javax.swing.JLabel chunksValLabel; @@ -341,8 +308,6 @@ class KeywordSearchGlobalSearchSettingsPanel extends javax.swing.JPanel implemen private javax.swing.JLabel informationLabel; private javax.swing.JSeparator informationSeparator; private javax.swing.JLabel ingestWarningLabel; - private javax.swing.JCheckBox limitedOcrCheckbox; - private javax.swing.JCheckBox ocrCheckBox; private javax.swing.JLabel settingsLabel; private javax.swing.JSeparator settingsSeparator; private javax.swing.JCheckBox showSnippetsCB; @@ -360,8 +325,6 @@ class KeywordSearchGlobalSearchSettingsPanel extends javax.swing.JPanel implemen KeywordSearchSettings.setSkipKnown(skipNSRLCheckBox.isSelected()); KeywordSearchSettings.setUpdateFrequency(getSelectedTimeValue()); KeywordSearchSettings.setShowSnippets(showSnippetsCB.isSelected()); - KeywordSearchSettings.setOcrOption(ocrCheckBox.isSelected()); - KeywordSearchSettings.setLimitedOcrOption(limitedOcrCheckbox.isSelected()); } @Override @@ -412,15 +375,6 @@ class KeywordSearchGlobalSearchSettingsPanel extends javax.swing.JPanel implemen logger.log(Level.WARNING, "Could not get number of indexed files/chunks"); //NON-NLS } - if (!PlatformUtil.isWindowsOS() || !PlatformUtil.is64BitOS()) { - ocrCheckBox.setText(Bundle.KeywordSearchGlobalSearchSettingsPanel_customizeComponents_windowsOCR()); - ocrCheckBox.setSelected(false); - ocrCheckBox.setEnabled(false); - limitedOcrCheckbox.setSelected(false); - limitedOcrCheckbox.setEnabled(false); - limitedOcrCheckbox.setText(Bundle.KeywordSearchGlobalSearchSettingsPanel_customizeComponents_windowsLimitedOCR()); - } - KeywordSearch.addNumIndexedFilesChangeListener( new PropertyChangeListener() { @Override diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestModule.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestModule.java index 034f53af74..d350bfea6d 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestModule.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestModule.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2019 Basis Technology Corp. + * Copyright 2011-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.keywordsearch; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; import com.google.common.io.CharSource; import java.io.IOException; import java.io.Reader; @@ -32,6 +33,7 @@ import java.util.HashMap; import java.util.List; import static java.util.Locale.US; import java.util.Map; +import java.util.Optional; import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Level; import java.util.stream.Collectors; @@ -43,7 +45,6 @@ import org.openide.util.lookup.Lookups; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.coreutils.ExecUtil.ProcessTerminator; -import org.sleuthkit.autopsy.coreutils.ExecUtil.TimedProcessTerminator; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.ingest.FileIngestModule; @@ -87,6 +88,8 @@ import org.sleuthkit.datamodel.TskData.FileKnown; }) public final class KeywordSearchIngestModule implements FileIngestModule { + private static final int LIMITED_OCR_SIZE_MIN = 100 * 1024; + /** * generally text extractors should ignore archives and let unpacking * modules take care of them @@ -132,19 +135,31 @@ public final class KeywordSearchIngestModule implements FileIngestModule { "Last-Printed", //NON-NLS "Creation-Date"); //NON-NLS - private static final Map METADATA_TYPES_MAP = ImmutableMap.builder() - .put("Last-Save-Date", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_MODIFIED) - .put("Last-Author", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_USER_ID) - .put("Creation-Date", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED) - .put("Company", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ORGANIZATION) - .put("Author", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_OWNER) - .put("Application-Name", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME) - .put("Last-Printed", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_LAST_PRINTED_DATETIME) - .put("Producer", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME) - .put("Title", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DESCRIPTION) - .put("pdf:PDFVersion", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_VERSION) - .build(); + private static final Map METADATA_TYPES_MAP = ImmutableMap.builder() + .put("Last-Save-Date", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_MODIFIED) + .put("Last-Author", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_USER_ID) + .put("Creation-Date", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED) + .put("Company", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ORGANIZATION) + .put("Author", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_OWNER) + .put("Application-Name", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME) + .put("Last-Printed", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_LAST_PRINTED_DATETIME) + .put("Producer", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME) + .put("Title", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DESCRIPTION) + .put("pdf:PDFVersion", BlackboardAttribute.ATTRIBUTE_TYPE.TSK_VERSION) + .build(); + private static final String IMAGE_MIME_TYPE_PREFIX = "image/"; + + // documents where OCR is performed + private static final ImmutableSet OCR_DOCUMENTS = ImmutableSet.of( + "application/pdf", + "application/msword", + "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + "application/vnd.ms-powerpoint", + "application/vnd.openxmlformats-officedocument.presentationml.presentation", + "application/vnd.ms-excel", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" + ); /** * Options for this extractor @@ -206,8 +221,8 @@ public final class KeywordSearchIngestModule implements FileIngestModule { * for final statistics at the end of the job. * * @param ingestJobId id of ingest job - * @param fileId id of file - * @param status ingest status of the file + * @param fileId id of file + * @param status ingest status of the file */ private static void putIngestStatus(long ingestJobId, long fileId, IngestStatus status) { synchronized (ingestStatus) { @@ -350,12 +365,31 @@ public final class KeywordSearchIngestModule implements FileIngestModule { return ProcessResult.OK; } + // if ocr only is enabled and not an ocr file, return + Optional extractorOpt = getExtractor(abstractFile); + + String mimeType = fileTypeDetector.getMIMEType(abstractFile).trim().toLowerCase(); + + if (settings.isOCREnabled()) { + // if ocr only and the extractor is not present or will not perform ocr on this file, continue + if (settings.isOCROnly() && (!extractorOpt.isPresent() || !extractorOpt.get().willUseOCR())) { + return ProcessResult.OK; + } + + // if limited ocr is enabled, the extractor will use ocr, and + // the file would not be subject to limited ocr reading, continue + if (settings.isLimitedOCREnabled() && extractorOpt.isPresent() + && extractorOpt.get().willUseOCR() && !isLimitedOCRFile(abstractFile, mimeType)) { + return ProcessResult.OK; + } + } + if (KeywordSearchSettings.getSkipKnown() && abstractFile.getKnown().equals(FileKnown.KNOWN)) { //index meta-data only if (context.fileIngestIsCancelled()) { return ProcessResult.OK; } - indexer.indexFile(abstractFile, false); + indexer.indexFile(extractorOpt, abstractFile, mimeType, false); return ProcessResult.OK; } @@ -363,7 +397,7 @@ public final class KeywordSearchIngestModule implements FileIngestModule { if (context.fileIngestIsCancelled()) { return ProcessResult.OK; } - indexer.indexFile(abstractFile, true); + indexer.indexFile(extractorOpt, abstractFile, mimeType, true); // Start searching if it hasn't started already if (!startedSearching) { @@ -427,6 +461,29 @@ public final class KeywordSearchIngestModule implements FileIngestModule { initialized = false; } + /** + * Returns true if file should have OCR performed on it when limited OCR + * setting is specified. + * + * @param aFile The abstract file. + * @param mimeType The file mime type. + * + * @return True if file should have text extracted when limited OCR setting + * is on. + */ + private boolean isLimitedOCRFile(AbstractFile aFile, String mimeType) { + if (OCR_DOCUMENTS.contains(mimeType)) { + return true; + } + + if (mimeType.startsWith(IMAGE_MIME_TYPE_PREFIX)) { + return aFile.getSize() > LIMITED_OCR_SIZE_MIN + || aFile.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.DERIVED; + } + + return false; + } + /** * Posts inbox message with summary of text_ingested files */ @@ -489,6 +546,18 @@ public final class KeywordSearchIngestModule implements FileIngestModule { } } + private Optional getExtractor(AbstractFile abstractFile) { + ImageConfig imageConfig = new ImageConfig(); + imageConfig.setOCREnabled(settings.isOCREnabled()); + ProcessTerminator terminator = () -> context.fileIngestIsCancelled(); + Lookup extractionContext = Lookups.fixed(imageConfig, terminator); + try { + return Optional.ofNullable(TextExtractorFactory.getExtractor(abstractFile, extractionContext)); + } catch (TextExtractorFactory.NoTextExtractorFound ex) { + return Optional.empty(); + } + } + /** * File indexer, processes and indexes known/allocated files, * unknown/unallocated files and directories accordingly @@ -502,25 +571,26 @@ public final class KeywordSearchIngestModule implements FileIngestModule { * streaming) from the file Divide the file into chunks and index the * chunks * - * @param aFile file to extract strings from, divide into chunks and - * index - * @param extractedMetadata Map that will be populated with the file's metadata. + * @param extractorOptional The textExtractor to use with this file or + * empty. + * @param aFile file to extract strings from, divide into + * chunks and index + * @param extractedMetadata Map that will be populated with the file's + * metadata. * * @return true if the file was text_ingested, false otherwise * * @throws IngesterException exception thrown if indexing failed */ - private boolean extractTextAndIndex(AbstractFile aFile, Map extractedMetadata) throws IngesterException { - ImageConfig imageConfig = new ImageConfig(); - imageConfig.setOCREnabled(KeywordSearchSettings.getOcrOption()); - imageConfig.setLimitedOCREnabled(KeywordSearchSettings.getLimitedOcrOption()); - ProcessTerminator terminator = () -> context.fileIngestIsCancelled(); - Lookup extractionContext = Lookups.fixed(imageConfig, terminator); + private boolean extractTextAndIndex(Optional extractorOptional, AbstractFile aFile, + Map extractedMetadata) throws IngesterException { try { - TextExtractor extractor = TextExtractorFactory.getExtractor(aFile, extractionContext); + if (!extractorOptional.isPresent()) { + return false; + } + TextExtractor extractor = extractorOptional.get(); Reader fileText = extractor.getReader(); - Reader finalReader; try { Map metadata = extractor.getMetadata(); @@ -547,17 +617,17 @@ public final class KeywordSearchIngestModule implements FileIngestModule { } //divide into chunks and index return Ingester.getDefault().indexText(finalReader, aFile.getId(), aFile.getName(), aFile, context); - } catch (TextExtractorFactory.NoTextExtractorFound | TextExtractor.InitReaderException ex) { - //No text extractor found... run the default instead + } catch (TextExtractor.InitReaderException ex) { + // Text extractor could not be initialized. No text will be extracted. return false; } } - + private void createMetadataArtifact(AbstractFile aFile, Map metadata) { - + String moduleName = KeywordSearchIngestModule.class.getName(); - - Collection attributes = new ArrayList<>(); + + Collection attributes = new ArrayList<>(); Collection bbartifacts = new ArrayList<>(); for (Map.Entry entry : metadata.entrySet()) { if (METADATA_TYPES_MAP.containsKey(entry.getKey())) { @@ -573,32 +643,31 @@ public final class KeywordSearchIngestModule implements FileIngestModule { bbartifacts.add(bbart); } catch (TskCoreException ex) { // Log error and return to continue processing - logger.log(Level.WARNING, String.format("Error creating or adding metadata artifact for file %s.", aFile.getParentPath() + aFile.getName()), ex); //NON-NLS - return; + logger.log(Level.WARNING, String.format("Error creating or adding metadata artifact for file %s.", aFile.getParentPath() + aFile.getName()), ex); //NON-NLS + return; } if (!bbartifacts.isEmpty()) { - try{ + try { Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboard().postArtifacts(bbartifacts, moduleName); } catch (NoCurrentCaseException | Blackboard.BlackboardException ex) { // Log error and return to continue processing - logger.log(Level.WARNING, String.format("Unable to post blackboard artifacts for file $s.", aFile.getParentPath() + aFile.getName()) , ex); //NON-NLS + logger.log(Level.WARNING, String.format("Unable to post blackboard artifacts for file $s.", aFile.getParentPath() + aFile.getName()), ex); //NON-NLS return; } } } } - private BlackboardAttribute checkAttribute(String key, String value) { String moduleName = KeywordSearchIngestModule.class.getName(); - if (!value.isEmpty() && value.charAt(0) != ' ') { + if (!value.isEmpty() && value.charAt(0) != ' ') { if (METADATA_DATE_TYPES.contains(key)) { - SimpleDateFormat metadataDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", US); + SimpleDateFormat metadataDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", US); Long metadataDateTime = Long.valueOf(0); try { - String metadataDate = value.replaceAll("T"," ").replaceAll("Z", ""); + String metadataDate = value.replaceAll("T", " ").replaceAll("Z", ""); Date usedDate = metadataDateFormat.parse(metadataDate); - metadataDateTime = usedDate.getTime()/1000; + metadataDateTime = usedDate.getTime() / 1000; return new BlackboardAttribute(METADATA_TYPES_MAP.get(key), moduleName, metadataDateTime); } catch (ParseException ex) { // catching error and displaying date that could not be parsed then will continue on. @@ -609,12 +678,11 @@ public final class KeywordSearchIngestModule implements FileIngestModule { return new BlackboardAttribute(METADATA_TYPES_MAP.get(key), moduleName, value); } } - + return null; } - - + /** * Pretty print the text extractor metadata. * @@ -639,7 +707,7 @@ public final class KeywordSearchIngestModule implements FileIngestModule { * Extract strings using heuristics from the file and add to index. * * @param aFile file to extract strings from, divide into chunks and - * index + * index * * @return true if the file was text_ingested, false otherwise */ @@ -668,21 +736,24 @@ public final class KeywordSearchIngestModule implements FileIngestModule { /** * Adds the file to the index. Detects file type, calls extractors, etc. * - * @param aFile File to analyze + * @param extractor The textExtractor to use with this file or empty + * if no extractor found. + * @param aFile File to analyze. + * @param mimeType The file mime type. * @param indexContent False if only metadata should be text_ingested. - * True if content and metadata should be index. + * True if content and metadata should be index. */ - private void indexFile(AbstractFile aFile, boolean indexContent) { + private void indexFile(Optional extractor, AbstractFile aFile, String mimeType, boolean indexContent) { //logger.log(Level.INFO, "Processing AbstractFile: " + abstractFile.getName()); TskData.TSK_DB_FILES_TYPE_ENUM aType = aFile.getType(); /** * Extract unicode strings from unallocated and unused blocks and - * carved text files. The reason for performing string extraction - * on these is because they all may contain multiple encodings which - * can cause text to be missed by the more specialized text extractors - * used below. + * carved text files. The reason for performing string extraction on + * these is because they all may contain multiple encodings which + * can cause text to be missed by the more specialized text + * extractors used below. */ if ((aType.equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) || aType.equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS)) @@ -714,11 +785,10 @@ public final class KeywordSearchIngestModule implements FileIngestModule { if (context.fileIngestIsCancelled()) { return; } - String fileType = fileTypeDetector.getMIMEType(aFile); // we skip archive formats that are opened by the archive module. // @@@ We could have a check here to see if the archive module was enabled though... - if (ARCHIVE_MIME_TYPES.contains(fileType)) { + if (ARCHIVE_MIME_TYPES.contains(mimeType)) { try { if (context.fileIngestIsCancelled()) { return; @@ -741,11 +811,11 @@ public final class KeywordSearchIngestModule implements FileIngestModule { if (context.fileIngestIsCancelled()) { return; } - if (fileType.equals(MimeTypes.OCTET_STREAM)) { + if (MimeTypes.OCTET_STREAM.equals(mimeType)) { extractStringsAndIndex(aFile); return; } - if (!extractTextAndIndex(aFile, extractedMetadata)) { + if (!extractTextAndIndex(extractor, aFile, extractedMetadata)) { // Text extractor not found for file. Extract string only. putIngestStatus(jobId, aFile.getId(), IngestStatus.SKIPPED_ERROR_TEXTEXTRACT); } else { @@ -773,7 +843,7 @@ public final class KeywordSearchIngestModule implements FileIngestModule { if (wasTextAdded == false) { extractStringsAndIndex(aFile); } - + // Now that the indexing is complete, create the metadata artifact (if applicable). // It is unclear why calling this from extractTextAndIndex() generates // errors. @@ -783,8 +853,8 @@ public final class KeywordSearchIngestModule implements FileIngestModule { } /** - * Adds the text file to the index given an encoding. - * Returns true if indexing was successful and false otherwise. + * Adds the text file to the index given an encoding. Returns true if + * indexing was successful and false otherwise. * * @param aFile Text file to analyze */ diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchJobSettings.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchJobSettings.java index 8ad969863b..865024dae8 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchJobSettings.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchJobSettings.java @@ -26,19 +26,35 @@ import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; /** * Ingest job settings for the keywords search module. */ -final class KeywordSearchJobSettings implements IngestModuleIngestJobSettings { +public final class KeywordSearchJobSettings implements IngestModuleIngestJobSettings { private static final long serialVersionUID = 1L; + private HashSet namesOfEnabledKeywordLists; private HashSet namesOfDisabledKeywordLists; // Added in version 1.1 + /** + * These are nullable so that if no serialized setting, the setting can + * defer to legacy KeywordSearchSettings. + */ + private Boolean ocrEnabled; + private Boolean limitedOCREnabled; + + private boolean ocrOnly; + /** * Constructs ingest job settings for the keywords search module. * * @param namesOfEnabledKeywordLists A list of enabled keywords lists. */ KeywordSearchJobSettings(List namesOfEnabledKeywordLists) { - this(namesOfEnabledKeywordLists, new ArrayList()); + this.namesOfEnabledKeywordLists = new HashSet<>(namesOfEnabledKeywordLists); + this.namesOfDisabledKeywordLists = new HashSet<>(); + + // explicitly set to default value + this.ocrEnabled = null; + this.limitedOCREnabled = null; + this.ocrOnly = false; } /** @@ -46,14 +62,91 @@ final class KeywordSearchJobSettings implements IngestModuleIngestJobSettings { * * @param namesOfEnabledKeywordLists A list of enabled keywords lists. * @param namesOfDisabledKeywordLists A list of disabled keywords lists. + * @param ocrEnabled Whether or not OCR is enabled for + * keyword search. + * @param limitedOCREnabled If true, OCR is to be performed only + * on images larger than 100KB. + * @param ocrOnly True if keyword search ingest should + * be solely limited to OCR. */ - KeywordSearchJobSettings(List namesOfEnabledKeywordLists, List namesOfDisabledKeywordLists) { + KeywordSearchJobSettings(List namesOfEnabledKeywordLists, List namesOfDisabledKeywordLists, boolean ocrEnabled, boolean limitedOCREnabled, boolean ocrOnly) { this.namesOfEnabledKeywordLists = new HashSet<>(namesOfEnabledKeywordLists); this.namesOfDisabledKeywordLists = new HashSet<>(namesOfDisabledKeywordLists); + this.ocrEnabled = ocrEnabled; + this.limitedOCREnabled = limitedOCREnabled; + this.ocrOnly = ocrOnly; + } + + /** + * Whether or not OCR is enabled for keyword search. + * + * @return Whether or not OCR is enabled for keyword search. + */ + @SuppressWarnings("deprecation") + public boolean isOCREnabled() { + if (ocrEnabled == null) { + ocrEnabled = KeywordSearchSettings.getOcrOption(); + } + + return ocrEnabled; + } + + /** + * Sets whether or not OCR is enabled for keyword search. + * + * @param ocrEnabled Whether or not OCR is enabled for keyword search. + */ + public void setOCREnabled(boolean ocrEnabled) { + this.ocrEnabled = ocrEnabled; + } + + /** + * Returns true if OCR is to be performed only on images larger than 100KB. + * May defer to KeywordSearchSettings if no setting serialized. + * + * @return If true, OCR is to be performed only on images larger than 100KB. + */ + @SuppressWarnings("deprecation") + boolean isLimitedOCREnabled() { + if (limitedOCREnabled == null) { + limitedOCREnabled = KeywordSearchSettings.getLimitedOcrOption(); + } + + return limitedOCREnabled; + } + + /** + * Sets whether or not OCR should be performed only on images larger than + * 100KB. + * + * @param limitedOCREnabled Whether or not OCR should be performed only on + * images larger than 100KB. + */ + void setLimitedOCREnabled(boolean limitedOCREnabled) { + this.limitedOCREnabled = limitedOCREnabled; + } + + /** + * Returns true if keyword search ingest should be solely limited to OCR. + * + * @return True if keyword search ingest should be solely limited to OCR. + */ + boolean isOCROnly() { + return ocrOnly; + } + + /** + * Sets whether or not keyword search ingest should be solely limited to + * OCR. + * + * @param ocrOnly Whether or not keyword search ingest should be solely + * limited to OCR. + */ + void setOCROnly(boolean ocrOnly) { + this.ocrOnly = ocrOnly; } /** - * @inheritDoc */ @Override public long getVersionNumber() { diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchJobSettingsPanel.form b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchJobSettingsPanel.form index ac3cdd5782..0294690848 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchJobSettingsPanel.form +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchJobSettingsPanel.form @@ -20,30 +20,34 @@ - - + + - - - - - - - - - + + + + + + + + + + + + + - + @@ -54,18 +58,24 @@ + + - - - - + + - + - + + + + + + + @@ -96,8 +106,15 @@ - - + + + + + + + + + @@ -150,5 +167,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchJobSettingsPanel.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchJobSettingsPanel.java index a71485cbb1..6bf036000a 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchJobSettingsPanel.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchJobSettingsPanel.java @@ -18,19 +18,17 @@ */ package org.sleuthkit.autopsy.keywordsearch; -import java.awt.Component; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import javax.swing.JLabel; import javax.swing.JTable; import javax.swing.ListSelectionModel; import javax.swing.table.AbstractTableModel; -import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.TableColumn; +import org.sleuthkit.autopsy.coreutils.PlatformUtil; import org.sleuthkit.autopsy.coreutils.StringExtract.StringExtractUnicodeTable.SCRIPT; import org.sleuthkit.autopsy.guiutils.SimpleTableCellRenderer; import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; @@ -41,17 +39,17 @@ import org.sleuthkit.autopsy.keywordsearch.KeywordSearchIngestModule.StringsExtr * Ingest job settings panel for keyword search file ingest modules. */ @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives -public final class KeywordSearchJobSettingsPanel extends IngestModuleIngestJobSettingsPanel implements PropertyChangeListener { - +public final class KeywordSearchJobSettingsPanel extends IngestModuleIngestJobSettingsPanel implements PropertyChangeListener { private final KeywordListsTableModel tableModel = new KeywordListsTableModel(); private final List keywordListNames = new ArrayList<>(); private final Map keywordListStates = new HashMap<>(); private final XmlKeywordSearchList keywordListsManager = XmlKeywordSearchList.getCurrent(); + KeywordSearchJobSettingsPanel(KeywordSearchJobSettings initialSettings) { - initializeKeywordListSettings(initialSettings); initComponents(); customizeComponents(); + initializeKeywordListSettings(initialSettings); } private void initializeKeywordListSettings(KeywordSearchJobSettings settings) { @@ -63,6 +61,23 @@ public final class KeywordSearchJobSettingsPanel extends IngestModuleIngestJobSe keywordListNames.add(listName); keywordListStates.put(listName, settings.keywordListIsEnabled(listName)); } + + ocrCheckBox.setSelected(settings.isOCREnabled()); + limitedOcrCheckbox.setSelected(settings.isLimitedOCREnabled()); + ocrOnlyCheckbox.setSelected(settings.isOCROnly()); + + handleOcrEnabled(settings.isOCREnabled()); + } + + /** + * Handles setting enabled state of checkbox. + * @param ocrEnabled Whether or not the ocr setting is enabled. + */ + private void handleOcrEnabled(boolean ocrEnabled) { + boolean platformSupported = PlatformUtil.isWindowsOS() && PlatformUtil.is64BitOS(); + ocrCheckBox.setEnabled(platformSupported); + limitedOcrCheckbox.setEnabled(platformSupported && ocrEnabled); + ocrOnlyCheckbox.setEnabled(platformSupported && ocrEnabled); } private void customizeComponents() { @@ -71,6 +86,10 @@ public final class KeywordSearchJobSettingsPanel extends IngestModuleIngestJobSe displayEncodings(); keywordListsManager.addPropertyChangeListener(this); languagesLabel.setText("" + org.openide.util.NbBundle.getMessage(KeywordSearchJobSettingsPanel.class, "KeywordSearchJobSettingsPanel.languagesLabel.text") + ""); // NOI18N NON-NLS + + // the gui builder does not explicitly set these to false. + listsTable.setShowHorizontalLines(false); + listsTable.setShowVerticalLines(false); } private void customizeKeywordListsTable() { @@ -174,7 +193,8 @@ public final class KeywordSearchJobSettingsPanel extends IngestModuleIngestJobSe disabledListNames.add(listName); } } - return new KeywordSearchJobSettings(enabledListNames, disabledListNames); + return new KeywordSearchJobSettings(enabledListNames, disabledListNames, + this.ocrCheckBox.isSelected(), this.limitedOcrCheckbox.isSelected(), this.ocrOnlyCheckbox.isSelected()); } void reset(KeywordSearchJobSettings newSettings) { @@ -241,6 +261,9 @@ public final class KeywordSearchJobSettingsPanel extends IngestModuleIngestJobSe languagesValLabel = new javax.swing.JLabel(); encodingsLabel = new javax.swing.JLabel(); keywordSearchEncodings = new javax.swing.JLabel(); + ocrCheckBox = new javax.swing.JCheckBox(); + limitedOcrCheckbox = new javax.swing.JCheckBox(); + ocrOnlyCheckbox = new javax.swing.JCheckBox(); setPreferredSize(new java.awt.Dimension(300, 170)); @@ -256,8 +279,9 @@ public final class KeywordSearchJobSettingsPanel extends IngestModuleIngestJobSe } )); - listsTable.setShowHorizontalLines(false); - listsTable.setShowVerticalLines(false); + listsTable.setMaximumSize(new java.awt.Dimension(32767, 32767)); + listsTable.setMinimumSize(new java.awt.Dimension(20, 200)); + listsTable.setPreferredSize(null); listsScrollPane.setViewportView(listsTable); listsTable.setDefaultRenderer(String.class, new SimpleTableCellRenderer()); @@ -275,29 +299,54 @@ public final class KeywordSearchJobSettingsPanel extends IngestModuleIngestJobSe keywordSearchEncodings.setText(org.openide.util.NbBundle.getMessage(KeywordSearchJobSettingsPanel.class, "KeywordSearchJobSettingsPanel.keywordSearchEncodings.text")); // NOI18N + ocrCheckBox.setText(org.openide.util.NbBundle.getMessage(KeywordSearchJobSettingsPanel.class, "KeywordSearchJobSettingsPanel.ocrCheckBox.text")); // NOI18N + ocrCheckBox.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + ocrCheckBoxActionPerformed(evt); + } + }); + + limitedOcrCheckbox.setText(org.openide.util.NbBundle.getMessage(KeywordSearchJobSettingsPanel.class, "KeywordSearchJobSettingsPanel.limitedOcrCheckbox.text")); // NOI18N + limitedOcrCheckbox.setVerticalTextPosition(javax.swing.SwingConstants.TOP); + limitedOcrCheckbox.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + limitedOcrCheckboxActionPerformed(evt); + } + }); + + ocrOnlyCheckbox.setText(org.openide.util.NbBundle.getMessage(KeywordSearchJobSettingsPanel.class, "KeywordSearchJobSettingsPanel.ocrOnlyCheckbox.text")); // NOI18N + ocrOnlyCheckbox.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + ocrOnlyCheckboxActionPerformed(evt); + } + }); + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addComponent(listsScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) - .addContainerGap()) - .addGroup(layout.createSequentialGroup() - .addGap(10, 10, 10) - .addComponent(languagesValLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 274, javax.swing.GroupLayout.PREFERRED_SIZE) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addComponent(languagesLabel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(layout.createSequentialGroup() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(listsScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 316, Short.MAX_VALUE) .addComponent(titleLabel) .addGroup(layout.createSequentialGroup() .addComponent(encodingsLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(keywordSearchEncodings))) - .addGap(0, 0, Short.MAX_VALUE)))) + .addComponent(keywordSearchEncodings)) + .addGroup(layout.createSequentialGroup() + .addGap(10, 10, 10) + .addComponent(languagesValLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 274, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(ocrCheckBox) + .addGroup(layout.createSequentialGroup() + .addGap(21, 21, 21) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(ocrOnlyCheckbox) + .addComponent(limitedOcrCheckbox, javax.swing.GroupLayout.PREFERRED_SIZE, 288, javax.swing.GroupLayout.PREFERRED_SIZE)))) + .addContainerGap()))) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -305,25 +354,48 @@ public final class KeywordSearchJobSettingsPanel extends IngestModuleIngestJobSe .addGap(7, 7, 7) .addComponent(titleLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(listsScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 41, Short.MAX_VALUE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(languagesLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(listsScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(languagesLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 13, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(languagesValLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(encodingsLabel) .addComponent(keywordSearchEncodings)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(ocrCheckBox) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(ocrOnlyCheckbox) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(limitedOcrCheckbox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addContainerGap()) ); }// //GEN-END:initComponents + + private void ocrCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_ocrCheckBoxActionPerformed + handleOcrEnabled(ocrCheckBox.isSelected()); + firePropertyChange(KeywordSearchOptionsPanelController.PROP_CHANGED, null, null); + }//GEN-LAST:event_ocrCheckBoxActionPerformed + + private void limitedOcrCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_limitedOcrCheckboxActionPerformed + firePropertyChange(KeywordSearchOptionsPanelController.PROP_CHANGED, null, null); + }//GEN-LAST:event_limitedOcrCheckboxActionPerformed + + private void ocrOnlyCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_ocrOnlyCheckboxActionPerformed + // TODO add your handling code here: + }//GEN-LAST:event_ocrOnlyCheckboxActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JLabel encodingsLabel; private javax.swing.JLabel keywordSearchEncodings; private javax.swing.JLabel languagesLabel; private javax.swing.JLabel languagesValLabel; + private javax.swing.JCheckBox limitedOcrCheckbox; private javax.swing.JScrollPane listsScrollPane; private javax.swing.JTable listsTable; + private javax.swing.JCheckBox ocrCheckBox; + private javax.swing.JCheckBox ocrOnlyCheckbox; private javax.swing.JLabel titleLabel; // End of variables declaration//GEN-END:variables } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchSettings.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchSettings.java index 0db0b30684..b7057a2c89 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchSettings.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchSettings.java @@ -133,20 +133,14 @@ class KeywordSearchSettings { ModuleSettings.setConfigSetting(PROPERTIES_OPTIONS, key, val); } - /** - * Save OCR setting to permanent storage - * - * @param enabled Is OCR enabled? - */ - static void setOcrOption(boolean enabled) { - ModuleSettings.setConfigSetting(PROPERTIES_OPTIONS, OCR_ENABLED, (enabled ? "true" : "false")); //NON-NLS - } - /** * Get OCR setting from permanent storage * * @return Is OCR enabled? + * + * @deprecated Please use KeywordSearchJobSettings instead. */ + @Deprecated static boolean getOcrOption() { if (ModuleSettings.settingExists(PROPERTIES_OPTIONS, OCR_ENABLED)) { return ModuleSettings.getConfigSetting(PROPERTIES_OPTIONS, OCR_ENABLED).equals("true"); //NON-NLS @@ -155,6 +149,24 @@ class KeywordSearchSettings { } } + /** + * Gets the limited OCR flag to indicate if OCR should be limited to larger + * images and images which were extracted from documents. + * + * @return Flag indicating if limited OCR is enabled. True if OCR should be + * limited, false otherwise. + * + * @deprecated Please use KeywordSearchJobSettings instead. + */ + @Deprecated + static boolean getLimitedOcrOption() { + if (ModuleSettings.settingExists(PROPERTIES_OPTIONS, LIMITED_OCR_ENABLED)) { + return ModuleSettings.getConfigSetting(PROPERTIES_OPTIONS, LIMITED_OCR_ENABLED).equals("true"); //NON-NLS + } else { + return LIMITED_OCR_ENABLED_DEFAULT; + } + } + static void setShowSnippets(boolean showSnippets) { ModuleSettings.setConfigSetting(PROPERTIES_OPTIONS, SHOW_SNIPPETS, (showSnippets ? "true" : "false")); //NON-NLS } @@ -246,45 +258,10 @@ class KeywordSearchSettings { logger.log(Level.INFO, "No configuration for UTF16 found, generating defaults..."); //NON-NLS KeywordSearchSettings.setStringExtractOption(StringsExtractOptions.EXTRACT_UTF16.toString(), Boolean.TRUE.toString()); } - //setting OCR default (disabled by default) - if (!ModuleSettings.settingExists(KeywordSearchSettings.PROPERTIES_OPTIONS, OCR_ENABLED)) { - logger.log(Level.INFO, "No configuration for OCR found, generating defaults..."); //NON-NLS - KeywordSearchSettings.setOcrOption(OCR_ENABLED_DEFAULT); - } - //setting OCR default (disabled by default) - if (!ModuleSettings.settingExists(KeywordSearchSettings.PROPERTIES_OPTIONS, LIMITED_OCR_ENABLED)) { - logger.log(Level.INFO, "No configuration for OCR found, generating defaults..."); //NON-NLS - KeywordSearchSettings.setLimitedOcrOption(LIMITED_OCR_ENABLED_DEFAULT); - } //setting default Latin-1 Script if (!ModuleSettings.settingExists(KeywordSearchSettings.PROPERTIES_SCRIPTS, SCRIPT.LATIN_1.name())) { logger.log(Level.INFO, "No configuration for Scripts found, generating defaults..."); //NON-NLS ModuleSettings.setConfigSetting(KeywordSearchSettings.PROPERTIES_SCRIPTS, SCRIPT.LATIN_1.name(), Boolean.toString(true)); } } - - /** - * Enables the limiting OCR to be run on larger images and images which were - * extracted from documents. - * - * @param enabled Flag indicating if OCR is enabled. - */ - static void setLimitedOcrOption(boolean enabled) { - ModuleSettings.setConfigSetting(PROPERTIES_OPTIONS, LIMITED_OCR_ENABLED, (enabled ? "true" : "false")); //NON-NLS - } - - /** - * Gets the limited OCR flag to indicate if OCR should be limited to larger - * images and images which were extracted from documents. - * - * @return Flag indicating if limited OCR is enabled. True if OCR should be - * limited, false otherwise.. - */ - static boolean getLimitedOcrOption() { - if (ModuleSettings.settingExists(PROPERTIES_OPTIONS, LIMITED_OCR_ENABLED)) { - return ModuleSettings.getConfigSetting(PROPERTIES_OPTIONS, LIMITED_OCR_ENABLED).equals("true"); //NON-NLS - } else { - return LIMITED_OCR_ENABLED_DEFAULT; - } - } } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/LanguageSpecificContentIndexingHelper.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/LanguageSpecificContentIndexingHelper.java index 387399d7ae..345126b62c 100755 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/LanguageSpecificContentIndexingHelper.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/LanguageSpecificContentIndexingHelper.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2019 Basis Technology Corp. + * Copyright 2011-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -35,15 +35,15 @@ import java.util.Optional; class LanguageSpecificContentIndexingHelper { private final LanguageDetector languageDetector = new LanguageDetector(); - - Optional detectLanguageIfNeeded(Chunker.Chunk chunk) throws NoOpenCoreException { + + Optional detectLanguageIfNeeded(String text) throws NoOpenCoreException { double indexSchemaVersion = NumberUtils.toDouble(KeywordSearch.getServer().getIndexInfo().getSchemaVersion()); if (2.2 <= indexSchemaVersion) { - return languageDetector.detect(chunk.toString()); + return languageDetector.detect(text); } else { return Optional.empty(); } - } + } void updateLanguageSpecificFields(Map fields, Chunker.Chunk chunk, Language language) { List values = new ArrayList<>(); diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/LuceneQuery.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/LuceneQuery.java index 2d10d5cbbc..43da17fa0b 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/LuceneQuery.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/LuceneQuery.java @@ -263,7 +263,10 @@ class LuceneQuery implements KeywordSearchQuery { ); try { - return content.newAnalysisResult(new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_KEYWORD_HIT), Score.SCORE_UNKNOWN, null, null, null, attributes) + return content.newAnalysisResult( + BlackboardArtifact.Type.TSK_KEYWORD_HIT, Score.SCORE_LIKELY_NOTABLE, + null, listName, null, + attributes) .getAnalysisResult(); } catch (TskCoreException e) { logger.log(Level.WARNING, "Error adding bb artifact for keyword hit", e); //NON-NLS diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/RegexQuery.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/RegexQuery.java index ebaf078585..39ea7a0e9b 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/RegexQuery.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/RegexQuery.java @@ -48,7 +48,6 @@ import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Account; import org.sleuthkit.datamodel.AccountFileInstance; import org.sleuthkit.datamodel.BlackboardArtifact; -import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE; import org.sleuthkit.datamodel.Content; @@ -73,7 +72,7 @@ import org.sleuthkit.datamodel.TskData; final class RegexQuery implements KeywordSearchQuery { public static final Logger LOGGER = Logger.getLogger(RegexQuery.class.getName()); - + /** * Lucene regular expressions do not support the following Java predefined * and POSIX character classes. There are other valid Java character classes @@ -614,7 +613,9 @@ final class RegexQuery implements KeywordSearchQuery { } try { - return content.newAnalysisResult(new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_KEYWORD_HIT), Score.SCORE_UNKNOWN, null, null, null, attributes) + return content.newAnalysisResult( + BlackboardArtifact.Type.TSK_KEYWORD_HIT, Score.SCORE_LIKELY_NOTABLE, + null, listName, null, attributes) .getAnalysisResult(); } catch (TskCoreException e) { LOGGER.log(Level.SEVERE, "Error adding bb attributes for terms search artifact", e); //NON-NLS diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java index 218be24de8..e5c3f8ae03 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java @@ -37,6 +37,7 @@ import org.sleuthkit.autopsy.casemodule.CaseMetadata; import org.sleuthkit.autopsy.coreutils.FileUtil; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; +import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService; import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchServiceException; import org.sleuthkit.autopsy.progress.ProgressIndicator; @@ -130,7 +131,11 @@ public class SolrSearchService implements KeywordSearchService, AutopsyService { throw new TskCoreException("Error indexing content", ex1); } } - ingester.commit(); + // only do a Solr commit if ingest is not running. If ingest is running, the changes will + // be committed via a periodic commit or via final commit after the ingest job has finished. + if (!IngestManager.getInstance().isIngestRunning()) { + ingester.commit(); + } } } @@ -461,5 +466,4 @@ public class SolrSearchService implements KeywordSearchService, AutopsyService { throw new TskCoreException(ex.getCause().getMessage(), ex); } } - } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/infastructure/Bundle.properties b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/infastructure/Bundle.properties new file mode 100644 index 0000000000..3b2f584c8f --- /dev/null +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/infastructure/Bundle.properties @@ -0,0 +1 @@ +NoReportConfigurationPanel.infoLabel.text=This report does not require configuration. diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/infastructure/Bundle.properties-MERGED b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/infastructure/Bundle.properties-MERGED new file mode 100644 index 0000000000..3b2f584c8f --- /dev/null +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/infastructure/Bundle.properties-MERGED @@ -0,0 +1 @@ +NoReportConfigurationPanel.infoLabel.text=This report does not require configuration. diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/infastructure/Bundle_ja.properties b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/infastructure/Bundle_ja.properties new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/infastructure/Bundle_ja.properties @@ -0,0 +1 @@ + diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/infastructure/NoReportConfigurationPanel.form b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/infastructure/NoReportConfigurationPanel.form new file mode 100644 index 0000000000..67cb16b749 --- /dev/null +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/infastructure/NoReportConfigurationPanel.form @@ -0,0 +1,50 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/infastructure/NoReportConfigurationPanel.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/infastructure/NoReportConfigurationPanel.java new file mode 100644 index 0000000000..077386ea0c --- /dev/null +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/infastructure/NoReportConfigurationPanel.java @@ -0,0 +1,68 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2021 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may 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.keywordsearch.infastructure; + +/** + * The panel shown for report modules with no configuration settings. + */ +@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives +public class NoReportConfigurationPanel extends javax.swing.JPanel { + + /** + * Creates new form NoReportConfigurationPanel + */ + public NoReportConfigurationPanel() { + initComponents(); + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + infoLabel = new javax.swing.JLabel(); + + infoLabel.setFont(infoLabel.getFont().deriveFont((infoLabel.getFont().getStyle() | java.awt.Font.ITALIC))); + org.openide.awt.Mnemonics.setLocalizedText(infoLabel, org.openide.util.NbBundle.getMessage(NoReportConfigurationPanel.class, "NoReportConfigurationPanel.infoLabel.text")); // NOI18N + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(infoLabel) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(infoLabel) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + }// //GEN-END:initComponents + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel infoLabel; + // End of variables declaration//GEN-END:variables +} diff --git a/NEWS.txt b/NEWS.txt index d9e2f99b90..3ab13cfab3 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -5,12 +5,18 @@ Data Source Management: - The main tree viewer can be configured to group by person and host. OS Accounts: -- Operating System (OS) accounts and realms are their own data types and not generic artifacts. +- Operating System (OS) accounts and realms are their own data types and no longer generic artifacts. - OS Accounts are created for Windows accounts found in the registry. Domain-scoped realms are not fully detected yet. - NTFS files are associated with OS Accounts by SID. - The Recent Activity module associates artifacts with OS Accounts based on SID or path of database. Other modules still need to be updated. - OS accounts appear in a dedicated sub-tree of the main tree view and their properties can be viewed in the results view. -- A new content viewer in the lower right area of the main window was built to display OS account data for the item selected in the result view. +- A new content viewer in the lower right area of the main window was built to display OS account data for the item selected in the results view. + +Analysis Result and Data Artifacts +- All modules make either Analysis Results or Data Artifacts instead of “Blackboard Artifacts.” +- New “Analysis Result” content viewer shows the results for a given file and its score. +- The tabular results viewer shows an icon for the aggregate score of a file. +- The tree organizes results into "Analysis Results" and "Data Artifacts" instead of simply “Results.” Discovery UI: - Domain categorization and account types are displayed in Domain Discovery results. @@ -22,17 +28,40 @@ Ingest Modules: - Parsing of iLEAPP and aLEAPP output was expanded to create communication relationships which can be displayed in the Communications UI. - EML email parsing handles EML messages that are attachments (and have their own attachments). - Domain categorization within Recent Activity can be customized by user-defined rules that can be imported and exported. +- Account IDs and Installed Applications are added to the Central Repository. +- Keyword search can be configured to only do OCR and skip non-OCR files. Miscellaneous: - A “Reset Windows” feature was created to help redock windows. - A case-insensitive wordlist of all words in the keyword search index can be exported as a text document. - Information from the Data Source Summary panels can be exported as an Excel spreadsheet. - More artifacts are added to the timeline and artifacts with multiple time-based attributes are mapped to multiple timeline events. -- The Auto Ingest Dashboard is resizable. - Added option to only perform optical character recognition on certain file types. - Heap dumps can be saved to a custom location. +- More detailed error messages about encrypted disks when they are added. +- Added file size filter to Ingest Filters. + +Performance: +- Keyword search does not make an explicit commit for each report if ingest is running. +- Language ID is performed on a small subset of a file instead of the entire file. +- Recent Activity is more efficient because of TSK changes to file searching (using extension). +- Embedded file extractor module has been made faster by doing file typing in memory and adding extracted files in batches. +- Moved Content Viewers setNode() and isSupported()/isPreferred() code to background threads. +- Moved Data Source Summary Panel population code to background threads. +- Moved Node/Tree queries to background threads. + +Bug Fixes: +- Fixed embedded file extractor file name escaping bug. +- Detect VHD files by signature and not extension. +- Fixed iLEAPP path error. +- Content viewers UIs are more consistent. - Assorted bug fixes are included. +Auto Ingest: +- The Auto Ingest Dashboard is resizable. +- Get thread dumps from AID +- Added beta pause feature that pauses auto ingest for a set amount of time at a scheduled date and time. + ---------------- VERSION 4.18.0 -------------- Keyword Search: - A major upgrade from Solr 4 to Solr 8.6.3. Single user cases continue to use the embedded server. diff --git a/RecentActivity/manifest.mf b/RecentActivity/manifest.mf index 76b6b1ce6f..03c6ce986b 100644 --- a/RecentActivity/manifest.mf +++ b/RecentActivity/manifest.mf @@ -1,6 +1,6 @@ Manifest-Version: 1.0 OpenIDE-Module: org.sleuthkit.autopsy.recentactivity/6 -OpenIDE-Module-Implementation-Version: 18 +OpenIDE-Module-Implementation-Version: 19 OpenIDE-Module-Layer: org/sleuthkit/autopsy/recentactivity/layer.xml OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/recentactivity/Bundle.properties OpenIDE-Module-Requires: diff --git a/RecentActivity/nbproject/project.xml b/RecentActivity/nbproject/project.xml index 8fc5e13b53..11dc55cab6 100644 --- a/RecentActivity/nbproject/project.xml +++ b/RecentActivity/nbproject/project.xml @@ -60,7 +60,7 @@ 10 - 10.23 + 10.24 diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle_ja.properties b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle_ja.properties index e1ea4fb368..c4405a64d4 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle_ja.properties +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle_ja.properties @@ -1,4 +1,6 @@ -#Fri Feb 12 16:56:29 UTC 2021 +#Mon Jul 12 13:22:00 UTC 2021 +Chrome.getAutofill.errMsg.errAnalyzingFiles={0}\uff1a\u30d5\u30a1\u30a4\u30eb\u306e\u5206\u6790\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\uff1a{1} +Chrome.getAutofill.errMsg.errGettingFiles=Chrome\u30a6\u30a7\u30d6\u30c7\u30fc\u30bf\u30d5\u30a1\u30a4\u30eb\u3092\u53d6\u5f97\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 Chrome.getBookmark.errMsg.errAnalyzeFile={0}\:\u30d5\u30a1\u30a4\u30eb\:{1}\u3092\u89e3\u6790\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f Chrome.getBookmark.errMsg.errAnalyzingFile={0}\:\u30d5\u30a1\u30a4\u30eb\:{1}\u3092\u89e3\u6790\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f Chrome.getBookmark.errMsg.errAnalyzingFile3={0}\:\u30d5\u30a1\u30a4\u30eb\:{1}\u3092\u89e3\u6790\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f @@ -18,11 +20,26 @@ Chrome.parentModuleName=\u6700\u8fd1\u306e\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u ChromeCacheExtract_adding_artifacts_msg=Chrome\u30ad\u30e3\u30c3\u30b7\u30e5\uff1a\u5206\u6790\u306e\u305f\u3081\u306b%d\u500b\u306e\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u3092\u8ffd\u52a0\u3057\u3066\u3044\u307e\u3059\u3002 ChromeCacheExtract_adding_extracted_files_msg=Chrome\u30ad\u30e3\u30c3\u30b7\u30e5\uff1a\u5206\u6790\u306e\u305f\u3081\u306b%d\u500b\u306e\u62bd\u51fa\u30d5\u30a1\u30a4\u30eb\u3092\u8ffd\u52a0\u3057\u3066\u3044\u307e\u3059\u3002 ChromeCacheExtract_loading_files_msg=Chrome\u30ad\u30e3\u30c3\u30b7\u30e5\uff1a %s\u304b\u3089\u30d5\u30a1\u30a4\u30eb\u3092\u8aad\u307f\u8fbc\u3093\u3067\u3044\u307e\u3059\u3002 +ChromeCacheExtractor.moduleName=ChromeCacheExtractor +ChromeCacheExtractor.progressMsg={0}\uff1a{3}\u304b\u3089{2}\u30a8\u30f3\u30c8\u30ea\u306e\u30ad\u30e3\u30c3\u30b7\u30e5\u30a8\u30f3\u30c8\u30ea{1}\u3092\u62bd\u51fa\u3057\u3066\u3044\u307e\u3059 +DataSourceUsageAnalyzer.customVolume.label=OS\u30c9\u30e9\u30a4\u30d6\uff08{0}\uff09 +DataSourceUsageAnalyzer.parentModuleName=\u6700\u8fd1\u306e\u6d3b\u52d5 +DataSourceUsage_AndroidMedia=Android\u30e1\u30c7\u30a3\u30a2\u30ab\u30fc\u30c9 DataSourceUsage_DJU_Drone_DAT=DJI\u5185\u8535SD\u30ab\u30fc\u30c9 +DataSourceUsage_FlashDrive=\u30d5\u30e9\u30c3\u30b7\u30e5\u30c9\u30e9\u30a4\u30d6 +DefaultPriorityDomainCategorizer_searchEngineCategory=\u691c\u7d22\u30a8\u30f3\u30b8\u30f3 DomainCategoryRunner_Progress_Message_Domain_Types=\u30c9\u30e1\u30a4\u30f3\u30bf\u30a4\u30d7\u306e\u691c\u7d22 DomainCategoryRunner_moduleName_text=DomainCategoryRunner DomainCategoryRunner_parentModuleName=\u6700\u8fd1\u306e\u6d3b\u52d5 Extract.dbConn.errMsg.failedToQueryDb={0}\:\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30af\u30a8\u30ea\u5b9f\u884c\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 +Extract.indexError.message=\u30ad\u30fc\u30ef\u30fc\u30c9\u691c\u7d22\u306e\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u306e\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u4f5c\u6210\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 +Extract.noOpenCase.errMsg=\u30aa\u30fc\u30d7\u30f3\u30b1\u30fc\u30b9\u306f\u3042\u308a\u307e\u305b\u3093\u3002 +ExtractEdge_Module_Name=\u30de\u30a4\u30af\u30ed\u30bd\u30d5\u30c8\u30fb\u30a8\u30c3\u30b8 +ExtractEdge_getHistory_containerFileNotFound=\u30a8\u30c3\u30b8\u5c65\u6b74\u306e\u5206\u6790\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +ExtractEdge_process_errMsg_errGettingWebCacheFiles=EdgeWebCacheV01\u30d5\u30a1\u30a4\u30eb\u3092\u53d6\u5f97\u3057\u3088\u3046\u3068\u3057\u3066\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +ExtractEdge_process_errMsg_spartanFail=\u30de\u30a4\u30af\u30ed\u30bd\u30d5\u30c8\u30fb\u30a8\u30c3\u30b8spartan.edb\u30d5\u30a1\u30a4\u30eb\u306e\u51e6\u7406\u306b\u5931\u6557\u3057\u307e\u3057\u305f +ExtractEdge_process_errMsg_unableFindESEViewer=ESEDatabaseViewer\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093 +ExtractEdge_process_errMsg_webcacheFail=\u30de\u30a4\u30af\u30ed\u30bd\u30d5\u30c8\u30fb\u30a8\u30c3\u30b8WebCacheV01.dat\u30d5\u30a1\u30a4\u30eb\u306e\u51e6\u7406\u306b\u5931\u6557\u3057\u307e\u3057\u305f ExtractIE.getBookmark.errMsg.errGettingBookmarks={0}\: Internet Explorer\u30d6\u30c3\u30af\u30de\u30fc\u30af\u3092\u53d6\u5f97\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 ExtractIE.getCookie.errMsg.errGettingFile={0}\:Internet Explorer\u306ecookie\u30d5\u30a1\u30a4\u30eb\u3092\u53d6\u5f97\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 ExtractIE.getCookie.errMsg.errReadingIECookie={0}\:Internet Explorer\u306ecookie{1}\u3092\u8aad\u307f\u53d6\u308a\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 @@ -40,9 +57,41 @@ ExtractIE.parsePascoOutput.errMsg.errParsing={0}\:Internet Explorer\u5c65\u6b74\ ExtractIE.parsePascoOutput.errMsg.errParsingEntry={0}\: Internet Explorer\u5c65\u6b74\u30a8\u30f3\u30c8\u30ea\u3092\u30d1\u30fc\u30b9\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 ExtractIE.parsePascoOutput.errMsg.notFound={0}\:Pasco\u30a2\u30a6\u30c8\u30d7\u30c3\u30c8\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f\uff1a{1} ExtractIE_executePasco_errMsg_errorRunningPasco={0}\uff1aInternet Explorer\u306eWeb\u5c65\u6b74\u306e\u5206\u6790\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +ExtractOS_progressMessage=OS\u306e\u78ba\u8a8d +ExtractOs.androidOs.label=\u30a2\u30f3\u30c9\u30ed\u30a4\u30c9 +ExtractOs.androidVolume.label=OS\u30c9\u30e9\u30a4\u30d6\uff08\u30a2\u30f3\u30c9\u30ed\u30a4\u30c9\uff09 +ExtractOs.debianLinuxOs.label=Linux\uff08Debian\uff09 +ExtractOs.debianLinuxVolume.label=OS\u30c9\u30e9\u30a4\u30d6\uff08Linux Debian\uff09 +ExtractOs.fedoraLinuxOs.label=Linux (Fedora) +ExtractOs.fedoraLinuxVolume.label=OS\u30c9\u30e9\u30a4\u30d6\uff08Linux Fedora\uff09 +ExtractOs.gentooLinuxOs.label=Linux (Gentoo) +ExtractOs.gentooLinuxVolume.label=OS\u30c9\u30e9\u30a4\u30d6\uff08Linux Gentoo\uff09 +ExtractOs.mandrakeLinuxOs.label=Linux (Mandrake) +ExtractOs.mandrakeLinuxVolume.label=OS\u30c9\u30e9\u30a4\u30d6\uff08Linux Mandrake\uff09 +ExtractOs.novellSUSEOs.label=Linux (Novell SUSE) +ExtractOs.novellSUSEVolume.label=OS\u30c9\u30e9\u30a4\u30d6\uff08Linux Novell SUSE\uff09 +ExtractOs.osx.label=Mac OS X +ExtractOs.osxVolume.label=OS\u30c9\u30e9\u30a4\u30d6\uff08OS X\uff09 +ExtractOs.parentModuleName=\u6700\u8fd1\u306e\u6d3b\u52d5 +ExtractOs.redhatLinuxOs.label=Linux (Redhat) +ExtractOs.redhatLinuxVolume.label=OS\u30c9\u30e9\u30a4\u30d6\uff08Linux Redhat\uff09 +ExtractOs.slackwareLinuxOs.label=Linux (Slackware) +ExtractOs.slackwareLinuxVolume.label=OS\u30c9\u30e9\u30a4\u30d6\uff08Linux Slackware\uff09 +ExtractOs.solarisSparcOs.label=Linux (Solaris/Sparc) +ExtractOs.solarisSparcVolume.label=OS\u30c9\u30e9\u30a4\u30d6\uff08Linux Solaris/Sparc\uff09 +ExtractOs.sunJDSLinuxOs.label=Linux (Sun JDS) +ExtractOs.sunJDSLinuxVolume.label=OS\u30c9\u30e9\u30a4\u30d6\uff08Linux Sun JDS\uff09 +ExtractOs.ubuntuLinuxOs.label=Linux (Ubuntu) +ExtractOs.ubuntuLinuxVolume.label=OS\u30c9\u30e9\u30a4\u30d6\uff08Linux Ubuntu\uff09 +ExtractOs.unitedLinuxOs.label=Linux (United Linux) +ExtractOs.unitedLinuxVolume.label=OS\u30c9\u30e9\u30a4\u30d6\uff08Linux United Linux\uff09 +ExtractOs.windowsVolume.label=OS\u30c9\u30e9\u30a4\u30d6\uff08Windows\uff09 +ExtractOs.yellowDogLinuxOs.label=Linux (Yellow Dog) +ExtractOs.yellowDogLinuxVolume.label=OS\u30c9\u30e9\u30a4\u30d6\uff08Linux Yellow Dog\uff09 ExtractPrefetch_errMsg_prefetchParsingFailed={0}\uff1a\u30d7\u30ea\u30d5\u30a7\u30c3\u30c1\u30fb\u30d5\u30a1\u30a4\u30eb\u306e\u5206\u6790\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f ExtractPrefetch_module_name=Windows Prefetch Extractor ExtractRecycleBin_Recyle_Bin_Display_Name=\u3054\u307f\u7bb1 +ExtractRecycleBin_module_name=\u3054\u307f\u7bb1 ExtractRegistry.analyzeRegFiles.errMsg.errReadingRegFile={0}\:\u30ec\u30b8\u30b9\u30c8\u30ea\u30d5\u30a1\u30a4\u30eb - {1}\u3092\u8aad\u307f\u53d6\u308a\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f ExtractRegistry.analyzeRegFiles.errMsg.errWritingTemp={0}\:\u30ec\u30b8\u30b9\u30c8\u30ea\u30d5\u30a1\u30a4\u30eb{1}\u3092\u89e3\u6790\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f ExtractRegistry.analyzeRegFiles.failedParsingResults={0}\:\u30ec\u30b8\u30b9\u30c8\u30ea\u30d5\u30a1\u30a4\u30eb\u7d50\u679c\u306e\u30d1\u30fc\u30b9\u306b\u5931\u6557\u3057\u307e\u3057\u305f{1} @@ -51,6 +100,10 @@ ExtractRegistry.findRegFiles.errMsg.errReadingFile=\u30ec\u30b8\u30b9\u30c8\u30e ExtractRegistry.moduleName.text=\u30ec\u30b8\u30b9\u30c8\u30ea ExtractRegistry.parentModuleName.noSpace=\u6700\u8fd1\u306e\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3 ExtractRegistry.programName=\u30ec\u30b8\u30b9\u30c8\u30ea\u30ea\u30c3\u30d1\u30fc +ExtractSafari_Error_Getting_History=Safari\u5c65\u6b74\u30d5\u30a1\u30a4\u30eb\u306e\u51e6\u7406\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +ExtractSafari_Error_Parsing_Bookmark=Safari\u30d6\u30c3\u30af\u30de\u30fc\u30af\u30d5\u30a1\u30a4\u30eb\u306e\u51e6\u7406\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +ExtractSafari_Error_Parsing_Cookies=Safari\u30af\u30c3\u30ad\u30fc\u30d5\u30a1\u30a4\u30eb\u306e\u51e6\u7406\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +ExtractSafari_Module_Name=Safari ExtractSru_error_finding_export_srudb_program=export_srudb\u30d7\u30ed\u30b0\u30e9\u30e0\u306e\u691c\u7d22\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f ExtractSru_module_name=\u30b7\u30b9\u30c6\u30e0\u30fb\u30ea\u30bd\u30fc\u30b9\u4f7f\u7528\u91cf\u62bd\u51fa\u6a5f\u80fd ExtractSru_process_error_executing_export_srudb_program=export_srudb\u30d7\u30ed\u30b0\u30e9\u30e0\u306e\u5b9f\u884c\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f @@ -63,6 +116,17 @@ ExtractWebAccountType.parentModuleName=\u6700\u8fd1\u306e\u6d3b\u52d5 ExtractWebAccountType.role.admin=\u7ba1\u7406\u8005\u306e\u5f79\u5272 ExtractWebAccountType.role.moderator=\u30e2\u30c7\u30ec\u30fc\u30bf\u30fc\u306e\u5f79\u5272 ExtractWebAccountType.role.user=\u30e6\u30fc\u30b6\u30fc\u306e\u5f79\u5272 +ExtractZone_Internet=\u30a4\u30f3\u30bf\u30fc\u30cd\u30c3\u30c8\u30be\u30fc\u30f3 +ExtractZone_Local_Intranet=\u30ed\u30fc\u30ab\u30eb\u30fb\u30a4\u30f3\u30c8\u30e9\u30cd\u30c3\u30c8\u30be\u30fc\u30f3 +ExtractZone_Local_Machine=\u30ed\u30fc\u30ab\u30eb\u30fb\u30de\u30b7\u30f3\u30be\u30fc\u30f3 +ExtractZone_Restricted=\u5236\u9650\u4ed8\u304d\u30b5\u30a4\u30c8\u30be\u30fc\u30f3 +ExtractZone_Trusted=\u4fe1\u983c\u3067\u304d\u308b\u30b5\u30a4\u30c8\u30be\u30fc\u30f3 +ExtractZone_process_errMsg=Zone.Identifier\u30d5\u30a1\u30a4\u30eb\u306e\u51e6\u7406\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +ExtractZone_process_errMsg_find=Zone.Identifier\u30d5\u30a1\u30a4\u30eb\u306e\u691c\u7d22\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +ExtractZone_progress_Msg=Zone.Identifier\u30d5\u30a1\u30a4\u30eb\u306e\u62bd\u51fa +Firefox.getAutofillProfiles.errMsg.errAnalyzeFile={0}\uff1a\u30d5\u30a1\u30a4\u30eb\u306e\u5206\u6790\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\uff1a{1} +Firefox.getAutofillProfiles.errMsg.errFetchingFiles=Firefox\u306e\u30aa\u30fc\u30c8\u30d5\u30a3\u30eb\u30fb\u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u30fb\u30d5\u30a1\u30a4\u30eb\u306e\u53d6\u5f97\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +Firefox.getAutofillProfiles.errMsg.noFilesFound=FireFox\u30aa\u30fc\u30c8\u30d5\u30a3\u30eb\u30fb\u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u30fb\u30d5\u30a1\u30a4\u30eb\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3002 Firefox.getBookmark.errMsg.errAnalyzeFile={0}\:\u30d5\u30a1\u30a4\u30eb\:{1}\u306e\u89e3\u6790\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f Firefox.getBookmark.errMsg.errFetchFiles=Firefox\u306e\u30d6\u30c3\u30af\u30de\u30fc\u30af\u30d5\u30a1\u30a4\u30eb\u3092\u53d6\u5f97\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 Firefox.getCookie.errMsg.errAnalyzeFile={0}\:\u30d5\u30a1\u30a4\u30eb\:{1}\u3092\u89e3\u6790\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f @@ -73,6 +137,9 @@ Firefox.getDlPre24.errMsg.errParsingArtifacts={0}\:{1} Firefox\u30a6\u30a7\u30d6 Firefox.getDlV24.errMsg.errAnalyzeFile={0}\:\u30d5\u30a1\u30a4\u30eb\:{1}\u3092\u89e3\u6790\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f Firefox.getDlV24.errMsg.errFetchFiles=Firefox\u306e\u300c\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u300d\u30d5\u30a1\u30a4\u30eb\u3092\u53d6\u5f97\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 Firefox.getDlV24.errMsg.errParsingArtifacts={0}\:{1} Firefox\u30a6\u30a7\u30d6\u5c65\u6b74\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u3092\u30d1\u30fc\u30b9\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +Firefox.getFormsAutofill.errMsg.errAnalyzeFile={0}\uff1a\u30d5\u30a1\u30a4\u30eb\u306e\u5206\u6790\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\uff1a{1} +Firefox.getFormsAutofill.errMsg.errFetchingFiles=Firefox\u306e\u30d5\u30a9\u30fc\u30e0\u5c65\u6b74\u30d5\u30a1\u30a4\u30eb\u306e\u30d5\u30a7\u30c3\u30c1\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 +Firefox.getFormsAutofill.errMsg.noFilesFound=FireFox\u30d5\u30a9\u30fc\u30e0\u5c65\u6b74\u30d5\u30a1\u30a4\u30eb\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3002 Firefox.getHistory.errMsg.errAnalyzeFile={0}\:\u30d5\u30a1\u30a4\u30eb\:{1}\u3092\u89e3\u6790\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f Firefox.getHistory.errMsg.errFetchingFiles=Firefox\u306e\u30a4\u30f3\u30bf\u30fc\u30cd\u30c3\u30c8\u5c65\u6b74\u30d5\u30a1\u30a4\u30eb\u3092\u53d6\u5f97\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 Firefox.getHistory.errMsg.noFilesFound=Firefox\u5c65\u6b74\u30d5\u30a1\u30a4\u30eb\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f\u3002 @@ -80,15 +147,41 @@ Firefox.moduleName=FireFox Firefox.parentModuleName=\u6700\u8fd1\u306e\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3 Firefox.parentModuleName.noSpace=\u6700\u8fd1\u306e\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3 OpenIDE-Module-Display-Category=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb -OpenIDE-Module-Long-Description=\u6700\u8fd1\u306e\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u3002\n\n\u3053\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u306f\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u4e2d\u306e\u30c7\u30a3\u30b9\u30af\u30a4\u30e1\u30fc\u30b8\u304b\u3089\u6709\u7528\u306a\u6700\u8fd1\u306e\u30e6\u30fc\u30b6\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3\u3092\u62bd\u51fa\u3057\u307e\u3059\u3002\u4f8b\u3048\u3070\uff1a\n\n-\u6700\u8fd1\u958b\u3044\u305f\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8\u3001\n-\u30a6\u30a7\u30d6\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3\uff08\u8a2a\u308c\u305f\u30b5\u30a4\u30c8\u3001\u4fdd\u5b58\u3055\u308c\u305fCookie\u3001\u30d6\u30c3\u30af\u30de\u30fc\u30af\u3055\u308c\u305f\u30b5\u30a4\u30c8\u3001\u30b5\u30fc\u30c1\u30a8\u30f3\u30b8\u30f3\u30af\u30a8\u30ea\u3001\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb\uff09\u3001\n-\u6700\u8fd1\u63a5\u7d9a\u3057\u305f\u30c7\u30d0\u30a4\u30b9\u3001\n-\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3055\u308c\u305f\u30d7\u30ed\u30b0\u30e9\u30e0\u3002\n\n\u3053\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u306f\u73fe\u5728Windows\u306e\u30c7\u30a3\u30b9\u30af\u30a4\u30e1\u30fc\u30b8\u3057\u304b\u30b5\u30dd\u30fc\u30c8\u3057\u3066\u3044\u307e\u305b\u3093\u3002\n\u30d7\u30e9\u30b0\u30a4\u30f3\u306fWindows\u7248\u306eAutopsy\u3092\u5229\u7528\u3059\u308b\u3068\u5168\u3066\u306e\u6a5f\u80fd\u304c\u4f7f\u3048\u307e\u3059\u3002 +OpenIDE-Module-Long-Description=\u6700\u8fd1\u306e\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3\u53d6\u8fbc\u307f\u30e2\u30b8\u30e5\u30fc\u30eb\u3002\n\n\u3053\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u306f\u3001\u53d6\u8fbc\u307e\u308c\u3066\u3044\u308b\u30c7\u30a3\u30b9\u30af\u30a4\u30e1\u30fc\u30b8\u3067\u306e\u6700\u8fd1\u306e\u30e6\u30fc\u30b6\u30fc\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3\u306b\u95a2\u3059\u308b\u6709\u7528\u306a\u60c5\u5831\u3092\u62bd\u51fa\u3057\u307e\u3059\u3002\n\n-\u6700\u8fd1\u958b\u3044\u305f\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8\u3001\n-Web\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3\uff08\u30a2\u30af\u30bb\u30b9\u3057\u305f\u30b5\u30a4\u30c8\u3001\u4fdd\u5b58\u3055\u308c\u305fCookie\u3001\u30d6\u30c3\u30af\u30de\u30fc\u30af\u3055\u308c\u305f\u30b5\u30a4\u30c8\u3001\u691c\u7d22\u30a8\u30f3\u30b8\u30f3\u30af\u30a8\u30ea\u3001\u30d5\u30a1\u30a4\u30eb\u306e\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\uff09\u3001\n-\u6700\u8fd1\u63a5\u7d9a\u3055\u308c\u305f\u30c7\u30d0\u30a4\u30b9\u3001\n-\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3055\u308c\u305f\u30d7\u30ed\u30b0\u30e9\u30e0\u3002\n\n\u3053\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u306fWindows\u306e\u307f\u306e\u30c7\u30a3\u30b9\u30af\u30a4\u30e1\u30fc\u30b8\u3092\u30b5\u30dd\u30fc\u30c8\u3057\u3066\u3044\u307e\u3059\u3002\nWindows\u30d0\u30fc\u30b8\u30e7\u30f3\u306eAutopsy\u306b\u30c7\u30d7\u30ed\u30a4\u3059\u308b\u3068\u30d7\u30e9\u30b0\u30a4\u30f3\u306f\u5b8c\u5168\u306b\u6a5f\u80fd\u3057\u307e\u3059\u3002 OpenIDE-Module-Name=\u6700\u8fd1\u306e\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3 OpenIDE-Module-Short-Description=\u6700\u8fd1\u306e\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3\u30d5\u30a1\u30a4\u30f3\u30c0\u30fc\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb +Progress_Message_Analyze_Registry=\u30ec\u30b8\u30b9\u30c8\u30ea\u30d5\u30a1\u30a4\u30eb\u306e\u5206\u6790 +Progress_Message_Analyze_Usage=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u306e\u4f7f\u7528\u72b6\u6cc1\u5206\u6790 Progress_Message_Chrome_AutoFill=Chrome\u81ea\u52d5\u5165\u529b\u30d6\u30e9\u30a6\u30b6{0} Progress_Message_Chrome_Bookmarks=Chrome\u30d6\u30c3\u30af\u30de\u30fc\u30af\u30d6\u30e9\u30a6\u30b6{0} +Progress_Message_Chrome_Cache=Chrome\u30ad\u30e3\u30c3\u30b7\u30e5 Progress_Message_Chrome_Cookies=Chrome\u30af\u30c3\u30ad\u30fc\u30d6\u30e9\u30a6\u30b6{0} Progress_Message_Chrome_Downloads=Chrome\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u30d6\u30e9\u30a6\u30b6{0} +Progress_Message_Chrome_FormHistory=Chrome\u30d5\u30a9\u30fc\u30e0\u306e\u5c65\u6b74 Progress_Message_Chrome_History=Chrome\u5c65\u6b74\u30d6\u30e9\u30a6\u30b6{0} Progress_Message_Chrome_Logins=Chrome\u30ed\u30b0\u30a4\u30f3\u30d6\u30e9\u30a6\u30b6{0} +Progress_Message_Edge_Bookmarks=\u30de\u30a4\u30af\u30ed\u30bd\u30d5\u30c8\u30fb\u30a8\u30c3\u30b8\u30fb\u30d6\u30c3\u30af\u30de\u30fc\u30af +Progress_Message_Edge_Cookies=\u30de\u30a4\u30af\u30ed\u30bd\u30d5\u30c8\u30fb\u30a8\u30c3\u30b8\u30fb\u30af\u30c3\u30ad\u30fc +Progress_Message_Edge_History=\u30de\u30a4\u30af\u30ed\u30bd\u30d5\u30c8\u30fb\u30a8\u30c3\u30b8\u5c65\u6b74 +Progress_Message_Extract_Resent_Docs=\u6700\u8fd1\u306e\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8 +Progress_Message_Find_Search_Query=\u691c\u7d22\u30af\u30a8\u30ea\u3092\u63a2\u3059 +Progress_Message_Firefox_AutoFill=Firefox\u30aa\u30fc\u30c8\u30d5\u30a3\u30eb +Progress_Message_Firefox_Bookmarks=Firefox\u30d6\u30c3\u30af\u30de\u30fc\u30af +Progress_Message_Firefox_Cookies=Firefox\u30af\u30c3\u30ad\u30fc +Progress_Message_Firefox_Downloads=Firefox\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9 +Progress_Message_Firefox_FormHistory=Firefox\u30d5\u30a9\u30fc\u30e0\u306e\u5c65\u6b74 +Progress_Message_Firefox_History=Firefox\u5c65\u6b74 +Progress_Message_IE_AutoFill=IE\u30aa\u30fc\u30c8\u30d5\u30a3\u30eb +Progress_Message_IE_Bookmarks=IE\u30d6\u30c3\u30af\u30de\u30fc\u30af +Progress_Message_IE_Cookies=IE\u30af\u30c3\u30ad\u30fc +Progress_Message_IE_Downloads=IE\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9 +Progress_Message_IE_FormHistory=IE\u30d5\u30a9\u30fc\u30e0\u306e\u5c65\u6b74 +Progress_Message_IE_History=IE\u5c65\u6b74 +Progress_Message_IE_Logins=IE\u30ed\u30b0\u30a4\u30f3 +Progress_Message_Safari_Bookmarks=Safari \u30d6\u30c3\u30af\u30de\u30fc\u30af +Progress_Message_Safari_Cookies=Safari \u30af\u30c3\u30ad\u30fc +Progress_Message_Safari_Downloads=Safari \u30c0\u30a6\u30f3\u30ed\u30fc\u30c9 +Progress_Message_Safari_History=Safari \u5c65\u6b74 RAImageIngestModule.complete.errMsg.failed={0} \u5b8c\u4e86\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f - \u8a73\u7d30\u306f\u30ed\u30b0\u3092\u78ba\u8a8d\u3057\u3066\u4e0b\u3055\u3044
RAImageIngestModule.getDesc=\u30a6\u30a7\u30d6\u30d6\u30e9\u30a6\u30b8\u30f3\u30b0\u3001\u6700\u8fd1\u958b\u3044\u305f\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8\u3001\u6700\u8fd1\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3057\u305f\u30d7\u30ed\u30b0\u30e9\u30e0\u7b49\u306e\u6700\u8fd1\u306e\u30e6\u30fc\u30b6\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3\u3092\u62bd\u51fa\u3057\u307e\u3059\u3002 RAImageIngestModule.getName=\u6700\u8fd1\u306e\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3 @@ -117,6 +210,8 @@ Recently_Used_Artifacts_Mmc=Windows\u7ba1\u7406\u30b3\u30f3\u30bd\u30fc\u30ebMRU Recently_Used_Artifacts_Office_Trustrecords=Office\u306e\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u4f8b\u5916\u304c\u8a31\u53ef\u3055\u308c\u305f\u305f\u3081\u3001TrustRecords\u306b\u4fdd\u5b58\u3055\u308c\u307e\u3057\u305f Recently_Used_Artifacts_Officedocs=Office MRU\u306b\u3088\u308b\u3068\u6700\u8fd1\u958b\u3044\u3066\u307e\u3059 Recently_Used_Artifacts_Winrar=WinRAR MRU\u306b\u3088\u308b\u3068\u6700\u8fd1\u958b\u3044\u3066\u307e\u3059 +RegRipperFullNotFound=\u30d5\u30eb\u30d0\u30fc\u30b8\u30e7\u30f3\u306eRegRipper\u5b9f\u884c\u30d5\u30a1\u30a4\u30eb\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3002 +RegRipperNotFound=Autopsy\u306eRegRipper\u5b9f\u884c\u30d5\u30a1\u30a4\u30eb\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3002 Registry_System_Bam=\u30d0\u30c3\u30af\u30b0\u30e9\u30a6\u30f3\u30c9\u30fb\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3\u30fb\u30e2\u30c7\u30ec\u30fc\u30bf\u30fc\uff08BAM\uff09\u306b\u3088\u308b\u3068\u6700\u8fd1\u5b9f\u884c\u3055\u308c\u307e\u3057\u305f SearchEngineURLQueryAnalyzer.domainSubStr.none=\u7121\u3057 SearchEngineURLQueryAnalyzer.engineName.none=\u7121\u3057 @@ -125,4 +220,10 @@ SearchEngineURLQueryAnalyzer.moduleName.text=\u691c\u7d22\u30a8\u30f3\u30b8\u30f SearchEngineURLQueryAnalyzer.parentModuleName=\u6700\u8fd1\u306e\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3 SearchEngineURLQueryAnalyzer.parentModuleName.noSpace=\u6700\u8fd1\u306e\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3 SearchEngineURLQueryAnalyzer.toString=\u540d\u79f0\uff1a {0}\n\u30c9\u30e1\u30a4\u30f3\u30b5\u30d6\u30b9\u30c8\u30ea\u30f3\u30b0\uff1a {1}\n\u30ab\u30a6\u30f3\u30c8\uff1a {2}\n\u5206\u5272\u30c8\u30fc\u30af\u30f3\n{3} +Shellbag_Artifact_Display_Name=Shell Bags +Shellbag_Key_Attribute_Display_Name=\u30ad\u30fc +Shellbag_Last_Write_Attribute_Display_Name=\u6700\u5f8c\u306e\u66f8\u8fbc\u307f UsbDeviceIdMapper.parseAndLookup.text=\u30d7\u30ed\u30c0\u30af\u30c8\uff1a{0} +cannotBuildXmlParser=XML\u30d1\u30fc\u30b5\u30fc\u3092\u69cb\u7bc9\u3067\u304d\u307e\u305b\u3093\uff1a +cannotLoadSEUQA=\u691c\u7d22\u30a8\u30f3\u30b8\u30f3\u306eURL\u30af\u30a8\u30ea\u30a2\u30ca\u30e9\u30a4\u30b6\u30fc\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30ebSEUQAMappings.xml\u3092\u8aad\u307f\u8fbc\u3081\u307e\u305b\u3093\uff1a +cannotParseXml=XML\u30d5\u30a1\u30a4\u30eb\u3092\u89e3\u6790\u3067\u304d\u307e\u305b\u3093\uff1a diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ChromeCacheExtractor.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ChromeCacheExtractor.java index 9435161a23..f3e073e7f9 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ChromeCacheExtractor.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ChromeCacheExtractor.java @@ -596,8 +596,9 @@ final class ChromeCacheExtractor { if (fileCopyCache.containsKey(fileTableKey)) { return Optional.of(fileCopyCache.get(fileTableKey).getAbstractFile()); } - - List cacheFiles = fileManager.findFiles(dataSource, cacheFileName, cacheFolderName); //NON-NLS + + List cacheFiles = currentCase.getSleuthkitCase().getFileManager().findFilesExactNameExactPath(dataSource, + cacheFileName, cacheFolderName); if (!cacheFiles.isEmpty()) { // Sort the list for consistency. Preference is: // - In correct subfolder and allocated diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chromium.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chromium.java index c8a3bb64cd..371394ff10 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chromium.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chromium.java @@ -41,6 +41,7 @@ import java.util.List; import java.util.Map; import java.util.HashMap; import java.util.ArrayList; +import java.util.Arrays; import org.apache.commons.io.FilenameUtils; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; @@ -59,6 +60,7 @@ import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.ReadContentInputStream.ReadContentInputStreamException; +import org.sleuthkit.datamodel.Score; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; import org.sleuthkit.datamodel.blackboardutils.WebBrowserArtifactsHelper; @@ -67,7 +69,7 @@ import org.sleuthkit.datamodel.blackboardutils.WebBrowserArtifactsHelper; * Chromium recent activity extraction */ class Chromium extends Extract { - + 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 private static final String COOKIE_QUERY = "SELECT name, value, host_key, expires_utc,last_access_utc, creation_utc FROM cookies"; //NON-NLS @@ -631,7 +633,7 @@ class Chromium extends Extract { BlackboardArtifact webDownloadArtifact = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, downloadFile, bbattributes); bbartifacts.add(webDownloadArtifact); String normalizedFullPath = FilenameUtils.normalize(fullPath, true); - for (AbstractFile downloadedFile : fileManager.findFiles(dataSource, FilenameUtils.getName(normalizedFullPath), FilenameUtils.getPath(normalizedFullPath))) { + for (AbstractFile downloadedFile : currentCase.getSleuthkitCase().getFileManager().findFilesExactNameExactPath(dataSource, FilenameUtils.getName(normalizedFullPath), FilenameUtils.getPath(normalizedFullPath))) { bbartifacts.add(createAssociatedArtifact(downloadedFile, webDownloadArtifact)); break; } @@ -823,11 +825,15 @@ class Chromium extends Extract { // get form address atifacts getFormAddressArtifacts(webDataFile, tempFilePath, isSchemaV8X); if (databaseEncrypted) { - Collection bbattributes = new ArrayList<>(); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COMMENT, - RecentActivityExtracterModuleFactory.getModuleName(), - String.format("%s Autofill Database Encryption Detected", browser))); - bbartifacts.add(createArtifactWithAttributes(ARTIFACT_TYPE.TSK_ENCRYPTION_DETECTED, webDataFile, bbattributes)); + String comment = String.format("%s Autofill Database Encryption Detected", browser); + Collection bbattributes = Arrays.asList( + new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COMMENT, + RecentActivityExtracterModuleFactory.getModuleName(), comment)); + + bbartifacts.add( + webDataFile.newAnalysisResult( + BlackboardArtifact.Type.TSK_ENCRYPTION_DETECTED, Score.SCORE_NOTABLE, + null, null, comment, bbattributes).getAnalysisResult()); } } catch (NoCurrentCaseException | TskCoreException | Blackboard.BlackboardException ex) { logger.log(Level.SEVERE, String.format("Error adding artifacts to the case database " diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/DataSourceUsageAnalyzer.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/DataSourceUsageAnalyzer.java index bd6b5836d5..0e4fa5ecf1 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/DataSourceUsageAnalyzer.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/DataSourceUsageAnalyzer.java @@ -157,17 +157,13 @@ class DataSourceUsageAnalyzer extends Extract { * does not exist with the given description. * * @param osType - the OS_TYPE to check for - * - * @return true if any specified files exist false if none exist */ private void checkIfOsSpecificVolume(ExtractOs.OS_TYPE osType) throws TskCoreException { - FileManager fileManager = currentCase.getServices().getFileManager(); for (String filePath : osType.getFilePaths()) { - for (AbstractFile file : fileManager.findFiles(dataSource, FilenameUtils.getName(filePath), FilenameUtils.getPath(filePath))) { - if ((file.getParentPath() + file.getName()).equals(filePath)) { - createDataSourceUsageArtifact(osType.getDsUsageLabel()); - return; - } + for (AbstractFile file : currentCase.getSleuthkitCase().getFileManager().findFilesExactNameExactPath(dataSource, + FilenameUtils.getName(filePath), FilenameUtils.getPath(filePath))) { + createDataSourceUsageArtifact(osType.getDsUsageLabel()); + return; } } } diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Extract.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Extract.java index c052ed2bbe..fc8cb67c65 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Extract.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Extract.java @@ -34,7 +34,6 @@ import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; -import java.util.Optional; import java.util.logging.Level; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; @@ -51,7 +50,6 @@ import org.sleuthkit.datamodel.BlackboardArtifact; import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.Content; -import org.sleuthkit.datamodel.OsAccount; import org.sleuthkit.datamodel.Score; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractOs.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractOs.java index a76c1652dd..6bc00ada63 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractOs.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractOs.java @@ -117,12 +117,10 @@ class ExtractOs extends Extract { * search for */ private AbstractFile getFirstFileFound(List pathsToSearchFor) throws TskCoreException{ - FileManager fileManager = currentCase.getServices().getFileManager(); for (String filePath : pathsToSearchFor) { - for (AbstractFile file : fileManager.findFiles(dataSource, FilenameUtils.getName(filePath), FilenameUtils.getPath(filePath))) { - if ((file.getParentPath() + file.getName()).equals(filePath)) { - return file; - } + List files = currentCase.getSleuthkitCase().getFileManager().findFilesExactNameExactPath(dataSource, FilenameUtils.getName(filePath), FilenameUtils.getPath(filePath)); + if (!files.isEmpty()) { + return files.get(0); } } return null; diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java index fd0c24e091..e3df208180 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java @@ -29,7 +29,9 @@ import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; +import java.io.InputStreamReader; import java.io.StringReader; +import java.nio.charset.StandardCharsets; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.logging.Level; @@ -815,7 +817,7 @@ class ExtractRegistry extends Extract { try { bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, value)); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, itemMtime)); - BlackboardArtifact bbart = regFile.newDataArtifact(new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_DELETED_PROG), bbattributes); + BlackboardArtifact bbart = regFile.newDataArtifact(new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_INSTALLED_PROG), bbattributes); newArtifacts.add(bbart); } catch (TskCoreException ex) { logger.log(Level.SEVERE, "Error adding installed program artifact to blackboard.", ex); //NON-NLS @@ -1062,7 +1064,7 @@ class ExtractRegistry extends Extract { File regfile = new File(regFilePath); List newArtifacts = new ArrayList<>(); - try (BufferedReader bufferedReader = new BufferedReader(new FileReader(regfile))) { + try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(regfile), StandardCharsets.UTF_8))) { // Read the file in and create a Document and elements String userInfoSection = "User Information"; String previousLine = null; @@ -1434,21 +1436,23 @@ class ExtractRegistry extends Extract { && !line.contains(("Recent File List"))) { // Split line on "> " which is the record delimiter between position and file String tokens[] = line.split("> "); - String fileName = tokens[1]; - Collection attributes = new ArrayList<>(); - attributes.add(new BlackboardAttribute(TSK_PATH, getName(), fileName)); - attributes.add(new BlackboardAttribute(TSK_COMMENT, getName(), comment)); - try{ - BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes); - if (bba != null) { - bbartifacts.add(bba); - bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); + if (tokens.length > 1) { + String fileName = tokens[1]; + Collection attributes = new ArrayList<>(); + attributes.add(new BlackboardAttribute(TSK_PATH, getName(), fileName)); + attributes.add(new BlackboardAttribute(TSK_COMMENT, getName(), comment)); + try{ + BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes); if (bba != null) { bbartifacts.add(bba); + bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); + if (bba != null) { + bbartifacts.add(bba); + } } + } catch(TskCoreException ex) { + logger.log(Level.SEVERE, String.format("Failed to create TSK_RECENT_OBJECT artifact for file %d", regFile.getId()), ex); } - } catch(TskCoreException ex) { - logger.log(Level.SEVERE, String.format("Failed to create TSK_RECENT_OBJECT artifact for file %d", regFile.getId()), ex); } line = reader.readLine(); } @@ -1682,18 +1686,13 @@ class ExtractRegistry extends Extract { * @returnv BlackboardArtifact or a null value */ private BlackboardArtifact createAssociatedArtifact(String filePathName, BlackboardArtifact bba) { - org.sleuthkit.autopsy.casemodule.services.FileManager fileManager = currentCase.getServices().getFileManager(); String fileName = FilenameUtils.getName(filePathName); String filePath = FilenameUtils.getPath(filePathName); List sourceFiles; try { - sourceFiles = fileManager.findFiles(dataSource, fileName, filePath); //NON-NLS + sourceFiles = currentCase.getSleuthkitCase().getFileManager().findFilesExactNameExactPath(dataSource, fileName, filePath); if (!sourceFiles.isEmpty()) { - for (AbstractFile sourceFile : sourceFiles) { - if (sourceFile.getParentPath().endsWith(filePath)) { - return createAssociatedArtifact(sourceFile, bba); - } - } + return createAssociatedArtifact(sourceFiles.get(0), bba); } } catch (TskCoreException ex) { // only catching the error and displaying the message as the file may not exist on the @@ -1996,7 +1995,7 @@ class ExtractRegistry extends Extract { } else { osAccount = optional.get(); if (userName != null && !userName.isEmpty()) { - OsAccountUpdateResult updateResult= accountMgr.updateCoreWindowsOsAccountAttributes(osAccount, null, userName, null, host); + OsAccountUpdateResult updateResult= accountMgr.updateCoreWindowsOsAccountAttributes(osAccount, null, userName, domainName.isEmpty() ? null : domainName, host); osAccount = updateResult.getUpdatedAccount().orElse(osAccount); } } @@ -2188,7 +2187,7 @@ class ExtractRegistry extends Extract { accountMgr.addExtendedOsAccountAttributes(osAccount, attributes); // update the loginname - accountMgr.updateCoreWindowsOsAccountAttributes(osAccount, null, loginName, null, host); + accountMgr.updateCoreWindowsOsAccountAttributes(osAccount, null, loginName, domainName.isEmpty() ? null : domainName, host); // update other standard attributes - fullname, creationdate accountMgr.updateStandardOsAccountAttributes(osAccount, fullName, null, null, creationTime); diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractSafari.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractSafari.java index 2bf0351542..429666f8d6 100755 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractSafari.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractSafari.java @@ -647,8 +647,6 @@ final class ExtractSafari extends Extract { Long time = null; Long pathID = null; - FileManager fileManager = getCurrentCase().getServices().getFileManager(); - NSString nsstring = (NSString) entry.get(PLIST_KEY_DOWNLOAD_URL); if (nsstring != null) { url = nsstring.toString(); @@ -669,7 +667,8 @@ final class ExtractSafari extends Extract { bbartifacts.add(webDownloadArtifact); // find the downloaded file and create a TSK_ASSOCIATED_OBJECT for it, associating it with the TSK_WEB_DOWNLOAD artifact. - for (AbstractFile downloadedFile : fileManager.findFiles(dataSource, FilenameUtils.getName(path), FilenameUtils.getPath(path))) { + for (AbstractFile downloadedFile : currentCase.getSleuthkitCase().getFileManager().findFilesExactNameExactPath(dataSource, + FilenameUtils.getName(path), FilenameUtils.getPath(path))) { bbartifacts.add(createAssociatedArtifact(downloadedFile, webDownloadArtifact)); break; } diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractZoneIdentifier.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractZoneIdentifier.java index b8c8d18dba..fc59685f9e 100755 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractZoneIdentifier.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractZoneIdentifier.java @@ -43,8 +43,8 @@ import org.sleuthkit.datamodel.ReadContentInputStream; import org.sleuthkit.datamodel.TskCoreException; /** - * Extract the :Zone.Identifier alternate data stream files. A file with - * a :Zone.Identifier extension contains information about the similarly + * Extract the :Zone.Identifier alternate data stream files. A file with a + * :Zone.Identifier extension contains information about the similarly * named (with out zone identifier extension) downloaded file. */ final class ExtractZoneIdentifier extends Extract { @@ -53,6 +53,7 @@ final class ExtractZoneIdentifier extends Extract { private static final String ZONE_IDENTIFIER_FILE = "%:Zone.Identifier"; //NON-NLS private static final String ZONE_IDENTIFIER = ":Zone.Identifier"; //NON-NLS + private Content dataSource; @Messages({ "ExtractZone_process_errMsg_find=A failure occured while searching for :Zone.Indentifier files.", @@ -62,7 +63,7 @@ final class ExtractZoneIdentifier extends Extract { @Override void process(Content dataSource, IngestJobContext context, DataSourceIngestModuleProgress progressBar) { - + this.dataSource = dataSource; progressBar.progress(Bundle.ExtractZone_progress_Msg()); List zoneFiles = null; @@ -76,7 +77,7 @@ final class ExtractZoneIdentifier extends Extract { if (zoneFiles == null || zoneFiles.isEmpty()) { return; } - + Set knownPathIDs = null; try { knownPathIDs = getPathIDsForType(TSK_WEB_DOWNLOAD); @@ -93,20 +94,20 @@ final class ExtractZoneIdentifier extends Extract { Collection downloadArtifacts = new ArrayList<>(); for (AbstractFile zoneFile : zoneFiles) { - + if (context.dataSourceIngestIsCancelled()) { return; } - + try { - processZoneFile(context, dataSource, zoneFile, associatedObjectArtifacts, downloadArtifacts, knownPathIDs); + processZoneFile(context, zoneFile, associatedObjectArtifacts, downloadArtifacts, knownPathIDs); } catch (TskCoreException ex) { addErrorMessage(Bundle.ExtractZone_process_errMsg()); String message = String.format("Failed to process zone identifier file %s", zoneFile.getName()); //NON-NLS LOG.log(Level.WARNING, message, ex); } } - + if (!context.dataSourceIngestIsCancelled()) { postArtifacts(associatedObjectArtifacts); postArtifacts(downloadArtifacts); @@ -116,15 +117,14 @@ final class ExtractZoneIdentifier extends Extract { /** * Process a single Zone Identifier file. * - * @param context IngestJobContext - * @param dataSource Content - * @param zoneFile Zone Indentifier file + * @param context IngestJobContext + * @param zoneFile Zone Identifier file * @param associatedObjectArtifacts List for TSK_ASSOCIATED_OBJECT artifacts - * @param downloadArtifacts List for TSK_WEB_DOWNLOAD artifacts + * @param downloadArtifacts List for TSK_WEB_DOWNLOAD artifacts * * @throws TskCoreException */ - private void processZoneFile(IngestJobContext context, Content dataSource, + private void processZoneFile(IngestJobContext context, AbstractFile zoneFile, Collection associatedObjectArtifacts, Collection downloadArtifacts, Set knownPathIDs) throws TskCoreException { @@ -142,63 +142,100 @@ final class ExtractZoneIdentifier extends Extract { return; } - AbstractFile downloadFile = getDownloadFile(dataSource, zoneFile); + AbstractFile downloadFile = getDownloadFile(zoneFile); if (downloadFile != null) { // Only create a new TSK_WEB_DOWNLOAD artifact if one does not exist for downloadFile - if (!knownPathIDs.contains(downloadFile.getDataSourceObjectId())) { + if (!knownPathIDs.contains(downloadFile.getId())) { // The zone identifier file is the parent of this artifact // because it is the file we parsed to get the data BlackboardArtifact downloadBba = createDownloadArtifact(zoneFile, zoneInfo, downloadFile); downloadArtifacts.add(downloadBba); // create a TSK_ASSOCIATED_OBJECT for the downloaded file, associating it with the TSK_WEB_DOWNLOAD artifact. if (downloadFile.getArtifactsCount(TSK_ASSOCIATED_OBJECT) == 0) { - associatedObjectArtifacts.add(createAssociatedArtifact(downloadFile, downloadBba)); + associatedObjectArtifacts.add(createAssociatedArtifact(downloadFile, downloadBba)); } } - + } } /** * Find the file that the Zone.Identifier file was created alongside. * - * @param dataSource Content - * @param zoneFile The zone identifier case file + * @param zoneFile The zone identifier case file * * @return The downloaded file or null if a file was not found * * @throws TskCoreException */ - private AbstractFile getDownloadFile(Content dataSource, AbstractFile zoneFile) throws TskCoreException { - AbstractFile downloadFile = null; - - org.sleuthkit.autopsy.casemodule.services.FileManager fileManager - = currentCase.getServices().getFileManager(); + private AbstractFile getDownloadFile(AbstractFile zoneFile) throws TskCoreException { String downloadFileName = zoneFile.getName().replace(ZONE_IDENTIFIER, ""); //NON-NLS - List fileList = fileManager.findFiles(dataSource, downloadFileName, zoneFile.getParentPath()); + // The downloaded file should have been added to the database just before the + // Zone.Identifier file, possibly with a slack file in between. We will load those files + // and test them first since loading files by ID will typically be much faster than + // the fallback method of searching by file name. + AbstractFile potentialDownloadFile = currentCase.getSleuthkitCase().getAbstractFileById(zoneFile.getId() - 1); + if (isZoneFileMatch(zoneFile, downloadFileName, potentialDownloadFile)) { + return potentialDownloadFile; + } + potentialDownloadFile = currentCase.getSleuthkitCase().getAbstractFileById(zoneFile.getId() - 2); + if (isZoneFileMatch(zoneFile, downloadFileName, potentialDownloadFile)) { + return potentialDownloadFile; + } - if (fileList.size() == 1) { - downloadFile = fileList.get(0); + org.sleuthkit.autopsy.casemodule.services.FileManager fileManager = currentCase.getServices().getFileManager(); + List fileList = fileManager.findFilesExactName(zoneFile.getParent().getId(), downloadFileName); - // Check that the download file and the zone file came from the same dir - if (!downloadFile.getParentPath().equals(zoneFile.getParentPath())) { - downloadFile = null; - } else if (zoneFile.getMetaAddr() != downloadFile.getMetaAddr()) { - downloadFile = null; + for (AbstractFile file : fileList) { + if (isZoneFileMatch(zoneFile, downloadFileName, file)) { + return file; } } - return downloadFile; + return null; + } + + /** + * Test whether a given zoneFile is associated with another file. Criteria: + * Metadata addresses match Names match Parent paths match + * + * @param zoneFile The zone file. + * @param expectedDownloadFileName The expected name for the downloaded + * file. + * @param possibleDownloadFile The file to test against the zone file. + * + * @return true if possibleDownloadFile corresponds to zoneFile, false + * otherwise. + */ + private boolean isZoneFileMatch(AbstractFile zoneFile, String expectedDownloadFileName, AbstractFile possibleDownloadFile) { + + if (zoneFile == null || possibleDownloadFile == null || expectedDownloadFileName == null) { + return false; + } + + if (zoneFile.getMetaAddr() != possibleDownloadFile.getMetaAddr()) { + return false; + } + + if (!expectedDownloadFileName.equals(possibleDownloadFile.getName())) { + return false; + } + + if (!possibleDownloadFile.getParentPath().equals(zoneFile.getParentPath())) { + return false; + } + + return true; } /** * Create a TSK_WEB_DOWNLOAD Artifact for the given zone identifier file. * - * @param zoneFile Zone identifier file - * @param zoneInfo ZoneIdentifierInfo file wrapper object + * @param zoneFile Zone identifier file + * @param zoneInfo ZoneIdentifierInfo file wrapper object * @param downloadFile The file associated with the zone identifier * * @return BlackboardArifact for the given parameters @@ -206,16 +243,16 @@ final class ExtractZoneIdentifier extends Extract { private BlackboardArtifact createDownloadArtifact(AbstractFile zoneFile, ZoneIdentifierInfo zoneInfo, AbstractFile downloadFile) throws TskCoreException { String downloadFilePath = downloadFile.getParentPath() + downloadFile.getName(); - + long pathID = Util.findID(dataSource, downloadFilePath); Collection bbattributes = createDownloadAttributes( - downloadFilePath, null, + downloadFilePath, pathID, zoneInfo.getURL(), null, (zoneInfo.getURL() != null ? NetworkUtils.extractDomain(zoneInfo.getURL()) : ""), null); if (zoneInfo.getZoneIdAsString() != null) { bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT, - RecentActivityExtracterModuleFactory.getModuleName(), - zoneInfo.getZoneIdAsString())); + RecentActivityExtracterModuleFactory.getModuleName(), + zoneInfo.getZoneIdAsString())); } return createArtifactWithAttributes(TSK_WEB_DOWNLOAD, zoneFile, bbattributes); } @@ -254,11 +291,11 @@ final class ExtractZoneIdentifier extends Extract { /** * Wrapper class for information in the :ZoneIdentifier file. The - * Zone.Identifier file has a simple format of \key\=\value\. There - * are four known keys: ZoneId, ReferrerUrl, HostUrl, and - * LastWriterPackageFamilyName. Not all browsers will put all values in the - * file, in fact most will only supply the ZoneId. Only Edge supplies the - * LastWriterPackageFamilyName. + * Zone.Identifier file has a simple format of + * \key\=\value\. There are four known keys: ZoneId, + * ReferrerUrl, HostUrl, and LastWriterPackageFamilyName. Not all browsers + * will put all values in the file, in fact most will only supply the + * ZoneId. Only Edge supplies the LastWriterPackageFamilyName. */ private final static class ZoneIdentifierInfo { @@ -297,8 +334,8 @@ final class ExtractZoneIdentifier extends Extract { zoneValue = Integer.parseInt(value); } } catch (NumberFormatException ex) { - String message = String.format("Unable to parse Zone Id for File %s", fileName); //NON-NLS - LOG.log(Level.WARNING, message); + String message = String.format("Unable to parse Zone Id for File %s", fileName); //NON-NLS + LOG.log(Level.WARNING, message); } return zoneValue; diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Firefox.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Firefox.java index 6dd30ed4cc..87bbb0232d 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Firefox.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Firefox.java @@ -592,7 +592,8 @@ class Firefox extends Extract { bbartifacts.add(webDownloadArtifact); // find the downloaded file and create a TSK_ASSOCIATED_OBJECT for it, associating it with the TSK_WEB_DOWNLOAD artifact. - for (AbstractFile downloadedFile : fileManager.findFiles(dataSource, FilenameUtils.getName(downloadedFilePath), FilenameUtils.getPath(downloadedFilePath))) { + for (AbstractFile downloadedFile : currentCase.getSleuthkitCase().getFileManager().findFilesExactNameExactPath(dataSource, + FilenameUtils.getName(downloadedFilePath), FilenameUtils.getPath(downloadedFilePath))) { bbartifacts.add(createAssociatedArtifact(downloadedFile, webDownloadArtifact)); break; } @@ -727,7 +728,8 @@ class Firefox extends Extract { bbartifacts.add(webDownloadArtifact); // find the downloaded file and create a TSK_ASSOCIATED_OBJECT for it, associating it with the TSK_WEB_DOWNLOAD artifact. - for (AbstractFile downloadedFile : fileManager.findFiles(dataSource, FilenameUtils.getName(downloadedFilePath), FilenameUtils.getPath(downloadedFilePath))) { + for (AbstractFile downloadedFile : currentCase.getSleuthkitCase().getFileManager().findFilesExactNameExactPath(dataSource, + FilenameUtils.getName(downloadedFilePath), FilenameUtils.getPath(downloadedFilePath))) { bbartifacts.add(createAssociatedArtifact(downloadedFile, webDownloadArtifact)); break; } diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java index b0c119ae25..d9ad0fbfb8 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java @@ -152,13 +152,12 @@ class RecentDocumentsByLnk extends Extract { * @returnv BlackboardArtifact or a null value */ private BlackboardArtifact createAssociatedArtifact(String filePathName, BlackboardArtifact bba) { - org.sleuthkit.autopsy.casemodule.services.FileManager fileManager = currentCase.getServices().getFileManager(); String normalizePathName = FilenameUtils.normalize(filePathName, true); String fileName = FilenameUtils.getName(normalizePathName); String filePath = FilenameUtils.getPath(normalizePathName); List sourceFiles; try { - sourceFiles = fileManager.findFiles(dataSource, fileName, filePath); //NON-NLS + sourceFiles = currentCase.getSleuthkitCase().getFileManager().findFilesExactNameExactPath(dataSource, fileName, filePath); for (AbstractFile sourceFile : sourceFiles) { if (sourceFile.getParentPath().endsWith(filePath)) { return createAssociatedArtifact(sourceFile, bba); diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Util.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Util.java index ff95c60ca8..766c3c61de 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Util.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Util.java @@ -135,8 +135,7 @@ class Util { parent_path = parent_path.substring(0, index); List files = null; try { - FileManager fileManager = Case.getCurrentCaseThrows().getServices().getFileManager(); - files = fileManager.findFiles(dataSource, name, parent_path); + files = Case.getCurrentCaseThrows().getSleuthkitCase().getFileManager().findFilesExactNameExactPath(dataSource, name, parent_path); } catch (TskCoreException | NoCurrentCaseException ex) { logger.log(Level.WARNING, "Error fetching 'index.data' files for Internet Explorer history."); //NON-NLS } diff --git a/TSKVersion.xml b/TSKVersion.xml index c0fece9373..0c5ef49ada 100644 --- a/TSKVersion.xml +++ b/TSKVersion.xml @@ -1,3 +1,3 @@ - + diff --git a/Testing/nbproject/project.xml b/Testing/nbproject/project.xml index acf97c4ddf..141594e95a 100644 --- a/Testing/nbproject/project.xml +++ b/Testing/nbproject/project.xml @@ -47,7 +47,7 @@ 10 - 10.23 + 10.24
diff --git a/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties b/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties index c2df473fe0..d1961563c4 100644 --- a/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties +++ b/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties @@ -1,5 +1,5 @@ #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 SPLASH_HEIGHT=314 SPLASH_WIDTH=538 diff --git a/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties b/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties index d519362703..e71aa34b66 100644 --- a/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties +++ b/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties @@ -1,4 +1,4 @@ #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_No_Project=Autopsy 4.18.0 diff --git a/build.xml b/build.xml index 7fc513ce24..a815fb2168 100644 --- a/build.xml +++ b/build.xml @@ -113,10 +113,14 @@ + + + + - + @@ -342,8 +346,8 @@ - - + + diff --git a/docs/doxygen-user/Doxyfile b/docs/doxygen-user/Doxyfile index d00e28635a..6074fa5e59 100644 --- a/docs/doxygen-user/Doxyfile +++ b/docs/doxygen-user/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NAME = "Autopsy User Documentation" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 4.18.0 +PROJECT_NUMBER = 4.19.0 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a @@ -1025,7 +1025,7 @@ GENERATE_HTML = YES # The default directory is: html. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_OUTPUT = 4.18.0 +HTML_OUTPUT = 4.19.0 # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each # generated HTML page (for example: .htm, .php, .asp). diff --git a/docs/doxygen-user/adHocKeywordSearch.dox b/docs/doxygen-user/adHocKeywordSearch.dox index 58ff25f2b4..6478028876 100644 --- a/docs/doxygen-user/adHocKeywordSearch.dox +++ b/docs/doxygen-user/adHocKeywordSearch.dox @@ -82,7 +82,7 @@ Results will be opened in a separate Results Viewer for every search executed. I \section ad_hoc_kw_lists Keyword Lists -In addition to being selected during ingest, keyword lists can also be run through the Keyword Lists button. For information on setting up these keyword lists, see the \ref keywordListsTab section of the ingest module documentation. +In addition to being selected during ingest, keyword lists can also be run through the Keyword Lists button. For information on setting up these keyword lists, see the \ref keyword_keywordListsTab section of the ingest module documentation. Lists created using the Keyword Search Configuration Dialog can be manually searched by the user by pressing on the 'Keyword Lists' button and selecting the check boxes corresponding to the lists to be searched. The search can be restricted to only certain data sources by selecting the checkbox near the bottom and then highlighting the data sources to search within. Multiple data sources can be selected used shift+left click or control+left click. Once everything has been configured, press "Search" to begin the search. The "Save search results" checkbox determines whether the search results will be saved to the case database. diff --git a/docs/doxygen-user/auto_ingest_administration.dox b/docs/doxygen-user/auto_ingest_administration.dox index 089a34d474..029a3d47f8 100644 --- a/docs/doxygen-user/auto_ingest_administration.dox +++ b/docs/doxygen-user/auto_ingest_administration.dox @@ -34,7 +34,15 @@ With the admin file in place, the user can right-click on jobs in each of the ta \image html AutoIngest/admin_jobs_panel.png -In the Running Jobs tables, the ingest progress can be viewed and the current job can be cancelled. Note that cancellation can take some time. +You can also selectively enable \ref keyword_search_ocr_config "optical character recognition (OCR)" on a case-by-case basis. This will override the normal Keyword Search settings for every job in the case. Jobs in progress will not be affected. To enable OCR for a case, right-click on a job from that case in the Pending Jobs table and select "Enable OCR For This Case". + +\image html admin_jobs_ocr1.png + +Once enabled, a green checkmark will appear in the OCR column next to every pending job for that case. + +\image html admin_jobs_ocr2.png + +In the Running Jobs tables, the ingest progress can be viewed and the current job can be cancelled. Note that cancellation can take some time. You can also generate a thread dump if you suspect ingest may be stuck. \image html AutoIngest/admin_jobs_cancel.png @@ -42,9 +50,11 @@ In the Completed Jobs table, the user can reprocess a job (generally useful when \image html AutoIngest/admin_jobs_completed.png + + \section auto_ingest_admin_nodes_panel Auto Ingest Nodes Panel -The Nodes panel displays the status of every online auto ingest node. Additionally, an admin can pause or resume a node, or shut down a node entirely (i.e., exit the Autopsy app). +The Nodes panel displays the status of every online auto ingest node. Additionally, an admin can pause or resume a node, generate a thread dump, or shut down a node entirely (i.e., exit the Autopsy app). \image html AutoIngest/admin_nodes_panel.png diff --git a/docs/doxygen-user/auto_ingest_setup.dox b/docs/doxygen-user/auto_ingest_setup.dox index 3e09b11c80..31f0423560 100644 --- a/docs/doxygen-user/auto_ingest_setup.dox +++ b/docs/doxygen-user/auto_ingest_setup.dox @@ -44,6 +44,8 @@ The "Advanced Settings" button will bring up the automated ingest job settings. \image html AutoIngest/advanced_settings.png +The Automated Ingest Pause Setting section lets you configure a weekly time period during which ingest will not run. This is useful if any of your network services has regularly scheduled downtime. Note that ingest isn't immediately stopped at the given "Start Time" - it will run until the current file is processed or the current ingest module is complete. For this reason, we suggest using a lead time of two hours before your system will go down. For example, if the network is not accessible from 4:00 PM to 5:00 PM every Sunday, you should set the start time to 14:00 and the duration to 3 hours (to cover the lead time and the down time). + The Automated Ingest Job Settings section contains the following options:
System synchronization wait time
diff --git a/docs/doxygen-user/central_repo.dox b/docs/doxygen-user/central_repo.dox index ce60070119..7745e4f884 100644 --- a/docs/doxygen-user/central_repo.dox +++ b/docs/doxygen-user/central_repo.dox @@ -111,7 +111,11 @@ Descriptions of the property types: - ICCID Number - ICCID properties are currently only created by custom Autopsy modules. - Credit Card - - Credid Card properties are created by the \ref keyword_search_page. + - Credit Card properties are created by the \ref keyword_search_page. +- OS Account + - OS account properties are created by the disk image data source processor and the \ref recent_activity_page. +- Installed Programs + - Installed program properties are created primarily by the \ref recent_activity_page. - App-specific Accounts (Facebook, Twitter, etc) - These properties primarily come from the \ref android_analyzer_page. @@ -148,7 +152,7 @@ There are three settings for the Central Repository ingest module:
  • Save items to the Central Repository - This should only be unselected in the rare case that you don't want to add any properties from the current data source to the central repository, but still want to flag past occurrences.
  • Flag items previously tagged as notable - Enabling this causes Interesting Item/File artifacts to be created when properties matching those previously flagged are found. See the next section \ref cr_tagging for details. -
  • Flag previously seen devices - When this is enabled, an Interesting Item artifact will be created if any device-related property (USB, MAC Address, IMSI, IMEI, ICCID) is found that is already in the central repository, regardless of whether they have been flagged. +
  • Flag previously seen devices and users - When this is enabled, an Interesting Item artifact will be created if any device-related property (USB, MAC Address, IMSI, IMEI, ICCID) or an OS account is found that is already in the central repository, regardless of whether they have been flagged.
  • \subsection cr_tagging Tagging Files and Artifacts diff --git a/docs/doxygen-user/content_viewer.dox b/docs/doxygen-user/content_viewer.dox index be5d5b5a33..425fc8eef1 100644 --- a/docs/doxygen-user/content_viewer.dox +++ b/docs/doxygen-user/content_viewer.dox @@ -75,9 +75,9 @@ Registry hive files can be viewed in a format similar to a registry editor. \image html content_viewer_registry.png -\section cv_metadata File Metadata +\section cv_metadata File Metadata / Source File Metadata -The File Metadata tab displays basic information about the file, such as type, size, and hash. It also displays the output of the Sleuth Kit istat tool. +The File Metadata tab displays basic information about the file selected or the file associated with the result, such as type, size, and hash. It also displays the output of the Sleuth Kit istat tool. \image html content_viewer_metadata.png @@ -87,14 +87,20 @@ The OS Accounts tab displays information on the OS account associated with a giv \image html content_viewer_os_account.png -\section cv_results Results +\section cv_results Data Artifacts -The Results tab is active when selecting items with associated results such as keyword hits, call logs, and messages. The exact fields displayed depend on the type of result. The two images below show the Results tab for a call log and a web bookmark. +The Data Artifacts tab shows the artifacts associated with the item selected in the result viewer such as web bookmarks, call logs, and messages. The exact fields displayed depend on the type of data artifact. The two images below show the Data Artifacts tab for a call log and a web bookmark. \image html content_viewer_results_call.png
    \image html content_viewer_results_bookmark.png +\section cv_analysis_results Analysis Results + +The Analysis Results tab shows all analysis results associated with the item selected in the result viewer. If you select an analysis result, it will auto-scroll to that result in the list. Analysis results come from data such as hash set hits, interesting items, and keyword hits. The image below shows web category analysis results. + +\image html content_viewer_analysis_result_webcat.png + \section cv_context Context The Context tab shows information on where a file came from and allows you to navigate to the original result. For example, it can show the the URL for downloaded files and the email message a file was attached to. In the image below you can see the context for an image that was sent as an email attachment. diff --git a/docs/doxygen-user/file_search.dox b/docs/doxygen-user/file_search.dox index 5c779a65a8..e294dc2a24 100644 --- a/docs/doxygen-user/file_search.dox +++ b/docs/doxygen-user/file_search.dox @@ -21,18 +21,18 @@ or select the "Tools", "File Search by Attributes". There are several categories that you can use to filter and show the directories and files within the images in the current opened case. The categories are: \li Name: -Search for all files and directory whose name contains the pattern given. +Search for all files and directories whose name contains the pattern given. Search is on the file/directory name only and does not look at the parent path. Note: it doesn't support regular expression and keyword matching. \li Size: -Search for all files and directory whose size matches the pattern given. The pattern can be "equal to", "greater than", and "less than". The unit for the size can be "Byte(s)", "KB", "MB", "GB", and "TB". +Search for all files and directories whose size matches the pattern given. The pattern can be "equal to", "greater than", and "less than". The unit for the size can be "Byte(s)", "KB", "MB", "GB", and "TB". \li MIME Type: Search for all files with the selected MIME type. Multiple types can be used by holding SHIFT or CTRL while selecting. \li MD5: Search for all files with the given MD5 hash. \li Date: -Search for all files and directory whose "date property" is within the date range given. The "date properties" are "Modified Date", "Accessed Date", "Changed Date", and "Created Date". You must also specify the timezone for the date given. +Search for all files and directories whose "date property" is within the date range given. The "date properties" are "Modified Date", "Accessed Date", "Changed Date", and "Created Date". You must also specify the timezone for the date given. \li Known Status: -Search for all files and directory whose known status is recognized as either Unknown, Known, or Known Bad. For more on Known Status, see the \ref hash_db_page. +Search for all files whose known status is recognized as either Unknown, Known, or Known Bad. For more on Known Status, see the \ref hash_db_page. To use any of these filters, check the box next to the category and click "Search" button to start the search process. The result will show up in the "Result Viewer". \li Data Source: Search only within the specified data source instead of the entire case. Note that multiple data sources can be selected by holding SHIFT or CTRL while selecting. diff --git a/docs/doxygen-user/hosts.dox b/docs/doxygen-user/hosts.dox index 1b3ff6f4e2..b4d1d752ca 100644 --- a/docs/doxygen-user/hosts.dox +++ b/docs/doxygen-user/hosts.dox @@ -19,7 +19,7 @@ Hosts are displayed in the \ref tree_viewer_page. Depending on the \ref view_opt \subsection host_os_accounts OS Accounts -OS accounts can be viewed in the OS Accounts node under Results. Each OS account is associated with a host, and the host information is displayed in the OS Account tab of the content viewer. +OS accounts can be viewed in the OS Accounts node of the tree viewer. Each OS account is associated with a host, and the host information is displayed in the OS Account tab of the content viewer. \image html host_os_accounts.png diff --git a/docs/doxygen-user/images/AutoIngest/admin_jobs_cancel.png b/docs/doxygen-user/images/AutoIngest/admin_jobs_cancel.png index ba3fb81691..d8cbd4deee 100644 Binary files a/docs/doxygen-user/images/AutoIngest/admin_jobs_cancel.png and b/docs/doxygen-user/images/AutoIngest/admin_jobs_cancel.png differ diff --git a/docs/doxygen-user/images/AutoIngest/admin_jobs_ocr1.png b/docs/doxygen-user/images/AutoIngest/admin_jobs_ocr1.png new file mode 100644 index 0000000000..a0db003ca6 Binary files /dev/null and b/docs/doxygen-user/images/AutoIngest/admin_jobs_ocr1.png differ diff --git a/docs/doxygen-user/images/AutoIngest/admin_jobs_ocr2.png b/docs/doxygen-user/images/AutoIngest/admin_jobs_ocr2.png new file mode 100644 index 0000000000..85aabf1154 Binary files /dev/null and b/docs/doxygen-user/images/AutoIngest/admin_jobs_ocr2.png differ diff --git a/docs/doxygen-user/images/AutoIngest/admin_jobs_panel.png b/docs/doxygen-user/images/AutoIngest/admin_jobs_panel.png index 32dfa89cdd..25ad7b1982 100644 Binary files a/docs/doxygen-user/images/AutoIngest/admin_jobs_panel.png and b/docs/doxygen-user/images/AutoIngest/admin_jobs_panel.png differ diff --git a/docs/doxygen-user/images/AutoIngest/admin_nodes_panel.png b/docs/doxygen-user/images/AutoIngest/admin_nodes_panel.png index 08488323dd..220b5d65a4 100644 Binary files a/docs/doxygen-user/images/AutoIngest/admin_nodes_panel.png and b/docs/doxygen-user/images/AutoIngest/admin_nodes_panel.png differ diff --git a/docs/doxygen-user/images/AutoIngest/advanced_settings.png b/docs/doxygen-user/images/AutoIngest/advanced_settings.png index 8dd88696d3..f93ca9bd00 100644 Binary files a/docs/doxygen-user/images/AutoIngest/advanced_settings.png and b/docs/doxygen-user/images/AutoIngest/advanced_settings.png differ diff --git a/docs/doxygen-user/images/central_repo_ingest_settings.png b/docs/doxygen-user/images/central_repo_ingest_settings.png index dec839f689..79feba954e 100644 Binary files a/docs/doxygen-user/images/central_repo_ingest_settings.png and b/docs/doxygen-user/images/central_repo_ingest_settings.png differ diff --git a/docs/doxygen-user/images/content_viewer_results_bookmark.png b/docs/doxygen-user/images/content_viewer_results_bookmark.png index 2c0d3cb736..cbefb1df56 100644 Binary files a/docs/doxygen-user/images/content_viewer_results_bookmark.png and b/docs/doxygen-user/images/content_viewer_results_bookmark.png differ diff --git a/docs/doxygen-user/images/content_viewer_results_call.png b/docs/doxygen-user/images/content_viewer_results_call.png index 3bc104af0a..843a68cd24 100644 Binary files a/docs/doxygen-user/images/content_viewer_results_call.png and b/docs/doxygen-user/images/content_viewer_results_call.png differ diff --git a/docs/doxygen-user/images/ingest-file-filters.PNG b/docs/doxygen-user/images/ingest-file-filters.PNG index e8d0ddf926..1831789733 100644 Binary files a/docs/doxygen-user/images/ingest-file-filters.PNG and b/docs/doxygen-user/images/ingest-file-filters.PNG differ diff --git a/docs/doxygen-user/images/keyword-search-configuration-dialog-general.PNG b/docs/doxygen-user/images/keyword-search-configuration-dialog-general.PNG index 4dbb566faa..dadd9f4e71 100644 Binary files a/docs/doxygen-user/images/keyword-search-configuration-dialog-general.PNG and b/docs/doxygen-user/images/keyword-search-configuration-dialog-general.PNG differ diff --git a/docs/doxygen-user/images/keyword-search-ingest-settings.PNG b/docs/doxygen-user/images/keyword-search-ingest-settings.PNG index d7c0b8e2fc..85c6378d60 100644 Binary files a/docs/doxygen-user/images/keyword-search-ingest-settings.PNG and b/docs/doxygen-user/images/keyword-search-ingest-settings.PNG differ diff --git a/docs/doxygen-user/images/solr/solr_comment_out_updateLog.jpg b/docs/doxygen-user/images/solr/solr_comment_out_updateLog.jpg new file mode 100644 index 0000000000..90737515fa Binary files /dev/null and b/docs/doxygen-user/images/solr/solr_comment_out_updateLog.jpg differ diff --git a/docs/doxygen-user/images/solr/solr_config_autocommit.jpg b/docs/doxygen-user/images/solr/solr_config_autocommit.jpg new file mode 100644 index 0000000000..5e6cc7a9bf Binary files /dev/null and b/docs/doxygen-user/images/solr/solr_config_autocommit.jpg differ diff --git a/docs/doxygen-user/images/solr/solr_transaction_log_errors.jpg b/docs/doxygen-user/images/solr/solr_transaction_log_errors.jpg new file mode 100644 index 0000000000..4328068b57 Binary files /dev/null and b/docs/doxygen-user/images/solr/solr_transaction_log_errors.jpg differ diff --git a/docs/doxygen-user/ingest.dox b/docs/doxygen-user/ingest.dox index ae36a91019..594108ee07 100644 --- a/docs/doxygen-user/ingest.dox +++ b/docs/doxygen-user/ingest.dox @@ -50,7 +50,7 @@ The file filters panel can be opened from the ingest module selection panel or t \image html ingest-file-filters.PNG -Each filter contains one or more rules for selecting files based on a combination of file name, path, and how recently the file was modified. Only one rule needs to match for the file to pass. Additionally, you can enter multiple comma-separated file extensions. All files will still be displayed in the tree view, but the ingest modules will only run on a subset. If we use the previous example and run the hash module, only files ending in .png will have their hash computed. +Each filter contains one or more rules for selecting files based on a combination of file name, path, file size, and how recently the file was modified. Only one rule needs to match for the file to pass. Additionally, you can enter multiple comma-separated file extensions. All files will still be displayed in the tree view, but the ingest modules will only run on a subset. If we use the previous example and run the hash module, only files ending in .png will have their hash computed. \section ingest_profiles Using Ingest Profiles diff --git a/docs/doxygen-user/keyword_search.dox b/docs/doxygen-user/keyword_search.dox index 45ef1c0dfa..48142ee4a7 100644 --- a/docs/doxygen-user/keyword_search.dox +++ b/docs/doxygen-user/keyword_search.dox @@ -18,11 +18,11 @@ Refer to \ref ad_hoc_keyword_search_page for more details on specifying regular \section keyword_search_configuration_dialog Keyword Search Configuration Dialog The keyword search configuration dialog has three tabs, each with its own purpose: -\li The \ref keywordListsTab is used to add, remove, and modify keyword search lists. -\li The \ref stringExtractionTab is used to enable language scripts and extraction type. -\li The \ref generalSettingsTab is used to configure the ingest timings and display information. +\li The \ref keyword_keywordListsTab is used to add, remove, and modify keyword search lists. +\li The \ref keyword_stringExtractionTab is used to enable language scripts and extraction type. +\li The \ref keyword_generalSettingsTab is used to configure the ingest timings and display information. -## Lists tab {#keywordListsTab} +\subsection keyword_keywordListsTab Lists tab The Lists tab is used to create/import and add content to keyword lists. To create a list, select the 'New List' button and choose a name for the new Keyword List. Once the list has been created, keywords can be added to it (see \ref ad_hoc_kw_types_section for more information on keyword types). Lists can be added to the keyword search ingest process; searches will happen at regular intervals as content is added to the index. @@ -40,7 +40,7 @@ Under the Keyword list is the option to send ingest inbox messages for each hit. \image html keyword-search-inbox.PNG -## String Extraction tab {#stringExtractionTab} +\subsection keyword_stringExtractionTab String Extraction tab The string extraction setting defines how strings are extracted from files from which text cannot be extracted normally because their file formats are not supported. This is the case with arbitrary binary files (such as the page file) and chunks of unallocated space that represent deleted files. When we extract strings from binary files we need to interpret sequences of bytes as text differently, depending on the possible text encoding and script/language used. In many cases we don't know in advance what the specific encoding/language the text is encoded in. However, it helps if the investigator is looking for a specific language, because by selecting less languages the indexing performance will be improved and the number of false positives will be reduced. @@ -50,20 +50,36 @@ The default setting is to search for English strings only, encoded as either UTF The user can also use the String Viewer first and try different script/language settings, and see which settings give satisfactory results for the type of text relevant to the investigation. Then the same setting that works for the investigation can be applied to the keyword search ingest. -## General Settings tab {#generalSettingsTab} +\subsection keyword_generalSettingsTab General Settings tab \image html keyword-search-configuration-dialog-general.PNG -### NIST NSRL Support +\subsubsection keyword_nsrl NIST NSRL Support The hash lookup ingest service can be configured to use the NIST NSRL hash set of known files. The keyword search advanced configuration dialog "General" tab contains an option to skip keyword indexing and search on files that have previously marked as "known" and uninteresting files. Selecting this option can greatly reduce size of the index and improve ingest performance. In most cases, user does not need to keyword search for "known" files. -### Result update frequency during ingest +\subsubsection keyword_update_freq Result update frequency during ingest To control how frequently searches are executed during ingest, the user can adjust the timing setting available in the keyword search advanced configuration dialog "General" tab. Setting the number of minutes lower will result in more frequent index updates and searches being executed and the user will be able to see results more in real-time. However, more frequent updates can affect the overall performance, especially on lower-end systems, and can potentially lengthen the overall time needed for the ingest to complete. One can also choose to have no periodic searches. This will speed up the ingest. Users choosing this option can run their keyword searches once the entire keyword search index is complete. -### Optical Character Recognition -There is also a setting to enable Optical Character Recognition (OCR). If enabled, text may be extracted from supported image types. Enabling this feature will make the keyword search module take longer to run, and the results are not perfect. The secondary checkbox can make OCR run faster by only processing large images and images extracted from documents. +\section keyword_usage Using the Module + +Search queries can be executed manually by the user at any time, as long as there are some files already indexed and ready to be searched. Searching before indexing is complete will naturally only search indexes that are already compiled. + +See \ref ingest_page "Ingest" for more information on ingest in general. + +Once there are files in the index, \ref ad_hoc_keyword_search_page will be available for use to manually search at any time. + +\subsection keyword_ingest_settings Ingest Settings + +The Ingest Settings for the Keyword Search module allow the user to enable or disable the specific built-in search expressions, Phone Numbers, IP Addresses, Email Addresses, and URLs. Using the Advanced button (covered below), one can add custom keyword groups. + +\image html keyword-search-ingest-settings.PNG + +\subsubsection keyword_ocr Optical Character Recognition +\anchor keyword_search_ocr_config + +There is also a setting to enable Optical Character Recognition (OCR). If enabled, text may be extracted from supported image types. Enabling this feature will make the keyword search module take longer to run, and the results are not perfect. The following shows a sample image containing text: @@ -73,7 +89,12 @@ The "Indexed Text" tab shows the results when running the keyword search module \image html keyword-search-ocr-indexed-text.png -\anchor keyword_search_ocr_config +The two options to related to OCR are the following: +
      +
    • Only index text extracted from an image. This will prevent keyword search from indexing text found in text files, docs, etc. +
    • Only run on large images and documents and extracted files. With this selected, OCR will only be performed on images over 100KB and PDFs/Office docs. It will also run on images of any size that were extracted from another file. +
    + By default, OCR is only configured for English text. Its configuration depends on the presence of language files (called "traineddata" files) that exist in a location that Autopsy can understand. To add support for more languages, you will need to download additional "traineddata" and move them to the right location. The following steps breakdown this process for you: @@ -88,28 +109,8 @@ and move them to the right location. The following steps breakdown this process The language files will now be supported when OCR is enabled in the Keyword Search Settings. - -
    -Using the Module -====== -Search queries can be executed manually by the user at any time, as long as there are some files already indexed and ready to be searched. Searching before indexing is complete will naturally only search indexes that are already compiled. - -See \ref ingest_page "Ingest" for more information on ingest in general. - -Once there are files in the index, \ref ad_hoc_keyword_search_page will be available for use to manually search at any time. - - - -Ingest Settings ------- -The Ingest Settings for the Keyword Search module allow the user to enable or disable the specific built-in search expressions, Phone Numbers, IP Addresses, Email Addresses, and URLs. Using the Advanced button (covered below), one can add custom keyword groups. - -\image html keyword-search-ingest-settings.PNG - - -Seeing Results ------- +\section keyword_results Seeing Results The Keyword Search module will save the search results regardless whether the search is performed by the ingest process, or manually by the user. The saved results are available in the Directory Tree in the left hand side panel. diff --git a/docs/doxygen-user/multi-user/installSolr.dox b/docs/doxygen-user/multi-user/installSolr.dox index d8a4690d58..dd380e6eef 100644 --- a/docs/doxygen-user/multi-user/installSolr.dox +++ b/docs/doxygen-user/multi-user/installSolr.dox @@ -207,7 +207,7 @@ Solr creates two types of data that need to be backed up:
    1. In a default installation that data is stored in \c "C:\solr-8.6.3\server\solr zoo_data" (assuming that the Solr package ZIP was extracted into \c "C:\solr-8.6.3" directory).
-\section Troubleshooting +\section troubleshooting Troubleshooting / Performance Tuning \subsection install_solr_delayed_start Delayed Start Problems With Large Number Of Solr Collections @@ -287,4 +287,36 @@ Some notes: +\subsection solr_commit_tuning Tuning Solr Server Commit Operations + +When Autopsy is running in a multi-user cluster environment with multiple auto ingest nodes, it may be beneficial to tune the configuration of Solr "commit" operations. + +Solr has two types of "commits" – hard commits and soft commits. These are explained in detail the following link: https://lucidworks.com/post/understanding-transaction-logs-softcommit-and-commit-in-sorlcloud/ + +In short: +
    +
  • Hard commits flush newly indexed documents from RAM to Solr index on disk. +
  • Depending on configuration, hard commits may or may not make the newly indexed documents "visible" to search. +
  • Soft commits do not flush newly indexed documents to disk but they make the newly indexed documents "visible" to search. +
+ +By default (when using AutopsyConfig) the Solr servers are performing a "hard" commit every 5 minutes and are also making the newly indexed documents "visible" to search. These operations can be costly when performed on a large index which is located on a shared network drive. In this stuation it can be very beneficial to modify Solr configuration (located in \c "SOLR_INSTALLATION_DIECTORY\server\solr\configsets\AutopsyConfig\conf\solrconfig.xml") with the following changes: +
    +
  1. Modify "hard commits" to still flush the newly created documents every 5 minutes but not make them "visible". This is accomplished by setting “openSearcher" to "false" in the "autoCommit" section of Solr configuration file. +
  2. Enable "soft commits" to be performed every 30 minutes thus making the newly indexed documents "visible" to search every 30 minutes. This is accomplished by enabling the "autoSoftCommit" section of Solr configuration file. The downside is that it may take up to 30 minutes to be able to search the latest document. Keep in mind that this only affects the scenario where an examiner is searching a case while the ingest is still ongoing. Autopsy automatically performs a commit after the ingest is complete so all the documents are immediately visible at that time. +
+ +The following image shows the Solr configuration changes discussed above: + +\image html solr_config_autocommit.jpg + +Until a hard commit is performed, by default Solr also maintains a transaction log which contains the raw text of every newly indexed document since last hard commit. When the Solr index is located on a network share, this again can be a very costly operation. Transaction logs can be disabled by commenting out the "updateLog" section of Solr configuration file: + +\image html solr_comment_out_updateLog.jpg + +Keep in mind that this has an unfortunate side effect of creating CommitTracker errors in Solr logs and Solr admin console. These errors can be ignored if transaction log has been intentionally disabled. + +\image html solr_transaction_log_errors.jpg + + */ diff --git a/docs/doxygen-user/multi-user/installSystems.dox b/docs/doxygen-user/multi-user/installSystems.dox index a583aeee93..7c46ce926f 100644 --- a/docs/doxygen-user/multi-user/installSystems.dox +++ b/docs/doxygen-user/multi-user/installSystems.dox @@ -26,14 +26,13 @@ We recommend: \subsection multiuser_system_hw Suggested Hardware -TODO +- PostgreSQL/ActiveMQ (Server 1): + - RAM: 16GB or more + - Local Storage: 500GB SSD -- PostgreSQL/ActiveMQ (server 1): - - RAM: - - Local Storage: Enough for databases -- Solr (server 2): - - RAM: - - Local Storage: Minimal +- Solr (Server 2): + - RAM: 32GB or more + - Local Storage: A single index will be roughly the size of the data source being ingested. For example 128GB E01 will usually generate a 128 GB index. \subsection multiuser_system_back Backups diff --git a/docs/doxygen-user/result_viewer.dox b/docs/doxygen-user/result_viewer.dox index 123e11b7a6..f2cc4018b6 100644 --- a/docs/doxygen-user/result_viewer.dox +++ b/docs/doxygen-user/result_viewer.dox @@ -25,8 +25,8 @@ These columns display the following information:
  • (S)core column - indicates whether the item is interesting or notable.
      -
    • Displays a red icon if the file is a match for a notable hashset or has been tagged with a notable tag. -
    • Displays a yellow icon if the file has an interesting item match or has been tagged with a non-notable tag. +
    • Displays a red icon if at least one child analysis result is notable or the file is tagged with a notable tag. +
    • Displays a yellow icon if at least one child analysis result is likely notable or the file has a tag.
  • (C)omment column - indicates whether the item has a comment in the Central Repository or has a comment associated with a tag.
  • (O)ther occurrences column - indicates how many data sources in the Central Repository contain this item. The count will include the selected item. diff --git a/docs/doxygen-user/tree_viewer.dox b/docs/doxygen-user/tree_viewer.dox index d3d6651fce..ae03a62438 100644 --- a/docs/doxygen-user/tree_viewer.dox +++ b/docs/doxygen-user/tree_viewer.dox @@ -3,10 +3,12 @@ [TOC] -The tree on the left-hand side of the main window is where you can browse the files in the data sources in the case and find saved results from automated analyis (ingest). The tree has five main areas: +The tree on the left-hand side of the main window is where you can browse the files in the data sources in the case and find saved results from automated analyis (ingest). The tree has seven main areas: - Persons / Hosts / Data Sources: This shows the directory tree hierarchy of the data sources. You can navigate to a specific file or directory here. Each data source added to the case is represented as a distinct sub tree. If you add a data source multiple times, it shows up multiple times. -- Views: Specific types of files from the data sources are shown here, aggregated by type or other properties. Files here can come from more than one data source. -- Results: This is where you can see the results from both the automated analysis (ingest) running in the background and your search results. +- File Views: Specific types of files from the data sources are shown here, aggregated by type or other properties. Files here can come from more than one data source. +- Data Artifacts: This isone of the main places where results from running \ref ingest_page appear. +- Analysis Results: This is the other main place where results from running \ref ingest_page appear. +- OS Accounts: This is where you can see the results from both the automated analysis (ingest) running in the background and your search results. - Tags: This is where files and results that have been \ref tagging_page "tagged" are shown. - Reports: Reports that you have generated, or that ingest modules have created, show up here. @@ -43,22 +45,28 @@ Unallocated space is the chunks of a file system that are currently not being us An example of the single file extraction option is shown below. \image html extracting-unallocated-space.PNG -\section ui_tree_views Views +\section ui_tree_views File Views Views filter all the files in the case by some property of the file. - File Types Sorts files by file extension or by MIME type, and shows them in the appropriate group. For example, files with .mp3 and .wav extensions end up in the "Audio" group. - Deleted Files Displays files that have been deleted, but the names have been recovered. - File Size Sorts files based on size. +\section ui_tree_results Data Artifacts -\section ui_tree_results Results -- Extracted Content: Many ingest modules will place results here; EXIF metadata, GPS locations, or Web history for example. -- Keyword Hits: Keyword search hits show up here. -- Hashset Hits: Hashset hits show up here. -- E-Mail Messages: Email messages show up here. -- Interesting Items: Things deemed interesting show up here. -- Accounts: Credit card accounts show up here. -- Tags: Any item you tag shows up here so you can find it again easily. +This section shows the data artifacts created by running ingest. In general, data artifacts contain concrete information extracted from the data source. For example, call logs and messages from communication logs or web bookmarks extracted from a browser database. + +\section ui_tree_analysis_results Analysis Results + +This section shows the analysis results created by running ingest. In general, analysis results contain information that the user has indicated they are interested in. For example, if the user sets up a list of \ref hash_db_page "notable hashes", any hash set hits will appear here. + +\section ui_tree_os_accounts OS Accounts + +This section shows the OS accounts found in the case. See \ref host_os_accounts for an example. + +\section ui_tree_tags Tags + +Any item you tag shows up here so you can find it again easily. See \ref tagging_page for more information. \section ui_tree_reports Reports diff --git a/docs/doxygen-user_fr/Doxyfile b/docs/doxygen-user_fr/Doxyfile new file mode 100644 index 0000000000..80ef7fab53 --- /dev/null +++ b/docs/doxygen-user_fr/Doxyfile @@ -0,0 +1,2366 @@ +# Doxyfile 1.8.9.1 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all text +# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv +# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv +# for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = "Documentation utilisateur Autopsy" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = 4.19.0 + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = "Plateforme de criminalistique numérique graphique pour The Sleuth Kit et autres outils." + +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = user-docs + +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = French + +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = YES + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: +# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: +# Fortran. In the later case the parser tries to guess whether the code is fixed +# or free formatted code, this is the default for Fortran type files), VHDL. For +# instance to make doxygen treat .inc files as Fortran files (default is PHP), +# and .f files as C (default is Fortran), use: inc=Fortran f=C. +# +# Note: For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = YES + +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. If set to YES, local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO, only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO, these classes will be included in the various overviews. This option +# has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO, these declarations will be +# included in the documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO, these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES, upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. +# The default value is: system dependent. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES, the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE= NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES, the +# list will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO, doxygen will only warn about wrong or incomplete +# parameter documentation, but not about the absence of documentation. +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text " + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. +# Note: If this tag is empty the current directory is searched. + + +INPUT = . + + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank the +# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, +# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, +# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, +# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, +# *.qsf, *.as and *.js. + +FILE_PATTERNS = *.dox + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = images/ + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# function all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = YES + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see http://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = YES + +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = 4.19.0 + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = footer.html + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the style sheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to NO can help when comparing the output of multiple runs. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = YES + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: http://developer.apple.com/tools/xcode/), introduced with +# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = YES + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Doxygen + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = YES + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler (hhc.exe). If non-empty, +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the master .chm file (NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = YES + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# http://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from http://www.mathjax.org before deployment. +# The default value is: http://cdn.mathjax.org/mathjax/latest. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /
+ + + + + + +
Nombre de machinesServices
Une
  • Solr - Installez Solr sur la machine la plus puissante; plus il y a de processeurs, mieux c'est.
  • +
  • Les dossiers de sortie des cas partagés peuvent également être mis sur cette machine.
Une
  • ActiveMQ - Ce service a des exigences minimales en matière de mémoire et de disque.
  • +
  • PostgreSQL - Ce service a des exigences minimales en matière de mémoire et de disque.
Une
  • Dossier d'image partagé - Cette machine a besoin d'une grande quantité d'espace disque mais n'a pas besoin du matériel le plus rapide.
Une ou plus
  • Automated Ingest Node(s) - Ces machines n'ont pas besoin de beaucoup d'espace disque mais doivent bénéficier d'une mémoire et d'une puissance de processeur supplémentaires.
Une ou plus
  • Examiner Node(s) - Voir la page \ref installation_page pour connaître les exigences système recommandées.
+ +Solr va être un gros consommateur de ressources. Une grande augmentation des performances sera constatée si vous placez des disques SSD dans la machine exécutant Solr et que cette machine héberge également le grand lecteur réseau sur des SSD dédiés pour le stockage de la sortie des cas. Les images source peuvent être sur des disques SAS (plus lents que les SSD) avec un impact très faible sur les performances. L'idée ici est d'avoir les opérations les plus gourmandes en ressources sur le matériel le plus rapide. En utilisant cette stratégie, il existe en fait deux grands stockages réseau, un pour les images en entrée et un pour les sorties des cas. + +\section auto_ingest_setup_services Installation des services et configuration d'Autopsy +Suivez les instructions de la page \ref install_multiuser_page pour mettre en place les services nécessaires et configurer vos clients Autopsy pour les utiliser. Une fois cette opération terminée, vous devriez pouvoir \ref multiuser_page "créer et utiliser des cas multi-utilisateurs". + +\section auto_ingest_setup_ain_config Configuration des "Automated Ingest Node" + +Alors que les "Examiner Node" ne nécessitent que la configuration des cas multi-utilisateurs, les "Automated Ingest Node" nécessitent une configuration supplémentaire. Pour commencer, allez dans l'onglet "Auto Ingest" du menu Options et sélectionnez le bouton radio "Auto Ingest mode". Si vous n'avez pas enregistré vos paramètres multi-utilisateurs, un message d'avertissement s'affichera ici - si vous le voyez, revenez à l'onglet "Multi-User" et assurez-vous d'avoir saisi tous les champs obligatoires, puis cliquez sur le bouton "Apply". + +\image html AutoIngest/auto_ingest_mode_setup.png + +\subsection auto_ingest_config_folders Configuration des dossiers + +La première chose à faire est de définir deux emplacements de dossiers. Le dossier des images partagées est le dossier de base de toutes les données qui seront acquises via les "Automated Ingest Nodes". Le dossier des cas partagés est le dossier de base des cas qui seront créés par les "Automated Ingest Nodes". + +\subsection auto_ingest_config_ingest_settings Bouton "Ingest Module Settings" +Le bouton "Ingest Module Settings" est utilisé pour configurer les \ref ingest_page que vous souhaitez exécuter pendant l'acquisition automatisée. Notez bien que pour les "Automated Ingest Node", nous vous recommandons de configurer le module de recherche par mot-clé pour qu'il n'effectue pas de recherches périodiques. Lorsqu'un utilisateur gère l'analyse devant son ordinateur, cette fonctionnalité existe afin de fournir des mises à jour fréquentes, mais elle n'est pas nécessaire sur ces nœuds. Pour configurer cela, choisissez la rubrique "Keyword Search" dans la fenêtre Options. Sélectionnez l'onglet "General" et choisissez l'option "No periodic searches". + +\image html AutoIngest/no_periodic_searches.png + +\subsection auto_ingest_advanced_settings Bouton "Advanced Settings" + +Le bouton "Advanced Settings" affichera les paramètres des tâches d'acquisition automatisées. Comme indiqué dans l'avertissement, il faut faire preuve de prudence lors de la modification de ce panneau. + +\image html AutoIngest/advanced_settings.png + +La section "Automated Ingest Pause Setting" vous permet de configurer une période hebdomadaire durant laquelle l'acquisition ne s'exécutera pas. Ceci est utile si l'un de vos services réseau est programmé avec des temps d'arrêt réguliers. Notez que l'acquisition n'est pas immédiatement arrêtée à l'heure spécifiée à "Start Time" - elle s'exécutera jusqu'à ce que le fichier actuel soit traité ou que le module d'acquisition actuel soit terminé. Pour cette raison, nous vous suggérons d'utiliser un délai de deux heures avant que votre système ne soit arrêté. Par exemple, si votre réseau n'est pas accessible tous les dimanches de 16h00 à 17h00, vous devez définir l'heure de début ("Start Time") à 14h00 et la durée ("Duration") à 3 heures (pour couvrir le délai de fin d'exécution du module et le temps d'arrêt). + +La section "Automated Ingest Job Settings" contient les options suivantes: +
+
System synchronization wait time
+
Un temps d'attente utilisé par les "Automated Ingest Node" pour assurer une synchronisation correcte des opérations des nœuds dans des circonstances où des retards peuvent survenir, comme par exemple une attente pour compenser les effets de latence du système de fichiers réseau sur la visibilité des répertoires et fichiers partagés nouvellement créés.
+
External processes time out
+
Les composants d'Autopsy qui génèrent des processus potentiellement longs ont la possibilité d'utiliser ce paramètre, s'il est activé, pour mettre fin à ces processus si le délai d'expiration spécifié s'est écoulé. Chaque composant qui utilise cette fonctionnalité est responsable de la mise en œuvre de sa propre stratégie pour le traitement des processus incomplets, lorsqu'un délai de processus externe se produit. Les composants de base qui utilisent des délais d'expiration de processus externes incluent les modules d'acquisition \ref recent_activity_page et \ref photorec_carver_page.
+
Interval between input scans
+
Intervalle entre les analyses des répertoires d'entrée d'acquisition automatisée pour les fichiers Manifest. Notez que la synchronisation réelle des analyses d'entrée par chaque nœud dépend à la fois de ce paramètre et de l'heure de démarrage du nœud.
+
Maximum job retries allowed
+
Nombre maximum de fois qu'une tâche d'acquisition automatisée en panne sera automatiquement relancée. Aucune distinction n'est faite entre les tâches qui se bloquent en raison de conditions d'erreur système telles que les pannes de courant et les tâches qui se bloquent en raison de la corruption de la source de données d'entrée. En général, la corruption de la source de données d'entrée peut être gérée correctement par Autopsy, mais ce paramètre offre une assurance contre les problèmes imprévus de viabilité des données d'entrée.
+
Target concurrent jobs per case
+
Une limite souple sur le nombre de tâches simultanées par cas lorsque plusieurs cas sont traités simultanément par un groupe de "Automated Ingest Node". Ce paramètre spécifie une cible plutôt qu'une limite stricte, car les nœuds ne sont jamais inactifs s'il y a des tâches d'acquisition à effectuer et les nœuds fonctionnent en coopération plutôt qu'en s'appuyant sur un service de planification de tâches centralisé à équilibrage de charge.
+
Number of threads to use for file ingest
+
Nombre de threads qu'un "Automated Ingest Node" consacre à l'analyse des fichiers à partir de sources de données parallèle. Notez que l'analyse des fichiers de source de données est toujours mono-thread.
+
+ +\subsection auto_ingest_file_export Bouton "File Export Settings" + +Le bouton "File Export Settings" fera apparaître la fenêtre de paramètrages \ref file_export_page. Cela permet à certains types de fichiers d'être automatiquement exportés lors de l'acquisition automatisée. La configuration de cette fonction nécessite une connaissance des structures de données internes d'Autopsy et peut être ignorée pour les utilisateurs. + +\subsection auto_ingest_shared_config Configuration partagée + +Lors de l'utilisation de plusieurs "Automated Ingest Node", la configuration peut être centralisée et partagée avec n'importe quel "Automated Ingest Node" qui souhaite l'utiliser. C'est ce qu'on appelle la configuration partagée. L'idée générale est que vous alliez configurer un nœud (le "maître") et télécharger cette configuration vers un emplacement central. Ensuite, les autres "Automated Ingest Node" (les nœuds "secondaires") téléchargeront cette configuration chaque fois qu'ils démarreront un nouveau travail. Cela permet de gagner du temps car vous n'avez besoin de configurer qu'un seul nœud et garantit la cohérence entre les "Automated Ingest Node". + +\subsubsection auto_ingest_shared_config_master Nœud maître + +Sur l'ordinateur qui sera le "Automated Ingest Node" configuré comme maître, suivez les étapes de configuration décrites ci-dessus pour configurer le nœud. +Si vous souhaitez que chaque "Automated Ingest Node" partagent les paramètres de configuration, cochez la première case dans la section "Shared Configuration" du panneau des options "Auto Ingest". Sélectionnez ensuite un dossier dans lequel stocker la configuration partagée. Ce dossier doit être un chemin vers un partage réseau auquel les autres machines du système auront accès. Utilisez un chemin UNC si possible. Ensuite, cochez la case "Use this node as a master node that can upload settings" qui devrait activer le bouton "Save & Upload Config". Si cela ne se produit pas, recherchez un message d'erreur rouge expliquant les paramètres manquants. + +\image html AutoIngest/master_node.png + +Après avoir enregistré et téléchargé la configuration, cliquez sur le bouton "Save" pour quitter le panneau Options. + +\subsubsection auto_ingest_shared_config_secondary Nœud secondaire + +Une fois qu'un nœud a téléchargé les données de configuration partagées, les nœuds restants peuvent être configurés pour les télécharger, en ignorant certaines des étapes de configuration ci-dessus. + +Pour configurer un nœud secondaire, commencez par parcourir la page \ref install_multiuser_page "configuration multi-utilisateurs." Appliquez les modifications, puis passez à l'onglet "Auto Ingest" du panneau Options. Cochez la case pour activer l'acquisition automatique ("Auto Ingest mode"), puis la case pour activer la configuration partagée ("Use shared configuration in folder") et entrez le même dossier que celui utilisé sur le nœud maître. Le bouton "Download Config" devrait maintenant être activé et peut être utilisé pour obtenir le reste de la configuration automatiquement. Ensuite, une boîte de dialogue apparaîtra probablement vous demandant de redémarrer Autopsy. + +\subsubsection auto_ingest_shared_config_notes Remarques + +Quelques remarques sur la configuration partagée: +
  • La \ref auto_ingest_error_suppression "modification de la base de regsitre pour la suppression des erreurs", vue ci-dessous, devra être faite sur chaque nœud +
  • Après la configuration initiale, les données de configuration partagées actuelles seront mises à jour avant chaque tâches (pas besoin de les télécharger à nouveau manuellement) +
  • Quelques options nécessitent un redémarrage pour prendre effet (par exemple, la plupart des paramètres multi-utilisateurs). Si celles-ci sont téléchargées automatiquement pendant l'exécution de l'acquisition automatique, elles ne seront pas utilisées tant que le "Automated Ingest Node" n'aura pas été redémarré. +
  • Il existe actuellement une limitation sur l'emplacement où les bases de données de hachage peuvent être enregistrées. Chaque base de données sera téléchargée dans le même dossier que celui dans lequel elle se trouvait sur le nœud maître, ce qui entraînera des erreurs si la lettre de ce lecteur n'est pas présente ou si le dossier n'a pas des droits d'écriture pour chaque nœud. +
  • Les copies partagées des bases de données de hachage ne sont pas non plus prises en charge actuellement. Chaque nœud téléchargera sa propre copie de chaque base de données. +
+ +\subsection auto_ingest_test_button Test + +Une fois que tout est configuré, vous pouvez utiliser le bouton "Test" en bas du panneau pour tester si tout est correctement configuré. Le bouton testera si les services sont disponibles, si un cas peut être créé et si les paramètres d'acquisition sont valides. Si le test réussit, vous verrez une coche verte. En cas d'échec, vous verrez un message donnant une brève description de l'erreur qui s'est produite. En fonction de l'erreur, vous pouvez également voir un message contextuel. Vous pouvez consulter les journaux pour obtenir des informations supplémentaires (fermez le panneau Options et cliquez sur "Help" puis "Open Log Folder"). + +\image html AutoIngest/test_button_failure.png + +\subsection auto_ingest_error_suppression Suppression d'erreurs + +Sur un "Automated Ingest Node", nous vous recommandons également fortement de configurer le système pour supprimer les boîtes de dialogue d'erreur que Windows peut afficher si une application se bloque. Certains des modules exécutés par Autopsy se sont bloqués sur certains tests effectués dans le passé et lorsqu'une une boîte de dialogue d'erreur s'affichait, tout le traitement s'arrêtait. + +La désactivation des messages d'erreur est effectuée en définissant la clé de registre suivante sur "1", comme illustré dans la capture d'écran ci-dessous. +\verbatim HKCU\Software\Microsoft\Windows\Windows Error Reporting\DontShowUI\endverbatim + +\image html AutoIngest/error_suppression.png + + +*/ \ No newline at end of file diff --git a/docs/doxygen-user_fr/case_management.dox b/docs/doxygen-user_fr/case_management.dox new file mode 100644 index 0000000000..7ce74dcc6a --- /dev/null +++ b/docs/doxygen-user_fr/case_management.dox @@ -0,0 +1,56 @@ +/*! \page cases_page Cases (Cas) + +[TOC] + + +Vous devez créer un cas avant de pouvoir analyser les données dans Autopsy. Un cas peut contenir une ou plusieurs sources de données (images de disque, disque physique, fichiers logiques). Les sources de données peuvent provenir de plusieurs lecteurs sur un seul ordinateur ou de plusieurs ordinateurs. C'est vous qui voyez. + +Chaque cas a son propre répertoire qui est nommé en fonction du nom du cas. Le répertoire contiendra des fichiers de configuration, une base de données, des rapports et d'autres fichiers générés par les modules. Le fichier de configuration principal du cas d'Autopsy a une extension ".aut". + +\section case_create Créer un cas + +\image html splashscreen.PNG + +Il existe plusieurs façons de créer un nouveau cas: +- L'écran d'ouverture a un bouton pour créer un nouveau cas ("New Case"). +- Le menu "Case", "Create New Case" + +La boîte de dialogue de l'assistant de création d'un nouveau cas s'ouvrira et vous devrez entrer le nom du cas ("Case Name") et le répertoire de base ("Base Directory"). Un répertoire pour le cas sera créé à l'intérieur du répertoire de base. Si le répertoire existe déjà, vous devrez soit supprimer le répertoire existant, soit choisir une autre combinaison de noms. + +\image html case-newcase.PNG + +REMARQUE: Vous n'aurez la possibilité de créer un cas multi-utilisateur que si vous avez configuré Autopsy avec des paramètres multi-utilisateurs. Voir \ref install_multiuser_page pour les instructions d'installation et \ref creating_multi_user_cases pour plus de détails sur la création de cas multi-utilisateurs. + +Vous serez également invité à fournir des informations facultatives ("Optional Information") comme indiqué ci-dessous: + +\image html new_case_optional_info.png + +Tous les champs de ce panneau sont facultatifs. De plus, la section "Organization" ne sera active que si le \ref central_repo_page "référentiel central" est activé. + +Après avoir créé le cas, vous serez invité à ajouter une source de données, comme décrit dans \ref ds_add. + +\section case_open Ouvrir un cas + +Pour ouvrir un cas, vous pourrez au choix: +- Choisir "Open Case" ou "Open Recent Case" dans l'écran d'ouverture. +- Choisir le menu "Case", "Open Case" ou "Case", "Open Recent Case" + +"Open Recent Case" affichera toujours un écran vous permettant de sélectionner l'un des cas récemment ouverts. "Open Case" fera une de ces deux choses: +- Si les cas multi-utilisateurs ne sont pas activés, il affichera une fenêtre de recherche de fichier pour chercher le fichier ".aut" dans le répertoire du cas souhaité +- Si les cas multi-utilisateurs sont activés, il affichera l'écran de sélection des cas multi-utilisateurs. Il utilise les services de coordination pour trouver la liste des cas multi-utilisateurs. Si nécessaire, le bouton "Open Single-User Case" peut être utilisé pour afficher la fenêtre classique de recherche de fichier. L'écran de sélection des cas multi-utilisateurs a une fonctionnalité \ref ui_quick_search qui peut être utilisée pour trouver rapidement un cas dans le tableau. Ce qui suit montre l'écran de sélection des cas multi-utilisateurs: + +\image html multi_user_case_select.png + +\section case_properties Affichage des détails du cas et du récapitulatif de la source de données +Vous pouvez afficher les propriétés du cas en accédant au menu "Case" et en cliquant sur "Case Details". + +\image html case_properties.png + +La plupart des propriétés des cas peuvent être modifiées via le bouton "Edit Details". + +Vous pouvez afficher le résumé de la source de données en accédant au menu "Case" et en cliquant sur "Data Source Summary" ou en sélectionnant la source de données dans l'\ref tree_viewer_page puis l'onglet "Summary". Plus d'informations peuvent être trouvées sur la page \ref data_source_summary_page. + +\image html ds_summary_window.png + + +*/ diff --git a/docs/doxygen-user_fr/central_repo.dox b/docs/doxygen-user_fr/central_repo.dox new file mode 100644 index 0000000000..3c4d1476b1 --- /dev/null +++ b/docs/doxygen-user_fr/central_repo.dox @@ -0,0 +1,231 @@ +/*! \page central_repo_page Référentiel central + +[TOC] + + +\section cr_overview Aperçu + +Le référentiel central permet à un utilisateur de retrouver des artefacts correspondants à la fois entre les cas et entre les sources de données dans le même cas. +Il s'agit d'une combinaison de module d'acquisition qui extrait, stocke et compare les propriétés à des listes de +propriétés notables, une base de données qui stocke ces propriétés et un panneau supplémentaire dans Autopsy pour afficher d'autres instances de chaque +propriété. La base de données du référentiel central peut être SQLite ou PostgreSQL. + +Voici quelques cas d'utilisation du référentiel central: +- Recherche d'autres instances d'une propriété + - Si vous accédez à un fichier ou à un artefact d’Autopsy (tel qu’un élément de "Web History"), une visionneuse de contenu en bas à droite vous montrera d’autres instances de cette propriété dans les données stockées dans le référentiel central. +- Alerte lorsque des propriétés précédemment caractérisées comme notables se produisent + - Vous pouvez utiliser le référentiel central pour enregistrer les propriétés associées aux fichiers et aux artefacts qui étaient des preuves (ou "notables"). Une fois que ces propriétés ont été marquées comme notables, elles seront ajoutées à la section "Interesting Items" de l'arborescence lorsqu'elles seront retrouvées dans de futurs cas. +- Stockage des ensembles de hachage + - Vous pouvez créer et importer des ensembles de hachage dans le référentiel central au lieu d'utiliser des copies locales pour le module \ref hash_db_page "Hash Lookup". Ces ensembles de hachage sont fonctionnellement équivalents aux ensembles de hachage locaux mais peuvent être partagés entre plusieurs analystes (lors de l'utilisation d'un référentiel central PostgreSQL). + +\section cr_terms Termes et concepts + +- Référentiel central (Central Repository) - La fonction d’Autopsy contenant la base de données du référentiel central et le module d’acquisition "Central Repository". Également responsable de l'affichage des propriétés corrélées pour l'utilisateur +- Base de données du référentiel central (Central Repository Database) - La base de données SQLite ou PostgreSQL qui contient toutes les données +- Module d'acquisition "Central Repository" - Module d'acquisition chargé d'ajouter de nouvelles propriétés à la base de données et de comparer ces propriétés aux propriétés notables existantes +- Propriété (Property) - Les données sont stockées/corrélées. Il peut s'agir de chemins de fichiers/hachages MD5, adresses e-mail, numéros de téléphone, etc... + +\section cr_setup Installer + +Les paramètres du référentiel central se trouvent dans le panneau d'options principal (Tools->Options) dans l'onglet "Central Repository". + +\image html central_repo_options.png + +\subsection cr_db_setup Database Configuration (Configuration de la base de données) + +Il existe deux types de bases de données de référentiel central: +- SQLite - Ce type de base de données est stocké dans un fichier. Il ne doit être utilisé que lorsqu'un seul client accède à la base de données. Vous ne pouvez pas utiliser cette option avec des \ref multiuser_page "cas multi-utilisateurs". +- PostgreSQL - Ce type de base de données est stocké sur un serveur s'exécutant soit sur l'hôte de l'utilisateur, soit sur un serveur distant. Cette option doit être utilisée si plusieurs utilisateurs utiliseront la même base de données. + +\subsubsection cr_db_setup_auto Configuration automatique de la base de données + +À partir de la version 4.15 d'Autopsy, lorsque vous chargez le logiciel et que le référentiel central n'est pas activé, il vous sera demandé si vous souhaitez l'activer. Cela créera une base de données SQLite dans votre dossier utilisateur Autopsy (sous Windows, ce sera dans AppData). Vous ne serez invité à le faire qu'une seule fois. Quelle que soit l'option que vous sélectionnez, vous pouvez modifier les paramètres de votre référentiel central ultérieurement, comme décrit ci-dessous. + +Puisqu'une base de données SQLite ne peut pas être utilisée pour des cas multi-utilisateurs, vous avez également la possibilité de basculer vers une base de données PostgreSQL lorsque vous \ref multiuser_install_clients "activez les cas multi-utilisateurs". Si vous utilisez actuellement une base de données SQLite, lorsque vous activez des cas multi-utilisateurs, il vous sera demandé si vous souhaitez basculer vers une base de données PostgreSQL sur le même serveur. Notez que le contenu de votre base de données SQLite ne sera pas copié. + +\subsubsection cr_db_setup_manual Configuration manuelle de la base de données + +Dans le panneau d'options du référentiel central, cochez l'option "Use a Central Repository" puis cliquez sur le bouton "Configure" pour créer une base de données. Il y a trois options ici: +- SQLite - Cette option stocke la base de données dans un fichier. Il ne doit être utilisé que lorsqu'un seul client accède à la base de données. +- PostgreSQL using multi-user settings - Cette option utilise un référentiel central sur le même serveur PostgreSQL qui a été configuré pour \ref multiuser_page "les cas multi-utilisateurs". Cette option ne peut pas être sélectionnée si les cas multi-utilisateurs ne sont pas activés. C'est l'une des options à sélectionner si plusieurs utilisateurs utilisent la même base de données. +- Custom PostgreSQL - Cette option utilise un serveur de base de données s'exécutant sur l'hôte de l'utilisateur ou sur un serveur distant, où le serveur est spécifié dans les paramètres du référentiel central. C'est l'une des options à sélectionner si plusieurs utilisateurs utilisent la même base de données. + +Une fois la base de données configurée, les deux boutons inférieurs du panneau principal seront activés, ce qui sera décrit ci-dessous. + +Configuration d'un déploiement PostgreSQL à l'aide des paramètres multi-utilisateurs + +Voir la page \ref install_multiuser_page pour obtenir des instructions sur la configuration d'un environnement multi-utilisateur. Une fois cela fait, vous pouvez sélectionner l'option "PostgreSQL using multi-user settings" pour créer/utiliser un référentiel central sur ce serveur PostgreSQL. + +Configurer un déploiement PostgreSQL personnalisé + +Si nécessaire, consultez la page \ref install_postgresql_page pour obtenir de l'aide sur la configuration de votre serveur PostgreSQL. + +Pour PostgreSQL, toutes les valeurs sont requises, mais certaines valeurs par défaut sont fournies pour plus de commodité. + +\image html central_repo_postgres.png + +- Host Name/IP : c'est le nom d'hôte ou l'adresse IP de votre serveur PostgreSQL. +- Port : c'est le port sur lequel le serveur PostgreSQL écoute; la valeur par défaut est 5432. +- User Name : c'est un utilisateur PostgreSQL qui peut créer et modifier des bases de données +- User Password : c'est le mot de passe de l'utilisateur. + +Si la base de données n'existe pas, vous serez invité à la créer. + + +Configuration du déploiement de SQLite + +Sélectionnez SQLite dans le type de base de données pour configurer une base de données SQLite. Les bases de données SQLite ne doivent pas être utilisées si plusieurs clients accèdent au référentiel central. + +\image html central_repo_sqlite.png + +Entrez ou recherchez un dossier pour la base de données. Si le fichier de base de données n'existe pas dans ce dossier, vous serez invité à le créer. + +\subsection cr_manage_properties Manage Correlation Properties (Gérer les propriétés de corrélation) + +Le module d'acquisition "Central Repository" peut enregistrer différents types de propriétés dans la base de données. Par défaut, toutes les propriétés sont enregistrées, mais +ce paramètre peut être modifié dans le panneau d'options via le bouton "Manage Correlation Properties". Notez que ces paramètres +sont enregistrés dans la base de données, donc dans un paramètrage multi-utilisateur, toute modification affectera tous les utilisateurs. + +\image html central_repo_types.png + +Descriptions des types de propriétés: +- Files + - Les fichiers sont corrélés en fonction du hachage MD5 et du chemin et du nom du fichier. Le module \ref hash_db_page doit être activé. +- Domains + - Les domaines sont extraits des différents artefacts Web, qui proviennent principalement du module \ref recent_activity_page. +- Email Addresses + - Les adresses e-mail sont créées par des modules tels que \ref email_parser_page. +- Phone Numbers + - Les numéros de téléphone ne sont actuellement extraits que des journaux d'appels, des listes de contacts et des messages, qui proviennent du module \ref android_analyzer_page. +- USB Devices + - Les propriétés du périphérique USB proviennent de l'analyse de la base de registre dans le module \ref recent_activity_page. +- Wireless Networks + - Les réseaux sans fil sont corrélés sur les SSID et proviennent de l'analyse de la base de registre dans le module \ref recent_activity_page. +- MAC Addresses + - Les propriétés d'adresses MAC ne sont actuellement créées que par des modules Autopsy personnalisés. +- IMEI Number + - Les propriétés d'IMEI ne sont actuellement créées que par des modules Autopsy personnalisés. +- IMSI Number + - Les propriétés d'IMSI ne sont actuellement créées que par des modules Autopsy personnalisés. +- ICCID Number + - Les propriétés d'ICCID ne sont actuellement créées que par des modules Autopsy personnalisés. +- Credit Card + - Les propriétés de carte de crédit sont créées par le module \ref keyword_search_page. +- App-specific Accounts (Facebook, Twitter, etc...) + - Ces propriétés proviennent principalement du module \ref android_analyzer_page. + +\subsection cr_manage_orgs Manage Organizations (Gérer les organisations) + +Les organisations sont stockées dans le référentiel central et contiennent les informations de contact pour l'organisation donnée. Les organisations sont utilisées pour les jeux de hachage enregistrés dans le référentiel central et peuvent également être associées à des cas d'Autopsy. + +\image html central_repo_orgs.png + +Une organisation par défaut, "Not Specified" sera toujours présente dans la liste. De nouvelles organisations peuvent être créées, modifiées et supprimées via les boutons appropriés. Notez que toute organisation actuellement utilisée par un cas ou un jeu de hachage ne peut pas être supprimée. Tous les champs à l'exception du nom de l'organisation sont facultatifs. + +\image html central_repo_new_org.png + +\subsection cr_show_cases Manage Cases (Gérer les cas) + +Affiche une liste de tous les cas qui se trouvent dans la base de données du référentiel central et des détails sur chaque cas. + +\image html central_repo_details.png + +\section cr_using_repo Utilisation du référentiel central + +\subsection cr_ingest_module Le module "Central Repository" + +Le module d'acquisition "Central Repository" est chargé d'ajouter des propriétés à la base de données et de comparer chaque propriété +à la liste des propriétés notables. Il est préférable d'exécuter tous les modules d'acquisition pour tirer le meilleur parti du moteur de corrélation. Par exemple, si "Hash Lookup" n'est pas exécuté, le module "Central Repository" ne mettra aucun fichier dans la +base de données. Si le module "Central Repository" n'est pas exécuté sur un cas particulier mais qu'un référentiel central est activé, +il y aura toujours des fonctionnalités limitées. La visionneuse de contenu affichera toujours les propriétés correspondantes dans +les autres cas/sources de données où le module "Central Repository" a été exécuté. + +\image html central_repo_ingest_settings.png + +Il existe trois paramètres pour le module d'acquisition "Central Repository": +
    +
  • Save items to the Central Repository - Cette option ne doit être désélectionnée que dans les rares cas où vous ne souhaitez pas ajouter de propriétés de la source de données actuelle au référentiel central, mais souhaitez quand même signaler les occurrences passées. +
  • Flag items previously tagged as notable - L'activation de cette option entraîne la création d'artefacts d'éléments/fichiers intéressants lorsque des propriétés correspondant à celles précédemment marquées sont trouvées. Voir la section suivante \ref cr_tagging pour plus de détails. +
  • Flag previously seen devices - Lorsque cette option est activée, un artefact "Interesting Item" sera créé si une propriété liée au périphérique (USB, adresse MAC, IMSI, IMEI, ICCID) est détectée et se trouve déjà dans le référentiel central, qu'elle ait été ou non signalée. +
  • + +\subsection cr_tagging Marquage de fichiers et d'artefacts + +Marquer un fichier ou un artefact avec une balise "notable" changera également sa propriété associée dans le référentiel central en notable. +Par défaut, il y aura une balise nommée "Notable Item" qui pourra être utilisée à cette fin. Voir la page sur les \ref tagging_page "marquages" pour plus d'informations sur la création de balises supplémentaires avec un statut notable. +Toute future acquisition de source de données (où ce module est activé) +utilisera ces propriétés "notables" de la même manière qu'un ensemble de hachage "connus défavorablement", provoquant l'ajout des fichiers et artefacts correspondants de cette acquisition à la liste "Interesting Items" du cas actuellement ouvert. + +\image html central_repo_tag_file.png + +Si une balise est accidentellement ajoutée à un fichier ou à un artefact, elle peut être supprimée via le menu contextuel. Cela supprimera sa propriété de statut notable dans le référentiel central. + +Si vous souhaitez empêcher la création de "Interesting Items" dans un cas particulier, vous pouvez désactiver le marquage +via les propriétés d'acquisition au moment de l'exécution. Notez que cela désactive uniquement les résultats de "Interesting Item" - toutes les propriétés sont toujours ajoutés au référentiel central. + +\image html central_repo_ingest_settings.png + +\section cr_viewing_results Affichage des résultats + +Les résultats de l'activation d'un référentiel central et de l'exécution du module d'acquisition "Central Repository" peuvent être consultés à deux endroits: +- La visionneuse de contenu, pour chaque fichier ou artefact, affichera toutes les propriétés correspondantes dans d'autres cas/sources de données +- Le nœud "Interesting Files" de l'arborescence contiendra tous les fichiers ou résultats correspondant aux propriétés précédemment marquées comme notables + +\subsection cr_content_viewer Visionneuse de contenu + +La \ref content_viewer_page est l'endroit où les instances précédentes des propriétés sont affichées. Sans un référentiel central activé, +le panneau "Other Occurrences" affichera les fichiers avec des hachages correspondant au fichier sélectionné dans le cas actuel. Activer un référentiel central permet à ce panneau d'afficher également les propriétés correspondantes stockées dans la base de données et ajoute des fonctionnalités à la ligne. +Notez que le module d'acquisition "Central Repository" n'a pas besoin d'avoir été exécuté sur la source de données actuelle pour voir les +propriétés du référentiel central. Si le fichier ou l'artefact sélectionné est associé, par l'un des types de corrélation pris en charge, +à une ou plusieurs propriétés de la base de données, les propriétés associées seront affichées. Remarque: La visionneuse de contenu affichera TOUTES les propriétés associées disponibles dans la base de données. Elle ignore les propriétés de corrélation activées/désactivées de l'utilisateur. + +Les autres occurrences sont regroupées par cas, puis par source de données. La sélection de l'un des résultats fait apparaître des informations à ce sujet dans la colonne de droite. Si un fichier ou un artefact était précédemment marqué comme notable, vous verrez "notable" en rouge à côté de "Known Status". + +\image html central_repo_content_viewer.png + +L'utilisateur peut cliquer sur n'importe quel en-tête de colonne pour trier les valeurs de cette colonne. + +Si l'utilisateur sélectionne une entrée dans la troisième colonne puis clique avec le bouton droit de la souris, un menu s'affiche. +Ce menu a plusieurs options. +-# Export All Other Occurrences to CSV +-# Show Case Details +-# Show Frequency + +Export All Other Occurrences to CSV (Exporter toutes les autres occurrences au format CSV) + +Cette option enregistre toutes les autres occurrences du tableau de la visionneuse de contenu dans un fichier CSV. +Par défaut, le fichier CSV est enregistré dans le répertoire d'export à l'intérieur du cas d'Autopsy actuellement ouvert, +mais l'utilisateur est libre de sélectionner un emplacement différent. + +Show Case Details (Afficher les détails du cas) + +Cette option ouvrira une boîte de dialogue qui affiche tous les détails pertinents pour le cas sélectionné. Ces détails comprendront: +- Case UUID (Identifiant du cas) +- Case Name (Nom du cas) +- Case Creation Date (Date de création du cas) +- Case Examiner contact information (Informations de contact de l'analyste du cas) +- Case Examiner's notes (Notes de l'analyste du cas) + +Ces détails auront été saisis par l'analyste du cas sélectionné, lors de la création du cas ou plus tard en allant dans le menu Case->Case Properties. + +Show Frequency (Afficher la fréquence) + +Cela montre à quel point le fichier sélectionné est commun. La valeur est le pourcentage de tuples de cas/source de données qui ont la propriété sélectionnée. + +\subsection cr_interesting_items Interesting Items (Éléments intéressants) + +Dans la section "Results" de l'arborescence d'un cas ouvert se trouve une entrée intitulée "Interesting Items". Lorsque ce module est activé, tous les propriétés corrélables entraîneront l'ajout de fichiers et d'artefacts correspondants à cette zone "Interesting Items" de l'arborescence, lors de l'acquisition. + +\image html central_repo_interesting_items.png + +Par exemple, supposons que la propriété "Files Correlatable" est activée et que l'acquisition traite actuellement un fichier "badfile.exe" dont le hachage MD5 existe déjà dans la base de données en tant que propriété de fichier notable. Dans ce cas, une entrée dans l'arborescence "Interesting Items" sera ajoutée pour +l'instance actuelle de "badfile.exe" dans la source de données en cours d'acquisition. + +Le même type de chose se produira pour chaque propriété corrélable activée. + +Dans le cas du type de numéro de téléphone corrélable, l'arborescence "Interesting Items" affichera une sous-arborescence pour chaque numéro de téléphone. Le sous-arbre contiendra alors chaque instance de ce numéro de téléphone notable. + + + + +*/ diff --git a/docs/doxygen-user_fr/command_line_ingest.dox b/docs/doxygen-user_fr/command_line_ingest.dox new file mode 100644 index 0000000000..a94f240534 --- /dev/null +++ b/docs/doxygen-user_fr/command_line_ingest.dox @@ -0,0 +1,208 @@ +/*! \page command_line_ingest_page Command Line Ingest (Acquisition en ligne de commande) + +[TOC] + + +\section command_line_ingest_overview Aperçu + +La fonction "Command Line Ingest" vous permet d'exécuter de nombreuses fonctions d'Autopsy à partir de la ligne de commande. Vous pouvez ajouter des sources de données aux cas, choisir les modules d'acquisition à exécuter et générer automatiquement un rapport. Une fois terminés, ces cas peuvent être ouverts normalement ou vous pouvez simplement utiliser les rapports et autres sorties sans ouvrir Autopsy. + +\section command_line_ingest_config Configuration + +Pour configurer l'acquisition en ligne de commande, accédez à Tools->Options puis sélectionnez l'onglet "Command Line Ingest". Si vous souhaitez créer ou ouvrir des cas multi-utilisateurs, vous devrez \ref install_multiuser_page "configurer les paramètres multi-utilisateurs". + +\image html command_line_ingest_options.png + +\subsection command_line_ingest_profile Configuration des profils d'acquisition + +À partir du panneau d'options, vous pouvez configurer le profil d'acquisition par défaut. C'est la même chose que pour la configuration normale des \ref ingest_page "modules d'acquisition" - choisissez un filtre de fichier, puis activez ou désactivez les modules d'acquisition individuels, en modifiant leurs paramètres si vous le souhaitez. Appuyez sur "OK" pour enregistrer vos paramètres. + +Actuellement, les profils d'acquisition personnalisés ne peuvent pas être configurés dans le panneau d'options de l'acquisition en ligne de commande, mais ils peuvent être créés via le \ref ingest_page "panneau d'option Ingest" puis utilisés avec la ligne de commande. Ici, nous avons créé un profil d'acquisition qui ne traitera que les types de fichiers image et n'exécutera que certains modules d'acquisition. + +\image html command_line_ingest_profile.png + +Voir la section sur \ref command_line_ds "l'exécution des modules d'acquisition" ci-dessous pour obtenir des instructions sur la spécification d'un profil d'acquisition avec la ligne de commande. + +\subsection command_line_report_profile Configuration des profils de rapport + +Vous pouvez configurer des profils de rapport à utiliser avec l'acquisition en ligne de commande. Vous commencerez avec un profil "default" et pourrez créer des profils supplémentaires. Chaque profil vous permettra de générer un type de rapport. La configuration est généralement la même que la \ref reporting_page "génération de rapports" normale avec quelques légères différences. Cela se voit principalement lorsque vos options dépendent du cas ouvert, comme le choix des \ref tagging_page "marquages" à intégrer au rapport ou les définitions des noms de \ref interesting_files_identifier_page "fichiers intéressants" à inclure. Par exemple, le rapport HTML vous permet normalement de choisir des balises spécifiques à inclure, mais pour l'acquisition en ligne de commande, il n'y aura que la possibilité d'inclure toutes les balises. + +Si vous souhaitez créer des profils de rapport supplémentaires, sélectionnez "Make new profile" dans le menu déroulant puis cliquez sur le bouton "Configure". Vous serez invité à nommer votre nouveau profil de rapport, puis vous passerez par la configuration de rapport normale. Avoir plusieurs profils de rapport vous permettra de générer facilement différents types de rapport à partir de la ligne de commande. Par exemple, vous pouvez avoir un profil de rapport "htmlReport" qui cré les rapports HTML et un autre profil de rapport pour générer des rapports KML. Voir la section \ref command_line_report "génération de rapports" ci-dessous pour savoir comment spécifier un profil de rapport en ligne de commande. + +\section command_line_ingest_commands Options de commande + +Dans une invite de commande, accédez au dossier "bin" d'Autopsy. Celui-ci est normalement situé à "C:\Program Files\Autopsy-version\bin". + +\image html command_line_ingest_bin_dir.png + +Le tableau ci-dessous présente un résumé des opérations en ligne de commande. Vous pouvez en exécuter une ou plusieurs à la fois, mais vous devez toujours créer un cas ou ouvrir un cas existant. + +
    + + + + + + + + + + + + +
    --listAllDataSources
    +
    OpérationCommande(s)Paramètre(s)Exemple
    Créer un nouveau cas
    --createCase
    --caseName
    +--caseBaseDir
    +--caseType (facultatif)
    --createCase --caseName="test5" --caseBaseDir="C:\work\cases"
    +--createCase --caseName="test_multi" --caseBaseDir="\\WIN-2913\work\cases" --caseType="multi"
    Ouvrir un cas existant 
    --caseDir
    --caseDir="C:\work\Cases\test5_2019_09_20_11_01_29"
    Ajouter une source de données
    --addDataSource
    +--runIngest (facultatif)
    +--runIngest=(nom du profil d'acquisition) (facultatif)
    --dataSourcePath
    --addDataSource --dataSourcePath="R:\work\images\small2.img" --runIngest
    Exécuter l'acquisition sur une source de données existante
    --runIngest
    +--runIngest=(nom du profil d'acquisition)
    --dataSourceObjectId
    --runIngest --dataSourceObjectId=1
    +--runIngest="imageAnalysis" --dataSourceObjectId=1
    Générer des rapports
    --generateReports
    +--generateReports=(nom du profil de rapport)
     
    --generateReports
    +--generateReports="kmlReport"
    Créer une liste de sources de données
    --listAllDataSources
     
    + + +Plus de détails sur chaque opération ainsi que des exemples supplémentaires sont donnés ci-dessous. + +\subsection command_line_cases Création et ouverture de cas + +Vous devrez toujours créer un cas ou donner le chemin vers un cas existant. Lors de la création d'un cas, l'horodatage actuel sera ajouté au nom du cas. Par exemple, exécutez cette commande: + +\verbatim +autopsy64.exe --createCase --caseName="test5" --caseBaseDir="C:\work\cases" +\endverbatim + +pourrait créer un dossier de cas "test5_2019_09_20_11_01_29". Notez que même si un horodatage est ajouté au nom, le champ --caseName doit être unique pour chaque exécution. + +\image html command_line_ingest_case_folder.png + +Par défaut, tous les cas seront mono-utilisateur. Si vous souhaitez créer un cas multi-utilisateur, vous aurez besoin du champ --caseType. Vous devez également utiliser le chemin d'accès réseau de votre dossier de cas afin que les services puissent y accéder: + +\verbatim +autopsy64.exe --createCase --caseName="test_multi" --caseBaseDir="\\WIN-2913\work\cases" --caseType="multi" +\endverbatim + +Une fois qu'un cas est créé, vous devrez utiliser le chemin d'accès complet au cas au lieu du nom du cas et du dossier de base. Par exemple, si nous avons créé le cas vide "test5" comme ci-dessus, nous pourrions utiliser la commande suivante pour y ajouter une source de données: + +\verbatim +autopsy64.exe --caseDir="C:\work\Cases\test5_2019_09_20_11_01_29" --addDataSource + --dataSourcePath="R:\work\images\small2.img" +\endverbatim + +Le type de dossier (mono ou multi-utilisateur) n'a pas à être spécifié lors de l'ouverture d'un cas. + +\subsection command_line_ds Ajout d'une nouvelle source de données et exécution de l'acquisition + +Vous pouvez ajouter une source de données à un nouveau cas ou un cas existant à l'aide de l'option --addDataSource, puis en indiquant le chemin d'accès à la source de données. Si vous utilisez l'option --runIngest, les modules d'acquisition que vous avez sélectionnés dans l'\ref command_line_ingest_config "étape de configuration" seront exécutés sur la source de données. Les \ref ds_img "images disque" et les \ref ds_log "fichiers logiques" sont pris en charge. Vous ne pouvez ajouter qu'une seule source de données à la fois. + +Dans cet exemple, nous allons créer un nouveau cas nommé "test6" et ajouter la source de données "blue_images.img". + +\verbatim +autopsy64.exe --createCase --caseName="test6" --caseBaseDir="C:\work\cases" --addDataSource + --dataSourcePath="R:\work\images\blue_images.img" +\endverbatim + +Et ici, nous allons ajouter une autre source de données ("green_images.img") au cas que nous venons de créer et exécuter une acquisition dessus. Notez que l'acquisition ne s'exécutera que sur la nouvelle source de données ("green_images.img"), pas sur celle déjà présente dans le cas ("blue_images.img"). + +\verbatim +autopsy64.exe --caseDir="C:\work\cases\test6_2019_09_20_13_00_51" --addDataSource --runIngest + --dataSourcePath="R:\work\images\green_images.img" +\endverbatim + +Ensuite, nous allons ajouter une troisième source de données ("red_images.img") au cas et exécuter l'acquisition à l'aide d'un profil d'acquisition personnalisé "imageAnalysis" créé comme décrit dans la section \ref command_line_ingest_profile "Configuration des profils d'acquisition" ci-dessus. + +\verbatim +autopsy64.exe --caseDir="C:\work\cases\test6_2019_09_20_13_00_51" --addDataSource --runIngest="imageAnalysis" + --dataSourcePath="R:\work\images\red_images.img" +\endverbatim + +Enfin, nous ajouterons un dossier ("Test files") en tant que fichier logique défini dans un nouveau cas ("test9"). + +\verbatim +autopsy64.exe --createCase --caseName="test9" --caseBaseDir="C:\work\Cases" --addDataSource + --dataSourcePath="R:\work\images\Test files" --runIngest +\endverbatim + +\subsection command_line_existing_ds Exécution de l'acquisition sur une source de données existante + +Vous pouvez exécuter l'acquisition sur une source de données déjà dans le cas si vous connaissez son identifiant ("Object ID"). Pour le trouver, allez dans le dossier du cas et ouvrez le dossier "Command Output". + +\image html command_line_ingest_output_folder.png + +Si vous avez l'exécutée avec l'option --listAllDataSources, il y aura au moins un fichier commençant par "listAllDataSources". Ouvrez le plus récent - le format sera similaire à celui-ci: + +\verbatim +{ + "@dataSourceName" : "blue_images.img", + "@dataSourceObjectId" : "1" +} { + "@dataSourceName" : "green_images.img", + "@dataSourceObjectId" : "84" +} +\endverbatim + +Vous pouvez également parcourir les fichiers addDataSource pour trouver celui correspondant au fichier que vous souhaitez acquérir. Le format sera le même. Une fois que vous connaissez l'identifiant de la source de données, vous pouvez utiliser l'option --dataSourceObjectId pour le spécifier. Par exemple, ceci exécutera l'acquisition sur "blue_images.img": + +\verbatim +autopsy64.exe --caseDir="C:\work\cases\test6_2019_09_20_13_00_51" --runIngest --dataSourceObjectId=1 +\endverbatim + +\subsection command_line_report Générer des rapports + +Vous pouvez générer un rapport sur le cas à l'aide de l'option --generateReports. Vous pouvez sélectionner le type de rapport à exporter via le panneau d'options d'Autopsy (voir la section \ref command_line_ingest_config "configuration"). Cette option peut être exécutée seule ou en même temps que vous traitez une source de données. Dans cet exemple, nous ajoutons une nouvelle source de données ("small2.img") et générons un rapport. + +\verbatim +autopsy64.exe --caseDir="C:\work\cases\test6_2019_09_20_13_00_51" --addDataSource + --dataSourcePath="R:\work\images\small2.img" --runIngest --generateReports +\endverbatim + +L'exemple ci-dessus utilise le profil de rapport par défaut. Si vous configurez un profil de rapport personnalisé comme décrit dans la section \ref command_line_report_profile "Configuration des profils d'acquisition" ci-dessus, vous pouvez spécifier ce profil après l'option --generateReports. + +\verbatim +autopsy64.exe --caseDir="C:\work\cases\test6_2019_09_20_13_00_51" --generateReports="html" +\endverbatim + +\subsection command_line_listds Liste de toutes les sources de données + +Vous pouvez ajouter --listAllDataSources à tout moment pour afficher une liste de toutes les sources de données actuellement dans le cas avec leurs identifiants, à utiliser lors de l'\ref command_line_existing_ds "exécution de l'acquisition sur une source de données existante". Cette commande peut même être exécutée seule avec uniquement le chemin d'accès au cas. + +\verbatim +autopsy64.exe --caseDir="C:\work\cases\test6_2019_09_20_13_00_51" --listAllDataSources +\endverbatim + + +\section command_line_ingest_run Exécution d'Autopsy + +Une fois que vous avez déterminé les paramètres dont vous avez besoin, il est temps d'exécuter Autopsy. Dans l'exemple ci-dessous, nous créons un nouveau cas ("xpCase"), en y ajoutant une source de données ("xp-sp3-v4.001"), en exécutant l'acquisition et en générant un rapport. Le type de rapport était \ref command_line_ingest_config "configuré" précédemment pour être un rapport HTML. + +\image html command_line_ingest_command_entry.png + +Si vous avez tout saisi correctement, Autopsy se chargera et vous verrez cette boîte de dialogue au milieu de l'écran: + +\image html command_line_ingest_dialog.png + +Si vous avez entré quelque chose de manière incorrecte, vous verrez probablement une erreur dans la sortie. Vous pourrez comparer ce que vous avez exécuté avec les descriptions et exemples ci-dessus pour essayer de corriger l'erreur. + +Si tout fonctionne correctement, vous verrez un journal du traitement en cours et Autopsy se fermera une fois terminé. + +\image html command_line_ingest_console_output.png + + +\section command_line_ingest_results Affichage des résultats + +Vous pouvez ouvrir le cas que vous avez créé directement à partir de la ligne de commande en spécifiant soit le dossier du cas, soit le chemin d'accès au fichier ".aut". N'oubliez pas que le dossier sera nommé avec l'horodatage ajouté au nom de votre cas. +\verbatim +autopsy64.exe "C:\work\cases\xpCase_2019_09_20_14_39_25" +autopsy64.exe "C:\work\cases\xpCase_2019_09_20_14_39_25\xpCase.aut" +\endverbatim + +Vous pouvez également ouvrir le cas normalement via Autopsy. Allez simplement dans "Open Case", puis accédez au dossier de sortie que vous avez configuré dans la section \ref command_line_ingest_config et recherchez le dossier commençant par le nom de votre cas. Il sera nommé avec l'horodatage ajouté au nom que vous avez spécifié. + +\image html command_line_ingest_open_case.png + +Si vous n'êtes intéressé que par les rapports, vous n'avez pas besoin d'ouvrir Autopsy. Vous pouvez simplement parcourir le dossier "Reports" dans le répertoire du cas et accéder directement aux rapports. + +\image html command_line_ingest_report.png + +*/ \ No newline at end of file diff --git a/docs/doxygen-user_fr/common_files.dox b/docs/doxygen-user_fr/common_files.dox new file mode 100644 index 0000000000..7a8d6223b1 --- /dev/null +++ b/docs/doxygen-user_fr/common_files.dox @@ -0,0 +1,72 @@ +/*! \page common_properties_page Recherche de propriétés communes + +[TOC] + + +\section common_properties_overview Aperçu + +La fonction de recherche de propriétés communes vous permet de rechercher plusieurs copies d'une propriété dans le cas actuel ou dans le \ref central_repo_page. + +Pour lancer une recherche, accédez à Tools->Find Common Properties pour afficher la boîte de dialogue principale. La recherche nécessite au moins l'une des conditions suivantes pour aboutir: +
      +
    • Le cas actuel a plus d'une source de données +
    • Le référentiel central contient au moins deux cas +
    + +S'il n'existe aucune de ces deux conditions, l'élément de menu sera désactivé. Si une seul n'est pas remplie, une partie de la boîte de dialogue de recherche sera désactivée. + +\section common_properties_search_types Portée de la recherche de propriétés communes + +Différents paramètres sont nécessaires pour configurer les deux types de recherche. Ceux-ci seront décrits ci-dessous. + +\subsection common_properties_intra_case Portée "Between data sources in the current case" (entre les sources de données dans le cas actuel) + +Ce type de recherche analyse les fichiers qui se trouvent dans plusieurs sources de données dans le cas actuel. Il ne nécessite pas l'activation du référentiel central et ne recherche actuellement que les fichiers communs. Vous devez exécuter le module \ref hash_db_page pour calculer les hachages MD5 sur chaque source de données avant d'effectuer cette recherche. Les résultats de la recherche n'incluront aucun fichier marqué comme "known" (connus) par le module de hachage (ex: fichiers qui sont dans le NSRL). + +\image html common_properties_intra_case.png + +Par défaut, la recherche trouvera les fichiers correspondants dans toutes les sources de données. Si vous le souhaitez, vous pouvez modifier cette recherche pour n'afficher que les correspondances où l'un des fichiers se trouve dans une certaine source de données en la sélectionnant dans la liste: + +\image html common_properties_select_ds.png + +Vous pouvez également choisir d'afficher n'importe quel type de fichiers correspondants ou restreindre la recherche aux images et vidéos et/ou documents. + +Enfin, si le référentiel central est activé, vous pouvez choisir de masquer les correspondances qui apparaissent avec une fréquence élevée dans le référentiel central. + +\subsection common_properties_central_repo Portée "Between current case and cases in the Central Repository" (entre le cas actuel et les cas dans le référentiel central) + +Ce type de recherche analyse les fichiers contenant des propriétés communes entre le cas actuel et les autres cas dans le référentiel central. Vous devez exécuter le module d'acquisition "Central Repository" sur chaque cas en ayant activé la propriété que vous souhaitez rechercher, ainsi que les modules d'acquisition qui produisent ce type de propriété (voir la \ref cr_manage_properties "gestion des propriétés de corrélation"). + +\image html common_properties_cr.png + +Vous pouvez restreindre la recherche pour inclure uniquement les résultats où au moins une des correspondances était dans un cas spécifique. + +\image html common_properties_cr_case_select.png + +Dans l'exemple ci-dessus, toutes les propriétés correspondantes devraient exister dans le cas actuel et dans le cas 2. Notez que les correspondances dans d'autres cas seront également incluses dans les résultats, tant que la propriété existe dans le cas actuel et le cas sélectionné. + +Vous pouvez sélectionner le type de propriété à rechercher dans le menu ci-dessous: + +\image html common_properties_cr_property.png + +La restriction d'une recherche de fichier pour ne renvoyer que des images ou des documents est actuellement désactivée. + +Vous pouvez choisir de masquer les correspondances qui apparaissent avec une fréquence élevée dans le référentiel central. Enfin, vous pouvez choisir comment afficher les résultats, ce qui sera décrit ci-dessous. + +\section common_properties_results Résultats de recherche + +Chaque recherche affiche ses résultats dans un nouvel onglet. Le titre de l'onglet inclura les paramètres de recherche. + +\subsection common_properties_sort_by_count Trier par nombre de sources de données + +\image html common_properties_result.png + +C'est ainsi que sont affichés tous les résultats des recherches dans le cas actuel, avec une option pour afficher les résultats d'une recherche entre le cas actuel et le référentiel central. Le niveau supérieur de l'arborescence des résultats indique le nombre de propriétés correspondantes. Les résultats sont regroupés en fonction du nombre de propriétés correspondantes trouvées, puis regroupés en fonction de la propriété elle-même. + +\subsection common_properties_sort_by_case Trier par cas + +Cette option n'est disponible que lors d'une recherche entre le cas actuel et le référentiel central. Le niveau supérieur montre chaque cas avec des propriétés correspondantes, puis vous pouvez sélectionner la source de données à afficher. Chaque propriété correspondante sera affichée sous la source de données. + +\image html common_properties_result_case_sort.png + +*/ \ No newline at end of file diff --git a/docs/doxygen-user_fr/communications.dox b/docs/doxygen-user_fr/communications.dox new file mode 100644 index 0000000000..4644b71840 --- /dev/null +++ b/docs/doxygen-user_fr/communications.dox @@ -0,0 +1,83 @@ +/*! \page communications_page Communications + +[TOC] + + +\section cvt_overview Aperçu + +L'outil de visualisation des communications donne une vue consolidée de tous les événements de communication pour le cas. Cela permet à un analyste de visualiser rapidement les données de communication telles que: +
      +
    • Les comptes les plus couramment utilisés +
    • Les communications dans un délai précis +
    + +\section cvt_usage Usage + +L'outil de visualisation des communications est chargé via le menu Tools->Communications. + +\image html cvt_main.png + +Dans la colonne de gauche, vous pouvez choisir les appareils à afficher, les types de données à afficher et éventuellement sélectionner une plage de temps. Vous pouvez également choisir de limiter l'affichage aux seules communications les plus récentes. Après toute modification des filtres, utilisez le bouton "Apply" pour mettre à jour les tables. Vous pouvez masquer cette colonne en cliquant sur la flèche gauche en haut de la colonne. + +La colonne du milieu affiche chaque compte, son appareil et son type, ainsi que le nombre de messages associés (e-mails, journaux d'appels, etc...). Par défaut, elle sera triée par ordre décroissant de fréquence. La colonne du milieu et la colonne de droite ont toutes deux une fonction de \ref ui_quick_search qui peut être utilisée pour trouver rapidement un élément visible dans le tableau de leur section. + +La sélection d'un compte dans la colonne du milieu affichera les données de ce compte dans la colonne de droite. Il y a quatre onglets qui affichent des informations sur le compte sélectionné. + +
      +
    • L'onglet Summary affiche le nombre de fois où le compte est apparu dans différents types de données dans la section supérieure. Au milieu, s'affiche les fichiers dans lesquels ce compte a été trouvé. Si le \ref central_repo_page est activé, vous pouvez voir si des \ref personas_page "personnes" sont associées à ce compte et s'il existe d'autres cas contenant ce compte. + +\image html cvt_summary_tab.png + +
    • L'onglet Messages affiche tous les messages ou journaux d'appels associés au compte. Les messages seront soit dans un fil de discussion ("Thread"), soit répertoriés sous un nœud appelé "Unthreaded". Cliquer sur le nœud "Unthreaded" affichera tous les messages qui ne sont pas dans un "Thread". + +\image html cvt_messages_threaded.png + +Vous pouvez utiliser le bouton "All Messages" en bas du panneau pour afficher tous les messages. Cliquez sur un message dans un fil de discussion pour afficher tous les messages de ce fil. Vous pouvez cliquer sur un message individuel pour l'afficher dans le panneau inférieur. Cliquez sur le bouton "Threads" pour revenir à l'écran d'origine. + +\image html cvt_message_email.png + +Si le message contient des pièces jointes, vous pouvez les afficher dans l'onglet "Attachments". Si vous sélectionnez une pièce jointe, vous pouvez choisir de l'ouvrir dans une nouvelle fenêtre ou de la consulter dans l'onglet "Thumbnails". + +\image html cvt_message_attach.png + +
    • L'onglet Call Logs affiche toutes les entrées du journal des appels concernant le compte sélectionné. + +\image html cvt_call_log.png + +
    • L'onglet Contacts affiche toutes les informations sur ce compte trouvées dans un fichier de contacts. + +\image html cvt_contacts.png + +
    • L'onglet Media Attachments affiche les miniatures de tous les fichiers multimédias dans les messages de ce compte. Si vous cliquez sur une de ces miniatures, le message d'où provient ce fichier multimédia s'affichera . + +\image html cvt_media.png + +
    + +\section cvt_viz Visualisation + +L'onglet "Visualize" dans le panneau du milieu affichera un graphique d'un ou plusieurs comptes sélectionnés dans l'onglet "Browse". + +Pour commencer, cliquez avec le bouton droit sur le premier compte que vous souhaitez afficher. + +\image html cvt_select_account.png + +Il existe deux options, qui sont équivalentes lorsqu'aucun compte n'a été préalablement sélectionné: +
      +
    • Add Selected Account to Visualization - Ajoute ce compte et ses connexions au graphique +
    • Visualize Only Selected Account - Efface le graphique et n'affiche que les connexions pour ce compte +
    + +Après avoir sélectionné l'une ou l'autre option, l'onglet du milieu passera à la vue "Visualize" et le graphique sera affiché. + +\image html cvt_visualize.png + +Les options en haut vous permettent d'effacer le graphique et de le redimensionner. Les nœuds du graphique peuvent être déplacés et les nœuds et les liens peuvent être sélectionnés pour afficher leurs messages ou leurs relations dans l'onglet de droite. Par exemple, dans l'image ci-dessous, un seul nœud a été sélectionné, de sorte que la visionneuse de messages n'affiche que les messages impliquant cette adresse e-mail. + +\image html cvt_links.png + +Si vous cliquez sur le bouton "Snapshot Report", vous pouvez générer un rapport similaire au format HTML du \ref reporting_page "module Rapports". Sélectionnez un nom pour votre rapport, qui sera enregistré dans le dossier "Reports" du cas actuel. Le "Snapshot Report" contiendra deux pages. La première présentera un résumé du cas, et la seconde le graphique actuel avec vos paramètres de filtre. + +\image html cvt_snapshot.png + +*/ \ No newline at end of file diff --git a/docs/doxygen-user_fr/configuration.dox b/docs/doxygen-user_fr/configuration.dox new file mode 100644 index 0000000000..a9e731c6f1 --- /dev/null +++ b/docs/doxygen-user_fr/configuration.dox @@ -0,0 +1,61 @@ +/*! \page config_page Configuration générale + +[TOC] + +\section config_overview Aperçu + +Vous pouvez configurer Autopsy via le panneau d'options principal. Ce dernier est accessible en allant dans Tools->Options. A cet endroit, vous pouvez modifier la façon dont les cas sont affichés, configurer le fonctionnement d’Autopsy, créer des ensembles de hachage, des listes de mots-clés, etc... + +Le panneau d'options comporte différents onglets pour chaque fonction. Ces options sont documentées sur les pages principales de chaque fonctionnalité. Par exemple, l'onglet \ref keyword_search_configuration_dialog "Keyword Search" est décrit sur la page principale du \ref keyword_search_page. Les onglets qui ne correspondent pas à une fonctionnalité documentée ailleurs seront décrits ici. + +\section config_app Application + +Le premier onglet du panneau d'options concerne les paramètres généraux de l'application. + +\image html options_application.png + +La section supérieure vous permet d'ajuster la quantité de mémoire utilisée par Autopsy et le nombre de fichiers journaux à conserver. En général, chaque session d’Autopsy génère un fichier journal, bien qu’elle puisse en générer davantage si le fichier journal devient trop volumineux. Vous pouvez également spécifier un emplacement personnalisé dans lequel écrire des captures de tas ("heap dump"). + +La section suivante vous permet de spécifier où Autopsy doit stocker les fichiers temporaires. Ces fichiers seront supprimés lors de la clôture d'un dossier. Il existe trois options: +
      +
    • Local temp directory - Utilise le dossier temporaire du système (Sur Windows, typiquement C:\\Users\\(nom de l'utilisateur)\\AppData\\Local\\Temp\\Autopsy) +
    • Temp folder in case directory - Place les fichiers temporaires dans le répertoire "temp" situé dans le dossier de cas +
    • Custom - Utilisera le dossier donné par l'utilisateur comme base pour les fichiers temporaires +
    + +La dernière section vous permet de définir un logo personnalisé. + +\image html options_logo.png + +Ce logo sera affiché dans tous les \ref report_html "rapports HTML" générés. + +\image html options_logo_report.jpg + +La section suivante répertorie les instructions sur la façon de modifier la mise à l'échelle pour les systèmes Windows à PPP élevé. + +\section config_view View + +Consultez la page \ref view_options_page pour une description de la façon dont vous pouvez personnaliser les données affichées dans Autopsy. + +\section config_ext_viewer External Viewers + +L'onglet "External Viewer" vous permet d'ajouter des associations de fichiers et de sélectionner un éditeur hexadécimal. + +\image html options_ext_viewer.jpg + +La section supérieure vous permet de saisir des associations de fichiers personnalisées par extension ou par type MIME. Dans l'image ci-dessus, nous avons associé des fichiers .xml à l'application Bloc-notes. Il est maintenant possible de faire un clic droit sur un fichier .xml dans la visionneuse de résultats et de choisir "Open in External Viewer" pour ouvrir ce fichier .xml dans le Bloc-notes. + +\image html options_ext_viewer_context_menu.jpg + +La section inférieure vous permet de spécifier un éditeur hexadécimal. HxD a été testé et est la valeur par défaut, mais d'autres éditeurs hexadécimaux fonctionneront également. L'éditeur hexadécimal sélectionné sera lancé en cliquant sur le bouton "Launch in HxD" dans l'onglet «Hex» de la \ref content_viewer_page. + +\section config_general General + +L'onglet "General" vous permet de configurer les paramètres du proxy. + +\image html proxySettings.PNG + + + + +*/ \ No newline at end of file diff --git a/docs/doxygen-user_fr/content_viewer.dox b/docs/doxygen-user_fr/content_viewer.dox new file mode 100644 index 0000000000..edd3e46f25 --- /dev/null +++ b/docs/doxygen-user_fr/content_viewer.dox @@ -0,0 +1,117 @@ +/*! \page content_viewer_page Visionneuse de contenu + +[TOC] + + +La visionneuse de contenu se trouve dans le coin inférieur droit de l'écran principal d'Autopsy et affiche des images, des vidéos, de l'hexadécimal, du texte, des chaînes de caractères extraites, des métadonnées, etc... La visionneuse de contenu est activée lorsque vous sélectionnez une entrée dans la \ref ui_results "visionneuse de résultats". + +La visionneuse de contenu est sensible au contexte, ce qui signifie que les différents onglets seront activés en fonction du type de contenu sélectionné et des modules d'acquisition exécutés. Elle adoptera par défaut ce qu'elle considère comme l'onglet "le plus représentatif". Par exemple, en sélectionnant un JPG, la visionneuse de contenu sélectionnera automatiquement l'onglet "Application" et y affichera l'image. Si vous souhaitez plutôt que la visionneuse de contenu reste sur l'onglet précédemment sélectionné lorsque vous passez à un autre objet, accédez aux \ref view_options_page en allant sur Tools->Options->Application Tab et en sélectionnant l'option "Stay on the same file viewer". + +\image html content_viewer_options_panel.png + +Lorsqu'un élément de résultat (et non un fichier) est sélectionné dans la visionneuse de résultats, la plupart des onglets correspondront au fichier associé au résultat et non au résultat lui-même. Par exemple, lors de la sélection d'un hit de mot-clé, les onglets "Hex", "Strings" et "File Metadata" afficheront les données du fichier dans lequel le mot-clé a été trouvé. Les descriptions ci-dessous supposeront généralement qu'un fichier a été sélectionné, mais la plupart s'appliquent également lorsqu'un fichier est associé à un résultat sélectionné. + +\section cv_hex Hex + +L'onglet "Hex" est presque toujours disponible et vous montre le contenu brut et exact d'un fichier. Dans cet onglet, les données du fichier sont représentées sous forme de valeurs hexadécimales regroupées en 2 groupes de 8 octets, suivis d'un groupe de 16 caractères ASCII qui sont dérivés de chaque paire de valeurs hexadécimales (chaque octet). Les caractères ASCII non imprimables et les caractères qui prendraient plus d'un espace de caractère sont généralement représentés par un point (".") dans le champ ASCII suivant. + +\image html content_viewer_hex.png + +Si vous le souhaitez, vous pouvez ouvrir le fichier dans un éditeur hexadécimal externe. Ceci est configurable via l'onglet \ref config_ext_viewer du panneau des options. HxD a été vérifié pour fonctionner avec Autopsy, mais d'autres éditeurs hexadécimaux peuvent également être compatibles. + +Notez que ce processus enregistre le fichier sur le disque avant de lancer l'éditeur hexadécimal. Un indicateur de progression sera affiché dans le coin inférieur droit de l'application. Si vous souhaitez annuler l'exportation du fichier, cliquez sur le 'X' à droite de la barre de progression. + +\image html content_viewer_hxd_progress.png + +\section cv_text Text + +L'onglet "Text" comporte trois sous-onglets pour afficher le texte contenu dans l'élément sélectionné. + +\subsection cv_strings Strings + +Le sous-onglet "Strings" affiche toutes les chaînes de caractères trouvées dans le fichier avec le script donné sélectionné en haut à droite. Par défaut, le "Latin" est utilisé. + +\image html content_viewer_strings_latin.png + +Différents scripts peuvent être choisis dans le menu déroulant pour afficher les résultats pour les alphabets non latins. + +\image html content_viewer_strings_cyrillic.png + +\subsection cv_indexed_text Indexed Text + +Le sous-onglet "Indexed Text" affiche le texte qui a été indexé par le module \ref keyword_search_page. Vous pouvez basculer le champ "Text Source" sur "Result Text" pour afficher le texte qui a été indexé pour les résultats associés à un fichier. + +\image html content_viewer_indexed_text.png + +\subsection cv_translation Translation + +Si un service de traduction est activé, le sous-onglet "Translation" vous permet de traduire le texte. Voir la page \ref machine_translation_page pour plus d'informations. + +\section cv_app Application + +Pour certains types de fichiers, l'onglet "Application" peut afficher le contenu dans un format convivial. Les captures d'écran suivantes montrent quelques exemples de ce que l'onglet "Application" va afficher. + +Il affichera la plupart des types d'images, qui peuvent être mises à l'échelle et pivotées: + +\image html content_viewer_app_image.png + +Il affiche les fichiers vidéo, vous permettant de mettre en lecture/pause, d'avancer ou de reculer de 30 secondes, de régler le volume et de modifier la vitesse de lecture. + +\image html content_viewer_video.png + +Il vous permet également de parcourir les tables SQLite et d'exporter leur contenu au format CSV: + +\image html content_viewer_app_sqlite.png + +Et les données de fichiers plist seront affichées et peuvent être exportées: + +\image html content_viewer_app_plist.png + +Les fichiers HTML peuvent être affichés au plus près de leur forme d'origine: + +\image html content_viewer_html.png + +Les fichiers des ruches de la Base de registre peuvent être affichés dans un format similaire à celui d'un éditeur de registre. + +\image html content_viewer_registry.png + +\section cv_metadata File Metadata + +L'onglet "File Metadata" affiche des informations de base sur le fichier, telles que le type, la taille et le hachage. Il affiche également la sortie de l'outil istat du Sleuth Kit. + +\image html content_viewer_metadata.png + +\section cv_os_account OS Accounts + +L'onglet "OS Accounts" affiche des informations sur le compte du système d'exploitation associé à un résultat donné, le cas échéant. Il est également utilisé pour donner des détails sur les comptes répertoriés sous le nœud "OS Accounts" dans l'arborescence. + +\image html content_viewer_os_account.png + +\section cv_results Results + +L'onglet "Results" est activé lors de la sélection d'éléments avec des résultats associés tels que des hits sur des mots clés, des journaux d'appels et des messages. Les champs exacts affichés dépendent du type de résultat. Les deux images ci-dessous montrent l'onglet "Results" pour un journal d'appels et un signet Web. + +\image html content_viewer_results_call.png +
    +\image html content_viewer_results_bookmark.png + +\section cv_context Context + +L'onglet "Context" affiche des informations sur l'origine d'un fichier et vous permet d'accéder au résultat d'origine. Par exemple, il peut afficher l'URL des fichiers téléchargés et le message électronique auquel un fichier était joint. Dans l'image ci-dessous, vous pouvez voir le contexte d'une image qui a été envoyée en tant que pièce jointe à un e-mail. + +\image html content_viewer_context.png + +\section cv_annotations Annotations + +L'onglet "Annotations" affiche les informations ajoutées par un analyste sur un fichier ou un résultat. Il affiche toutes les balises et commentaires associés au fichier ou au résultat, et si le \ref central_repo_page est activé, il affichera également tous les commentaires enregistrés dans le référentiel central. + +\image html content_viewer_annotations.png + +\section cv_other_occurrences Other Occurrences + +L'onglet "Other Occurrences" affiche d'autres instances de ce fichier ou résultat. L'activation du \ref central_repo_page ajoute des fonctionnalités supplémentaires à cet onglet. Voir la section \ref cr_content_viewer pour plus d'informations. + +\image html content_viewer_other_occurrences.png + + +*/ diff --git a/docs/doxygen-user_fr/data_source_integrity.dox b/docs/doxygen-user_fr/data_source_integrity.dox new file mode 100644 index 0000000000..2a9d2039a8 --- /dev/null +++ b/docs/doxygen-user_fr/data_source_integrity.dox @@ -0,0 +1,53 @@ +/*! \page data_source_integrity_page Data Source Integrity (Intégrité de la source de données) + +[TOC] + + +\section data_source_integrity_overview Aperçu + +Le module "Data Source Integrity" a deux objectifs: +
      +
    • Si la source de données est associée à des hachages (saisis par l'utilisateur ou contenus dans un fichier E01), il vérifiera ces hachages +
    • Si la source de données n'a pas de hachage associé, il calculera les hachages et les stockera dans la base de données +
    + +\section data_source_integrity_running Exécuter le module + +Si vous souhaitez vérifier les hachages, la première étape consiste à entrer des hachages pour votre image disque (sauf si vous avez un fichier E01 - le hachage est inclus dans la source de données). +Vous pouvez le faire dans l'assistant "Add Data Source" dans lequel vous sélectionnez votre image disque. + +\image html data_source_integrity_add_ds.png + +Vous pouvez saisir n'importe quelle combinaison de hachages à vérifier. + +Vous devrez ensuite configurer le module d'acquisition. + +\image html data_source_integrity_ingest_settings.png + +Notez qu'il s'agit simplement d'activer un comportement ou les deux, non pas choisir celui à exécuter (calculer ou vérifier). Cela est déterminé uniquement par le fait que la source de données a des hachages associés. Décocher les deux cases mais laisser le module activé entraînera une erreur lors du démarrage du module d'acquisition. + +\section data_source_integrity_results Affichage des résultats + +\subsection data_source_integrity_verification Vérification du hachage + +Au terme du calcul, si la vérification réussit, vous verrez un message dans boîte de notification vous le confirmant. Si vous ouvrez ce message, vous verrez les valeurs de hachage stockées et calculées. + +\image html data_source_integrity_pass1.png +
    +\image html data_source_integrity_pass2.png + +Si la vérification échoue, vous verrez un message dans boîte de notification en jaune et le même message dans une info bulle d'avertissement. + +\image html data_source_integrity_failed_inbox.png + +Les messages de la boîte de notification disparaîtront une fois le cas fermé, le module ajoute donc également au cas un artefact "Verification Failed" ("Échec de la vérification"). + +\image html data_source_integrity_failed_artifact.png + +\subsection data_source_integrity_computation Calcul de hachage + +Pour afficher les hachages calculés, sélectionnez "Data Sources" dans l'arborescence, sélectionnez votre source de données dans la visionneuse de résultats, puis ouvrez l'onglet "File Metadata". Si vous êtes en mode "Group by data source" (voir \ref view_options_page), selectionnez "Data Source Files" sous la source de données que vous souhaitez examiner. + +\image html data_source_integrity_metadata.png + +*/ diff --git a/docs/doxygen-user_fr/data_source_summary.dox b/docs/doxygen-user_fr/data_source_summary.dox new file mode 100644 index 0000000000..0bb4517857 --- /dev/null +++ b/docs/doxygen-user_fr/data_source_summary.dox @@ -0,0 +1,89 @@ +/*! \page data_source_summary_page Résumé de la source de données + +[TOC] + +\section ds_summary_overview Aperçu + +La visionneuse "Data Source Summary" vous permet d'afficher une vue d'ensemble des types de fichiers, des résultats et d'autres informations pour une source de données particulière. + +\section ds_summary_opening Ouverture du résumé de la source de données + +Il existe deux façons d'afficher le résumé de la source de données. Le premier est d'aller sur Case->Data Source Summary. Cela ouvrira le résumé dans une nouvelle fenêtre. + +\image html ds_summary_window.png + +La deuxième façon d'afficher le résumé consiste à sélectionner la source de données dans l'\ref tree_viewer_page puis sélectionner l'onglet "Summary" dans la \ref result_viewer_page. + +\image html ds_summary_result_viewer.png + +\section ds_summary_main Sections + +Chaque onglet du résumé de la source de données affiche différents types d'informations sur la source de données sélectionnée. Si l'acquisition est en cours, le résumé sera mis à jour périodiquement au fur et à mesure que de nouvelles données seront disponibles. + +Si le ou les module(s) d'acquisition requis pour un type de données n'ont pas été exécutés, vous verrez une note expliquant pourquoi il n'y a pas de données. Par exemple, les résultats "Recent Programs" sont créés par le module \ref recent_activity_page, vous verrez donc un message sur l'exécution de ce module si vous ne l'avez pas fait. + +\image html DataSourceSummary/ds_summary_noRA.png + +\subsection ds_summary_types Types + +L'onglet "Types" affiche le nombre de types de fichiers différents trouvés dans la source de données. + +\image html ds_summary_types.png + +\subsection ds_summary_user_activity User Activity + +L'onglet "User Activity" affiche les résultats les plus récents trouvés dans la source de données. Vous pouvez faire un clic droit sur une ligne pour accéder directement au résultat correspondant. + +\image html ds_summary_user_activity.png + +\subsection ds_summary_analysis Analysis + +L'onglet "Analysis" montre les ensembles avec le plus grand nombre de résultats concernant les modules \ref hash_db_page, \ref keyword_search_page, et \ref interesting_files_identifier_page. + +\image html ds_summary_analysis.png + +\subsection ds_summary_recent_files Recent Files + +L'onglet "Recent Files" affiche des informations sur les fichiers les plus récents ouverts et téléchargés. Vous pouvez faire un clic droit sur une ligne pour accéder directement au fichier ou au résultat correspondant. + +\image html ds_summary_recent_files.png + +\subsection ds_summary_past_cases Past Cases + +L'onglet "Past Cases" montre quels cas avaient des résultats ou des fichiers notables en commun avec la source de données actuelle. Ceci est basé sur les résultats de la zone "Interesting Items" de la section "Results" de l'\ref tree_viewer_page. Le module d'acquisition \ref central_repo_page "Central Repository" doit avoir été exécuté avec les options "Flag items previously tagged as notable" et "Flag devices previously seen in other cases" activées. + +\image html ds_summary_past_cases.png + +Notez que, comme ces entrées sont basées sur les résultats des éléments intéressants créés lors de l'acquisition et n'interrogent pas le référentiel central, elles ne refléteront aucune correspondance dans les cas traités après ce dernier. Par exemple, supposons que nous créons le cas A et procédons à l'acquisition d'une source de données avec le périphérique Z. Si nous créons un nouveau cas B par la suite et procédons à l'acquisition d'une source de données qui a également le périphérique Z, nous verrons le cas A répertorié dans cet onglet pour le cas B, mais si nous rouvrions le cas A, nous ne verrions pas le cas B répertorié à moins que l'acquisition ne soit exécutée à nouveau. + +\subsection ds_summary_geo Geolocation + +L'onglet "Geolocation" utilise les coordonnées des résultats de géolocalisation pour trouver la ville la plus proche pour chacune et affiche les villes les plus récentes et les villes les plus courantes. Si l'emplacement est à plus de 150 km d'une ville, il sera affiché comme "Unknown" (inconnu). Le bouton "View in Map" sous le tableau des villes récentes ouvrira la fenêtre \ref geolocation_page "Geolocation" affichant tous les points de cheminement de cette source de données avec des horodatages au cours des 30 derniers jours. Le bouton "View in Map" sous les villes les plus courantes affichera tous les points de cheminement pour cette source de données. + +\image html ds_summary_geo.png + +\subsection ds_summary_timeline Timeline + +L'onglet "Timeline" montre une version simplifiée de la visionneuse \ref timeline_page "Timeline" pour la source de données sélectionnée. Il affichera les événements des 30 derniers jours d'activité dans la source de données et donnera les première et dernière dates d'activité. "File events" représente les dates de création, de modification, d'accès et de changement des fichiers. "Result events" représente les résultats de l'exécution de l'acquisition, tels que l'heure d'envoi d'un message ou l'accès à une URL. Le bouton "View in Timeline" ouvrira la visionneuse \ref timeline_page "Timeline". + +\image html ds_summary_timeline.png + +\subsection ds_summary_ingest_history Ingest History + +L'onglet "Ingest History" indique quels modules d'acquisition ont été exécutés sur la source de données et la version de chaque module. + +\image html ds_summary_ingest.png + +\subsection ds_summary_container Container + +L'onglet "Container" affiche des informations sur la source de données elle-même, telles que la taille et les chemins de l'image. + +\image html ds_summary_container.png + +\subsection ds_summary_export Export + +L'onglet "Export" vous permet d'exporter le contenu des autres onglets de résumé de la source de données vers un fichier au format Excel. + +\image html ds_summary_export.png + +*/ \ No newline at end of file diff --git a/docs/doxygen-user_fr/data_sources.dox b/docs/doxygen-user_fr/data_sources.dox new file mode 100644 index 0000000000..5706d43991 --- /dev/null +++ b/docs/doxygen-user_fr/data_sources.dox @@ -0,0 +1,154 @@ +/*! \page ds_page Data Sources (Sources de données) + + +[TOC] + + +Une source de données est ce que vous souhaitez analyser. Il peut s'agir d'une image disque, de certains fichiers logiques, d'un disque local, etc... Vous devez ouvrir un cas avant d'ajouter une source de données à Autopsy. + +Autopsy prend en charge plusieurs types de sources de données: +- Disk Image or VM File: Un fichier (ou un ensemble de fichiers) qui est une copie bit à bit d'un disque dur ou d'une carte multimédia, ou une image de machine virtuelle. (voir \ref ds_img) +- Local Disk: Périphérique de stockage local (lecteur local, lecteur USB, etc...). (voir \ref ds_local) +- Logical Files: Fichiers ou dossiers locaux. (voir \ref ds_log) +- Unallocated Space Image Files: Tout type de fichier qui ne contient pas de système de fichiers mais que vous souhaitez analyser via les modules d'acquisition (voir \ref ds_unalloc) +- Autopsy Logical Imager Results: Les résultats de l'exécution du Logical Imager (imageur logique) d'Autopsy. (voir \ref ds_logical_imager) +- XRY Text Export: Les résultats de l'exportation de fichiers texte depuis XRY. (voir \ref ds_xry) + +\section ds_add Ajouter une source de données + +Vous pouvez ajouter une source de données de plusieurs manières: +- Une fois que vous avez créé un cas, Autopsy vous invite automatiquement à ajouter une source de données. +- Il existe un élément de la barre d'outils "Add Data Source" pour ajouter une source de données lorsqu'un cas est ouvert. +- Le menu "Cases", "Add Data Source" lorsqu'un cas est ouvert. + +La source de données doit rester accessible pendant toute la durée de l'analyse car le cas contient une référence à la source de données. Il ne copie pas la source de données dans le dossier de cas. + +Quel que soit le type de source de données, le processus comporte certaines étapes courantes: +
      + +
    1. Vous choisirez l'hôte de la source de données que vous allez ajouter. Voir la page \ref host_page "Hôtes" pour plus d'informations sur les hôtes. + +\image html data_source_host_select.png + +Il existe trois options: +
        +
      • Generate new host based on data source name - cela créera typiquement un hôte avec un nom similaire à votre source de données avec l'ID utilisé dans la base de données ajouté pour l'unicité. +
      • Specify new host name - cela vous permet de saisir un nom d'hôte. +
      • Use existing host - cela vous permet de choisir un nom d'hôte déjà utilisé dans le cas actuel. +
      + +
    2. Vous sélectionnerez le type de source de données. + +\image html select-data-source-type.PNG + +
    3. Vous serez invité à spécifier la source de données à ajouter. Cet écran varie en fonction du type de source de données. Les détails sur l'ajout de chaque type de source de données sont fournis ci-dessous. + +REMARQUE: Si vous ajoutez une source de données à un cas multi-utilisateur, assurez-vous que tous les clients Autopsy auront accès à la source de données sur le même chemin. Nous vous recommandons d'utiliser des chemins UNC pour garantir un mappage cohérent. + +
    4. Ensuite, vous serez invité à activer une liste de modules d'acquisition. Si un ou plusieurs profils d'acquisition ont été enregistrés, il y aura un écran avant cela vous demandant s'il faut utiliser l'un des profils enregistrés ou effectuer une configuration personnalisée. Voir \ref ingest_page pour plus d'informations sur la configuration des profils d'acquisition. + +\image html select-ingest-modules.PNG + +
    5. Vous devrez attendre qu'Autopsy effectue un examen de base de la source de données et remplit la base de données intégrée avec une entrée pour chaque fichier de la source de données. + +\image html data-source-progress-bar.PNG + +
    6. Une fois l'examen de base de la source de données terminé, les modules d'acquisition seront probablement toujours en cours d'exécution, mais vous pouvez commencer à parcourir les fichiers de votre source de données. +
    + +Les sources de données peuvent être supprimées des cas créés avec Autopsy 4.14.0 et versions ultérieures. Voir la section \ref data_source_deletion "ci-dessous". + +\section ds_img Ajout d'une image disque + +Autopsy prend en charge les images disque dans les formats suivants: +- Raw Single (*.img, *.dd, *.raw, *.bin) +- Raw Split (*.001, *.aa) +- EnCase (*.e01) +- Virtual Machine Disk (*.vmdk) +- Virtual Hard Disk (*.vhd) + +\image html data_source_disk_image.png + +Pour ajouter une image disque: + +
      +
    1. Choisissez "Disk Image or VM File" parmi les types de source de données. +
    2. Accédez au premier fichier de l'image disque. Vous devez spécifier uniquement le premier fichier et Autopsy trouvera le reste.
    3. Choisissez d'effectuer la recherche de fichiers orphelins sur les systèmes de fichiers FAT. Cela peut prendre beaucoup de temps, car il faudra qu'Autopsy examine chaque secteur de l'appareil. +
    4. Choisissez le fuseau horaire d'où provient l'image disque. Ceci est le plus important lors de l'ajout de systèmes de fichiers FAT car ils ne stockent pas les informations de fuseau horaire et Autopsy ne saura pas comment se normaliser en UTC. +
    5. Choisissez éventuellement la taille du secteur. Le mode de détection automatique fonctionnera correctement sur la majorité des images, mais si l'ajout de la source de données échoue, vous souhaiterez peut-être essayer les autres tailles de secteur. +
    6. Entrez éventuellement un ou plusieurs hachages pour l'image. Ceux-ci seront enregistrés dans les métadonnées de l'image et pourront être vérifiés à l'aide du module \ref data_source_integrity_page. +
    + +\section ds_local Ajout d'un disque local + +Autopsy peut analyser un disque local sans avoir besoin d'en faire d'abord une image. Ceci est très utile lors de l'analyse d'un périphérique USB via un bloqueur en écriture. + +Notez que si vous analysez un disque local en cours de mise à jour, Autopsy ne verra pas les fichiers ajoutés après l'avoir ajouté en tant que source de données. + +Vous devrez exécuter Autopsy en tant qu'administrateur pour afficher tous les appareils. + +Il existe une option pour faire une copie du disque local en tant que disque dur virtuel pendant l'analyse. Ce VHD peut être chargé dans Windows ou analysé par Autopsy. Il existe une option supplémentaire pour mettre à jour le chemin de l'image dans la base de données de cas vers ce fichier nouvellement créé. L'activation de cette option vous permettra de parcourir les données de cas normalement, même après la suppression du disque local. Notez qu'au moins un module d'acquisition doit être exécuté avec succès pour générer la copie d'image complète. + +\image html local-disk-data-source.PNG + +Pour ajouter un lecteur local: +-# Choisissez "Local Disk" parmi les types de source de données. +-# Utilisez le bouton "Select Disk" pour ouvrir une boîte de dialogue affichant les disques locaux. Le chargement peut prendre une minute. Sélectionnez ensuite l'appareil dans la liste. +-# Choisissez d'effectuer la recherche de fichiers orphelins. Voir le commentaire dans \ref ds_img à propos de ce paramètre. +-# Choisissez de créer une copie VHD du disque local et de mettre à jour le chemin de l'image. +-# Choisissez éventuellement la taille du secteur. Le mode de détection automatique fonctionnera correctement sur la majorité des images, mais si l'ajout de la source de données échoue, vous souhaiterez peut-être essayer les autres tailles de secteur. + +\section ds_log Ajout d'un fichier logique + +Vous pouvez ajouter des fichiers ou des dossiers qui se trouvent sur votre ordinateur local (ou sur un lecteur partagé) sans les placer dans une image disque. Ceci est utile si vous ne disposez que d'une collection de fichiers que vous souhaitez analyser. + +Quelques points à noter lors de cette opération: +- Autopsy ignore les horodatages sur les fichiers qu'il ajoute de cette façon, car ce pourraient être les horodatages lorsque ces éléments ont été copiés sur votre appareil d'examen. +- Si vous possédez un périphérique USB que vous analysez et que vous choisissez d'ajouter le contenu du périphérique à l'aide de cette méthode, notez qu'Autopsy ne regardera pas l'espace non alloué ou les fichiers supprimés. Autopsy ne pourra voir que les fichiers alloués. Vous devez ajouter le périphérique en tant que "Logical Drive" pour analyser l'espace non alloué. +- Vous pouvez modifier le nom de l'ensemble de fichiers logiques par défaut LogicalFileSet# en cliquant sur le bouton "Change" comme indiqué dans la capture d'écran ci-dessous: + +\image html change_logical_file_set_display_name.PNG + +Pour ajouter des fichiers logiques: +-# Choisissez "Logical Files" parmi les types de source de données. +-# Laissez la liste déroulante du haut sur "Local files and folders" +-# Cliquez sur le bouton "Add" et accédez au dossier ou fichier à ajouter. Le choix d'un dossier entraînera l'ajout de tout son contenu (y compris les sous-dossiers). +-# Continuez de cliquer sur "Add" jusqu'à ce que tous les fichiers et dossiers aient été sélectionnés. + +Tous les fichiers que vous avez ajoutés dans le panneau seront regroupés dans une seule source de données, appelée "LogicalFileSet" dans l'interface utilisateur principale. + +La prise en charge limitée des fichiers de preuves logiques (L01) est également possible. Pour en ajouter un comme source de données, sélectionnez "Logical evidence file (L01)" dans la liste déroulante du haut, puis accédez à votre fichier. + +\section ds_unalloc Ajout d'un fichier image d'espace non alloué + +\image html unallocated_space_options.PNG + +Pour ajouter des fichiers image d'espace non alloué: +-# Choisissez "Unallocated Space Image File" parmi les types de source de données. +-# Accédez au fichier. +-# Choisissez de diviser l'image en morceaux. Le fractionnement de l'image donnera de meilleures performances car les blocs peuvent être traités en parallèle, mais il est possible que des mots-clés ou des résidus de fichiers qui dépassent les limites des blocs soient manquants. + +\section ds_logical_imager Ajout d'un résultat du "Logical Imager" (imageur logique) d'Autopsy + +Cette option vous permet d'ajouter les résultats d'une collecte de l'imageur logique. Voir la page \ref logical_imager_page pour plus de détails. + +\section ds_xry Ajout de données d'exportation de texte XRY +Un dossier d'exportation de fichiers texte XRY devrait ressembler à ceci: + +\image html xry_folder.png + +Pour ajouter des fichiers texte exportés: +-# Choisissez "XRY Text Export" parmi les types de source de données. +-# Naviguez jusqu'au dossier contenant les fichiers texte. + +\image html xry_dsp.png + +\section data_source_deletion Suppression de sources de données + +Depuis Autopsy 4.14.0, les sources de données peuvent être supprimées des cas. La suppression d'une source de données supprimera tous les fichiers associés à celle-ci, ainsi que tous les résultats de l'exécution des modules d'acquisition, les marquages et les données de chronologie. \ref reporting_page "Les rapports" ne seront pas supprimés, car la plupart ne sont pas associés à une source de données spécifique. Si une nouvelle source de données a été créée lors du traitement d'une source de données initiale (par le module \ref vm_extractor_page par exemple), cette nouvelle source de données sera également supprimée si son parent est supprimé. + +Pour supprimer une source de données, faites un clic-droit sur celle-ci dans l'\ref tree_viewer_page ou la \ref result_viewer_page et sélectionnez "Remove Data Source". Si le cas a été créé à l'origine avec une version d'Autopsy antérieure à 4.14.0, cette option sera désactivée. Après une boîte de dialogue de confirmation, le cas se fermera puis se rouvrira une fois la source de données supprimée. + +\image html data_source_delete.png + +*/ \ No newline at end of file diff --git a/docs/doxygen-user_fr/drone.dox b/docs/doxygen-user_fr/drone.dox new file mode 100644 index 0000000000..dffe1444f8 --- /dev/null +++ b/docs/doxygen-user_fr/drone.dox @@ -0,0 +1,35 @@ +/*! \page drone_page DJI Drone Analyzer (Analyseur de drone DJI) + +[TOC] + + +\section drone_overview Aperçu + +Le module "DJI Drone Analyzer" vous permet d'analyser les fichiers d'un drone. + +Actuellement, ce module fonctionne sur les images obtenues à partir de la carte SD interne des modèles de drones DJI suivants: +- Phantom 3 +- Phantom 4 +- Phantom 4 Pro +- Inspire 1 +- Inspire 2 +- Mavic Pro +- Mavic Air + +Le module trouvera les fichiers DAT et les traitera à l'aide de DatCon (https://datfile.net/DatCon/intro.html). + +\section drone_config Exécution du module + +Pour activer le module d'acquisition DJI Drone Analyzer, cochez la case dans \ref ingest_configure "l'écran de configuration des Ingest Modules". + +\section drone_results Affichage des résultats + +Les résultats sont affichés dans l'arborescence des résultats sous "Extracted Content". + +\image html gps_track_artifact.png + +Les résultats GPS peuvent également être consultés dans la fenêtre \ref geolocation_page et dans le rapport KML. + +\image html geolocation_drone_path.png + +*/ diff --git a/docs/doxygen-user_fr/email_parser.dox b/docs/doxygen-user_fr/email_parser.dox new file mode 100644 index 0000000000..86188e4ee5 --- /dev/null +++ b/docs/doxygen-user_fr/email_parser.dox @@ -0,0 +1,39 @@ +/*! \page email_parser_page Email Parser (Analyseur d’email) + +[TOC] + + +Qu'est ce que ça fait +======== + +Le module "Email Parser" identifie les fichiers au format MBOX, EML et PST en fonction des signatures de fichier, en extrait les e-mails, en ajoutant les résultats au Blackboard. Ce module ignore les fichiers connus et cré un artefact dans le Blackboard pour chaque message. Il ajoute les pièces jointes aux e-mails en tant que fichiers attachés. + +Cela permet à l'utilisateur d'identifier les communications par courrier électronique à partir du système en cours d'analyse. + +Configuration +======= + +Aucune configuration n'est requise. + + +Utilisation du module +====== +Explorez la partie "Results", "E-Mail Messages" de l'arborescence pour passer en revue les résultats de ce module. + +Paramètres d'intégration +------ +Aucun paramètre à l'exécution de ce module n'est requis. + +Voir les résultats +------ +Les résultats s'affichent dans la partie "Results", "E-Mail Messages" de l'\ref tree_viewer_page. + +\image html email_results.PNG + +Si un e-mail comporte une pièce jointe, l'onglet "Attachments" de la \ref content_viewer_page sera actif. + +\image html email_attachments.png + +Vous pouvez faire un clic-droit et sélectionner "View File in Directory" pour accéder au fichier joint. Vous pouvez également basculer vers l'onglet "Thumbnails" pour voir un aperçu de toutes les images en pièces jointes. + +*/ diff --git a/docs/doxygen-user_fr/encryption_detection.dox b/docs/doxygen-user_fr/encryption_detection.dox new file mode 100644 index 0000000000..a996078aa8 --- /dev/null +++ b/docs/doxygen-user_fr/encryption_detection.dox @@ -0,0 +1,43 @@ +/*! \page encryption_page Encryption Detection (Détection de chiffrement) + +[TOC] + + +\section encrypt_overview Aperçu + +Le module "Encryption Detection" recherche les fichiers qui pourraient être chiffrés en utilisant à la fois un calcul général d'entropie et des tests plus spécialisés pour certains types de fichiers. + +\section encrypt_running Lancement du module + +Les paramètres du module peuvent être configurés lors de l'exécution. Ces paramètres n'affectent que les tests basés sur l'entropie. + +\image html encrypt_module.png + +L'entropie minimale peut être réglée à une valeur supérieure ou inférieure, en fonction du nombre de faux positifs produits. Il existe également une option permettant d'exécuter le test uniquement sur des fichiers dont la taille est un multiple de 512, ce qui est utile pour trouver certains algorithmes de chiffrement. + +Le module recherche les types de chiffrement suivants: +
      +
    • Tout fichier qui a une entropie égale ou supérieure au seuil fixé dans les paramètres du module et qui correspond aux contraintes de taille de fichier +
    • Fichiers Office, PDF et fichiers de base de données Access protégés par mot de passe +
    • Volumes BitLocker +
    • SQLCipher (utilise l'entropie minimale des paramètres du module) +
    • VeraCrypt (utilise l'entropie minimale des paramètres du module) +
    + +\section encrypt_results Voir les résultats + +Les fichiers qui réussissent les tests de détection de chiffrement sont affichés dans la zone "Results" de l'arborescence sous "Encryption Detected" ou "Encryption Suspected". Généralement, si le test utilisé impliquait la recherche d'une +structure d'en-tête/fichier spécifique, le résultat sera "Encryption Detected" et le type de chiffrement sera affiché dans la colonne "Comment". Si le test était basé sur l'entropie du fichier, +le résultat sera "Encryption Suspected" et l'entropie calculée sera affichée dans la colonne "Comment". + +\image html encrypt_tree.png + +Chaque découverte de suspicion de chiffrement génère également un message dans la boîte de notification. Ceux-ci sont indiqués grâce à un triangle d'avertissement près du haut de l'écran. + +\image html encrypt_inbox.png + +La sélection de l'un des résultats de détection de chiffrement affiche l'entropie calculée du fichier. + +\image html encrypt_entropy.png + +*/ \ No newline at end of file diff --git a/docs/doxygen-user_fr/experimental.dox b/docs/doxygen-user_fr/experimental.dox new file mode 100644 index 0000000000..a952212f70 --- /dev/null +++ b/docs/doxygen-user_fr/experimental.dox @@ -0,0 +1,16 @@ +/*! \page experimental_page Experimental Module (Module expérimental) + +[TOC] + + +\section exp_overview Aperçu + +Le module "Experimental Module", comme son nom l'indique, contient du code qui ne fait pas encore partie de la version officielle d'Autopsy. Ces fonctionnalités expérimentales peuvent être utilisées mais peuvent être moins perfectionnées que d'autres fonctionnalités et auront moins de documentation. Ces modules peuvent être modifiés à tout moment. + +\section exp_setup Activation du module expérimental + +Pour commencer, allez dans Tools->Plugins et sélectionnez l'onglet "Installed", puis cochez la case à côté de "Experimental", cliquez sur "Activate" et passez les deux écrans suivants. Un redémarrage ne devrait pas être nécessaire. + +\image html experimental_plugins_menu.png + +*/ \ No newline at end of file diff --git a/docs/doxygen-user_fr/extension_mismatch.dox b/docs/doxygen-user_fr/extension_mismatch.dox new file mode 100644 index 0000000000..d537cf7047 --- /dev/null +++ b/docs/doxygen-user_fr/extension_mismatch.dox @@ -0,0 +1,42 @@ +/*! \page extension_mismatch_detector_page Extension Mismatch Detector (Détecteur de discordance d'extension) + +[TOC] + + +Qu'est ce que ça fait +======== + +Le module "Extension Mismatch Detector" utilise les résultats de l'identification du type de fichier et marque les fichiers dont l'extension n'est pas traditionnellement associée au type de fichier détecté. Il ignore les fichiers "connus" (NSRL). Vous pouvez personnaliser les types MIME et les extensions de fichier par type MIME dans "Tools", "Options", "File Extension Mismatch". + +Cela détecte les fichiers que quelqu'un tente peut-être de cacher. + +Configuration +======= +On peut ajouter et supprimer des types MIME dans la boîte de dialogue "Tools", "Options", "File Extension Mismatch", ainsi qu'ajouter et supprimer des extensions à des types MIME particuliers. +
    +\image html extension-mismatch-detected-configuration.PNG +
    + +Si vous souhaitez apporter votre contribution à la communauté, vous devrez télécharger votre fichier %APPDATA%\\autopsy\\dev\\config\\mismatch_config.xml mis à jour puis, au choix: +- Créer un "Fork" du dépôt Github d'Autopsy et copier le nouveau fichier dans le dossier src\\org\\sleuthkit\\autopsy\\fileextmismatch, avant de soumettre une "Pull Request" +- Attacher l'intégralité du fichier mismatch_config.xml à une "Issue" (problème relevé) sur Github. + +Utilisation du module +====== +Notez que vous pouvez obtenir beaucoup de faux positifs avec ce module. Vous pouvez ajouter vos propres règles à Autopsy pour réduire les retours indésirables. + +Paramètres d'intégration +------ + +Dans les paramètres des modules d'acquisition ("Configure Ingest Modules"), l'utilisateur peut choisir d'exécuter ce module sur tous les fichiers, tous les fichiers sauf les fichiers texte, ou uniquement les fichiers multimédias ou exécutables. En outre, l'utilisateur peut choisir d'ignorer tous les fichiers sans extension et d'ignorer tous les fichiers connus identifiés par le module "Hash Lookup" (module de recherche de hachage), s'il est activé. + +\image html extension-mismatch-detected-ingest-settings.PNG + + +Voir les résultats +------ +Les résultats apparaissent dans la zone Results de l'arborescence sous "Extension Mismatch Detected". + +\image html extension-mismatch-detected.PNG + +*/ diff --git a/docs/doxygen-user_fr/file_discovery.dox b/docs/doxygen-user_fr/file_discovery.dox new file mode 100644 index 0000000000..ffa6ac7c76 --- /dev/null +++ b/docs/doxygen-user_fr/file_discovery.dox @@ -0,0 +1,236 @@ +/*! \page discovery_page Discovery (Découverte de fichiers) + +[TOC] + +\section file_disc_overview Aperçu + +L'outil "Discovery" affiche des images, des vidéos, des documents ou des domaines qui correspondent à un ensemble de filtres configurés par l'utilisateur. Vous pouvez choisir comment regrouper et classer vos résultats afin de voir d'abord les données les plus pertinentes. + +\section file_disc_prereq Conditions préalables + +Nous vous suggérons d'exécuter tous les \ref ingest_page "modules d'acquisition" avant de lancer l'outil de découverte, mais si le temps est un facteur déterminant pour vous, les modules suivants sont les plus importants. Vous verrez un avertissement si vous ouvrez l'outil de découverte sans exécuter les modules \ref file_type_identification_page, \ref hash_db_page, et \ref EXIF_parser_page. + +Modules d'acquisition requis: +
      +
    • \ref file_type_identification_page pour les recherches d'images, de vidéos et de documents +
    • \ref recent_activity_page ou l'un des analyseurs mobiles (\ref android_analyzer_page, \ref ileapp_page, \ref aleapp_page) pour les recherches de domaines +
    + +Modules d'acquisition facultatifs: +
      +
    • \ref cr_ingest_module - Nécessaire pour utiliser le \ref file_disc_occur_filter +
    • \ref EXIF_parser_page - Nécessaire pour utiliser le \ref file_disc_user_filter +
    • \ref hash_db_page - Nécessaire pour utiliser le \ref file_disc_hash_filter et pour dédupliquer des fichiers +
    • \ref interesting_files_identifier_page - Nécessaire pour utiliser le \ref file_disc_int_filter +
    • \ref object_detection_page - Nécessaire pour utiliser le \ref file_disc_obj_filter +
    • \ref keyword_search_page - Améliore les résumés de documents +
    • \ref embedded_file_extractor_page - Permet d'afficher une image contenue dans un document +
    + +\section file_disc_run Exécution de "Discovery" + +Pour lancer l'outil de découverte, cliquez sur l'icône "Discovery" en haut de l'interface utilisateur d'Autopsy ou allez dans "Tools", "Discovery". Il y a trois étapes lors de la configuration de cet outil, qui vont du haut du panneau vers le bas: +
      +
    1. \ref file_disc_type "Choose result type" (Choisir le type de résultat) +
    2. \ref file_disc_filtering "Filter which images to show" (Filtrer les images à afficher) +
    3. \ref file_disc_grouping "Choose display settings" (Choisir les paramètres d'affichage) +
    + +\image html FileDiscovery/fd_setup.png + +Une fois que tout est configuré, utilisez le bouton "Search" en bas à droite pour afficher vos résultats. + +\image html FileDiscovery/fd_main.png + +\subsection file_disc_type Type de résultat + +La première étape consiste à choisir si vous souhaitez afficher des images, des vidéos, des documents ou des domaines. Les trois premiers (images, videos et documents) renverront les résultats des fichiers du type donné. Le type de fichier est déterminé par le type MIME du fichier, c'est pourquoi le module \ref file_type_identification_page doit être exécutée pour voir les résultats. Le basculement entre les types de résultats réinitialisera les filtres. + +\image html FileDiscovery/fd_fileType.png + +\subsection file_disc_filtering Filtres + +La deuxième étape consiste à sélectionner et configurer vos filtres. Les filtres disponibles varient en fonction du type de résultat. Pour la plupart des filtres, activez-les à l'aide de la case à cocher sur la gauche, puis cochez les cases à côté des options que vous souhaitez activer. Les boutons "Check All" et "Uncheck All" peuvent être utilisés pour cocher ou décocher toutes les options de la liste. Les résultats doivent passer tous les filtres activés pour être affichés. + +\subsubsection file_disc_size_filter Filtre "File Size" (taille du fichier) + +Le filtre "File Size" vous permet de restreindre la quantité de résultats. Les options sont différentes en fonction des différents types de fichiers - une très petite image peut faire moins de 16 Ko tandis qu'une très petite vidéo fait moins de 500 Ko. + +\image html FileDiscovery/fd_fileSizeFilter.png + +\subsubsection file_disc_ds_filter Filtre "Data Source" (source de données) + +Le filtre "Data Source" vous permet de restreindre les sources de données de votre cas à inclure dans les résultats. + +\image html FileDiscovery/fd_dataSourceFilter.png + +\subsubsection file_disc_occur_filter Filtre "Past Occurrences" (occurrences passées) + +Le filtre "Past Occurrences" utilise le \ref central_repo_page "référentiel central" et le module \ref hash_db_page "de recherche d'ensembles de hachage connus" (pour les recherches de type de fichier) afin de fixer à quel point une entrée doit être considérée comme commune/rare pour être incluse dans les résultats. Pour les recherches de type de fichier, l'option "Known (NSRL)" est désactivée par défaut, ce qui signifie que tout fichier correspondant au NSRL ou à une autre "liste blanche" de hachage ne sera pas affiché. + +\image html FileDiscovery/fd_pastOccur.png + +Les décomptes pour les autres options sont basés sur le nombre de sources de données dans votre référentiel central contenant une copie de ce fichier (basé sur le hachage) ou de ce domaine. Si un résultat n'apparaît que dans la source de données du cas actuel, il correspondra à "Unique (1)". S'il n'a été vu que dans quelques autres sources de données, il correspondra à "Rare (2-10)". Notez que peu importe le nombre de fois où un résultat apparaît dans chaque source de données - un résultat peut avoir vingt copies dans une source de données et être toujours "unique". + +\subsubsection file_disc_user_filter Filtre "Possibly User Created" (peut-être créé par l'utilisateur) + +Le filtre "Possibly User Created" limite les résultats aux fichiers soupçonnés d'être des images ou des vidéos brutes. + +\image html FileDiscovery/fd_userCreatedFilter.png + +Cela signifie que le fichier doit être associé à un résultat "User Content Suspected". Ceux-ci proviennent principalement du module \ref EXIF_parser_page. + +\image html FileDiscovery/fd_userContentArtifact.png + +\subsubsection file_disc_hash_filter Filtre "Hash Set" (jeu de hachage) + +Le filtre "Hash Set" restreint les résultats aux fichiers trouvés dans les ensembles de hachage sélectionnés. Seuls les ensembles de hachage notables qui ont des hits dans le cas actuel sont répertoriés. Voir la page \ref hash_db_page pour plus d'informations sur la création et l'utilisation d'ensembles de hachage. + +\image html FileDiscovery/fd_hashSetFilter.png + +\subsubsection file_disc_int_filter Filtre "Interesting Item" (élément intéressant) + +Le filtre "Interesting Item" restreint les résultats aux fichiers trouvés dans les ensembles de règles d'éléments intéressants sélectionnés. Seuls les ensembles de règles de fichiers intéressants qui ont des résultats dans le cas actuel sont répertoriés. Voir la page \ref interesting_files_identifier_page pour plus d'informations sur la création et l'utilisation d'ensembles de règles d'éléments intéressants. + +\image html FileDiscovery/fd_interestingItemsFilter.png + +\subsubsection file_disc_obj_filter Filtre "Object Detected" (objet détecté) + +Le filtre "Object Detected" restreint les résultats aux fichiers correspondant aux classificateurs sélectionnés. Seuls les classificateurs qui ont des résultats dans le cas actuel sont répertoriés. Notez qu'actuellement, la module d'acquisition intégré \ref object_detection_page ne fonctionne que sur les images, vous ne devez donc généralement pas utiliser ce filtre avec des vidéos. Voir la page \ref object_detection_page pour plus d'informations sur la configuration des classificateurs. + +\image html FileDiscovery/fd_objectFilter.png + +\subsubsection file_disc_parent_filter Filtre "Parent Folder" (dossier parent) + +Le filtre "Parent Folder" restreint le chemin sur lequel les fichiers peuvent se trouver. Ce filtre fonctionne différemment des autres en ce que les options individuelles n'ont pas à être sélectionnées - chaque règle qui a été entrée sera appliquée. + +\image html FileDiscovery/fd_parentFilter.png + +Vous pouvez entrer les chemins à inclure ("Include") et les chemins à ignorer ("Exclude"). Pour les deux, spécifiez ensuite si le chemin d'accès que vous avez entré est un chemin complet ("Full") ou un sous-chemin ("Substring"). Pour les correspondances de chemin complet, vous devrez inclure les barres obliques de début et de fin. Les correspondances de chemin complet sont également sensibles à la casse. + +Les options par défaut, illustrées ci-dessus, excluront tout fichier contenant un dossier "Windows" ou un dossier "Program Files" dans son chemin. Cela exclurait des fichiers comme "/Windows/System32/image1.jpg" mais n'exclurait pas "/Mes Images/Bay Windows/image2.jpg" parce que les barres obliques autour de "Windows" forcent la correspondance avec le nom exact du dossier. + +Voici un autre exemple. Cette règle a été créée avec "Full" et "Include" sélectionnés. + +\image html FileDiscovery/fd_parentEx2.png + +Cela correspond au fichier "/LogicalFileSet2/File Discovery/bird1.tif" mais aucune image située dans les sous-dossiers de "File Discovery". + +Lorsqu'il y a plusieurs options de chemin dans le filtre, elles seront appliquées comme suit: +
      +
    • Le chemin du fichier doit correspondre à toutes les règles "Exclude" pour apparaître +
    • Si des règles "Include" existent, le chemin du fichier doit correspondre à au moins une règle "Include" pour apparaître +
    + +Cela vous permet, par exemple, de créer des règles pour inclure à la fois les dossiers "Mes documents" et "Mes images". + +\subsubsection file_disc_prev_notable_filter Filtre "Previously Notable" (remarqué auparavant) + +Le filtre "Previously Notable" sert pour les recherches de domaines uniquement et est utilisé pour limiter les résultats aux seuls domaines qui ont déjà été marqués comme "Notable" dans le \ref central_repo_page. + +\image html FileDiscovery/fd_notableFilter.png + +\subsubsection file_disc_known_account_filter Filtre "Known Account Type" (type de compte connu) + +Le filtre "Known Account Type" sert pour les recherches de domaines uniquement et est utilisé pour limiter les résultats aux seuls domaines qui ont un type de compte connu. + +\image html FileDiscovery/fd_knownAccountFilter.png + +\subsubsection file_disc_result_filter Filtre "Result Type" (type de résultat) + +Le filtre "Result Type" sert pour les recherches de domaines uniquement et peut être utilisé pour restreindre les types de résultats Web dont les domaines peuvent provenir. + +\image html FileDiscovery/fd_domainResultFilter.png + +\subsubsection file_disc_date_filter Filtre "Date" + +Le filtre "Date" sert pour les recherches de domaines uniquement et limite la recherche aux domaines qui ont été accédés dans un laps de temps donné. Cette période peut être soit les N derniers jours (par rapport à la date actuelle), soit entre une date de début et/ou de fin spécifique. + +\image html FileDiscovery/fd_dateFilter.png + +\subsection file_disc_grouping Regroupement et tri + +Les dernières options concernent la manière dont vous souhaitez regrouper et trier vos résultats. + +\image html FileDiscovery/fd_grouping.png + +La première option vous permet de choisir le regroupement de niveau supérieur pour vos résultats et la deuxième option vous permet de choisir comment les trier. Les groupes apparaissent dans la colonne de gauche de la fenêtre de résultats. Notez que certaines des options de regroupement peuvent ne pas toujours apparaître - par exemple, le regroupement par occurrences passées ne sera présent que si le \ref central_repo_page est activé, et le regroupement par jeu de hachage ne sera présent que s'il y a des hits de jeux de hachage dans votre cas actuel. L'exemple ci-dessous montre les groupes créés à l'aide des options par défaut (recherche d'images, regrouper par taille de fichier, classer les groupes par nom de groupe): + +\image html FileDiscovery/fd_groupingSize.png + +Dans le cas de la taille du fichier et des occurrences passées, le classement par nom de groupe est basé sur l'ordre naturel du groupe (du plus grand au plus petit ou du plus rare au plus courant). Pour les autres groupes, ce sera par ordre alphabétique. Le classement des groupes par taille les triera en fonction du nombre de fichiers que contient chaque groupe, du plus grand au plus petit. Par exemple, ici, nous avons regroupé par ensemble d'éléments intéressants et avons ordonné les groupes en fonction de leur taille. + +\image html FileDiscovery/fd_groupingInt.png + +Le filtre des éléments intéressants n'était pas activé, donc la plupart des images se sont retrouvées dans le groupe "None", ce qui signifie qu'elles ne sont associées à aucun résultat de fichier intéressant. Le dernier groupe de la liste contient un fichier correspondant à deux ensembles de règles d'éléments intéressants. + +La dernière option de regroupement et de tri consiste à choisir comment trier les résultats au sein d'un groupe. Il s'agit de l'ordre des résultats sur le côté droit de la fenêtre de résultats après avoir sélectionné un groupe dans la colonne de gauche. Notez qu'en raison de la fusion des résultats ayant le même hachage dans ce panneau, le classement par nom de fichier, chemin ou source de données peut varier. Voir la section \ref file_disc_dedupe ci-dessous pour plus d'informations. + +\section file_disc_results Affichage des résultats + +\subsection file_disc_results_overview Aperçu + +Une fois que vous aurez sélectionné vos options et cliqué sur "Search", vous verrez une nouvelle fenêtre avec la liste des groupes sur le côté gauche. La sélection de l'un de ces groupes affichera les résultats de ce groupe sur le côté droit. La sélection d'un résultat fera apparaître un panneau affichant plus de détails sur chaque instance de ce résultat. Vous pouvez soulever et abaisser manuellement ce panneau à l'aide des grandes flèches sur le côté droit du séparateur. + +Si vos résultats sont des images, vous verrez des miniatures pour chaque image dans la zone supérieure du panneau de droite. + +\image html FileDiscovery/fd_resultGroups.png + +Si vos résultats sont des vidéos, chaque résultat affichera quatre vignettes de la vidéo. + +\image html FileDiscovery/fd_videos.png + +Si vos résultats sont des documents, vous verrez une partie du texte du document. Si le module \ref embedded_file_extractor_page a trouvé des images dans le document, vous verrez une vignette de la plus grande d'entre elles affichée sur le côté droit avec un décompte du nombre d'images extraites du document. + +\image html FileDiscovery/fd_documents.png + +Si vos résultats sont des domaines, vous verrez des informations sur chaque domaine. Si une image est associée à ce domaine, elle sera affichée à droite. + +\image html FileDiscovery/fd_domains.png + +Pour les recherches d'images, de vidéos et de documents, lorsque vous sélectionnez un résultat en haut du panneau de droite, vous verrez le chemin d'accès au(x) fichier(s) correspondant(s) dans le panneau "Instances" sous les miniatures. Il peut y avoir plus d'une instance de fichier associée à un résultat - voir la section \ref file_disc_dedupe ci-dessous. Vous pouvez cliquer avec le bouton droit sur les fichiers dans le panneau des instances pour utiliser la plupart des options disponibles dans la \ref result_viewer_page. + +\image html FileDiscovery/fd_instanceContext.png + +La partie inférieure du panneau est identique à la \ref content_viewer_page standard et affiche les données qui correspondent à l'instance du fichier sélectionné dans le milieu du panneau. + +Pour les recherches de domaines, lorsque vous sélectionnez un domaine en haut du panneau de droite, vous verrez une zone de détails qui est une variante de la \ref content_viewer_page. Le premier onglet de cette zone de détails affiche une chronologie ("Timeline") simple - la sélection d'une date affichera tous les résultats de cette date au centre du panneau, avec les détails du résultat sélectionné sur la droite. Les autres onglets (Web Bookmarks, Web Cookies, etc...) afficheront les résultats du type sélectionné avec une liste de résultats à gauche et plus de détails à droite. Vous pouvez cliquer avec le bouton droit sur les résultats pour utiliser la plupart des options disponibles dans la \ref result_viewer_page. + +\image html FileDiscovery/fd_domainDetails.png + +\subsection file_disc_dedupe Déduplication + +Cette section s'applique uniquement aux recherches d'images, de vidéos et de documents. + +En supposant que le module \ref hash_db_page ait été exécuté, tous les fichiers d'un groupe de résultats avec le même hachage seront fusionnés sous une seule instance. Le chemin du fichier vers l'une des instances sera affiché avec une note telle que "and 1 more" (et 1 de plus) indiquant le nombre de doublons trouvés. La sélection du fichier affichera chaque instance dans la section centrale du panneau. + +\image html FileDiscovery/fd_dupeEx.png + +Cliquer sur une instance particulière chargera les données de ce fichier dans la zone de visualisation de contenu en bas. + +Notez que les fichiers de différents groupes ne seront pas fusionnés ou n'apparaîtront pas dans la liste des instances les uns des autres. Par exemple, si vous choisissez de regrouper par dossier parent et que vous avez deux instances d'un fichier avec le même hachage mais dans des dossiers différents, chacune apparaîtra une fois dans son dossier parent. Le regroupement par taille de fichier (par défaut) fusionnera toujours chaque instance du même fichier. + +\subsection file_disc_icons Icônes d'état + +Cette section s'applique uniquement aux recherches d'images, de vidéos et de documents. + +Un certain nombre d'icônes peuvent être affichées en bas à droite des vignettes pour aider à souligner les résultats notables. Le survol de l'icône affichera un message expliquant pourquoi l'icône est présente. Dans l'image ci-dessous, l'icône jaune est présente car le fichier est associé à un ensemble d'éléments intéressant. + +\image html FileDiscovery/fd_icon.png + +La plupart des icônes correspondent à ce qui serait affiché dans la colonne "S" de la \ref result_viewer_page normale. + +| Icône | Usage | +|-------|------| +\image html FileDiscovery/yellow-circle-yield.png "" | \ref interesting_files_identifier_page "Correspondance avec un jeu de fichiers intéressants" ou un \ref tagging_page "marquage de fichier" normal +\image html FileDiscovery/red-circle-exclamation.png "" | \ref hash_db_page "Correspondance avec un jeu de hachage" notable ou un \ref tagging_page "marquage de fichier" notable +\image html FileDiscovery/file-icon-deleted.png "" | Fichier supprimé (chaque instance est supprimée) + + +\subsection file_disc_paging Pagination + +Si le groupe que vous sélectionnez a de nombreux résultats, les résultats seront divisés en pages. Vous pouvez utiliser les flèches gauche et droite pour vous déplacer entre les pages ou saisir le numéro de page à laquelle vous souhaitez accéder. Vous pouvez ajuster le nombre de résultats par page à l'aide de la liste déroulante en haut à droite. + +\image html FileDiscovery/fd_paging.png + +*/ \ No newline at end of file diff --git a/docs/doxygen-user_fr/file_export.dox b/docs/doxygen-user_fr/file_export.dox new file mode 100644 index 0000000000..a352a888a7 --- /dev/null +++ b/docs/doxygen-user_fr/file_export.dox @@ -0,0 +1,72 @@ +/*! \page file_export_page File Export (Export de fichiers) + +[TOC] + + +\section file_export_overview Aperçu + +S'il est activé, l'exportateur de fichiers s'exécutera après chaque tâche d'\ref auto_ingest_page et exportera tous les fichiers de cette source de données qui correspondent aux règles fournies. La plupart des utilisateurs n'auront pas besoin d'utiliser cette fonctionnalité - les analystes peuvent ouvrir les cas d'acquisition automatique dans un "Examiner Node" et y consulter les données. + +\section file_export_setup Configuration + +Après avoir activé l'exportateur de fichiers, la première chose à faire est de définir deux dossiers de sortie. Le "Files Folder" est le répertoire de base de tous les fichiers exportés et le "Reports Folder" est le répertoire de base des rapports (listes de chaque fichier exporté pour chaque source de données). Si possible, il est préférable d'utiliser des chemins UNC. + +\image html AutoIngest/file_exporter_main.png + +Ensuite, vous établissez des règles pour les fichiers que vous souhaitez exporter. Chaque règle doit avoir un nom et au moins un ensemble de conditions. Si plusieurs conditions sont définies, toutes les conditions doivent être vraies pour exporter le fichier. Lorsque vous avez terminé de configurer votre règle, appuyez sur le bouton "Save" pour la sauvegarder. Vous verrez la nouvelle règle dans la liste sur le côté gauche. + +Toutes les règles enregistrées seront exécutées sur chaque source de données. Il n'y a aucun moyen de définir une règle comme inactive, donc si vous créez une règle et que vous ne voulez pas qu'elle s'exécute, vous devrez utiliser le bouton "Delete Rule" pour la supprimer. + +Vous devrez exécuter les modules \ref hash_db_page et \ref file_type_identification_page pour utiliser l'exportateur de fichiers. Vous devrez peut-être exécuter des modules supplémentaires en fonction des attributs de vos règles. + +\subsection file_exporter_mime MIME Type (Type MIME) + +La première condition est basée sur le type MIME. Pour l'activer, cochez la case avant "MIME Type", puis sélectionnez un type MIME dans la liste et choisissez si vous voulez le faire correspondre ou non. Pour le moment, il est impossible de sélectionner plusieurs types MIME. Ce qui suit montre une règle qui correspondra à toutes les images PNG. + +\image html AutoIngest/file_export_png.png + +\subsection file_exporter_size File Size (Taille de fichier) + +La deuxième condition est basée sur la taille du fichier. Vous pouvez choisir une taille de fichier (en utilisant la liste de droite pour modifier les unités), puis sélectionner si les fichiers doivent être plus grands, plus petits, égaux ou non à cette taille. Ce qui suit montre une règle qui correspondra aux fichiers de texte brut de plus de 1 Ko. + +\image html AutoIngest/file_export_size.png + +\subsection file_exporter_attributes Attributes (Attributs) + +La troisième condition est basée sur les artefacts et les attributs du Blackboard, c'est ainsi qu'Autopsy stocke la plupart de ses résultats d'analyse. Un fichier sera exporté s'il est lié à un attribut correspondant. L'utilisation de ce type de condition exigera une certaine familiarité avec la manière exacte dont ces attributs sont créés et les données que nous nous attendons à y voir. Il y a quelques informations de base dans la documentation Sleuthkit. Vous devrez probablement également ouvrir un fichier de base de données d'Autopsy pour vérifier les types d'attributs exacts utilisés pour contenir les données qui vous intéressent. + +Pour créer une condition d'attribut, sélectionnez le type d'artefact, puis le type d'attribut qui vous intéresse. Sur la ligne suivante, vous pouvez entrer une valeur et définir la relation que vous voulez qu'ait l'attribut (égal, pas égal, supérieur/inférieur). Toutes les options n'auront pas de sens avec tous les types de données. Utilisez ensuite le bouton "Add Attribute" pour l'ajouter à la liste d'attributs. Si vous faites une erreur, utilisez le bouton "Delete Attribute" pour l'effacer. Ce qui suit montre une règle qui exportera tous les fichiers étant ressortis d'une recherche de mots-clés avec le mot "bomb". + +\image html AutoIngest/file_export_keyword.png + +Il est possible de paramétrer une correspondance plus générale sur les artefacts. Supposons que vous vouliez exporter tous les fichiers que le module \ref encryption_page a marqué comme "Encryption Suspected". Ces fichiers auront un artefact TSK_ENCRYPTION_SUSPECTED avec un seul attribut "TSK_COMMENT" qui contient l'entropie calculée pour chaque fichier. Dans ce cas, nous pouvons utiliser l'opérateur "non égal" avec la chaîne que nous ne nous attendons pas à trouver dans le champs TSK_COMMENT, afin de modifier efficacement la condition en "possède un artefact TSK_ENCRYPTION_SUSPECTED associé." + +\image html AutoIngest/file_export_encrypton.png + +\section file_export_output Export + +Les fichiers exportés se trouvent dans le dossier qui a été spécifié lors de l'étape de \ref file_export_setup, puis organisés au niveau du dossier racine par l'identifiant du périphérique de la source de données. + +\image html AutoIngest/file_export_dir_structure.png + +Les fichiers exportés sont nommés avec leur hachage et stockés dans des sous-dossiers basés sur les parties de ce hachage, pour éviter qu'un seul dossier ne devienne très volumineux. + +\image html AutoIngest/file_export_file_loc.png + +Les fichiers de rapport se trouvent également dans les sous-dossiers sous l'identifiant de l'appareil, puis le nom de la règle. + +\image html AutoIngest/file_export_json_loc.png + +Ce fichier json contiendra des informations sur le fichier et tous les artefacts associés faisant partie des règles de conditions. +\verbatim +{"7C89F280C337AB3E997D20527B8EC6F8":{"Filename":"\\\\WIN-4913\\AutopsyData\\FileExportFiles\\37567\\text-plain\\7C\\89\\F2\\80\\7C89F280C337AB3E997D20527B8EC6F8", +"Type":"text/plain","MD5":"7C89F280C337AB3E997D20527B8EC6F8","File data":{"Modified":["0000-00-00 00:00:00"],"Changed":["0000-00-0000:00:00"], +"Accessed":["0000-00-00 00:00:00"],"Created":["0000-00-00 00:00:00"],"Extension":["txt"],"Filename":["File about explosions.txt"],"Size":["54"], +"Source Path":["/kwTest_2019_03_14_12_53_33//File about explosions.txt"],"Flags (Dir)":["Allocated"],"Flags (Meta)":["Allocated"], +"Mode":["r---------"],"User ID":["0"],"Group ID":["0"],"Meta Addr":["0"],"Attr Addr":["1-0"],"Dir Type":["r"],"MetaType":["r"], +"Known":["unknown"]},"TSK_KEYWORD_HIT":{"TSK_KEYWORD":["bomb"]}, +"TSK_KEYWORD_HIT":{"TSK_KEYWORD_PREVIEW":["keyword search for the word bomb in this file.\n\n\n------"]}, +"TSK_KEYWORD_HIT":{"TSK_SET_NAME":["bomb"]},"TSK_KEYWORD_HIT":{"TSK_KEYWORD_SEARCH_TYPE":["0"]}}} +\endverbatim + +*/ \ No newline at end of file diff --git a/docs/doxygen-user_fr/file_search.dox b/docs/doxygen-user_fr/file_search.dox new file mode 100644 index 0000000000..fa6b210f1f --- /dev/null +++ b/docs/doxygen-user_fr/file_search.dox @@ -0,0 +1,44 @@ +/*! \page file_search_page Recherche de fichier + +[TOC] + + +\section about_file_search À propos de la recherche de fichiers +L'outil de recherche de fichiers est accessible à partir du menu Tools ou en faisant un clic droit sur un nœud de source de données dans l'arborescence de répertoires. En utilisant la recherche de fichiers, vous pouvez spécifier, filtrer et afficher les répertoires et les fichiers que vous souhaitez voir à partir des images dans le cas actuellement ouvert. Les résultats de la recherche de fichiers seront renseignés dans une toute nouvelle table de résultats sur le côté droit. + +Remarque: Actuellement, la recherche de fichiers ne prend pas en charge les expressions régulières. La fonction de recherche par mot-clé d'Autopsy prend en charge les expressions régulières et peut être utilisée pour rechercher des fichiers et/ou des répertoires par nom. + +\section how_to_open_file_search Comment ouvrir la recherche de fichiers + +Pour ouvrir la recherche de fichiers, vous pouvez effectuer l'une des opérations suivantes: +Cliquez avec le bouton droit sur une source de données et choisissez "Open File Search by Attributes". +\image html open-file-search-component-1.PNG +ou sélectionnez le menu "Tools", "File Search by Attributes". +\image html open-file-search-component-2.PNG + +\section how_to_use_file_search Comment utiliser la recherche de fichiers + +Il existe plusieurs catégories que vous pouvez utiliser pour filtrer et afficher les répertoires et les fichiers dans les images du cas ouvert actuellement. +Ces catégories sont: +\li Name: +Recherchez tous les fichiers et répertoires dont le nom contient le modèle donné. +Remarque: il ne prend pas en charge la correspondance d'expressions régulières et de mots clés. +\li Size: +Recherchez tous les fichiers et répertoires dont la taille correspond au modèle donné. Le motif peut être "equal to" (égal à), "greater than" (supérieur à) et "less than" (inférieur à). L'unité pour la taille peut être "Octet(s)", "Ko", "Mo", "Go" et "To". +\li MIME Type: +Recherchez tous les fichiers avec le type MIME sélectionné. Plusieurs types peuvent être utilisés en maintenant SHIFT ou CTRL pendant la sélection. +\li MD5: +Recherchez tous les fichiers avec le hachage MD5 donné. +\li Date: +Recherchez tous les fichiers et répertoires dont la propriété "date" est comprise dans la plage de dates indiquée. Les propriétés de date sont "Modified Date" (Date de modification), "Accessed Date" (Date d'accès), "Changed Date" (Date de changement), and "Created Date" (Date de création). Vous devez également spécifier le fuseau horaire de la date donnée. +\li Known Status: +Recherchez tous les fichiers et répertoires dont l'état est reconnu comme "Unknown" (Inconnu), "Known" (Connu) ou "Notable" (Connu défavorablement). Pour plus d'informations sur ces états, consultez la page \ref hash_db_page. +Pour utiliser l'un de ces filtres, cochez la case à côté de la catégorie et cliquez sur le bouton "Search" pour démarrer le processus de recherche. Le résultat apparaîtra dans la visionneuse de résultats. +\li Data Source: +Rechercher uniquement dans la source de données spécifiée au lieu de l'ensemble du cas. Notez que plusieurs sources de données peuvent être sélectionnées en maintenant MAJ ou CTRL pendant la sélection. + +Voici un exemple fictif où nous essayons d'obtenir tous les répertoires et fichiers dont le nom contient "hello", ayant une taille supérieure à 1000 octets, étant au format JPEG, ayant été créé entre le 06/01/2018 et +le 06/08/2017 (dans le fuseau horaire GMT-5), étant un fichier inconnu (Unknown), ayant un hachage de 1127F348BD4303A4C3D1D587C807B49F et apparaîssant dans la source de données "image3.vhd": +\image html example-of-file-search.PNG + +*/ \ No newline at end of file diff --git a/docs/doxygen-user_fr/filetype.dox b/docs/doxygen-user_fr/filetype.dox new file mode 100644 index 0000000000..f1f49bad13 --- /dev/null +++ b/docs/doxygen-user_fr/filetype.dox @@ -0,0 +1,46 @@ +/*! \page file_type_identification_page File Type Identification (Identification du type de fichier) + +[TOC] + + +Qu'est ce que ça fait +======== + +Le module "File Type Identification" identifie les fichiers en fonction de leurs signatures internes et ne repose pas sur les extensions de fichier. Autopsy utilise la bibliothèque Tika pour faire la principale détection d'identification de fichier, et ceci peut être personnalisable avec des règles définies par l'utilisateur. + +Vous devez activer ce module car de nombreux autres modules dépendent de ses résultats pour déterminer s'ils doivent analyser un fichier. Voici quelques exemples de modules dépendant de ce dernier: + +- \subpage extension_mismatch_detector_page +- \subpage keyword_search_page + + +Configuration +======= + +Vous n'avez pas besoin de configurer quoi que ce soit pour ce module, sauf si vous souhaitez définir vos propres types. Pour définir vos propres types, allez dans le panneau "Tools", "Options", "File Types". + +À partir de là, vous pouvez définir des règles basées sur l'offset de la signature et si la signature est une séquence d'octets d'une chaîne ASCII. + +\image html filetype.PNG + +Utilisation du module +====== + +Paramètres d'intégration +------ +Il n'y a pas de paramètres d'exécution pour ce module lorsque vous l'exécutez sur +une source de données. Toutes les règles définies par l'utilisateur et celles de Tika sont toujours appliquées. + + +Voir les résultats +------ + +Les résultats apparaissent dans l'arborescence, sous Views->File Types->By MIME Type. + +\image html mime-type-tree.PNG + +Notez que seuls les types MIME définis par l'utilisateur sous la forme (type de fichier)/(sous-type de fichier) seront affichés dans l'arborescence. + +Pour voir le type d'un fichier particulier, affichez l'onglet "File Metadata" en bas à droite lorsque vous accédez au fichier. Vous devriez voir une page qui mentionne le type de ce fichier. + +*/ diff --git a/docs/doxygen-user_fr/footer.html b/docs/doxygen-user_fr/footer.html new file mode 100644 index 0000000000..97da7f61f0 --- /dev/null +++ b/docs/doxygen-user_fr/footer.html @@ -0,0 +1,7 @@ +
    +

    Copyright © 2012-2021 Basis Technology. Généré le $date
    +Cette documentation est sous licence +Creative Commons Attribution-Share Alike 3.0 United States License. +

    + + diff --git a/docs/doxygen-user_fr/geolocation.dox b/docs/doxygen-user_fr/geolocation.dox new file mode 100644 index 0000000000..ced4742321 --- /dev/null +++ b/docs/doxygen-user_fr/geolocation.dox @@ -0,0 +1,152 @@ +/*! \page geolocation_page Geolocation (Géolocalisation) + +[TOC] + + +\section geo_overview Aperçu + +La fenêtre "Geolocation" affiche les artefacts qui ont des attributs de longitude et de latitude comme points de cheminement sur une carte. En pratique, lorsque l'accès aux serveurs de tuiles de carte en ligne peut ne pas être disponible, la fenêtre de géolocalisation prend en charge les sources de données de tuiles de carte hors ligne. + +\image html geo_main.png + +\section geo_usage Usage + +Pour ouvrir la fenêtre de géolocalisation, cliquez sur le bouton "Geolocation" près du haut de la fenêtre principale, ou allez sur "Tools" puis sélectionnez "Geolocation". + +\subsection geo_navigation Usage général + +Vous pouvez déplacer la carte en cliquant et en faisant glisser, et zoomer à l'aide de la molette de la souris ou du curseur en bas à gauche de la carte. Si une tuile de carte n'est pas disponible, la tuile apparaîtra grise mais les points géocodés seront toujours affichés. Cela est susceptible de se produire lors de la modification de la valeur par défaut des \ref geo_map_options. Différents types de points géocodés seront affichés dans différentes couleurs. Vous pouvez utiliser la touche en bas à gauche pour identifier facilement le type de chaque point géocodé. Certains types utiliseront également différentes icônes sur la carte. Par exemple, les points de suivi individuels seront affichés sous forme de cercles plus petits. La piste entière sera mise en surbrillance lors de la sélection d'un point de piste individuel. + +\image html geo_track_points.png + +Vous pouvez faire un clic gauche sur un point géocodé pour mettre ce point en surbrillance et afficher une fenêtre contextuelle de détails dans le coin supérieur droit de la carte. La fenêtre contextuelle des détails sera mise à jour lorsque vous cliquez sur différents points géocodés. Les données affichées varient en fonction du type de point géocodé. Par exemple, s'il s'agit d'un signet GPS: + +\image html geo_details_bookmark.png + +Ou bien s'il s'agit d'une image avec des coordonnées GPS trouvées par le module \ref EXIF_parser_page : + +\image html geo_details.png + +Vous pouvez également faire un clic droit sur un point géocodé pour afficher un menu similaire à ce que vous verriez dans la \ref result_viewer_page. + +\image html geo_context_menu.png + +\subsection geo_filter Filtes + +Les filtres sont affichés sur le côté gauche de l'écran. Le filtre supérieur vous permet de filtrer les points de cheminement en fonction de l'horodatage. Si cette option est activée, vous ne verrez que les points géocodés avec un horodatage dans les N jours du point géocodé le plus récent (pas la date actuelle). Lorsque vous utilisez ce filtre, vous pouvez également choisir si vous souhaitez voir les points géocodés sans horodatage. + +\image html geo_filter_time.png + +Le deuxième filtre vous permet d'afficher les points géocodés uniquement pour les sources de données sélectionnées. Notez que seules les sources de données contenant des données de géolocalisation sont affichées ici. + +\image html geo_filter_datasource.png + +Le dernier filtre vous permet d'afficher uniquement certains types de points géocodés. Le nombre à côté du type indique le nombre de points de ce type dans votre cas. + +\image html geo_filter_type.png + +Une fois que vous avez terminé la configuration de vos filtres, cliquez sur le bouton "Apply" en haut du panneau des filtres. + +Si vous le souhaitez, le panneau de filtre peut être masqué en cliquant sur l'onglet vertical "Filters" sur le bord supérieur droit du panneau de filtre. Cliquer sur cet onglet une seconde fois restaurera le panneau des filtres. + +\subsection geo_report Générer un rapport + +Vous pouvez générer un rapport KML en utilisant le bouton "KML Report" dans le coin inférieur droit de la fenêtre. Le rapport n'inclura que les points géocodés actuellement visibles et se trouvera dans le dossier "Reports" de votre cas. + +\image html geo_report.png + +Comme avec les autres \ref reporting_page "modules de rapports", le rapport généré apparaîtra sous la section "Reports" dans l'\ref tree_viewer_page. Notez que vous pouvez également utiliser le module de rapport \ref report_kml pour générer un rapport contenant toutes les données de géolocalisation dans le cas. + +\section geo_map_options Options de tuiles de carte + +

    La fenêtre de géolocalisation d'Autopsy prend en charge plusieurs options de source de données de tuiles de carte. La source de données des tuiles de carte peut être modifiée +dans le panneau "Geolocation" de la boîte de dialogue Options. Il existe quatre options pour les données de tuiles de géolocalisation, dont deux peuvent être utilisées hors ligne. +

      +
    • Default online tile server +
        +
      • La source de données de tuiles de la fenêtre de géolocalisation par défaut est le serveur Microsoft Virtual Earth https://www.bing.com/maps. +
      +
    • OpenStreetMap server +
        +
      • Vous pouvez spécifier l'adresse d'un serveur de tuiles OSM. Une liste des serveurs de tuiles en ligne peut être trouvée ici: https://wiki.openstreetmap.org/wiki/Tile_servers. +Les serveurs de tuiles peuvent avoir des restrictions qui empêchent Autopsy d'accéder à leurs tuiles. Si l'URL des tuiles est quelque chose de la forme "http://tiles.example.org/${z}/${x}/${y}.png", +alors vous devrez entrer "http://tiles.example.org" dans le panneau des options. + +\image html geo_openstreetmap.png +
      +
    • OpenStreetMap zip file +
        +
      • Permet l'utilisation hors ligne d'un fichier zip d'images de tuiles OSM +
      • Les détails sur la façon de générer des fichiers zip de tuiles sont abordés \ref geo_generate_zip "ci-dessous". +
      +
    • MBTiles file +
        +
      • Permet l'utilisation hors ligne d'un fichier MBTiles contenant des tuiles matricielles. +
      • Les fichiers de tuiles matricielles MBTiles peuvent être téléchargés de OpenMapTiles. +
      • OpenMapTiles fournit des téléchargements de fichiers MBTile pour des zones aussi grandes que la planète entière à aussi petites que des régions de pays. +
      • Pour chacune de ces régions, au moins quatre MBTiles sont disponibles au téléchargement, assurez-vous de télécharger l'un des fichiers "Raster Tile", +pas les "Vector Tiles". +
      +
    + +\subsection geo_generate_zip Utilisation de Maperative pour générer des fichiers zip d'images de tuiles + +Maperative est un outil pour dessiner des cartes, mais il peut également être utilisé pour créer des images de tuiles. Les téléchargements et les documentations de Maperative peuvent être trouvés sur http://maperitive.net/ . + +Par défaut, Maperative utilise un serveur de tuiles en ligne pour générer une carte. Pour une utilisation hors ligne, vous pouvez utiliser un extrait de données brutes OpenStreetMap. + + +\subsubsection geo_generate_tile_image Génération de fichiers zip d'images de tuiles à l'aide de n'importe quelle source de données cartographiques: +
      +
    1. Téléchargez et exécutez Maperative. +
    2. Centrez et zoomez sur une zone d'intérêt. Plus la zone est grande, plus il y aura de tuiles générées. Des tuiles seront générées pour la zone visible dans la fenêtre de la carte. +
    3. Choisissez si vous souhaitez utiliser les niveaux de zoom par défaut ou personnalisés. Les niveaux de zoom dans Mapertive commencent à 1. Au fur et à mesure que le niveau de zoom augmente, la quantité de tuiles générées ainsi que le détail de chaque tuile augmentent également. La création de tuiles, en particulier pour les zones très peuplées, peut prendre du temps. Veuillez être patient avec l'une ou l'autre des méthodes. +
        +
      • Pour générer des tuiles à l'aide des niveaux de zoom par défaut, sélectionnez Tools->Generate Tiles + +\image html geo_gen_tiles.png + +Maperative générera des tuiles pour les niveaux de zoom en fonction de la zone d'intérêt et du niveau de zoom. Par exemple, si vous commencez à effectuer un zoom arrière complet, vous générerez probablement les niveaux 1 à 10. Si vous commencez à zoomer, vous pouvez avoir les niveaux 10 à 14. + +
      • Maperative fournit une interface en ligne de commande qui vous permet de générer des tuiles pour des niveaux de zoom spécifiques. Les commandes peuvent être exécutées dans le champ de texte de l'invite de commande au bas de la fenêtre Maperative. Pour une liste complète des commandes, consultez la documentation de Maperative ou http://maperitive.net/docs/. La commande generate-tiles peut être utilisée pour générer des tuiles pour la zone visible dans la fenêtre de la carte. Pour plus de détails sur generate-tiles voir la documentation fournie avec Maperative ou http://maperitive.net/docs/Commands/GenerateTiles.html. Voici un exemple de commande pour générer des tuiles pour les niveaux de zoom 2 à 3 dans le dossier Tiles: +\verbatim generate-tiles minzoom=2 maxzoom=3 tilesdir=C:\Tiles \endverbatim + +\image html geo_command_line.png + +
      +
    4. Pour une utilisation avec Autopsy, les images de tuiles générées doivent être dans un fichier zip. Pour créer un zip de tuiles à utiliser dans Autopsy, compresser tous les dossiers dans le répertoire de sortie du fichier de tuiles. N'incluez pas le répertoire parent, mais uniquement les dossiers numérotés qu'il contient. Si vous utilisez l'option de la barre de menus ou si vous n'avez pas spécifié de dossier dans votre commande, les tuiles générées seront situées dans le dossier d'installation <Maperative>\\Tiles. + +\image html geo_tile_folder.png + +Assurez-vous de compresser uniquement le contenu du dossier, pas le dossier de niveau supérieur. +
    + + +\subsubsection geo_add_ds Ajout d'une source de données à Maperative + +Maperative peut être utilisé pour générer des tuiles en utilisant des extraits de données brutes d'OpenStreetMap. Les fichiers d'extraits de données (*.osm ou *.osm.pbf) peuvent être téléchargés à partir de divers emplacements. Voir https://wiki.openstreetmap.org/wiki/Planet.osm pour une liste d'emplacements. Le serveur de téléchargement de Geofabrik a des extraits gratuits de données OpenStreetMap pour de nombreuses régions. Lors de l'utilisation d'extraits de données brutes OSM dans Maperative, il est recommandé d'utiliser des fichiers plus petits (.osm). + +Pour ajouter une source de données à Maperative: +
      +
    1. Sélectionnez dans la barre de menu File->Open Map Source... + +\image html geo_add_ds.png + +
    2. La nouvelle source de données apparaîtra dans le coin inférieur droit de la fenêtre dans la liste "Map Sources". +
    3. Pour désactiver une entrée de "Map Sources", sélectionnez la source de carte dans la liste et cliquez sur le bouton X. +
    + +\subsubsection geo_merge_osm Fusion d'extraits de données brutes OSM + +Pour faciliter l'utilisation, les utilisateurs peuvent s'ils le souhaitent fusionner des extraits de données brutes OSM. OSMConvert est un outil qui peut être utilisé pour fusionner des extraits de données brutes OSM. + +Pour fusionner deux extraits de données brutes OSM country1.osm.pbf et country2.osm.pbf, utilisez les commandes suivantes. Notez que cela suppose que osmcovert et les fichiers se trouvent dans le même répertoire; s'ils ne le sont pas, assurez-vous d'utiliser des chemins complets. +\verbatim +osmconvert country1.osm.pbf -o=country1.o5m +osmconvert country2.osm.pbf -o=country2.o5m +osmconvert country1.o5m country2.o5m -o=together.o5m +osmconvert together.o5m -o=together.osm.pbf +\endverbatim + + +*/ \ No newline at end of file diff --git a/docs/doxygen-user_fr/gpx.dox b/docs/doxygen-user_fr/gpx.dox new file mode 100644 index 0000000000..d3044a6496 --- /dev/null +++ b/docs/doxygen-user_fr/gpx.dox @@ -0,0 +1,52 @@ +/*! \page gpx_page GPX Parser (Analyseur GPX) + +[TOC] + + +\section gpx_overview Aperçu + +Le module "GPX Parser" vous permettent d'importer des données GPS à partir d'un fichier GPX. Vous trouverez ici des informations sur le format GPX. Voici un court exemple de fichier GPX: + +\verbatim + + + + + + Garmin International + + + + + Example GPX Document + + + 4.46 + + + + 4.94 + + + + 6.87 + + + + + +\endverbatim + +\section gpx_config Exécution du module + +Pour activer le module d'acquisition "GPX Parser", cochez la case dans \ref ingest_configure "l'écran de configuration des modules d'acquisition" ("Configure Ingest Modules"). + +\section gpx_results Affichage des résultats + +Les résultats sont affichés dans l'arborescence sous "Extracted Content". Les types de données GPX "wptType", "rteType" et "trkType" produisent respectivement des résultats de type GPS Bookmarks (signet), GPS Route (route) et GPS Track (traces). + +\image html gpx_results.png + +Les résultats GPS peuvent également être consultés dans la fenêtre \ref geolocation_page et dans le rapport KML. + +*/ \ No newline at end of file diff --git a/docs/doxygen-user_fr/hashdb_lookup.dox b/docs/doxygen-user_fr/hashdb_lookup.dox new file mode 100644 index 0000000000..9505e8b70b --- /dev/null +++ b/docs/doxygen-user_fr/hashdb_lookup.dox @@ -0,0 +1,112 @@ +/*! \page hash_db_page Hash Lookup (Recherche de hachage) + +[TOC] + + +Qu'est ce que ça fait +======== + +Le module "Hash Lookup" calcule les valeurs de hachage MD5 pour les fichiers et recherche ces valeurs de hachage dans une base de données pour déterminer si le fichier est notable, connu (en général), inclus dans un ensemble spécifique de fichiers ou inconnu. Les hachages SHA-256 sont également calculés, bien qu'ils ne soient pas utilisés dans les recherches de jeux de hachage. + + +Configuration +======= +L'onglet "Hash Sets" du panneau Options vous permet de définir et de mettre à jour les informations de votre jeu de hachage. Les jeux de hachage sont utilisés pour identifier les fichiers qui sont connus ("Known"), notables ("Notable") ou sans changement ("No Change"). +\li "Known" : ce sont des fichiers connus qui peuvent être ignorés en toute sécurité. Cet ensemble de fichiers comprend fréquemment des fichiers de système d'exploitation et d'applications standards. Ignorer ces fichiers inintéressants pour l'enquêteur peut réduire considérablement le temps d'analyse des images. +\li "Notable" (ou connus défavorablement) : ce sont des fichiers qui devraient sensibiliser l'analyste. Cet ensemble variera en fonction du type d'enquête, mais les exemples courants incluent les images de contrebande et les logiciels malveillants. +\li "No change" : ce sont des fichiers qui peuvent révéler des informations sur le système mais qui ne sont pas notables. Par exemple, savoir qu'une image contient de nombreux fichiers connus pour être des cartes de Londres pourrait être intéressant pour un enquêteur, mais les cartes elles-mêmes ne sont pas notables. + +\section adding_hashsets Importation de jeux de hachage + +Pour importer un jeu de hachage existant, utilisez le bouton "Import Hash Set" du panneau d'options des jeux de hachage ("Hash Sets"). Cela fera apparaître une boîte de dialogue pour importer le fichier. + +\image html hash_import.png + +Hash Set Path - Le chemin d'accès au jeu de hachage que vous importez. Autopsy prend en charge les formats suivants: +\li Texte: Un hachage sur chaque ligne. Par exemple, la sortie de l'exécution du programme md5, md5sum ou md5deep sur un ensemble de fichiers (* .txt) +\li Index seul: Généré par The Sleuth Kit/Autopsy. Le NSRL est disponible dans ce format pour une utilisation avec Autopsy (\ref using_hashsets "voir ci-dessous") (*.idx) +\li Base de données de format The Sleuth Kit/Autopsy: jeux de hachage SQLite créé par Autopsy (*.kdb) +\li EnCase: Un fichier de jeu de hachage EnCase (*.hash) +\li HashKeeper: Un fichier de jeu de hachage conforme au standard HashKeeper (*.hsh) + +Destination - Le champ Destination fait référence à l'endroit où le jeu de hachage sera stocké. +\li Local: Le fichier de jeu de hachage sera utilisé à partir de l'emplacement d'origine sur le disque +\li Remote: Le jeu de hachage sera copié dans le \ref central_repo_page "référentiel central". Lorsque vous utilisez un référentiel central PostgreSQL, cela permet à plusieurs utilisateurs de partager facilement les mêmes ensembles de hachage. + +Name - Afficher le nom du jeu de hachage. Un nom sera suggéré en fonction du nom du fichier, mais cela peut être modifié. + +Version - La version du jeu de hachage ne peut être saisie que lors de l'importation du jeu de hachage dans le référentiel central. En outre, aucune version ne peut être entrée si le jeu de hachage n'est pas en lecture seule. + +Source Organization - L'organisation ne peut être saisie que lors de l'importation du jeu de hachage dans le référentiel central. Voir la section \ref cr_manage_orgs "gestion des organisations" pour plus d'informations. + +Type of database set - Toutes les entrées de l'ensemble de hachage doivent être "Known" (peuvent être ignorées en toute sécurité), "Notables" (peuvent être des indicateurs de comportement suspect) ou "No Change" (connues pour être liées à un certain type de fichier). + +Make hash set read-only - Le paramètre en lecture seule n'est actif que lors de l'importation du jeu de hachage dans le référentiel central. Une base de données en lecture seule ne peut pas avoir de nouveaux hachages ajoutés via le panneau d'options "Hash Sets" ou le menu contextuel. Pour les ensembles de hachage importés localement, la possibilité d'écrire ou non dépend du type de jeu de hachage. Les bases de données au format Autopsy (* .kdb) peuvent être modifiées, mais tous les autres types seront en lecture seule. + +Send ingest inbox message for each hit - Détermine si un message est envoyé dans la boîte de notification pour chaque fichier correspondant. Cela ne peut pas être activé pour un jeu de hachage "Known". + +Copy hash set into user configuration folder - Cré une copie du jeu de hachage au lieu d'utiliser celui existant. Ceci est destiné à être utilisé dans le cadre de la \ref live_triage_page. + +\subsection hashset_indexing Indexage + +Après avoir importé le jeu de hachage, vous devrez peut-être l'indexer avant de pouvoir l'utiliser. Pour la plupart des types de jeux de hachage, Autopsy a besoin d'un index de ce dernier pour l'utiliser réellement. Il peut créer l'index si vous importez uniquement le jeu de hachage. Tous les ensembles de hachage qui nécessitent un index seront affichés en rouge, et "Index Status" indiquera qu'un index doit être créé. Cela se fait simplement en utilisant le bouton "Index". + +\image html hash_indexing.png + +Autopsy utilise le système de gestion des jeux de hachage de The Sleuth Kit. Vous pouvez créer manuellement un index à l'aide de l'outil de ligne de commande 'hfind' ou vous pouvez utiliser Autopsy. Si vous essayez de continuer sans indexer un jeu de hachage, Autopsy vous proposera de produire automatiquement un index pour vous. +Vous pouvez également spécifier uniquement le fichier d'index et ne pas utiliser le jeu de hachage complet - le fichier d'index est suffisant pour identifier les fichiers connus. Cela peut économiser de l'espace. Pour ce faire, spécifiez le fichier .idx dans le panneau d'options "Hash Sets". + +\section creating_hashsets Création de jeux de hachage + +De nouveaux ensembles de hachage peuvent être créés à l'aide du bouton "New Hash Set". Les champs sont pour la plupart les mêmes que dans la \ref adding_hashsets "boîte de dialogue d'importation" décrite ci-dessus. + +\image html hash_new_db.png + +Dans ce cas, le chemin de la base de données ("Hash Set Path") est l'endroit où la nouvelle base de données sera stockée. Si le référentiel central est utilisé, ce champ n'est pas nécessaire. + +\section hash_adding_hashes Ajout de hachages à un ensemble de hachages + +Une fois que vous avez créé un ensemble de hachage, vous devrez y ajouter des hachages. La première façon de faire est d'utiliser le bouton "Add Hashes to Hash Set" dans le panneau d'options. Chaque hachage doit être sur sa propre ligne et peut éventuellement être suivi d'une virgule puis d'un commentaire sur le fichier auquel correspond le hachage. Ici, nous créons un ensemble de hachage "No Change" correspondant aux images de chat: + +\image html hash_add.png + +L'autre façon d'ajouter une entrée à un jeu de hachage consiste à utiliser le menu contextuel. Mettez en surbrillance le fichier que vous souhaitez ajouter à un ensemble de hachage dans la visionneuse de résultats et cliquez avec le bouton droit de la souris, puis sélectionnez "Add File to Hash Set" et enfin l'ensemble auquel vous souhaitez l'ajouter. Notez que cela n'ajoute pas automatiquement le fichier à la liste des hits de l'ensemble de hachage pour le cas actuel - vous devrez réexécuter le module d'acquisition "Hash Lookup" pour le voir apparaître ici. + +\image html hash_add_context.png + +\section using_hashsets Utilisation d'ensembles de hachage +Il y a un \ref ingest_page "module d'acquisition" qui hachera les fichiers et les recherchera dans les ensembles de hachage. Il marquera les fichiers qui étaient dans le jeu de hachage comme "Notable" et ces résultats seront affichés dans la section Results de l'\ref tree_viewer_page. +D'autres modules d'acquisition peuvent utiliser l'état "Known" d'un fichier pour décider s'ils doivent ignorer le fichier ou le traiter. +Vous pouvez également voir les résultats dans la fenêtre de \ref how_to_open_file_search "recherche de fichiers". Il existe une option pour choisir le "Known Status". De là, vous pouvez effectuer une recherche pour voir tous les fichiers notables ("Notable"). À partir de là, vous pouvez également choisir d'ignorer tous les fichiers connus ("Known") trouvés dans le NSRL. Vous pouvez également voir l'état du fichier dans une colonne lorsque le fichier est répertorié. +
    +NIST NSRL +------ +Autopsy peut utiliser le NIST NSRL pour détecter les fichiers "connus". Le NSRL contient des hachages de fichiers "connus" qui peuvent être bons ou mauvais en fonction de votre perspective et du type d'enquête. Par exemple, l'existence d'un logiciel financier peut être intéressant pour votre enquête et ce logiciel pourrait être dans le NSRL. Par conséquent, Autopsy traite les fichiers qui se trouvent dans le NSRL comme simplement "Known" (connus) et ne spécifie pas bon ou mauvais. Les modules d'acquisition ont la possibilité d'ignorer les fichiers trouvés dans le NSRL. + +Pour utiliser le NSRL, vous pouvez télécharger un index pré-établi à partir de http://sourceforge.net/projects/autopsy/files/NSRL. Télécharger le fichier NSRL-XYZm-autopsy.zip (où 'XYZ' est le numéro de version. Au moment d'écrire ces lignes, c'est 270) et décompressez le. Utiliser le menu "Tools", "Options" et sélectionner l'onglet "Hash Sets". Cliquer sur "Import Database" et accédez à l'emplacement du fichier NSRL décompressé. Vous pouvez modifier le nom du jeu de hachage ("Hash Set Name") si vous le souhaitez. Sélectionnez le type de base de données souhaité, et choisissez "Send ingest inbox message for each hit" (un message est envoyé dans la boîte de notification pour chaque fichier correspondant) si vous le souhaitez, puis cliquez sur "OK". + +
    +\image html nsrl_import_process.PNG +
    + +Utilisation du module +====== + +Paramètres d'intégration +------ +Lorsque les ensembles de hachage sont configurés, l'utilisateur peut sélectionner quels ensembles utiliser pendant le processus d'acquisition. + +\image html hash-lookup.PNG + + + +Voir les résultats +------ + +Les résultats s'affichent dans l'arborescence sous "Hashset Hits", regroupés par le nom du jeu de hachage. Si les hits de l'ensemble de hachage avaient des commentaires associés, vous les verrez dans la colonne "Comment" dans la visionneuse de résultats avec le hachage du fichier. + +\image html hashset-hits.PNG + +Vous pouvez également afficher les commentaires dans l'onglet "Annotations" de la visionneuse de contenu. + +*/ diff --git a/docs/doxygen-user_fr/hosts.dox b/docs/doxygen-user_fr/hosts.dox new file mode 100644 index 0000000000..d1a0b30a08 --- /dev/null +++ b/docs/doxygen-user_fr/hosts.dox @@ -0,0 +1,50 @@ +/*! \page host_page Hosts (Hôtes) + + +[TOC] + +\section host_use Utilisation des hôtes + +\subsection host_wizard Association d'une source de données à un hôte + +Chaque source de données doit être associée à un hôte (host). La première étape du \ref ds_add "processus d'ajout d'une source de données" consiste à sélectionner un hôte pour la source de données que vous êtes sur le point d'ajouter au cas. Cet hôte peut être généré automatiquement, saisi par l'utilisateur ou sélectionné dans la liste des hôtes déjà présents dans le cas. + +\image html data_source_host_select.png + +\subsection host_view Affichage des hôtes + +Les hôtes sont affichés dans l'\ref tree_viewer_page. En fonction des \ref view_options_page sélectionnées, les hôtes peuvent être regroupés sous des "personnes". + +\image html ui_tree_top_ds.png + +\subsection host_os_accounts Comptes de système d'exploitation + +Les comptes de système d'exploitation peuvent être affichés dans le nœud "OS Accounts" sous "Results". Chaque compte de système d'exploitation est associé à un hôte et les informations sur l'hôte sont affichées dans l'onglet "OS Accounts" de la visionneuse de contenu. + +\image html host_os_accounts.png + +\section host_management Gérer les hôtes + +\subsection host_menu Menu "Manage Hosts" + +Allez sur Case->Manage Hosts pour ouvrir le panneau de gestion des hôtes. + +\image html manage_hosts.png + +Ici, vous pouvez voir tous les hôtes dans le cas, ajouter de nouveaux hôtes, changer le nom d'un hôte existant et supprimer les hôtes qui ne sont pas utilisés. + +\subsection host_merge Fusion d'hôtes + +Au cours du traitement d'un cas, il peut devenir évident que deux hôtes (ou plus) doivent être combinés. La fusion d'un hôte dans un autre déplacera toutes les sources de données de l'hôte source vers l'hôte de destination et déplacera ou combinera tous les comptes de système d'exploitation trouvés. + + +Pour fusionner des hôtes, cliquez avec le bouton droit sur l'hôte que vous souhaitez fusionner dans un autre hôte. + +\image html host_merge.png + +Une fenêtre de confirmation s'affiche indiquant que cela ne peut pas être annulé. Après avoir validé cette action, les hôtes seront fusionnés et le nœud de l'arborescence se mettra à jour en affichant les données combinées. + +\image html host_merge_result.png + + +*/ \ No newline at end of file diff --git a/docs/doxygen-user_fr/ileapp.dox b/docs/doxygen-user_fr/ileapp.dox new file mode 100644 index 0000000000..ace06d920d --- /dev/null +++ b/docs/doxygen-user_fr/ileapp.dox @@ -0,0 +1,20 @@ +/*! \page ileapp_page iOS Analyzer (iLEAPP) (Analyseur iOS - iLEAPP) + +[TOC] + +\section ileapp_overview Aperçu + +Le module "iOS Analyzer" exécute iLEAPP (https://github.com/abrignoni/iLEAPP) et convertit les retours en résultats qui peuvent être visualisés dans Autopsy. + +\section ileapp_config Utilisation du module + +Cochez la case dans l'écran de paramétrage des modules d'acquisition ("Configure Ingest Modules") pour activer le module iOS Analyzer (iLEAPP). Le module fonctionnera sur les fichiers .tar/.zip trouvés dans des sources de données de type \ref ds_log "fichiers logiques" ou \ref ds_img "image disque". + +\section ileapp_results Voir les résultats + +Les résultats du module iOS Analyzer apparaîtront dans l'\ref tree_viewer_page sous Results->Extracted Content. + +\image html ileapp_main.jpg + + +*/ diff --git a/docs/doxygen-user_fr/image_gallery.dox b/docs/doxygen-user_fr/image_gallery.dox new file mode 100644 index 0000000000..cb25858add --- /dev/null +++ b/docs/doxygen-user_fr/image_gallery.dox @@ -0,0 +1,125 @@ +/*! \page image_gallery_page Images/Vidéos + +[TOC] + + +Aperçu +======== +Ce document décrit l'utilisation de la fonction "Images/Videos" d'Autopsy. Cette fonctionnalité a été financée par le DHS S&T pour aider à fournir des outils de criminalistique numérique gratuits et open source aux forces de l'ordre. + +La fonction "Images/Videos" a été spécialement conçue pour les cas de pédo-pornographie, mais peut être utilisée pour une variété d'autres types d'enquêtes impliquant des images et des vidéos. Elle offre les fonctionnalités suivantes au-delà de la traditionnelle longue liste de vignettes qu'Autopsy et d'autres outils fournissent généralement. +- Regroupe les images par dossier (et autres attributs) pour aider l'examinateur à diviser un grand ensemble d'images en groupes plus petits et à se concentrer sur les zones contenant des images d'intérêt. +- Permet à l'examinateur de commencer à visualiser les images immédiatement après les avoir ajoutées au cas. Au fur et à mesure que les images sont hachées, elles sont mises à jour dans l'interface. Vous n'avez pas besoin d'attendre que la source de données entière soit traitée. + +Ce document suppose une connaissance de base d'Autopsy. +Démarrage rapide +================ +1. L'outil "Images/Videos" peut être configuré pour collecter des données sur les images/vidéos lors de l'acquisition mais également après l'acquisition. Pour modifier ce paramètre, accédez à "Tools", "Options", "Image /Video Gallery". Ce paramètre est enregistré par cas, mais ne peut pas être modifié pendant l'acquisition. Voir la fenêtre Options pour plus de détails. +2. Créez un cas comme d'habitude et ajoutez une image disque (ou un dossier de fichiers) comme source de données. Assurez-vous que le module "Hash Lookup" est activé avec les NSRL et les jeux de hachage défavorablement connus, que le module "Picture Analyzer" est activé ainsi que le module "File Type Identification". +3. Cliquez sur le bouton "Images/Videos" ou sélectionnez "Images/Videos" dans le menu "Tools". Cela ouvrira l'outil "Image/Video Gallery" d'Autopsy dans une nouvelle fenêtre. +4. Des groupes d'images seront présentés au fur et à mesure de leur analyse par les modules d'acquisition s'exécutant en arrière-plan. Vous pouvez y revenir plus tard et les regrouper, mais il est nécessaire de les garder groupés par dossier pendant que l'acquisition est toujours en cours. +5. Au fur et à mesure que chaque groupe est examiné, le groupe suivant par ordre de priorité la plus élevée est présenté, selon un critère de tri (la valeur par défaut est la densité des hits de l'ensemble de hachage). +6. Les images qui étaient des hits de l'ensemble de hachage, auront une bordure en pointillés autour d'elles. +7. Vous pouvez utiliser la barre de menus en haut du groupe pour classer l'ensemble du groupe. +8. Vous pouvez faire un clic droit sur une image pour catégoriser ou marquer l'image individuelle. +9. Marquer les fichiers avec des balises personnalisables. Une balise "Follow Up" est déjà intégrée à l'outil et dans les options de filtre. Les balises peuvent être appliquées en plus de la catégorisation. Une image ne peut avoir qu'une seule catégorisation, mais peut avoir plusieurs balises pour prendre en charge votre flux de travail. +10. Créez un rapport contenant les détails de chaque fichier balisé et/ou catégorisé, via la fonction standard de génération de rapport d'Autopsy. + +Détails d'un cas d'utilisation +============================== +En plus de l'utilisation de base présentée dans la section précédente, voici quelques conseils sur les cas d'utilisation qui ont été conçus dans l'outil. +- Lorsque vous visualisez les groupes, ils sont présentés dans un ordre basé sur la densité des hits de hachage (par défaut). Si vous trouvez un groupe qui contient beaucoup de fichiers intéressants et que vous voulez voir ce qu'il y a dans le dossier parent ou les dossiers voisins, utilisez l'arborescence de navigation sur la gauche. +- A tout moment, vous pouvez utiliser la liste sur le côté gauche pour voir les groupes avec le plus grand nombre de hits du le jeu de hachage. +- Pour voir quels dossiers contiennent le plus d'images, triez les groupes par taille de groupe (décroissante). +- Les fichiers qui ont des hits de hachage ne sont pas automatiquement marqués ou catégorisés. Vous devez le faire après les avoir examinés. Le moyen le plus simple de le faire est d'attendre la fin de l'acquisition, puis de grouper par jeu de hachage. Vous pouvez ensuite passer en revue chaque groupe et classer le groupe entier en une seule fois à l'aide de l'en-tête de groupe. + +Catégories +========== +L'outil a été conçu spécifiquement pour les cas de pornographie infantile et a une notion de catégorisation. Nous allons modifier cela à l'avenir pour être plus flexible avec des noms de catégories personnalisés, mais actuellement, il est codé en dur pour utiliser les noms qu'utilise le Project Vic (et d'autres groupes internationaux). Nous avons attribué des couleurs à chaque catégorie pour mettre en valeur chaque image. + + +Nom|Description|Couleur +----|-----------------|-------- +CAT-0|Uncategorized|![gray](ImageGallery/gray.PNG) +CAT-1|Child Abuse Material |![red](ImageGallery/red.PNG) +CAT-2|Child Exploitative / Age Difficult|![orange](ImageGallery/orange.PNG) +CAT-3|CGI / Animation|![yellow](ImageGallery/yellow.PNG) +CAT-4|Comparison Images |![bisque](ImageGallery/bisque.PNG) +CAT-5|Non-pertinent|![green](ImageGallery/green.PNG) + +Contrôles graphiques +==================== +Vous pouvez effectuer l'intégralité de vos investigations à l'aide de la souris, mais de nombreux analystes aiment utiliser des raccourcis clavier pour traiter rapidement de grandes quantités d'images. + +Raccourcis clavier +------------------ +raccourcis | action +------------|------ +touches 0-5 | attribuer la catégorie numérotée correspondante au(x) fichier(s) sélectionné(s) +alt + 0-5 | attribuer la catégorie numérotée correspondante à tous les fichiers du groupe ciblé +flèches | sélectionner le fichier suivant dans le sens de la flèche +page haut/bas | faire défiler la liste des fichiers + +Commandes supplémentaires de la souris +------------------------- +action de la souris| action +----------|---------- +ctrl + clic gauche|basculer la sélection du fichier cliqué, sélectionner plusieurs fichiers +clic droit sur un fichier|afficher le menu contextuel permettant des actions sur le fichier (baliser, catégoriser, extraire le fichier en local, afficher dans une visionneuse externe, afficher dans la visionneuse de contenu Autopsy, ajouter un fichier à la base de données de hachage) +clic droit sur l'espace vide d'un groupe|afficher le menu contextuel permettant des actions par groupe (baliser, catégoriser, extraire le(s) fichier(s) en local, ajouter le(s) fichier(s) à la base de données de hachage) +double clic sur un fichier|ouvrir le fichier sélectionné en mode diaporama + +Détails de l'interface utilisateur +================================== +Zone d'affichage du groupe +-------------------------- +La zone d'affichage centrale contient la liste des fichiers du groupe actuel. Les images du groupe peuvent être affichées en mode miniature ou en mode diaporama. Le mode diaporama fournit des images plus grandes et la lecture de fichiers vidéo. À droite de l'en-tête du groupe se trouve deux boutons pour changer le mode d'affichage du groupe (vignettes/diaporama). + +Tuiles Image/Vidéo +------------------ + +Chaque fichier est représenté dans la zone d'affichage principale par une petite vignette. La vignette montre: +- La vignette de l'image/vidéo +- Le nom du fichier +- Des indicateurs d'autres détails importants: + +| image | description | signification| +|----|----|-----| +| | bordure de couleur unie | catégorie attribuée au fichier.| +| ![](ImageGallery/purpledash.PNG) | bordure pointillée violette | Le fichier a un hit de hachage défavorablement connu, mais n'a pas encore été catégorisé. | +| ![](ImageGallery/hashset_hits.PNG) |punaise | Le fichier a un hit de hachage défavorablement connu| +| ![](ImageGallery/video-file.PNG) | clap de cinéma sur document | fichier vidéo| +| ![](ImageGallery/flag_red.PNG) | un drapeau rouge | le fichier a été "marqué" ainsi avec une balise de suivi| + + +Mode diaporama +-------------- +En mode diaporama, un groupe affiche un seul fichier à la fois avec une taille accrue. Les contrôles de balise/catégorie de fichier au-dessus du coin supérieur droit de l'image et les gros boutons gauche et droit permettent de parcourir les fichiers du groupe. Si le fichier actif est un format vidéo pris en charge par Autopsy, les commandes de lecture vidéo apparaissent sous la vidéo. + +Tableau/arborescence du contenu +------------------------------- +La section en haut à gauche avec les onglets intitulés "All Groups" et "Only Hash Hits" donne un aperçu des groupes de fichiers dans le cas. Il change pour refléter le paramètre "Group By" actuel: pour les regroupements hiérarchiques (chemin), il affiche une arborescence de dossiers (les dossiers contenant des images/vidéos (groupes) sont marqués d'une icône distinctive), et pour les autres regroupements, il affiche uniquement une liste. + +Chaque groupe affiche le nombre de fichiers qui correpondent aux bases de données de hachage configurées lors de l'acquisition (hits de hachage) et le nombre total de fichiers image/vidéo sous forme de rapport (hits de hachage/total) après son nom. En sélectionnant des groupes dans l'arborescence/la liste, vous pouvez y accéder directement dans la zone d'affichage principale. Si l'onglet "Only Hash Hits" est sélectionné, seuls les groupes contenant des fichiers qui ont des hits de hachage sont affichés. + + +À l'écoute des changements +========================== +La galerie d'images maintient sa propre base de données, qui doit être mise à jour au fur et à mesure que les fichiers sont analysés par Autopsy. Par exemple, elle doit savoir quand un fichier a été haché ou si des données EXIF ont été extraites. Par défaut, la galerie d'images est toujours à l'écoute de ces changements dans les cas mono-utilisateur et maintient sa base de données à jour. Si cela a un impact sur les performances, vous pouvez désactiver cette fonctionnalité dans le panneau Options. + +Vous pouvez désactiver l'écoute pour le cas actuel et vous pouvez modifier le comportement par défaut pour les cas futurs. + + + +Cas multi-utilisateurs +====================== +Si un cas a été créé dans un environnement multi-utilisateurs, il devient alors beaucoup plus difficile de garder la base de données de la galerie d'images synchronisée car de nombreux autres examinateurs pourraient analyser les données de ce cas. Par conséquent, la galerie d'images a des comportements de mise à jour différents dans un cas multi-utilisateur et dans un cas mono-utilisateur. Notamment: +- Si votre système exécute l'acquisition sur la source de données, vous continuerez à obtenir des mises à jour en temps réel, comme dans un cas mono-utilisateur. Ainsi, dès qu'un dossier de fichiers a été haché et que des données EXIF ont été extraites, il vous sera possible de le visualiser. +- Si un autre système du cluster exécute l'acquisition sur la source de données, vous risquez de ne pas voir ses résultats tant que l'acquisition n'est pas terminée. Vous n'obtiendrez pas de mises à jour en temps réel et, à la place, vous obtiendrez des mises à jour uniquement après avoir fermé la galerie d'images et l'avoir ouverte à nouveau. +- Chaque fois que vous ouvrez la galerie d'images, elle vérifiera la base de données locale pour voir si elle est synchronisée avec la base de données de cas. Si ce n'est pas le cas, elle vous demandera de la reconstruire. En effet, des données supplémentaires peuvent avoir été ajoutées à la base de données de cas par un autre système et votre base de données "Images/Videos" n'est plus exacte. + +Vous avez également la possibilité de voir les groupes (ou dossiers) qui sont nouveaux pour vous ou pour tout le monde. Lorsque vous appuyez sur "Next Unseen Group", le comportement par défaut est de vous montrer le groupe de priorité le plus élevé que vous n'avez pas encore vu. Mais vous pouvez également choisir de voir des groupes que personne d'autre n'a vus. Ce choix peut être fait en utilisant la case à cocher à côté du bouton "Next Unseen Group". + + + +*/ diff --git a/docs/doxygen-user_fr/images/AutoIngest/admin_file.png b/docs/doxygen-user_fr/images/AutoIngest/admin_file.png new file mode 100644 index 0000000000..0112d84ef3 Binary files /dev/null and b/docs/doxygen-user_fr/images/AutoIngest/admin_file.png differ diff --git a/docs/doxygen-user_fr/images/AutoIngest/admin_jobs_cancel.png b/docs/doxygen-user_fr/images/AutoIngest/admin_jobs_cancel.png new file mode 100644 index 0000000000..d8cbd4deee Binary files /dev/null and b/docs/doxygen-user_fr/images/AutoIngest/admin_jobs_cancel.png differ diff --git a/docs/doxygen-user_fr/images/AutoIngest/admin_jobs_completed.png b/docs/doxygen-user_fr/images/AutoIngest/admin_jobs_completed.png new file mode 100644 index 0000000000..f1046371de Binary files /dev/null and b/docs/doxygen-user_fr/images/AutoIngest/admin_jobs_completed.png differ diff --git a/docs/doxygen-user_fr/images/AutoIngest/admin_jobs_ocr1.png b/docs/doxygen-user_fr/images/AutoIngest/admin_jobs_ocr1.png new file mode 100644 index 0000000000..a0db003ca6 Binary files /dev/null and b/docs/doxygen-user_fr/images/AutoIngest/admin_jobs_ocr1.png differ diff --git a/docs/doxygen-user_fr/images/AutoIngest/admin_jobs_ocr2.png b/docs/doxygen-user_fr/images/AutoIngest/admin_jobs_ocr2.png new file mode 100644 index 0000000000..85aabf1154 Binary files /dev/null and b/docs/doxygen-user_fr/images/AutoIngest/admin_jobs_ocr2.png differ diff --git a/docs/doxygen-user_fr/images/AutoIngest/admin_jobs_panel.png b/docs/doxygen-user_fr/images/AutoIngest/admin_jobs_panel.png new file mode 100644 index 0000000000..25ad7b1982 Binary files /dev/null and b/docs/doxygen-user_fr/images/AutoIngest/admin_jobs_panel.png differ diff --git a/docs/doxygen-user_fr/images/AutoIngest/admin_nodes_panel.png b/docs/doxygen-user_fr/images/AutoIngest/admin_nodes_panel.png new file mode 100644 index 0000000000..220b5d65a4 Binary files /dev/null and b/docs/doxygen-user_fr/images/AutoIngest/admin_nodes_panel.png differ diff --git a/docs/doxygen-user_fr/images/AutoIngest/advanced_settings.png b/docs/doxygen-user_fr/images/AutoIngest/advanced_settings.png new file mode 100644 index 0000000000..f93ca9bd00 Binary files /dev/null and b/docs/doxygen-user_fr/images/AutoIngest/advanced_settings.png differ diff --git a/docs/doxygen-user_fr/images/AutoIngest/auto_ingest_in_progress.png b/docs/doxygen-user_fr/images/AutoIngest/auto_ingest_in_progress.png new file mode 100644 index 0000000000..cf894b13c3 Binary files /dev/null and b/docs/doxygen-user_fr/images/AutoIngest/auto_ingest_in_progress.png differ diff --git a/docs/doxygen-user_fr/images/AutoIngest/auto_ingest_mode_setup.png b/docs/doxygen-user_fr/images/AutoIngest/auto_ingest_mode_setup.png new file mode 100644 index 0000000000..b9875d6245 Binary files /dev/null and b/docs/doxygen-user_fr/images/AutoIngest/auto_ingest_mode_setup.png differ diff --git a/docs/doxygen-user_fr/images/AutoIngest/case_delete_confirm.png b/docs/doxygen-user_fr/images/AutoIngest/case_delete_confirm.png new file mode 100644 index 0000000000..6d3acec6ae Binary files /dev/null and b/docs/doxygen-user_fr/images/AutoIngest/case_delete_confirm.png differ diff --git a/docs/doxygen-user_fr/images/AutoIngest/cases_context_menu.png b/docs/doxygen-user_fr/images/AutoIngest/cases_context_menu.png new file mode 100644 index 0000000000..e83c083f49 Binary files /dev/null and b/docs/doxygen-user_fr/images/AutoIngest/cases_context_menu.png differ diff --git a/docs/doxygen-user_fr/images/AutoIngest/cases_panel.png b/docs/doxygen-user_fr/images/AutoIngest/cases_panel.png new file mode 100644 index 0000000000..c932b57bf1 Binary files /dev/null and b/docs/doxygen-user_fr/images/AutoIngest/cases_panel.png differ diff --git a/docs/doxygen-user_fr/images/AutoIngest/error_suppression.png b/docs/doxygen-user_fr/images/AutoIngest/error_suppression.png new file mode 100644 index 0000000000..91d2805029 Binary files /dev/null and b/docs/doxygen-user_fr/images/AutoIngest/error_suppression.png differ diff --git a/docs/doxygen-user_fr/images/AutoIngest/examiner_dashboard.png b/docs/doxygen-user_fr/images/AutoIngest/examiner_dashboard.png new file mode 100644 index 0000000000..7e0da4d353 Binary files /dev/null and b/docs/doxygen-user_fr/images/AutoIngest/examiner_dashboard.png differ diff --git a/docs/doxygen-user_fr/images/AutoIngest/file_export_dir_structure.png b/docs/doxygen-user_fr/images/AutoIngest/file_export_dir_structure.png new file mode 100644 index 0000000000..2e9003831c Binary files /dev/null and b/docs/doxygen-user_fr/images/AutoIngest/file_export_dir_structure.png differ diff --git a/docs/doxygen-user_fr/images/AutoIngest/file_export_encrypton.png b/docs/doxygen-user_fr/images/AutoIngest/file_export_encrypton.png new file mode 100644 index 0000000000..829ee730f0 Binary files /dev/null and b/docs/doxygen-user_fr/images/AutoIngest/file_export_encrypton.png differ diff --git a/docs/doxygen-user_fr/images/AutoIngest/file_export_file_loc.png b/docs/doxygen-user_fr/images/AutoIngest/file_export_file_loc.png new file mode 100644 index 0000000000..8311283585 Binary files /dev/null and b/docs/doxygen-user_fr/images/AutoIngest/file_export_file_loc.png differ diff --git a/docs/doxygen-user_fr/images/AutoIngest/file_export_json_loc.png b/docs/doxygen-user_fr/images/AutoIngest/file_export_json_loc.png new file mode 100644 index 0000000000..2652c387cc Binary files /dev/null and b/docs/doxygen-user_fr/images/AutoIngest/file_export_json_loc.png differ diff --git a/docs/doxygen-user_fr/images/AutoIngest/file_export_keyword.png b/docs/doxygen-user_fr/images/AutoIngest/file_export_keyword.png new file mode 100644 index 0000000000..c2b6a26b78 Binary files /dev/null and b/docs/doxygen-user_fr/images/AutoIngest/file_export_keyword.png differ diff --git a/docs/doxygen-user_fr/images/AutoIngest/file_export_png.png b/docs/doxygen-user_fr/images/AutoIngest/file_export_png.png new file mode 100644 index 0000000000..2d872401d0 Binary files /dev/null and b/docs/doxygen-user_fr/images/AutoIngest/file_export_png.png differ diff --git a/docs/doxygen-user_fr/images/AutoIngest/file_export_size.png b/docs/doxygen-user_fr/images/AutoIngest/file_export_size.png new file mode 100644 index 0000000000..c4e2eb7917 Binary files /dev/null and b/docs/doxygen-user_fr/images/AutoIngest/file_export_size.png differ diff --git a/docs/doxygen-user_fr/images/AutoIngest/file_exporter_main.png b/docs/doxygen-user_fr/images/AutoIngest/file_exporter_main.png new file mode 100644 index 0000000000..2aa3e99778 Binary files /dev/null and b/docs/doxygen-user_fr/images/AutoIngest/file_exporter_main.png differ diff --git a/docs/doxygen-user_fr/images/AutoIngest/health_monitor.png b/docs/doxygen-user_fr/images/AutoIngest/health_monitor.png new file mode 100644 index 0000000000..2550900ee8 Binary files /dev/null and b/docs/doxygen-user_fr/images/AutoIngest/health_monitor.png differ diff --git a/docs/doxygen-user_fr/images/AutoIngest/health_monitor_disabled.png b/docs/doxygen-user_fr/images/AutoIngest/health_monitor_disabled.png new file mode 100644 index 0000000000..ae8bcf64e9 Binary files /dev/null and b/docs/doxygen-user_fr/images/AutoIngest/health_monitor_disabled.png differ diff --git a/docs/doxygen-user_fr/images/AutoIngest/manifest_file_in_file_explorer.png b/docs/doxygen-user_fr/images/AutoIngest/manifest_file_in_file_explorer.png new file mode 100644 index 0000000000..2df4d7a777 Binary files /dev/null and b/docs/doxygen-user_fr/images/AutoIngest/manifest_file_in_file_explorer.png differ diff --git a/docs/doxygen-user_fr/images/AutoIngest/manifest_tool_root_folder.png b/docs/doxygen-user_fr/images/AutoIngest/manifest_tool_root_folder.png new file mode 100644 index 0000000000..ac58fa06e5 Binary files /dev/null and b/docs/doxygen-user_fr/images/AutoIngest/manifest_tool_root_folder.png differ diff --git a/docs/doxygen-user_fr/images/AutoIngest/manifest_tool_ui.png b/docs/doxygen-user_fr/images/AutoIngest/manifest_tool_ui.png new file mode 100644 index 0000000000..70766fc8a4 Binary files /dev/null and b/docs/doxygen-user_fr/images/AutoIngest/manifest_tool_ui.png differ diff --git a/docs/doxygen-user_fr/images/AutoIngest/master_node.png b/docs/doxygen-user_fr/images/AutoIngest/master_node.png new file mode 100644 index 0000000000..3f0813047f Binary files /dev/null and b/docs/doxygen-user_fr/images/AutoIngest/master_node.png differ diff --git a/docs/doxygen-user_fr/images/AutoIngest/metrics.png b/docs/doxygen-user_fr/images/AutoIngest/metrics.png new file mode 100644 index 0000000000..bff656a259 Binary files /dev/null and b/docs/doxygen-user_fr/images/AutoIngest/metrics.png differ diff --git a/docs/doxygen-user_fr/images/AutoIngest/no_periodic_searches.png b/docs/doxygen-user_fr/images/AutoIngest/no_periodic_searches.png new file mode 100644 index 0000000000..40326527d2 Binary files /dev/null and b/docs/doxygen-user_fr/images/AutoIngest/no_periodic_searches.png differ diff --git a/docs/doxygen-user_fr/images/AutoIngest/overview_pic1.png b/docs/doxygen-user_fr/images/AutoIngest/overview_pic1.png new file mode 100644 index 0000000000..29852cb6e3 Binary files /dev/null and b/docs/doxygen-user_fr/images/AutoIngest/overview_pic1.png differ diff --git a/docs/doxygen-user_fr/images/AutoIngest/overview_pic2.png b/docs/doxygen-user_fr/images/AutoIngest/overview_pic2.png new file mode 100644 index 0000000000..99dcc07266 Binary files /dev/null and b/docs/doxygen-user_fr/images/AutoIngest/overview_pic2.png differ diff --git a/docs/doxygen-user_fr/images/AutoIngest/test_button_failure.png b/docs/doxygen-user_fr/images/AutoIngest/test_button_failure.png new file mode 100644 index 0000000000..b4410d8df1 Binary files /dev/null and b/docs/doxygen-user_fr/images/AutoIngest/test_button_failure.png differ diff --git a/docs/doxygen-user_fr/images/DataSourceSummary/ds_summary_analysis.png b/docs/doxygen-user_fr/images/DataSourceSummary/ds_summary_analysis.png new file mode 100644 index 0000000000..4232c8f434 Binary files /dev/null and b/docs/doxygen-user_fr/images/DataSourceSummary/ds_summary_analysis.png differ diff --git a/docs/doxygen-user_fr/images/DataSourceSummary/ds_summary_container.png b/docs/doxygen-user_fr/images/DataSourceSummary/ds_summary_container.png new file mode 100644 index 0000000000..328b233dc3 Binary files /dev/null and b/docs/doxygen-user_fr/images/DataSourceSummary/ds_summary_container.png differ diff --git a/docs/doxygen-user_fr/images/DataSourceSummary/ds_summary_export.png b/docs/doxygen-user_fr/images/DataSourceSummary/ds_summary_export.png new file mode 100644 index 0000000000..da7601f32e Binary files /dev/null and b/docs/doxygen-user_fr/images/DataSourceSummary/ds_summary_export.png differ diff --git a/docs/doxygen-user_fr/images/DataSourceSummary/ds_summary_geo.png b/docs/doxygen-user_fr/images/DataSourceSummary/ds_summary_geo.png new file mode 100644 index 0000000000..7e49cac8c3 Binary files /dev/null and b/docs/doxygen-user_fr/images/DataSourceSummary/ds_summary_geo.png differ diff --git a/docs/doxygen-user_fr/images/DataSourceSummary/ds_summary_ingest.png b/docs/doxygen-user_fr/images/DataSourceSummary/ds_summary_ingest.png new file mode 100644 index 0000000000..6ed19b77c0 Binary files /dev/null and b/docs/doxygen-user_fr/images/DataSourceSummary/ds_summary_ingest.png differ diff --git a/docs/doxygen-user_fr/images/DataSourceSummary/ds_summary_noRA.png b/docs/doxygen-user_fr/images/DataSourceSummary/ds_summary_noRA.png new file mode 100644 index 0000000000..111d6f195d Binary files /dev/null and b/docs/doxygen-user_fr/images/DataSourceSummary/ds_summary_noRA.png differ diff --git a/docs/doxygen-user_fr/images/DataSourceSummary/ds_summary_past_cases.png b/docs/doxygen-user_fr/images/DataSourceSummary/ds_summary_past_cases.png new file mode 100644 index 0000000000..4ac2623e6e Binary files /dev/null and b/docs/doxygen-user_fr/images/DataSourceSummary/ds_summary_past_cases.png differ diff --git a/docs/doxygen-user_fr/images/DataSourceSummary/ds_summary_recent_files.png b/docs/doxygen-user_fr/images/DataSourceSummary/ds_summary_recent_files.png new file mode 100644 index 0000000000..c9edf412ff Binary files /dev/null and b/docs/doxygen-user_fr/images/DataSourceSummary/ds_summary_recent_files.png differ diff --git a/docs/doxygen-user_fr/images/DataSourceSummary/ds_summary_result_viewer.png b/docs/doxygen-user_fr/images/DataSourceSummary/ds_summary_result_viewer.png new file mode 100644 index 0000000000..8f2b4d3f47 Binary files /dev/null and b/docs/doxygen-user_fr/images/DataSourceSummary/ds_summary_result_viewer.png differ diff --git a/docs/doxygen-user_fr/images/DataSourceSummary/ds_summary_timeline.png b/docs/doxygen-user_fr/images/DataSourceSummary/ds_summary_timeline.png new file mode 100644 index 0000000000..891802da42 Binary files /dev/null and b/docs/doxygen-user_fr/images/DataSourceSummary/ds_summary_timeline.png differ diff --git a/docs/doxygen-user_fr/images/DataSourceSummary/ds_summary_types.png b/docs/doxygen-user_fr/images/DataSourceSummary/ds_summary_types.png new file mode 100644 index 0000000000..b8dca4a984 Binary files /dev/null and b/docs/doxygen-user_fr/images/DataSourceSummary/ds_summary_types.png differ diff --git a/docs/doxygen-user_fr/images/DataSourceSummary/ds_summary_user_activity.png b/docs/doxygen-user_fr/images/DataSourceSummary/ds_summary_user_activity.png new file mode 100644 index 0000000000..089345f85b Binary files /dev/null and b/docs/doxygen-user_fr/images/DataSourceSummary/ds_summary_user_activity.png differ diff --git a/docs/doxygen-user_fr/images/DataSourceSummary/ds_summary_window.png b/docs/doxygen-user_fr/images/DataSourceSummary/ds_summary_window.png new file mode 100644 index 0000000000..547f42fab8 Binary files /dev/null and b/docs/doxygen-user_fr/images/DataSourceSummary/ds_summary_window.png differ diff --git a/docs/doxygen-user_fr/images/EXIF-heic.png b/docs/doxygen-user_fr/images/EXIF-heic.png new file mode 100644 index 0000000000..b3f1014326 Binary files /dev/null and b/docs/doxygen-user_fr/images/EXIF-heic.png differ diff --git a/docs/doxygen-user_fr/images/EXIF-tree.PNG b/docs/doxygen-user_fr/images/EXIF-tree.PNG new file mode 100644 index 0000000000..6fdc2efcd4 Binary files /dev/null and b/docs/doxygen-user_fr/images/EXIF-tree.PNG differ diff --git a/docs/doxygen-user_fr/images/FileDiscovery/fd_dataSourceFilter.png b/docs/doxygen-user_fr/images/FileDiscovery/fd_dataSourceFilter.png new file mode 100644 index 0000000000..fed4932bf0 Binary files /dev/null and b/docs/doxygen-user_fr/images/FileDiscovery/fd_dataSourceFilter.png differ diff --git a/docs/doxygen-user_fr/images/FileDiscovery/fd_dateFilter.png b/docs/doxygen-user_fr/images/FileDiscovery/fd_dateFilter.png new file mode 100644 index 0000000000..10f354661a Binary files /dev/null and b/docs/doxygen-user_fr/images/FileDiscovery/fd_dateFilter.png differ diff --git a/docs/doxygen-user_fr/images/FileDiscovery/fd_documents.png b/docs/doxygen-user_fr/images/FileDiscovery/fd_documents.png new file mode 100644 index 0000000000..3f60954eae Binary files /dev/null and b/docs/doxygen-user_fr/images/FileDiscovery/fd_documents.png differ diff --git a/docs/doxygen-user_fr/images/FileDiscovery/fd_domainDetails.png b/docs/doxygen-user_fr/images/FileDiscovery/fd_domainDetails.png new file mode 100644 index 0000000000..111f77c215 Binary files /dev/null and b/docs/doxygen-user_fr/images/FileDiscovery/fd_domainDetails.png differ diff --git a/docs/doxygen-user_fr/images/FileDiscovery/fd_domainResultFilter.png b/docs/doxygen-user_fr/images/FileDiscovery/fd_domainResultFilter.png new file mode 100644 index 0000000000..34ad45439d Binary files /dev/null and b/docs/doxygen-user_fr/images/FileDiscovery/fd_domainResultFilter.png differ diff --git a/docs/doxygen-user_fr/images/FileDiscovery/fd_domains.png b/docs/doxygen-user_fr/images/FileDiscovery/fd_domains.png new file mode 100644 index 0000000000..88df1ccb17 Binary files /dev/null and b/docs/doxygen-user_fr/images/FileDiscovery/fd_domains.png differ diff --git a/docs/doxygen-user_fr/images/FileDiscovery/fd_dupeEx.png b/docs/doxygen-user_fr/images/FileDiscovery/fd_dupeEx.png new file mode 100644 index 0000000000..e94e3d1339 Binary files /dev/null and b/docs/doxygen-user_fr/images/FileDiscovery/fd_dupeEx.png differ diff --git a/docs/doxygen-user_fr/images/FileDiscovery/fd_fileSizeFilter.png b/docs/doxygen-user_fr/images/FileDiscovery/fd_fileSizeFilter.png new file mode 100644 index 0000000000..d352f941a4 Binary files /dev/null and b/docs/doxygen-user_fr/images/FileDiscovery/fd_fileSizeFilter.png differ diff --git a/docs/doxygen-user_fr/images/FileDiscovery/fd_fileType.png b/docs/doxygen-user_fr/images/FileDiscovery/fd_fileType.png new file mode 100644 index 0000000000..75a46c4c36 Binary files /dev/null and b/docs/doxygen-user_fr/images/FileDiscovery/fd_fileType.png differ diff --git a/docs/doxygen-user_fr/images/FileDiscovery/fd_grouping.png b/docs/doxygen-user_fr/images/FileDiscovery/fd_grouping.png new file mode 100644 index 0000000000..1a671c8999 Binary files /dev/null and b/docs/doxygen-user_fr/images/FileDiscovery/fd_grouping.png differ diff --git a/docs/doxygen-user_fr/images/FileDiscovery/fd_groupingInt.png b/docs/doxygen-user_fr/images/FileDiscovery/fd_groupingInt.png new file mode 100644 index 0000000000..1de9099297 Binary files /dev/null and b/docs/doxygen-user_fr/images/FileDiscovery/fd_groupingInt.png differ diff --git a/docs/doxygen-user_fr/images/FileDiscovery/fd_groupingSize.png b/docs/doxygen-user_fr/images/FileDiscovery/fd_groupingSize.png new file mode 100644 index 0000000000..e21707eb44 Binary files /dev/null and b/docs/doxygen-user_fr/images/FileDiscovery/fd_groupingSize.png differ diff --git a/docs/doxygen-user_fr/images/FileDiscovery/fd_hashSetFilter.png b/docs/doxygen-user_fr/images/FileDiscovery/fd_hashSetFilter.png new file mode 100644 index 0000000000..b8d9a1f3fd Binary files /dev/null and b/docs/doxygen-user_fr/images/FileDiscovery/fd_hashSetFilter.png differ diff --git a/docs/doxygen-user_fr/images/FileDiscovery/fd_icon.png b/docs/doxygen-user_fr/images/FileDiscovery/fd_icon.png new file mode 100644 index 0000000000..9e29ceaf2b Binary files /dev/null and b/docs/doxygen-user_fr/images/FileDiscovery/fd_icon.png differ diff --git a/docs/doxygen-user_fr/images/FileDiscovery/fd_instanceContext.png b/docs/doxygen-user_fr/images/FileDiscovery/fd_instanceContext.png new file mode 100644 index 0000000000..e8d7961da2 Binary files /dev/null and b/docs/doxygen-user_fr/images/FileDiscovery/fd_instanceContext.png differ diff --git a/docs/doxygen-user_fr/images/FileDiscovery/fd_interestingItemsFilter.png b/docs/doxygen-user_fr/images/FileDiscovery/fd_interestingItemsFilter.png new file mode 100644 index 0000000000..df3d443575 Binary files /dev/null and b/docs/doxygen-user_fr/images/FileDiscovery/fd_interestingItemsFilter.png differ diff --git a/docs/doxygen-user_fr/images/FileDiscovery/fd_knownAccountFilter.png b/docs/doxygen-user_fr/images/FileDiscovery/fd_knownAccountFilter.png new file mode 100644 index 0000000000..10d62bc4a9 Binary files /dev/null and b/docs/doxygen-user_fr/images/FileDiscovery/fd_knownAccountFilter.png differ diff --git a/docs/doxygen-user_fr/images/FileDiscovery/fd_loadSettings.png b/docs/doxygen-user_fr/images/FileDiscovery/fd_loadSettings.png new file mode 100644 index 0000000000..0ed2169853 Binary files /dev/null and b/docs/doxygen-user_fr/images/FileDiscovery/fd_loadSettings.png differ diff --git a/docs/doxygen-user_fr/images/FileDiscovery/fd_main.png b/docs/doxygen-user_fr/images/FileDiscovery/fd_main.png new file mode 100644 index 0000000000..69e7a109a9 Binary files /dev/null and b/docs/doxygen-user_fr/images/FileDiscovery/fd_main.png differ diff --git a/docs/doxygen-user_fr/images/FileDiscovery/fd_notableFilter.png b/docs/doxygen-user_fr/images/FileDiscovery/fd_notableFilter.png new file mode 100644 index 0000000000..0ce100ef98 Binary files /dev/null and b/docs/doxygen-user_fr/images/FileDiscovery/fd_notableFilter.png differ diff --git a/docs/doxygen-user_fr/images/FileDiscovery/fd_objectFilter.png b/docs/doxygen-user_fr/images/FileDiscovery/fd_objectFilter.png new file mode 100644 index 0000000000..fae7f9a3ce Binary files /dev/null and b/docs/doxygen-user_fr/images/FileDiscovery/fd_objectFilter.png differ diff --git a/docs/doxygen-user_fr/images/FileDiscovery/fd_paging.png b/docs/doxygen-user_fr/images/FileDiscovery/fd_paging.png new file mode 100644 index 0000000000..060e66e0ec Binary files /dev/null and b/docs/doxygen-user_fr/images/FileDiscovery/fd_paging.png differ diff --git a/docs/doxygen-user_fr/images/FileDiscovery/fd_parentEx2.png b/docs/doxygen-user_fr/images/FileDiscovery/fd_parentEx2.png new file mode 100644 index 0000000000..102f39f92b Binary files /dev/null and b/docs/doxygen-user_fr/images/FileDiscovery/fd_parentEx2.png differ diff --git a/docs/doxygen-user_fr/images/FileDiscovery/fd_parentFilter.png b/docs/doxygen-user_fr/images/FileDiscovery/fd_parentFilter.png new file mode 100644 index 0000000000..5cf24a7fda Binary files /dev/null and b/docs/doxygen-user_fr/images/FileDiscovery/fd_parentFilter.png differ diff --git a/docs/doxygen-user_fr/images/FileDiscovery/fd_pastOccur.png b/docs/doxygen-user_fr/images/FileDiscovery/fd_pastOccur.png new file mode 100644 index 0000000000..5f816cc4f8 Binary files /dev/null and b/docs/doxygen-user_fr/images/FileDiscovery/fd_pastOccur.png differ diff --git a/docs/doxygen-user_fr/images/FileDiscovery/fd_resultGroups.png b/docs/doxygen-user_fr/images/FileDiscovery/fd_resultGroups.png new file mode 100644 index 0000000000..5872da0ad1 Binary files /dev/null and b/docs/doxygen-user_fr/images/FileDiscovery/fd_resultGroups.png differ diff --git a/docs/doxygen-user_fr/images/FileDiscovery/fd_setup.png b/docs/doxygen-user_fr/images/FileDiscovery/fd_setup.png new file mode 100644 index 0000000000..4b73514a9f Binary files /dev/null and b/docs/doxygen-user_fr/images/FileDiscovery/fd_setup.png differ diff --git a/docs/doxygen-user_fr/images/FileDiscovery/fd_userContentArtifact.png b/docs/doxygen-user_fr/images/FileDiscovery/fd_userContentArtifact.png new file mode 100644 index 0000000000..f4af8f8fb6 Binary files /dev/null and b/docs/doxygen-user_fr/images/FileDiscovery/fd_userContentArtifact.png differ diff --git a/docs/doxygen-user_fr/images/FileDiscovery/fd_userCreatedFilter.png b/docs/doxygen-user_fr/images/FileDiscovery/fd_userCreatedFilter.png new file mode 100644 index 0000000000..510624fcd0 Binary files /dev/null and b/docs/doxygen-user_fr/images/FileDiscovery/fd_userCreatedFilter.png differ diff --git a/docs/doxygen-user_fr/images/FileDiscovery/fd_videos.png b/docs/doxygen-user_fr/images/FileDiscovery/fd_videos.png new file mode 100644 index 0000000000..4cf58e29a6 Binary files /dev/null and b/docs/doxygen-user_fr/images/FileDiscovery/fd_videos.png differ diff --git a/docs/doxygen-user_fr/images/FileDiscovery/file-icon-deleted.png b/docs/doxygen-user_fr/images/FileDiscovery/file-icon-deleted.png new file mode 100644 index 0000000000..ef172e501b Binary files /dev/null and b/docs/doxygen-user_fr/images/FileDiscovery/file-icon-deleted.png differ diff --git a/docs/doxygen-user_fr/images/FileDiscovery/red-circle-exclamation.png b/docs/doxygen-user_fr/images/FileDiscovery/red-circle-exclamation.png new file mode 100644 index 0000000000..26b61e6f06 Binary files /dev/null and b/docs/doxygen-user_fr/images/FileDiscovery/red-circle-exclamation.png differ diff --git a/docs/doxygen-user_fr/images/FileDiscovery/yellow-circle-yield.png b/docs/doxygen-user_fr/images/FileDiscovery/yellow-circle-yield.png new file mode 100644 index 0000000000..85c873f33f Binary files /dev/null and b/docs/doxygen-user_fr/images/FileDiscovery/yellow-circle-yield.png differ diff --git a/docs/doxygen-user_fr/images/ImageGallery/application_view_tile.PNG b/docs/doxygen-user_fr/images/ImageGallery/application_view_tile.PNG new file mode 100644 index 0000000000..3bc0bd32fc Binary files /dev/null and b/docs/doxygen-user_fr/images/ImageGallery/application_view_tile.PNG differ diff --git a/docs/doxygen-user_fr/images/ImageGallery/bisque.PNG b/docs/doxygen-user_fr/images/ImageGallery/bisque.PNG new file mode 100644 index 0000000000..f99cc0d1e5 Binary files /dev/null and b/docs/doxygen-user_fr/images/ImageGallery/bisque.PNG differ diff --git a/docs/doxygen-user_fr/images/ImageGallery/drawabletile.PNG b/docs/doxygen-user_fr/images/ImageGallery/drawabletile.PNG new file mode 100644 index 0000000000..d6b97547bc Binary files /dev/null and b/docs/doxygen-user_fr/images/ImageGallery/drawabletile.PNG differ diff --git a/docs/doxygen-user_fr/images/ImageGallery/flag_gray.PNG b/docs/doxygen-user_fr/images/ImageGallery/flag_gray.PNG new file mode 100644 index 0000000000..1888f8da96 Binary files /dev/null and b/docs/doxygen-user_fr/images/ImageGallery/flag_gray.PNG differ diff --git a/docs/doxygen-user_fr/images/ImageGallery/flag_red.PNG b/docs/doxygen-user_fr/images/ImageGallery/flag_red.PNG new file mode 100644 index 0000000000..e8a602da7b Binary files /dev/null and b/docs/doxygen-user_fr/images/ImageGallery/flag_red.PNG differ diff --git a/docs/doxygen-user_fr/images/ImageGallery/folder_picture.PNG b/docs/doxygen-user_fr/images/ImageGallery/folder_picture.PNG new file mode 100644 index 0000000000..052b33638e Binary files /dev/null and b/docs/doxygen-user_fr/images/ImageGallery/folder_picture.PNG differ diff --git a/docs/doxygen-user_fr/images/ImageGallery/gray.PNG b/docs/doxygen-user_fr/images/ImageGallery/gray.PNG new file mode 100644 index 0000000000..538aaacd46 Binary files /dev/null and b/docs/doxygen-user_fr/images/ImageGallery/gray.PNG differ diff --git a/docs/doxygen-user_fr/images/ImageGallery/green.PNG b/docs/doxygen-user_fr/images/ImageGallery/green.PNG new file mode 100644 index 0000000000..6aa2f63211 Binary files /dev/null and b/docs/doxygen-user_fr/images/ImageGallery/green.PNG differ diff --git a/docs/doxygen-user_fr/images/ImageGallery/hashset_hits.PNG b/docs/doxygen-user_fr/images/ImageGallery/hashset_hits.PNG new file mode 100644 index 0000000000..f1caff1f30 Binary files /dev/null and b/docs/doxygen-user_fr/images/ImageGallery/hashset_hits.PNG differ diff --git a/docs/doxygen-user_fr/images/ImageGallery/orange.PNG b/docs/doxygen-user_fr/images/ImageGallery/orange.PNG new file mode 100644 index 0000000000..97ef5d24b6 Binary files /dev/null and b/docs/doxygen-user_fr/images/ImageGallery/orange.PNG differ diff --git a/docs/doxygen-user_fr/images/ImageGallery/purpledash.PNG b/docs/doxygen-user_fr/images/ImageGallery/purpledash.PNG new file mode 100644 index 0000000000..edd815d641 Binary files /dev/null and b/docs/doxygen-user_fr/images/ImageGallery/purpledash.PNG differ diff --git a/docs/doxygen-user_fr/images/ImageGallery/red.PNG b/docs/doxygen-user_fr/images/ImageGallery/red.PNG new file mode 100644 index 0000000000..2e5d76720d Binary files /dev/null and b/docs/doxygen-user_fr/images/ImageGallery/red.PNG differ diff --git a/docs/doxygen-user_fr/images/ImageGallery/slide.PNG b/docs/doxygen-user_fr/images/ImageGallery/slide.PNG new file mode 100644 index 0000000000..8f1ae4496e Binary files /dev/null and b/docs/doxygen-user_fr/images/ImageGallery/slide.PNG differ diff --git a/docs/doxygen-user_fr/images/ImageGallery/video-file.PNG b/docs/doxygen-user_fr/images/ImageGallery/video-file.PNG new file mode 100644 index 0000000000..c290609f59 Binary files /dev/null and b/docs/doxygen-user_fr/images/ImageGallery/video-file.PNG differ diff --git a/docs/doxygen-user_fr/images/ImageGallery/yellow.PNG b/docs/doxygen-user_fr/images/ImageGallery/yellow.PNG new file mode 100644 index 0000000000..0e593b22d3 Binary files /dev/null and b/docs/doxygen-user_fr/images/ImageGallery/yellow.PNG differ diff --git a/docs/doxygen-user_fr/images/InterestingFiles/bomb_png.png b/docs/doxygen-user_fr/images/InterestingFiles/bomb_png.png new file mode 100644 index 0000000000..016ff5dea5 Binary files /dev/null and b/docs/doxygen-user_fr/images/InterestingFiles/bomb_png.png differ diff --git a/docs/doxygen-user_fr/images/InterestingFiles/download_archive.png b/docs/doxygen-user_fr/images/InterestingFiles/download_archive.png new file mode 100644 index 0000000000..aa457e929c Binary files /dev/null and b/docs/doxygen-user_fr/images/InterestingFiles/download_archive.png differ diff --git a/docs/doxygen-user_fr/images/InterestingFiles/if_create_set.png b/docs/doxygen-user_fr/images/InterestingFiles/if_create_set.png new file mode 100644 index 0000000000..6302a6026c Binary files /dev/null and b/docs/doxygen-user_fr/images/InterestingFiles/if_create_set.png differ diff --git a/docs/doxygen-user_fr/images/InterestingFiles/if_export.png b/docs/doxygen-user_fr/images/InterestingFiles/if_export.png new file mode 100644 index 0000000000..7743689db4 Binary files /dev/null and b/docs/doxygen-user_fr/images/InterestingFiles/if_export.png differ diff --git a/docs/doxygen-user_fr/images/InterestingFiles/if_new_rule.png b/docs/doxygen-user_fr/images/InterestingFiles/if_new_rule.png new file mode 100644 index 0000000000..826b2b1203 Binary files /dev/null and b/docs/doxygen-user_fr/images/InterestingFiles/if_new_rule.png differ diff --git a/docs/doxygen-user_fr/images/InterestingFiles/if_official_rule_details.png b/docs/doxygen-user_fr/images/InterestingFiles/if_official_rule_details.png new file mode 100644 index 0000000000..669a5d4dca Binary files /dev/null and b/docs/doxygen-user_fr/images/InterestingFiles/if_official_rule_details.png differ diff --git a/docs/doxygen-user_fr/images/InterestingFiles/ingest.png b/docs/doxygen-user_fr/images/InterestingFiles/ingest.png new file mode 100644 index 0000000000..9dedfd045b Binary files /dev/null and b/docs/doxygen-user_fr/images/InterestingFiles/ingest.png differ diff --git a/docs/doxygen-user_fr/images/InterestingFiles/main.png b/docs/doxygen-user_fr/images/InterestingFiles/main.png new file mode 100644 index 0000000000..fd74aa70a5 Binary files /dev/null and b/docs/doxygen-user_fr/images/InterestingFiles/main.png differ diff --git a/docs/doxygen-user_fr/images/InterestingFiles/new_large_files.png b/docs/doxygen-user_fr/images/InterestingFiles/new_large_files.png new file mode 100644 index 0000000000..a159f5af1f Binary files /dev/null and b/docs/doxygen-user_fr/images/InterestingFiles/new_large_files.png differ diff --git a/docs/doxygen-user_fr/images/InterestingFiles/new_rule.png b/docs/doxygen-user_fr/images/InterestingFiles/new_rule.png new file mode 100644 index 0000000000..3385a402c0 Binary files /dev/null and b/docs/doxygen-user_fr/images/InterestingFiles/new_rule.png differ diff --git a/docs/doxygen-user_fr/images/InterestingFiles/new_rule_set.png b/docs/doxygen-user_fr/images/InterestingFiles/new_rule_set.png new file mode 100644 index 0000000000..eb857b4734 Binary files /dev/null and b/docs/doxygen-user_fr/images/InterestingFiles/new_rule_set.png differ diff --git a/docs/doxygen-user_fr/images/InterestingFiles/private_folder.png b/docs/doxygen-user_fr/images/InterestingFiles/private_folder.png new file mode 100644 index 0000000000..706bbeca57 Binary files /dev/null and b/docs/doxygen-user_fr/images/InterestingFiles/private_folder.png differ diff --git a/docs/doxygen-user_fr/images/InterestingFiles/results.png b/docs/doxygen-user_fr/images/InterestingFiles/results.png new file mode 100644 index 0000000000..9ce29ceaea Binary files /dev/null and b/docs/doxygen-user_fr/images/InterestingFiles/results.png differ diff --git a/docs/doxygen-user_fr/images/JRE_bitness.PNG b/docs/doxygen-user_fr/images/JRE_bitness.PNG new file mode 100644 index 0000000000..d558822392 Binary files /dev/null and b/docs/doxygen-user_fr/images/JRE_bitness.PNG differ diff --git a/docs/doxygen-user_fr/images/LogicalImager/VHDfolder.png b/docs/doxygen-user_fr/images/LogicalImager/VHDfolder.png new file mode 100644 index 0000000000..edd4b3e0ce Binary files /dev/null and b/docs/doxygen-user_fr/images/LogicalImager/VHDfolder.png differ diff --git a/docs/doxygen-user_fr/images/LogicalImager/command_prompt.png b/docs/doxygen-user_fr/images/LogicalImager/command_prompt.png new file mode 100644 index 0000000000..d4c33ebd13 Binary files /dev/null and b/docs/doxygen-user_fr/images/LogicalImager/command_prompt.png differ diff --git a/docs/doxygen-user_fr/images/LogicalImager/config_flag.png b/docs/doxygen-user_fr/images/LogicalImager/config_flag.png new file mode 100644 index 0000000000..0cecc4bedb Binary files /dev/null and b/docs/doxygen-user_fr/images/LogicalImager/config_flag.png differ diff --git a/docs/doxygen-user_fr/images/LogicalImager/configure_drive.png b/docs/doxygen-user_fr/images/LogicalImager/configure_drive.png new file mode 100644 index 0000000000..186f98310e Binary files /dev/null and b/docs/doxygen-user_fr/images/LogicalImager/configure_drive.png differ diff --git a/docs/doxygen-user_fr/images/LogicalImager/dsp_select.png b/docs/doxygen-user_fr/images/LogicalImager/dsp_select.png new file mode 100644 index 0000000000..e40d980044 Binary files /dev/null and b/docs/doxygen-user_fr/images/LogicalImager/dsp_select.png differ diff --git a/docs/doxygen-user_fr/images/LogicalImager/exe_folder.png b/docs/doxygen-user_fr/images/LogicalImager/exe_folder.png new file mode 100644 index 0000000000..3891f14f80 Binary files /dev/null and b/docs/doxygen-user_fr/images/LogicalImager/exe_folder.png differ diff --git a/docs/doxygen-user_fr/images/LogicalImager/fileTree.png b/docs/doxygen-user_fr/images/LogicalImager/fileTree.png new file mode 100644 index 0000000000..dd0ba5175f Binary files /dev/null and b/docs/doxygen-user_fr/images/LogicalImager/fileTree.png differ diff --git a/docs/doxygen-user_fr/images/LogicalImager/full_path_rule.png b/docs/doxygen-user_fr/images/LogicalImager/full_path_rule.png new file mode 100644 index 0000000000..2471c02e4f Binary files /dev/null and b/docs/doxygen-user_fr/images/LogicalImager/full_path_rule.png differ diff --git a/docs/doxygen-user_fr/images/LogicalImager/image_flag.png b/docs/doxygen-user_fr/images/LogicalImager/image_flag.png new file mode 100644 index 0000000000..cdc0b2a611 Binary files /dev/null and b/docs/doxygen-user_fr/images/LogicalImager/image_flag.png differ diff --git a/docs/doxygen-user_fr/images/LogicalImager/import.png b/docs/doxygen-user_fr/images/LogicalImager/import.png new file mode 100644 index 0000000000..2e3155b26e Binary files /dev/null and b/docs/doxygen-user_fr/images/LogicalImager/import.png differ diff --git a/docs/doxygen-user_fr/images/LogicalImager/interestingFiles.png b/docs/doxygen-user_fr/images/LogicalImager/interestingFiles.png new file mode 100644 index 0000000000..f961eca707 Binary files /dev/null and b/docs/doxygen-user_fr/images/LogicalImager/interestingFiles.png differ diff --git a/docs/doxygen-user_fr/images/LogicalImager/main_config_panel.png b/docs/doxygen-user_fr/images/LogicalImager/main_config_panel.png new file mode 100644 index 0000000000..a1b40a0fa4 Binary files /dev/null and b/docs/doxygen-user_fr/images/LogicalImager/main_config_panel.png differ diff --git a/docs/doxygen-user_fr/images/LogicalImager/new_attr_rule.png b/docs/doxygen-user_fr/images/LogicalImager/new_attr_rule.png new file mode 100644 index 0000000000..827ff7d19d Binary files /dev/null and b/docs/doxygen-user_fr/images/LogicalImager/new_attr_rule.png differ diff --git a/docs/doxygen-user_fr/images/LogicalImager/nonVHDexport.png b/docs/doxygen-user_fr/images/LogicalImager/nonVHDexport.png new file mode 100644 index 0000000000..5e655a39a9 Binary files /dev/null and b/docs/doxygen-user_fr/images/LogicalImager/nonVHDexport.png differ diff --git a/docs/doxygen-user_fr/images/LogicalImager/nonVHDfolder.png b/docs/doxygen-user_fr/images/LogicalImager/nonVHDfolder.png new file mode 100644 index 0000000000..1042e5a13b Binary files /dev/null and b/docs/doxygen-user_fr/images/LogicalImager/nonVHDfolder.png differ diff --git a/docs/doxygen-user_fr/images/LogicalImager/output_folder.png b/docs/doxygen-user_fr/images/LogicalImager/output_folder.png new file mode 100644 index 0000000000..ff24f8ba87 Binary files /dev/null and b/docs/doxygen-user_fr/images/LogicalImager/output_folder.png differ diff --git a/docs/doxygen-user_fr/images/LogicalImager/save.png b/docs/doxygen-user_fr/images/LogicalImager/save.png new file mode 100644 index 0000000000..6b9281081a Binary files /dev/null and b/docs/doxygen-user_fr/images/LogicalImager/save.png differ diff --git a/docs/doxygen-user_fr/images/LogicalImager/select_folder.png b/docs/doxygen-user_fr/images/LogicalImager/select_folder.png new file mode 100644 index 0000000000..84b0ed66e0 Binary files /dev/null and b/docs/doxygen-user_fr/images/LogicalImager/select_folder.png differ diff --git a/docs/doxygen-user_fr/images/LogicalImager/tools_menu.png b/docs/doxygen-user_fr/images/LogicalImager/tools_menu.png new file mode 100644 index 0000000000..1a203de29a Binary files /dev/null and b/docs/doxygen-user_fr/images/LogicalImager/tools_menu.png differ diff --git a/docs/doxygen-user_fr/images/Personas/persona_edit.png b/docs/doxygen-user_fr/images/Personas/persona_edit.png new file mode 100644 index 0000000000..2f2bde865f Binary files /dev/null and b/docs/doxygen-user_fr/images/Personas/persona_edit.png differ diff --git a/docs/doxygen-user_fr/images/Personas/personas_calllog.png b/docs/doxygen-user_fr/images/Personas/personas_calllog.png new file mode 100644 index 0000000000..63e0a4b01a Binary files /dev/null and b/docs/doxygen-user_fr/images/Personas/personas_calllog.png differ diff --git a/docs/doxygen-user_fr/images/Personas/personas_contact_found.png b/docs/doxygen-user_fr/images/Personas/personas_contact_found.png new file mode 100644 index 0000000000..b32d39936c Binary files /dev/null and b/docs/doxygen-user_fr/images/Personas/personas_contact_found.png differ diff --git a/docs/doxygen-user_fr/images/Personas/personas_contact_not_found.png b/docs/doxygen-user_fr/images/Personas/personas_contact_not_found.png new file mode 100644 index 0000000000..e221e775f5 Binary files /dev/null and b/docs/doxygen-user_fr/images/Personas/personas_contact_not_found.png differ diff --git a/docs/doxygen-user_fr/images/Personas/personas_create.png b/docs/doxygen-user_fr/images/Personas/personas_create.png new file mode 100644 index 0000000000..5da750d572 Binary files /dev/null and b/docs/doxygen-user_fr/images/Personas/personas_create.png differ diff --git a/docs/doxygen-user_fr/images/Personas/personas_create_account.png b/docs/doxygen-user_fr/images/Personas/personas_create_account.png new file mode 100644 index 0000000000..17a89fffd8 Binary files /dev/null and b/docs/doxygen-user_fr/images/Personas/personas_create_account.png differ diff --git a/docs/doxygen-user_fr/images/Personas/personas_cvt_accounts.png b/docs/doxygen-user_fr/images/Personas/personas_cvt_accounts.png new file mode 100644 index 0000000000..87a5a2755e Binary files /dev/null and b/docs/doxygen-user_fr/images/Personas/personas_cvt_accounts.png differ diff --git a/docs/doxygen-user_fr/images/Personas/personas_cvt_hover.png b/docs/doxygen-user_fr/images/Personas/personas_cvt_hover.png new file mode 100644 index 0000000000..a16b6d8f71 Binary files /dev/null and b/docs/doxygen-user_fr/images/Personas/personas_cvt_hover.png differ diff --git a/docs/doxygen-user_fr/images/Personas/personas_main.png b/docs/doxygen-user_fr/images/Personas/personas_main.png new file mode 100644 index 0000000000..b5aa67bd5b Binary files /dev/null and b/docs/doxygen-user_fr/images/Personas/personas_main.png differ diff --git a/docs/doxygen-user_fr/images/Personas/personas_message.png b/docs/doxygen-user_fr/images/Personas/personas_message.png new file mode 100644 index 0000000000..4d39e0aa41 Binary files /dev/null and b/docs/doxygen-user_fr/images/Personas/personas_message.png differ diff --git a/docs/doxygen-user_fr/images/StartActiveMQService.PNG b/docs/doxygen-user_fr/images/StartActiveMQService.PNG new file mode 100644 index 0000000000..2aa68fc0f7 Binary files /dev/null and b/docs/doxygen-user_fr/images/StartActiveMQService.PNG differ diff --git a/docs/doxygen-user_fr/images/StopActiveMQService.PNG b/docs/doxygen-user_fr/images/StopActiveMQService.PNG new file mode 100644 index 0000000000..31b5a0da0c Binary files /dev/null and b/docs/doxygen-user_fr/images/StopActiveMQService.PNG differ diff --git a/docs/doxygen-user_fr/images/activeMQ_node_cleanup.png b/docs/doxygen-user_fr/images/activeMQ_node_cleanup.png new file mode 100644 index 0000000000..3df88436b5 Binary files /dev/null and b/docs/doxygen-user_fr/images/activeMQ_node_cleanup.png differ diff --git a/docs/doxygen-user_fr/images/activemq.PNG b/docs/doxygen-user_fr/images/activemq.PNG new file mode 100644 index 0000000000..9118780f7a Binary files /dev/null and b/docs/doxygen-user_fr/images/activemq.PNG differ diff --git a/docs/doxygen-user_fr/images/add-data-source.PNG b/docs/doxygen-user_fr/images/add-data-source.PNG new file mode 100644 index 0000000000..56a1212159 Binary files /dev/null and b/docs/doxygen-user_fr/images/add-data-source.PNG differ diff --git a/docs/doxygen-user_fr/images/aleapp_main.jpg b/docs/doxygen-user_fr/images/aleapp_main.jpg new file mode 100644 index 0000000000..d318748a6d Binary files /dev/null and b/docs/doxygen-user_fr/images/aleapp_main.jpg differ diff --git a/docs/doxygen-user_fr/images/android_analyzer_output.PNG b/docs/doxygen-user_fr/images/android_analyzer_output.PNG new file mode 100644 index 0000000000..91606a187b Binary files /dev/null and b/docs/doxygen-user_fr/images/android_analyzer_output.PNG differ diff --git a/docs/doxygen-user_fr/images/apachebadmessage.PNG b/docs/doxygen-user_fr/images/apachebadmessage.PNG new file mode 100644 index 0000000000..b2d7566df4 Binary files /dev/null and b/docs/doxygen-user_fr/images/apachebadmessage.PNG differ diff --git a/docs/doxygen-user_fr/images/case-newcase.PNG b/docs/doxygen-user_fr/images/case-newcase.PNG new file mode 100644 index 0000000000..4f4050a6a8 Binary files /dev/null and b/docs/doxygen-user_fr/images/case-newcase.PNG differ diff --git a/docs/doxygen-user_fr/images/case_properties.png b/docs/doxygen-user_fr/images/case_properties.png new file mode 100644 index 0000000000..9079484f6f Binary files /dev/null and b/docs/doxygen-user_fr/images/case_properties.png differ diff --git a/docs/doxygen-user_fr/images/central_repo_content_viewer.png b/docs/doxygen-user_fr/images/central_repo_content_viewer.png new file mode 100644 index 0000000000..55ef8e2398 Binary files /dev/null and b/docs/doxygen-user_fr/images/central_repo_content_viewer.png differ diff --git a/docs/doxygen-user_fr/images/central_repo_details.png b/docs/doxygen-user_fr/images/central_repo_details.png new file mode 100644 index 0000000000..cef6c7ceca Binary files /dev/null and b/docs/doxygen-user_fr/images/central_repo_details.png differ diff --git a/docs/doxygen-user_fr/images/central_repo_ingest_settings.png b/docs/doxygen-user_fr/images/central_repo_ingest_settings.png new file mode 100644 index 0000000000..dec839f689 Binary files /dev/null and b/docs/doxygen-user_fr/images/central_repo_ingest_settings.png differ diff --git a/docs/doxygen-user_fr/images/central_repo_interesting_items.png b/docs/doxygen-user_fr/images/central_repo_interesting_items.png new file mode 100644 index 0000000000..2c689eb67b Binary files /dev/null and b/docs/doxygen-user_fr/images/central_repo_interesting_items.png differ diff --git a/docs/doxygen-user_fr/images/central_repo_manage_tags.png b/docs/doxygen-user_fr/images/central_repo_manage_tags.png new file mode 100644 index 0000000000..ce78a3a373 Binary files /dev/null and b/docs/doxygen-user_fr/images/central_repo_manage_tags.png differ diff --git a/docs/doxygen-user_fr/images/central_repo_new_org.png b/docs/doxygen-user_fr/images/central_repo_new_org.png new file mode 100644 index 0000000000..33276efc27 Binary files /dev/null and b/docs/doxygen-user_fr/images/central_repo_new_org.png differ diff --git a/docs/doxygen-user_fr/images/central_repo_options.png b/docs/doxygen-user_fr/images/central_repo_options.png new file mode 100644 index 0000000000..07873d8be8 Binary files /dev/null and b/docs/doxygen-user_fr/images/central_repo_options.png differ diff --git a/docs/doxygen-user_fr/images/central_repo_orgs.png b/docs/doxygen-user_fr/images/central_repo_orgs.png new file mode 100644 index 0000000000..3637e18f6d Binary files /dev/null and b/docs/doxygen-user_fr/images/central_repo_orgs.png differ diff --git a/docs/doxygen-user_fr/images/central_repo_postgres.png b/docs/doxygen-user_fr/images/central_repo_postgres.png new file mode 100644 index 0000000000..ecaacff69e Binary files /dev/null and b/docs/doxygen-user_fr/images/central_repo_postgres.png differ diff --git a/docs/doxygen-user_fr/images/central_repo_sqlite.png b/docs/doxygen-user_fr/images/central_repo_sqlite.png new file mode 100644 index 0000000000..1a1f633659 Binary files /dev/null and b/docs/doxygen-user_fr/images/central_repo_sqlite.png differ diff --git a/docs/doxygen-user_fr/images/central_repo_tag_file.png b/docs/doxygen-user_fr/images/central_repo_tag_file.png new file mode 100644 index 0000000000..b84d4b52d9 Binary files /dev/null and b/docs/doxygen-user_fr/images/central_repo_tag_file.png differ diff --git a/docs/doxygen-user_fr/images/central_repo_types.png b/docs/doxygen-user_fr/images/central_repo_types.png new file mode 100644 index 0000000000..96b70b149e Binary files /dev/null and b/docs/doxygen-user_fr/images/central_repo_types.png differ diff --git a/docs/doxygen-user_fr/images/change_logical_file_set_display_name.PNG b/docs/doxygen-user_fr/images/change_logical_file_set_display_name.PNG new file mode 100644 index 0000000000..dfaa158c0f Binary files /dev/null and b/docs/doxygen-user_fr/images/change_logical_file_set_display_name.PNG differ diff --git a/docs/doxygen-user_fr/images/command_line_ingest_bin_dir.png b/docs/doxygen-user_fr/images/command_line_ingest_bin_dir.png new file mode 100644 index 0000000000..5f23d867e1 Binary files /dev/null and b/docs/doxygen-user_fr/images/command_line_ingest_bin_dir.png differ diff --git a/docs/doxygen-user_fr/images/command_line_ingest_case_folder.png b/docs/doxygen-user_fr/images/command_line_ingest_case_folder.png new file mode 100644 index 0000000000..e156cf5688 Binary files /dev/null and b/docs/doxygen-user_fr/images/command_line_ingest_case_folder.png differ diff --git a/docs/doxygen-user_fr/images/command_line_ingest_command_entry.png b/docs/doxygen-user_fr/images/command_line_ingest_command_entry.png new file mode 100644 index 0000000000..2f19ffa098 Binary files /dev/null and b/docs/doxygen-user_fr/images/command_line_ingest_command_entry.png differ diff --git a/docs/doxygen-user_fr/images/command_line_ingest_console_output.png b/docs/doxygen-user_fr/images/command_line_ingest_console_output.png new file mode 100644 index 0000000000..a17285db1b Binary files /dev/null and b/docs/doxygen-user_fr/images/command_line_ingest_console_output.png differ diff --git a/docs/doxygen-user_fr/images/command_line_ingest_dialog.png b/docs/doxygen-user_fr/images/command_line_ingest_dialog.png new file mode 100644 index 0000000000..5b4a050140 Binary files /dev/null and b/docs/doxygen-user_fr/images/command_line_ingest_dialog.png differ diff --git a/docs/doxygen-user_fr/images/command_line_ingest_open_case.png b/docs/doxygen-user_fr/images/command_line_ingest_open_case.png new file mode 100644 index 0000000000..2a216bae1b Binary files /dev/null and b/docs/doxygen-user_fr/images/command_line_ingest_open_case.png differ diff --git a/docs/doxygen-user_fr/images/command_line_ingest_options.png b/docs/doxygen-user_fr/images/command_line_ingest_options.png new file mode 100644 index 0000000000..4e42611368 Binary files /dev/null and b/docs/doxygen-user_fr/images/command_line_ingest_options.png differ diff --git a/docs/doxygen-user_fr/images/command_line_ingest_output_folder.png b/docs/doxygen-user_fr/images/command_line_ingest_output_folder.png new file mode 100644 index 0000000000..36ca54b99e Binary files /dev/null and b/docs/doxygen-user_fr/images/command_line_ingest_output_folder.png differ diff --git a/docs/doxygen-user_fr/images/command_line_ingest_profile.png b/docs/doxygen-user_fr/images/command_line_ingest_profile.png new file mode 100644 index 0000000000..8d417c837c Binary files /dev/null and b/docs/doxygen-user_fr/images/command_line_ingest_profile.png differ diff --git a/docs/doxygen-user_fr/images/command_line_ingest_report.png b/docs/doxygen-user_fr/images/command_line_ingest_report.png new file mode 100644 index 0000000000..13070eeccd Binary files /dev/null and b/docs/doxygen-user_fr/images/command_line_ingest_report.png differ diff --git a/docs/doxygen-user_fr/images/common_properties_cr.png b/docs/doxygen-user_fr/images/common_properties_cr.png new file mode 100644 index 0000000000..007570aa44 Binary files /dev/null and b/docs/doxygen-user_fr/images/common_properties_cr.png differ diff --git a/docs/doxygen-user_fr/images/common_properties_cr_case_select.png b/docs/doxygen-user_fr/images/common_properties_cr_case_select.png new file mode 100644 index 0000000000..ef4f0327b1 Binary files /dev/null and b/docs/doxygen-user_fr/images/common_properties_cr_case_select.png differ diff --git a/docs/doxygen-user_fr/images/common_properties_cr_property.png b/docs/doxygen-user_fr/images/common_properties_cr_property.png new file mode 100644 index 0000000000..9105ad6e41 Binary files /dev/null and b/docs/doxygen-user_fr/images/common_properties_cr_property.png differ diff --git a/docs/doxygen-user_fr/images/common_properties_intra_case.png b/docs/doxygen-user_fr/images/common_properties_intra_case.png new file mode 100644 index 0000000000..044eef3c8e Binary files /dev/null and b/docs/doxygen-user_fr/images/common_properties_intra_case.png differ diff --git a/docs/doxygen-user_fr/images/common_properties_result.png b/docs/doxygen-user_fr/images/common_properties_result.png new file mode 100644 index 0000000000..575078a0ab Binary files /dev/null and b/docs/doxygen-user_fr/images/common_properties_result.png differ diff --git a/docs/doxygen-user_fr/images/common_properties_result_case_sort.png b/docs/doxygen-user_fr/images/common_properties_result_case_sort.png new file mode 100644 index 0000000000..d4c61150af Binary files /dev/null and b/docs/doxygen-user_fr/images/common_properties_result_case_sort.png differ diff --git a/docs/doxygen-user_fr/images/common_properties_select_ds.png b/docs/doxygen-user_fr/images/common_properties_select_ds.png new file mode 100644 index 0000000000..a0ac3e83fc Binary files /dev/null and b/docs/doxygen-user_fr/images/common_properties_select_ds.png differ diff --git a/docs/doxygen-user_fr/images/content_viewer_annotations.png b/docs/doxygen-user_fr/images/content_viewer_annotations.png new file mode 100644 index 0000000000..445b96372e Binary files /dev/null and b/docs/doxygen-user_fr/images/content_viewer_annotations.png differ diff --git a/docs/doxygen-user_fr/images/content_viewer_app_image.png b/docs/doxygen-user_fr/images/content_viewer_app_image.png new file mode 100644 index 0000000000..50bfe7473d Binary files /dev/null and b/docs/doxygen-user_fr/images/content_viewer_app_image.png differ diff --git a/docs/doxygen-user_fr/images/content_viewer_app_plist.png b/docs/doxygen-user_fr/images/content_viewer_app_plist.png new file mode 100644 index 0000000000..749a5d4f93 Binary files /dev/null and b/docs/doxygen-user_fr/images/content_viewer_app_plist.png differ diff --git a/docs/doxygen-user_fr/images/content_viewer_app_sqlite.png b/docs/doxygen-user_fr/images/content_viewer_app_sqlite.png new file mode 100644 index 0000000000..b377395cf1 Binary files /dev/null and b/docs/doxygen-user_fr/images/content_viewer_app_sqlite.png differ diff --git a/docs/doxygen-user_fr/images/content_viewer_context.png b/docs/doxygen-user_fr/images/content_viewer_context.png new file mode 100644 index 0000000000..758d1f2aed Binary files /dev/null and b/docs/doxygen-user_fr/images/content_viewer_context.png differ diff --git a/docs/doxygen-user_fr/images/content_viewer_hex.png b/docs/doxygen-user_fr/images/content_viewer_hex.png new file mode 100644 index 0000000000..ec68e2a521 Binary files /dev/null and b/docs/doxygen-user_fr/images/content_viewer_hex.png differ diff --git a/docs/doxygen-user_fr/images/content_viewer_hex_editor_setup.png b/docs/doxygen-user_fr/images/content_viewer_hex_editor_setup.png new file mode 100644 index 0000000000..4b9d7276e7 Binary files /dev/null and b/docs/doxygen-user_fr/images/content_viewer_hex_editor_setup.png differ diff --git a/docs/doxygen-user_fr/images/content_viewer_html.png b/docs/doxygen-user_fr/images/content_viewer_html.png new file mode 100644 index 0000000000..f42feba21d Binary files /dev/null and b/docs/doxygen-user_fr/images/content_viewer_html.png differ diff --git a/docs/doxygen-user_fr/images/content_viewer_hxd_progress.png b/docs/doxygen-user_fr/images/content_viewer_hxd_progress.png new file mode 100644 index 0000000000..33dca02584 Binary files /dev/null and b/docs/doxygen-user_fr/images/content_viewer_hxd_progress.png differ diff --git a/docs/doxygen-user_fr/images/content_viewer_indexed_text.png b/docs/doxygen-user_fr/images/content_viewer_indexed_text.png new file mode 100644 index 0000000000..11e4da475f Binary files /dev/null and b/docs/doxygen-user_fr/images/content_viewer_indexed_text.png differ diff --git a/docs/doxygen-user_fr/images/content_viewer_message.png b/docs/doxygen-user_fr/images/content_viewer_message.png new file mode 100644 index 0000000000..7f3e109396 Binary files /dev/null and b/docs/doxygen-user_fr/images/content_viewer_message.png differ diff --git a/docs/doxygen-user_fr/images/content_viewer_metadata.png b/docs/doxygen-user_fr/images/content_viewer_metadata.png new file mode 100644 index 0000000000..67ed3e0186 Binary files /dev/null and b/docs/doxygen-user_fr/images/content_viewer_metadata.png differ diff --git a/docs/doxygen-user_fr/images/content_viewer_options_panel.png b/docs/doxygen-user_fr/images/content_viewer_options_panel.png new file mode 100644 index 0000000000..47e8e2816f Binary files /dev/null and b/docs/doxygen-user_fr/images/content_viewer_options_panel.png differ diff --git a/docs/doxygen-user_fr/images/content_viewer_os_account.png b/docs/doxygen-user_fr/images/content_viewer_os_account.png new file mode 100644 index 0000000000..74bb53c366 Binary files /dev/null and b/docs/doxygen-user_fr/images/content_viewer_os_account.png differ diff --git a/docs/doxygen-user_fr/images/content_viewer_other_occurrences.png b/docs/doxygen-user_fr/images/content_viewer_other_occurrences.png new file mode 100644 index 0000000000..cb23535502 Binary files /dev/null and b/docs/doxygen-user_fr/images/content_viewer_other_occurrences.png differ diff --git a/docs/doxygen-user_fr/images/content_viewer_registry.png b/docs/doxygen-user_fr/images/content_viewer_registry.png new file mode 100644 index 0000000000..1d48467916 Binary files /dev/null and b/docs/doxygen-user_fr/images/content_viewer_registry.png differ diff --git a/docs/doxygen-user_fr/images/content_viewer_results_bookmark.png b/docs/doxygen-user_fr/images/content_viewer_results_bookmark.png new file mode 100644 index 0000000000..2c0d3cb736 Binary files /dev/null and b/docs/doxygen-user_fr/images/content_viewer_results_bookmark.png differ diff --git a/docs/doxygen-user_fr/images/content_viewer_results_call.png b/docs/doxygen-user_fr/images/content_viewer_results_call.png new file mode 100644 index 0000000000..3bc104af0a Binary files /dev/null and b/docs/doxygen-user_fr/images/content_viewer_results_call.png differ diff --git a/docs/doxygen-user_fr/images/content_viewer_strings_cyrillic.png b/docs/doxygen-user_fr/images/content_viewer_strings_cyrillic.png new file mode 100644 index 0000000000..e9c1945e7f Binary files /dev/null and b/docs/doxygen-user_fr/images/content_viewer_strings_cyrillic.png differ diff --git a/docs/doxygen-user_fr/images/content_viewer_strings_latin.png b/docs/doxygen-user_fr/images/content_viewer_strings_latin.png new file mode 100644 index 0000000000..4fbf4dd576 Binary files /dev/null and b/docs/doxygen-user_fr/images/content_viewer_strings_latin.png differ diff --git a/docs/doxygen-user_fr/images/content_viewer_video.png b/docs/doxygen-user_fr/images/content_viewer_video.png new file mode 100644 index 0000000000..09d19bdfde Binary files /dev/null and b/docs/doxygen-user_fr/images/content_viewer_video.png differ diff --git a/docs/doxygen-user_fr/images/credentialsWithDomain.PNG b/docs/doxygen-user_fr/images/credentialsWithDomain.PNG new file mode 100644 index 0000000000..4127a9497f Binary files /dev/null and b/docs/doxygen-user_fr/images/credentialsWithDomain.PNG differ diff --git a/docs/doxygen-user_fr/images/custom_web_categories.png b/docs/doxygen-user_fr/images/custom_web_categories.png new file mode 100644 index 0000000000..a49a1d2852 Binary files /dev/null and b/docs/doxygen-user_fr/images/custom_web_categories.png differ diff --git a/docs/doxygen-user_fr/images/custom_web_categories_results.png b/docs/doxygen-user_fr/images/custom_web_categories_results.png new file mode 100644 index 0000000000..68cc44bbfd Binary files /dev/null and b/docs/doxygen-user_fr/images/custom_web_categories_results.png differ diff --git a/docs/doxygen-user_fr/images/cvt_call_log.png b/docs/doxygen-user_fr/images/cvt_call_log.png new file mode 100644 index 0000000000..3b06328687 Binary files /dev/null and b/docs/doxygen-user_fr/images/cvt_call_log.png differ diff --git a/docs/doxygen-user_fr/images/cvt_contacts.png b/docs/doxygen-user_fr/images/cvt_contacts.png new file mode 100644 index 0000000000..4f674e6579 Binary files /dev/null and b/docs/doxygen-user_fr/images/cvt_contacts.png differ diff --git a/docs/doxygen-user_fr/images/cvt_links.png b/docs/doxygen-user_fr/images/cvt_links.png new file mode 100644 index 0000000000..5765d5c087 Binary files /dev/null and b/docs/doxygen-user_fr/images/cvt_links.png differ diff --git a/docs/doxygen-user_fr/images/cvt_main.png b/docs/doxygen-user_fr/images/cvt_main.png new file mode 100644 index 0000000000..1c9ec9e903 Binary files /dev/null and b/docs/doxygen-user_fr/images/cvt_main.png differ diff --git a/docs/doxygen-user_fr/images/cvt_media.png b/docs/doxygen-user_fr/images/cvt_media.png new file mode 100644 index 0000000000..bf4982cb62 Binary files /dev/null and b/docs/doxygen-user_fr/images/cvt_media.png differ diff --git a/docs/doxygen-user_fr/images/cvt_message_attach.png b/docs/doxygen-user_fr/images/cvt_message_attach.png new file mode 100644 index 0000000000..3eee863ba2 Binary files /dev/null and b/docs/doxygen-user_fr/images/cvt_message_attach.png differ diff --git a/docs/doxygen-user_fr/images/cvt_message_email.png b/docs/doxygen-user_fr/images/cvt_message_email.png new file mode 100644 index 0000000000..e322a3548b Binary files /dev/null and b/docs/doxygen-user_fr/images/cvt_message_email.png differ diff --git a/docs/doxygen-user_fr/images/cvt_messages_threaded.png b/docs/doxygen-user_fr/images/cvt_messages_threaded.png new file mode 100644 index 0000000000..6ca9274426 Binary files /dev/null and b/docs/doxygen-user_fr/images/cvt_messages_threaded.png differ diff --git a/docs/doxygen-user_fr/images/cvt_select_account.png b/docs/doxygen-user_fr/images/cvt_select_account.png new file mode 100644 index 0000000000..f12d8df325 Binary files /dev/null and b/docs/doxygen-user_fr/images/cvt_select_account.png differ diff --git a/docs/doxygen-user_fr/images/cvt_snapshot.png b/docs/doxygen-user_fr/images/cvt_snapshot.png new file mode 100644 index 0000000000..82dae4e80e Binary files /dev/null and b/docs/doxygen-user_fr/images/cvt_snapshot.png differ diff --git a/docs/doxygen-user_fr/images/cvt_summary_tab.png b/docs/doxygen-user_fr/images/cvt_summary_tab.png new file mode 100644 index 0000000000..405448d31e Binary files /dev/null and b/docs/doxygen-user_fr/images/cvt_summary_tab.png differ diff --git a/docs/doxygen-user_fr/images/cvt_visualize.png b/docs/doxygen-user_fr/images/cvt_visualize.png new file mode 100644 index 0000000000..a7301abaee Binary files /dev/null and b/docs/doxygen-user_fr/images/cvt_visualize.png differ diff --git a/docs/doxygen-user_fr/images/data-source-progress-bar.PNG b/docs/doxygen-user_fr/images/data-source-progress-bar.PNG new file mode 100644 index 0000000000..9957cf7830 Binary files /dev/null and b/docs/doxygen-user_fr/images/data-source-progress-bar.PNG differ diff --git a/docs/doxygen-user_fr/images/data_source_delete.png b/docs/doxygen-user_fr/images/data_source_delete.png new file mode 100644 index 0000000000..d33e42e107 Binary files /dev/null and b/docs/doxygen-user_fr/images/data_source_delete.png differ diff --git a/docs/doxygen-user_fr/images/data_source_disk_image.png b/docs/doxygen-user_fr/images/data_source_disk_image.png new file mode 100644 index 0000000000..6a59e90bea Binary files /dev/null and b/docs/doxygen-user_fr/images/data_source_disk_image.png differ diff --git a/docs/doxygen-user_fr/images/data_source_host_select.png b/docs/doxygen-user_fr/images/data_source_host_select.png new file mode 100644 index 0000000000..f9275d9387 Binary files /dev/null and b/docs/doxygen-user_fr/images/data_source_host_select.png differ diff --git a/docs/doxygen-user_fr/images/data_source_integrity_add_ds.png b/docs/doxygen-user_fr/images/data_source_integrity_add_ds.png new file mode 100644 index 0000000000..a480bc67c2 Binary files /dev/null and b/docs/doxygen-user_fr/images/data_source_integrity_add_ds.png differ diff --git a/docs/doxygen-user_fr/images/data_source_integrity_failed_artifact.png b/docs/doxygen-user_fr/images/data_source_integrity_failed_artifact.png new file mode 100644 index 0000000000..a62e91ecaa Binary files /dev/null and b/docs/doxygen-user_fr/images/data_source_integrity_failed_artifact.png differ diff --git a/docs/doxygen-user_fr/images/data_source_integrity_failed_inbox.png b/docs/doxygen-user_fr/images/data_source_integrity_failed_inbox.png new file mode 100644 index 0000000000..e1b525d2d1 Binary files /dev/null and b/docs/doxygen-user_fr/images/data_source_integrity_failed_inbox.png differ diff --git a/docs/doxygen-user_fr/images/data_source_integrity_ingest_settings.png b/docs/doxygen-user_fr/images/data_source_integrity_ingest_settings.png new file mode 100644 index 0000000000..869a5fedc2 Binary files /dev/null and b/docs/doxygen-user_fr/images/data_source_integrity_ingest_settings.png differ diff --git a/docs/doxygen-user_fr/images/data_source_integrity_metadata.png b/docs/doxygen-user_fr/images/data_source_integrity_metadata.png new file mode 100644 index 0000000000..451365e026 Binary files /dev/null and b/docs/doxygen-user_fr/images/data_source_integrity_metadata.png differ diff --git a/docs/doxygen-user_fr/images/data_source_integrity_pass1.png b/docs/doxygen-user_fr/images/data_source_integrity_pass1.png new file mode 100644 index 0000000000..88208ecf77 Binary files /dev/null and b/docs/doxygen-user_fr/images/data_source_integrity_pass1.png differ diff --git a/docs/doxygen-user_fr/images/data_source_integrity_pass2.png b/docs/doxygen-user_fr/images/data_source_integrity_pass2.png new file mode 100644 index 0000000000..7d95e1003b Binary files /dev/null and b/docs/doxygen-user_fr/images/data_source_integrity_pass2.png differ diff --git a/docs/doxygen-user_fr/images/dzkrun.PNG b/docs/doxygen-user_fr/images/dzkrun.PNG new file mode 100644 index 0000000000..978c8847e1 Binary files /dev/null and b/docs/doxygen-user_fr/images/dzkrun.PNG differ diff --git a/docs/doxygen-user_fr/images/email_attachments.png b/docs/doxygen-user_fr/images/email_attachments.png new file mode 100644 index 0000000000..6eab4cc45f Binary files /dev/null and b/docs/doxygen-user_fr/images/email_attachments.png differ diff --git a/docs/doxygen-user_fr/images/email_results.PNG b/docs/doxygen-user_fr/images/email_results.PNG new file mode 100644 index 0000000000..49ccbc6439 Binary files /dev/null and b/docs/doxygen-user_fr/images/email_results.PNG differ diff --git a/docs/doxygen-user_fr/images/encrypt_entropy.png b/docs/doxygen-user_fr/images/encrypt_entropy.png new file mode 100644 index 0000000000..98716c544a Binary files /dev/null and b/docs/doxygen-user_fr/images/encrypt_entropy.png differ diff --git a/docs/doxygen-user_fr/images/encrypt_inbox.png b/docs/doxygen-user_fr/images/encrypt_inbox.png new file mode 100644 index 0000000000..f88f5dfe46 Binary files /dev/null and b/docs/doxygen-user_fr/images/encrypt_inbox.png differ diff --git a/docs/doxygen-user_fr/images/encrypt_module.png b/docs/doxygen-user_fr/images/encrypt_module.png new file mode 100644 index 0000000000..d175fa062a Binary files /dev/null and b/docs/doxygen-user_fr/images/encrypt_module.png differ diff --git a/docs/doxygen-user_fr/images/encrypt_tree.png b/docs/doxygen-user_fr/images/encrypt_tree.png new file mode 100644 index 0000000000..5766e75ed3 Binary files /dev/null and b/docs/doxygen-user_fr/images/encrypt_tree.png differ diff --git a/docs/doxygen-user_fr/images/example-of-file-search.PNG b/docs/doxygen-user_fr/images/example-of-file-search.PNG new file mode 100644 index 0000000000..310704a471 Binary files /dev/null and b/docs/doxygen-user_fr/images/example-of-file-search.PNG differ diff --git a/docs/doxygen-user_fr/images/experimental_plugins_menu.png b/docs/doxygen-user_fr/images/experimental_plugins_menu.png new file mode 100644 index 0000000000..21895bc953 Binary files /dev/null and b/docs/doxygen-user_fr/images/experimental_plugins_menu.png differ diff --git a/docs/doxygen-user_fr/images/explorer-tree.PNG b/docs/doxygen-user_fr/images/explorer-tree.PNG new file mode 100644 index 0000000000..0151161104 Binary files /dev/null and b/docs/doxygen-user_fr/images/explorer-tree.PNG differ diff --git a/docs/doxygen-user_fr/images/extension-mismatch-detected-configuration.PNG b/docs/doxygen-user_fr/images/extension-mismatch-detected-configuration.PNG new file mode 100644 index 0000000000..f7f2e9a2a1 Binary files /dev/null and b/docs/doxygen-user_fr/images/extension-mismatch-detected-configuration.PNG differ diff --git a/docs/doxygen-user_fr/images/extension-mismatch-detected-ingest-settings.PNG b/docs/doxygen-user_fr/images/extension-mismatch-detected-ingest-settings.PNG new file mode 100644 index 0000000000..9fb7daa33c Binary files /dev/null and b/docs/doxygen-user_fr/images/extension-mismatch-detected-ingest-settings.PNG differ diff --git a/docs/doxygen-user_fr/images/extension-mismatch-detected.PNG b/docs/doxygen-user_fr/images/extension-mismatch-detected.PNG new file mode 100644 index 0000000000..3bd90ded78 Binary files /dev/null and b/docs/doxygen-user_fr/images/extension-mismatch-detected.PNG differ diff --git a/docs/doxygen-user_fr/images/extracted_content.PNG b/docs/doxygen-user_fr/images/extracted_content.PNG new file mode 100644 index 0000000000..b8696a93e7 Binary files /dev/null and b/docs/doxygen-user_fr/images/extracted_content.PNG differ diff --git a/docs/doxygen-user_fr/images/extracting-unallocated-space.PNG b/docs/doxygen-user_fr/images/extracting-unallocated-space.PNG new file mode 100644 index 0000000000..b456c8f892 Binary files /dev/null and b/docs/doxygen-user_fr/images/extracting-unallocated-space.PNG differ diff --git a/docs/doxygen-user_fr/images/filetype.PNG b/docs/doxygen-user_fr/images/filetype.PNG new file mode 100644 index 0000000000..142491862f Binary files /dev/null and b/docs/doxygen-user_fr/images/filetype.PNG differ diff --git a/docs/doxygen-user_fr/images/geo_add_ds.png b/docs/doxygen-user_fr/images/geo_add_ds.png new file mode 100644 index 0000000000..60ac3f5684 Binary files /dev/null and b/docs/doxygen-user_fr/images/geo_add_ds.png differ diff --git a/docs/doxygen-user_fr/images/geo_command_line.png b/docs/doxygen-user_fr/images/geo_command_line.png new file mode 100644 index 0000000000..de69fdfd15 Binary files /dev/null and b/docs/doxygen-user_fr/images/geo_command_line.png differ diff --git a/docs/doxygen-user_fr/images/geo_context_menu.png b/docs/doxygen-user_fr/images/geo_context_menu.png new file mode 100644 index 0000000000..fc1d216228 Binary files /dev/null and b/docs/doxygen-user_fr/images/geo_context_menu.png differ diff --git a/docs/doxygen-user_fr/images/geo_details.png b/docs/doxygen-user_fr/images/geo_details.png new file mode 100644 index 0000000000..92e1b4ccf7 Binary files /dev/null and b/docs/doxygen-user_fr/images/geo_details.png differ diff --git a/docs/doxygen-user_fr/images/geo_details_bookmark.png b/docs/doxygen-user_fr/images/geo_details_bookmark.png new file mode 100644 index 0000000000..7dec786a51 Binary files /dev/null and b/docs/doxygen-user_fr/images/geo_details_bookmark.png differ diff --git a/docs/doxygen-user_fr/images/geo_filter_datasource.png b/docs/doxygen-user_fr/images/geo_filter_datasource.png new file mode 100644 index 0000000000..0ac4004d58 Binary files /dev/null and b/docs/doxygen-user_fr/images/geo_filter_datasource.png differ diff --git a/docs/doxygen-user_fr/images/geo_filter_time.png b/docs/doxygen-user_fr/images/geo_filter_time.png new file mode 100644 index 0000000000..96d3728307 Binary files /dev/null and b/docs/doxygen-user_fr/images/geo_filter_time.png differ diff --git a/docs/doxygen-user_fr/images/geo_filter_type.png b/docs/doxygen-user_fr/images/geo_filter_type.png new file mode 100644 index 0000000000..b0244b9d2e Binary files /dev/null and b/docs/doxygen-user_fr/images/geo_filter_type.png differ diff --git a/docs/doxygen-user_fr/images/geo_gen_tiles.png b/docs/doxygen-user_fr/images/geo_gen_tiles.png new file mode 100644 index 0000000000..0f1547779c Binary files /dev/null and b/docs/doxygen-user_fr/images/geo_gen_tiles.png differ diff --git a/docs/doxygen-user_fr/images/geo_main.png b/docs/doxygen-user_fr/images/geo_main.png new file mode 100644 index 0000000000..20a34fea4b Binary files /dev/null and b/docs/doxygen-user_fr/images/geo_main.png differ diff --git a/docs/doxygen-user_fr/images/geo_openstreetmap.png b/docs/doxygen-user_fr/images/geo_openstreetmap.png new file mode 100644 index 0000000000..a35d4234be Binary files /dev/null and b/docs/doxygen-user_fr/images/geo_openstreetmap.png differ diff --git a/docs/doxygen-user_fr/images/geo_report.png b/docs/doxygen-user_fr/images/geo_report.png new file mode 100644 index 0000000000..4b710b3cbc Binary files /dev/null and b/docs/doxygen-user_fr/images/geo_report.png differ diff --git a/docs/doxygen-user_fr/images/geo_tile_folder.png b/docs/doxygen-user_fr/images/geo_tile_folder.png new file mode 100644 index 0000000000..2ae5c347eb Binary files /dev/null and b/docs/doxygen-user_fr/images/geo_tile_folder.png differ diff --git a/docs/doxygen-user_fr/images/geo_track_points.png b/docs/doxygen-user_fr/images/geo_track_points.png new file mode 100644 index 0000000000..1aecf18bdd Binary files /dev/null and b/docs/doxygen-user_fr/images/geo_track_points.png differ diff --git a/docs/doxygen-user_fr/images/geolocation_drone_path.png b/docs/doxygen-user_fr/images/geolocation_drone_path.png new file mode 100644 index 0000000000..ef7dc83674 Binary files /dev/null and b/docs/doxygen-user_fr/images/geolocation_drone_path.png differ diff --git a/docs/doxygen-user_fr/images/gps_track_artifact.png b/docs/doxygen-user_fr/images/gps_track_artifact.png new file mode 100644 index 0000000000..d6541a4061 Binary files /dev/null and b/docs/doxygen-user_fr/images/gps_track_artifact.png differ diff --git a/docs/doxygen-user_fr/images/gpx_results.png b/docs/doxygen-user_fr/images/gpx_results.png new file mode 100644 index 0000000000..0a061f2b2d Binary files /dev/null and b/docs/doxygen-user_fr/images/gpx_results.png differ diff --git a/docs/doxygen-user_fr/images/grantAccessToComputer.PNG b/docs/doxygen-user_fr/images/grantAccessToComputer.PNG new file mode 100644 index 0000000000..a155a20ea7 Binary files /dev/null and b/docs/doxygen-user_fr/images/grantAccessToComputer.PNG differ diff --git a/docs/doxygen-user_fr/images/groups.properties.after.PNG b/docs/doxygen-user_fr/images/groups.properties.after.PNG new file mode 100644 index 0000000000..c6f8e60344 Binary files /dev/null and b/docs/doxygen-user_fr/images/groups.properties.after.PNG differ diff --git a/docs/doxygen-user_fr/images/groups.properties.before.PNG b/docs/doxygen-user_fr/images/groups.properties.before.PNG new file mode 100644 index 0000000000..be233d6ff7 Binary files /dev/null and b/docs/doxygen-user_fr/images/groups.properties.before.PNG differ diff --git a/docs/doxygen-user_fr/images/hash-lookup.PNG b/docs/doxygen-user_fr/images/hash-lookup.PNG new file mode 100644 index 0000000000..a9a8a2dbc2 Binary files /dev/null and b/docs/doxygen-user_fr/images/hash-lookup.PNG differ diff --git a/docs/doxygen-user_fr/images/hash_add.png b/docs/doxygen-user_fr/images/hash_add.png new file mode 100644 index 0000000000..ed0b2c1a52 Binary files /dev/null and b/docs/doxygen-user_fr/images/hash_add.png differ diff --git a/docs/doxygen-user_fr/images/hash_add_context.png b/docs/doxygen-user_fr/images/hash_add_context.png new file mode 100644 index 0000000000..76544e1072 Binary files /dev/null and b/docs/doxygen-user_fr/images/hash_add_context.png differ diff --git a/docs/doxygen-user_fr/images/hash_import.png b/docs/doxygen-user_fr/images/hash_import.png new file mode 100644 index 0000000000..b76765b4f0 Binary files /dev/null and b/docs/doxygen-user_fr/images/hash_import.png differ diff --git a/docs/doxygen-user_fr/images/hash_indexing.png b/docs/doxygen-user_fr/images/hash_indexing.png new file mode 100644 index 0000000000..f7f01cb164 Binary files /dev/null and b/docs/doxygen-user_fr/images/hash_indexing.png differ diff --git a/docs/doxygen-user_fr/images/hash_new_db.png b/docs/doxygen-user_fr/images/hash_new_db.png new file mode 100644 index 0000000000..41405f3e45 Binary files /dev/null and b/docs/doxygen-user_fr/images/hash_new_db.png differ diff --git a/docs/doxygen-user_fr/images/hashset-hits.PNG b/docs/doxygen-user_fr/images/hashset-hits.PNG new file mode 100644 index 0000000000..efec101916 Binary files /dev/null and b/docs/doxygen-user_fr/images/hashset-hits.PNG differ diff --git a/docs/doxygen-user_fr/images/host_merge.png b/docs/doxygen-user_fr/images/host_merge.png new file mode 100644 index 0000000000..b5235eb8d4 Binary files /dev/null and b/docs/doxygen-user_fr/images/host_merge.png differ diff --git a/docs/doxygen-user_fr/images/host_merge_result.png b/docs/doxygen-user_fr/images/host_merge_result.png new file mode 100644 index 0000000000..bb22063c3d Binary files /dev/null and b/docs/doxygen-user_fr/images/host_merge_result.png differ diff --git a/docs/doxygen-user_fr/images/host_os_accounts.png b/docs/doxygen-user_fr/images/host_os_accounts.png new file mode 100644 index 0000000000..d73505fa5c Binary files /dev/null and b/docs/doxygen-user_fr/images/host_os_accounts.png differ diff --git a/docs/doxygen-user_fr/images/ileapp_main.jpg b/docs/doxygen-user_fr/images/ileapp_main.jpg new file mode 100644 index 0000000000..8a08b8cba7 Binary files /dev/null and b/docs/doxygen-user_fr/images/ileapp_main.jpg differ diff --git a/docs/doxygen-user_fr/images/inbox-button.PNG b/docs/doxygen-user_fr/images/inbox-button.PNG new file mode 100644 index 0000000000..d7ec55ee76 Binary files /dev/null and b/docs/doxygen-user_fr/images/inbox-button.PNG differ diff --git a/docs/doxygen-user_fr/images/inbox-detail-screen.PNG b/docs/doxygen-user_fr/images/inbox-detail-screen.PNG new file mode 100644 index 0000000000..1f2a420864 Binary files /dev/null and b/docs/doxygen-user_fr/images/inbox-detail-screen.PNG differ diff --git a/docs/doxygen-user_fr/images/inbox-main-screen.PNG b/docs/doxygen-user_fr/images/inbox-main-screen.PNG new file mode 100644 index 0000000000..f5baf84c21 Binary files /dev/null and b/docs/doxygen-user_fr/images/inbox-main-screen.PNG differ diff --git a/docs/doxygen-user_fr/images/ingest-already-run.PNG b/docs/doxygen-user_fr/images/ingest-already-run.PNG new file mode 100644 index 0000000000..9e5ceb307b Binary files /dev/null and b/docs/doxygen-user_fr/images/ingest-already-run.PNG differ diff --git a/docs/doxygen-user_fr/images/ingest-file-filters.PNG b/docs/doxygen-user_fr/images/ingest-file-filters.PNG new file mode 100644 index 0000000000..1831789733 Binary files /dev/null and b/docs/doxygen-user_fr/images/ingest-file-filters.PNG differ diff --git a/docs/doxygen-user_fr/images/ingest-history.PNG b/docs/doxygen-user_fr/images/ingest-history.PNG new file mode 100644 index 0000000000..085475a6d4 Binary files /dev/null and b/docs/doxygen-user_fr/images/ingest-history.PNG differ diff --git a/docs/doxygen-user_fr/images/ingest-profile-create.PNG b/docs/doxygen-user_fr/images/ingest-profile-create.PNG new file mode 100644 index 0000000000..d1139b55ef Binary files /dev/null and b/docs/doxygen-user_fr/images/ingest-profile-create.PNG differ diff --git a/docs/doxygen-user_fr/images/ingest-profiles.PNG b/docs/doxygen-user_fr/images/ingest-profiles.PNG new file mode 100644 index 0000000000..7902140b9e Binary files /dev/null and b/docs/doxygen-user_fr/images/ingest-profiles.PNG differ diff --git a/docs/doxygen-user_fr/images/ingest_pipeline.PNG b/docs/doxygen-user_fr/images/ingest_pipeline.PNG new file mode 100644 index 0000000000..a91b73f642 Binary files /dev/null and b/docs/doxygen-user_fr/images/ingest_pipeline.PNG differ diff --git a/docs/doxygen-user_fr/images/ingest_progress_snapshot.PNG b/docs/doxygen-user_fr/images/ingest_progress_snapshot.PNG new file mode 100644 index 0000000000..305de61b0a Binary files /dev/null and b/docs/doxygen-user_fr/images/ingest_progress_snapshot.PNG differ diff --git a/docs/doxygen-user_fr/images/insertTextHere.PNG b/docs/doxygen-user_fr/images/insertTextHere.PNG new file mode 100644 index 0000000000..c057e1640e Binary files /dev/null and b/docs/doxygen-user_fr/images/insertTextHere.PNG differ diff --git a/docs/doxygen-user_fr/images/insertedText.PNG b/docs/doxygen-user_fr/images/insertedText.PNG new file mode 100644 index 0000000000..3d7fb34403 Binary files /dev/null and b/docs/doxygen-user_fr/images/insertedText.PNG differ diff --git a/docs/doxygen-user_fr/images/keyword-search-ad-hoc.PNG b/docs/doxygen-user_fr/images/keyword-search-ad-hoc.PNG new file mode 100644 index 0000000000..c29eaa37f4 Binary files /dev/null and b/docs/doxygen-user_fr/images/keyword-search-ad-hoc.PNG differ diff --git a/docs/doxygen-user_fr/images/keyword-search-bar.PNG b/docs/doxygen-user_fr/images/keyword-search-bar.PNG new file mode 100644 index 0000000000..e0d18b0639 Binary files /dev/null and b/docs/doxygen-user_fr/images/keyword-search-bar.PNG differ diff --git a/docs/doxygen-user_fr/images/keyword-search-configuration-dialog-general.PNG b/docs/doxygen-user_fr/images/keyword-search-configuration-dialog-general.PNG new file mode 100644 index 0000000000..4dbb566faa Binary files /dev/null and b/docs/doxygen-user_fr/images/keyword-search-configuration-dialog-general.PNG differ diff --git a/docs/doxygen-user_fr/images/keyword-search-configuration-dialog-string-extraction.PNG b/docs/doxygen-user_fr/images/keyword-search-configuration-dialog-string-extraction.PNG new file mode 100644 index 0000000000..51df8bd5bd Binary files /dev/null and b/docs/doxygen-user_fr/images/keyword-search-configuration-dialog-string-extraction.PNG differ diff --git a/docs/doxygen-user_fr/images/keyword-search-configuration-dialog.PNG b/docs/doxygen-user_fr/images/keyword-search-configuration-dialog.PNG new file mode 100644 index 0000000000..b7c15ca36d Binary files /dev/null and b/docs/doxygen-user_fr/images/keyword-search-configuration-dialog.PNG differ diff --git a/docs/doxygen-user_fr/images/keyword-search-configuration-new-keywords.PNG b/docs/doxygen-user_fr/images/keyword-search-configuration-new-keywords.PNG new file mode 100644 index 0000000000..a1d02bcbe7 Binary files /dev/null and b/docs/doxygen-user_fr/images/keyword-search-configuration-new-keywords.PNG differ diff --git a/docs/doxygen-user_fr/images/keyword-search-hits.PNG b/docs/doxygen-user_fr/images/keyword-search-hits.PNG new file mode 100644 index 0000000000..b1e0193f27 Binary files /dev/null and b/docs/doxygen-user_fr/images/keyword-search-hits.PNG differ diff --git a/docs/doxygen-user_fr/images/keyword-search-inbox.PNG b/docs/doxygen-user_fr/images/keyword-search-inbox.PNG new file mode 100644 index 0000000000..e95a3c5666 Binary files /dev/null and b/docs/doxygen-user_fr/images/keyword-search-inbox.PNG differ diff --git a/docs/doxygen-user_fr/images/keyword-search-ingest-settings.PNG b/docs/doxygen-user_fr/images/keyword-search-ingest-settings.PNG new file mode 100644 index 0000000000..d7c0b8e2fc Binary files /dev/null and b/docs/doxygen-user_fr/images/keyword-search-ingest-settings.PNG differ diff --git a/docs/doxygen-user_fr/images/keyword-search-list-results.PNG b/docs/doxygen-user_fr/images/keyword-search-list-results.PNG new file mode 100644 index 0000000000..368e744a41 Binary files /dev/null and b/docs/doxygen-user_fr/images/keyword-search-list-results.PNG differ diff --git a/docs/doxygen-user_fr/images/keyword-search-list.PNG b/docs/doxygen-user_fr/images/keyword-search-list.PNG new file mode 100644 index 0000000000..65cbccefb9 Binary files /dev/null and b/docs/doxygen-user_fr/images/keyword-search-list.PNG differ diff --git a/docs/doxygen-user_fr/images/keyword-search-ocr-image.png b/docs/doxygen-user_fr/images/keyword-search-ocr-image.png new file mode 100644 index 0000000000..a8fda73cc4 Binary files /dev/null and b/docs/doxygen-user_fr/images/keyword-search-ocr-image.png differ diff --git a/docs/doxygen-user_fr/images/keyword-search-ocr-indexed-text.png b/docs/doxygen-user_fr/images/keyword-search-ocr-indexed-text.png new file mode 100644 index 0000000000..d6c3a0ac8c Binary files /dev/null and b/docs/doxygen-user_fr/images/keyword-search-ocr-indexed-text.png differ diff --git a/docs/doxygen-user_fr/images/keyword_results.PNG b/docs/doxygen-user_fr/images/keyword_results.PNG new file mode 100644 index 0000000000..0ea7ef04d5 Binary files /dev/null and b/docs/doxygen-user_fr/images/keyword_results.PNG differ diff --git a/docs/doxygen-user_fr/images/live_triage_case.png b/docs/doxygen-user_fr/images/live_triage_case.png new file mode 100644 index 0000000000..fee49485f5 Binary files /dev/null and b/docs/doxygen-user_fr/images/live_triage_case.png differ diff --git a/docs/doxygen-user_fr/images/live_triage_dialog.png b/docs/doxygen-user_fr/images/live_triage_dialog.png new file mode 100644 index 0000000000..4768ec8245 Binary files /dev/null and b/docs/doxygen-user_fr/images/live_triage_dialog.png differ diff --git a/docs/doxygen-user_fr/images/live_triage_ds.png b/docs/doxygen-user_fr/images/live_triage_ds.png new file mode 100644 index 0000000000..f21a50aa82 Binary files /dev/null and b/docs/doxygen-user_fr/images/live_triage_ds.png differ diff --git a/docs/doxygen-user_fr/images/live_triage_import_hash.png b/docs/doxygen-user_fr/images/live_triage_import_hash.png new file mode 100644 index 0000000000..8acf9d5330 Binary files /dev/null and b/docs/doxygen-user_fr/images/live_triage_import_hash.png differ diff --git a/docs/doxygen-user_fr/images/live_triage_script.png b/docs/doxygen-user_fr/images/live_triage_script.png new file mode 100644 index 0000000000..2bdf7f12ae Binary files /dev/null and b/docs/doxygen-user_fr/images/live_triage_script.png differ diff --git a/docs/doxygen-user_fr/images/local-disk-data-source.PNG b/docs/doxygen-user_fr/images/local-disk-data-source.PNG new file mode 100644 index 0000000000..ff80c7afb3 Binary files /dev/null and b/docs/doxygen-user_fr/images/local-disk-data-source.PNG differ diff --git a/docs/doxygen-user_fr/images/log4j.PNG b/docs/doxygen-user_fr/images/log4j.PNG new file mode 100644 index 0000000000..c9800a1fe4 Binary files /dev/null and b/docs/doxygen-user_fr/images/log4j.PNG differ diff --git a/docs/doxygen-user_fr/images/manage_hosts.png b/docs/doxygen-user_fr/images/manage_hosts.png new file mode 100644 index 0000000000..14f4805027 Binary files /dev/null and b/docs/doxygen-user_fr/images/manage_hosts.png differ diff --git a/docs/doxygen-user_fr/images/maxConnections.PNG b/docs/doxygen-user_fr/images/maxConnections.PNG new file mode 100644 index 0000000000..13734ce420 Binary files /dev/null and b/docs/doxygen-user_fr/images/maxConnections.PNG differ diff --git a/docs/doxygen-user_fr/images/maxinactivityduration.PNG b/docs/doxygen-user_fr/images/maxinactivityduration.PNG new file mode 100644 index 0000000000..14401d7361 Binary files /dev/null and b/docs/doxygen-user_fr/images/maxinactivityduration.PNG differ diff --git a/docs/doxygen-user_fr/images/messagebubbles.PNG b/docs/doxygen-user_fr/images/messagebubbles.PNG new file mode 100644 index 0000000000..6557b6326a Binary files /dev/null and b/docs/doxygen-user_fr/images/messagebubbles.PNG differ diff --git a/docs/doxygen-user_fr/images/messagebubblesbigger.PNG b/docs/doxygen-user_fr/images/messagebubblesbigger.PNG new file mode 100644 index 0000000000..a73fd81c86 Binary files /dev/null and b/docs/doxygen-user_fr/images/messagebubblesbigger.PNG differ diff --git a/docs/doxygen-user_fr/images/mime-type-tree.PNG b/docs/doxygen-user_fr/images/mime-type-tree.PNG new file mode 100644 index 0000000000..b7a5947acf Binary files /dev/null and b/docs/doxygen-user_fr/images/mime-type-tree.PNG differ diff --git a/docs/doxygen-user_fr/images/module_install_netbeans.png b/docs/doxygen-user_fr/images/module_install_netbeans.png new file mode 100644 index 0000000000..db50799d1c Binary files /dev/null and b/docs/doxygen-user_fr/images/module_install_netbeans.png differ diff --git a/docs/doxygen-user_fr/images/module_install_python.png b/docs/doxygen-user_fr/images/module_install_python.png new file mode 100644 index 0000000000..cb393c30b5 Binary files /dev/null and b/docs/doxygen-user_fr/images/module_install_python.png differ diff --git a/docs/doxygen-user_fr/images/mt_config.png b/docs/doxygen-user_fr/images/mt_config.png new file mode 100644 index 0000000000..b793191ae8 Binary files /dev/null and b/docs/doxygen-user_fr/images/mt_config.png differ diff --git a/docs/doxygen-user_fr/images/mt_content_viewer_translated.png b/docs/doxygen-user_fr/images/mt_content_viewer_translated.png new file mode 100644 index 0000000000..7ba3804415 Binary files /dev/null and b/docs/doxygen-user_fr/images/mt_content_viewer_translated.png differ diff --git a/docs/doxygen-user_fr/images/mt_content_viewer_untranslated_text.png b/docs/doxygen-user_fr/images/mt_content_viewer_untranslated_text.png new file mode 100644 index 0000000000..488254a11b Binary files /dev/null and b/docs/doxygen-user_fr/images/mt_content_viewer_untranslated_text.png differ diff --git a/docs/doxygen-user_fr/images/mt_file_name_enable.png b/docs/doxygen-user_fr/images/mt_file_name_enable.png new file mode 100644 index 0000000000..8f2ee50ae0 Binary files /dev/null and b/docs/doxygen-user_fr/images/mt_file_name_enable.png differ diff --git a/docs/doxygen-user_fr/images/mt_file_name_original.png b/docs/doxygen-user_fr/images/mt_file_name_original.png new file mode 100644 index 0000000000..93d9aaa449 Binary files /dev/null and b/docs/doxygen-user_fr/images/mt_file_name_original.png differ diff --git a/docs/doxygen-user_fr/images/mt_file_names_translated.png b/docs/doxygen-user_fr/images/mt_file_names_translated.png new file mode 100644 index 0000000000..38904efa38 Binary files /dev/null and b/docs/doxygen-user_fr/images/mt_file_names_translated.png differ diff --git a/docs/doxygen-user_fr/images/mt_message_orig.png b/docs/doxygen-user_fr/images/mt_message_orig.png new file mode 100644 index 0000000000..3dcd4f7027 Binary files /dev/null and b/docs/doxygen-user_fr/images/mt_message_orig.png differ diff --git a/docs/doxygen-user_fr/images/mt_message_translated.png b/docs/doxygen-user_fr/images/mt_message_translated.png new file mode 100644 index 0000000000..ba71074c11 Binary files /dev/null and b/docs/doxygen-user_fr/images/mt_message_translated.png differ diff --git a/docs/doxygen-user_fr/images/mt_ocr_image.png b/docs/doxygen-user_fr/images/mt_ocr_image.png new file mode 100644 index 0000000000..b4e16bfa09 Binary files /dev/null and b/docs/doxygen-user_fr/images/mt_ocr_image.png differ diff --git a/docs/doxygen-user_fr/images/mt_ocr_result.png b/docs/doxygen-user_fr/images/mt_ocr_result.png new file mode 100644 index 0000000000..27d9af77f0 Binary files /dev/null and b/docs/doxygen-user_fr/images/mt_ocr_result.png differ diff --git a/docs/doxygen-user_fr/images/multi-user-case-properties.PNG b/docs/doxygen-user_fr/images/multi-user-case-properties.PNG new file mode 100644 index 0000000000..1bd87ba21f Binary files /dev/null and b/docs/doxygen-user_fr/images/multi-user-case-properties.PNG differ diff --git a/docs/doxygen-user_fr/images/multi-user-network.png b/docs/doxygen-user_fr/images/multi-user-network.png new file mode 100644 index 0000000000..bdc6ce7ca7 Binary files /dev/null and b/docs/doxygen-user_fr/images/multi-user-network.png differ diff --git a/docs/doxygen-user_fr/images/multi_user_case_select.png b/docs/doxygen-user_fr/images/multi_user_case_select.png new file mode 100644 index 0000000000..c4ca377fc6 Binary files /dev/null and b/docs/doxygen-user_fr/images/multi_user_case_select.png differ diff --git a/docs/doxygen-user_fr/images/newLoginRole.PNG b/docs/doxygen-user_fr/images/newLoginRole.PNG new file mode 100644 index 0000000000..2ceaf5305f Binary files /dev/null and b/docs/doxygen-user_fr/images/newLoginRole.PNG differ diff --git a/docs/doxygen-user_fr/images/newPassword.PNG b/docs/doxygen-user_fr/images/newPassword.PNG new file mode 100644 index 0000000000..aeaa67fb31 Binary files /dev/null and b/docs/doxygen-user_fr/images/newPassword.PNG differ diff --git a/docs/doxygen-user_fr/images/newRights.PNG b/docs/doxygen-user_fr/images/newRights.PNG new file mode 100644 index 0000000000..548519c757 Binary files /dev/null and b/docs/doxygen-user_fr/images/newRights.PNG differ diff --git a/docs/doxygen-user_fr/images/newUserAndPassword.PNG b/docs/doxygen-user_fr/images/newUserAndPassword.PNG new file mode 100644 index 0000000000..39f90ab846 Binary files /dev/null and b/docs/doxygen-user_fr/images/newUserAndPassword.PNG differ diff --git a/docs/doxygen-user_fr/images/new_case_optional_info.png b/docs/doxygen-user_fr/images/new_case_optional_info.png new file mode 100644 index 0000000000..77e2477d67 Binary files /dev/null and b/docs/doxygen-user_fr/images/new_case_optional_info.png differ diff --git a/docs/doxygen-user_fr/images/nsrl_import_process.PNG b/docs/doxygen-user_fr/images/nsrl_import_process.PNG new file mode 100644 index 0000000000..54d52f33e3 Binary files /dev/null and b/docs/doxygen-user_fr/images/nsrl_import_process.PNG differ diff --git a/docs/doxygen-user_fr/images/objectTypesComputers.PNG b/docs/doxygen-user_fr/images/objectTypesComputers.PNG new file mode 100644 index 0000000000..10b6db1444 Binary files /dev/null and b/docs/doxygen-user_fr/images/objectTypesComputers.PNG differ diff --git a/docs/doxygen-user_fr/images/object_detection_classifier_dir.PNG b/docs/doxygen-user_fr/images/object_detection_classifier_dir.PNG new file mode 100644 index 0000000000..7915d370de Binary files /dev/null and b/docs/doxygen-user_fr/images/object_detection_classifier_dir.PNG differ diff --git a/docs/doxygen-user_fr/images/object_detection_results.PNG b/docs/doxygen-user_fr/images/object_detection_results.PNG new file mode 100644 index 0000000000..28866ac9c9 Binary files /dev/null and b/docs/doxygen-user_fr/images/object_detection_results.PNG differ diff --git a/docs/doxygen-user_fr/images/object_detection_warning.PNG b/docs/doxygen-user_fr/images/object_detection_warning.PNG new file mode 100644 index 0000000000..b1367d9365 Binary files /dev/null and b/docs/doxygen-user_fr/images/object_detection_warning.PNG differ diff --git a/docs/doxygen-user_fr/images/open-file-search-component-1.PNG b/docs/doxygen-user_fr/images/open-file-search-component-1.PNG new file mode 100644 index 0000000000..a226d461b7 Binary files /dev/null and b/docs/doxygen-user_fr/images/open-file-search-component-1.PNG differ diff --git a/docs/doxygen-user_fr/images/open-file-search-component-2.PNG b/docs/doxygen-user_fr/images/open-file-search-component-2.PNG new file mode 100644 index 0000000000..c968e0e223 Binary files /dev/null and b/docs/doxygen-user_fr/images/open-file-search-component-2.PNG differ diff --git a/docs/doxygen-user_fr/images/open_log_folder.PNG b/docs/doxygen-user_fr/images/open_log_folder.PNG new file mode 100644 index 0000000000..d280d9d0fa Binary files /dev/null and b/docs/doxygen-user_fr/images/open_log_folder.PNG differ diff --git a/docs/doxygen-user_fr/images/open_output_folder.PNG b/docs/doxygen-user_fr/images/open_output_folder.PNG new file mode 100644 index 0000000000..d520d885b2 Binary files /dev/null and b/docs/doxygen-user_fr/images/open_output_folder.PNG differ diff --git a/docs/doxygen-user_fr/images/options_application.png b/docs/doxygen-user_fr/images/options_application.png new file mode 100644 index 0000000000..3823eb7a2e Binary files /dev/null and b/docs/doxygen-user_fr/images/options_application.png differ diff --git a/docs/doxygen-user_fr/images/options_ext_viewer.jpg b/docs/doxygen-user_fr/images/options_ext_viewer.jpg new file mode 100644 index 0000000000..fcb9fa75de Binary files /dev/null and b/docs/doxygen-user_fr/images/options_ext_viewer.jpg differ diff --git a/docs/doxygen-user_fr/images/options_ext_viewer_context_menu.jpg b/docs/doxygen-user_fr/images/options_ext_viewer_context_menu.jpg new file mode 100644 index 0000000000..d6d53cb2f0 Binary files /dev/null and b/docs/doxygen-user_fr/images/options_ext_viewer_context_menu.jpg differ diff --git a/docs/doxygen-user_fr/images/options_logo.png b/docs/doxygen-user_fr/images/options_logo.png new file mode 100644 index 0000000000..99e04f80b4 Binary files /dev/null and b/docs/doxygen-user_fr/images/options_logo.png differ diff --git a/docs/doxygen-user_fr/images/options_logo_report.jpg b/docs/doxygen-user_fr/images/options_logo_report.jpg new file mode 100644 index 0000000000..43266b8d6f Binary files /dev/null and b/docs/doxygen-user_fr/images/options_logo_report.jpg differ diff --git a/docs/doxygen-user_fr/images/othernodeingesting.PNG b/docs/doxygen-user_fr/images/othernodeingesting.PNG new file mode 100644 index 0000000000..15d73c9e75 Binary files /dev/null and b/docs/doxygen-user_fr/images/othernodeingesting.PNG differ diff --git a/docs/doxygen-user_fr/images/pgAdmin.PNG b/docs/doxygen-user_fr/images/pgAdmin.PNG new file mode 100644 index 0000000000..cca4988335 Binary files /dev/null and b/docs/doxygen-user_fr/images/pgAdmin.PNG differ diff --git a/docs/doxygen-user_fr/images/photo_rec_custom.png b/docs/doxygen-user_fr/images/photo_rec_custom.png new file mode 100644 index 0000000000..fb48d787e3 Binary files /dev/null and b/docs/doxygen-user_fr/images/photo_rec_custom.png differ diff --git a/docs/doxygen-user_fr/images/photo_rec_extensions.png b/docs/doxygen-user_fr/images/photo_rec_extensions.png new file mode 100644 index 0000000000..5d26757b0e Binary files /dev/null and b/docs/doxygen-user_fr/images/photo_rec_extensions.png differ diff --git a/docs/doxygen-user_fr/images/photo_rec_settings.PNG b/docs/doxygen-user_fr/images/photo_rec_settings.PNG new file mode 100644 index 0000000000..1c14373501 Binary files /dev/null and b/docs/doxygen-user_fr/images/photo_rec_settings.PNG differ diff --git a/docs/doxygen-user_fr/images/photorec_output.PNG b/docs/doxygen-user_fr/images/photorec_output.PNG new file mode 100644 index 0000000000..566e6a4652 Binary files /dev/null and b/docs/doxygen-user_fr/images/photorec_output.PNG differ diff --git a/docs/doxygen-user_fr/images/plaso_config.png b/docs/doxygen-user_fr/images/plaso_config.png new file mode 100644 index 0000000000..e31aea1a23 Binary files /dev/null and b/docs/doxygen-user_fr/images/plaso_config.png differ diff --git a/docs/doxygen-user_fr/images/plaso_timeline.png b/docs/doxygen-user_fr/images/plaso_timeline.png new file mode 100644 index 0000000000..af112b2732 Binary files /dev/null and b/docs/doxygen-user_fr/images/plaso_timeline.png differ diff --git a/docs/doxygen-user_fr/images/portable_case_chunks.png b/docs/doxygen-user_fr/images/portable_case_chunks.png new file mode 100644 index 0000000000..de21370434 Binary files /dev/null and b/docs/doxygen-user_fr/images/portable_case_chunks.png differ diff --git a/docs/doxygen-user_fr/images/portable_case_empty_image.png b/docs/doxygen-user_fr/images/portable_case_empty_image.png new file mode 100644 index 0000000000..e6766db08b Binary files /dev/null and b/docs/doxygen-user_fr/images/portable_case_empty_image.png differ diff --git a/docs/doxygen-user_fr/images/portable_case_folder.png b/docs/doxygen-user_fr/images/portable_case_folder.png new file mode 100644 index 0000000000..1e3a5b98df Binary files /dev/null and b/docs/doxygen-user_fr/images/portable_case_folder.png differ diff --git a/docs/doxygen-user_fr/images/portable_case_interesting_items.png b/docs/doxygen-user_fr/images/portable_case_interesting_items.png new file mode 100644 index 0000000000..3a8358c4c6 Binary files /dev/null and b/docs/doxygen-user_fr/images/portable_case_interesting_items.png differ diff --git a/docs/doxygen-user_fr/images/portable_case_open_bat.png b/docs/doxygen-user_fr/images/portable_case_open_bat.png new file mode 100644 index 0000000000..57e0985562 Binary files /dev/null and b/docs/doxygen-user_fr/images/portable_case_open_bat.png differ diff --git a/docs/doxygen-user_fr/images/portable_case_original_version.png b/docs/doxygen-user_fr/images/portable_case_original_version.png new file mode 100644 index 0000000000..74b906c671 Binary files /dev/null and b/docs/doxygen-user_fr/images/portable_case_original_version.png differ diff --git a/docs/doxygen-user_fr/images/portable_case_portable_version.png b/docs/doxygen-user_fr/images/portable_case_portable_version.png new file mode 100644 index 0000000000..1172e06708 Binary files /dev/null and b/docs/doxygen-user_fr/images/portable_case_portable_version.png differ diff --git a/docs/doxygen-user_fr/images/portable_case_report_panel.png b/docs/doxygen-user_fr/images/portable_case_report_panel.png new file mode 100644 index 0000000000..0919d68d62 Binary files /dev/null and b/docs/doxygen-user_fr/images/portable_case_report_panel.png differ diff --git a/docs/doxygen-user_fr/images/portable_case_tags.png b/docs/doxygen-user_fr/images/portable_case_tags.png new file mode 100644 index 0000000000..d5b7064d27 Binary files /dev/null and b/docs/doxygen-user_fr/images/portable_case_tags.png differ diff --git a/docs/doxygen-user_fr/images/portable_case_unpackage.png b/docs/doxygen-user_fr/images/portable_case_unpackage.png new file mode 100644 index 0000000000..1d4b20b7ec Binary files /dev/null and b/docs/doxygen-user_fr/images/portable_case_unpackage.png differ diff --git a/docs/doxygen-user_fr/images/postgresqlinstall3.PNG b/docs/doxygen-user_fr/images/postgresqlinstall3.PNG new file mode 100644 index 0000000000..37aaf8b7da Binary files /dev/null and b/docs/doxygen-user_fr/images/postgresqlinstall3.PNG differ diff --git a/docs/doxygen-user_fr/images/postgresqlinstall4.PNG b/docs/doxygen-user_fr/images/postgresqlinstall4.PNG new file mode 100644 index 0000000000..76a26ffd92 Binary files /dev/null and b/docs/doxygen-user_fr/images/postgresqlinstall4.PNG differ diff --git a/docs/doxygen-user_fr/images/postgresqlinstall5.PNG b/docs/doxygen-user_fr/images/postgresqlinstall5.PNG new file mode 100644 index 0000000000..d9637ad148 Binary files /dev/null and b/docs/doxygen-user_fr/images/postgresqlinstall5.PNG differ diff --git a/docs/doxygen-user_fr/images/postgresqlinstall6.PNG b/docs/doxygen-user_fr/images/postgresqlinstall6.PNG new file mode 100644 index 0000000000..a2bafe672f Binary files /dev/null and b/docs/doxygen-user_fr/images/postgresqlinstall6.PNG differ diff --git a/docs/doxygen-user_fr/images/postgresqlinstall7.PNG b/docs/doxygen-user_fr/images/postgresqlinstall7.PNG new file mode 100644 index 0000000000..4df64a135f Binary files /dev/null and b/docs/doxygen-user_fr/images/postgresqlinstall7.PNG differ diff --git a/docs/doxygen-user_fr/images/previous-version-already-run.PNG b/docs/doxygen-user_fr/images/previous-version-already-run.PNG new file mode 100644 index 0000000000..3e685577d0 Binary files /dev/null and b/docs/doxygen-user_fr/images/previous-version-already-run.PNG differ diff --git a/docs/doxygen-user_fr/images/profile-data-source-panel.PNG b/docs/doxygen-user_fr/images/profile-data-source-panel.PNG new file mode 100644 index 0000000000..debdf66ad5 Binary files /dev/null and b/docs/doxygen-user_fr/images/profile-data-source-panel.PNG differ diff --git a/docs/doxygen-user_fr/images/proxySettings.PNG b/docs/doxygen-user_fr/images/proxySettings.PNG new file mode 100644 index 0000000000..b405bb53b0 Binary files /dev/null and b/docs/doxygen-user_fr/images/proxySettings.PNG differ diff --git a/docs/doxygen-user_fr/images/quick_search_configuration.png b/docs/doxygen-user_fr/images/quick_search_configuration.png new file mode 100644 index 0000000000..986d667c0c Binary files /dev/null and b/docs/doxygen-user_fr/images/quick_search_configuration.png differ diff --git a/docs/doxygen-user_fr/images/quick_search_result.png b/docs/doxygen-user_fr/images/quick_search_result.png new file mode 100644 index 0000000000..c11d8ffa74 Binary files /dev/null and b/docs/doxygen-user_fr/images/quick_search_result.png differ diff --git a/docs/doxygen-user_fr/images/reports_case.png b/docs/doxygen-user_fr/images/reports_case.png new file mode 100644 index 0000000000..8e128f51e7 Binary files /dev/null and b/docs/doxygen-user_fr/images/reports_case.png differ diff --git a/docs/doxygen-user_fr/images/reports_datasource_select.png b/docs/doxygen-user_fr/images/reports_datasource_select.png new file mode 100644 index 0000000000..3c93abcf66 Binary files /dev/null and b/docs/doxygen-user_fr/images/reports_datasource_select.png differ diff --git a/docs/doxygen-user_fr/images/reports_excel.png b/docs/doxygen-user_fr/images/reports_excel.png new file mode 100644 index 0000000000..35ad752126 Binary files /dev/null and b/docs/doxygen-user_fr/images/reports_excel.png differ diff --git a/docs/doxygen-user_fr/images/reports_files_config.png b/docs/doxygen-user_fr/images/reports_files_config.png new file mode 100644 index 0000000000..00f746d562 Binary files /dev/null and b/docs/doxygen-user_fr/images/reports_files_config.png differ diff --git a/docs/doxygen-user_fr/images/reports_files_delimiter.png b/docs/doxygen-user_fr/images/reports_files_delimiter.png new file mode 100644 index 0000000000..6726897cc6 Binary files /dev/null and b/docs/doxygen-user_fr/images/reports_files_delimiter.png differ diff --git a/docs/doxygen-user_fr/images/reports_files_results.png b/docs/doxygen-user_fr/images/reports_files_results.png new file mode 100644 index 0000000000..0ef80a5e8f Binary files /dev/null and b/docs/doxygen-user_fr/images/reports_files_results.png differ diff --git a/docs/doxygen-user_fr/images/reports_folder.png b/docs/doxygen-user_fr/images/reports_folder.png new file mode 100644 index 0000000000..b597320f4f Binary files /dev/null and b/docs/doxygen-user_fr/images/reports_folder.png differ diff --git a/docs/doxygen-user_fr/images/reports_hashes_config.png b/docs/doxygen-user_fr/images/reports_hashes_config.png new file mode 100644 index 0000000000..9e30e406f2 Binary files /dev/null and b/docs/doxygen-user_fr/images/reports_hashes_config.png differ diff --git a/docs/doxygen-user_fr/images/reports_html_all_results.png b/docs/doxygen-user_fr/images/reports_html_all_results.png new file mode 100644 index 0000000000..bad6a9500d Binary files /dev/null and b/docs/doxygen-user_fr/images/reports_html_all_results.png differ diff --git a/docs/doxygen-user_fr/images/reports_html_art_select.png b/docs/doxygen-user_fr/images/reports_html_art_select.png new file mode 100644 index 0000000000..fa428d6ad8 Binary files /dev/null and b/docs/doxygen-user_fr/images/reports_html_art_select.png differ diff --git a/docs/doxygen-user_fr/images/reports_html_display.png b/docs/doxygen-user_fr/images/reports_html_display.png new file mode 100644 index 0000000000..35f1f102fb Binary files /dev/null and b/docs/doxygen-user_fr/images/reports_html_display.png differ diff --git a/docs/doxygen-user_fr/images/reports_html_header.png b/docs/doxygen-user_fr/images/reports_html_header.png new file mode 100644 index 0000000000..205e7fa2f0 Binary files /dev/null and b/docs/doxygen-user_fr/images/reports_html_header.png differ diff --git a/docs/doxygen-user_fr/images/reports_html_tagged.png b/docs/doxygen-user_fr/images/reports_html_tagged.png new file mode 100644 index 0000000000..da4c0583f4 Binary files /dev/null and b/docs/doxygen-user_fr/images/reports_html_tagged.png differ diff --git a/docs/doxygen-user_fr/images/reports_kml.png b/docs/doxygen-user_fr/images/reports_kml.png new file mode 100644 index 0000000000..f3e8b1cd83 Binary files /dev/null and b/docs/doxygen-user_fr/images/reports_kml.png differ diff --git a/docs/doxygen-user_fr/images/reports_result_viewer.png b/docs/doxygen-user_fr/images/reports_result_viewer.png new file mode 100644 index 0000000000..097f6363db Binary files /dev/null and b/docs/doxygen-user_fr/images/reports_result_viewer.png differ diff --git a/docs/doxygen-user_fr/images/reports_select.png b/docs/doxygen-user_fr/images/reports_select.png new file mode 100644 index 0000000000..97e440adeb Binary files /dev/null and b/docs/doxygen-user_fr/images/reports_select.png differ diff --git a/docs/doxygen-user_fr/images/reset_windows.png b/docs/doxygen-user_fr/images/reset_windows.png new file mode 100644 index 0000000000..0b1a7ef411 Binary files /dev/null and b/docs/doxygen-user_fr/images/reset_windows.png differ diff --git a/docs/doxygen-user_fr/images/result-viewer-example-1.PNG b/docs/doxygen-user_fr/images/result-viewer-example-1.PNG new file mode 100644 index 0000000000..409cea78be Binary files /dev/null and b/docs/doxygen-user_fr/images/result-viewer-example-1.PNG differ diff --git a/docs/doxygen-user_fr/images/result-viewer-example-2.PNG b/docs/doxygen-user_fr/images/result-viewer-example-2.PNG new file mode 100644 index 0000000000..25be40d481 Binary files /dev/null and b/docs/doxygen-user_fr/images/result-viewer-example-2.PNG differ diff --git a/docs/doxygen-user_fr/images/result-viewer-example-3.PNG b/docs/doxygen-user_fr/images/result-viewer-example-3.PNG new file mode 100644 index 0000000000..f9cd06056b Binary files /dev/null and b/docs/doxygen-user_fr/images/result-viewer-example-3.PNG differ diff --git a/docs/doxygen-user_fr/images/result-viewer-window-example.PNG b/docs/doxygen-user_fr/images/result-viewer-window-example.PNG new file mode 100644 index 0000000000..17caedafd4 Binary files /dev/null and b/docs/doxygen-user_fr/images/result-viewer-window-example.PNG differ diff --git a/docs/doxygen-user_fr/images/result_viewer_csv.PNG b/docs/doxygen-user_fr/images/result_viewer_csv.PNG new file mode 100644 index 0000000000..c02c182b89 Binary files /dev/null and b/docs/doxygen-user_fr/images/result_viewer_csv.PNG differ diff --git a/docs/doxygen-user_fr/images/result_viewer_paging.PNG b/docs/doxygen-user_fr/images/result_viewer_paging.PNG new file mode 100644 index 0000000000..2604b53741 Binary files /dev/null and b/docs/doxygen-user_fr/images/result_viewer_paging.PNG differ diff --git a/docs/doxygen-user_fr/images/runtime_settings.PNG b/docs/doxygen-user_fr/images/runtime_settings.PNG new file mode 100644 index 0000000000..1d02f96a42 Binary files /dev/null and b/docs/doxygen-user_fr/images/runtime_settings.PNG differ diff --git a/docs/doxygen-user_fr/images/screenshot.PNG b/docs/doxygen-user_fr/images/screenshot.PNG new file mode 100644 index 0000000000..b3d7359da6 Binary files /dev/null and b/docs/doxygen-user_fr/images/screenshot.PNG differ diff --git a/docs/doxygen-user_fr/images/search_all_cases_dialog.png b/docs/doxygen-user_fr/images/search_all_cases_dialog.png new file mode 100644 index 0000000000..3b2f405cee Binary files /dev/null and b/docs/doxygen-user_fr/images/search_all_cases_dialog.png differ diff --git a/docs/doxygen-user_fr/images/search_all_cases_results.png b/docs/doxygen-user_fr/images/search_all_cases_results.png new file mode 100644 index 0000000000..dcdfdcd168 Binary files /dev/null and b/docs/doxygen-user_fr/images/search_all_cases_results.png differ diff --git a/docs/doxygen-user_fr/images/select-data-source-type.PNG b/docs/doxygen-user_fr/images/select-data-source-type.PNG new file mode 100644 index 0000000000..e772e0114e Binary files /dev/null and b/docs/doxygen-user_fr/images/select-data-source-type.PNG differ diff --git a/docs/doxygen-user_fr/images/select-ingest-modules.PNG b/docs/doxygen-user_fr/images/select-ingest-modules.PNG new file mode 100644 index 0000000000..9941a0dfb3 Binary files /dev/null and b/docs/doxygen-user_fr/images/select-ingest-modules.PNG differ diff --git a/docs/doxygen-user_fr/images/serviceinstall.PNG b/docs/doxygen-user_fr/images/serviceinstall.PNG new file mode 100644 index 0000000000..b20f07d9c8 Binary files /dev/null and b/docs/doxygen-user_fr/images/serviceinstall.PNG differ diff --git a/docs/doxygen-user_fr/images/sharedStoragePermissions.PNG b/docs/doxygen-user_fr/images/sharedStoragePermissions.PNG new file mode 100644 index 0000000000..bea1aa0fd4 Binary files /dev/null and b/docs/doxygen-user_fr/images/sharedStoragePermissions.PNG differ diff --git a/docs/doxygen-user_fr/images/single-user-case-properties.PNG b/docs/doxygen-user_fr/images/single-user-case-properties.PNG new file mode 100644 index 0000000000..181cf65b87 Binary files /dev/null and b/docs/doxygen-user_fr/images/single-user-case-properties.PNG differ diff --git a/docs/doxygen-user_fr/images/solr/solr_adding_nodes_1.png b/docs/doxygen-user_fr/images/solr/solr_adding_nodes_1.png new file mode 100644 index 0000000000..72eda5b3eb Binary files /dev/null and b/docs/doxygen-user_fr/images/solr/solr_adding_nodes_1.png differ diff --git a/docs/doxygen-user_fr/images/solr/solr_adding_nodes_2.png b/docs/doxygen-user_fr/images/solr/solr_adding_nodes_2.png new file mode 100644 index 0000000000..f93324681d Binary files /dev/null and b/docs/doxygen-user_fr/images/solr/solr_adding_nodes_2.png differ diff --git a/docs/doxygen-user_fr/images/solr/solr_autopsy.png b/docs/doxygen-user_fr/images/solr/solr_autopsy.png new file mode 100644 index 0000000000..06aea11831 Binary files /dev/null and b/docs/doxygen-user_fr/images/solr/solr_autopsy.png differ diff --git a/docs/doxygen-user_fr/images/solr/solr_autopsy_zk.png b/docs/doxygen-user_fr/images/solr/solr_autopsy_zk.png new file mode 100644 index 0000000000..53e61c17c1 Binary files /dev/null and b/docs/doxygen-user_fr/images/solr/solr_autopsy_zk.png differ diff --git a/docs/doxygen-user_fr/images/solr/solr_comment_out_updateLog.jpg b/docs/doxygen-user_fr/images/solr/solr_comment_out_updateLog.jpg new file mode 100644 index 0000000000..90737515fa Binary files /dev/null and b/docs/doxygen-user_fr/images/solr/solr_comment_out_updateLog.jpg differ diff --git a/docs/doxygen-user_fr/images/solr/solr_config_autocommit.jpg b/docs/doxygen-user_fr/images/solr/solr_config_autocommit.jpg new file mode 100644 index 0000000000..5e6cc7a9bf Binary files /dev/null and b/docs/doxygen-user_fr/images/solr/solr_config_autocommit.jpg differ diff --git a/docs/doxygen-user_fr/images/solr/solr_config_case.png b/docs/doxygen-user_fr/images/solr/solr_config_case.png new file mode 100644 index 0000000000..b2e73468be Binary files /dev/null and b/docs/doxygen-user_fr/images/solr/solr_config_case.png differ diff --git a/docs/doxygen-user_fr/images/solr/solr_config_folder.png b/docs/doxygen-user_fr/images/solr/solr_config_folder.png new file mode 100644 index 0000000000..615e0903d5 Binary files /dev/null and b/docs/doxygen-user_fr/images/solr/solr_config_folder.png differ diff --git a/docs/doxygen-user_fr/images/solr/solr_config_monitoring.png b/docs/doxygen-user_fr/images/solr/solr_config_monitoring.png new file mode 100644 index 0000000000..d6116cd256 Binary files /dev/null and b/docs/doxygen-user_fr/images/solr/solr_config_monitoring.png differ diff --git a/docs/doxygen-user_fr/images/solr/solr_config_param.png b/docs/doxygen-user_fr/images/solr/solr_config_param.png new file mode 100644 index 0000000000..3960fcf2e8 Binary files /dev/null and b/docs/doxygen-user_fr/images/solr/solr_config_param.png differ diff --git a/docs/doxygen-user_fr/images/solr/solr_config_todo.png b/docs/doxygen-user_fr/images/solr/solr_config_todo.png new file mode 100644 index 0000000000..01c587dfff Binary files /dev/null and b/docs/doxygen-user_fr/images/solr/solr_config_todo.png differ diff --git a/docs/doxygen-user_fr/images/solr/solr_disable_periodic_search.png b/docs/doxygen-user_fr/images/solr/solr_disable_periodic_search.png new file mode 100644 index 0000000000..c6b4242c68 Binary files /dev/null and b/docs/doxygen-user_fr/images/solr/solr_disable_periodic_search.png differ diff --git a/docs/doxygen-user_fr/images/solr/solr_install_1.png b/docs/doxygen-user_fr/images/solr/solr_install_1.png new file mode 100644 index 0000000000..17b9359d69 Binary files /dev/null and b/docs/doxygen-user_fr/images/solr/solr_install_1.png differ diff --git a/docs/doxygen-user_fr/images/solr/solr_install_2.png b/docs/doxygen-user_fr/images/solr/solr_install_2.png new file mode 100644 index 0000000000..fe2a9516ef Binary files /dev/null and b/docs/doxygen-user_fr/images/solr/solr_install_2.png differ diff --git a/docs/doxygen-user_fr/images/solr/solr_install_3.png b/docs/doxygen-user_fr/images/solr/solr_install_3.png new file mode 100644 index 0000000000..571312d5a5 Binary files /dev/null and b/docs/doxygen-user_fr/images/solr/solr_install_3.png differ diff --git a/docs/doxygen-user_fr/images/solr/solr_install_4.png b/docs/doxygen-user_fr/images/solr/solr_install_4.png new file mode 100644 index 0000000000..6ff5fa8bcd Binary files /dev/null and b/docs/doxygen-user_fr/images/solr/solr_install_4.png differ diff --git a/docs/doxygen-user_fr/images/solr/solr_jvm.png b/docs/doxygen-user_fr/images/solr/solr_jvm.png new file mode 100644 index 0000000000..1285110183 Binary files /dev/null and b/docs/doxygen-user_fr/images/solr/solr_jvm.png differ diff --git a/docs/doxygen-user_fr/images/solr/solr_running_in_parallel.png b/docs/doxygen-user_fr/images/solr/solr_running_in_parallel.png new file mode 100644 index 0000000000..53e61c17c1 Binary files /dev/null and b/docs/doxygen-user_fr/images/solr/solr_running_in_parallel.png differ diff --git a/docs/doxygen-user_fr/images/solr/solr_standalone_zk_1.png b/docs/doxygen-user_fr/images/solr/solr_standalone_zk_1.png new file mode 100644 index 0000000000..8ac44025e9 Binary files /dev/null and b/docs/doxygen-user_fr/images/solr/solr_standalone_zk_1.png differ diff --git a/docs/doxygen-user_fr/images/solr/solr_standalone_zk_2.png b/docs/doxygen-user_fr/images/solr/solr_standalone_zk_2.png new file mode 100644 index 0000000000..ab64dcb392 Binary files /dev/null and b/docs/doxygen-user_fr/images/solr/solr_standalone_zk_2.png differ diff --git a/docs/doxygen-user_fr/images/solr/solr_standalone_zk_3.png b/docs/doxygen-user_fr/images/solr/solr_standalone_zk_3.png new file mode 100644 index 0000000000..937a871f31 Binary files /dev/null and b/docs/doxygen-user_fr/images/solr/solr_standalone_zk_3.png differ diff --git a/docs/doxygen-user_fr/images/solr/solr_standalone_zk_4.png b/docs/doxygen-user_fr/images/solr/solr_standalone_zk_4.png new file mode 100644 index 0000000000..744b478d69 Binary files /dev/null and b/docs/doxygen-user_fr/images/solr/solr_standalone_zk_4.png differ diff --git a/docs/doxygen-user_fr/images/solr/solr_start_1.png b/docs/doxygen-user_fr/images/solr/solr_start_1.png new file mode 100644 index 0000000000..c17bb02a86 Binary files /dev/null and b/docs/doxygen-user_fr/images/solr/solr_start_1.png differ diff --git a/docs/doxygen-user_fr/images/solr/solr_start_2.png b/docs/doxygen-user_fr/images/solr/solr_start_2.png new file mode 100644 index 0000000000..28a3825e46 Binary files /dev/null and b/docs/doxygen-user_fr/images/solr/solr_start_2.png differ diff --git a/docs/doxygen-user_fr/images/solr/solr_testing_1.png b/docs/doxygen-user_fr/images/solr/solr_testing_1.png new file mode 100644 index 0000000000..6157dadf67 Binary files /dev/null and b/docs/doxygen-user_fr/images/solr/solr_testing_1.png differ diff --git a/docs/doxygen-user_fr/images/solr/solr_transaction_log_errors.jpg b/docs/doxygen-user_fr/images/solr/solr_transaction_log_errors.jpg new file mode 100644 index 0000000000..4328068b57 Binary files /dev/null and b/docs/doxygen-user_fr/images/solr/solr_transaction_log_errors.jpg differ diff --git a/docs/doxygen-user_fr/images/solr/solr_user_1.png b/docs/doxygen-user_fr/images/solr/solr_user_1.png new file mode 100644 index 0000000000..31bbc855e3 Binary files /dev/null and b/docs/doxygen-user_fr/images/solr/solr_user_1.png differ diff --git a/docs/doxygen-user_fr/images/solr/solr_user_2.png b/docs/doxygen-user_fr/images/solr/solr_user_2.png new file mode 100644 index 0000000000..8849a5e082 Binary files /dev/null and b/docs/doxygen-user_fr/images/solr/solr_user_2.png differ diff --git a/docs/doxygen-user_fr/images/solr/solr_zk_migration_1.png b/docs/doxygen-user_fr/images/solr/solr_zk_migration_1.png new file mode 100644 index 0000000000..d85ba4e992 Binary files /dev/null and b/docs/doxygen-user_fr/images/solr/solr_zk_migration_1.png differ diff --git a/docs/doxygen-user_fr/images/solr/solr_zk_migration_2.png b/docs/doxygen-user_fr/images/solr/solr_zk_migration_2.png new file mode 100644 index 0000000000..9f8afbe3e4 Binary files /dev/null and b/docs/doxygen-user_fr/images/solr/solr_zk_migration_2.png differ diff --git a/docs/doxygen-user_fr/images/solr/solr_zk_migration_3.png b/docs/doxygen-user_fr/images/solr/solr_zk_migration_3.png new file mode 100644 index 0000000000..ec329b6dc2 Binary files /dev/null and b/docs/doxygen-user_fr/images/solr/solr_zk_migration_3.png differ diff --git a/docs/doxygen-user_fr/images/solr/solr_zk_migration_4.png b/docs/doxygen-user_fr/images/solr/solr_zk_migration_4.png new file mode 100644 index 0000000000..f2e67a5503 Binary files /dev/null and b/docs/doxygen-user_fr/images/solr/solr_zk_migration_4.png differ diff --git a/docs/doxygen-user_fr/images/solr/solr_zk_migration_5.png b/docs/doxygen-user_fr/images/solr/solr_zk_migration_5.png new file mode 100644 index 0000000000..51dca488ce Binary files /dev/null and b/docs/doxygen-user_fr/images/solr/solr_zk_migration_5.png differ diff --git a/docs/doxygen-user_fr/images/solrinstall1.PNG b/docs/doxygen-user_fr/images/solrinstall1.PNG new file mode 100644 index 0000000000..4ecc093de5 Binary files /dev/null and b/docs/doxygen-user_fr/images/solrinstall1.PNG differ diff --git a/docs/doxygen-user_fr/images/solrinstall2.PNG b/docs/doxygen-user_fr/images/solrinstall2.PNG new file mode 100644 index 0000000000..b0cb95d496 Binary files /dev/null and b/docs/doxygen-user_fr/images/solrinstall2.PNG differ diff --git a/docs/doxygen-user_fr/images/solrinstall3.PNG b/docs/doxygen-user_fr/images/solrinstall3.PNG new file mode 100644 index 0000000000..4eb5040bb2 Binary files /dev/null and b/docs/doxygen-user_fr/images/solrinstall3.PNG differ diff --git a/docs/doxygen-user_fr/images/splashscreen.PNG b/docs/doxygen-user_fr/images/splashscreen.PNG new file mode 100644 index 0000000000..389df13e84 Binary files /dev/null and b/docs/doxygen-user_fr/images/splashscreen.PNG differ diff --git a/docs/doxygen-user_fr/images/symlinkjava.PNG b/docs/doxygen-user_fr/images/symlinkjava.PNG new file mode 100644 index 0000000000..25876c7144 Binary files /dev/null and b/docs/doxygen-user_fr/images/symlinkjava.PNG differ diff --git a/docs/doxygen-user_fr/images/table-result-viewer-tab.PNG b/docs/doxygen-user_fr/images/table-result-viewer-tab.PNG new file mode 100644 index 0000000000..aea0085790 Binary files /dev/null and b/docs/doxygen-user_fr/images/table-result-viewer-tab.PNG differ diff --git a/docs/doxygen-user_fr/images/tagging-1.PNG b/docs/doxygen-user_fr/images/tagging-1.PNG new file mode 100644 index 0000000000..e6c81c4afa Binary files /dev/null and b/docs/doxygen-user_fr/images/tagging-1.PNG differ diff --git a/docs/doxygen-user_fr/images/tagging-2.PNG b/docs/doxygen-user_fr/images/tagging-2.PNG new file mode 100644 index 0000000000..8a1b3c07b4 Binary files /dev/null and b/docs/doxygen-user_fr/images/tagging-2.PNG differ diff --git a/docs/doxygen-user_fr/images/tagging-3.PNG b/docs/doxygen-user_fr/images/tagging-3.PNG new file mode 100644 index 0000000000..9ad39a0225 Binary files /dev/null and b/docs/doxygen-user_fr/images/tagging-3.PNG differ diff --git a/docs/doxygen-user_fr/images/tagging-4.PNG b/docs/doxygen-user_fr/images/tagging-4.PNG new file mode 100644 index 0000000000..d1ee2a7b97 Binary files /dev/null and b/docs/doxygen-user_fr/images/tagging-4.PNG differ diff --git a/docs/doxygen-user_fr/images/tagging-5.PNG b/docs/doxygen-user_fr/images/tagging-5.PNG new file mode 100644 index 0000000000..e070db9b09 Binary files /dev/null and b/docs/doxygen-user_fr/images/tagging-5.PNG differ diff --git a/docs/doxygen-user_fr/images/tagging-6.PNG b/docs/doxygen-user_fr/images/tagging-6.PNG new file mode 100644 index 0000000000..c3ce6972d8 Binary files /dev/null and b/docs/doxygen-user_fr/images/tagging-6.PNG differ diff --git a/docs/doxygen-user_fr/images/tagging_comment_anno.png b/docs/doxygen-user_fr/images/tagging_comment_anno.png new file mode 100644 index 0000000000..24c906a457 Binary files /dev/null and b/docs/doxygen-user_fr/images/tagging_comment_anno.png differ diff --git a/docs/doxygen-user_fr/images/tagging_comment_context.png b/docs/doxygen-user_fr/images/tagging_comment_context.png new file mode 100644 index 0000000000..b0b25d86ef Binary files /dev/null and b/docs/doxygen-user_fr/images/tagging_comment_context.png differ diff --git a/docs/doxygen-user_fr/images/tagging_comment_icon.png b/docs/doxygen-user_fr/images/tagging_comment_icon.png new file mode 100644 index 0000000000..7b55aaf571 Binary files /dev/null and b/docs/doxygen-user_fr/images/tagging_comment_icon.png differ diff --git a/docs/doxygen-user_fr/images/tagging_comment_in_result_viewer.png b/docs/doxygen-user_fr/images/tagging_comment_in_result_viewer.png new file mode 100644 index 0000000000..274b8ff574 Binary files /dev/null and b/docs/doxygen-user_fr/images/tagging_comment_in_result_viewer.png differ diff --git a/docs/doxygen-user_fr/images/tagging_cr_comment.png b/docs/doxygen-user_fr/images/tagging_cr_comment.png new file mode 100644 index 0000000000..1c5f14393b Binary files /dev/null and b/docs/doxygen-user_fr/images/tagging_cr_comment.png differ diff --git a/docs/doxygen-user_fr/images/tagging_image_create_tag.png b/docs/doxygen-user_fr/images/tagging_image_create_tag.png new file mode 100644 index 0000000000..067cc278dd Binary files /dev/null and b/docs/doxygen-user_fr/images/tagging_image_create_tag.png differ diff --git a/docs/doxygen-user_fr/images/tagging_image_edit_tag.png b/docs/doxygen-user_fr/images/tagging_image_edit_tag.png new file mode 100644 index 0000000000..ce9a629526 Binary files /dev/null and b/docs/doxygen-user_fr/images/tagging_image_edit_tag.png differ diff --git a/docs/doxygen-user_fr/images/tagging_image_menu.png b/docs/doxygen-user_fr/images/tagging_image_menu.png new file mode 100644 index 0000000000..9ca8f06099 Binary files /dev/null and b/docs/doxygen-user_fr/images/tagging_image_menu.png differ diff --git a/docs/doxygen-user_fr/images/tagging_image_multiple.png b/docs/doxygen-user_fr/images/tagging_image_multiple.png new file mode 100644 index 0000000000..d41bba0f9a Binary files /dev/null and b/docs/doxygen-user_fr/images/tagging_image_multiple.png differ diff --git a/docs/doxygen-user_fr/images/tagging_image_one_tag.png b/docs/doxygen-user_fr/images/tagging_image_one_tag.png new file mode 100644 index 0000000000..4aa206bf49 Binary files /dev/null and b/docs/doxygen-user_fr/images/tagging_image_one_tag.png differ diff --git a/docs/doxygen-user_fr/images/tagging_image_report.png b/docs/doxygen-user_fr/images/tagging_image_report.png new file mode 100644 index 0000000000..6a053c9af5 Binary files /dev/null and b/docs/doxygen-user_fr/images/tagging_image_report.png differ diff --git a/docs/doxygen-user_fr/images/tagging_image_select.png b/docs/doxygen-user_fr/images/tagging_image_select.png new file mode 100644 index 0000000000..d44e2552aa Binary files /dev/null and b/docs/doxygen-user_fr/images/tagging_image_select.png differ diff --git a/docs/doxygen-user_fr/images/tagging_new_tag.PNG b/docs/doxygen-user_fr/images/tagging_new_tag.PNG new file mode 100644 index 0000000000..4ae64540f0 Binary files /dev/null and b/docs/doxygen-user_fr/images/tagging_new_tag.PNG differ diff --git a/docs/doxygen-user_fr/images/tagging_user_name.png b/docs/doxygen-user_fr/images/tagging_user_name.png new file mode 100644 index 0000000000..3869bde855 Binary files /dev/null and b/docs/doxygen-user_fr/images/tagging_user_name.png differ diff --git a/docs/doxygen-user_fr/images/tagging_view_options.png b/docs/doxygen-user_fr/images/tagging_view_options.png new file mode 100644 index 0000000000..8310c3c5fd Binary files /dev/null and b/docs/doxygen-user_fr/images/tagging_view_options.png differ diff --git a/docs/doxygen-user_fr/images/threadcount.PNG b/docs/doxygen-user_fr/images/threadcount.PNG new file mode 100644 index 0000000000..14ab551813 Binary files /dev/null and b/docs/doxygen-user_fr/images/threadcount.PNG differ diff --git a/docs/doxygen-user_fr/images/thumbnail-result-viewer-tab.PNG b/docs/doxygen-user_fr/images/thumbnail-result-viewer-tab.PNG new file mode 100644 index 0000000000..b53c14dc52 Binary files /dev/null and b/docs/doxygen-user_fr/images/thumbnail-result-viewer-tab.PNG differ diff --git a/docs/doxygen-user_fr/images/timeline_counts_view.png b/docs/doxygen-user_fr/images/timeline_counts_view.png new file mode 100644 index 0000000000..0f14c75c79 Binary files /dev/null and b/docs/doxygen-user_fr/images/timeline_counts_view.png differ diff --git a/docs/doxygen-user_fr/images/timeline_details_view.png b/docs/doxygen-user_fr/images/timeline_details_view.png new file mode 100644 index 0000000000..7357191a97 Binary files /dev/null and b/docs/doxygen-user_fr/images/timeline_details_view.png differ diff --git a/docs/doxygen-user_fr/images/timeline_list_view.png b/docs/doxygen-user_fr/images/timeline_list_view.png new file mode 100644 index 0000000000..46e012a315 Binary files /dev/null and b/docs/doxygen-user_fr/images/timeline_list_view.png differ diff --git a/docs/doxygen-user_fr/images/transientcache.PNG b/docs/doxygen-user_fr/images/transientcache.PNG new file mode 100644 index 0000000000..27aa656c9c Binary files /dev/null and b/docs/doxygen-user_fr/images/transientcache.PNG differ diff --git a/docs/doxygen-user_fr/images/triage/createVHD.png b/docs/doxygen-user_fr/images/triage/createVHD.png new file mode 100644 index 0000000000..8c8c859bcf Binary files /dev/null and b/docs/doxygen-user_fr/images/triage/createVHD.png differ diff --git a/docs/doxygen-user_fr/images/triage/fileFilter.png b/docs/doxygen-user_fr/images/triage/fileFilter.png new file mode 100644 index 0000000000..e327a15d71 Binary files /dev/null and b/docs/doxygen-user_fr/images/triage/fileFilter.png differ diff --git a/docs/doxygen-user_fr/images/triage/fileFilterImage.png b/docs/doxygen-user_fr/images/triage/fileFilterImage.png new file mode 100644 index 0000000000..22b21d81af Binary files /dev/null and b/docs/doxygen-user_fr/images/triage/fileFilterImage.png differ diff --git a/docs/doxygen-user_fr/images/triage/ingestProfile.png b/docs/doxygen-user_fr/images/triage/ingestProfile.png new file mode 100644 index 0000000000..731058c4d8 Binary files /dev/null and b/docs/doxygen-user_fr/images/triage/ingestProfile.png differ diff --git a/docs/doxygen-user_fr/images/triage/pipelineFolders.png b/docs/doxygen-user_fr/images/triage/pipelineFolders.png new file mode 100644 index 0000000000..41aa8a64bf Binary files /dev/null and b/docs/doxygen-user_fr/images/triage/pipelineFolders.png differ diff --git a/docs/doxygen-user_fr/images/triage/profileSelect.png b/docs/doxygen-user_fr/images/triage/profileSelect.png new file mode 100644 index 0000000000..d0b53df7e6 Binary files /dev/null and b/docs/doxygen-user_fr/images/triage/profileSelect.png differ diff --git a/docs/doxygen-user_fr/images/troubleshooting_log_menu.png b/docs/doxygen-user_fr/images/troubleshooting_log_menu.png new file mode 100644 index 0000000000..f6f4689021 Binary files /dev/null and b/docs/doxygen-user_fr/images/troubleshooting_log_menu.png differ diff --git a/docs/doxygen-user_fr/images/troubleshooting_thread.png b/docs/doxygen-user_fr/images/troubleshooting_thread.png new file mode 100644 index 0000000000..a384b81156 Binary files /dev/null and b/docs/doxygen-user_fr/images/troubleshooting_thread.png differ diff --git a/docs/doxygen-user_fr/images/ui-layout-1.PNG b/docs/doxygen-user_fr/images/ui-layout-1.PNG new file mode 100644 index 0000000000..8e54967524 Binary files /dev/null and b/docs/doxygen-user_fr/images/ui-layout-1.PNG differ diff --git a/docs/doxygen-user_fr/images/ui_layout_group_tree.PNG b/docs/doxygen-user_fr/images/ui_layout_group_tree.PNG new file mode 100644 index 0000000000..ff4c897018 Binary files /dev/null and b/docs/doxygen-user_fr/images/ui_layout_group_tree.PNG differ diff --git a/docs/doxygen-user_fr/images/ui_person_select.png b/docs/doxygen-user_fr/images/ui_person_select.png new file mode 100644 index 0000000000..e82a5d0c30 Binary files /dev/null and b/docs/doxygen-user_fr/images/ui_person_select.png differ diff --git a/docs/doxygen-user_fr/images/ui_tree_top_ds.png b/docs/doxygen-user_fr/images/ui_tree_top_ds.png new file mode 100644 index 0000000000..7870ae8d0c Binary files /dev/null and b/docs/doxygen-user_fr/images/ui_tree_top_ds.png differ diff --git a/docs/doxygen-user_fr/images/ui_tree_top_persons.png b/docs/doxygen-user_fr/images/ui_tree_top_persons.png new file mode 100644 index 0000000000..56b3c43f56 Binary files /dev/null and b/docs/doxygen-user_fr/images/ui_tree_top_persons.png differ diff --git a/docs/doxygen-user_fr/images/unallocated_space_options.PNG b/docs/doxygen-user_fr/images/unallocated_space_options.PNG new file mode 100644 index 0000000000..a72fcc6dd8 Binary files /dev/null and b/docs/doxygen-user_fr/images/unallocated_space_options.PNG differ diff --git a/docs/doxygen-user_fr/images/updatedSolr_cmd.PNG b/docs/doxygen-user_fr/images/updatedSolr_cmd.PNG new file mode 100644 index 0000000000..14b7abef3d Binary files /dev/null and b/docs/doxygen-user_fr/images/updatedSolr_cmd.PNG differ diff --git a/docs/doxygen-user_fr/images/urlInAddressbar.PNG b/docs/doxygen-user_fr/images/urlInAddressbar.PNG new file mode 100644 index 0000000000..2577a55450 Binary files /dev/null and b/docs/doxygen-user_fr/images/urlInAddressbar.PNG differ diff --git a/docs/doxygen-user_fr/images/users.properties.after.PNG b/docs/doxygen-user_fr/images/users.properties.after.PNG new file mode 100644 index 0000000000..6fee464715 Binary files /dev/null and b/docs/doxygen-user_fr/images/users.properties.after.PNG differ diff --git a/docs/doxygen-user_fr/images/users.properties.before.PNG b/docs/doxygen-user_fr/images/users.properties.before.PNG new file mode 100644 index 0000000000..8dff55d79b Binary files /dev/null and b/docs/doxygen-user_fr/images/users.properties.before.PNG differ diff --git a/docs/doxygen-user_fr/images/view_options_gear.png b/docs/doxygen-user_fr/images/view_options_gear.png new file mode 100644 index 0000000000..b522308035 Binary files /dev/null and b/docs/doxygen-user_fr/images/view_options_gear.png differ diff --git a/docs/doxygen-user_fr/images/view_options_gmt.png b/docs/doxygen-user_fr/images/view_options_gmt.png new file mode 100644 index 0000000000..03672fa46d Binary files /dev/null and b/docs/doxygen-user_fr/images/view_options_gmt.png differ diff --git a/docs/doxygen-user_fr/images/view_options_hide_slack.png b/docs/doxygen-user_fr/images/view_options_hide_slack.png new file mode 100644 index 0000000000..5a3d83c2e6 Binary files /dev/null and b/docs/doxygen-user_fr/images/view_options_hide_slack.png differ diff --git a/docs/doxygen-user_fr/images/view_options_local_time.png b/docs/doxygen-user_fr/images/view_options_local_time.png new file mode 100644 index 0000000000..475c418768 Binary files /dev/null and b/docs/doxygen-user_fr/images/view_options_local_time.png differ diff --git a/docs/doxygen-user_fr/images/view_options_options_panel.png b/docs/doxygen-user_fr/images/view_options_options_panel.png new file mode 100644 index 0000000000..168ce70cc4 Binary files /dev/null and b/docs/doxygen-user_fr/images/view_options_options_panel.png differ diff --git a/docs/doxygen-user_fr/images/view_options_reject_account.png b/docs/doxygen-user_fr/images/view_options_reject_account.png new file mode 100644 index 0000000000..e722bcb61f Binary files /dev/null and b/docs/doxygen-user_fr/images/view_options_reject_account.png differ diff --git a/docs/doxygen-user_fr/images/view_options_sco.png b/docs/doxygen-user_fr/images/view_options_sco.png new file mode 100644 index 0000000000..ec165e1b45 Binary files /dev/null and b/docs/doxygen-user_fr/images/view_options_sco.png differ diff --git a/docs/doxygen-user_fr/images/view_options_show_slack.png b/docs/doxygen-user_fr/images/view_options_show_slack.png new file mode 100644 index 0000000000..6b0e4f2e48 Binary files /dev/null and b/docs/doxygen-user_fr/images/view_options_show_slack.png differ diff --git a/docs/doxygen-user_fr/images/views_grouped_tree.png b/docs/doxygen-user_fr/images/views_grouped_tree.png new file mode 100644 index 0000000000..d76b991a52 Binary files /dev/null and b/docs/doxygen-user_fr/images/views_grouped_tree.png differ diff --git a/docs/doxygen-user_fr/images/views_standard_tree.png b/docs/doxygen-user_fr/images/views_standard_tree.png new file mode 100644 index 0000000000..80eddc68a9 Binary files /dev/null and b/docs/doxygen-user_fr/images/views_standard_tree.png differ diff --git a/docs/doxygen-user_fr/images/virtual_machine_extractor_results.png b/docs/doxygen-user_fr/images/virtual_machine_extractor_results.png new file mode 100644 index 0000000000..d302c2e553 Binary files /dev/null and b/docs/doxygen-user_fr/images/virtual_machine_extractor_results.png differ diff --git a/docs/doxygen-user_fr/images/volatility_dsp_config.PNG b/docs/doxygen-user_fr/images/volatility_dsp_config.PNG new file mode 100644 index 0000000000..84bb9a414f Binary files /dev/null and b/docs/doxygen-user_fr/images/volatility_dsp_config.PNG differ diff --git a/docs/doxygen-user_fr/images/volatility_dsp_interesting_items.PNG b/docs/doxygen-user_fr/images/volatility_dsp_interesting_items.PNG new file mode 100644 index 0000000000..83fbc276eb Binary files /dev/null and b/docs/doxygen-user_fr/images/volatility_dsp_interesting_items.PNG differ diff --git a/docs/doxygen-user_fr/images/volatility_dsp_module_output.PNG b/docs/doxygen-user_fr/images/volatility_dsp_module_output.PNG new file mode 100644 index 0000000000..256dc09fc3 Binary files /dev/null and b/docs/doxygen-user_fr/images/volatility_dsp_module_output.PNG differ diff --git a/docs/doxygen-user_fr/images/volatility_dsp_select.png b/docs/doxygen-user_fr/images/volatility_dsp_select.png new file mode 100644 index 0000000000..aa1b6b477a Binary files /dev/null and b/docs/doxygen-user_fr/images/volatility_dsp_select.png differ diff --git a/docs/doxygen-user_fr/images/wherejava.PNG b/docs/doxygen-user_fr/images/wherejava.PNG new file mode 100644 index 0000000000..ee93d1717e Binary files /dev/null and b/docs/doxygen-user_fr/images/wherejava.PNG differ diff --git a/docs/doxygen-user_fr/images/xry_dsp.png b/docs/doxygen-user_fr/images/xry_dsp.png new file mode 100644 index 0000000000..46e2659c19 Binary files /dev/null and b/docs/doxygen-user_fr/images/xry_dsp.png differ diff --git a/docs/doxygen-user_fr/images/xry_folder.png b/docs/doxygen-user_fr/images/xry_folder.png new file mode 100644 index 0000000000..1f2e734a98 Binary files /dev/null and b/docs/doxygen-user_fr/images/xry_folder.png differ diff --git a/docs/doxygen-user_fr/images/yara_ingest_settings.png b/docs/doxygen-user_fr/images/yara_ingest_settings.png new file mode 100644 index 0000000000..0917a73bd0 Binary files /dev/null and b/docs/doxygen-user_fr/images/yara_ingest_settings.png differ diff --git a/docs/doxygen-user_fr/images/yara_new_rule_set.png b/docs/doxygen-user_fr/images/yara_new_rule_set.png new file mode 100644 index 0000000000..1470f8f45c Binary files /dev/null and b/docs/doxygen-user_fr/images/yara_new_rule_set.png differ diff --git a/docs/doxygen-user_fr/images/yara_options.png b/docs/doxygen-user_fr/images/yara_options.png new file mode 100644 index 0000000000..e04a1e62f4 Binary files /dev/null and b/docs/doxygen-user_fr/images/yara_options.png differ diff --git a/docs/doxygen-user_fr/images/yara_results.png b/docs/doxygen-user_fr/images/yara_results.png new file mode 100644 index 0000000000..5e1d447935 Binary files /dev/null and b/docs/doxygen-user_fr/images/yara_results.png differ diff --git a/docs/doxygen-user_fr/images/zipped_children_1.PNG b/docs/doxygen-user_fr/images/zipped_children_1.PNG new file mode 100644 index 0000000000..d391c91105 Binary files /dev/null and b/docs/doxygen-user_fr/images/zipped_children_1.PNG differ diff --git a/docs/doxygen-user_fr/images/zipped_children_2.PNG b/docs/doxygen-user_fr/images/zipped_children_2.PNG new file mode 100644 index 0000000000..f1e7318258 Binary files /dev/null and b/docs/doxygen-user_fr/images/zipped_children_2.PNG differ diff --git a/docs/doxygen-user_fr/images/zipped_context_menu.png b/docs/doxygen-user_fr/images/zipped_context_menu.png new file mode 100644 index 0000000000..848ac8ea2e Binary files /dev/null and b/docs/doxygen-user_fr/images/zipped_context_menu.png differ diff --git a/docs/doxygen-user_fr/images/zipped_encryption_detected.png b/docs/doxygen-user_fr/images/zipped_encryption_detected.png new file mode 100644 index 0000000000..cfd4b88953 Binary files /dev/null and b/docs/doxygen-user_fr/images/zipped_encryption_detected.png differ diff --git a/docs/doxygen-user_fr/images/zipped_tree.png b/docs/doxygen-user_fr/images/zipped_tree.png new file mode 100644 index 0000000000..6afc67ecfb Binary files /dev/null and b/docs/doxygen-user_fr/images/zipped_tree.png differ diff --git a/docs/doxygen-user_fr/images/zooDir.PNG b/docs/doxygen-user_fr/images/zooDir.PNG new file mode 100644 index 0000000000..8240f3a7d3 Binary files /dev/null and b/docs/doxygen-user_fr/images/zooDir.PNG differ diff --git a/docs/doxygen-user_fr/images/zooPurge.PNG b/docs/doxygen-user_fr/images/zooPurge.PNG new file mode 100644 index 0000000000..d8e8a8b364 Binary files /dev/null and b/docs/doxygen-user_fr/images/zooPurge.PNG differ diff --git a/docs/doxygen-user_fr/ingest.dox b/docs/doxygen-user_fr/ingest.dox new file mode 100644 index 0000000000..6dbe19f2ba --- /dev/null +++ b/docs/doxygen-user_fr/ingest.dox @@ -0,0 +1,104 @@ +/*! \page ingest_page Ingest Modules (Modules d'acquisition) + +[TOC] + + +Les "Ingest Modules" analysent les données d'une source de données. Ils effectuent toutes les analyses des fichiers ainsi que de leur contenu. Exemples de modules d'acquisition: \ref hash_db_page, \ref keyword_search_page ou \ref recent_activity_page. + +Immédiatement après avoir ajouté une source de données à un cas - voir \ref ds_page -, une boîte de dialogue vous sera présentée pour configurer les modules d'acquisition à exécuter dessus. Une fois configurés, ils fonctionneront en arrière-plan et vous fourniront des résultats en temps réel lorsqu'ils trouveront des informations pertinentes. + +Cette page couvre l'utilisation des modules d'acquisition. Des pages spécifiques couvriront la configuration de modules particuliers. Voir \ref module_install_page pour plus de détails sur l'installation de modules d'acquisition tiers. + +\section ingest_performance Multi-thread et priorités + +Les modules d'acquisition sont configurés pour trouver rapidement le contenu de l'utilisateur. Les modules d'acquisition sont regroupés en pipelines et chaque fichier descend dans le pipeline, traversant module après module. Un pipeline peut faire passer les fichiers à travers les modules dans l'ordre suivant: + +\image html ingest_pipeline.PNG + +Plusieurs pipelines peuvent fonctionner en même temps. Par défaut, deux pipelines sont exécutés en même temps, mais vous pouvez en ajouter d'autres en fonction du nombre de cœurs que vous avez sur votre système. Vous pouvez configurer le nombre de pipelines dans la zone "Tools", "Options", "General". + +Autopsy donne la priorité au contenu de l'utilisateur par rapport aux autres types de fichiers et enverra les données du dossier "Documents and Settings" ou "Users" dans les pipelines avant le dossier "Windows". Il priorise chaque dossier du système pour garantir que le contenu de l'utilisateur soit analysé avant tout autre contenu. + + +\section ingest_running Exécution des modules d'acquisition + +Il existe deux façons de démarrer les modules d'acquisition: +-# Immédiatement après avoir ajouté une source de données +-# En faisant un clic droit sur une source de données dans l'arborescence de l'interface principale et en choisissant "Run Ingest Modules" + +Une fois l'acquisition démarrée, vous pouvez consulter les tâches d'acquisition en cours d'exécution dans la barre des tâches située dans le coin inférieur droit de la fenêtre principale. Les tâches d'acquisition peuvent être annulées par l'utilisateur s'il le souhaite. + +Remarque: parfois, le processus d'annulation peut prendre plusieurs secondes ou plus pour se terminer proprement, en fonction de ce que faisait actuellement le module d'acquisition. + +\section ingest_configure Configuration des modules d'acquisition + +Une interface vous sera présentée pour configurer les modules d'acquisition. De là, vous pouvez choisir le type de fichiers à analyser et activer ou désactiver chaque module. Certains modules auront des paramètres de configuration supplémentaires. + +\image html select-ingest-modules.PNG + +La zone de sélection en haut contrôle les fichiers sur lesquels les modules d'acquisition seront exécutés. Les deux options intégrées sont "All files, directories, and unallocated space" ("Tous les fichiers, répertoires et espace non alloué"") et "All Files and Directories" ("Tous les fichiers et répertoires"). La section \ref file_filters décrit comment créer des filtres de fichiers personnalisés. Le filtre choisi s'applique à tous les modules d'acquisition. + +Il existe deux emplacements pour configurer les modules d'acquisition. Lorsque vous sélectionnez le nom du module, vous pouvez avoir des options "d'exécution" à configurer dans le panneau de droite. Il s'agit généralement de paramètres que vous souhaiterez peut-être modifier en fonction de votre cas. + +Il peut également y avoir un bouton "Global Settings" qui est activé dans le coin inférieur. Appuyez sur ce bouton pour modifier les paramètres globaux qui ne sont pas spécifiques à un seul cas. Ce panneau de configuration avancée se trouve souvent aussi dans le menu "Tools", "Options". + +À titre d'exemple, le module de "Hash Lookup" (recherche de hachage) vous permettra d'activer ou de désactiver les jeux de hachage dans le panneau des options "d'exécution", mais vous oblige à accéder à la boîte de dialogue "Global Settings" pour ajouter ou supprimer des ensembles de hachage de la configuration d'Autopsy. + +\section file_filters File Filters (Filtres de fichiers personnalisés) + +Le panneau "File Filters" peut être ouvert à partir du panneau de sélection du module d'acquisition ou via l'onglet "Ingest" du panneau d'options principal. Les filtres de fichiers permettent aux modules d'acquisition d'être exécutés uniquement sur un sous-ensemble des fichiers. Dans l'exemple ci-dessous, un filtre a été mis en place pour ne s'exécuter que sur les fichiers avec une extension "png". + +\image html ingest-file-filters.PNG + +Chaque filtre contient une ou plusieurs règles de sélection de fichiers en fonction d'une combinaison du nom du fichier, du chemin, de la taille et de la date de modification du fichier. Une seule règle doit correspondre pour que le fichier passe. En outre, vous pouvez saisir plusieurs extensions de fichiers séparées par des virgules. Tous les fichiers seront toujours affichés dans l'arborescence, mais les modules d'acquisition ne fonctionneront que sur un sous-ensemble. Si nous utilisons l'exemple précédent et exécutons le module de hachage, seuls les fichiers se terminant par .png verront leur hachage calculé. + +\section ingest_profiles Profiles (Profils d'acquisition) + +Les profils d'acquisition vous permettent de choisir rapidement un ensemble défini de modules d'acquisition à exécuter. Cela peut être utile si vous exécutez différents ensembles de modules d'acquisition (ou différentes configurations de ces modules d'acquisition) sur différents types de données. Les profils d'acquisition peuvent être configurés via l'onglet "Ingest" du panneau d'options. + +\image html ingest-profiles.PNG + +Chaque profil peut spécifier différents paramètres d'exécution pour chaque module d'acquisition, et vous pouvez choisir d'utiliser un filtre de fichiers prédéfini ou personnalisé - voir \ref file_filters. + +\image html ingest-profile-create.PNG + +Si des profils personnalisés ont été créés, un nouvel écran s'affichera dans l'assistant d'ajout de source de données. + +\image html profile-data-source-panel.PNG + +Si vous choisissez des paramètres personnalisés ("Custom Settings"), le panneau normal de sélection des modules d'acquisition apparaîtra. Si vous choisissez un profil défini par l'utilisateur, l'écran du module d'acquisition sera entièrement ignoré et les modules d'acquisition de ce profil seront exécutés sur la source de données. Le panneau de sélection de profil apparaîtra également lors de l'exécution de l'acquisition en effectuant un clic droit sur une source de données dans l'arborescence. + +

    +\section ingest_already_run Notification de module déjà exécuté +Si un module d'acquisition a déjà été exécuté sur une source de données particulière, vous verrez une icône triangulaire jaune avec un point d'exclamation à côté du module dans la boîte de dialogue "Run Ingest Modules", comme illustré dans la capture d'écran ci-dessous. +

    +\image html ingest-already-run.PNG +

    +Si une ancienne version d'un module d'acquisition a été exécutée sur une source de données particulière, vous verrez une icône ronde bleue avec un "i" à côté du module dans la boîte de dialogue "Run Ingest Modules", comme illustré dans la capture d'écran ci-dessous. +

    +\image html previous-version-already-run.PNG +

    + +Cliquez sur "History" pour afficher l'historique des modules d'acquisition sous forme de tableau, vous permettant de voir quels modules ont été exécutés sur quelles sources de données et à quel moment, comme indiqué dans la capture d'écran ci-dessous. +

    +\image html ingest-history.PNG +

    + +\section ingest_results Affichage des résultats du module d'acquisition + +Les modules d'acquisition s'exécutent en arrière-plan. Un module d'acquisition peut vous fournir des résultats de différentes manières, mais nous vous présentons quelques méthodes spécifiques: + +-# S'ils publient des résultats dans le Blackboard, vous trouverez ces derniers dans la zone "Results" de l'arborescence de l'interface principale. +-# Ils peuvent envoyer un message dans la boîte de notification des Ingest Modules afin que vous receviez un message chaque fois que quelque chose de vraiment important est trouvé. +\image html inbox-button.PNG +\image html inbox-main-screen.PNG +-# Si le module est un container incluant un autre outil d'investigation, il peut simplement fournir un lien vers la sortie de cet outil, auquel cas vous verrez une nouvelle entrée dans la zone "Reports" de l'arborescence. + +Tous les modules officiels d'Autopsy envoient les résultats au Blackboard, mais si vous installez des applications tierces, elles peuvent choisir n'importe quelle autre approche -- y compris une fenêtre contextuelle chaque fois qu'elles trouvent quelque chose. + +\section ingest_monitoring Affichage de l'activité en cours des modules d'acquisition +Pendant que les modules d'acquisition sont en cours d'exécution, on peut utiliser l'outil "Ingest Progress Snapshot" pour voir quelle activité est en cours en ce moment. Cliquez sur "Help", "Get Ingest Progress Snapshot" pour afficher la boîte de dialogue illustrée dans la capture d'écran ci-dessous. +\image html ingest_progress_snapshot.PNG +Pour actualiser la vue, utilisez le bouton "Refresh". + +*/ diff --git a/docs/doxygen-user_fr/ingest_template.xod b/docs/doxygen-user_fr/ingest_template.xod new file mode 100644 index 0000000000..92e0366a46 --- /dev/null +++ b/docs/doxygen-user_fr/ingest_template.xod @@ -0,0 +1,28 @@ +/*! \page XYZ_page XYZ Module + +Qu'est ce que ça fait +======== + +Qu'est ce que ça fait? + +Pourquoi l'utiliseriez-vous? + + +Configuration +======= + +Y a-t-il quelque chose que vous devez configurer? + + +Utilisation du module +====== + +Paramètres d'intégration +------ +Existe-t-il des paramètres d'intégration à l'exécution? + +Voir les résultats +------ +Où voyez-vous les résultats? Dans l'arborescence? + +*/ diff --git a/docs/doxygen-user_fr/installation.dox b/docs/doxygen-user_fr/installation.dox new file mode 100644 index 0000000000..bb202cc06a --- /dev/null +++ b/docs/doxygen-user_fr/installation.dox @@ -0,0 +1,60 @@ +/*! \page installation_page Installation d'Autopsy + +[TOC] + + +\section install Types de déploiement + +Il existe deux façons de déployer Autopsy: +- **Mono-utilisateur**: les cas ne peuvent être ouverts que par une seule instance d'Autopsy à la fois. Les installations d'Autopsy ne communiquent pas entre elles. C'est le plus simple à installer et à déployer. Cette page décrit ce processus d'installation. +- **Multi-utilisateurs**: les cas peuvent être ouverts par plusieurs utilisateurs en même temps et les utilisateurs peuvent voir ce que font les autres. Ce déploiement collaboratif nécessite l'installation et la configuration d'autres services réseau. L'installation de ce déploiement est traitée dans la section \ref install_multiuser_page. + + +\section download Télécharger +Quel que soit le type de déploiement, vous pouvez télécharger Autopsy à partir du site Web: + +https://www.autopsy.com/download/ + +Nous distribuons un programme d'installation Windows et des fichiers ZIP à exécuter sous Linux et MacOS X. + + + +\section install_reqs Configuration requise + +\subsection prereqs_av AntiVirus + +Vous devez soit désactiver le logiciel antivirus installé sur vos ordinateurs qui exécuteront Autopsy ou configurer votre logiciel antivirus pour qu’il ignore le contenu de votre répertoire d’export de cas. Un logiciel antivirus peut mettre en quarantaine ou même supprimer certains de vos résultats avant que vous n'ayez la possibilité de les consulter. Autopsy encode certains des fichiers qu'il extrait afin qu'ils ne puissent pas être exécutés ou analysés, mais certains modules (comme notre module d'extraction ZIP) écriront directement les fichiers sur le disque dans un format non codé. + +Bien entendu, la désactivation du logiciel antivirus présente le risque que votre ordinateur soit infecté par des logiciels malveillants provenant de vos médias. + + + +\subsection sysreqs Mémoire + +Nous recommandons un minimum de 16 Go de RAM. + +Par défaut, Autopsy utilisera un maximum de 4 Go de RAM (sans compter la mémoire utilisée par le serveur d'indexation de texte Solr). Vous pouvez augmenter cette taille après l'installation en modifiant la valeur de la mémoire JVM maximale dans la section Runtime du menu Tools -> Options -> Application. + +\image html runtime_settings.PNG + + + +\section install_standalone Installation mono-utilisateur +Pour installer Autopsy, procédez comme suit: +1. Exécutez le fichier msi Autopsy +2. Si une fenêtre Windows de contrôle de compte d'utilisateur apparait, cliquez sur Oui +3. Cliquez sur les boîtes de dialogue jusqu'à ce que vous puissiez cliquer sur un bouton indiquant Terminer +4. Autopsy devrait maintenant être entièrement installé + + +\section install_proxy Proxies + +Si vous êtes derrière un proxy et avez besoin d'accéder à un réseau avec Autopsy ou l'un des ses modules, vous pouvez définir vos informations de proxy dans l'onglet Tools, Options, General comme indiqué dans la capture d'écran ci-dessous. + +\image html proxySettings.PNG + +\section install_file_association Association de fichiers Windows + +Si vous le souhaitez, vous pouvez configurer une association de fichiers Windows entre les fichiers .aut et l'exécutable d’Autopsy (normalement situé sous C:\\Program Files\\Autopsy-(version actuelle)\\bin\\autopsy64.exe). Cela vous permettra de double-cliquer sur le fichier .aut d'un cas pour lancer Autopsy avec l’ouverture de ce cas. Vous trouverez des instructions pour configurer les associations de fichiers en effectuant une recherche sur le Web pour savoir "comment définir les associations de fichiers Windows". + +*/ diff --git a/docs/doxygen-user_fr/interesting_files.dox b/docs/doxygen-user_fr/interesting_files.dox new file mode 100644 index 0000000000..7ee3d0aa44 --- /dev/null +++ b/docs/doxygen-user_fr/interesting_files.dox @@ -0,0 +1,118 @@ +/*! \page interesting_files_identifier_page Interesting Files Identifier (Identifiant de fichiers intéressant) + +[TOC] + + +\section interesting_files_overview Aperçu + +Le module "Interesting Files Identifier" vous permet de marquer automatiquement les fichiers et répertoires qui correspondent à un ensemble de règles. Cela peut être utile si vous devez toujours vérifier si des fichiers avec un nom ou un chemin donné se trouvent dans une source de données, ou si vous êtes toujours intéressé par des fichiers ayant un certain type. + +Ce module vous permet de créer des ensembles de règles qui seront exécutées sur chaque fichiers au fur et à mesure de leur traitement. Si un fichier correspond à l'une des règles, vous verrez une entrée concernant celui-ci dans l'\ref tree_viewer_page. Vous pouvez partager vos règles avec d'autres utilisateurs et importer des ensembles créés par d'autres dans votre copie d'Autopsy. + +\section interesting_files_terminology Terminologie + +
      +
    • Le terme "Rule" correspond à un ensemble de conditions qui doivent être vraies pour un fichier afin qu'il corresponde à la règle. Toutes les conditions de la règle doivent être vraies. Par exemple, si une règle comporte des conditions "File Size > 1 MB" ("Taille du fichier > 1 Mo") et "File Extension = .txt" ("Extension du fichier = .txt"), seuls les fichiers qui correspondent aux deux conditions seront considérés comme une correspondance. +
    • Le terme "Rule Set" correspond à un ensemble de règles. Si un fichier correspond à une règle de l'ensemble de règles, il sera marqué comme étant une correspondance pour cet ensemble de règles. Les ensembles de règles peuvent être activés et désactivés au moment de l'acquisition. +
    + +\section interesting_files_config Configuration + +Pour créer et modifier vos ensembles de règles, allez dans "Tools", "Options" puis sélectionnez l'onglet "Interesting Files". La zone sur le côté gauche vous montrera une liste de tous les ensembles de règles actuellement disponibles. Cela inclura les ensembles de règles officiels inclus avec Autopsy ainsi que tous les ensembles de règles que vous créez. La sélection d'un ensemble de règles affichera sa description et des informations sur chacune de ses règles sur le côté droit du panneau. + +\image html InterestingFiles/main.png + +Les boutons situés en bas à gauche du panneau contrôlent les ensembles de règles. + +
      +
    • New Set - Vous permet de créer un nouvel ensemble de règles (les règles seront ajoutées ultérieurement). Vous verrez une nouvelle fenêtre demandant le nom du nouvel ensemble de règles, une description facultative et si les fichiers connus doivent être ignorés (c'est-à-dire, si un fichier est dans le NSRL, il n'apparaîtra pas dans la liste des correspondances même s'il satisfait aux conditions de l'une des règles de l'ensemble). +\image html InterestingFiles/new_rule_set.png +
    • Edit Set - Ouvre la même fenêtre que "New Set" et vous permet de modifier l'un des champs. +
    • Delete Set - Supprime l'ensemble de règles sélectionné +
    • Copy Set - Crée une copie de l'ensemble de règles sélectionné. Cela fera apparaître la même fenêtre que "New Set". Vous devez modifier le nom de l'ensemble de règles pour enregistrer la copie. +
    • Import Set - Importe un ensemble de règles précédemment exporté. Une fois importé, vous n'aurez pas besoin de la copie originale. +
    • Export Set - Exporte l'ensemble de règles sélectionné dans un format qui peut être partagé avec d'autres utilisateurs d'Autopsy. +
    + +Notez que les ensembles de règles prédéfinis ne peuvent pas être supprimés ou modifiés. Si vous pensez à des ajouts qui seraient utiles pour la communauté, consultez la page \ref update_interesting_files_page pour obtenir les instructions pour soumettre des mises à jour. + +La sélection d'un ensemble de règles affichera sa description, s'il ignore les fichiers connus et les règles contenues dans l'ensemble. La sélection d'une règle affichera les conditions de cette règle dans la section "Rule Details". + +Les boutons sous la liste des règles vous permettent de créer de nouvelles règles et de modifier ou supprimer des règles existantes. Sélectionner "New Rule" fera apparaître une nouvelle fenêtre pour créer une règle. + +\image html InterestingFiles/new_rule.png + +La ligne du haut vous permet de choisir si vous voulez faire correspondre uniquement des fichiers ("Files"), uniquement des répertoires ("Directories") ou les deux ("All"). Si vous sélectionnez des répertoires ou les deux, certains types de conditions ne seront pas disponibles car ils ne s'appliquent qu'aux fichiers. + +Chaque règle doit avoir au moins une condition. Pour créer des conditions, cochez la case à gauche de la condition que vous souhaitez activer. Ce qui suit est une description de chaque condition, avec quelques exemples complets. + +
      +
    • Name - Entrez soit le nom complet du fichier ("Full Name") soit une ou plusieurs extensions ("Extension Only"), et sélectionnez s'il s'agit d'une correspondance exacte ou d'une sous-chaîne de caractères/expression régulière ("Substring/Regex"). Si la correspondance "Substring/Regex" est activée, elle ajoutera automatiquement des caractères génériques au début et à la fin du texte. Si vous ne faites correspondre que des répertoires, cela correspondra au nom du répertoire. Si vous utilisez une liste d'extensions séparées par des virgules, assurez-vous que la case à cocher "Substring/Regex" est désactivée - tout le contenu sera interprété comme une expression régulière lorsque la case est cochée. Le tableau suivant montre quelques exemples d'utilisation des différentes combinaisons. + + + + + + + + + +
      TypeSubstring/RegexTexteDescriptionExemple de correspondance
      Full Namefaux\verbatim test.txt \endverbatimCorrespondra aux fichiers nommés "test.txt"text.txt
      Full Namevrai\verbatim bomb \endverbatimAssociera les fichiers avec "bomb" à n'importe quel endroit de leur nomPipe_bomb.png
      Full Namevrai\verbatim virus.*\.exe \endverbatimCorrespondra aux fichiers avec "virus" suivi de ".exe" à n'importe quel endroit de leur nombad_virus.exe
      Extension Onlyfaux\verbatim zip \endverbatimCorrespondra aux fichiers .zipmyArchive.zip
      Extension Onlyfaux\verbatim zip,rar,7z \endverbatimCorrespondra aux fichiers .zip, .rar, et .7z filesanotherArchive.rar
      Extension Onlyvrai\verbatim jp \endverbatimCorrespondra aux fichiers .jpg, .jpeg, et tous les autres ayant "jp" dans l'extensionmyImage.jpg
      + +
    • Path Substring - Entrez un nom de dossier qui doit faire partie du chemin du fichier pour qu'il corresponde. Si vous souhaitez uniquement spécifier un mot apparaîssant quelque part dans le chemin, utilisez l'option regex. + + + + + +
      RegexTexteDescriptionExemple de correspondance
      faux\verbatim Documents \endverbatimCorrespond à n'importe quel fichier qui a un dossier nommé "Documents" dans son chemin/folder1/Documents/fileA.doc
      vrai\verbatim bomb \endverbatimCorrespond à n'importe quel fichier qui a "bomb" dans son chemin/folder1/bomb making/file2.doc
      vrai\verbatim Users/.*/Downloads \endverbatimCorrespond à n'importe quel fichier qui a "Users" et "Downloads" dans son cheminC:/Users/user1/Downloads/myFile.txt
      + +
    • MIME Type - Utilisez la liste déroulante pour sélectionner un type MIME. Un seul type MIME peut être sélectionné. + +
    • File Size - Indiquez si vous souhaitez faire correspondre des fichiers de taille égale, inférieure ou supérieure à une taille donnée. + +
    • Modified Within - Sélectionnez la date à laquelle un fichier doit avoir été modifié pour correspondre à la règle. +
    + +Enfin, vous pouvez éventuellement saisir un nom pour la règle. Cela sera affiché dans l'interface utilisateur pour chaque correspondance. + +\subsection interesting_files_examples Exemples +Voici quelques exemples de règles en cours de création. + +C'est une règle qui correspond à tout fichier avec "bomb" dans le nom qui a également un type MIME "image/png". + +\image html InterestingFiles/bomb_png.png + +Il s'agit d'une règle qui correspond aux dossiers nommés "Private". + +\image html InterestingFiles/private_folder.png + +Cette règle recherche les archives dans le répertoire de téléchargement de l'utilisateur. Elle nécessite "Users" et "Downloads" dans le chemin du fichier, ainsi qu'une extension .zip, .rar ou .7z. + +\image html InterestingFiles/download_archive.png + +Il s'agit d'une règle qui correspond aux fichiers d'une taille d'au moins 50 Mo qui ont été modifiés la semaine dernière. + +\image html InterestingFiles/new_large_files.png + +\section interesting_files_running Exécution du module + +Lors du paramétrage, vous pouvez sélectionner les ensembles de règles que vous souhaitez exécuter sur votre source de données. + +\image html InterestingFiles/ingest.png + +\section interesting_files_results Affichage des résultats + +Les fichiers qui correspondent à l'une des règles des ensembles de règles activés seront affichés dans la section Results de l'\ref tree_viewer_page sous "Interesting Items", puis sous le nom de l'ensemble de règles correspondant. Notez que d'autres modules en plus de "Interesting Files Identifier" placent leurs résultats dans cette section de l'arborescence, il peut donc y avoir plus d'éléments que ceux qui correspondent à vos ensembles de règles. Sélectionner le nœud "Interesting Files" sous l'un de vos ensembles de règles affichera tous les fichiers correspondants dans la \ref result_viewer_page. + +\image html InterestingFiles/results.png + +Vous pouvez voir quelle règle correspond dans la colonne "Category". Vous pouvez exporter tout ou partie des fichiers pour une analyse plus approfondie. Pour ce faire, utilisez d'abord la méthode standard de sélection de fichier sous Windows afin de mettre en évidence les fichiers que vous souhaitez exporter via la \ref result_viewer_page : +
      +
    • Maintenez la touche Ctrl enfoncée et cliquez sur chaque fichier que vous souhaitez exporter +
    • Maintenez la touche Maj enfoncée pour sélectionner une plage de fichiers +
    • Cliquez sur n'importe quel fichier dans la visionneuse de résultats, puis appuyez sur Ctrl+A pour sélectionner tous les fichiers +
    +Une fois que vous avez sélectionné les fichiers souhaités, faites un clic-droit et sélectionnez "Extract Files" pour en enregistrer une copie. + +*/ diff --git a/docs/doxygen-user_fr/keyword_search.dox b/docs/doxygen-user_fr/keyword_search.dox new file mode 100644 index 0000000000..5fd79997cd --- /dev/null +++ b/docs/doxygen-user_fr/keyword_search.dox @@ -0,0 +1,121 @@ +/*! \page keyword_search_page Keyword Search (Recherches par mots clés) + +[TOC] + + +\section keyword_module_overview Qu'est ce que ça fait + +Le module "Keyword Search" facilite à la fois la partie de recherche lors de l'\ref ingest_page "acquisition" et prend également en charge la recherche manuelle de texte une fois l'acquisition terminée (voir \ref ad_hoc_keyword_search_page). Il extrait le texte des fichiers en cours d'acquisition, des rapports sélectionnés générés et des résultats d'autres modules. Ce texte extrait est ensuite ajouté à un index Solr qui peut ensuite être consulté au cours de cette recherche. + +Autopsy fait de son mieux pour extraire le maximum de texte des fichiers indexés. Tout d'abord, l'indexation essaiera d'extraire le texte des formats de fichier pris en charge, tels que le format de fichier texte brut, les documents MS Office, les fichiers PDF, les e-mails et bien d'autres. Si le fichier n'est pas pris en charge par l'extracteur de texte standard, Autopsy reviendra à un algorithme d'extraction de chaîne de caractères. L'extraction de chaînes de caractères sur des formats de fichiers inconnus ou sur des fichiers binaires arbitraires peut souvent extraire une quantité importante de texte d'un fichier, assez souvent pour fournir des indices supplémentaires aux analystes. L'extraction de chaînes de caractère n'extraira pas les chaînes de texte des fichiers chiffrés. + +Autopsy est livrée avec des listes intégrées qui définissent des expressions régulières et permettent à l'utilisateur de rechercher des numéros de téléphone ("Phone Numbers"), des adresses IP ("IP addresses"), des URL ("URLs") et des adresses e-mail ("E-mail addresses"). Cependant, l'activation de certaines de ces listes très générales peut produire un très grand nombre de résultats, et beaucoup d'entre eux peuvent être des faux positifs. Les expressions régulières peuvent prendre du temps à se terminer. + +Une fois les fichiers placés dans l'index Solr, ils peuvent être recherchés rapidement pour des mots-clés spécifiques, des expressions régulières ou des listes de recherche de mots-clés pouvant contenir un mélange de mots-clés et d'expressions régulières. Les requêtes de recherche peuvent être exécutées automatiquement pendant l'exécution de l'acquisition ou à la fin de l'acquisition, en fonction des paramètres actuels et du temps nécessaire à l'acquisition de l'image. + +Référez vous à la page \ref ad_hoc_keyword_search_page pour plus de détails sur la spécification des expressions régulières et d'autres types de recherche. + +\section keyword_search_configuration_dialog Configuration de la recherche par mot-clé + +L'option de configuration de la recherche par mot-clé ("Keyword Search") comporte trois onglets, chacun ayant son propre objectif: +\li L'\ref keywordLists est utilisé pour ajouter, supprimer et modifier des listes de recherche par mot-clé. +\li L'\ref stringExtraction est utilisé pour activer les scripts de langage et le type d'extraction. +\li L'\ref generalSettings est utilisé pour configurer les horaires d'acquisition et afficher les informations. + +\subsection keywordLists Onglet "Lists" + +L'onglet "Lists" est utilisé pour créer/importer et ajouter du contenu aux listes de mots clés. Pour créer une liste, sélectionnez le bouton "New List" et choisissez un nom pour la nouvelle liste de mots clés. Une fois la liste créée, des mots clés peuvent y être ajoutés (voir la section \ref ad_hoc_kw_types_section pour plus d'informations sur les types de mots-clés). Des listes peuvent être ajoutées au processus d'acquisition de la recherche par mot-clé; les recherches auront lieu à intervalles réguliers au fur et à mesure que le contenu est ajouté à l'index. + +\image html keyword-search-configuration-dialog.PNG + +Les listes de mots-clés se trouvent sur le côté gauche du panneau. De nouvelles listes peuvent être créées, les listes existantes peuvent être renommées, copiées, exportées ou supprimées et les listes peuvent être importées. Autopsy prend en charge l'importation de listes Encase délimitées par des tabulations ainsi que des listes créées précédemment avec Autopsy. Pour les listes Encase, la structure et la hiérarchie des dossiers sont ignorées. Il n'existe actuellement aucun moyen d'exporter des listes à utiliser avec Encase, mais les listes peuvent être exportées pour être partagées entre les utilisateurs d'Autopsy. + +Une fois qu'une liste de mots-clés est sélectionnée, tous les mots-clés de cette liste seront affichés sur le côté droit de l'onglet. Le bouton "New Keywords" peut être utilisé pour ajouter une ou plusieurs entrées à la liste, et les boutons "Edit keyword" et "Delete keywords" peuvent modifier les entrées existantes. + +\image html keyword-search-configuration-new-keywords.PNG + +Les nouvelles entrées peuvent être saisies dans la boîte de dialogue ou collées à partir du presse-papiers. Toutes les entrées ajoutées en même temps doivent être du même type de correspondance ("Exact Match": correspondance exacte, "Substring Match" : correspondance avec une sous-chaîne de caractères, ou "Regular Expression" : expression régulière), mais la boîte de dialogue peut être utilisée plusieurs fois pour ajouter des mots-clés à la liste. Reportez-vous à la section \ref ad_hoc_kw_types_section pour une explication sur chaque type de mot-clé. + +Sous la liste "Keywords", vous pouvez solliciter la réception d'un messages dans la boite de notification des Ingest Modules pour chaque découverte de correspondance. Si cette option est activée, la découverte de chaque mot-clé trouvé pour cette liste sera notifiée via le triangle jaune à côté du bouton "Keyword Lists". Cette fonctionnalité vous offre un moyen rapide d'afficher les résultats de recherche de mots clés les plus importants. + +\image html keyword-search-inbox.PNG + +\subsection stringExtraction Onglet "String Extraction" +Le paramètre "String Extraction" définit comment les chaînes de caractères sont extraites des fichiers dont le texte ne peut pas être extrait normalement car les formats de ces fichier ne sont pas pris en charge. C'est le cas des fichiers binaires arbitraires (tels que les fichiers d'échanges) et des morceaux d'espace non alloué qui représentent des fichiers supprimés. +Lorsque nous extrayons des chaînes de caractères de fichiers binaires, nous devons interpréter les séquences d'octets comme du texte différemment en fonction du codage de texte possible et du script/langage utilisé. Dans de nombreux cas, nous ne savons pas à l'avance dans quel encodage/langue spécifique le texte est encodé. Cependant, cela peut être intéressant si l'enquêteur recherche une langue spécifique, car en sélectionnant moins de langues, les performances d'indexation seront améliorées et le nombre des faux positifs seront réduits. + +\image html keyword-search-configuration-dialog-string-extraction.PNG + +Le paramètre par défaut consiste à rechercher uniquement les chaînes anglaises, codées en UTF8 ou UTF16. Ce paramètre offre les meilleures performances (temps d'acquisition le plus court). +L'utilisateur peut également utiliser en premier le "String Viewer" et essayer différents paramètres de script/langue, et voir quels paramètres donnent des résultats satisfaisants pour le type de texte pertinent pour l'enquête. Ensuite, ce même paramètre qui fonctionne pour l'enquête peut être appliqué au module d'acquisition de recherche par mot-clé. + + +\subsection generalSettings Onglet "General" + +\image html keyword-search-configuration-dialog-general.PNG + +### Prise en charge du NIST NSRL +Le module d'acquisition "Hash Lookup" peut être configuré pour utiliser l'ensemble de hachage NIST NSRL de fichiers connus. L'onglet "General" de la boîte de dialogue de configuration avancée de la recherche par mot-clé contient une option permettant d'ignorer l'indexation par mot-clé et de rechercher des fichiers précédemment marqués comme "connus" ("Known") et sans intérêt. La sélection de cette option peut réduire considérablement la taille de l'index et améliorer les performances d'acquisition. Dans la plupart des cas, l'utilisateur n'a pas besoin de rechercher par mot-clé les fichiers "connus". + +### Fréquence de mise à jour des résultats lors de l'acquisition +Pour contrôler la fréquence à laquelle les recherches sont exécutées pendant l'acquisition, l'utilisateur peut ajuster le paramètre de synchronisation disponible dans l'onglet "General" de la boîte de dialogue de configuration avancée de la recherche par mot-clé. La réduction du nombre de minutes entraînera des mises à jour d'index et des recherches plus fréquentes et l'utilisateur pourra voir les résultats davantage en temps réel. Cependant, des mises à jour plus fréquentes peuvent affecter les performances globales, en particulier sur les systèmes peu performants, et peuvent potentiellement allonger le temps total nécessaire à l'acquisition. + +On peut également choisir de ne pas effectuer de recherches périodiques. Cela accélérera l'acquisition. Les utilisateurs qui choisissent cette option peuvent exécuter leurs recherches par mots-clés une fois que l'index de recherche par mots-clés est complet. + +### Reconnaissance optique de caractères (OCR) +Il existe également un paramètre pour activer le Optical Character Recognition (OCR). Si cette option est activée, le texte peut être extrait des types d'images pris en charge. L'activation de cette fonctionnalité rendra le module de recherche par mot-clé plus long à exécuter et les résultats ne sont pas parfaits. La deuxième case à cocher peut accélérer l'exécution de l'OCR en ne traitant que les grandes images et les images extraites de documents. + +Voici un exemple d'image contenant du texte: + +\image html keyword-search-ocr-image.png + +L'onglet "Indexed Text" affiche les résultats lors de l'exécution du module de recherche par mot-clé avec l'option OCR activée. Si nous devions utiliser la recherche par mot-clé pour rechercher le mot "forensics", ce fichier serait une correspondance. + +\image html keyword-search-ocr-indexed-text.png + +\anchor keyword_search_ocr_config +Par défaut, l'OCR n'est configuré que pour le texte anglais. Sa configuration dépend de la présence de fichiers de langue (appelés fichiers "traineddata") +qui existent dans un endroit qu'Autopsy peut atteindre. Pour ajouter la prise en charge de plusieurs langues, vous devrez télécharger des "traineddata" supplémentaires +et les déplacer au bon endroit. Les étapes suivantes décrivent ce processus: + +
      +
    1. Aller sur https://tesseract-ocr.github.io/tessdoc/Data-Files. +
    2. Dans la section intitulée "Data Files for Version 4.00 (November 29, 2016)", vous trouverez un tableau contenant des fichiers représentant chaque langue. Ces fichiers ont l'extension ".traineddata". +
    3. Pour télécharger la langue souhaitée, cliquez sur les liens dans la colonne à l'extrême droite du tableau. Vous pouvez en télécharger autant que vous le souhaitez. Notez que vous ne devez choisir que dans ce tableau. Les fichiers de langue dans les autres sections ne sont pas garantis de fonctionner dans Autopsy. +
    4. Une fois que vous avez téléchargé vos fichiers de langue, faites-les simplement glisser et déposez-les dans le dossier "AppData\Roaming\autopsy\ocr_language_packs" se trouvant dans votre dossier utilisateur. +
    5. Démarrez Autopsy et vous serez prêt. Si Autopsy était en cours d'exécution, cela nécessitera un redémarrage pour prendre effet. +
    + +Les fichiers de langue seront désormais pris en charge lorsque l'OCR est activé dans les paramètres de "Keyword Search". + + + +
    +Utilisation du module +====== +Les requêtes de recherche peuvent être exécutées manuellement par l'utilisateur à tout moment, à condition que certains fichiers soient déjà indexés et prêts à être recherchés. La recherche avant que l'indexation ne soit terminée ne prendra naturellement en compte que les index déjà compilés. + +Voir la page \ref ingest_page "Modules d'acquisition" pour plus d'informations sur l'acquisition en général. + +Une fois qu'il y a des fichiers dans l'index, la \ref ad_hoc_keyword_search_page sera disponible pour une recherche manuelle à tout moment. + + + +Paramètres d'acquisition +------ +Les paramètres d'acquisition du module "Keyword Search" permettent à l'utilisateur d'activer ou de désactiver les expressions de recherche intégrées spécifiques : Phone Numbers, IP Addresses, Email Addresses, and URLs. En utilisant le bouton "Global Settings" (voir ci-dessous), on peut ajouter des groupes de mots clés personnalisés. + +\image html keyword-search-ingest-settings.PNG + + +Voir les résultats +------ + +Le module "Keyword Search" enregistrera les résultats de la recherche, que celle-ci ait été effectuée par le processus d'acquisition ou manuellement par l'utilisateur. Les résultats enregistrés sont disponibles dans l'arborescence des répertoires dans le panneau de gauche. + +Les résultats des mots clés apparaîtront dans l'arborescence sous "Keyword Hits". Chaque terme de recherche par mot-clé affichera le nombre de correspondances et peut être développé pour afficher ces correspondances. À partir de là, en cliquant sur l'une des correspondances, une liste de fichiers apparaîtra sur le côté droit de l'écran. Sélectionnez un fichier et accédez à l'onglet "Indexed Text" pour voir exactement où les correspondances apparaissent dans le fichier. + +\image html keyword_results.PNG + + +*/ diff --git a/docs/doxygen-user_fr/live_triage.dox b/docs/doxygen-user_fr/live_triage.dox new file mode 100644 index 0000000000..789e2480e4 --- /dev/null +++ b/docs/doxygen-user_fr/live_triage.dox @@ -0,0 +1,49 @@ +/*! \page live_triage_page Création d'un lecteur de triage en direct + +[TOC] + + +\section live_triage_overview Aperçu + +La fonction "Live Triage" vous permet de charger Autopsy sur un lecteur amovible pour l'exécuter sur les systèmes cibles tout en apportant des modifications minimes à ces systèmes cibles. Cela ne fonctionnera actuellement que sur les systèmes Windows. + +\section live_triage_create_drive Créer un lecteur de triage en direct + +Pour créer un lecteur de triage en direct, allez dans Tools->Make Live Triage Drive pour afficher la boîte de dialogue principale. + +\image html live_triage_dialog.png + +Sélectionnez le lecteur que vous souhaitez utiliser - tout type de périphérique de stockage USB fonctionnera. Pour de meilleurs résultats, utilisez le lecteur le plus rapide disponible. Une fois le processus terminé, le dossier racine contiendra un dossier Autopsy et un fichier RunFromUSB.bat. + +\section live_triage_usage Exécution d'Autopsy à partir du lecteur de triage en direct + +Insérez votre lecteur dans la machine cible et accédez à ce lecteur dans l'explorateur Windows. Faites un clic droit sur RunFromUSB.bat et sélectionnez "Exécuter en tant qu'administrateur". Ceci est nécessaire pour analyser les lecteurs locaux. + +\image html live_triage_script.png + +L'exécution du script générera quelques répertoires supplémentaires sur la clé USB. Le répertoire configData stocke toutes les données utilisées par Autopsy - principalement les fichiers de configuration et les fichiers temporaires. Vous pouvez apporter des modifications aux paramètres d'Autopsy et ils persisteront d'une analyse à l'autre. Le répertoire des cas est créé comme emplacement par défaut pour enregistrer vos données de cas. Vous devrez y accéder lors de la création d'un cas dans Autopsy. + +Une fois Autopsy en cours d'exécution, créez un cas comme d'habitude, en veillant à le sauvegarder sur la clé USB. + +\image html live_triage_case.png + +Ensuite, choisissez la source de données "Local Disk" et sélectionnez le lecteur souhaité. + +\image html live_triage_ds.png + +Voir la page \ref ds_local pour plus d'informations sur les sources de données de disque local. + +\section live_triage_hash_db Utilisation d'ensembles de hachage + +Suivez ces étapes pour importer un ensemble de hachage à utiliser avec le module \ref hash_db_page : +
      +
    1. Exécutez Autopsy à partir du lecteur de triage en direct, comme décrit précédemment +
    2. Allez sur Tools->Options puis sur l'onglet "Hash Set" +
    3. Importez le jeu de hachage comme d'habitude (en utilisant la destination "Local") mais cochez l'option "Copy hash set into user configuration folder" en bas + +\image html live_triage_import_hash.png +
    + +Cela permettra d'utiliser le jeu de hachage quelle que soit la lettre de lecteur affectée au lecteur de triage en direct. + +*/ \ No newline at end of file diff --git a/docs/doxygen-user_fr/logical_imager.dox b/docs/doxygen-user_fr/logical_imager.dox new file mode 100644 index 0000000000..b42f2703d1 --- /dev/null +++ b/docs/doxygen-user_fr/logical_imager.dox @@ -0,0 +1,185 @@ +/*! \page logical_imager_page Imageur logique + +[TOC] + + +\section logical_imager_overview Aperçu + +L'imageur logique ("Logical Imager") vous permet de collecter des fichiers en direct à partir d'un ordinateur Windows allumé. L'imageur est configuré avec des règles qui spécifient les fichiers à collecter. Les règles peuvent être basées sur des attributs de fichier tels que les noms de dossier, les extensions et les tailles. Vous pouvez utiliser cette fonction lorsque vous n'avez pas le temps ou l'autorisation d'effectuer une acquisition complète du lecteur. + +L'imageur logique peut enregistrer les fichiers correspondants de deux manières. La méthode par défaut consiste à enregistrer des fichiers individuels, ce qui est la méthode la plus rapide et utilise le moins d'espace disque. L'autre option consiste à produire une ou plusieurs images "sparse VHD" contenant toutes les données du système de fichiers qui ont été lues. Ces images VHD peuvent être importées dans Autopsy ou montées avec Windows. Dans les deux cas, l'imageur logique énumère également les comptes d'utilisateurs présents sur le système et peut générer des alertes si des programmes de chiffrement existent. + +Le flux de travail général est: +
      +
    • Configurez l'imageur logique à l'aide d'Autopsy. Cela copiera sur votre lecteur amovible un fichier de configuration spécifiant les fichiers à collecter ainsi que l'exécutable de l'imageur logique. +
    • Insérez le lecteur dans le système cible et exécutez l'imageur logique. Cela génèrera un dossier contenant soit les fichiers correspondants, soit un ou plusieurs "sparse VHD", ainsi qu'un fichier contenant des informations sur les comptes d'utilisateurs et sur les fichiers qui ont généré des alertes. +
    • Chargez le résultat de l'exécution de l'imageur logique dans Autopsy pour parcourir tous les fichiers correspondants et voir les informations des comptes utilisateurs. +
    + +Actuellement, l'imageur logique ne peut être configuré que sur Windows et analysera uniquement les systèmes Windows. Vous devrez également exécuter l'imageur logique en tant qu'administrateur sur le système cible. + +\section logical_imager_config Configuration + +Pour commencer, ouvrez Autopsy et accédez à Tools->Create Logical Imager. + +\image html LogicalImager/tools_menu.png + +
      +
    • Configuration d'un lecteur externe + +L'utilisation normale consiste à sélectionner un lecteur dans la liste sous "Configure selected external drive". Une fois la configuration terminée, cela placera l'exécutable de l'imageur logique et un fichier de configuration dans le répertoire racine de ce lecteur. Notez que l'imageur logique ne peut être configuré et exécuté que sur un lecteur non formaté FAT (sauf exFAT) en raison de la taille maximale de fichier limitée à 4 Go sur les systèmes FAT. + +\image html LogicalImager/configure_drive.png + +
    • Configuration dans un dossier + +Si vous n'êtes pas encore prêt à configurer votre lecteur, ou si vous souhaitez créer un fichier de configuration différent, vous pouvez utiliser la deuxième option en allant chercher un dossier ou un fichier de configuration existant. Si vous créez un nouveau fichier, accédez au dossier dans lequel vous souhaitez le créer. +Notez que le fichier de configuration porte le nom par défaut "logical-imager-config.json". Vous pouvez modifier cela, mais si vous le faites, vous devrez le renommer après l'avoir copié sur votre lecteur ou utiliser l'invite de commande pour exécuter l'imageur. Voir la rubrique sur l'\ref logical_imager_custom_run. + +\image html LogicalImager/select_folder.png +
    + +Dans les deux cas, vous pouvez maintenant configurer votre imageur. Si le fichier de configuration existe déjà, cette fenêtre apparaîtra avec les paramètres actuels du fichier. + +\image html LogicalImager/main_config_panel.png + +Sur le côté gauche, vous pouvez voir chaque règle dans le fichier de configuration. Chacune de ces règles sera appliquée sur le système analysé en direct. Une règle a un nom, une description facultative, une ou plusieurs conditions et des paramètres pour ce qui doit se passer lorsqu'un fichier correspondant à la règle est trouvé. Lorsque vous sélectionnez une règle, vous verrez tous les paramètres de cette règle sur le côté droit du panneau. Vous pouvez modifier ou supprimer des règles une fois que vous les avez sélectionnées. Il existe également des paramètres globaux en bas à droite qui s'appliquent au fichier de configuration dans son ensemble: +
      +
    • Alert if encryption programs are found - Cela ajoutera une règle prédéfinie pour rechercher les programmes de chiffrement et pour vous alerter et exporter tous ceux qui sont trouvés. Vous ne pourrez pas modifier cette règle. + + +
    • Prompt before exiting imager - Si ce paramètre est sélectionné, vous devrez appuyer sur une touche à la fin de l'exécution de l'imageur logique. Cela maintient ouverte la fenêtre d'invite de commande afin que vous puissiez viualiser la sortie. +
    • Create VHD - Si cette option est sélectionnée, un "sparse VHD" sera créé lors de l'exécution de l'imageur logique. Voir plus de détails ci-dessous. +
        +
      • Continue imaging after searches are performed - Uniquement pertinent lors de la création d'un VHD. Par défaut, l'imageur logique copiera uniquement les secteurs qu'il utilise ou qui font partie des fichiers correspondants aux critères de recherches et qui seront exportés. Si cette option est sélectionnée, l'imageur logique parcourt à nouveau l'image une fois la correspondance de règles de recherches terminée et copie tous les secteurs restants. Cela prendra plus de temps à exécuter et donnera des images VHD beaucoup plus grandes. +
      +
    + +Plus d'informations sur la création d'un VHD par rapport à l'enregistrement direct des fichiers correspondants: +
      +
    • Mode non-VHD +
        +
      • Dans ce mode, tous les fichiers correspondant à une règle dont l'option "Extract File" est activée seront copiés dans le dossier de sortie de l'imageur logique. Les chemins et les noms sont raccourcis dans le dossier de sortie mais apparaîtront sous leur forme originale une fois les résultats chargés dans Autopsy. +
      • Avantages: Plus rapide que la création d'un disque dur virtuel et utilisera généralement beaucoup moins d'espace disque +
      • Inconvénients: toutes les métadonnées des fichiers ne sont pas conservées. Aucune donnée supplémentaire sur le système de fichiers n'est enregistrée +
      +
    • Mode VHD +
        +
      • Dans ce mode, toutes les données lues par l'imageur logique sont copiées dans un VHD. Cela inclura tous les fichiers correspondants dans leur intégralité, ainsi que les métadonnées de tous les fichiers du système. +
      • Avantages : Des métadonnées plus complètes pour les fichiers correspondants. Contient des informations sur le système au-delà des fichiers correspondants. Avoir la possibilité de copier l'intégralité du système de fichiers. +
      • Inconvénients : Plus lent et utilise plus d'espace disque. Peut également être déroutant dans Autopsy car de nombreuses entrées de fichiers n'auront pas de données (leurs métadonnées ont été copiées sur le VHD mais pas leur contenu) +
      +
    + +Pour créer une nouvelle règle, cliquez sur le bouton "New Rule". + +\image html LogicalImager/new_attr_rule.png + +Vous avez le choix entre deux types de règles: +
      +
    • Les règles "Attribute" vous permettent d'entrer plusieurs conditions qui doivent être vraies pour qu'un fichier corresponde +
    • Les règles "Full path" vous permettent de saisir un ou plusieurs chemins complets (chemin et nom de fichier) qui doivent correspondre exactement +
    + +Pour chaque type de règle, commencez par saisir un nom de règle et une description facultative. Vous devrez également choisir au moins une action à effectuer lorsqu'une correspondance est trouvée. +
      +
    • Alert in Imager console - cela affichera les données du fichier dans la console et l'ajoutera au fichier de sortie "alerts.txt". +
    • Extract file - cela garantira que le contenu du fichier correspondant sera copié dans le dossier de sortie ou le "sparse VHD" +
    + +Les règles d'attribut peuvent avoir une ou plusieurs conditions. Toutes les conditions doivent être vraies pour qu'une règle corresponde. +
      +
    • Extensions - Le fichier doit correspondre à l'une des extensions données (séparées par des virgules). Les extensions sont insensibles à la casse. +
    • File names - Le fichier doit correspondre à l'un des noms de fichiers donnés (séparés par un retour à la ligne). Les noms de fichiers doivent inclure des extensions et ne sont pas sensibles à la casse. +
    • Folder names - Le fichier doit correspondre à l'un des chemins donnés (séparés par un retour à la ligne). Le chemin donné peut être une sous-chaîne du chemin du fichier. Vous pouvez utiliser "[USER_FOLDER]" pour faire correspondre n'importe quel dossier utilisateur sur le système. Par exemple, "[USER_FOLDER]/Downloads" correspondra au dossier de téléchargements dans n'importe quel dossier utilisateur, tel que "Users/nom d'utilisateur/Downloads". +
    • Minimum size / Maximum size - La taille du fichier doit être dans la plage donnée. Vous pouvez soit spécifier les deux champs pour spécifier une plage, soit en utiliser un seul pour faire correspondre tous les fichiers plus grands ou plus petits que la taille donnée. +
    • Modified Within - Le fichier doit avoir été modifié dans le nombre de jours spécifié +
    + +Les règles de chemin complet ont une seule condition. +
      +
    • Full paths: Le fichier doit correspondre exactement à l'un des chemins complets donnés (séparés par un retour à la ligne) +
    + +\image html LogicalImager/full_path_rule.png + +Une fois que vous avez configuré toutes vos règles, accédez au panneau suivant et cliquez sur "Save" pour enregistrer votre fichier de configuration et l'exécutable de l'imageur logique à l'emplacement que vous avez sélectionné. + +\image html LogicalImager/save.png + +\section logical_imager_running Exécution de l'imageur logique + +\subsection logical_imager_default_run Exécution avec la configuration par défaut + +L'utilisation des valeurs par défaut dans le processus de configuration créera un lecteur avec le fichier de configuration (nommé "logical-imager-config.json") et l'exécutable de l'imageur logique dans le dossier racine de votre lecteur. + +\image html LogicalImager/exe_folder.png + +L'utilisation par défaut consiste à exécuter l'imageur logique sur chaque lecteur, à l'exception de celui qui le contient. Notez que l'exécutable de l'imageur logique doit se trouver dans le répertoire racine pour que le lecteur soit ignoré. Pour exécuter l'imageur, faites un clic droit sur "tsk_logical_imager.exe" et sélectionnez "Exécuter en tant qu'administrateur". Cela ouvrira une fenêtre de console où vous verrez des informations sur le traitement et, si vous avez défini des règles pour créer des alertes, vous verrez également les correspondances dans la console. Selon l'option que vous avez sélectionnée lors de la configuration, la fenêtre peut se fermer automatiquement lorsque le traitement est terminé. + +L'imageur logique commencera à écrire dans un répertoire à côté de l'exécutable. + +\image html LogicalImager/output_folder.png + +\subsection logical_imager_custom_run Exécution à partir d'une invite de commande + +Pour exécuter l'imageur logique avec des paramètres personnalisés, vous devez d'abord ouvrir une invite de commande en mode administrateur (cliquez avec le bouton droit, puis sélectionnez "Exécuter en tant qu'administrateur"). Passez ensuite au lecteur sur lequel se trouve l'imageur logique. Vous pouvez l'exécuter en utilisant la configuration par défaut en tapant simplement "tsk_logical_imager.exe". + +\image html LogicalImager/command_prompt.png + +Si votre fichier de configuration ne s'appelle pas "logical-imager-config.json" (par exemple, si vous avez plusieurs fichiers de configuration pour différentes situations), vous devrez spécifier le nom du fichier à l'aide de l'argument "-c". + +\image html LogicalImager/config_flag.png + +Si vous souhaitez spécifier le lecteur sur lequel exécuter l'imageur logique, vous pouvez utiliser l'argument "-i". Cela peut être utile pour tester votre fichier de configuration - vous pouvez créer une petite clé USB avec des fichiers qui doivent correspondre à vos règles pour vous assurer que tout fonctionne correctement avant de l'utiliser sur un système réel. L'exemple suivant montre comment exécuter l'imageur uniquement sur le lecteur "G" du système: + +\image html LogicalImager/image_flag.png + +\section logical_imager_results Affichage des résultats + +\subsection logical_imager_folder Structure du dossier de sortie + +Si l'imageur logique a été exécuté dans le mode par défaut (sans créer de VHD), le dossier de sortie ressemblera à ceci: + +\image html LogicalImager/nonVHDfolder.png + +Contenu du dossier: +
      +
    • Le dossier root contient tous les fichiers extraits. Ceux-ci peuvent être visualisés directement dans l'explorateur Windows mais comme les noms ont été modifiés et les répertoires aplatis, il est préférable de les visualiser dans Autopsy. +\image html LogicalImager/nonVHDexport.png +
    • config.json est une copie du fichier de configuration utilisé pour générer la sortie +
    • console.txt est une copie de tout ce qui était écrit dans la console Windows +
    • SearchResults.txt est utilisé lors de l'\ref logical_imager_dsp "ajout des résultats dans Autopsy" pour faire correspondre les fichiers exportés avec leurs chemins et noms de fichiers d'origine, ainsi que la règle à laquelle ils correspondent. Ce fichier sera ajouté au cas d'Autopsy en tant que \ref reporting_page "rapport". +
    • users.txt contient des informations sur les comptes utilisateurs trouvés dans le système. Ce fichier sera également ajouté au cas d'Autopsy en tant que \ref reporting_page "rapport". +
    + +Si l'imageur logique a été configuré pour créer des VHD, vous verrez ces VHD dans le dossier de sortie (avec les autres fichiers de sortie décrits ci-dessus, à l'exception du dossier racine): + +\image html LogicalImager/VHDfolder.png + +\subsection logical_imager_dsp Ajout des résultats à Autopsy + +Les résultats de l'imageur logique peuvent être ajoutés à un cas d'Autopsy en tant que \ref ds_page "source de données". Cela ajoute soit uniquement les fichiers correspondants, soit le ou les "sparse VHD" en tant qu'image disque, et cela ajoute également les autres fichiers créés par l'imageur logique. Sélectionnez l'option "Autopsy Imager" et passez à la page suivante. + +\image html LogicalImager/dsp_select.png + +Dans la section supérieure, vous pouvez voir tous les dossiers de résultats de l'imageur logique dans le dossier racine de chaque lecteur. Sélectionnez celui que vous souhaitez ajouter, puis cliquez sur le bouton "Next". + +\image html LogicalImager/import.png + +Si les résultats de votre imageur logique se trouvent à un emplacement différent, sélectionnez "Manually Choose Folder" et utilisez le bouton "Browse" pour localiser vos résultats. + +Dans les deux cas, vous aurez à configurer les \ref ingest_page "modules d'acquisition" à exécuter. Vous pouvez exécuter n'importe lesquels, mais si vous avez créé un VHD, votre image disque peut ne pas être complète et vous pouvez voir un plus grand nombre d'erreurs qu'à l'accoutumée. Par exemple, un "sparse VHD" contiendra l'intégralité de la table d'allocation de fichiers, mais les données réelles qui accompagnent la plupart des fichiers seront manquantes. + +Que vous ayez utilisé un VHD ou non, les fichiers correspondants apparaîtront dans leur chemin d'origine avec leur nom d'origine dans l'\ref tree_viewer_page. Si vous n'avez pas créé de VHD, vous ne verrez que les fichiers correspondants dans l'arborescence. Si vous avez créé un VHD, vous verrez également des entrées pour les fichiers qui ne correspondent pas, bien que le contenu de ces fichiers puisse ne pas figurer dans l'image. + +\image html LogicalImager/fileTree.png + +Des artefacts "Interesting File" seront créés pour tous les fichiers qui correspondent aux règles. + +\image html LogicalImager/interestingFiles.png + +Les alertes et fichiers d'utilisateur créés par l'imageur logique se trouvent dans la section Reports de l'arborescence. + + +*/ \ No newline at end of file diff --git a/docs/doxygen-user_fr/logs_and_output_page.dox b/docs/doxygen-user_fr/logs_and_output_page.dox new file mode 100644 index 0000000000..f9a2401b39 --- /dev/null +++ b/docs/doxygen-user_fr/logs_and_output_page.dox @@ -0,0 +1,11 @@ +/*! \page logs_and_output_page Affichage des sorties des cas et des journaux + +Il existe plusieurs raccourcis pour accéder aux dossiers et journaux des cas. + +- Pour ouvrir le dossier contenant les sorties du cas, utilisez "Tools", "Open Output Folder" comme indiqué ci-dessous: +\image html open_output_folder.PNG + +- Pour ouvrir le dossier contenant les journaux du cas, utilisez "Help", "Open Log Folder" comme indiqué ci-dessous: +\image html open_log_folder.PNG + +*/ diff --git a/docs/doxygen-user_fr/machine_translation.dox b/docs/doxygen-user_fr/machine_translation.dox new file mode 100644 index 0000000000..bf50fe2bfc --- /dev/null +++ b/docs/doxygen-user_fr/machine_translation.dox @@ -0,0 +1,62 @@ +/*! \page machine_translation_page Traduction automatique + +[TOC] + + +Vous pouvez configurer un service de traduction automatique à utiliser avec Autopsy. Si un service est configuré, vous pourrez traduire du texte dans la \ref content_viewer_page ainsi que les noms de fichiers dans la \ref result_viewer_page et l'\ref tree_viewer_page. + +\section mt_config Configuration + +Pour configurer un service de traduction automatique, accédez à Options->Tools puis sélectionnez l'onglet "Machine Translation". Sélectionnez le service que vous souhaitez utiliser dans le menu déroulant en haut. Vous devrez créer un compte avec Bing ou Google, puis entrer les informations de compte. + + +\image html mt_config.png + +Chaque service nécessitera des étapes de configuration légèrement différentes. Après avoir tout configuré, vous pouvez exécuter une vérification rapide pour contrôler si le service est correctement configuré en utilisant le bouton "Test". + +La case à cocher en bas vous permet d'activer ou de désactiver la reconnaissance optique de caractères (OCR). Lorsqu'elle est activée, si vous sélectionnez une image dans la \ref mt_content_viewer "visionneuse de contenu", Autopsy utilisera l'OCR pour tenter d'extraire le texte à traduire. Les instructions d'installation des packages OCR pour différentes langues se trouvent sur la page \ref keyword_search_ocr_config "Recherches par mots clés (Keyword Search)". + +\section mt_file_names Traduction des noms de fichiers + +Vous pouvez utiliser la traduction automatique pour traduire automatiquement les noms de fichiers et de dossiers, tels que ceux présentés ci-dessous: + +\image html mt_file_name_original.png + +Pour activer la traduction des noms de fichiers, accédez à la page \ref view_options_page et cochez la case sous "Translate Text". + +\image html mt_file_name_enable.png + +Une fois activée, les versions traduites des noms de fichier et de dossier seront affichées dans l'\ref tree_viewer_page et dans la première colonne de la \ref result_viewer_page. Le nom d'origine sera affiché dans la nouvelle colonne "Original Name". + +\image html mt_file_names_translated.png + +\section mt_content_viewer Traduction du contenu des fichiers et des messages + +Une fois que vous avez configuré un service de traduction automatique, le sous-onglet "Translation" sous l'onglet "Text" de la visionneuse de contenu sera activé. L'onglet "Translation" vous permet d'utiliser votre service pour traduire le début d'un fichier. Par exemple, vous pouvez voir par défaut ce qui suit dans l'onglet "Indexed Text": + +\image html mt_content_viewer_untranslated_text.png + +Passer à l'onglet "Translation" affichera le texte traduit via le service de traduction automatique. + +\image html mt_content_viewer_translated.png + +La traduction automatique fonctionne également pour les messages. Pour traduire un message, sélectionnez l'onglet "Text" au-dessus du contenu du message. + +\image html mt_message_orig.png + +Ensuite, utilisez le menu déroulant sur la droite pour passer de "Original Text" à "Translated Text". + +\image html mt_message_translated.png + +Si vous avez activé l'OCR comme décrit dans la section \ref mt_config ci-dessus, vous pouvez extraire et traduire du texte à partir d'images. Voici une image contenant le début d'un poème français: + +\image html mt_ocr_image.png + +Si vous allez sur l'onglet "Text" puis l'onglet "Translation", l'OCR sera utilisé pour lire le texte de l'image, puis afficher la traduction. + +\image html mt_ocr_result.png + +*/ \ No newline at end of file diff --git a/docs/doxygen-user_fr/main.dox b/docs/doxygen-user_fr/main.dox new file mode 100644 index 0000000000..aabf341c7c --- /dev/null +++ b/docs/doxygen-user_fr/main.dox @@ -0,0 +1,115 @@ +/*! \mainpage Guide de l'utilisateur d'Autopsy + + +Aperçu +----- + +Ceci est le guide de l'utilisateur de la plate-forme open source Autopsy. Autopsy vous permet d'analyser un disque dur ou un appareil mobile et d'en récupérer des éléments de preuves. Ce guide devrait vous aider à utiliser Autopsy. Le guide du développeur vous aidera à développer vos propres modules d'Autopsy. + +Remarque: pour les utilisateurs exécutant Autopsy sur des appareils Mac, les fonctionnalités disponibles via la boîte de dialogue "Tools"->"Options" et décritent dans cette documentation sont accessibles via la barre de menu système sous "Préférences" ou via le raccourci Cmd +, (touche "Cmd" + touche "plus"). + +Rubriques d'aide +------- +Les rubriques suivantes sont disponibles: + +- \subpage installation_page +- Mises à niveau notables + - \subpage upgrade_solr8_page +- Configuration + - \subpage config_page + - \subpage performance_page + - Cluster multi-utilisateurs + - \subpage install_multiuser_page + - \subpage multiuser_sec_page + - \subpage multiuser_page + +- \subpage quick_start_guide "Guide de démarrage rapide" + +- Cas et ajout de sources de données + - \subpage workflow_page + - \subpage cases_page + - \subpage ds_page + - \subpage logs_and_output_page + + +- Modules d'acquisition + - \subpage ingest_page + - \subpage recent_activity_page + - \subpage hash_db_page + - \subpage file_type_identification_page + - \subpage embedded_file_extractor_page + - \subpage EXIF_parser_page + - \subpage keyword_search_page + - \subpage email_parser_page + - \subpage extension_mismatch_detector_page + - \subpage data_source_integrity_page + - \subpage android_analyzer_page + - \subpage interesting_files_identifier_page + - \subpage photorec_carver_page + - \subpage cr_ingest_module "Central Repository (Référentiel central)" + - \subpage encryption_page + - \subpage vm_extractor_page + - \subpage plaso_page + - \subpage drone_page + - \subpage gpx_page + - \subpage ileapp_page + - \subpage aleapp_page + - \subpage yara_page + +- Examen des résultats + - \subpage uilayout_page + - \subpage tree_viewer_page + - \subpage result_viewer_page + - \subpage content_viewer_page + - \subpage data_source_summary_page + - \subpage machine_translation_page + +- Recherches + - \subpage ui_quick_search + - \subpage file_search_page + - \subpage ad_hoc_keyword_search_page + - \subpage stix_page + - \subpage common_properties_page + - \subpage search_all_cases_page + +- Visionneuses spécialisées + - \subpage image_gallery_page + - \subpage timeline_page + - \subpage communications_page + - \subpage geolocation_page + - \subpage discovery_page + - \subpage personas_page + +- Rapports + - \subpage tagging_page + - \subpage reporting_page + +- \subpage module_install_page +- \subpage central_repo_page + +- Autres flux de travail + - Triage + - \subpage triage_page + - \subpage live_triage_page + - \subpage logical_imager_page + - \subpage command_line_ingest_page + + +- Module expérimental + - \subpage experimental_page + - \ref auto_ingest_page + - \ref object_detection_page + - \ref volatility_dsp_page + +- Contributions de la communauté + - \subpage translations_page + - \subpage update_interesting_files_page + +- \subpage troubleshooting_page + +Si le sujet dont vous avez besoin n'est pas répertorié, vous pouvez: +- Vous référer au Wiki Autopsy +- Poser une question sur le Forum +- Poser une question sur la Mailing liste. + +*/ diff --git a/docs/doxygen-user_fr/manifest_tool.dox b/docs/doxygen-user_fr/manifest_tool.dox new file mode 100644 index 0000000000..6bc27c3095 --- /dev/null +++ b/docs/doxygen-user_fr/manifest_tool.dox @@ -0,0 +1,65 @@ +/*! \page manifest_tool_page Outil Manifest + +[TOC] + + +\section manifest_tool_overview Aperçu + +"Manifest Tool" est un exécutable conçu pour aider à la création automatisée de fichiers Manifest nécessaires pour exécuter l'acquisition automatisée sur une source de données. Aucune installation n'est nécessaire. Pour utiliser l'outil, double-cliquez sur l'exécutable "Manifest Tool". Lorsqu'il s'ouvre, sélectionnez l'option avec l'algorithme que vous souhaitez exécuter dans la liste déroulante, et remplissez tous les paramètres disponibles avant de cliquer sur le bouton "Run". Un journal indiquant le succès ou l'échec de chaque fichier Manifest qu'il tente de créer apparaîtra dans la zone de progression. + +\section manifest_tool_output Sortie + +La sortie de l'outil Manifest sera des fichiers XML se terminant par _Manifest.xml. + +\subsection manifest_tool_one_ds_per_folder "One Data Source Per Folder" + +L'algorithme "One Data Source Per Folder" est conçu pour un cas d'utilisation spécifique : lorsque le dossier de cas contient plusieurs sous-dossiers, chacun contenant généralement une source de données d'un certain type. Référez vous à la section \ref manifest_tool_algorithm_specifics pour plus de détails sur cet algorithme. + +Pour utiliser cet algorithme, utilisez le bouton "Browse" pour sélectionner un dossier racine comme répertoire de cas. Sélectionnez ensuite le bouton "Run" pour générer des fichiers Manifest pour chacune des sources de données détectées. Un fichier Manifest sera généré pour chaque sous-dossier du dossier racine sélectionné, les fichiers Manifest seront placés dans le dossier racine sélectionné. + +\subsection manifest_tool_single_ds "Single Data Source" + +L'algorithme "Single Data Source" sert à créer un fichier Manifest pour une seule image ou un fichier logique avec un nom de cas spécifié par l'utilisateur. + +Pour utiliser cet algorithme, utilisez le bouton "Browse" pour sélectionner un fichier à utiliser comme source de données et entrez un nom de cas dans le champ "Case name". Sélectionnez ensuite le bouton "Run" pour générer un fichier Manifest. Le fichier Manifest sera créé dans le même dossier que la source de données sélectionnée. + +\subsection manifest_tool_logical_file_folder "Folder of Logical Files" + +L'algorithme "Folder of Logical Files" sert à créer un fichier Manifest unique pour un dossier entier de fichiers qui seront tous analysés en tant que fichiers logiques. + +Pour utiliser cet algorithme, utilisez le bouton "Browse" pour sélectionner un dossier à ajouter en tant que dossier de fichiers logiques et entrez un nom de cas dans le champ "Case name". Sélectionnez ensuite le bouton "Run" pour générer un fichier Manifest. Le fichier Manifest sera créé dans le dossier parent de votre dossier de fichiers logiques. + +\section manifest_tol_example Exemple + +Étant donné un dossier racine qui ressemble à ceci: + +\image html AutoIngest/manifest_tool_root_folder.png + +Un utilisateur ayant sélectionné l'algorithme "One Data Source Per Folder" obtiendra une sortie qui ressemble à ce qui suit, où un fichier Manifest existe maintenant pour chaque sous-dossier non vide. Le nom du dossier racine sera utilisé comme nom de cas dans les fichiers Manifest (dans cet exemple, le nom de cas sera TestCaseFolder.) + +\image html AutoIngest/manifest_tool_ui.png + +Le contenu d'un fichier XML aura le format suivant: + +\verbatim + + +TestCaseFolder +interestingL01\interesting_files2.L01 + +\endverbatim + +\section manifest_tool_algorithm_specifics Spécificités de l'algorithme "One Data Source Per Folder" +
      +
    • Le seul paramètre de configuration que l'utilisateur doit choisir est un dossier racine. +
    • Le nom du dossier racine spécifié deviendra le nom de cas utilisé dans les fichiers Manifest. +
    • Chaque sous-dossier non vide du dossier racine aura un fichier Manifest créé pour lui. +
    • Tous les fichiers Manifest seront créés dans le dossier racine. +
    • Les fichiers directement dans le dossier racine seront ignorés et resteront non traités. +
    • Les sous-dossiers qui contiennent un fichier .E01, .L01, .001 ou .AD1 auront le premier fichier de ce type utilisé comme source de données dans le fichier Manifest. +
    • Les sous-dossiers contenant plusieurs fichiers .E01, .L01, .001 ou .AD1 verront les fichiers supplémentaires ignorés et ils resteront non traités. +
    • Les sous-dossiers sans fichier .E01, .L01, .001 ou .AD1 auront le sous-dossier entier ajouté comme source de données. +
    • Si le dossier racine contient déjà un fichier _Manifest.xml spécifique, il ne sera ni remplacé ni modifié. +
    + +*/ \ No newline at end of file diff --git a/docs/doxygen-user_fr/module_install.dox b/docs/doxygen-user_fr/module_install.dox new file mode 100644 index 0000000000..e3cb3ae84b --- /dev/null +++ b/docs/doxygen-user_fr/module_install.dox @@ -0,0 +1,26 @@ +/*! \page module_install_page Installation de modules tiers + +[TOC] + + +Il existe différents endroits dans Autopsy où les développeurs peuvent écrire des modules d'extension personnalisés. Cette page explique comment les installer. + +Il existe deux types de modules: +- Modules écrits en Java livrés dans des fichiers NBM (NetBeans Module). +- Modules écrits en Python livrés sous forme de dossier dans un fichier ZIP. + +\section module_install_nbm Installation des modules NetBeans +Si vous disposez d'un fichier NBM, il peut contenir un ou plusieurs modules Autopsy. Pour l'installer, utilisez le gestionnaire de plugins dans "Tools", "Plugins". + +\image html module_install_netbeans.png + +Choisissez l'onglet "Downloaded" puis "Add Plugins". Accédez au fichier NBM. Vous devrez peut-être redémarrer Autopsy. + +\section module_install_python Installation des modules Python +Si vous avez un fichier ZIP contenant un module Python, décompressez le fichier et vous devriez obtenir un dossier. Ouvrez le dossier de la bibliothèque des modules Python via Autopsy en utilisant "Tools", "Python Plugins". + +\image html module_install_python.png + +Sous Windows, ce sera sous votre répertoire utilisateur, dans "AppData\Roaming\autopsy\python_modules". Collez à cet emplacement le dossier du module et Autopsy devrait l'identifier et l'utiliser la prochaine fois qu'il chargera les modules. + +*/ diff --git a/docs/doxygen-user_fr/multi-user/createMultiUserCase.dox b/docs/doxygen-user_fr/multi-user/createMultiUserCase.dox new file mode 100644 index 0000000000..98326d1232 --- /dev/null +++ b/docs/doxygen-user_fr/multi-user/createMultiUserCase.dox @@ -0,0 +1,30 @@ +/*! \page multiuser_page Utilisation de cas multi-utilisateurs + +\section creating_multi_user_cases Créer des cas multi-utilisateurs + +Les cas multi-utilisateurs permettent à plusieurs instances d'Autopsy d'avoir le même cas ouvert en même temps. Lors de la création d'un cas, les utilisateurs ont le choix entre un cas mono-utilisateur ou multi-utilisateurs, comme indiqué dans la capture d'écran ci-dessous. + +\image html case-newcase.PNG + +Pour créer un cas multi-utilisateurs, les opérations suivantes doivent avoir été réalisées: +- Les services réseau doivent être installés, configurés et en cours d'exécution. Voir \ref multiuser_install_install. +- Le dossier "Case" doit se trouver dans un dossier partagé auquel tous les autres clients peuvent également accéder via le même chemin (UNC ou lettre de lecteur). +- Les sources de données ajoutées avec l'assistant "Add Data Source" doivent se trouver dans un dossier partagé auquel tous les clients peuvent accéder via le même chemin. + +\section multi_user_other Autres informations multi-utilisateurs + +- Lors de l'utilisation d'un cas multi-utilisateurs, d'autres nœuds peuvent exécuter une acquisition de données sur le même cas. Pendant ce temps, vous verrez une barre de progression étiquetée avec le nom d'hôte de la machine effectuant l'acquisition en bas à droite d'Autopsy. La barre de progression continuera à se déplacer d'avant en arrière jusqu'à ce que l'acquisition soit terminée ou annulée. Vous pouvez toujours exécuter une acquisition sur votre ordinateur local pendant que cela est en cours. Ceci est montré dans la capture d'écran ci-dessous. + +\image html othernodeingesting.PNG + +- Lorsque des problèmes surviennent, une "info-bulle" apparait en bas à droite de l'écran. Il a un "i" à l'intérieur d'un cercle, avec une couleur de cercle différente en fonction du message. Rouge pour signaler un problème et bleue pour une information. Voir la capture d'écran ci-dessous. + +\image html messagebubbles.PNG + +- Cliquer sur cette "info-bulle" fait apparaître la liste des notifications précédentes qui n'ont pas été rejetées en cliquant sur le "x". Comme vous pouvez le voir dans la capture d'écran ci-dessous, le câble réseau a été débranché de la machine et elle a perdu toute connexion aux trois services. Lorsque le câble a été reconnecté, les services ont été retrouvés. + +\image html messagebubblesbigger.PNG + +- Lors de la création de cas multi-utilisateurs, nous vous recommandons d'utiliser des chemins UNC pour spécifier les noms des lecteurs. Le mappage de lecteur fonctionnera, mais il est parfois difficile de faire correspondre toutes les machines participant à un cas aux mêmes lettres de lecteur pour les mêmes ressources. Il est beaucoup plus simple d'utiliser des chemins UNC entièrement spécifiés sous la forme \\\\nom-hote\\nom-partage\\dossier. + +*/ \ No newline at end of file diff --git a/docs/doxygen-user_fr/multi-user/installActiveMQ.dox b/docs/doxygen-user_fr/multi-user/installActiveMQ.dox new file mode 100644 index 0000000000..fbfacc7a2b --- /dev/null +++ b/docs/doxygen-user_fr/multi-user/installActiveMQ.dox @@ -0,0 +1,145 @@ +/*! \page install_activemq_page Installer et configurer ActiveMQ + +\section install_activemq_overview Aperçu + +ActiveMQ est un service de messagerie qui permet aux clients Autopsy de communiquer entre eux. Cela permet à chaque client d'obtenir des mises à jour en temps réel. Ce service a des exigences de stockage minimales. + + +\section install_activemq_prereq Conditions préalables + +Vous aurez besoin de: +- Java Runtime Environment 8 (JRE) version 64 bits téléchargeable à partir de https://github.com/ojdkbuild/ojdkbuild ( Lien vers l'installateur) +- Télécharger ActiveMQ depuis: http://activemq.apache.org/download.html . Autopsy a été testé avec ActiveMQ version 5.14.0. + + +\section install_activemq_install Installation + +\subsection install_activemq_install_java Installation du JRE +Installez Java JRE si nécessaire. Vous pouvez tester l'installation en exécutant _where java_ à partir du terminal de commande. Si vous voyez une sortie similaire aux résultats ci-dessous, vous avez un JRE. +

    +\image html wherejava.PNG +

    +Si vous avez besoin du JRE, installez-le avec les paramètres par défaut. + + +\subsection install_activemq_install_mq Installation de ActiveMQ + +
      +
    1. Extrayez le contenu de l'archive ActiveMQ vers un emplacement de votre choix, en gardant à l'esprit que les fichiers doivent se trouver dans un emplacement où le processus en cours d'exécution dispose d'autorisations d'écriture. Un choix de dossier typique serait C:\\Program Files\\apache-activemq-5.13.3. Le système peut demander une autorisation d'administrateur pour déplacer le dossier. Autorisez-la si nécessaire. + +
    2. Ouvrez le fichier conf\\activemq.xml dans le dossier extrait avec un éditeur de texte et apportez les modifications suivantes: +
        +
      • Ajoutez "schedulePeriodForDestinationPurge="10000"" à la balise _broker_ puis ajouter "gcInactiveDestinations="true" inactiveTimoutBeforeGC="30000"" à la balise _policyEntry_. Ceci est surligné en jaune ci-dessous: + +\image html activeMQ_node_cleanup.png + +
      • Ajoutez "&wireFormat.maxInactivityDuration=0" à l'URI dans la balise _transportConnector_ nommée _openwire_. Ceci est surligné en jaune ci-dessous: +

        +\image html maxinactivityduration.PNG +

        +
      + +
    3. Installez ActiveMQ en tant que service en accédant au dossier bin\\win64, puis en faisant un clic droit sur _InstallService.bat_, sélectionnez _Exécuter en tant qu'administrateur_, puis cliquez sur _Oui_. + +
    4. Démarrez le service ActiveMQ en cliquant sur le bouton _Démarrer_, puis tapez _services.msc_, et validez avec _Entrer_. Trouvez _ActiveMQ_ dans la liste et cliquez sur le lien _Démarrer le service_. + +
    5. ActiveMQ doit maintenant être installé et configuré à l'aide des informations d'identification par défaut. +
    + +\subsection install_activemq_test Essai + +Pour tester votre installation, vous pouvez accéder aux pages d'administration par votre navigateur Web via une URL comme celle-ci: http://localhost:8161/admin. + +Le nom d'administrateur par défaut est _admin_ avec le mot de passe _admin_ et le nom d'utilisateur standard par défaut est _user_ avec le mot de passe _password_. Vous pouvez modifier ces mots de passe en suivant les instructions ci-dessous. + +Si vous pouvez voir une page qui ressemble à ce qui suit, cela confirme que le service ActiveMQ s'exécute localement, mais cela ne signifie pas nécessairement que le service est visible par les autres ordinateurs du réseau. +

    +\image html activemq.PNG +

    + +Vous pouvez confirmer que votre installation ActiveMQ est visible par les autres ordinateurs du réseau en essayant de vous connecter à une URL comme celle-ci (en remplaçant le nom d'hôte par celui de l'ordinateur ActiveMQ) dans un navigateur Web: http://activemq-computer:61616 + +Si vous ne parvenez pas à vous connecter à cette adresse: +- Vérifiez que le service ActiveMQ est en cours d'exécution +- Vérifiez que le port (61616) n'est pas bloqué par un pare-feu. + + + +\section install_activemq_install_pw Configuration de l'authentification + +Vous pouvez éventuellement ajouter une authentification à votre serveur ActiveMQ. Les communications ActiveMQ ne sont pas chiffrées et contiennent des messages de base entre les systèmes sur le moment où de nouvelles données ont été trouvées. + +Les instructions suivantes vous permettent de configurer les informations d'identification: + +1. Copiez et collez le texte suivant dans le fichier "conf\groups.properties", en écrasant le texte surligné en jaune dans la capture d'écran ci-dessous: +
    +admins=system,sslclient,client,broker1,broker2
    +tempDestinationAdmins=system,user,sslclient,client,broker1,broker2
    +users=system,user,sslclient,client,broker1,broker2
    +guests=guest
    +
    +

    +\image html groups.properties.before.PNG +

    +Une fois terminé, le fichier devrait ressembler à ceci: +

    +\image html groups.properties.after.PNG +

    + +2. Copiez et collez le texte suivant dans le fichier "conf\users.properties", en écrasant le texte surligné en jaune dans la capture d'écran ci-dessous: +
    +system=manager
    +user=password
    +guest=password
    +sslclient=CN=localhost, OU=activemq.org, O=activemq.org, L=LA, ST=CA, C=US
    +
    +

    +\image html users.properties.before.PNG +

    +Une fois terminé, le fichier devrait ressembler à ceci: +

    +\image html users.properties.after.PNG +

    + +3. Copiez et collez le texte suivant dans le fichier "conf\activemq.xml", en insérant le texte au niveau de la ligne indiquée en jaune dans la capture d'écran ci-dessous. + + + + + + + + + + + + +

    +\image html insertTextHere.PNG +

    +Après l'insertion, le fichier doit ressembler à la capture d'écran ci-dessous, avec la partie insérée surlignée en jaune. C'est ici que vous pouvez modifier le nom d'utilisateur et le mot de passe pour votre configuration ActiveMQ. +

    +\image html insertedText.PNG +

    + + +Pour ajouter un nouvel utilisateur ou modifier le mot de passe: + +1. Arrêtez le service ActiveMQ en cliquant sur le bouton _Démarrer_, puis tapez _services.msc_, et validez avec _Entrer_. Trouvez _ActiveMQ_ dans la liste et cliquez sur le lien _Arrêter le service_. +

    +\image html StopActiveMQService.PNG +

    +2. Modifiez le fichier "conf\activemq.xml" en ajoutant la ligne souhaitée. Les variables _username_ et _password_ sont sensibles à la casse. Il sera très probablement souhaitable de garder vos nouveaux utilisateurs dans le groupe _users_. +

    +\image html newUserAndPassword.PNG +

    +3. Démarrez le service ActiveMQ en cliquant sur le bouton _Démarrer_, puis tapez _services.msc_, et validez avec _Entrer_. Trouvez _ActiveMQ_ dans la liste et cliquez sur le lien _Démarrer le service_. +

    +\image html StartActiveMQService.PNG +

    + +\section install_mq_backup Sauvegarde + +Il n'y a rien à sauvegarder pour ActiveMQ. Il ne stocke aucune donnée relative aux cas dans ses fichiers. + +*/ diff --git a/docs/doxygen-user_fr/multi-user/installMultiUser.dox b/docs/doxygen-user_fr/multi-user/installMultiUser.dox new file mode 100644 index 0000000000..070dd9dd44 --- /dev/null +++ b/docs/doxygen-user_fr/multi-user/installMultiUser.dox @@ -0,0 +1,35 @@ +/*! \page install_multiuser_page Configuration d'un cluster multi-utilisateur + +\section multiuser_install_overview Aperçu + +Autopsy peut être configuré pour fonctionner dans un environnement où plusieurs utilisateurs sur différents ordinateurs peuvent ouvrir le même cas en même temps. Pour configurer ce type d'environnement, vous devrez configurer des services réseau supplémentaires (gratuits et open source). + +Le concept de base est que vous aurez: +- une base de données centrale +- un index central de recherche par mots-clés +- un stockage central + +Chaque client Autopsy utilisera ensuite ces ressources partagées au lieu des versions intégrées qui sont utilisées pour les cas mono-utilisateur. + +\image html multi-user-network.png + + +\section multiuser_install_install Installation et configuration du cluster + +Passons maintenant au processus de configuration d'un cluster Autopsy. Lorsque vous configurez les services réseau, notez les adresses, les noms d'utilisateurs et les mots de passe afin de pouvoir configurer plus facilement chacun des systèmes clients par la suite. + +Etape 1: \ref install_multiuser_systems_page + +Etape 2: \ref install_multiuseruser_page + +Etape 3: \ref install_multiuser_storage_page + +Etape 4: \ref install_postgresql_page + +Etape 5: \ref install_solr_page + +Etape 6: \ref install_activemq_page + +Etape 7: \ref install_multiuserclient_page + +*/ \ No newline at end of file diff --git a/docs/doxygen-user_fr/multi-user/installMultiUserClient.dox b/docs/doxygen-user_fr/multi-user/installMultiUserClient.dox new file mode 100644 index 0000000000..872255efae --- /dev/null +++ b/docs/doxygen-user_fr/multi-user/installMultiUserClient.dox @@ -0,0 +1,21 @@ +/*! \page install_multiuserclient_page Installer les clients Autopsy + + +\section multiuser_install_clients Aperçu + +Une fois l'infrastructure en place, vous pouvez configurer les clients Autopsy pour les utiliser. +
      +
    1. Installez Autopsy sur chaque système client. Utilisez le programme d'installation normal et choisissez les valeurs par défaut. +
    2. Vérifiez que l'utilisateur a accès au stockage partagé en ouvrant les dossiers de stockage partagés à l'aide de l'Explorateur Windows. Si une invite de mot de passe s'affiche, entrez le mot de passe et stockez les informations d'identification (Voir \ref multiuser_users_store). +
    3. Démarrez Autopsy et ouvrez le panneau des paramètres multi-utilisateurs à partir de "Tools", "Options", "Multi-user". Comme le montre la capture d'écran ci-dessous, vous pouvez ensuite saisir toutes les informations d'adresse et d'authentification pour les services réseau. Notez que pour créer ou ouvrir des cas multi-utilisateurs, "Enable Multi-user cases" doit être coché et les paramètres ci-dessous doivent être corrects. + +\image html solr_autopsy.png + +
    4. Pour chaque réglage, cliquez sur le bouton "Test Connection" pour vous assurer qu'Autopsy peut communiquer avec chaque service. En cas d'échec, reportez-vous à la page de configuration spécifique pour les options de test. Vérifiez également qu'un pare-feu ne bloque pas les communications. +
      • REMARQUE: aucun de ces tests ne concerne les autorisations sur le stockage partagé car Autopsy ne connaît pas le stockage partagé. Il ne peut pas le tester tant que vous ne présentez pas de cas.
      +
    5. Créez un cas test (voir \ref creating_multi_user_cases). Vous pouvez ajouter un seul fichier en tant que source de données logique. Le concept clé est de rechercher les erreurs. +
        +
      • Si vous trouvez des erreurs, recherchez les erreurs dans le fichier journal sur le client Autopsy. +
      • Si vous avez suivi toutes les étapes précédentes dans toutes les pages précédentes, une erreur courante à ce stade est que Solr ne peut pas accéder au stockage partagé et qu'il s'exécute en tant que compte de Service. Lorsque cela se produit, vous verrez un message d'erreur indiquant que Solr ne peut pas créer ou accéder à un "noyau". Si cela se produit, vérifiez sous quel utilisateur Solr doit être exécuté (voir la section \ref multiuser_users_solr) et modifiez la configuration du stockage partagé ou assurez-vous que les informations d'identification sont stockées.
      +
    +*/ \ No newline at end of file diff --git a/docs/doxygen-user_fr/multi-user/installPostgres.dox b/docs/doxygen-user_fr/multi-user/installPostgres.dox new file mode 100644 index 0000000000..90a2dd82ce --- /dev/null +++ b/docs/doxygen-user_fr/multi-user/installPostgres.dox @@ -0,0 +1,119 @@ +/*! \page install_postgresql_page Installer et configurer PostgreSQL + + +\section install_post_over Aperçu + +Dans un cas multi-utilisateur, un serveur de base de données PostgreSQL central est utilisé à la place des bases de données SQLite intégrées. + +Une nouvelle base de données sera créée pour chaque cas et la base de données sera stockée dans un emplacement que vous aurez choisi lors de l'installation. Il est recommandé de choisir un lecteur local sur la machine et non le lecteur système. + +Vous devez vous assurer que le dossier de la base de données est sauvegardé. + +\section install_post_install Installation + +Pour installer PostgreSQL, procédez comme suit: + +1. Téléchargez le programme d'installation PostgreSQL 64 bits depuis https://www.enterprisedb.com/downloads/postgres-postgresql-downloads Choisissez-en un pour Windows x86-64. Autopsy a été testé avec PostgreSQL version 9.5. + +2. Exécutez le programme d'installation. Le nom sera similaire à _postgresql-9.5.3-1-windows-x64.exe_. + +3. Vous pouvez accepter les valeurs par défaut pour tous les éléments à l'exception du mot de passe et de l'emplacement de stockage de la base de données lorsque vous utilisez l'assistant. Ne perdez pas le mot de passe que vous avez entré. Il s'agit du mot de passe de connexion de l'administrateur PostgreSQL. + +4. Vous n'avez pas besoin de lancer StackBuilder ni d'acquérir d'autres logiciels. Décochez l'option pour utiliser StackBuilder et appuyez sur _Terminé_. + + +\section install_post_config Configuration + +1. Créez un compte utilisateur de la base de données standard qu'Autopsy utilisera. Vous pouvez le faire avec l'une des ces deux méthodes : graphiquement ou en ligne de commande. Nous décrirons l'option graphique ici. + + +- Utilisez l'outil pgAdmin III et connectez-vous avec le login administrateur PostgreSQL. +- Faites un clic droit sur "Login Roles" et sélectionnez "New Login Role..." comme indiqué ci-dessous: +

    +\image html pgAdmin.PNG +

    +- Entrez le nom d'utilisateur que vous souhaitez utiliser dans le champ "Role name". +

    +\image html newLoginRole.PNG +

    +- Entrez le mot de passe dans l'onglet "Definition". +

    +\image html newPassword.PNG +

    +- Cochez "Can create databases" dans l'onglet "Role Privileges". +

    +\image html newRights.PNG +

    +- Cliquez sur "OK". + +2. Modifiez C:\\Program Files\\PostgreSQL\\9.5\\data\\pg_hba.conf pour ajouter une entrée permettant aux ordinateurs externes de se connecter via le réseau. +

    +Tout d'abord, recherchez l'adresse IPv4 et le masque de sous-réseau de votre appareil (Cliquez sur _Démarrer_, tapez _cmd_, entrez _ipconfig_ et analysez les résultats. L'adresse IP est affichée en jaune ci-dessous. +
    +\image html postgresqlinstall3.PNG +
    +Voici un exemple de règle qui permet à tous les clients du sous-réseau 10.10.192.x de se connecter à l'aide d'une authentification md5. +
    +> host      all      all      10.10.192.0/24      md5 +
    +__Règles générales de masque de sous-réseau:__ + - Si votre masque de sous-réseau est 255.255.0.0, votre règle devrait ressembler à ceci: A.B.0.0/16, où A est le premier octet de votre adresse IP et B est le deuxième octet. +
    + - Si votre masque de sous-réseau est 255.255.255.0, votre règle devrait ressembler à ceci: A.B.C.0/24, où A est le premier octet de votre adresse IP, B est le deuxième octet et C est le troisième octet. +

    +Ajoutez la ligne surlignée en jaune ci-dessous, formatée avec des espaces entre les entrées, en ajustant l'adresse IP à une valeur appropriée comme décrit ci-dessus. +

    +\image html postgresqlinstall4.PNG +
    +

    +Si vous avez l'intention d'utiliser PostgreSQL à partir de machines sur un sous-réseau différent, vous avez besoin d'une entrée dans le fichier _pg_hba.conf_ pour chaque sous-réseau. +

    + +3. Décommentez les entrées suivantes dans le fichier de configuration situé à C:\\Program Files\\PostgreSQL\\9.5\\data\\postgresql.conf en supprimant les premiers "#", et en changeant les valeurs à "off" comme indiqué ci-dessous. +
    +> fsync = off
    +> synchronous_commit = off
    +> full_page_writes = off
    +
    +En image, modifiez ce qui suit, de ceci: +

    +\image html postgresqlinstall5.PNG +

    +A cela: +

    +\image html postgresqlinstall6.PNG +

    +Notez la suppression du symbole d'entête - ceci annule la mise en commentaire de cette entrée. +

    + +4. Toujours dans "C:\Program Files\PostgreSQL\9.5\data\postgresql.conf", trouvez l'entrée nommée _max_connections_ et définissez-la avec le nombre de connexions suggérées pour votre configuration. Une règle d'or est d'ajouter 100 connexions pour chaque nœud d'acquisition automatisé et 100 connexions pour chaque nœud d'analyste que vous prévoyez d'avoir dans le réseau. Voir la capture d'écran ci-dessous. +

    +\image html maxConnections.PNG +

    + + + +5. Redémarrez le service via le panneau Services en allant sur _Démarrer_, puis en tapant _services.msc_, et en appuyant sur _Entrer_. Sélectionnez _postgresql-x64-9.5_ dans la liste des services et cliquez sur le lien _Arrêter le service_. Si vous voulez que PostgreSQL s'exécute en tant qu'utilisateur différent (ce n'est pas nécessaire), effectuez cette modification maintenant. Une fois terminé, cliquez sur le lien _Démarrer le service_ comme indiqué dans la capture d'écran ci-dessous. +

    +\image html postgresqlinstall7.PNG +

    + + +\section install_post_test Essai + +Vous pouvez vérifier que PostgreSQL est en cours d'exécution en utilisant soit l'outil _pgAdmin_, soit l'outil _psql_ pour vous connecter au serveur de base de données à partir d'une autre machine sur le réseau. + +Les problèmes courants résultent généralement de: +- Pare-feu bloquant le port (par défaut: 5432) sur le serveur PostgreSQL. +- Compte d'utilisateur de base de données mal configuré ou informations d'identification incorrectes. +- Plage d'adresses IP mal configurée dans le fichier pg_hba.conf. + + +\section install_post_backup Sauvegarde + +Les bases de données et les fichiers de configuration sont stockés à l'emplacement que vous avez choisi lors de l'installation de PostgreSQL (pas de stockage partagé). Vous devez donc sauvegarder ce répertoire périodiquement. + +Pour une installation où les options ont été choisies par défaut, le répertoire se trouve à l'adresse C:\\Program Files\\PostgreSQL\\9.5\\data. + + +*/ diff --git a/docs/doxygen-user_fr/multi-user/installSharedStorage.dox b/docs/doxygen-user_fr/multi-user/installSharedStorage.dox new file mode 100644 index 0000000000..144fe36336 --- /dev/null +++ b/docs/doxygen-user_fr/multi-user/installSharedStorage.dox @@ -0,0 +1,42 @@ +/*! \page install_multiuser_storage_page Configurer le stockage partagé + +\section multiuser_storage Aperçu + +Le cluster aura besoin d'un stockage partagé accessible depuis: +- Les clients Autopsy +- Le serveur Solr (selon la configuration) + +Ce stockage partagé sera utilisé à la fois pour les sources de données et les sorties de cas, vous aurez donc besoin de beaucoup d'espace. + +La configuration spécifique du stockage partagé dépendra du type de partage de fichiers dont vous disposez. Les exemples illustrent le partage de fichiers Windows, Linux Samba ou un NAS utilisant FibreChannel. + +Vous trouverez ci-dessous quelques directives générales à utiliser lors de l'installation et de la configuration. + +\subsection multiuser_storage_req Conditions +- Tous les ordinateurs devront accéder au stockage partagé par le même chemin. Ainsi, tous doivent avoir les mêmes lettres de lecteurs ou être capables de résoudre les mêmes noms d'hôte (pour les chemins UNC). +- Si Solr est exécuté en tant que service Windows, vous devrez probablement utiliser des chemins UNC. Le service n'aura pas accès aux lettres de lecteurs pour les lecteurs montés sur le réseau (comme le partage de fichiers Windows). Si vous possédez un NAS matériel, vous pourrez peut-être utiliser des lettres de lecteurs. +- Les comptes d'utilisateurs exécutés par Autopsy et Solr auront besoin d'autorisations pour lire et écrire sur le stockage partagé. Voir \ref multiuser_users pour obtenir des conseils sur la sélection des comptes utilisateurs et l'enregistrement des informations d'identification. + + +\subsection multiuser_storage_con Considérations +- Vous obtiendrez probablement de meilleures performances en ayant des lecteurs différents pour les entrées (images disque) et les sorties (dossiers de cas). +- Si vous séparez les partages, le partage "entrées" peut être fourni en lecture seule si vous ne souhaitez pas que les clients modifient les sources de données. + + +\subsection multiuser_storage_ex Exemple +- Serveur Windows +- Disques SSD dédiés pour les entrées (sources de données) et les sorties (dossier de cas). +- Chaque lecteur est partagé avec les noms «DataSources» et «Cases». +- Si le serveur ne fait pas partie d'un domaine, des comptes locaux sont créés dessus pour chaque utilisateur qui exécutera Autopsy ou Solr. Chaque compte aura le même mot de passe sur tous les systèmes. +- Si Solr est exécuté en tant que compte NetworkService, accordez l'accès aux partages de l'ordinateur exécutant Solr (c'est-à-dire pas seulement à un utilisateur spécifique). + + +\subsection multiuser_storage_test Essai +- Avant de procéder à la configuration d'autres services, vous devez tester que les ordinateurs peuvent accéder au partage. Les problèmes d'autorisation de partages sont le défi de configuration le plus courant. +- Connectez-vous à un ordinateur qui deviendra éventuellement un client Autopsy en utilisant un compte sous lequel Autopsy fonctionnera. +- Accédez au partage, tel que \\\\autopsy_storage\\Cases. +- Si vous êtes invité à entrer un mot de passe, alors soit: + - Stockez les informations d'identification, comme indiqué dans la section \ref multiuser_users_store. Vous devrez répéter cette procédure sur tous les clients et le serveur Solr. + - Reconfigurez le serveur de stockage partagé si l'invite était due à une erreur. Vous pouvez aussi vous assurer qu'ils ont tous les deux le même mot de passe. + +*/ \ No newline at end of file diff --git a/docs/doxygen-user_fr/multi-user/installSolr.dox b/docs/doxygen-user_fr/multi-user/installSolr.dox new file mode 100644 index 0000000000..ce4b8c7899 --- /dev/null +++ b/docs/doxygen-user_fr/multi-user/installSolr.dox @@ -0,0 +1,322 @@ +/*! \page install_solr_page Installer et configurer Solr + +[TOC] + +\section install_solr_overview Aperçu +Autopsy utilise Apache Solr pour stocker des index de texte de mots clés. Un serveur central est nécessaire dans un cluster multi-utilisateurs pour maintenir et rechercher ces index. + +Un nouvel index de texte est créé pour chaque cas. L'index peut être stocké soit sur un stockage partagé, soit sur le lecteur local du ou des serveurs Solr (une grande quantité de stockage local est requise). + +ZooKeeper intégré à Solr est également utilisé comme service de coordination pour Autopsy. + +Si vous avez déjà installé Solr 4 avec une version précédente d'Autopsy, veuillez consulter la page \ref upgrade_solr8_page pour plus d'informations sur la manière d'ouvrir les anciens cas après la mise à niveau et de migrer les données. + +REMARQUE : ce document suppose que vous exécuterez Solr sur Windows en tant que service. Vous pouvez ne pas l'exécuter en tant que service ou l'exécuter sur une autre plate-forme, mais vous devrez comprendre les étapes de ce document pour y parvenir. + +\section install_solr_prereq Conditions préalables + +Vous aurez besoin de: +
      +
    • Une version 64 bits de Java 8 Runtime Environment (JRE) que vous pourrez trouver sur https://github.com/ojdkbuild/ojdkbuild. (Lien de téléchargement) +
    • Une version Autopsy pré-packagée avec Solr que vous pourrez trouver ici. Cela contient Solr, NSSM pour le faire fonctionner en tant que service, ainsi que les fichiers de configuration de schéma nécessaires. +
    • Une machine accessible en réseau sur laquelle installer Solr. Notez que le processus Solr peut avoir besoin d'écrire sur un lecteur de stockage partagé (si c'est ainsi que vous le configurez) et aura donc besoin des autorisations adéquates. +
    + + +\section install_solr_install Installation de Solr + +\subsection install_solr_jre Installation du JRE + +Solr nécessite un environnement d'exécution Java (JRE), qui peut déjà être installé. Vous pouvez tester cela en exécutant \c "where java" à partir de la ligne de commande. Si vous voyez une sortie similaire aux résultats ci-dessous, vous avez un JRE. + +\image html wherejava.PNG + +Si vous avez besoin du JRE, utilisez le lien figurant dans la section \ref install_solr_prereq ci-dessus pour télécharger le programme d'installation. Acceptez les paramètres par défaut lors de l'installation. + +\subsection install_solr_config Configuration de Solr + +Suivez ces étapes pour configurer Solr: + +
      +
    1. Extrayez l'archive solr-8.6.3.zip de l'emplacement indiqué dans la section \ref install_solr_prereq dans un répertoire de votre choix. Le reste de ce document suppose que l'archive est extraite dans le répertoire \c "C:\solr-8.6.3" . +
    2. Aller dans le répertoire \c "C:\solr-8.6.3\bin" et ouvrez le fichier \c "solr.in.cmd" dans un éditeur de texte. +\image html solr_config_folder.png +
    3. Recherchez chaque "TODO" et spécifiez un chemin valide pour chacun des paramètres de configuration requis. Ces paramètres seront décrits en détail \ref install_solr_params "ci-dessous". + +\image html solr_config_todo.png +
      +\image html solr_config_param.png +
    + +\subsubsection install_solr_params Paramètres de configuration Solr + +Paramètres de configuration requis pour Solr: +
      +
    • JAVA_HOME – chemin d'accès à l'installation du JRE 64 bits. Par exemple \c "JAVA_HOME=C:\Program Files\Java\jre1.8.0_151" ou \c "JAVA_HOME=C:\Program Files\ojdkbuild\java-1.8.0-openjdk-1.8.0.222-1" +
    • DEFAULT_CONFDIR – chemin vers le répertoire de configuration d'Autopsy. Si l'archive Solr a été extraite dans le répertoire \c "C:\solr-8.6.3", alors ce chemin sera \c "C:\ solr-8.6.3\server\solr\configsets\AutopsyConfig\conf". N'incluez pas de guillemets autour du chemin. +
    • SOLR_JAVA_MEM - La taille du tas JVM Solr doit être aussi grande que les ressources de la machine Solr le permettent, au moins la moitié de la RAM totale disponible sur la machine. Une règle empirique serait d'utiliser "set SOLR_JAVA_MEM=-Xms2G -Xmx40G" pour une machine avec 64 Go de RAM, "set SOLR_JAVA_MEM=-Xms2G -Xmx20G" pour une machine avec 32 Go de RAM, et "set SOLR_JAVA_MEM=-Xms2G -Xmx8G" pour une machine avec 16 Go de RAM. Veuillez consulter la \ref install_solr_heap_usage "rubrique dépannage" pour plus d'informations sur l'utilisation du tas Solr et sur les informations de dépannage. +
    • SOLR_DATA_HOME – emplacement où les index Solr seront stockés. Si ce n'est pas configuré, les index seront stockés dans le répertoire \c "C:\solr-8.6.3\server\solr". REMARQUE: pour les cas d'Autopsy composés d'un grand nombre de sources de données, les index Solr peuvent devenir très volumineux (des centaines de Go ou de To), ils devront donc probablement être stockés sur un partage réseau plus important. +
    + +Paramètres de configuration Solr facultatifs: +
      +
    • SOLR_HOST – par défaut, le nom du nœud Solr est "localhost". Si plusieurs nœuds Solr doivent être utilisés dans le cadre d'un SolrCloud, spécifiez le nom d'hôte de l'ordinateur actuel dans la variable SOLR_HOST. +
    + +\subsubsection install_sorl_index_file_loc Emplacement du fichier d'index de texte Solr + +Note importante: les versions précédentes d'Autopsy (Autopsy 4.17.0 et versions antérieures) stockaient les index de texte Solr dans le répertoire de sortie de cas. En conséquence, les index Solr étaient supprimés si un utilisateur supprimait le répertoire de sortie de cas. Solr 8 (c'est-à-dire pour Autopsy 4.18.0 et versions ultérieures) ne stocke plus les fichiers d'index de texte Solr dans le répertoire de sortie du cas, mais les stocke à la place dans un emplacement défini par le paramètre SOLR_DATA_HOME. Par conséquent, si un utilisateur choisit de supprimer manuellement les répertoires de sortie de cas (par exemple, pour libérer de l'espace disque), les répertoires d'index Solr situés dans SOLR_DATA_HOME doivent également être supprimés manuellement. + +L'index de texte pour un cas d'Autopsy suivra une structure de nommage selon les règles suivantes: \c "[nom du cas Autopsy] [Horodatage de la création du cas] [Horodatage de la création de l'index] [shardX_replica_nY]". Par exemple, l'index de texte pour un cas d'Autopsy "Test Case" sera situé dans le répertoire suivant à l'intérieur SOLR_DATA_HOME: + +\image html solr_config_case.png + +\section install_solr_service Installation du service Windows Solr + +À ce stade, Solr a été configuré et est prêt à l'emploi. La dernière étape consiste à le configurer en tant que service Windows afin qu'il démarre à chaque démarrage de l'ordinateur. + +Ouvrez un invite de commande en tant qu'administrateur et accédez au répertoire \c "C:\solr-8.6.3\bin". À partir de là, exécutez la commande suivante: \c "nssm install Solr_8.6.3". + +\image html solr_install_1.png + +Une fenêtre d'interface utilisateur NSSM apparaîtra. Cliquez sur le bouton de navigation "Path": + +\image html solr_install_2.png + +Selectionnez le fichier \c "C:\solr-8.6.3\bin\solr.cmd". REMARQUE: Assurez-vous de ne pas sélectionner le fichier \c "solr.in.cmd" par accident. Dans le paramètre "Arguments", tapez \c "start –f –c": + +\image html solr_install_3.png + +En option, configurez le nom d'affichage du service, le type de démarrage et les informations de compte: + +\image html solr_install_4.png + +\subsection install_solr_service_user Configurer l'utilisateur du service + +Dans la section \ref install_multiuseruser_page, vous avez dû décider sous quel utilisateur exécuter Solr. Pour configurer Solr afin qu'il s'exécute en tant que cet utilisateur, vous utiliserez Windows Service Manager. + +Basculez vers l'onglet "Log On" pour modifier les informations d'identification de connexion pour l'utilisateur choisi qui aura accès au stockage partagé. +
    • Si vous spécifiez un compte de domaine, le nom du compte sera sous la forme \c "DOMAINNAME\username" comme le montre l'exemple ci-dessous
    + +\image html solr_user_1.png + +Cliquez sur \c "Install Service". Vous devriez voir apparaître la fenêtre d'interface utilisateur suivante: + +\image html solr_user_2.png + +\subsection install_solr_start Démarrer le service Solr + +À ce stade, le service Solr a été configuré et est installé. Vous pouvez le vérifier en ouvrant la fenêtre "Services" de Windows: + +\image html solr_start_1.png + +Démarrez le service "Solr_8.6.3" et vérifiez que l'état du service passe à "En cours d'exécution". + +\image html solr_start_2.png + +\section install_solr_testing Essais + +Vous devez effectuer deux tests pour confirmer que la machine Solr est correctement configurée. + +
      +
    • Interface Web: Vous devez essayer d'accéder au panneau d'administration de Solr dans un navigateur Web. Sur la machine Solr, accédez à http://localhost:8983/solr/#/ et vérifiez que la console d'administration Solr s'affiche. Vous devez également essayer d'accéder au panneau d'administration Solr dans un navigateur Web à partir d'une autre machine du réseau. Remplacez "localhost" dans l'URL précédente par l'adresse IP ou le nom d'hôte sur lequel le service Solr s'exécute. + +\image html solr_testing_1.png + +Si le service est correctement démarré mais que vous ne pouvez pas voir la capture d'écran ci-dessus, il se peut que le port 8983 pour Solr et le port 9983 pour ZooKeeper soient bloqués par votre pare-feu. Contactez votre administrateur réseau pour ouvrir ces ports. + +
    • Stockage partagé: Connectez-vous à l'ordinateur Solr en tant qu'utilisateur avec lequel vous avez décidé d'exécuter le service Solr et essayez d'accéder aux chemins de stockage partagé. Assurez-vous que vous pouvez accéder aux chemins UNC (ou aux lettres de lecteur si vous avez un NAS matériel). Si tout est configuré correctement, vous devriez pouvoir accéder aux chemins de stockage sans avoir à fournir d'informations d'identification. Si vous êtes invité à saisir un mot de passe pour accéder au stockage partagé, saisissez le mot de passe et choisissez d'enregistrer les informations d'identification ou modifiez la configuration afin que les mêmes mots de passe soient utilisés. Voir la rubrique \ref multiuser_users_store concernant les étapes de stockage des informations d'identification. Si vous avez besoin de stocker les informations d'identification, vous devez redémarrer le service ou redémarrer l'ordinateur (nous avons observé qu'un service en cours d'exécution n'obtient pas les informations d'identification mises à jour). +
    + +\section install_solr_autopsy Configuration des clients Autopsy + +Une fois les services configuré, vous allez \ref install_multiuserclient_page "configurer Autopsy pour activer les cas multi-utilisateurs". Pour le serveur Solr 8, configurez le service Solr 8 et les informations de connexion du service ZooKeeper. Les informations de connexion ZooKeeper sont requises. Le numéro de port ZooKeeper est égal au numéro de port du service Solr plus 1000. Par défaut, le port du service Solr est 8983, ce qui rend le port intégré à ZooKeeper égal à 9983. Vous pouvez également utiliser un \ref install_solr_standalone_zk "service autonome ZooKeeper". + +\section install_sorl_adding_nodes Ajout de plus de nœuds Solr (SolrCloud) + +Solr 8 permet à plusieurs nœuds Solr de fonctionner ensemble en tant que cluster Solr. Dans ce mode (mode SolrCloud), chaque collection/index Solr est réparti sur tous les nœuds Solr disponibles. C'est ce qu'on appelle le sharding. Par exemple, s'il y a 4 nœuds Solr dans un cluster SolrCloud, l'index de texte sera divisé entre les 4 nœuds Solr, réduisant ainsi considérablement la charge sur chaque serveur Solr individuel et améliorant les performances d'indexation et de recherche Solr. + +Pour créer un cluster Solr, vous devez suivre les étapes suivantes: +
      +
    1. Suivez les étapes des sections \ref install_solr_config et \ref install_solr_service pour créer un nœud Solr (par exemple "Solr1"). Démarrez le service Solr sur la machine Solr1. Cette machine hébergera le service ZooKeeper pour le cluster SolrCloud. +
    2. Pour ajouter un nœud Solr supplémentaire (par exemple "Solr2") au cluster SolrCloud, suivez les étapes des sections \ref install_solr_config et \ref install_solr_service sur la machine Solr2. Ne démarrez pas encore le service Solr sur Solr2. +
    3. Solr utilise ZooKeeper pour sa coordination interne, donc tous les nœuds Solr dans le SolrCloud doivent pointer vers la même instance du service ZooKeeper. Par conséquent, pour que le nœud Solr2 fasse partie de SolrCloud, il doit utiliser le service ZooKeeper que tous les autres nœuds Solr du cluster SolrCloud utilisent. À l'étape 1, nous avons configuré le nœud Solr1 pour démarrer son service ZooKeeper intégré (il s'agit du comportement par défaut de Solr). Pour y parvenir, le paramètre ZK_HOST sur Solr2 doit être modifié pour pointer vers le service ZooKeeper qui s'exécute sur le nœud Solr1. Le numéro de port ZooKeeper est égal à SOLR_PORT plus 1000. Par défaut, SOLR_PORT est égal à 8983, donc le port ZooKeeper intégré est 9983. Par conséquent, le paramètre ZK_HOST dans le fichier \c "C:\solr-8.6.3\bin\solr.in.cmd" (en supposant que le package Solr ZIP a été extrait dans le répertoire \c "C:\solr-8.6.3\") sur la machine Solr2 doit être modifié pour que le service ZooKeeper utilisé soit exécuté sur Solr1:9983. + +\image html solr_adding_nodes_1.png + +
    4. Démarrez le service Solr sur la machine Solr2. +
    5. Lorsque vous vous connectez à une console d'administration Solr sur Solr1 ou Solr2 (soit en allant sur http://localhost:8983/solr/#/ sur la machine, soit via http://solr1:8983/solr/#/), puis naviguez jusqu'à la section "Cloud" -> "Nodes" de l'arborescence d'administration, vous devriez voir tous les nœuds Solr qui font partie du SolrCloud: + +\image html solr_adding_nodes_2.png + +
    6. Des nœuds Solr supplémentaires peuvent être ajoutés au SolrCloud en répétant les étapes précédentes. +
    + +\section install_solr_autopsy_zk Utilisation du service ZooKeeper par Autopsy + +Autopsy utilise le service ZooKeeper à des fins de coordination multi-utilisateurs. Autopsy utilise ZooKeeper pour verouiller les ressources d'un cas avant de les modifier. Plus important encore, Autopsy stocke certaines de ses données d'état internes dans ZooKeeper - quels cas ont été créés, leur état de traitement (en attente, en traitement ou terminé), ainsi que d'autres données d'état des cas et des tâches. Ceci est particulièrement important si vous exécutez Autopsy en mode "Auto Ingest", car l'acquisition automatisée doit savoir quelles tâches ont déjà été traitées. + +Dans la capture d'écran ci-dessous, Autopsy utilisera le serveur ZooKeeper qui s'exécute sur le serveur Solr 8 (machine "Solr1") à des fins de coordination. + +\image html solr_autopsy_zk.png + +\subsection install_solr_standalone_zk Serveur ZooKeeper autonome + +Lors de nos tests, il n'a pas été nécessaire d'avoir un serveur ZooKeeper autonome avec Autopsy. En cas d'utilisation normale d'Autopsy, il suffit d'utiliser le service ZooKeeper "intégré" qui est démarré par le service Solr (sur le port 9983). Cependant, la documentation d'Apache Solr recommande d'utiliser un service ZooKeeper autonome (s'exécutant sur une machine distincte) dans les environnements de production. Vous trouverez ci-dessous des instructions sur la configuration d'un serveur ZooKeeper autonome et la configuration de Solr et d'Autopsy pour utiliser ce serveur. + +Les étapes générales pour mettre en place ce processus lié à Solr sont décrites dans le guide de l'utilisateur de Solr ci-dessous, dans la section "SolrCloud Configuration and Parameters": + +https://lucene.apache.org/solr/guide/8_6/solrcloud-configuration-and-parameters.html + +
      +
    1. Téléchargez l'installation appropriée de ZooKeeper à partir de http://zookeeper.apache.org/releases.html . Solr 8.6.3 est intégré à Zookeeper 3.5.7. Il existe plusieurs options de téléchargement – binaires ou code source. Le fichier que vous recherchez est \c "apache-zookeeper-3.5.7-bin.tar.gz": +https://archive.apache.org/dist/zookeeper/zookeeper-3.5.7/ +
    2. Extrayez le fichier tar téléchargé contenant l'installation de ZooKeeper +
    3. Créer/éditer le fichier \c "/conf/zoo.cfg" pour avoir les éléments suivants: +
        +
      • Spécifiez le répertoire "dataDir" - c'est là que la base de données ZooKeeper sera stockée. +
      • Spécifiez "clientPort". Par exemple, "clientPort=9983". +
      • "Four letter commands" doit être activé dans le fichier de configuration ZooKeeper: https://lucene.apache.org/solr/guide/8_6/setting-up-an-external-zookeeper-ensemble.html#configuration-for-a-zookeeper-ensemble +
      +
    4. Il existe des scripts de démarrage Windows et Linux pour ZooKeeper. Pour Windows, ouvrez une invite de commande (administrateur NON requis), accédez au répertoire où le fichier tar a été extrait (par exemple, \c "C:\Bitnami\zookeeper-3.5.7"), et tapez \c "bin\zkServer.cmd". Nous avons utilisé Cygwin dans nos tests et nous avons donc utilisé des commandes Linux dans nos exemples. Pour Linux/CygWin, allez dans le même répertoire (par ex. \c "C:\Bitnami\zookeeper-3.5.7"), et tapez \c "bin/zkServer.sh start". +
    5. Pour vérifier que ZooKeeper est en cours d'exécution, dans l'invite de commande, vous pouvez taper \c "bin/zkServer.sh status" (ou une commande Windows équivalente). + +\image html solr_standalone_zk_1.png + +
    6. Pour que Solr utilise un ZooKeeper autonome, les étapes suivantes doivent être effectuées. Accédez au répertoire où se trouvent les scripts de démarrage Solr (généralement \c "C:\solr-8.6.3\apache-solr\bin"). Ouvrez le fichier \c "solr.in.cmd" dans un éditeur de texte. Si le service ZooKeeper autonome s'exécute sur la même machine (non recommandé), modifiez la variable ZK_HOST en \c "set ZK_HOST=localhost:9983". Si ZooKeeper s'exécute sur une machine différente (par exemple, "Solr5"), entrez le nom d'hôte ou l'adresse IP de la machine ZooKeeper au lieu de "localhost" (par exemple, \c "set ZK_HOST=Solr5:9983"). + +\image html solr_standalone_zk_2.png + +
    7. La réinstallation du service Solr n'est pas nécessaire. Arrêtez simplement le service Solr et redémarrez-le. +
    8. Une fois le service Solr redémarré, vous pouvez accéder à la console d'administration Solr (Cloud -> ZK Status) et vérifiez que Solr utilise le bon ZooKeeper et que ZooKeeper est en cours d'exécution. + +\image html solr_standalone_zk_3.png + +
    9. Configurez les options multi-utilisateurs d'Autopsy pour utiliser le serveur autonome ZooKeeper. Démarrez Autopsy et ouvrez le panneau des paramètres multi-utilisateurs à partir de "Tools", "Options", "Multi-user". Notez que pour créer ou ouvrir des cas multi-utilisateurs, "Enable Multi-user cases" doit être coché et les paramètres ci-dessous doivent être corrects. + +\image html solr_standalone_zk_4.png +
    + +\section install_solr_backup Sauvegarde + +Solr crée deux types de données qui doivent être sauvegardées: + +
      +
    • Index de texte: Ceux-ci sont stockés dans le répertoire qui a été spécifié dans le paramètre SOLR_DATA_HOME (voir \ref install_solr_params). +
    • Données ZooKeeper: Autopsy utilise un service appelé ZooKeeper intégré à Solr qui stocke des données sur les cas existants et sur qui les a ouverts. Ces données doivent être sauvegardées afin que vous puissiez avoir une liste de tous les cas multi-utilisateurs disponibles. +
      1. Dans une installation par défaut les données sont stockées dans \c "C:\solr-8.6.3\server\solr zoo_data" (en supposant que le package ZIP de Solr ait été extrait dans le répertoire \c "C:\solr-8.6.3").
      +
    + +\section troubleshooting Dépannage / Optimisation des performances + +\subsection install_solr_delayed_start Problèmes de démarrage retardé avec un grand nombre de collections Solr + +Lors de nos tests, nous avons rencontré des problèmes lorsqu'un très grand nombre (des milliers) de cas Autopsy multi-utilisateurs ont été créés. Chaque nouveau cas multi-utilisateurs Autopsy crée une "collection" Solr qui contient l'index de texte Solr. Avec 2 000 collections existantes, lorsque le service Solr est redémarré, Solr semble "charger" en interne environ 250 collections par minute (par ordre chronologique, en commençant par les collections les plus anciennes). Après 4 minutes, environ la moitié des 2 000 collections étaient chargées. Les utilisateurs peuvent rechercher dans les collections qui ont été chargées, mais ils ne peuvent pas ouvrir ou rechercher dans les collections qui n'ont pas encore été chargées en interne par Solr. Après 7 à 8 minutes, toutes les collections ont été chargées. Ces chiffres varient en fonction de la configuration spécifique du cluster, de l'emplacement du fichier d'index de texte (stockage réseau ou local), du débit du réseau, du nombre de serveurs Solr, etc... + +\subsection install_solr_heap_usage Utilisation du tas Solr et recommandations + +Le tas JVM Solr joue un rôle particulièrement important si vous allez créer un grand nombre de cas Autopsy (c'est-à-dire des collections Solr). Voici quelques "règles empiriques" de statistiques d'utilisation du tas Solr que nous avons identifiées lors de nos tests internes: +
      +
    • Pour les très petits cas/collections, nos tests montrent que Solr utilise un minimum absolu de 7 à 10 Mo de tas par collection. +
    • Pour les cas/collections plus volumineux (taille de E01 en entrée : 50-100 Go), Solr utilise au moins 65 Mo par collection +
    • Pour les cas/collections volumineux (taille de E01 en entrée : 1,5 To) Solr utilise au moins 850 Mo par collection +
    + +\subsubsection install_solr_heap_troublshooting Dépannage des problèmes de tas Solr + +Lorsque la JVM Solr a utilisé tout son tas disponible et est incapable de libérer de la mémoire avec des éliminations de collections, le service Solr ne pourra pas créer de nouvelles collections ou peut complètement ne plus répondre, ce qui empêchera Autopsy de créer de nouveaux index de texte. Vous trouverez ci-dessous une liste de certaines erreurs que vous pourriez voir à la suite de ce problème dans les journaux de service Solr (pas dans les journaux d'Autopsy) et/ou la console d'administration Solr: + +
      +
    • org.apache.solr.common.SolrException: Could not register as the leader because creating the ephemeral registration node in ZooKeeper failed +
    • RequestHandlerBase org.apache.solr.common.SolrException: Failed to get config from zookeeper +
    • RecoveryStrategy Error while trying to recover. org.apache.solr.common.SolrException: Cloud state still says we are leader. +
    • RequestHandlerBase org.apache.solr.common.SolrException: Could not load collection from ZK +
    • org.apache.solr.common.SolrException: Error CREATEing SolrCore: Unable to create core. Caused by: There are no more files +
    • org.apache.solr.common.SolrException: java.io.IOException: There are no more files +
    • org.apache.solr.common.SolrException: Cannot unload non-existent core +
    • ZkIndexSchemaReader Error creating ZooKeeper watch for the managed schema +
    + +Vous pouvez également voir les erreurs ZooKeeper suivantes: +
      +
    • org.apache.zookeeper.KeeperException$NodeExistsException: KeeperErrorCode = NodeExists +
    • org.apache.zookeeper.KeeperException$BadVersionException: KeeperErrorCode = BadVersion for (collection_name)/state.json +
    • org.apache.zookeeper.KeeperException$SessionExpiredException: KeeperErrorCode = Session expired for /roles.json +
    • org.apache.zookeeper.KeeperException$SessionExpiredException: KeeperErrorCode = Session expired for /configs/AutopsyConfig/managed-schema +
    + +Le thème commun à la plupart de ces erreurs est la rupture de la communication entre Solr et ZooKeeper, en particulier lors de l'utilisation d'un serveur ZooKeeper intégré. Il est important de noter que ces erreurs peuvent potentiellement se produire pour d'autres raisons et ne sont pas propres aux problèmes de tas Solr. + +\subsubsection install_solr_monitoring Surveillance de l'utilisation du tas Solr + +Le moyen le plus simple de voir l'utilisation actuelle du tas Solr est de consulter la page Web de la console d'administration Solr. Pour accéder à la console d'administration Solr, sur la machine Solr, accédez à http://localhost:8983/solr/#/ . Vous pourrez y voir l'utilisation de la mémoire Solr: + +\image html solr_config_monitoring.png + +Cependant, le tableau de bord ne montre pas suffisamment de détails pour savoir quand Solr est à court de tas, il ne doit donc être utilisé que pour identifier que vous n'avez PAS de problèmes de tas. Même si le tableau de bord indique que le tas Solr est entièrement utilisé, cela peut être un problème ou non. Il est préférable d'utiliser des outils de profilage comme Java VisualVM. Pour que VisualVM se connecte à Solr, vous devez activer l'interface JMX pour le processus Java de Solr. Les détails sont décrits ici : +
    • https://solr.apache.org/guide/8_3/using-jmx-with-solr.html#using-jmx-with-solr
    + +Le tas Solr et d'autres réglages de performances sont décrits dans l'article suivant: +
    • https://cwiki.apache.org/confluence/display/SOLR/SolrPerformanceProblems
    + +\subsubsection install_solr_performance_tuning Remarques sur le réglage des performances de Solr + +Si vous envisagez de travailler avec des images volumineuses (de plusieurs To) et que les performances de KWS sont importantes, la meilleure approche consiste à utiliser un serveur Solr en réseau (multi-utilisateurs). + +Quelques notes: +
      +
    • Un seul serveur Solr fonctionne bien pour les sources de données jusqu'à 1 To ; après cela, ses performances commencent à ralentir. Les performances ne "chutent pas", mais elles continuent de ralentir à mesure que vous ajoutez plus de données à l'index. Après 3 To de données d'entrée, les performances de Solr diminuent considérablement. + +
    • Un seul serveur Solr multi-utilisateur peut ne pas fonctionner beaucoup mieux qu'un cas Autopsy mono-utilisateur. Cependant, en mode multi-utilisateurs, vous pouvez ajouter des serveurs Solr supplémentaires et créer un cluster Solr. Voir la rubrique \ref install_sorl_adding_nodes dans la documentation ci-dessus. Ces nœuds supplémentaires sont une source des gains en performances, en particulier pour les sources de données d'entrée volumineuses. La documentation Apache Solr appelle ce mode "SolrCloud" et chaque serveur Solr est appelé un "shard". Plus vous avez de serveurs/shards Solr, meilleures sont les performances pour les grands ensembles de données. Sur nos clusters de test et de production, nous utilisons 4 à 6 serveurs Solr pour gérer des ensembles de données allant jusqu'à 10 To, ce qui semble être la limite la plus haute. Après cela, il vaut mieux diviser votre cas Autopsy en plusieurs cas, créant ainsi un index Solr distinct pour chaque cas. + +
    • Lors de nos tests, un SolrCloud à 3 nœuds indexe les données environ deux fois plus vite qu'un seul nœud Solr. Un SolrCloud à 6 nœuds indexe les données presque deux fois plus vite qu'un SolrCloud à 3 nœuds. Après cela, nous n'avons pas vu beaucoup de gain de performance. Ces chiffres de performances dépendent fortement du débit du réseau, des ressources de la machine, de la vitesse d'accès au disque et du type de données indexées. + +
    • Les recherches de correspondance exacte sont beaucoup plus rapides que les recherches de sous-chaîne ou d'expression régulière. + +
    • Les recherches Regex ont tendance à utiliser beaucoup de RAM sur le serveur Solr. + +
    • L'indexation/la recherche d'espace non alloué ralentit vraiment tout, car il s'agit principalement de données binaires ou tronquées. + +
    • Si vous n'allez pas consulter les résultats de la recherche tant que l'acquisition n'est pas terminée, vous devez désactiver les recherches périodiques par mot-clé. Elles commenceront à prendre plus de temps au fur et à mesure que vos données d'entrée augmenteront. Cela peut être fait via le menu Tools->Options->Keyword Search: + +\image html solr_disable_periodic_search.png + +
    • En mode mono-utilisateur, si vous exécutez une acquisition et indexez des sources de données de plusieurs To, la mémoire d'Autopsy et en particulier la mémoire JVM Solr doivent être augmentées par rapport aux paramètres par défaut. Cela peut être fait via le menu Tools->Options->Application. Nous recommandons une taille de tas d'au moins 10 Go pour Autopsy et une taille de tas d'au moins 6 à 8 Go pour Solr. Notez qu'il s'agit des valeurs "maximum" que le processus sera autorisé à utiliser/demander. Le système d'exploitation n'allouera pas plus de tas que le processus n'en a réellement besoin. + +\image html solr_jvm.png + +
    + +\subsection solr_commit_tuning Réglage des opérations de validation du serveur Solr + +Lorsque Autopsy s'exécute dans un environnement de cluster multi-utilisateurs avec plusieurs nœuds d'acquisition automatique, il peut être intéressant de régler la configuration des opérations de validation de Solr. + +Solr a deux types de validations : les validations "dures" ("hard commits") et les validations "souples" ("soft commits"). Celles-ci sont expliquées en détail sur la page suivante: https://lucidworks.com/post/understanding-transaction-logs-softcommit-and-commit-in-sorlcloud/ + +En bref: +
      +
    • Les validations "dures" transferent les documents nouvellement indexés de la RAM vers l'index Solr, sur le disque. +
    • En fonction de la configuration, les validations "dures" peuvent rendre les documents nouvellement indexés "visibles" ou non pour la recherche. +
    • Les validations "souples" ne transfèrent pas les documents nouvellement indexés sur le disque, mais ils les rendent "visibles" pour la recherche. +
    + +Par défaut (lors de l'utilisation d'AutopsyConfig), les serveurs Solr effectuent une validation "dure" toutes les 5 minutes et rendent également les documents nouvellement indexés "visibles" pour la recherche. Ces opérations peuvent être coûteuses en ressources lorsqu'elles sont effectuées sur un index volumineux situé sur un lecteur réseau partagé. Dans cette situation, il peut être très intéressant de modifier la configuration de Solr (située dans \c "REPERTOIRE_INSTALLATION_SOLR\server\solr\configsets\AutopsyConfig\conf\solrconfig.xml") avec les changements suivantes : +
      +
    1. Modifiez les validations "dures" pour transférer systématiquement les documents nouvellement créés toutes les 5 minutes sans les rendre "visibles". Ceci peut être fixé en définissant "openSearcher" sur "false" dans la section "autoCommit" du fichier de configuration Solr. +
    2. Activez les validations "souples" à effectuer toutes les 30 minutes, rendant ainsi les documents nouvellement indexés "visibles" pour une recherche toutes les 30 minutes. Ceci peut être fixé en activant la section "autoSoftCommit" du fichier de configuration Solr. L'inconvénient est que la recherche du dernier document peut prendre jusqu'à 30 minutes. Gardez à l'esprit que cela n'a d'incidence que dans le cas où un analyste recherche un dossier alors que l'acquisition est toujours en cours. Autopsy effectue automatiquement une validation une fois l'acquisition terminée afin que tous les documents soient immédiatement visibles à ce moment-là. +
    + +L'image suivante montre les modifications de configuration de Solr décrites ci-dessus: + +\image html solr_config_autocommit.jpg + +Jusqu'à ce qu'une validation "dure" soit effectuée, par défaut Solr maintient également un journal des transactions qui contient le texte brut de chaque document nouvellement indexé depuis la dernière validation "dure". Lorsque l'index Solr est situé sur un partage réseau, cela peut à nouveau être une opération très coûteuse en ressources. Les journaux de transactions peuvent être désactivés en commentant la section "updateLog" du fichier de configuration Solr: + +\image html solr_comment_out_updateLog.jpg + +Notez bien cependant que cela a pour effet secondaire de créer des erreurs CommitTracker dans les journaux Solr et dans la console d'administration Solr. Ces erreurs peuvent être ignorées si le journal des transactions a été intentionnellement désactivé. + +\image html solr_transaction_log_errors.jpg + + +*/ diff --git a/docs/doxygen-user_fr/multi-user/installSystems.dox b/docs/doxygen-user_fr/multi-user/installSystems.dox new file mode 100644 index 0000000000..a83a2a7366 --- /dev/null +++ b/docs/doxygen-user_fr/multi-user/installSystems.dox @@ -0,0 +1,45 @@ +/*! \page install_multiuser_systems_page Choisissez votre configuration matérielle / VM + +\section multiuser_system Aperçu + +La première étape de la configuration d'un cluster multi-utilisateur consiste à choisir le nombre d'ordinateurs ou de machines virtuelles que vous utiliserez pour exécuter les différents services. + +Du point de vue des services, vous devrez exécuter: +- Serveur de base de données PostgeSQL +- Serveur d'indexation de texte Apache Solr +- Serveur de messagerie ActiveMQ +- Stockage en réseau + +Vous pouvez exécuter chacun d'entre eux sur leur propre machine virtuelle dédiée, mais ce n'est pas nécessaire. + +Apache Solr utilise beaucoup de mémoire, nous vous recommandons donc de la conserver seule, sauf si vous utilisez le partage de fichiers Windows pour le stockage partagé. Vous pouvez obtenir de meilleures performances avec Solr s'il écrit sur le stockage local plutôt que sur le réseau. Vous pouvez donc envisager d'utiliser le même ordinateur pour Solr et le stockage partagé. + +Notez également que, étant donné que tous les ordinateurs doivent accéder au stockage partagé par le même chemin, vous ne pouvez pas mélanger les systèmes d'exploitation. + + +Nous recommandons: + +- Serveur 1: PostgreSQL et ActiveMQ + - Ces deux services sont relativement faibles consommateurs de ressources. +- Serveur 2: Apache Solr et Stockage partagé (si vous utilisez le partage de fichiers Windows). + + +\subsection multiuser_system_hw Matériel suggéré + +- PostgreSQL/ActiveMQ (Serveur 1): + - RAM: 16 Go minimum + - Stockage local: SSD à 500 Go + +- Solr (Serveur 2): + - RAM: 32 Go minimum + - Stockage local: Un index unique aura à peu près la taille de la source de données analysée. Par exemple, 128 Go de données E01 génère généralement un index de 128 Go. + +\subsection multiuser_system_back Sauvegardes + +Vous aurez beaucoup de données importantes sur le système. Assurez-vous que les éléments suivants soient régulièrement sauvegardés: +- Stockage partagé (qui contient les données des cas et les index de texte) +- Bases de données sur le serveur PostgreSQL (voir \ref install_post_backup) +- Données Zookeeper sur le serveur Solr (voir \ref install_solr_backup) + + +*/ diff --git a/docs/doxygen-user_fr/multi-user/installUsers.dox b/docs/doxygen-user_fr/multi-user/installUsers.dox new file mode 100644 index 0000000000..c78dce4b47 --- /dev/null +++ b/docs/doxygen-user_fr/multi-user/installUsers.dox @@ -0,0 +1,87 @@ +/*! \page install_multiuseruser_page Choisissez vos comptes utilisateurs + +\section multiuser_users Aperçu + +Avant de vous lancer dans la configuration des ordinateurs, vous devez savoir quels comptes d’utilisateurs seront utilisés. Les autorisations de compte utilisateur sont l'un des défis les plus courants que les gens rencontrent lors de la configuration d'un cluster. + +Il y a deux profils majeures à prendre en compte concernant les utilisateurs: +- L'utilisateur pour Autopsy. +- L'utilisateur du service Solr. + +Ces utilisateurs sont importants car ils auront besoin d'accéder au stockage partagé sans devoir être invité à entrer un mot de passe. D'autres services, tels que PostgreSQL et ActiveMQ, peuvent s'exécuter en tant que compte de service par défaut car ils n'utilisent que le stockage local. + +Le choix que vous faites ici dépendra du type de plate-forme de stockage partagé que vous utilisez et du type d'infrastructure Windows dont vous disposez. + + +\subsection multiuser_users_autopsy Utilisateur d'Autopsy + +Le compte d'utilisateur sous lequel Autopsy s'exécute devra accéder au stockage partagé. Il existe trois options générales: + +- Comptes de domaine: Si le cluster se trouve sur un domaine Windows, Autopsy peut être exécuté avec un compte de domaine. + - Si votre stockage partagé est un partage de fichiers Windows, les utilisateurs devraient pouvoir y accéder sans avoir besoin d'un mot de passe. + - Si votre stockage partagé est une autre plate-forme, vous devrez probablement forcer Windows à stocker les informations d'identification de stockage partagé (comme décrit ci-dessous). +- Comptes locaux uniques: Certains clusters ne sont pas sur un domaine Windows et ont des comptes uniques pour chaque analyste/utilisateur. + - Si votre stockage partagé est un partage de fichiers Windows, les utilisateurs n'auront pas besoin de saisir leur mot de passe SI le même nom d'utilisateur et le même mot de passe existent sur le serveur de partage de fichiers. + - Sinon, vous devrez forcer Windows à stocker les informations d'identification. +- Compte local partagé: Enfin, certains clusters utilisent un seul compte local, comme celui nommé "autopsy" pour tous les utilisateurs. Cela n'est pas recommandé car Autopsy utilise le nom de connexion pour savoir qui a effectué certaines actions, telles que le marquage de fichiers. + - Les mêmes règles de mot de passe s'appliquent ici que dans le scénario précédent. Soit avoir le même mot de passe sur tous les systèmes, soit forcer Windows à stocker les mots de passe. + + +\subsection multiuser_users_solr Service Solr + +Solr fonctionnera en tant que service Windows et peut avoir besoin d'accéder au stockage partagé s'il ne dispose pas de suffisamment de stockage local. Solr fonctionne mieux lorsqu'il dispose d'un accès rapide au stockage, il est donc préférable de conserver les index sur les disques SSD locaux. Cependant, certains clusters devront stocker les index sur le même stockage partagé que celui utilisé pour les images et autres sorties de cas. + +REMARQUE: Autopsy 4.17.0 (ainsi que les versions précédentes) exigeait que les index soient stockés sur les lecteurs de stockage partagés. A partir de la version 4.18.0 (qui utilise maintenant Solr 8) Autopsy peut utiliser le stockage local ou partagé. + +Si vous utilisez le stockage local pour Solr, vous pouvez exécuter le service Solr en tant que "LocalService". + +Si vous envisagez d'utiliser le stockage réseau pour Solr, vous avez trois options: +- NetworkService: Si vous êtes sur un domaine, vous pourrez peut-être exécuter Solr en tant que compte "NetworkService". Ce compte a accès au réseau, mais le défi peut être d'accorder l'accès de ce compte au stockage partagé. + - Si votre stockage partagé est un partage de fichiers Windows, vous devrez accorder l'accès au compte de l'ordinateur exécutant Solr comme suit: +
    1. Faites un clic droit sur le dossier de stockage partagé, choisissez "Propriétés" et sélectionnez l'onglet "Sécurité". +
    2. Cliquez sur le bouton "Modifier ..." puis sur le bouton "Ajouter ...". +
    3. Cliquez sur le bouton "Types d'objets" et confirmez que le type d'objet "Ordinateurs" est coché. + \image html objectTypesComputers.PNG +
    4. Entrez le nom de l'ordinateur et cliquez sur le bouton "Vérifier les noms" pour confirmer qu'il est correct. + \image html grantAccessToComputer.PNG +
    5. Assurez-vous que le compte de l'ordinateur dispose à la fois d'un accès en lecture et en écriture au stockage partagé. + \image html sharedStoragePermissions.PNG
    + - Pour un autre stockage partagé, vous ne pourrez peut-être pas accéder aux données du compte NetworkService. +- Utilisateur normal: Si vous n'êtes pas sur un domaine ou ne pouvez pas accorder l'accès à l'ordinateur pour le stockage partagé, exécutez Solr en tant qu'utilisateur normal (local ou domaine). + - Si vous faites cela, reportez-vous aux scénarios décrits ci-dessus pour choisir un utilisateur Autopsy. Les mêmes règles s'appliqueront en ce qui concerne les mots de passe et l'enregistrement des informations d'identification. + - Le principal inconvénient est que le service doit être mis à jour lorsque le mot de passe du compte change et qu'il peut être nécessaire d'informer les autres clients sur le nouveau mot de passe. +- LocalService: Enfin, si vous utilisez le même serveur pour Solr et le stockage partagé, il est possible d'exécuter Solr en tant que "LocalService" par défaut car il n'a pas besoin d'un accès réseau. + + + + +\section multiuser_users_store Stockage des informations d'identification + +En fonction de votre stockage partagé et de votre choix ci-dessus pour les comptes d'utilisateurs, vous devrez peut-être forcer chaque ordinateur Windows à stocker les informations d'identification pour le stockage partagé. Par exemple, si votre stockage partagé est un système basé sur Linux. + + +Pour stocker les informations d'identification sur un ordinateur donné, nous accédons simplement au stockage partagé. Windows nous demandera un mot de passe et nous choisissons l'option pour enregistrer les informations d'identification. Nous allons répéter cela sur chaque ordinateur pour chaque compte utilisateur et en utilisant à la fois le nom d'hôte et l'adresse IP du stockage. Si deux analystes utilisent le même ordinateur client Autopsy et qu'ils ont leurs propres comptes, vous devrez le faire pour les deux utilisateurs. + +- Lancez l'Explorateur Windows et saisissez le chemin UNC du stockage partagé à l'aide de l'adresse IP, telle que "\\10.10.152.211\Cases". Appuyez sur Entrée. +

    +\image html urlInAddressbar.PNG +

    + +- Si le dossier s'ouvre sans vous demander de mot de passe, tout est OK. Si vos informations d'identification sont nécessaires, vous verrez une boîte de dialogue semblable à la suivante: + +

    +\image html credentialsWithDomain.PNG +

    + +- Si votre compte fait partie d'un domaine Windows, ajoutez le domaine dans la case du haut avant le "\". Entrez à la suite votre nom d'utilisateur. Si vous n'avez pas de nom de domaine, utilisez simplement votre nom d'utilisateur sans barres obliques. Ajoutez votre mot de passe dans la case suivante et cochez "Mémoriser mes identifiants", puis cliquez sur "OK". + + +Ensuite, répétez avec le nom d'hôte du stockage partagé. Par example "\\autopsy_storage\Cases". Saisissez à nouveau vos identifiants et choisissez "Mémoriser mes identifiants". + + +Suivez ces étapes pour chaque machine qui accédera au disque partagé. + + +Notez également que vous devrez répéter ce processus lorsque le mot de passe du stockage partagé change. + +*/ diff --git a/docs/doxygen-user_fr/multi-user/multiuser-security.dox b/docs/doxygen-user_fr/multi-user/multiuser-security.dox new file mode 100644 index 0000000000..1f22aab376 --- /dev/null +++ b/docs/doxygen-user_fr/multi-user/multiuser-security.dox @@ -0,0 +1,16 @@ +/*! \page multiuser_sec_page Sécurité des cas multi-utilisateurs + +\section mulit_sec_overview Aperçu +Cette page décrit les protections de sécurité qui existent dans un déploiement de cas multi-utilisateurs afin que vous puissiez protéger les données sensibles. Un déploiement multi-utilisateur doit se trouver dans un réseau privé pour garantir que seuls les utilisateurs autorisés peuvent accéder aux données. Les sites distants doivent se connecter aux services centraux via un VPN. + +- Stockage central: il est de votre responsabilité d'utiliser les autorisations basées sur les dossiers pour restreindre l'accès aux dossiers des cas. Un utilisateur doit être capable de lire et d'écrire dans les dossiers des cas pour ouvrir un cas via Autopsy. Il contient l'index Solr, la sortie des modules, les journaux et les rapports. +- Base de données centrale: PostgreSQL prend en charge l'authentification via un login et un mot de passe. Chaque client Autopsy doit être configuré avec un nom d'utilisateur et un mot de passe PostgreSQL. C'est à vous de décider s'il existe un nom d'utilisateur et un mot de passe unique pour l'ensemble du laboratoire ou si vous allez en configurer un différent pour chaque client. +- Centrale Solr: Solr n'a pas besoin d'un nom d'utilisateur ou d'un mot de passe pour se connecter et interroger sa base de données. Il existe un moyen facultatif de configurer Solr pour les exiger, mais nous n'avons pas encore essayé cela. +- Service de messagerie: ActiveMQ peut être configuré pour exiger un nom d'utilisateur et un mot de passe. Tout comme la base de données centrale, c'est à vous de décider s'il y a un seul nom d'utilisateur et mot de passe ou un pour chaque client. + +Étant donné que le serveur Solr ne restreint pas l'accès au contenu indexé, +vous devez déployer ces services dans un réseau qui ne permet l'accès qu'aux utilisateurs +autorisés. Les versions futures permettront une protection supplémentaire +des données sensibles. + +*/ \ No newline at end of file diff --git a/docs/doxygen-user_fr/multi-user/upgradeSolr8.dox b/docs/doxygen-user_fr/multi-user/upgradeSolr8.dox new file mode 100644 index 0000000000..8855c20e03 --- /dev/null +++ b/docs/doxygen-user_fr/multi-user/upgradeSolr8.dox @@ -0,0 +1,90 @@ +/*! \page upgrade_solr8_page Mise à niveau vers Autopsy 4.18.0 (avec Solr 8) + +[TOC] + +Autopsy 4.18.0 (et versions supérieures) créera de nouveaux cas avec Solr 8 au lieu de Solr 4. Puisque Solr 8 n'est pas rétrocompatible avec Solr 4, cela aura un certain impact pour vous. Notamment: + +- Les cas réalisés avec Autopsy 4.17.0 et versions antérieures continueront à utiliser les index Solr 4 et pourront être ouverts avec Autopsy 4.18.0+ +- Les cas réalisés avec Autopsy 4.18.0 et versions ultérieures utiliseront Solr 8 et ne peuvent pas être ouverts par Autopsy 4.17.0 et versions antérieures. +Le principal avantage est que vous pouvez ouvrir des cas plus anciens, mais de nouveaux cas ne peuvent pas être ouverts par des logiciels plus anciens. + +Si vous utilisez des cas mono-utilisateur, vous n'avez rien d'autre à faire. Autopsy est livré avec Solr 4 et 8 intégrés. + +Si vous utilisez un cluster multi-utilisateurs, vous devrez installer un nouveau serveur Solr 8 et choisirez peut-être de conserver également Solr 4. + + +\section solr8_upgrade_cluster Options de cluster multi-utilisateurs + +Il y a deux éléments à prendre en compte lors de la conversion ascendante d'un cluster multi-utilisateur: +- Quelles versions de serveurs Solr exécuter +- Où stocker les données ZooKeeper + +Les sections suivantes couvrent ces sujets plus en détail. + +\subsection solr8_upgrade_cluster_solr Plusieurs serveurs Solr + +Vous souhaiterez probablement que les serveurs Solr 4 et 8 soient en cours d'exécution afin de pouvoir ouvrir des cas plus anciens. Si tel est le cas, alors: +- Obtenez un nouveau serveur et installez Solr 8 dessus en utilisant les instructions de la page \ref install_solr_page. +- Configurez chaque client Autopsy pour avoir les adresses des deux serveurs (voir ci-dessous). + +Si vous ne voulez avoir que Solr 8, suivez simplement les instructions pour Solr 8 et débarrassez-vous du serveur Solr 4. Vous ne pourrez pas ouvrir de cas plus anciens. Il est possible de mettre à jour les index Solr, mais nous ne l'avons pas testé. + + +Pour configurer Autopsy afin de pouvoir se connecter à la fois aux serveurs multi-utilisateurs Solr 8 et Solr 4, démarrez Autopsy et ouvrez le panneau des paramètres multi-utilisateurs depuis "Tools", "Options", "Multi-user". Notez que pour créer ou ouvrir des cas multi-utilisateurs, "Enable Multi-user cases" doit être coché et les paramètres ci-dessous doivent être corrects. + +Il est recommandé d'exécuter les serveurs Solr 8 et Solr 4 sur des machines distinctes. Dans l'exemple ci-dessous, le serveur Solr 8 s'exécute sur une machine avec le nom d'hôte "Solr1" et le serveur Solr 4 s'exécute sur une machine avec le nom d'hôte "Solr6". + +\image html solr_running_in_parallel.png + +Une fois que les informations de connexion aux serveurs multi-utilisateurs Solr 8 et Solr 4 sont entrées et enregistrées, Autopsy pourra ouvrir les cas multi-utilisateurs Solr 8 (Autopsy version 4.18.0 et ultérieure), ainsi que les anciens cas multi-utilisateurs Solr 4 existants (cas créés avec les versions 4.17.0 et antérieures d'Autopsy). + +IMPORTANT: Le bouton "Test Connection" ne vérifie pas à quelle version de Solr Autopsy se connecte. Il vérifie uniquement que Autopsy se connecte à un serveur Solr et est capable de recevoir une réponse. Par conséquent, il est important que l'utilisateur entre des informations de connexion au serveur correctes dans les champs appropriés. + +Si vous avez l'intention d'exécuter les serveurs Solr 4 et Solr 8 sur la même machine en même temps, vous devez changer le port du service Solr 8 en utilisant le paramètre SOLR_PORT dans \c "C:\solr-8.6.3\bin\solr.in.cmd" (en supposant que le fichier ZIP du package Solr ait été extrait dans le répertoire \c "C:\solr-8.6.3\"). Par défaut, le service Solr démarre sur le port 8983. + +\subsection install_solr_zk_migration Migration des données ZooKeeper + +Outre l'indexation de texte, le service Solr stocke également des données de "coordination" à l'aide d'Apache ZooKeeper. Vous pourrez déplacer ces données si vous vous débarrassez de votre serveur Solr 4. Ces données vous permettent de: +- Savoir quels cas multi-utilisateurs vous pouvez ouvrir +- Savoir quelles images de disque ont déjà été traitées par l'acquisition automatique + +Vous pouvez continuer à utiliser votre instance Solr 4 de ZooKeeper, mais nous avons également un utilitaire qui vous permet de migrer les données vers un nouveau serveur, tel que celui exécutant Solr 8 (ou une instance autonome). + +Dans notre exemple, nous allons migrer les données ZooKeeper d'un serveur ZooKeeper fonctionnant sur un serveur Solr 4 (sur la machine "Solr6") vers un tout nouveau serveur ZooKeeper fonctionnant sur un serveur Solr 8 (sur la machine "Solr1"). + +Vous pouvez parcourir les données ZooKeeper existantes si vous accédez à la machine Solr6 et ouvrez la console d'administration Solr (http://localhost:8983/solr/#/). Dans la console d'administration Solr, accédez à "Cloud"-> "Tree", et développez la section "autopsy" de l'arborescence: + +\image html solr_zk_migration_1.png + +Vous pouvez suivre les mêmes étapes pour parcourir les données ZooKeeper sur le nouveau serveur Solr 8 (sur la machine "Solr1"). Si Autopsy n'a pas encore été utilisé avec ce serveur, le dossier "autopsy" sera manquant, comme dans l'exemple ci-dessous: + +\image html solr_zk_migration_2.png + +L'utilitaire de migration ZooKeeper (ZookeeperNodeMigration.jar) se trouve dans le répertoire \c "C:\Program Files\(version actuelle d'Autopsy)\autopsy\ZookeeperNodeMigration": + +\image html solr_zk_migration_3.png + +L'utilitaire ZookeeperNodeMigration nécessite les entrées suivantes: +
      +
    • Saisie de l'adresse IP ou du nom d'hôte de Zookeeper +
    • Saisie du numéro de port de Zookeeper +
    • Sortie de l'adresse IP ou du nom d'hôte de Zookeeper +
    • Sortie du numéro de port de Zookeeper +
    + +Par exemple, si vous exécutez la commande suivante à partir de la ligne de commande, les nœuds Zookeeper seront copiés du serveur Zookeeper sur Solr6:9983 vers le serveur Zookeeper sur Solr1:9983: + +> java -jar ZookeeperNodeMigration.jar Solr6 9983 Solr1 9983 + +\image html solr_zk_migration_4.png + +Si Java n'est pas installé sur la machine, vous pouvez utiliser la version packagée de Java qui est distribuée avec Autopsy. Par example: + +> \c "C:\Program Files\Autopsy-4.18.0\jre\bin\java.exe" -jar ZookeeperNodeMigration.jar Solr6 9983 Solr1 9983 + +Pour vérifier que les données ZooKeeper ont été copiées du serveur Solr6 vers le serveur Solr1, actualisez la console d'administration Solr sur la machine Solr1. Vous devriez maintenant voir le répertoire "autopsy", ainsi que son contenu, lorsque vous accédez à la section "Cloud" -> "Tree" de la console d'administration Solr: + +\image html solr_zk_migration_5.png + + +*/ diff --git a/docs/doxygen-user_fr/object_detection.dox b/docs/doxygen-user_fr/object_detection.dox new file mode 100644 index 0000000000..0421c75e42 --- /dev/null +++ b/docs/doxygen-user_fr/object_detection.dox @@ -0,0 +1,30 @@ +/*! \page object_detection_page Object Detection (Détection d'objets) + +[TOC] + + +\section object_overview Aperçu + +Le module "Object Detection" utilise OpenCV pour essayer de détecter des objets dans les images. + +\ref experimental_page doit être activé pour exécuter ce module. + +\section object_setup Installation + +Pour commencer, vous aurez besoin de quelques classificateurs, qui sont des fichiers xml. Autopsy ne peut pas créer de classificateurs - effectuez une recherche sur le Web pour "train OpenCV classifiers" pour trouver des informations sur la création de classificateurs, ou visitez la page OpenCV. + +Une fois que vous avez votre ensemble de classificateurs, copiez-les dans le dossier "object_detection_classifiers" de votre répertoire utilisateur Autopsy. Sous Windows, cela se trouve normalement dans "C:\Users\\AppData\Roaming\Autopsy". Si vous ne trouvez pas le répertoire, essayez d'exécuter le module comme décrit dans la section suivante. Le message d'avertissement vous indiquera où le module s'attend à ce que les classificateurs soient stockés. + +\image html object_detection_classifier_dir.PNG + +\section object_running Exécution du module d'acquisition + +Vous pouvez exécuter le module de détection d'objets en l'activant lors de l'exécution des modules d'acquisition. Aucune configuration supplémentaire n'est nécessaire. Si vous n'avez ajouté aucun classificateur ou si vous avez mis les classificateurs au mauvais endroit, vous verrez une info-bulle d'avertissement. + +\image html object_detection_warning.PNG + +Tous les fichiers contenant des objets détectés apparaîtront sous "Objects Detected". L'arborescence des résultats montrera quels classificateurs correspondaient à chaque image. + +\image html object_detection_results.PNG + +*/ \ No newline at end of file diff --git a/docs/doxygen-user_fr/performance.dox b/docs/doxygen-user_fr/performance.dox new file mode 100644 index 0000000000..0189ce319c --- /dev/null +++ b/docs/doxygen-user_fr/performance.dox @@ -0,0 +1,19 @@ +/*! \page performance_page Optimiser les performances + +Après avoir installé Autopsy, nous vous suggérons de faire plusieurs paramétrages en fonction de votre matériel pour optimiser les performances: + +1. Nombre de threads: modifiez le nombre de pipelines parallèles utilisés au moment de l'exécution. La valeur par défaut est de deux pipelines, mais cela peut être augmenté si vous utilisez un système avec plusieurs cœurs. Pour faire ça: + - Exécutez Autopsy à partir du menu Démarrer ou du bureau + - Lorsque l'écran de démarrage de création de cas est présenté, annulez/fermez la fenêtre + - Sélectionnez "Tools", "Options" + - Dans le panneau "Ingest" et dans l'onglet "Settings", il y a une liste déroulante "Number of threads to use for file ingest". La valeur maximale est la même que le nombre de processeurs sur votre système (jusqu'à quatre). Le nombre de threads d'acquisition ne peut pas être défini au-dessus de quatre. Les tests ont révélé que, pour la plupart des systèmes et des configurations, après quatre threads, la machine est de toute façon liée aux E/S, et augmenter ce nombre au-delà de quatre peut en fait réduire les performances. + - Après chaque modification, redémarrez Autopsy pour que ce paramètre prenne effet. + +

    +\image html threadcount.PNG +

    + +2. Lorsque vous créez un cas, utilisez différents lecteurs pour stocker le cas et les images. Cela permet de lire et d'écrire simultanément un maximum de données. + +3. Nous avons obtenu de meilleures performances en utilisant des disques SSD ou un stockage SAN fibré. +*/ \ No newline at end of file diff --git a/docs/doxygen-user_fr/personas.dox b/docs/doxygen-user_fr/personas.dox new file mode 100644 index 0000000000..bf48631be4 --- /dev/null +++ b/docs/doxygen-user_fr/personas.dox @@ -0,0 +1,109 @@ +/*! \page personas_page Personas (Personnages) + +[TOC] + +\section personas_overview Aperçu + +Autopsy peut stocker et organiser les informations de compte en fonction des "Personas", qui représentent une identité en ligne. Une personne peut avoir plusieurs identités en ligne et donc plusieurs "Personas". À titre d'exemple, une seule personne peut avoir un ensemble de comptes qui publient en ligne sur l'amour des chats et un autre ensemble de comptes semblant sans rapport et publiant sur la haine des chats. + +\section personas_concepts Concepts + +Voici quelques concepts de base sur ces "Personas": +
      +
    • Pour créer un "Persona", vous devez avoir un nom et au moins un compte. +
    • Un "Persona" peut avoir plusieurs comptes - un numéro de téléphone, un e-mail, un compte Facebook, un compte Skype, etc... +
    • Les "Personas" portent sur les cas et sont donc stockées dans le \ref central_repo_page "Référentiel central". +
    • Vous pouvez créer manuellement un "Persona" ou en créer un en fonction d'une entrée du carnet de contacts, d'un journal d'appels ou d'un message. +
    • Un compte peut faire partie de plusieurs "Personas". Cela peut se produire si quelqu'un utilise le même numéro de téléphone portable de récupération pour les comptes de plusieurs personnes. +
    • Un "Persona" peut être associé à des métadonnées supplémentaires sous forme de paires nom/valeur. +
    • Un "Persona" peut avoir un ou plusieurs alias. +
    • Autopsy vous montrera si un compte fait partie d'un "Persona", le cas échéant. +
    + +Les "Personas" sont stockées dans le référentiel central en fonction des comptes trouvés dans les résultats. Ces résultats sont générés par divers modules d'acquisition tels que \ref recent_activity_page et \ref android_analyzer_page. + +Autopsy fournit un outil dédié, le \ref personas_editor "Personas Editor", pour créer, afficher, modifier et supprimer des "Personas". + +\section personas_editor Personas Editor (Editeur de "Personas") + +Le "Personas Editor" est chargé via le menu Tools -> Personas. + +Le panneau de gauche du "Personas Editor" est un tableau qui répertorie les "Personas", en fonction des critères sélectionnés. Le panneau de droite affiche les détails du personnage actuellement sélectionné dans le panneau de gauche. + +Par défaut, lorsque l'éditeur de "Personas" est lancé, tous les "Personas" du référentiel central sont répertoriés dans le tableau. Vous pouvez filtrer cette liste en cochant la case "Filter personas by Keyword". Tapez un nom de personne ou un identifiant de compte dans la zone de texte et sélectionnez le bouton radio "Name" ou "Account" de manière appropriée. Cliquez ensuite sur le bouton "Show" pour n'afficher que les "Personas" qui correspondent aux critères de filtrage. + +\image html Personas/personas_main.png + +\subsection personas_create Créer des "Personas" + +Pour créer un nouveau "Persona", cliquez sur le bouton "New Persona". Une boîte de dialogue "Create Persona" apparaîtra. Voici une description de chaque champ: + +
      +
    • Name: Le nom du personnage +
    • Created by: Sera automatiquement renseigné avec de nom de l'utilisateur actuel +
    • Created on: Sera automatiquement renseigné après avoir enregistré le "Persona" +
    • Comment: Une description du personnage +
    • Accounts: Au moins un compte appartenant au "Persona" +
    • Metadata: (Facultatif) Paires de données nom/valeur liées au "Persona" +
    • Aliases: (Facultatif) Tous les alias pour ce "Persona" +
    • Cases found in: Sera automatiquement renseigné lors de la modification d'un "Persona" +
    + +Chaque "Persona" a besoin d'au moins un compte qui lui est associé. Ces comptes doivent avoir été préalablement enregistrés dans le \ref central_repo_page "référentiel central". Cliquez sur "Add" sous "Accounts" pour ouvrir une autre boîte de dialogue avec quatre champs, tous obligatoires: + +
      +
    • Identifier: L'identifiant du compte (numéro de téléphone, adresse e-mail, identifiant de compte Facebook, etc...) +
    • Type: Le type d'identifiant +
    • Confidence: Degré de confiance générale sur le fait que ce compte va avec le "Persona" donné +
    • Justification: Pourquoi ce compte est ajouté au "Persona" +
    + +\image html Personas/personas_create.png + +Lorsque vous avez terminé d'ajouter au moins un compte et de remplir les champs requis, cliquez sur OK pour créer le "Persona". Un "Persona" avec le nom spécifié sera créé et associé au(x) compte(s) spécifié(s). + +\subsection personas_edit Modifier les "Personas" + +Pour modifier un "Persona", cliquez sur le bouton "Edit Persona". Vous pourrez modifier toutes les données sur le "Persona". + +\image html Personas/persona_edit.png + +\subsection personas_delete Supprimer des "Personas" + +Pour supprimer un "Persona", sélectionnez ce dernier dans le tableau et cliquez sur le bouton "Delete Persona". Cliquez sur "Yes" dans la fenêtre de confirmation pour supprimer le "Persona" sélectionné. + +\subsection personas_account_create Créer un compte + +Tous les "Personas" doivent être associés à au moins un compte. Normalement, ces comptes seront ajoutés au référentiel central par divers modules d'acquisition, mais vous pouvez également les créer manuellement avec le bouton "Create Account". + +\image html Personas/personas_create_account.png + +\section personas_artifact_viewers Intégration de "Persona" dans les visionneuses de contenu + +Autopsy montre les "Personas" associés aux comptes, le cas échéant. Lors de l'affichage des résultats de contacts, de journal des appels et de messages, Autopsy affiche les "Personas" associés aux comptes dans ces panneaux. Si aucun "Persona" n'existe pour un compte, Autopsy fournit un bouton permettant à l'utilisateur d'en créer un. + +Comme indiqué ci-dessous, lorsque vous affichez le résultat d'un contact, vous pouvez voir les données personnelles. Lorsqu'un ou plusieurs "Personas" sont trouvés associés aux comptes dans le résultat, le nom du "Persona" est affiché dans la visionneuse de contenu du contact. Il y aura un bouton "View" pour voir les détails du "Persona". + +\image html Personas/personas_contact_found.png + +Si aucun "Persona" correspondant n'est trouvé, un bouton "Create" s'affiche pour créer un "Persona" pour le(s) compte(s). Cela vous amènera au panneau \ref personas_create "Create Personas" avec le(s) compte(s) déjà ajouté(s), en supposant que des comptes existent dans le référentiel central. Si le compte souhaité n'apparaît pas, fermez le panneau des "Personas", puis copiez le compte dans le presse-papiers, soit en mettant en surbrillance le compte et en appuyant sur contrôle + c, soit en faisant un clic droit dessus et en sélectionnant "Copy". Puis allez sur Tools->Personas pour ouvrir l'éditeur de "Personas", et cliquez sur "Create Account". Collez les éléments copiés dans le compte et sélectionnez le type, puis validez avec OK. Fermez maintenant l'éditeur et cliquez à nouveau sur "Create". Le compte doit maintenant être rempli automatiquement. + +\image html Personas/personas_contact_not_found.png + +Les "Personas" sont intégrés de la même manière dans la visionneuse de contenus pour les journaux d'appels et les messages/e-mails. + +\image html Personas/personas_calllog.png +
    +\image html Personas/personas_message.png + +\section personas_cvt Intégration de "Personas" dans l'outil de visualisation des communications + +Les "Personas" sont intégrées à la visionneuse \ref communications_page. Lorsque vous affichez des comptes dans la partie "Accounts" de l'outil de visualisation des communications, les informations de "Personas" associés sont affichées dans l'info-bulle si vous survolez le compte. + +\image html Personas/personas_cvt_hover.png + +Comme dans la fenêtre principale d'Autopsy, vous pouvez également créer ou afficher des "Personas" lors de l'examen des contacts, des journaux d'appels et des messages dans l'outil de visualisation des communications. + +\image html Personas/personas_cvt_accounts.png + +*/ \ No newline at end of file diff --git a/docs/doxygen-user_fr/photorec_carver.dox b/docs/doxygen-user_fr/photorec_carver.dox new file mode 100644 index 0000000000..915a71152e --- /dev/null +++ b/docs/doxygen-user_fr/photorec_carver.dox @@ -0,0 +1,96 @@ +/*! \page photorec_carver_page PhotoRec Carver (Carving PhotoRec) + +[TOC] + + +\section photorec_overview Aperçu + +Le module "PhotoRec Carver" effectue des recherches par carving de fichiers à partir de l'espace non alloué dans la source de données et envoie les fichiers trouvés dans la chaîne de traitement des modules d'acquisition. + +Cela peut aider un analyste à découvrir plus d'informations sur les fichiers qui se trouvaient auparavant sur l'appareil et qui ont été supprimés par la suite. Ce sont simplement des fichiers supplémentaires qui ont été trouvés dans des parties "vides" du stockage de l'appareil. + + +\section photorec_usage Utilisation du module + +Cochez la case dans l'écran des paramètres des modules d'acquisition ("Configure Ingest Modules") pour activer PhotoRec Carver. Assurez-vous que "All Files, Directories and Unallocated Space" est sélectionné. + +\subsection photorec_settings Paramètres d'intégration + +Les paramètres d'exécution de ce module vous permettent de choisir "Keep corrupted files"(conserver les fichiers corrompus) et "Focus on certain file types" (inclure ou d'exclure certains types de fichiers). + +\image html photo_rec_settings.PNG + +Pour l'option "Focus on certain file types", vous entrerez une liste de types de fichiers séparés par des virgules. Selon l'option que vous choisissez, PhotoRec n'effectuera des recherches par carving que sur les fichiers de ces types ("Include only the specified types") ou sur tous les fichiers à l'exception de ces types ("Exclude the specified types"). Vous verrez une erreur si un type non valide est entré. Notez que les types de fichiers sont sensibles à la casse. + +\image html photo_rec_extensions.png + +La liste des \ref photorec_extensions "types de fichiers valides" pour la version actuelle d'Autopsy se trouve au bas de cette page. + +\subsection photorec_results Voir les résultats + +Les résultats de la recherche par carving apparaissent dans l'arborescence de la source de données appropriée avec l'en-tête "$CarvedFiles". + +\image html photorec_output.PNG + +Les types sélectionnés apparaissent également dans la section "Views", "File Types" de l'arborescence, selon le type de fichier. + +\section photorec_custom Signatures de fichier personnalisées +Pour ajouter des signatures de fichier personnalisées, créez un fichier (s'il n'existe pas) photorec.sig dans le répertoire de base de l'utilisateur (par exemple - /home/john/photorec.sig, ou C:\\Users\john\photorec.sig). Le fichier photorec.sig doit contenir une expression par ligne. +Par exemple, pour détecter le fichier foo.bar qui a pour signature d'en-tête - 0x4141414141414141, ajouter une expression + + bar 0 0x4141414141414141 +dans le fichier photorec.sig où *bar* est l'extension du fichier, *0* est l'offset de la signature, et *0x4141414141414141* est la signature. Ajoutez une autre expression sur une nouvelle ligne pour détecter un autre type personnalisé de fichier en fonction de sa signature. Notez que les signatures personnalisées ne peuvent pas être utilisées avec l'option "Focus on certain file types". + +\image html photo_rec_custom.png + +\section photorec_extensions Types de fichiers valides + +Voici la liste des types de fichiers valides pour la version de PhotoRec actuellement utilisée par Autopsy: + +\verbatim +1cd caf dwg gp2 max pdb rw2 vfb +3dm cam dxf gp5 mb pdf rx2 vib +7z catdrawing e01 gpg mcd pds sav vmdk +a cdt eCryptfs gpx mdb pf save vmg +ab che edb gsm mdf pfx ses wallet +abr chm elf gz mfa plist sgcta wdp +acb class emf hdf mfg plr shn wee +accdb comicdoc ess hdr mft plt sib wim +ace cow evt hds mid png sit win +ado cp_ evtx hfsp mig pnm skd wks +afdesign cpi exe hm mk5 prc skp wld +ahn crw exs hr9 mkv prd snag wmf +aif csh ext http mlv prt snz wnk +all ctg fat ibd mobi ps sp3 woff +als cwk fbf icc mov psb sparseimage wpb +amd d2s fbk icns mov/mdat psd spe wpd +amr dad fcp ico mp3 psf spf wtv +apa dar fcs idx mpg psp sqlite wv +ape dat fdb ifo mpl pst sqm x3f +apple DB fds imb mrw ptb steuer2014 x3i +ari db fh10 indd msa ptf stl x4a +arj dbf fh5 info mus pyc studio xar +asf dbn fit iso mxf pzf swf xcf +asl dcm fits it MYI pzh tar xfi +asm ddf flac itu myo qbb tax xfs +atd dex flp jks nd2 qdf tg xm +au diskimage flv jpg nds qkt tib xml +axp djv fm jsonlz4 nes qxd tif xpt +axx dmp fob kdb njx r3d TiVo xsv +bac doc fos kdbx nk2 ra torrent xv +bdm dpx fp5 key nsf raf tph xz +bim drw fp7 ldf oci rar tpl z2d +bin ds2 freeway lit ogg raw ts zcode +binvox DS_Store frm lnk one rdc ttf zip +bkf dsc fs logic orf reg tx? zpr +blend dss fwd lso paf res txt +bmp dst gam luks pap rfp tz +bpg dta gct lxo par2 riff v2i +bvr dump gho lzh pcap rlv vault +bz2 dv gi lzo pcb rm vdi +c4d dvi gif m2ts pct rns vdj +cab dvr gm* mat pcx rpm veg + +\endverbatim + +*/ \ No newline at end of file diff --git a/docs/doxygen-user_fr/plaso.dox b/docs/doxygen-user_fr/plaso.dox new file mode 100644 index 0000000000..574a475391 --- /dev/null +++ b/docs/doxygen-user_fr/plaso.dox @@ -0,0 +1,22 @@ +/*! \page plaso_page Plaso + +[TOC] + + +Plaso est un framework pour l'exécution de modules ayant pour but d'extraire les horodatages de différents types de fichiers. Le module d'acquisition Plaso exécute Plaso pour générer des événements qui sont affichés dans la \ref timeline_page d'Autopsy. Pour plus d'informations sur Plaso, voir la documentation. + +\section plaso_config Exécution du module + +Le module d'acquisition Plaso exécute des dizaines d'analyseurs individuels et peut prendre beaucoup de temps à s'exécuter. Lors des tests, les analyseurs les plus lents étaient de loin winreg, pe, et chrome_cache. chrome_cache est toujours désactivé car il duplique les événements créés par le module \ref recent_activity_page. Vous pouvez choisir d'activer les modules winreg et pe sur le panneau de configuration des modules d'acquisition ("Configure Ingest Modules"). + +\image html plaso_config.png + +Plaso ne fonctionnera que sur des sources de données de type \ref ds_img "image disque". + +\section plaso_results Voir les résultats + +Les événements Plaso seront présentés dans la \ref timeline_page. Notez que les événements créés par Plaso ne sont pas affichés dans l'\ref tree_viewer_page. + +\image html plaso_timeline.png + +*/ \ No newline at end of file diff --git a/docs/doxygen-user_fr/portable_case.dox b/docs/doxygen-user_fr/portable_case.dox new file mode 100644 index 0000000000..84ee528aaf --- /dev/null +++ b/docs/doxygen-user_fr/portable_case.dox @@ -0,0 +1,81 @@ +/*! \page portable_case_page Cas portables + +[TOC] + + +\section portable_case_overview Aperçu + +Un cas portable est une copie partielle d'un cas d'Autopsy normal qui peut être ouvert de n'importe où. Il contient un sous-ensemble des données du cas d'origine et a été conçu pour faciliter le partage des données pertinentes avec d'autres analystes. Les cas portables contiendront un rapport \ref report_case_uco détaillant le contenu du cas portable. + + +Le cas d'utilisation général est le suivant: +
      +
    1. Alice analyse une ou plusieurs sources de données à l'aide d'Autopsy. Elle balise les fichiers et les résultats qui présentent un intérêt particulier. +
    2. Alice souhaite partager ses découvertes avec Bob mais est incapable de lui envoyer les sources de données originales car il ne doit pas les voir ou les originaux sont trop gros. +
    3. Alice crée un cas portable qui ne contiendra que ses fichiers et résultats marqués, ainsi que tous les fichiers associés à ces résultats, et l'envoie à Bob. Elle pourrait également choisir d'inclure des \ref interesting_files_identifier_page "fichiers intéressants" ou des résultats. +
    4. Bob peut ouvrir le cas portable dans Autopsy et afficher tous les fichiers et résultats marqués par Alice, et exécuter l'une des fonctionalités normales d'Autopsy. +
    + +Par exemple, le cas original d'Alice pourrait ressembler à ceci: + +\image html portable_case_original_version.png + +La version portable pourrait ressembler à ceci: + +\image html portable_case_portable_version.png + +Alice n'a marqué que huit fichiers et résultats et son cas ne contenait aucun élément intéressant, de sorte que la plupart du contenu original n'est plus dans le cas. Certaines sources de données ne comportaient aucun élément balisé, elles ne sont donc pas du tout incluses. La structure de tous les fichiers balisés est préservée - vous pouvez voir que l'image balisée dans la capture d'écran est toujours au même emplacement, mais les fichiers non marqués ont disparu. Notez que bien que même si les images originales (telles que "image1.vhd") apparaissent dans l'arborescence, leur contenu n'est pas inclus dans le cas portable. + +\section portable_case_creation Créer un cas portable + +Un cas portable peut contenir des fichiers marqués ainsi que des résultats et des données de la section "Interesting Items" de l'\ref tree_viewer_page. Vous pourrez choisir parmi les ensembles d'éléments intéressants ceux que vous souhaitez inclure dans le cas portable. + +\image html portable_case_interesting_items.png + +Vous pouvez baliser tous les fichiers supplémentaires que vous souhaitez inclure dans le cas portable. Voir la page \ref tagging_page pour plus de détails sur la création de balises. Notez que les contours des \ref image_tagging "images marquées" seront également visibles dans le cas portable. Vous pouvez voir les balises que vous avez ajoutées dans l'\ref tree_viewer_page. + +\image html portable_case_tags.png + +Les cas portables sont créés grâce la fonctionnalité \ref reporting_page. La boîte de dialogue "Generate Report" affiche une liste de toutes les balises et ensembles de fichiers intéressants qui sont utilisés dans le cas actuel et vous pouvez choisir ceux que vous souhaitez inclure. En bas, vous pouvez choisir de compresser éventuellement le cas dans une archive et d'inclure l'application Autopsy. Choisir de compresser le cas sans segmentation compressera simplement le cas portable dans une archive unique qui peut être extraite avec des programmes de compression courants. Si vous choisissez de diviser le cas compressé en plusieurs fichiers, vous devrez utiliser l'option "Unpack and Open Portable Case" pour l'ouvrir. Vous ne pouvez pas inclure l'application si vous utilisez cette option. La décompression d'un cas portable sera abordé dans la section suivante. + +Si le destinataire du cas portable n'a pas Autopsy, vous pouvez choisir d'inclure l'application dans le cas portable. Cela permettra au destinataire d'ouvrir le cas portable sans installer aucun autre logiciel. Vous pouvez choisir de compresser le cas sans le découper. Si vous le faites, le destinataire devra le décompresser avant d'ouvrir Autopsy. + +Le cas portable sera placé dans le dossier "Reports" du cas en cours. + +\image html portable_case_report_panel.png + +Ici vous pouvez voir un cas portable non compressé. Il sera nommé avec le nom de cas d'origine plus "(Portable)". Il manque initialement de nombreux dossiers Autopsy normaux dans un cas portable - ceux-ci seront créés la première fois qu'un utilisateur l'ouvrira. Cela commencera cependant par un dossier "Reports" contenant un fichier de rapport \ref report_case_uco généré automatiquement. + +\image html portable_case_folder.png + +Si vous avez compressé le cas portable mais n'avez pas choisi de le diviser en morceaux, vous aurez un seul fichier .zip. Si vous avez choisi de fractionner le cas, vous aurez un ou plusieurs fichiers commençant par l'extension .zip.001. + +\image html portable_case_chunks.png + +\section portable_case_usage Utilisation d'un cas portable + +Si l'application Autopsy était incluse dans le cas portable, elle peut être ouverte en double-cliquant sur le fichier "open.bat". + +\image html portable_case_open_bat.png + +Sinon, vous commencerez par ouvrir l'application Autopsy. Les cas portables non compressés peuvent être ouverts comme n'importe quel autre cas via Case->Open Case. Si votre cas portable est compressé, vous devrez utiliser l'option de décompression pour l'ouvrir. Ouvrez le menu "Case", puis sélectionnez "Unpack and Open Portable Case". Cela fera apparaître une boîte de dialogue dans laquelle vous pouvez accéder à votre cas compressé et sélectionner où l'extraire. Le cas s'ouvrira également. Notez que toutes les modifications apportées au cas à ce stade seront enregistrées dans l'emplacement décompressé, et la prochaine fois que vous l'ouvrirez, vous devrez accéder au dossier décompressé. + +\image html portable_case_unpackage.png + +Les cas portables se comportent généralement comme n'importe quel autre cas d'Autopsy. Vous pouvez exécuter des modules d'acquisition, effectuer des recherches par mot-clé, utiliser la visionneuse "Timeline", etc... Notez bien que si les noms des sources de données d'origine apparaissent dans le cas, les sources de données elles-mêmes n'ont pas été copiées dans le cas portable. + +\image html portable_case_empty_image.png + +Cela peut provoquer des messages d'avertissement ou d'erreur lors de l'utilisation de modules d'acquisition qui s'exécutent sur l'image complète, tels que le module \ref data_source_integrity_page. Vous ne pourrez pas non plus afficher les sources de données dans la visionneuse de contenu. + +Vous pouvez également ajouter des sources de données supplémentaires au cas portable si vous le souhaitez. Le cas ne sera plus portable, mais si vous le souhaitez, vous pouvez générer un nouveau cas portable qui comprendra les fichiers et résultats marqués des nouvelles sources de données, comme dans le cas d'origine. + +\section portable_case_inside À l'intérieur d'un cas portable + +Un cas portable est un dossier, comme n'importe quel autre cas d'Autopsy. Il contient une base de données SQLite (tout comme un cas d'Autopsy normal) avec des lignes uniquement pour les éléments que l'utilisateur a sélectionné pour apparaître dans le cas portable. Par exemple, si un utilisateur a marqué un fichier et l'a inclus dans le cas portable, la base de données aura une ligne pour la balise, une ligne pour le fichier, une ligne pour le système de fichiers dans lequel se trouvait ce fichier, une ligne pour le système de volume , une ligne pour l'image, etc... Tout ce qui est associé à la balise est là et vous devriez voir ces éléments dans Autopsy. + +Une copie de tout fichier balisé est faite dans le dossier de cas et la base de données SQLite y fait référence. Cela vous permet d'examiner le contenu du fichier sans la source de données d'origine. + +Étant donné qu'un cas portable n'est en réalité qu'un sous-ensemble du cas d'origine, presque toutes les autres opérations d'Autopsy fonctionnent normalement. + +*/ diff --git a/docs/doxygen-user_fr/quick_start_guide.dox b/docs/doxygen-user_fr/quick_start_guide.dox new file mode 100644 index 0000000000..e232ccb7bc --- /dev/null +++ b/docs/doxygen-user_fr/quick_start_guide.dox @@ -0,0 +1,148 @@ +/*! \page quick_start_guide Guide de démarrage rapide + +[TOC] + + +\section s1 Cas et sources de données + +Autopsy organise les données par cas. Chaque cas peut avoir une ou plusieurs sources de données, qui peut être une image disque, un ensemble de fichiers logiques, un périphérique connecté via USB, etc... + +Les cas peuvent être mono-utilisateur ou multi-utilisateurs. Les cas multi-utilisateurs permettent à plusieurs analystes d'examiner les données en même temps et de collaborer, mais nécessitent la configuration de serveurs open source supplémentaires. + +Lorsque vous disposez de plusieurs sources de données et que vous décidez de créer un cas, considérez les faits suivants: +- Vous ne pouvez ouvrir qu'un seul cas à la fois +- Les rapports sont générés au niveau du cas +- L'application peut ralentir lorsqu'il y a de nombreuses sources de données volumineuses dans le même cas + +\subsection s1a Créer un cas +Pour créer un cas, utilisez soit l'option "Create New Case" sur l'écran de bienvenue, soit à partir du menu "Case". Cela lancera l'assistant de création d'un nouveau cas. Vous devrez lui fournir le nom du cas et un répertoire dans lequel stocker les résultats du cas. Vous pouvez éventuellement fournir le numéro de dossier et le nom de l'analyste. + +\subsection s1b Ajouter une source de données +L'étape suivante consiste à ajouter une source de données d'entrée au cas. L'assistant d'ajout d'une source de données démarre automatiquement une fois le cas créé ou vous pouvez le démarrer manuellement à partir du menu "Case" ou de la barre d'outils. Vous devrez choisir le type de source de données à ajouter (image, disque local ou fichiers et dossiers logiques). Ensuite, indiquez-lui l'emplacement de la source à ajouter. + + +- Pour une image disque, accédez au premier fichier image (Autopsy trouvera le reste des fichiers). Autopsy prend actuellement en charge les fichiers E01 et raw (dd). +- Pour un disque local, sélectionnez l'un des disques détectés. Autopsy ajoutera la vue actuelle du disque au cas (c'est-à-dire un instantané des méta-données). Cependant, le contenu des fichiers individuels (pas les métadonnées) est mis à jour avec les modifications apportées au disque. Vous pouvez éventuellement créer une copie de toutes les données lues à partir du disque local vers un fichier VHD, ce qui peut être utile pour les situations de triage. Remarquez bien que vous devrez peut-être exécuter Autopsy en tant qu'administrateur pour détecter tous les disques. +- Pour les fichiers logiques (un seul fichier ou dossier de fichiers), utilisez le bouton "Add" pour ajouter au cas un ou plusieurs fichiers ou dossiers de votre système. Les dossiers seront ajoutés de manière récursive au dossier. + +Ensuite, Autopsy vous demandera de configurer les Ingest Modules (modules d'acquisition). + + +\subsection s1c Ingest Modules (modules d'acquisition) + +Les modules d'acquisition sont chargés de l'analyse du contenu de la source de données et s'exécuteront en arrière-plan. Les modules d'acquisition analysent les fichiers dans un ordre de priorité afin que les fichiers situés dans le répertoire d'un utilisateur soient analysés avant les fichiers dans d'autres dossiers. Il existe des modules d'acquistion tiers qui peuvent être ajoutés à Autopsy. + +Les modules d'acquisition standard inclus avec Autopsy sont: +- \subpage recent_activity_page extrait l'activité de l'utilisateur telle qu'elle est enregistrée par les navigateurs Web et le système d'exploitation. Exécute également "Regripper" sur les ruches de la Base de registre. +- \subpage hash_db_page utilise des ensembles de hachage pour ignorer les fichiers connus du NIST NSRL et signaler les fichiers défavorablement connus. Utilisez le bouton "Global Settings" pour ajouter et configurer les ensembles de hachage à utiliser pendant ce processus. Vous obtiendrez des informations sur les accès aux fichiers défavorablement connus au fur et à mesure de l'acquisition. Vous pouvez ultérieurement ajouter des ensembles de hachage via le menu Tools -> Options dans l'interface utilisateur principale. Vous pouvez télécharger un index du NIST NSRL à partir de http://sourceforge.net/projects/autopsy/files/NSRL/ +- \subpage file_type_identification_page détermine les types de fichiers en fonction de leurs signatures et les regroupe en fonction de leur type MIME. Il stocke les résultats dans le Blackboard et de nombreux modules en dépendent. Il utilise la bibliothèque open source Tika. Vous pouvez définir vos propres types de fichiers personnalisés dans Tools, Options, File Types. +- \subpage extension_mismatch_detector_page utilise les résultats du module "File Type Identification" et marque les fichiers dont l'extension n'est pas traditionnellement associée au type de fichier détecté. Ignore les fichiers "connus" (NSRL). Vous pouvez personnaliser les types MIME et les extensions de fichier par type MIME dans Tools, Options, File Extension Mismatch. +- \subpage embedded_file_extractor_page ouvre les fichiers ZIP, RAR, ainsi que d'autres formats d'archive, DOC, DOCX, PPT, PPTX, XLS et XLSX et renvoie les fichiers intégrés dans ces derniers via la chaîne d'acquisition pour analyse. +- \subpage EXIF_parser_page extrait les informations EXIF des fichiers JPEG et publie les résultats dans l'arborescence de l'interface utilisateur principale. Convertit également les fichiers HEIC/HEIF au format JPEG et extrait les données EXIF de ces JPEG. +- \subpage keyword_search_page utilise des listes de mots clés pour identifier les fichiers contenant des mots spécifiques. Vous pouvez sélectionner les listes de mots clés pour faire des recherches automatisées et vous pouvez créer de nouvelles listes à l'aide du bouton "Global Settings". Notez que la recherche par mot-clé vous permet toujours d'effectuer des recherches une fois l'acquisition terminée. Les mots clés inclus dans les listes que vous avez sélectionnées lors de l'acquisition seront recherchés à intervalles réguliers et vous obtiendrez les résultats en temps réel. Vous n'avez pas besoin d'attendre que tous les fichiers soient indexés avant d'effectuer une recherche par mot-clé, mais vous n'obtiendrez que les résultats ressortant de fichiers qui ont déjà été indexés lorsque vous effectuez votre recherche. +- \subpage email_parser_page identifie les fichiers Thunderbird MBOX et les fichiers au format PST en fonction des signatures de fichiers, en extrayant les e-mails, et en ajoutant les résultats au Blackboard. +- \subpage encryption_page recherche les fichiers chiffrés. +- \subpage interesting_files_identifier_page recherche des fichiers et des répertoires en fonction des règles spécifiées par l'utilisateur dans Tools, Options, Interesting Files. Il fonctionne comme un "module d'alerte" de fichier. Il génère des messages dans la boîte de notification lorsque des fichiers spécifiés sont trouvés. +- \subpage cr_ingest_module ajoute des hachages de fichiers et d'autres propriétés extraites à un référentiel central pour une future corrélation et pour marquer les fichiers notables précédemment analysés. +- \subpage photorec_carver_page effectue du carving de fichiers sur l'espace non alloué et les envoie à travers la chaîne de traitement des fichiers. +- \subpage vm_extractor_page extrait les données des fichiers de machine virtuelle. +- \subpage data_source_integrity_page calcule une somme de contrôle sur les fichiers E01 et la compare avec la somme de contrôle interne du fichier E01 pour s'assurer qu'elles correspondent. +- \subpage drone_page extrait les données des fichiers de drone. +- \subpage plaso_page utilise Plaso pour créer des évènements de la \ref timeline_page "Timeline" (Chronologie). +- \subpage yara_page utilise un ensemble de règles Yara pour rechercher dans les fichiers des modèles textuels ou binaires. +- \subpage android_analyzer_page et \subpage aleapp_page vous permet d'analyser les éléments classiques de systèmes Android. Place des artefacts dans le BlackBoard. +- \subpage ileapp_page extrait les données des sources de données iOS. +- \subpage gpx_page extrait les données de géolocalisation des fichiers .gpx. + +Lorsque vous sélectionnez un module, vous aurez la possibilité de modifier ses paramètres. Par exemple, vous pouvez configurer les listes de recherche de mots clés à utiliser lors de l'acquisition et les ensembles de hachage à utiliser. Reportez-vous à l'aide de chaque module pour plus de détails sur leurs configurations. + +Pendant que les modules d'acquisition s'exécutent en arrière-plan, vous verrez une barre de progression en bas à droite. Vous pouvez utiliser l'interface graphique pour examiner les résultats au fur et à mesure de l'analyse et effectuer d'autres tâches dans le même temps que l'acquisition. + +\section s2 Bases de l'analyse + +Une fois que les modules d'acquisition ont commencé à analyser la source de données, vous verrez l'interface d'analyse principale. Vous pouvez choisir de rechercher des éléments spécifiques, de parcourir des dossiers spécifiques ou de consulter les résultats des modules d'acquisition. + +\image html screenshot.PNG + +Vous commencerez toutes vos opérations d'analyse à partir de l'arborescence de gauche. + +- Le nœud racine Data Sources affiche toutes les données du cas. + - Les nœuds d'image individuels montrent la structure du système de fichiers des images disque ou des disques locaux en fonction de votre cas. + - Les nœuds LogicalFileSet affichent les fichiers logiques dans le cas. +- Le nœud Views affiche les mêmes données sous une perspective différente, par exemple, organisées par type de fichier. +- Le nœud Results affiche la sortie des modules d'acquisition. + +Lorsque vous sélectionnez un nœud dans l'arborescence de gauche, une liste de fichiers s'affiche dans la partie supérieure droite. Vous pouvez utiliser l'onglet Thumbnail en haut gauche pour afficher les images. Lorsque vous sélectionnez un fichier dans cette partie supérieure droite, son contenu s'affiche en bas de la fenêtre. Vous pouvez utiliser les onglets de cette partie inférieure pour afficher le texte du fichier, une image ou les données hexadécimales. + +Si vous affichez des fichiers à partir des nœuds Views et Results, vous pouvez cliquer avec le bouton droit sur un fichier pour accéder à son emplacement dans le système de fichiers. Cette fonctionnalité est utile pour voir ce que l'utilisateur a stocké dans le même dossier que le fichier que vous regardez actuellement. Vous pouvez également cliquer avec le bouton droit sur un fichier pour l'extraire sur le système local. + +Si vous souhaitez rechercher des mots-clés uniques, vous pouvez utiliser la zone de recherche en haut à droite de la fenêtre du programme. Les résultats seront affichés dans un tableau en haut à droite. + +L'arbrorescence à gauche ainsi que le tableau à droite ont une fonction \ref ui_quick_search qui peut être utilisée pour trouver rapidement un nœud visible. + +Vous pouvez marquer (ajouter un signet) les fichiers que vous souhaitez afin de pouvoir les retrouver plus rapidement plus tard ou de les inclure spécifiquement dans un rapport. + +\section s3 Autres interfaces d'analyse + +En plus de l'interface utilisateur à 3 panneaux avec l'arborescence à gauche, il existe d'autres interfaces plus spécialisées. + +\subsection s3b Images/Videos + +Cette galerie d'images se concentre sur l'affichage des images et des vidéos de la source de données organisées par dossier. Elle vous montrera les fichiers dès qu'ils auront été hachés et les données EXIF extraites. Vous pouvez l'ouvrir depuis le menu "Tools" ou via le bouton "Images/Videos" de la barre d'outils. Voir la section \subpage image_gallery_page pour plus de détails. + +\subsection s3c Communications + +L'interface "Communications" se concentre sur l'affichage des comptes avec lesquels les communications ont le plus été effectuées et les messages qui ont été envoyés. Elle vous permet de vous concentrer sur certaines relations ou communications dans une certaine plage de date. Vous pouvez l'ouvrir depuis le menu "Tools" ou via le bouton "Communications" de la barre d'outils. Voir la section \subpage communications_page pour plus de détails. + +\subsection s3d Geolocation (Géolocalisations) + +Le panneau "Geolocation" affiche une carte avec des marqueurs pour tous les résultats de géolocalisation trouvés dans le cas. Vous pouvez l'ouvrir depuis le menu "Tools" ou via le bouton "Geolocation" de la barre d'outils. Voir la section \subpage geolocation_page pour plus de détails. + +\subsection s3a Timeline (Chronologie) + +La fonction "Timeline" peut être ouverte à partir du menu "Tools" ou via le bouton "Timeline" de la barre d'outils. Cela vous permettra de voir le système de fichiers et d'autres événements organisés par heure à l'aide de diverses techniques d'affichage. Voir la section \subpage timeline_page pour plus de détails. + +\subsection s3e Discovery (Découverte) + +Le panneau "Discovery" vous permet de rechercher différents types de données dans un cas et de les afficher sous une forme facilement intelligible. Vous pouvez l'ouvrir depuis le menu "Tools" ou via le bouton "Discovery" de la barre d'outils. Voir la section \subpage discovery_page section pour plus de détails. + +\subsection s3f Personas (Personnages) + +Le panneau "Personas" est pour créer et gérer des "personnages". La création d'un personnage vous permet d'associer un ou plusieurs comptes à un nom et à d'autres données. Vous pouvez l'ouvrir depuis le menu "Tools". Voir la section \subpage personas_page section pour plus de détails. + +\section s5 Exemples de cas d'utilisation +Dans cette section, nous présenterons des exemples sur la façon d'effectuer des tâches d'analyse courantes. + +\subsection s5a Artefacts Web + +Si vous souhaitez afficher l'activité Web récente de l'utilisateur, assurez-vous que le module d'acquisition "Recent Activity" a été activé. +Vous pouvez ensuite aller au niveau du nœud "Results " dans l'arborescence sur le côté gauche de l'interface, puis sur le nœud "Extracted Data". +Là, vous pouvez trouver les signets, les cookies, les téléchargements et l'historique de navigation. + +\subsection s5b Hachages de fichiers défavorablement connus + +Si vous voulez voir si la source de données contient des fichiers défavorablement connus, assurez-vous que le module d'acquisition "Hash Lookup" a été activé. +Vous pouvez ensuite aller au niveau de la section "Hashset Hits" de la zone "Results" située dans l'arborescence sur le côté gauche de l'interface. +Notez que la recherche de hachage peut prendre un certain temps, donc cette section sera mise à jour constamment tant que le processus d'acquisition sera en cours. +Utilisez la boîte de notification des modules d'acquisition ("Ingest Modules") pour garder un visuel sur les fichiers défavorablement connus récemment trouvés. + +Lorsque vous trouvez un fichier défavorablement connu dans cette interface, vous pouvez faire un clic droit sur ce fichier pour l'afficher également dans son emplacement d'origine. +Vous pouvez trouver des fichiers supplémentaires qui sont pertinents et stockés dans le même dossier que ce fichier. + +\subsection s5c Médias: images et vidéos + +Si vous souhaitez voir toutes les images et vidéos sur l'image disque, accédez à la section "Views" située dans l'arborescence sur le côté gauche de l'interface, puis dans la zone "File Types". +Sélectionnez soit "Images" soit "Videos". +Vous pouvez utiliser l'onglet Thumbnail dans la cadre situé en haut à droite, pour afficher les miniatures de toutes les images. + + +Vous pouvez sélectionner une image ou une vidéo dans la partie supérieure droite et afficher la vidéo ou l'image dans la zone inférieure droite de la fenêtre. La vidéo sera lue avec le son. + +\section s6 Rapports + +Un rapport final peut être généré qui inclura tous les résultats de l'analyse, à l'aide du bouton "Generate Report" de la barre d'outils. Les rapports peuvent être générés aux formats HTML, XLS, KML et autres. + +Vous pouvez retrouver plus tard vos rapports générés en accédant à l'arborescence et en ouvrant le nœud Reports en bas. + + +*/ \ No newline at end of file diff --git a/docs/doxygen-user_fr/recent_activity.dox b/docs/doxygen-user_fr/recent_activity.dox new file mode 100644 index 0000000000..ce34fd7f0d --- /dev/null +++ b/docs/doxygen-user_fr/recent_activity.dox @@ -0,0 +1,43 @@ +/*! \page recent_activity_page Recent Activity (Activités récentes) + +[TOC] + + +Qu'est ce que ça fait +======== + +Le module "Recent Activity" extrait l'activité de l'utilisateur telle qu'elle est enregistrée par les navigateurs Web (y compris les recherches Web), les programmes installés et le système d'exploitation. Il exécute également Regripper sur les ruches de la base de registre. + +Cela vous permet de voir quelle activité s'est produite au cours des sept derniers jours d'utilisation, quels sites Web ont été consultés, ce que la machine a fait et à quoi elle s'est connectée. + +Configuration +======= + +Configuration de la personnalisation des catégories Web +------ + +Le module "Recent Activity" créera des résultats "Web Categories" pour les domaines qui correspondent à une liste de catégories. Il existe des catégories intégrées, mais des catégories personnalisées peuvent également être saisies via l'onglet "Custom Web Categories" du panneau d'options principal. Ces catégories personnalisées remplaceront toute catégorie intégrée correspondante. + +\image html custom_web_categories.png + +Les boutons situés sous la liste des catégories vous permettent de saisir de nouvelles catégories, de modifier des catégories existantes et de supprimer des catégories. Vous pouvez également exporter votre liste de catégories et importer un ensemble de catégories précédemment exportées à partir de ce panneau. L'importation d'un ensemble ajoutera ces catégories à la liste actuelle (les catégories existantes ne seront pas supprimées). + +La catégorie correspondante pour chaque domaine sera répertoriée dans la colonne "Name" dans la visionneuse de résultats. +\image html custom_web_categories_results.png + + +Utilisation du module +====== + +Paramètres d'intégration +------ +Il n'y a pas de paramètre à l'exécution pour ce module. + + +Voir les résultats +------ +Les résultats s'affichent dans l'arborescence sous "Extracted Content". + +\image html extracted_content.PNG + +*/ diff --git a/docs/doxygen-user_fr/reporting.dox b/docs/doxygen-user_fr/reporting.dox new file mode 100644 index 0000000000..8696cb4d93 --- /dev/null +++ b/docs/doxygen-user_fr/reporting.dox @@ -0,0 +1,119 @@ +/*! \page reporting_page Rapports + +[TOC] + + +\section reporting_overview Aperçu + +Les modules de rapport permettent à l'utilisateur d'extraire les informations clés d'un cas dans une variété de formats, incluant la création de rapport HTML ou Excel contenant tout le contenu extrait d'un cas, les correspondances de mots clés dans ce cas, etc... , ou la création d'un fichier KML contenant +toutes les coordonnées trouvées pour les charger dans un logiciel comme Google Earth. + +\image html reports_select.png + +La plupart des types de rapports vous permettront de sélectionner les sources de données à inclure dans le rapport. Notez que les noms des sources de données exclues peuvent toujours être présents dans le rapport. Par exemple, le \ref report_html listera toutes les sources de données dans le cas sur la page principale mais ne contiendra pas les résultats, les fichiers balisés, etc... de la ou des sources de données exclue(s). + +\image html reports_datasource_select.png + +Les différents types de rapports seront décrits ci-dessous. La majorité des modules de rapport génèreront un fichier de rapport qui +sera affiché dans le cas sous le nœud "Reports" de l'\ref tree_viewer_page. + +\image html reports_result_viewer.png + +Si le type de rapport est associé à une visionneuse (tel qu'un navigateur Web pour un rapport HTML), vous pouvez double-cliquer sur le rapport pour l'ouvrir +dans une application externe. Vous pouvez également parcourir le dossier "Reports" dans le dossier du cas et ouvrir le rapport à partir de là. + +\image html reports_folder.png + +\section report_types Types de rapports + +\subsection report_html HTML Report (Rapport HTML) + +Pour les rapports HTML, vous pouvez d'abord choisir de saisir un en-tête et un pied de page qui seront affichés dans vos résultats. Par exemple, vous souhaiterez peut-être ajouter une bannière de classification. + +\image html reports_html_header.png + +Il existe deux options lors de la génération d'un rapport: inclure tous les résultats ("All Results") ou inclure uniquement les résultats balisés ("Tagged Results"). + +\image html reports_html_all_results.png + +Si vous choisissez "All Results", vous pouvez alors éventuellement utiliser le bouton "Data Types" pour choisir les types de données à inclure dans le rapport. + +\image html reports_html_art_select.png + +Si vous choisissez "Tagged Results", vous pouvez limiter les fichiers et les résultats qui s'affichent dans le rapport aux seuls balisés avec les balises que vous sélectionnerez. +Notez que vous ne pouvez pas filtrer sur le type de données lorsque vous utilisez cette option. + +\image html reports_html_tagged.png + +Le rapport terminé ressemblera à ceci: + +\image html reports_html_display.png + +Vous pouvez utiliser les liens sur le côté gauche pour voir les résultats pour chaque type de données. + +\subsection report_excel Excel Report (Rapport Excel) + +La génération d'un rapport Excel est très similaire à un \ref report_html. Vous sélectionnez les balises ou les types de données à exporter et Autopsy créera un fichier .xlsx. + +\image html reports_excel.png + +\subsection report_files Files - Text (Fichiers - Texte) + +Ce module de rapport vous permet de créer un fichier texte délimité par des tabulations ou des virgules contenant la liste de tous les fichiers dans le cas actuel. Commencez par sélectionner le délimiteur que vous souhaitez utiliser. + +\image html reports_files_delimiter.png + +Vous pouvez ensuite sélectionner les champs à inclure au rapport. + +\image html reports_files_config.png +
    +\image html reports_files_results.png + +\subsection report_tagged_hashes Save Tagged Hashes (Enregistrer les hachages balisés) + +C'est l'un des modules de rapport qui ne génère pas de rapport réel. Le but de ce module est d'ajouter facilement les hachages +de certains/tous les fichiers balisés vers un jeu de hachage Autopsy qui pourra être utilisé par le module \ref hash_db_page. Vous pouvez utiliser le bouton "Configure Hash Sets" pour créer un nouveau +jeu de hachage ou utiliser un jeu de hachage existant. + +\image html reports_hashes_config.png + +Après avoir exécuté ce module, si vous utilisez le même jeu de hachage dans les cas futurs, tout ce qui a été marqué avec l'une des balises sélectionnées dans ce cas +apparaîtra dans la section "Hashset Hits" de l'arborescence. + +\subsection report_body_file TSK Body File + +Ce module génère un fichier TSK Body File à partir des fichiers de votre cas, qui ressemble à ce qui suit: + +
    7ff498a44e45e77374cc7c962b1b92f2|/img_image1.vhd/vol_vol2/$UpCase|10|rr-xr-xr-x|0|0|131072|1498757218|1498757218|1498757218|1498757218
    +d41d8cd98f00b204e9800998ecf8427e|/img_image1.vhd/vol_vol2/$Volume|3|rr-xr-xr-x|48|0|0|1498757218|1498757218|1498757218|1498757218
    +43fffda5c5edd8e9c647f1df476717de|/img_image1.vhd/vol_vol2/0000/0000_a.txt|63|rrwxrwxrwx|0|0|11|1498757454|1498176989|1498757454|1498757454
    +411c8024a7c38ee3843ba8a07d048ec2|/img_image1.vhd/vol_vol2/0000/0000_b.txt|64|rrwxrwxrwx|0|0|11|1498757454|1498176990|1498757454|1498757454
    +fcc958c5096889a222785ddb8c4bff80|/img_image1.vhd/vol_vol2/0000/0000_c.txt|65|rrwxrwxrwx|0|0|11|1498757454|1498176990|1498757454|1498757454
    +b7cde263cc1b5df5a13aeec742637a89|/img_image1.vhd/vol_vol2/0000/0000_d.txt|66|rrwxrwxrwx|0|0|11|1498757454|1498176990|1498757454|1498757454
    + +\subsection report_kml Google Earth KML + +Ce module de rapport génère un fichier KML à partir de toutes les données GPS du cas. Ce fichier peut ensuite être utilisé avec Google Earth. + +\image html reports_kml.png + +\subsection report_stix STIX + +Le module STIX vous permet de générer un rapport et des artefacts "Interesting File" en exécutant un fichier (ou des fichiers) STIX sur les sources de données du cas. +Pour plus d'informations, consultez la page \ref stix_page. + +\subsection report_case_uco CASE-UCO + +Ce module cré un fichier de sortie JSON dans un format CASE-UCO pour une seule source de données. + +\image html reports_case.png + +\subsection report_portable_case Portable Case (Cas portable) + +Ce module de rapport génère un nouveau cas Autopsy qui comprend les éléments marqués et/ou intéressants. Voir la page \ref portable_case_page pour plus d'informations. + +\subsection reports_unique_words Extract Unique Words (Extraire des mots uniques) + +Ce module de rapport vous permet d'exporter tous les "mots" uniques trouvés dans un cas. Ces mots proviennent de l'index Solr créé par le module \ref keyword_search_page. + +*/ diff --git a/docs/doxygen-user_fr/result_viewer.dox b/docs/doxygen-user_fr/result_viewer.dox new file mode 100644 index 0000000000..6b628ff978 --- /dev/null +++ b/docs/doxygen-user_fr/result_viewer.dox @@ -0,0 +1,64 @@ +/*! \page result_viewer_page Visionneuse de résultats + +[TOC] + + +La visionneuse de résultats est située en haut à droite de l'écran d'Autopsy et affiche le contenu de ce qui a été sélectionné dans l'\ref tree_viewer_page. + +\section result_viewer_table La visionneuse "Table" + +La visionneuse principale dans l'onglet "Listing" affiche le contenu de la sélection actuelle sous forme de tableau avec les détails (propriétés) de chaque élément sélectionnés. Pour les fichiers, voici quelques exemples des propriétés que cette visionneuse montre: nom ("Name"), heures (modification = "Modified Time", changement = "Change Time", consultation = "Access Time" et création = "Created Time"), taille ("Size"), indicateurs ("Flags" - répertoire et méta), mode, ID utilisateur, ID de groupe, adresse de métadonnées ("Metadata Address"), adresse d'attribut ("Attribute Address") et type (répertoire et méta). Pour les autres types de données, les colonnes seront différentes. Cliquez sur l'onglet "Table" pour sélectionner cette vue. + +La capture écran suivante montre la visionneuse "Table" lorsqu'un dossier est sélectionné dans la section "Data Source" de l'\ref tree_viewer_page. +\image html result-viewer-example-1.PNG + +Comme mentionné ci-dessus, la visionneuse "Table" est sensible au contexte, ce qui signifie qu'elle affichera les colonnes applicables pour le type de données sélectionné. La capture écran suivante montre les données du nœud "Web Bookmarks" dans l'\ref tree_viewer_page. + +\image html result-viewer-example-3.PNG + +\subsection result_viewer_sco Colonnes SCO +Par défaut, les trois premières colonnes après le nom de fichier dans une visionneuse "Table" sont nommées "S", "C" et "O". + +\image html view_options_sco.png + +Ces colonnes affichent les informations suivantes: +
      +
    • (S)core - indique si l'élément est intéressant ou notable. +
        +
      • Affiche une icône rouge si le fichier correspond à un hachage notable ou a été marqué avec une balise notable. +
      • Affiche une icône jaune si le fichier correspond à un élément intéressant ou a été marqué avec une balise non notable. +
      +
    • (C)omment - indique si l'élément a un commentaire dans le référentiel central ou si un commentaire est associé à une balise. +
    • (O)ther occurrences - indique combien de sources de données dans le référentiel central contiennent cet élément. Le décompte comprendra l'élément sélectionné. +
    + +Pour afficher plus d'informations sur la raison pour laquelle une icône est apparue, vous pouvez la survoler. Ces colonnes interrogent le référentiel central ainsi que la base de données de cas. Si cela semble avoir un impact sur les performances, vous pouvez les désactiver via le panneau des \ref view_options_page. Cela supprimera entièrement la colonne "(O)ther occurrences", la colonne "(C)omment" sera basée uniquement sur les balises et la colonne "(S)core" ne pourra plus refléter les éléments notables. + +\subsection export_csv Export au format CSV + +Vous pouvez exporter le contenu d'une visionneuse "Table" vers un fichier CSV de deux manières. Le bouton "Save table as CSV" dans le coin supérieur gauche enregistre tout le contenu de la visionneuse "Table" dans un fichier CSV. Vous pouvez également sélectionner des lignes dans la visionneuse "Table", puis faire un clic-droit et sélectionner "Export selected rows to CSV" pour enregistrer uniquement un sous-ensemble des lignes: + +\image html result_viewer_csv.PNG + +\subsection right_click_functions Fonctions du clic droit +L'onglet "Table" dans la visionneuse de résultats a certaines fonctions de clic droit intégrées qui sont accessibles lorsqu'une ligne d'un type particulier est sélectionnée (un fichier, un répertoire ou un résultat). +Voici quelques exemples que vous pouvez voir: +\li Open File in External Viewer: Ouvre le fichier sélectionné dans une application "externe" telle que définie par le système d'exploitation local ou via l'onglet "External Viewer" dans lequel vous pouvez vous rendre via le panneau Options du menu Tools. Par exemple, les fichiers HTML peuvent être ouverts par Chrome ou Firefox ou un autre navigateur, selon la configuration du système local pour l'utilisation de navigateurs Web. +\li View in New Window: Ouvre l'élément sélectionné dans une nouvelle visionneuse de contenu (au lieu de l'emplacement par défaut dans la zone inférieure droite de la fenêtre principale). +\li Extract: Crée une copie locale du fichier ou du répertoire sélectionné pour une analyse plus approfondie. + + +\section thumbnail_result_viewer La visionneuse "Thumbnail" +L'onglet "Thumbnail" afficher les éléments sélectionnés dans l'\ref tree_viewer_page sous forme d'un tableau d'images miniatures dans des tailles ajustables. Cette visionneuse ne prend en charge que les fichiers "image" (elle ne prend actuellement en charge que les formats JPG, GIF et PNG). Cliquez sur l'onglet "Thumbnail" dans l'onglet principal "Listing" pour sélectionner cette vue. Notez que pour un grand nombre d'images dans un répertoire sélectionné dans la zone "Data Sources" de l'\ref tree_viewer_page, ou pour une sélection dans la zone "Views" de l'\ref tree_viewer_page qui contient un grand nombre d'images, cela peut prendre un certain temps pour remplir la visionneuse de vignettes pour la première fois, c'est-à-dire avant que les vignettes ne soient mises en cache. + +\image html thumbnail-result-viewer-tab.PNG + +\section result_viewer_paging Pagination + +La visionneuse "Table" peut fonctionner lentement lors de l'affichage d'un grand nombre de lignes. Pour résoudre ce problème, lorsqu'il y a plus d'un certain nombre de lignes (10 000 par défaut), les résultats seront divisés en pages. Les commandes de pagination en haut à droite de la vue tableau vous permettent de parcourir les différentes pages. + +\image html result_viewer_paging.PNG + +Vous pouvez ajuster les tailles de page via les \ref view_options_page ou désactiver complètement la pagination. + +*/ diff --git a/docs/doxygen-user_fr/search_all_cases.dox b/docs/doxygen-user_fr/search_all_cases.dox new file mode 100644 index 0000000000..6249120d1d --- /dev/null +++ b/docs/doxygen-user_fr/search_all_cases.dox @@ -0,0 +1,24 @@ +/*! \page search_all_cases_page Rechercher dans tous les cas + +[TOC] + + +\section search_all_cases_overview Aperçu + +La fonction de recherche dans tous les cas vous permet de rechercher dans le \ref central_repo_page avec des propriétés arbitraires. Vous devez avoir activé le référentiel central pour exécuter +cette recherche, et vous devez avoir un cas ouvert (bien que le cas ouvert n'ait aucun effet sur les résultats de la recherche). + +\section search_all_cases_usage Usage + +Allez sur Tools->Search All Cases pour ouvrir la boîte de dialogue de recherche. Ici, vous pouvez sélectionner le type de propriété et la valeur à rechercher. Un exemple de ce à quoi la valeur devrait ressembler +sera affiché en gris clair dans la zone "Correlation Property Value". Si la valeur saisie n'est pas valide pour ce type de propriété, un message d'erreur rouge s'affiche. + +\image html search_all_cases_dialog.png + +Une fois que vous avez cliqué sur le bouton Search, tous les résultats seront affichés dans la visionneuse de résultats. Le titre de l'onglet affichera ce qui était +recherché ("Email Addresses" et "sample@gmail.com" dans l'exemple). + +\image html search_all_cases_results.png + + +*/ \ No newline at end of file diff --git a/docs/doxygen-user_fr/stix.dox b/docs/doxygen-user_fr/stix.dox new file mode 100644 index 0000000000..b23be80288 --- /dev/null +++ b/docs/doxygen-user_fr/stix.dox @@ -0,0 +1,104 @@ +/*! \page stix_page STIX + +[TOC] + + +Aperçu +======== +Ce document décrit l'utilisation de la fonction STIX d'Autopsy. Cette fonction permet à un ou plusieurs fichiers Structured Threat Information Exchange (STIX) de s'exécuter sur une source de données, indiquant quels indicateurs ont été trouvés dans la source de données. Vous trouverez plus d'informations sur STIX sur https://stix.mitre.org/. +Ce document suppose une connaissance de base d'Autopsy. + +Démarrage rapide +=========== +-# Créez un cas comme d'habitude et ajoutez une image disque (ou un dossier de fichiers) comme source de données. Pour tirer le meilleur parti du module STIX, assurez-vous que les modules d'acquisition suivants sont sélectionnés: + - Recent Activity + - Hash Lookup (Case cochée pour calculer les hachages MD5 même si aucune base de données n'est sélectionnée) + - File Type Identification + - Keyword Search (URLs, IP Addresses, et Email addresses) + - Email Parser + - Extension Mismatch Detector +-# Une fois l'image ajoutée et l'acquisition terminée, cliquez sur le bouton "Report" puis sélectionnez STIX. Ensuite, choisissez un seul fichier STIX ou un répertoire de fichiers STIX à exécuter sur l'image. Il est possible de le faire pendant l'acquisition, mais les résultats seront incomplets. +-# Une fois le module de rapport STIX terminé, il y aura deux ensembles de résultats: + - Les entrées seront créées sous "Interesting Items" dans l'arborescence Autopsy, avec une sous-rubrique pour chaque indicateur. + - Un journal des indicateurs/observations trouvés est généré par le module de rapport (Suivez le lien sur la fenêtre "Report Generation Progress") + + +Objets CybOX supportés +====================== + +- Address Object (adresse) + - Address_Value (valeur) + +- Domain Name Object (domaine) + - Value (valeur) + +- Email Message Object (courriel) + - To (A) + - CC (Copie) + - From (De) + - Subject (Sujet) + +- File Object (fichier) + - Size_In_Bytes (taille en octets) + - File_Name (nom) + - File_Path (chemin) + - File_Extension (extension) + - Modified_Time (date de modification) + - Accessed_Time (date de dernier accès) + - Created_Time (date de création) + - Hashes (MD5 uniquement) + - File_Format (format du fichier) + - is_masqueraded (masqué) + +- URI Object (URI) + - Value (valeur) + +- URL History Object (historique URL) + - Browser_Information (nom du navigateur) + - URL + - Hostname (nom de l'hôte) + - Referrer_URL (referer) + - Page_Title (titre de la page) + - User_Profile_Name (nom du profil de l'utilisateur) + +- User Account Object (compte utilisateur) + - Home_Directory (répertoire principal de l'utilisateur) + - Username (nom de l'utilisateur) + +- Win Executable File Object (fichiers Windows exécutables) + - Time_Date_Stamp (date et heure) + +- Windows Network Share Object (partage réseau Windows) + - Local_Path (chemin local) + - Netname (nom du répertoire réseau) + +- Win Registry Key Object (clé de registre Windows) + - Key (obligatoire) + - Hive (ruche) + - Values (valeur) + +- System Object (système) + - Hostname (nom de l'hôte) + - Processor_Architecture (architecture processeur) + +- Win System Object (système Windows) + - Product_ID (identifiant produit) + - Product_Name (nom du produit) + - Registered_Owner (propriétaire enregistré) + - Registered_Organization (société enregistrée) + - Windows_System_Directory (répertoire système) + - Windows_Temp_Directory (répertoire temporaire) + +- Win User Account Object (compte utilisateur Windows) + - SID + +Voir http://cybox.mitre.org pour plus d'informations sur les obkets CybOX. + +Limites +======= +- Comme indiqué dans la liste ci-dessus, tous les objets/champs CybOX ne sont pas actuellement pris en charge. Lorsqu'un objet/champ non pris en charge est trouvé dans une observation, son statut est défini commme "indeterminate" au lieu de vrai ou faux. Ces champs indéterminés ne changeront pas le résultat de la composition observable (c'est-à-dire que si le reste est vrai, le résultat global restera vrai). +- Toutes les valeurs ConditionTypeEnum ne sont pas supportées. Cela varie selon les champs, mais généralement sur les champs "String" les éléments suivant fonctionnent: EQUALS, DOES_NOT_EQUAL, CONTAINS, DOES_NOT_CONTAIN, STARTS_WITH, ENDS_WITH. Si un type de condition n'est pas pris en charge, un avertissement apparaît dans le fichier journal. +- Les objets liés ne sont pas traités. + + +*/ diff --git a/docs/doxygen-user_fr/tagging.dox b/docs/doxygen-user_fr/tagging.dox new file mode 100644 index 0000000000..98d9b5e8a7 --- /dev/null +++ b/docs/doxygen-user_fr/tagging.dox @@ -0,0 +1,141 @@ +/*! \page tagging_page Marquages et commentaires + +[TOC] + + +Le marquage (ou bookmarking) vous permet de créer une référence sur un fichier ou un objet et de le retrouver facilement plus tard ou de l'inclure dans un \ref reporting_page "rapport". Il est également utilisé par le \ref central_repo_page "référentiel central" pour marquer les éléments "notables". Vous pouvez ajouter des commentaires aux fichiers et aux résultats marqués par des balises ou via le référentiel central. + +\section tagging_items Marquage des éléments + +Lorsqu'un élément intéressant est découvert, l'utilisateur peut le baliser en faisant un clic droit sur l'élément et en sélectionnant l'une des options de marquage. + +Lorsque vous marquez un résultat d'artefact du Blackboard, vous avez le choix entre: +- Add File Tag -- utilisez ceci lorsque le fichier lui-même est intéressant +- Add Result Tag -- utilisez ceci lorsque le résultat est intéressant + +Le choix dépend du contexte et de ce que vous désirez faire apparaître dans le rapport final. + +\image html tagging-1.PNG + +À ce stade, il existe trois options: +- Utilisez l'une des balises existantes pour l'ajouter au fichier/résultat sans commentaire +- Tag and Comment -- utilisez ceci si vous avez besoin d'ajouter un commentaire sur ce marquage + +\image html tagging-2.PNG + +- New tag -- Créez une nouvelle balise et ajoutez-la au fichier/résultat + +\image html tagging_new_tag.PNG + +Il existe plusieurs noms de balises par défaut: +- Bookmark - Balise par défaut pour marquer les fichiers d'intérêt +- Project Vic - À l'usage des forces de l'ordre +- Follow Up - Balise par défaut pour le marquage des fichiers à suivre +- Notable item - Balise par défaut pour indiquer qu'un élément doit être marqué comme "notable" dans le référentiel central + +Vous pouvez également créer des noms de balises personnalisés. Ces noms de balises seront automatiquement enregistrés pour une utilisation future et seront affichés au-dessus des noms de balises par défaut. + +Si vous souhaitez simplement marquer l'élément avec la balise "Bookmark" par défaut, vous pouvez également utiliser le raccourci clavier Control + B au lieu de parcourir les menus. + +Vous pouvez également appliquer des balises à des groupes de plusieurs éléments à la fois. Sélectionnez ces éléments dans le Blackboard, cliquez avec le bouton droit de la souris et ajoutez la balise appropriée. +Les éléments peuvent avoir plus d'une balise. + +Les résultats marqués sont affichés dans la partie "Results" de l'arborescence sous la zone "Tags". Les éléments marqués sont également mis en surbrillance dans la visionneuse de résultats. + +\image html tagging-4.PNG + +\section image_tagging Marquage d'une image + +Lorsque vous avez sélectionné une image dans la \ref result_viewer_page, vous verrez une option "Tags Menu" dans la partie supérieure droite de la \ref content_viewer_page "Visionneuse de contenu", sous l'onglet "Application". Cela vous permet de marquer uniquement une zone sélectionnée de l'image. Le marquage d'une image n'est actuellement activé que sur Windows. + +\image html tagging_image_menu.png + +\subsection image_tagging_creation Créer un marquage d'une image + +Pour commencer, sélectionnez l'option "Create" dans le "Tags Menu". Vous pouvez ensuite faire un clic gauche et glisser le curseur de la souris sur l'image pour créer un rectangle (qui sera votre "tag"). Lorsque vous relâchez la souris, vous pourrez appliquer un nom de balise (et éventuellement un commentaire) à votre marquage d'image. + +\image html tagging_image_select.png + +Vous pouvez ajouter un nouveau nom de balise à l'aide du bouton "New Tag". + +\image html tagging_image_create_tag.png + +Une fois que vous avez choisi le nom de la balise, vous verrez un contour rouge dans l'image autour de la section que vous avez choisie. + +\image html tagging_image_one_tag.png + +Vous pouvez créer plusieurs marquages dans la même image. + +\image html tagging_image_multiple.png + +Si vous souhaitez masquer temporairement les contours des balises, sélectionnez "Hide" dans le "Tags Menu". Vous pouvez ensuite sélectionner "Show" pour les revoir. Les contours réapparaissent également si vous passez à un élément différent dans la visionneuse de résultats et que vous revenez sur l'image. + +\subsection image_tagging_editing Sélection, redimensionnement et suppression du marquage d'une image + +Pour redimensionner ou supprimer le marquage d'une image, vous devrez d'abord le sélectionner. Vous pouvez le faire en cliquant avec le bouton gauche de la souris n'importe où à l'intérieur de (ou sur) la balise d'image. Les balises sélectionnées peuvent être redimensionnées en faisant glisser l'une des 8 poignées qui apparaissent. Les cotes redimensionnées seront automatiquement enregistrées lorsque la souris sera relâchée. + +\image html tagging_image_edit_tag.png + +La sélection d'une balise activera également l'option "Delete" dans le "Tags Menu". La suppression d'un marquage est une opération irréversible, donc soyez prudent. + +\subsection image_tagging_report Exportation et création de rapports sur les marquages d'une image + +Si vous souhaitez enregistrer l'image avec le contour du marquage, sélectionnez "Export" dans le "Tags Menu". Le résultat sera toujours un fichier PNG. Notez que l'utilisation de l'option "Extract File(s)" du menu contextuel de la visionneuse de résultats exportera l'image d'origine. + +Vous pourrez également voir les marquages d'images dans le \ref report_html "Rapport HTML". + +\image html tagging_image_report.png + +\section managing_tags Gérer les balises + +La liste des balises peut être modifiée via l'onglet "Custom Tags" du menu Options. + +\image html tagging-5.PNG + + +De là, de nouvelles balises peuvent être ajoutées, les balises existantes peuvent être modifiées et les balises créées par l'utilisateur peuvent être supprimées. Notez que la suppression d'une balise ne la supprime d'aucun élément marqué, et cette balise sera toujours utilisable dans tous les cas où elle a été utilisée pour marquer un élément. + +\image html tagging-6.PNG + + +Si vous utilisez le référentiel central, la modification du statut "notable" affectera les éléments marqués (dans le cas actuel uniquement) de la manière suivante: +- Si "Fichier A" est marqué avec "Tag A", qui n'est pas "notable", et que "Tag A" est remplacé par "notable", "Fichier A" sera marqué comme "notable" dans le référentiel central +- Si "Fichier B" est étiqueté avec "Tag B", qui est "notable", puis "Tag B" est remplacé par une catégorie "non-notable", s'il n'y a pas d'autres balises "notables" sur "Fichier B", alors son statut "notable" dans le référentiel central sera supprimé. + +\subsection user_tags Masquer les marquages des autres utilisateurs + +Les marquages sont associés au nom du compte de l'utilisateur qui les a mis en place. Ces informations sont visibles en sélectionnant les éléments dans la section "Tags" de l'arborescence: + +\image html tagging_user_name.png + +ou via l'onglet \ref cv_annotations de la visionneuse de contenu: + +\image html content_viewer_annotations.png + +Il est possible de masquer tous les fichiers et résultats présents dans la zone "Tags" de l'arborescence et ayant été marqués par d'autres utilisateurs. Ouvrez les \ref view_options_page, soit via l'icône en forme d'engrenage au-dessus de l'arborescence, soit via Tools->Options. Puis, dans la zone "Hide other users' tags in the:" cochez la case "Tags area in the tree". + +\image html tagging_view_options.png + +\section tagging_commenting Commenter + +Il existe deux méthodes pour ajouter des commentaires aux fichiers et aux résultats. La première méthode a été abordée dans la section \ref tagging_items. Faites un clic droit sur le fichier ou le résultat qui vous intéresse, choisissez "Add File Tag" ou "Add Result Tag" puis "Tag and Comment". Cela vous permet d'ajouter un commentaire sur l'élément. Vous pouvez ajouter plusieurs balises avec des commentaires au même fichier ou résultat. + +\image html tagging_comment_context.png + +Si vous avez activé un \ref central_repo_page "référentiel central", vous pouvez également l'utiliser pour enregistrer des commentaires sur les fichiers. Faites un clic droit sur le fichier et sélectionnez "Add/Edit Central Repository Comment". S'il y avait déjà un commentaire pour ce fichier, il apparaîtra dans la boîte de dialogue et peut être modifié - un seul commentaire peut être stocké à la fois dans le référentiel central. + +\image html tagging_cr_comment.png + +Si un fichier ou un résultat est associé à un commentaire, vous verrez une icône en forme de bloc-notes dans la colonne "C" de la visionneuse de résultats. Le survol vous indiquera le type de commentaires sur cet élément. + +\image html tagging_comment_icon.png + +Vous pouvez afficher les commentaires associés aux balises en allant dans la section "Tags" de l'arborescence et en sélectionnant l'une de vos balises. Tous les commentaires apparaîtront dans la colonne "Comment" de la visionneuse de résultats. + +\image html tagging_comment_in_result_viewer.png + +Vous pouvez afficher tous les commentaires sur un élément via l'onglet "Annotation" de la visionneuse de contenu. + +\image html tagging_comment_anno.png + +*/ diff --git a/docs/doxygen-user_fr/timeline.dox b/docs/doxygen-user_fr/timeline.dox new file mode 100644 index 0000000000..b995a5b3b8 --- /dev/null +++ b/docs/doxygen-user_fr/timeline.dox @@ -0,0 +1,188 @@ +/*! \page timeline_page Timeline (Chronologie) + +[TOC] + + +\section timeline_overview Aperçu + +Ce document décrit l'utilisation de la fonction Timeline d'Autopsy. Cette fonctionnalité a été financée par le DHS S&T pour aider à fournir des outils de criminalistique numérique gratuits et open source aux forces de l'ordre. La fonction Timeline peut aider à répondre à des questions telles que celles-ci: + +- Quand une activité Web majeure s'est-elle produite sur un système? +- Quand des périphériques externes ont-ils été connectés au système? +- Quand les images contenant des informations EXIF ont-elles été ajoutées? +- Quels sites Web ont été consultés qui ont entraîné des modifications du système de fichiers immédiatement après? + +Notez qu'à partir d'Autopsy 4.13, les événements de la Timeline sont désormais générés lors de l'acquisition et stockés dans la base de données du cas au lieu d'une base de données distincte. Pour cette raison, les cas plus anciens ne fonctionneront plus avec la Timeline. + +\section timeline_quickstart Démarrage rapide + +Utilisez cette section pour apprendre les bases de la Timeline. Vous trouverez plus de détails sur les options d'affichage plus loin dans ce document. + +Vous devez d'abord ouvrir un cas dans Autopsy. Pour tirer le meilleur parti de la Timeline, vous devez effectuer les opérations suivantes lors de l'acquisition: +- Activer le module \ref hash_db_page "Hash Lookup" et utilisez le NSRL pour ignorer les fichiers connus +- Activer le module \ref recent_activity_page "Recent Activity" pour générer des événements liés au Web et d'autres types d'événements divers +- Activer le module \ref EXIF_parser_page "Picture Analyzer" pour générer des événements sur l'horodatage des images +- Activez d'autres modules d'acquisition qui s'appliquent à vos données. Si vous avez des données de messagerie, assurez-vous que le module \ref email_parser_page "Email Parser" est activé. Si vous analysez des appareils mobiles, assurez-vous que le module \ref android_analyzer_page "Android Analyzer" et tous les autres modules pertinents sont activés. + +Pour ouvrir la chronologie, utilisez le bouton "Timeline" ou allez dans le menu "Tools" puis "Timeline". Vous pouvez ouvrir la Timeline pendant le traitement d'une image, mais les données ne seront pas complètes tant qu'il ne sera pas terminé. La chronologie s'ouvrira sur la vue \ref timeline_counts_view "Counts" avec un graphique montrant le nombre d'événements dans chaque période. + +\image html timeline_counts_view.png + +Vous pouvez cliquer sur l'un des segments des graphiques pour voir la liste des événements en bas à gauche. Cliquer sur un seul événement affichera les détails dans la section inférieure droite. + +Vous pouvez changer le mode d'affichage à l'aide des boutons situés dans la partie supérieure centrale de la fenêtre. Le deuxième mode d'affichage, la vue \ref timeline_details_view "Details", affiche des informations sur les événements survenus au cours d'une période donnée. Ce mode est plus efficient avec un filtre sur une petite fenêtre de temps. + +\image html timeline_details_view.png + +Le mode d'affichage final est la vue \ref timeline_list_view "List". Cette vue montre chaque événement dans l'ordre dans lequel il s'est produit. Cela peut être utile pour voir quels autres événements se sont produits dans le même laps de temps qu'un événement d'intérêt. Comme pour le mode Details, ce mode est plus efficient avec des filtres pour réduire le nombre d'événements affichés. + +\image html timeline_list_view.png + + +\section timeline_basic_concepts Concepts de base +Cette section couvre quelques concepts de base de l'interface. + +\subsection timeline_events Evènements + +L'outil Timeline est organisé autour d'événements ("Event"). Un événement a un horodatage, un type et une description. Remarque: tous les événements sont distincts, mais peuvent être regroupés pour former des clusters avec une durée dans la vue Details en fonction du niveau de description ("Description") activé dans l'interface utilisateur. + +La Timeline collecte des données à partir de plusieurs sources et organise les événements dans la taxonomie suivante: + +- File System (Fichiers Système) + - Modified (Modification) + - Access (Accès) + - Created (Création) + - Changed (Changement) +- Web Activity (Activités Web) + - Web Downloads (Téléchargements) + - Web Cookies (Cookies) + - Web Bookmarks (creation) (Création de signets) + - Web History (Historique) + - Web Searches (Recherches) + - Web Form Auto Fill (Remplissage automatique de formulaire) + - Web Form Address (Adresse de formulaire) +- Miscellaneous (Divers) + - Messages + - GPS Routes (Routes GPS) + - Location History (Historique de localisation) + - Calls (Appels) + - Email (Courriels) + - Recent Documents (Documents récents) + - Installed Programs (Programmes installés) + - Exif metadata (Métadonnées EXIF) + - Devices Attached (Périphériques connectés) + - Log Entry (Entrées de journaux) + - Registry (Base de registre) + + +\subsection timeline_viz_types Types de visualisation + +Il existe trois types de graphiques différents fournis par la visionneuse d'Autopsy. Chacun est mieux adapté à un type de question différent auquel l'enquêteur tente de répondre. Vous pouvez naviguer entre les trois types dans la partie supérieure de l'interface. + +La vue \ref timeline_counts_view "Counts" affiche un graphique en histogrammes. Utilisez ce type de graphique pour afficher combien d'activités se sont produites dans un laps de temps donné. Cependant, il ne vous montrera pas d’événements spécifiques. Il peut être utile de déterminer quand l'ordinateur a été utilisé pour la dernière fois ou à quelle fréquence il a été utilisé. Lorsque vous démarez une Timeline, elle s'ouvrira avec ce style de graphique. + +La vue \ref timeline_details_view "Details" affiche des événements liés individuellement ou en groupe. Les dates/heures sont représentées horizontalement le long de l'axe horizonal, mais l'axe vertical ne représente aucune unité spécifique. Vous utiliseriez cette interface pour déterminer les événements spécifiques qui se sont produits dans un laps de temps donné ou sur les événements survenus avant ou après un événement donné. Vous utiliserez généralement ce type d'interface après avoir utilisé la vue Counts pour identifier une période de temps sur laquelle vous souhaitez obtenir des détails. Il peut y avoir beaucoup de détails dans cette vue et nous avons introduit les concepts de zoom, comme décrit dans la section suivante, pour vous aider. + +La vue \ref timeline_list_view "List" affiche tous les événements dans l'ordre dans lequel ils se sont produits. Cela peut être utile pour savoir ce qui s'est passé avant et après un certain événement. Par exemple, si vous avez un téléchargement Web, vous pouvez trouver d'autres fichiers qui ont été créés avant ou après cela. La vue List peut comporter trop de données car il peut y avoir des milliers d'événements dans une plage de temps donnée. Utilisez les filtres décrits ci-dessous pour ramener le nombre d'événements à une taille appropriée. + +Le tableau en bas à gauche du panneau a une fonctionnalité \ref ui_quick_search qui peut être utilisée pour trouver rapidement un nœud dans le tableau. + +\subsection timeline_viz_settings Paramètres de visualisation + +La barre d'outils au-dessus de la zone de visualisation affiche les paramètres spécifiques à la visualisation active. Ces paramètres affectent la façon dont les événements sont affichés et/ou la disposition de la visualisation. + + + +\subsection timeline_zooming Zoom + +Un défi courant avec l'analyse chronologique est la surcharge d'informations. Pour vous aider, l'interface d'Autopsy dispose de trois méthodes de zoom qui vous aideront à identifier les données correctes. Celles-ci peuvent être contrôlées à partir d'une seule zone dans le coin supérieur gauche de l'interface. + + +- __Time Units__: Ce niveau de zoom contrôle le détail temporel affiché sur l'axe horizontal. Il dicte l'échelle des marqueurs sur un créneau d'une année à une seconde. Si vous voulez plus de détails sur ce qui s'est passé dans une plage de temps donnée, vous zoomerez davantage avec cette commande. +- __Event Type__: Ce niveau de zoom contrôle les types d'événements que vous voyez. Par exemple, il existe un type principal d'événement "File System" avec des sous-types pour les horodatages des modifications, des accès ou des créations. Si vous voulez plus de détails sur un type d'évènement donné, vous zoomerez davantage avec cette commande. +- __Description Detail__: Ce niveau de zoom est propre à Autopsy et regroupe les événements similaires en fonction de leur description. Par exemple, il regroupera les événements du système de fichiers s'ils se trouvent dans le même dossier racine lorsque vous effectuez un zoom arrière complet. Cela vous permet de voir généralement où il y a une activité sans avoir à analyser chaque fichier individuellement. + +Dans le cadre d'une approche de démarrage rapide, vous devez garder ceci à l'esprit: un double-clic sur quelque chose ne changera qu'un de ces niveaux de zoom. Nous avons essayé de choisir ce qui serait le plus intuitif pour la plupart des cas d'utilisation. +Si vous souhaitez choisir une approche de zoom différente, utilisez les curseurs en haut à gauche ou faites un clic droite sur le graphique. + +\subsection timeline_history Historique + +A tout moment vous pouvez revenir à quelque chose que vous avez vu auparavant, utilisez les boutons d'historique "Back" (précédent) "Forward" (suivant) en haut à gauche ou le raccourci clavier "Alt + Gauche/Droite". + + + + + +\section timeline_interaction Détails de l'interaction et de la configuration de la Timeline + +\subsection timeline_filters Filters (Filtres) + +La zone "Filters" permet à l'utilisateur d'appliquer des filtres pour limiter les événements affichés dans la visionneuse. Lorsque la vue Details est active, un onglet dans cette zone permet également de naviguer dans la visionneuse par descriptions d'événements (voir la section sur la vue \ref timeline_details_view "Details" pour en savoir plus) + + +Lorsque le filtre __Must include text__ est actif, seuls les événements contenant la chaîne de caractères fournie en tant que sous-chaîne seront affichés. + +Lorsque le filtre __Must be tagged__ est activé, seuls les éléments marqués par l'analyste seront inclus dans la visionneuse de la Timeline. + +Lorsque le filtre __Must have hash hit__ est activé, seuls les fichiers avec des hachages connus seront inclus dans la visionneuse de la Timeline. Pour que ce filtre fonctionne, le module d'acquisition Hash Lookup doit avoir été exécuté avec un jeu de hachage connu activé. + +Lorsque le filtre __Limit data sources to__ est activé, seuls les éléments de la source de données séléctionnée seront inclus dans la visionneuse de la Timeline. + +Le filtre __Limit file types to__ permet à l'utilisateur de sélectionner les types de fichiers à afficher. Un clic droit sur un type de fichier fait apparaître un menu contextuel avec des options pour sélectionner différents ensembles de types ("all": tous les types, "none": aucun des types, "only": seulement ce type, "others": les autres types). + +Le filtre __Limit event types to__ permet à l'utilisateur de sélectionner les types d'évènements à afficher. Un clic droit sur un type d'évènement fait apparaître un menu contextuel avec des options pour sélectionner différents ensembles de types ("all": tous les types, "none": aucun des types, "only": seulement ce type, "others": les autres types). + +La hiérarchie des types d'événement affichée dans l'onglet de filtre fonctionne également comme __légende__ pour les visionneuses. Les événements sont codés par couleur pour correspondre à leur type et ont l'icône correspondante affichée à plusieurs endroits. + +\subsection timeline_time_range Sélection de la plage de temps + + +La zone de sélection de la plage de temps offre plusieurs moyens d'ajuster la plage affichée. Les champs Date/Time indiquent la date et l'heure exactes du début ("Start" - à gauche) et de la fin ("End" - à droite) de la plage affichée. L'utilisateur peut taper directement dans ces champs ou utiliser un sélecteur de date/heure graphique pour modifier l'heure de début ou de fin. +Les boutons "loupes" moins et plus agrandissent la plage de temps visible selon un pourcentage défini. Le menu déroulant à leur droite permet de sélectionner une plage de temps prédéfinie. Ces méthodes ajusteront la plage de temps visible autour de son centre. +La dernière méthode pour ajuster la plage de temps visible consiste à utiliser le curseur de plage. L'utilisateur peut positionner chaque extrémité indépendamment pour ajuster respectivement l'heure de début et de fin ou faire glisser la section bleue en surbrillance pour déplacer la plage visible sans changer sa longueur. Dans les deux visionneuses (Counts et Details), l'utilisateur peut également cliquer sur une zone du graphique (en commençant dans un espace vide) puis glisser la souris sur un intervalle de temps, représenté par un cadre bleu pâle, et double-cliquer dessus pour agrandir l'intervalle de temps visible. Un clic droit sur la zone bleue de la période la désactive. + +\subsection timeline_histogram Histogramme + +Derrière le curseur de plage de temps se trouve un histogramme de tous les événements du cas. L'histogramme peut aider à mettre la visualisation principale en perspective en affichant un résumé global de tous les événements du cas, avec une représentation de la plage de temps visible superposée via le curseur de plage de temps. L'histogramme divise la durée totale de tous les événements du cas en intervalles égaux et montre le nombre d'événements dans chaque intervalle via la hauteur de la barre correspondante. L'histogramme ne doit être utilisé qu'à des fins de comparaison et de contexte relatifs et non pour déterminer le nombre exact ou l'heure des événements. Remarque: cet histogramme n'est pas affecté par les filtres ou le zoom. + +\subsection timeline_time_zone Fuseau horaire + + +L'utilisateur peut choisir entre l'affichage des événements dans son fuseau horaire local ou en UTC. + +\subsection timeline_counts_view Zone de visualisation: vue Counts + +La vue "Counts" affiche un graphique en histogrammes avec des périodes le long de l'axe horizontal et des décomptes d'événements le long de l'axe vertical. La hauteur de chaque barre représente le nombre d'événements qui se sont produits au cours de cette période. Les différents segments colorés représentent différents types d'événements. Un clic droit sur les barres fait apparaître un menu contextuel avec des actions de sélection et de zoom. + +Le seul paramètre spécifique à la vue Counts est le type d'échelle (Scale) verticale à utiliser: l'échelle linéaire (Linear) convient à de nombreux cas d'utilisation. Lorsque cette échelle est sélectionnée, la hauteur des barres représente les décomptes de manière linéaire, un à un, et l'axe vertical est étiqueté avec des valeurs. Lorsque la plage de valeurs est très large, les périodes avec des nombres faibles peuvent avoir une barre trop petite pour être visualisée. Pour aider l'utilisateur à détecter cela, les étiquettes des plages de dates avec des événements sont en gras. Pour voir les barres trop petites, il existe trois options: ajustez la taille de la fenêtre afin que la zone de visualisation ait plus d'espace vertical, ajustez la plage de temps affichée de sorte que les périodes avec des barres plus grandes soient exclues, ou ajustez le paramètre d'échelle sur logarithmique. + +L'échelle logarithmique représente le nombre d'événements d'une manière non linéaire qui compresse la différence entre les grands et les petits nombres. Notez que même avec l'échelle logarithmique, une très grande différence de comptage peut toujours produire des barres trop petites pour être visibles. Dans ce cas, la seule option peut être de filtrer les événements pour réduire la différence de comptage. REMARQUE: étant donné que l'échelle logarithmique est appliquée à chaque type d'événement séparément, la signification de la hauteur de l'histogramme n'est pas intuitive et, pour le souligner, aucune étiquette n'est affichée sur l'axe vertical avec l'échelle logarithmique. L'échelle logarithmique doit être utilisée pour comparer rapidement les décomptes *dans le temps au sein d'un type, ou entre les types pour une période de temps, mais pas les deux.* Les décomptes réels (disponibles dans les infobulles ou dans le visualiseur de résultats) doivent être utilisés pour des comparaisons absolues. Utilisez l'échelle logarithmique avec précaution. + + +\subsection timeline_details_view Zone de visualisation: vue Details + + +La vue "Detais" affiche les événements regroupés par leur description. Les dates/heures sont représentés le long de l'axe horizonal, mais l'axe vertical ne représente rien et n'est utilisé que comme espace pour mettre en page les événements qui se chevauchent. Les événements avec le même type et la même description qui se produisent à proximité dans le temps peuvent être regroupés. Les curseurs "Time Unit" (Unité de temps), "Event Type" (Type d'évènement) et "Description Detail" (Détail de description) contrôlent la manière dont les événements sont regroupés. Lorsque le niveau de "Description Detail" est au maximum, il est probable que très peu d'événements seront regroupés, ce qui entraînera l'affichage d'une énorme quantité de détails. Cela peut entraîner un ralentissement important de l'interface utilisateur, __il n'est donc pas recommandé d'utiliser la description complète à moins que la plage de temps n'ait été réduite et/ou que des filtres n'aient été appliqués pour réduire le nombre d'événements affichés__. La projection des clusters sélectionnés est affichée sur l'axe horizontal pour aider à visualiser les relations temporelles entre ces derniers. + +La vue Details comporte quatre paramètres qui affectent les informations visibles et la disposition des clusters d'événements. Ces quatre paramètres sont indépendants. Ils sont situés dans le menu déroulant "Advanced Layout Options" et peuvent être combinés pour obtenir une variété d'effets avec différentes densités d'informations et différents modèles de mise en page. + +__Band by Type__: Si cette option n'est pas sélectionnée, tous les clusters d'événements de différents types seront mélangés, dans une mise en page compacte. Si elle est sélectionnée, chaque type d'événement aura une bande horizontale qui lui sera réservée et les événements de différents types ne seront pas mélangés. Cette option est utile lorsque l'utilisateur souhaite comparer principalement des événements du même type. + +__One event per Row__: Si cette option est sélectionnés, aucun cluster d'événements ne se superposera verticalement, cela rendra la visualisation plus semblable à un diagramme de Gantt mais utilisera beaucoup plus d'espace vertical. + +__Truncate Descriptions__: L'utilisateur peut sélectionner cette option et choisir une longueur (en pixels) pour tronquer le libellé de texte affiché pour chaque cluster. Ceci est utile si les descriptions sont longues et empêchent une mise en page compacte. + +L'utilisateur peut choisir un niveau de visibilité de la description : + +__Show Full Description__: c'est la valeur d'affichage par défaut - __Show Counts Only__: seul le décompte entre parenthèses est affiché - __Hide Description__: l'intégralité de l'étiquette de texte est masquée + + "Show Counts Only" et "Hide Description" sont utiles si l'utilisateur souhaite obtenir une vue moins encombrée, se concentrer davantage sur le moment où les clusters d'événements se sont produits ainsi que sur leur type, et n'est pas intéressé par les descriptions. + +Cliquer sur le petit bouton vert [+] dans un cluster l'élargira avec le niveau de détail supérieur. Les événements du cluster seront affichés en cluster à une échelle de temps appropriée à leur étendue et au niveau de détail choisi. Cela peut être répété pour les sous-clusters, afin de créer une hiérarchie imbriquée de clusters. Cliquez sur le bouton rouge [-] pour réduire un cluster à un niveau de détail inférieur. Comme pour le niveau de description global, il convient d'être prudent lors de l'expansion complète de grands clusters, car cela peut entraîner l'affichage d'une énorme quantité de détails, ralentissant l'outil. + + +\subsection timeline_list_view Zone de visualisation: vue List + +La vue "List" affiche tous les événements de la plage horaire que vous avez sélectionnée. Vous pouvez contrôler cette plage de temps à l'aide des entrées "Start" et "End" sous la liste, ou en déplaçant les extrémités du curseur de la ligne bleue qui s'affiche sous la liste. La sélection d'un événement dans la liste affichera ses détails dans la section inférieure de l'écran. + +*/ diff --git a/docs/doxygen-user_fr/translations.dox b/docs/doxygen-user_fr/translations.dox new file mode 100644 index 0000000000..16f0f3039a --- /dev/null +++ b/docs/doxygen-user_fr/translations.dox @@ -0,0 +1,157 @@ +/*! \page translations_page Traduire la documentation et l'interface utilisateur + +[TOC] + + +La base d'utilisateurs d'Autopsy est globale. Vous pouvez contribuer en traduisant l'interface utilisateur et cette documentation. + +\section translations_doc Traduire la documentation + +Cette section explique comment traduire cette documentation utilisateur. Pour traduire, vous aurez besoin de: +- Un compte Github +- Des connaissances de base de Git +- Un éditeur de texte + +La documentation Autopsy est créée avec [Doxygen](http://www.doxygen.nl/) à partir de fichiers textes ".dox" dans le dossier [docs/doxygen-user](https://github.com/sleuthkit/autopsy/tree/develop/docs/doxygen-user) du dépôt Github. + +La première étape consiste à créer un "Fork" du [dépôt Autopsy](https://github.com/sleuthkit/autopsy) dans votre compte Github et à en faire un clone dans votre environnement afin que vous puissiez apporter des modifications aux fichiers. + +Lors de vos modifications, vous pouvez consulter votre documentation en installant Doxygen et en exécutant 'doxygen' à partir du dossier des traductions. Il enregistrera les pages HTML dans un dossier 'user-docs'. + +\subsection translations_doc_start Traduire dans une nouvelle langue + +S'il n'y a pas encore de documentation dans une langue, vous devez faire une copie du dossier anglais entier 'doxygen-user' et le nommer 'doxygen-user_AB' où AB est remplacé par les deux caratères du [code pays] (http://www.lingoes.net/en/translator/langcode.htm). Par exemple, 'doxygen-user_fr' pour le français et 'doxygen-user_ja' pour le japonnais. + +Modifiez le fichier Doxyfile pour mettre à jour le champ OUTPUT_LANGUAGE. Pour l'anglais, ce sera: + +\code +OUTPUT_LANGUAGE = English +\endcode + +Maintenant, commencez simplement à traduire les documents en anglais. + +\subsection translations_doc_update Mise à jour de la documentation + +Lorsque de nouvelles versions sont publiées et que la documentation en anglais est mise à jour, les autres langues doivent également être mises à jour. Pour déterminer ce qui a changé: +- Tout d'abord, déterminez la date de la dernière modification de la documentation. À partir d'une ligne de commande, vous pouvez accéder au dossier de documentation traduite et saisir: + +\code + $ cd docs/doxygen-user_fr + $ git log -n 1 . + commit 94e4b1042af47908dd4a0b2959b3f6c3d4af1111 + Author: John Doe + Date: Tue Jan 1 22:56:09 2019 -0500 + + update to quick start +\endcode + +Cela vous montre que le commit 94e4b1042af47908dd4a0b2959b3f6c3d4af1111 était la dernière mise à jour de traduction pour la version française. + +- Ensuite, déterminez ce qui a changé dans la version anglaise depuis lors: + +\code + $ git diff 94e4b1042af47908dd4a0b2959b3f6c3d4af1111 ../doxygen-user + diff --git a/docs/doxygen-user/central_repo.dox b/docs/doxygen-user/central_repo.dox +index 83d3407e8..e8cd01c1b 100644 + --- a/docs/doxygen-user/central_repo.dox + +++ b/docs/doxygen-user/central_repo.dox + @@ -79,6 +79,16 @@ Descriptions of the property types: + - Phone numbers are currently only extracted from call logs, contact lists and message, which come from the Android Analyzer module. + - USB Devices + - USB device properties come from the registry parsing in the Recent Activity Module. + +- Wireless Networks + + - Wireless networks are correlated on SSIDs, and come from the registry par +\endcode + +- Mettez à jour la documentation traduite en fonction de ce qui a changé dans la version anglaise. + +- Si vous ne parvenez pas à effectuer toutes les modifications, vous devez créer un fichier TODO.txt qui répertorie ce qui n'a pas été mis à jour afin que d'autres personnes sachent que tout n'a pas été réactualisé. + +\subsection translations_doc_commit Validation de la documentation + +Vous devez soumettre une "Pull Request" sur Github lorsque: +- Vous avez complété une langue. +- Vous n'avez pas eu le temps de faire plus de travail, mais souhaitez soumettre ce que vous avez fait. + +Pour que le code soit validé, envoyez une [Pull Request](https://help.github.com/articles/about-pull-requests/) sur le dépôt principal d'Autopsy. + +\section translations_ui Traduire l'interface utilisateur +Cette section explique comment traduire l'interface utilisateur. Pour ce faire, vous aurez besoin de: + +- Un compte Github +- Des connaissances de base de Git +- Un environnement complet de développement d'Autopsy. + +\subsection translations_ui_autopsy Environnement de développement d'Autopsy + +Vous aurez besoin d'une configuration complète de l'environnement de développement d’Autopsy afin de pouvoir lancer le logiciel avec vos traductions et vérifier qu'elles se trouvent au bon emplacement et qu'elles ne sont pas rognées. + +Vous pourrez trouver des instructions pour ce faire dans le fichier [BUILDING.txt](https://github.com/sleuthkit/autopsy/blob/develop/BUILDING.txt). + +\subsection translations_ui_strings Où sont stockées les chaînes de caractères anglaises + +Autopsy utilise deux méthodes différentes pour stocker les chaînes de caractères anglaises de l'interface utilisateur. Certaines sont stockées dans des fichiers Bundle.properties et d'autres sont stockées dans le code sous forme d'annotations \@Message. Les annotations compliquent la traduction du code car les traducteurs doivent chercher à deux endroits, mais cela facilite le développement. + +Pour faciliter les traductions, nous avons ajouté une logique dans notre processus de construction en fusionnant les différentes chaînes en un seul endroit. Lorsque le code d'Autopsy est compilé, il fusionne le contenu des annotations et des fichiers Bundle.properties dans un seul fichier nommé Bundle.properties-MERGED. Un de ces fichiers existe pour chaque package Java. + +Voici un exemple dans le package corecomponents (Notez que certains de ces liens peuvent ne pas être tout à fait corrects si ces fichiers ont été mis à jour et que la documentation ne l’a pas été, mais ils servent de référence de base): +- Il existe un fichier [Bundle.properties](https://github.com/sleuthkit/autopsy/blob/develop/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties). Au moment où cette documentation a été écrite, il y avait 230 lignes dans ce fichier. +- Dans ce même package, la classe [AutopsyOptionsPanel.java](https://github.com/sleuthkit/autopsy/blob/develop/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java#L53) contient des chaînes de caractères définies au niveau des annotations \@Message. +- Il existe un fichier [Bundle.properties-MERGED](https://github.com/sleuthkit/autopsy/blob/develop/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties-MERGED) qui contient les chaînes de caractères de Bundle.properties ainsi que les annotations. Au moment de la rédaction de cet article, ce fichier comportait 277 lignes. + +\subsection translations_ui_translation Où les chaînes de caractères traduites sont stockées + +Chaque package Java doit avoir un fichier Bundle_AB.properties qui stocke le texte traduit. AB doit être remplacé par les deux caractères du [code pays] (http://www.lingoes.net/en/translator/langcode.htm), comme Bundle_fr.properties pour le français ou Bundle_ja.properties pour le japonnais. + +À titre d'exemple, vous pouvez voir la traduction japonaise du package corecomponents précédemment cité dans [Bundle_ja.properties](https://github.com/sleuthkit/autopsy/blob/develop/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle_ja.properties). + +Ce fichier doit contenir toutes les chaînes de caractères de cette langue. Il doit être basé sur le fichier Bundle.properties-MERGED, et non sur le fichier Bundle.properties (qui ne contient pas toutes les chaînes). + + + +\subsection translations_ui_start Traduire dans une nouvelle langue + +S'il n'y a pas déjà de traduction dans une langue, vous devez: +- aller dans chaque paquet +- copier le fichier Bundle.properties-MERGED dans le fichier Bundle_XX.properties où XX est remplacé par le code de langue. +- modifier le fichier Bundle_XX.properties et traduire les chaînes de caractères en anglais. + + +\subsection translations_ui_update Mise à jour des traductions + +Lorsque de nouvelles versions sont publiées et que l'interface utilisateur anglaise est mise à jour, les autres langues doivent également être mises à jour. Pour déterminer ce qui a changé: + +- Tout d'abord, déterminez la date de la dernière modification du fichier traduit. À partir d'une ligne de commande, vous pouvez accéder au dossier du package et taper: + +\code + $ cd Core/src/org/sleuthkit/autopsy/corecomponents + $ git log -n 1 Bundle_ja.properties + commit 94e4b1042af47908dd4a0b2959b3f6c3d4af1333 + Author: John Doe + Date: Tue Jan 1 22:56:09 2019 -0500 +\endcode + +Cela vous montre que le commit 94e4b1042af47908dd4a0b2959b3f6c3d4af1333 était la dernière mise à jour de traduction pour la version japonaise. + +- Ensuite, déterminez ce qui a changé dans la version anglaise depuis lors: + +\code + $ git diff 94e4b1042af47908dd4a0b2959b3f6c3d4af1333 Bundle.properties-MERGED + -AutopsyOptionsPanel.restartNecessaryWarning.text=A restart is necessary for any changes to max memory to take effect. + +AutopsyOptionsPanel.restartNecessaryWarning.text=A restart is necessary for any memory changes to take effect. +\endcode + +- Mettez à jour les chaînes de caractères de Bundle_ja.properties de manière appropriée, en fonction de ce qui a été ajouté, supprimé ou modifié. + +- Si vous ne parvenez pas à effectuer toutes les modifications, vous devez créer un fichier TODO_xx.txt qui répertorie ce qui n'a pas été mis à jour afin que d'autres personnes sachent que tout n'a pas été réactualisé. + +\subsection translations_ui_commit Validation de la documentation + +Vous devez soumettre une "Pull Request" sur Github lorsque: +- Vous avez complété une langue. +- Vous n'avez pas eu le temps de faire plus de travail, mais souhaitez soumettre ce que vous avez fait. + +Pour que le code soit validé, envoyez une [Pull Request](https://help.github.com/articles/about-pull-requests/) sur le dépôt principal d'Autopsy. + + +*/ diff --git a/docs/doxygen-user_fr/tree_viewer.dox b/docs/doxygen-user_fr/tree_viewer.dox new file mode 100644 index 0000000000..0f67d27271 --- /dev/null +++ b/docs/doxygen-user_fr/tree_viewer.dox @@ -0,0 +1,67 @@ +/*! \page tree_viewer_page Arborescence + +[TOC] + + +L'arborescence sur le côté gauche de la fenêtre principale est l'endroit où vous pouvez parcourir les fichiers dans les sources de données du cas et trouver les résultats enregistrés à partir des analyses automatisées (Ingest). L'arborescence a cinq zones principales: +- Persons / Hosts / Data Sources: Cela montre la hiérarchie arborescente de répertoires des sources de données. Vous pouvez accéder à un fichier ou à un répertoire spécifique ici. Chaque source de données ajoutée au cas est représentée sous la forme d'une sous-arborescence distincte. Si vous ajoutez une source de données plusieurs fois, elle apparaît plusieurs fois. +- Views: Des types spécifiques de fichiers provenant des sources de données sont affichés ici, agrégés par type ou par d'autres propriétés. Les fichiers ici peuvent provenir de plusieurs sources de données. +- Results: C'est ici que vous pouvez voir les résultats des analyses automatisées (Ingest) exécutée en arrière-plan ainsi que vos résultats de recherche. +- Tags: C'est là que les fichiers et les résultats qui ont été \ref tagging_page "marqués" sont affichés. +- Reports: Les rapports que vous avez générés ou que les modules d'acquisition ont créés s'affichent ici. + +Vous pouvez également utiliser l'option "Group by Person/Host" disponible via la page \ref view_options_page pour déplacer les nœuds d'arborescence Views, Results, et Tags sous les catégories "Persons" et "Hosts" correspondantes. Cela peut être utile dans les cas très volumineux pour réduire la taille de chaque sous-arborescence. + +\section ui_tree_ds Persons / Hosts / Data Sources (Personnes / Hôtes / Sources de données) +Par défaut, le nœud supérieur de l'arborescence contiendra toutes les sources de données du cas. Le nœud "Data Sources" est organisé par hôte, puis par source de données elle-même. Un clic droit sur les différents nœuds dans la zone "Data Sources" de l'arborescence vous permettra d'obtenir plus d'options pour chaque source de données et son contenu. + +\image html ui_tree_top_ds.png + +Si l'option "Group by Person/Host" a été sélectionnée dans le panneau \ref view_options_group "Options", les hôtes et les sources de données seront organisés par rapport à toutes les personnes ayant été associées aux hôtes. De plus, le reste des nœuds (Views, Results, etc...) se trouve sous chaque source de données. + +\image html ui_tree_top_persons.png + +\subsection ui_tree_persons Persons (Personnes) + +Si l'option "Group by Person/Host" a été sélectionnée dans le panneau \ref view_options_group "Options", les nœuds de niveau supérieur afficheront les personnes. Les personnes sont créées manuellement et peuvent être associées à un ou plusieurs hôtes. Pour ajouter ou supprimer une personne d'un hôte, cliquez avec le bouton droit sur l'hôte et sélectionnez l'option appropriée. + +\image html ui_person_select.png + +Vous pouvez modifier et supprimer des personnes en faisant un clic droit sur le nœud. + +\subsection ui_tree_hosts Hosts (Hôtes) + +Toutes les sources de données sont organisées sous des nœuds "Hosts" (Hôtes). Voir la page \ref host_page "Hôtes" pour plus d'informations sur l'utilisation des hôtes. + +\subsection ui_tree_ds_node Data Sources (Sources de données) +Sous les hôtes se trouvent les nœuds de chaque source de données. + +L'espace non alloué (Unallocated space) représente les parties d'un système de fichiers qui ne sont actuellement utilisées pour rien. L'espace non alloué peut contenir des fichiers supprimés et d'autres artefacts intéressants. Dans une source de données d'image disque, l'espace non alloué est stocké dans des blocs situés à des emplacements distincts dans le système de fichiers. Cependant, en raison du fonctionnement des outils de carving, il est préférable d'alimenter ces outils avec un seul et grand fichier d'espace non alloué. Autopsy permet d'accéder aux deux méthodes d'examen de l'espace non alloué. +\li Blocs individuels dans un volume - Pour chaque volume, il y a un dossier "virtuel" nommé "$Unalloc". Ce dossier contient tous les blocs non alloués individuels situés de façon contiguës (fichiers d'espace non alloué) à la manière dont l'image les stocke. Vous pouvez faire un clic droit et extraire tout fichier d'espace non alloué de la même manière que vous pouvez extraire tout autre type de fichier dans la zone "Data Sources". +\li Fichiers uniques - Faites un clic droit sur un volume et sélectionnez "Extract Unallocated Space as Single File" pour concaténer tous les fichiers d'espace non alloués du volume en un seul fichier continu. (Si vous le souhaitez, vous pouvez faire un clic droit sur une image et sélectionner "Extract Unallocated Space to Single Files", ce qui fera la même chose mais une fois pour chaque volume de l'image). + +Un exemple de l'option d'extraction de fichier unique est illustré ci-dessous. +\image html extracting-unallocated-space.PNG + +\section ui_tree_views Views (Vues) + +La zone "Views" filtre tous les fichiers du cas en fonction de certaines propriétés du fichier. +- File Types - Trie les fichiers par extension ou par type MIME et les affiche dans le groupe approprié. Par exemple, les fichiers avec les extensions .mp3 et .wav se retrouvent dans le groupe "Audio". +- Deleted Files - Affiche les fichiers qui ont été supprimés, mais dont les noms ont été récupérés. +- File Size - Trie les fichiers en fonction de leur taille. + + +\section ui_tree_results Results (Résultats) +- Extracted Content: De nombreux modules d'acquisition placeront les résultats ici: métadonnées EXIF, emplacements GPS ou historiques Web par exemple. +- Keyword Hits: Les résultats de la recherche par mot-clé s'affichent ici. +- Hashset Hits: Les résultats de la recherche de hachage s'affichent ici. +- E-Mail Messages: Les e-mails s'affichent ici. +- Interesting Items: Les éléments jugés intéressants apparaissent ici. +- Accounts: Les comptes de carte de crédit s'affichent ici. +- Tags: Tout élément que vous avez marqué apparaît ici pour que vous puissiez le retrouver facilement. + +\section ui_tree_reports Reports (Rapports) + +Les rapports peuvent être ajoutés par les \subpage ingest_page ou créés en utilisant l'outil \subpage reporting_page. + +*/ diff --git a/docs/doxygen-user_fr/triage.dox b/docs/doxygen-user_fr/triage.dox new file mode 100644 index 0000000000..d6a4deb503 --- /dev/null +++ b/docs/doxygen-user_fr/triage.dox @@ -0,0 +1,104 @@ +/*! \page triage_page Triage + +[TOC] + + +\section triage_overview Aperçu + +Parfois, vous devez prendre une décision rapide sur un ou plusieurs systèmes et vous n'avez ni le temps ni les ressources pour créer des images complètes. Par exemple, lors d'une perquisition, vous voulez savoir s'il existe des données notables sur le système. Ou vous êtes à un endroit avec de nombreux systèmes et vous voulez savoir lesquels doivent être analysés en premier. Autopsy a des fonctionnalités qui vous permettront de trouver rapidement les données d'intérêt sans faire des images complètes des appareils. Ces fonctionnalités seront décrites ci-dessous, suivies de quelques exemples de scénarios qui montrent comment tout assembler. + +\section triage_features Caractéristiques liées au triage + +Il existe de nombreuses fonctionnalités d'Autopsy qui peuvent entrer en jeu dans une situation de triage. Certaines vous aident à traiter au plus tôt les fichiers les plus susceptibles d'être pertinents, et d'autres vous permettent de continuer à analyser les données après la déconnexion du système cible. + +\subsection triage_prioritization Priorisation + +L'objectif est de trouver d'abord les fichiers les plus importants lorsque le temps d'analyse d'un système est limité. Autopsy s'exécute toujours en premier sur les dossiers de l'utilisateur (le cas échéant), car dans de nombreuses situations, ce sont les dossiers les plus susceptibles de contenir des données d'intérêt. + +\image html triage/pipelineFolders.png + +\subsection triage_file_filter Filtres de fichiers + +Dans certains cas particuliers, vous pouvez connaître les types de fichiers spécifiques qui vous intéressent. Par exemple, si vous êtes uniquement intéressé par la recherche d'images, vous pouvez gagner du temps en n'analysant aucun fichier non image. Cela permettra à un système d'être traité beaucoup plus rapidement que si vous analysiez chaque fichier. + +\image html triage/fileFilterImage.png + +Les filtres de fichiers vous permettent de limiter les types de fichiers qui seront traités. La section \ref file_filters de la page relative aux \ref ingest_page montre comment créer un filtre de fichiers. Vous pouvez filtrer sur le nom/l'extension du fichier, le chemin ou la date à laquelle le fichier a été récemment modifié. Une fois enregistré, votre nouveau filtre de fichiers peut être sélectionné lors de la configuration des modules d'acquisition. + +\image html triage/fileFilter.png + +\subsection triage_profile Profils d'acquisition + +Une autre façon d'accélérer l'analyse consiste à n'exécuter que certains des modules d'acquisition. Par exemple, si nous ne nous intéressons qu'aux images, il peut être inutile d'exécuter le module \ref keyword_search_page ou le module \ref encryption_page. Vous pouvez sélectionner et configurer manuellement et à chaque fois les modules que vous souhaitez exécuter, mais comme de nombreuses sessions sont similaires, il peut être plus facile de configurer un profil d'acquisition. Un profil d'acquisition vous permet de stocker le filtre de fichiers que vous souhaitez exécuter, les modules d'acquisition qui doivent être activés et votre configuration pour chaque module d'acquisition. + +\image html triage/ingestProfile.png + +Une fois que vous avez configuré au moins un profil d'acquisition, un nouvel écran apparaîtra avant le panneau de configuration normal des modules d'acquisition. Si vous choisissez votre profil défini par l'utilisateur, le panneau de configuration des modules d'acquisition sera entièrement ignoré et les modules d'acquisition de ce profil seront exécutés sur la source de données. + +\image html triage/profileSelect.png + +Voir la section \ref ingest_profiles de la page \ref ingest_page pour plus d'informations sur la configuration et l'utilisation d'un profil d'acquisition. + +\subsection triage_no_image Exécution sur des systèmes et des périphériques en fonctionnement + +Dans une situation de triage, il n'y a généralement pas le temps de faire une image complète du système en question. Il existe plusieurs façons de traiter des systèmes et des appareils allumés avec Autopsy: + +
      +
    • Les périphériques tels que les clés USB peuvent être analysés en tant que disques locaux sans avoir besoin de créer un fichier image. Voir la section \ref ds_local pour plus de détails. +
    • Un lecteur de triage en direct peut être créé qui vous permettra d'exécuter Autopsy à partir d'un lecteur USB sur un système allumé. Toutes les données du cas seront enregistrées sur la clé USB avec des modifications minimes sur le système analysé. Voir \ref live_triage_page pour plus de détails. +
    • L'ordinateur cible peut être démarré à partir d'une clé USB Linux ou Windows de confiance et Autopsy peut être exécutée à partir de celle-ci. Paladin inclut Autopsy dans sa clé USB Linux bootable et une image Windows FE peut également être créée. +
    + +\subsubsection triage_vhd Créer une image sparse + +Avec les méthodes énumérées ci-dessus pour analyser les systèmes et les périphériques en direct, un problème persiste: votre cas Autopsy ne sera pas très utile après la déconnexion du lecteur. Il fera référence à un appareil qui n'existe plus et, plus important encore, vous pourriez ne pas avoir de copie des fichiers d'intérêt que vous avez observés lors du triage. + +Pour résoudre ce problème, vous pouvez choisir de faire un "sparse VHD" lorsque Autopsie traite l’appareil. Cela enregistrera une copie de chaque secteur lu par Autopsy, qui comprendra les structures du système de fichiers (telles que les Master File Tables) et les fichiers qui ont été analysés par les filtres d'acquisition (telles que toutes les images). + +VHD est un format de fichier utilisé par les machines virtuelles Microsoft qui est lisible par Windows et d'autres outils d'investigation. La taille du disque dur virtuel augmentera au fur et à mesure qu'Autopsy lit les données à partir du lecteur cible. + +Pour créer un VHD sparse, cochez la case "Make a VHD image..." lors de la sélection du disque à analyser. + +\image html triage/createVHD.png + +\section triage_scenarios Scénarios + +\subsection triage_scen1 Scénario: Prévisualisation d'un ordinateur pour la recherche de contenu pédo-pornographique + +Dans ce scénario, vous essayez de déterminer si des images d'exploitation d'enfants existent dans une situation de perquisition où vous disposerez d'un temps limité avec le système cible. + +Préparation au bureau: +
      +
    • Créez un \ref live_triage_page "support de triage en direct" sur votre clé USB +
    • Lancez Autopsy à partir de cette clé USB et créez un \ref ingest_profiles "profil d'acquisition" qui: +
        +
      • Utilise un \ref file_filters "filtre de fichiers" qui ne s'appliquera que sur les extensions d'image et ZIP +
      • Exécute uniquement les modules \ref hash_db_page, \ref EXIF_parser_page, \ref file_type_identification_page et \ref embedded_file_extractor_page +
      • Utilise les ensembles de hachage connus de fichiers pédo-pornographiques, en suivant les instructions de la section \ref live_triage_hash_db pour les copier sur la clé USB +
      +
    + +Sur les lieux de la perquisition: +
      +
    • Démarrez l'analyse: +
        +
      • Branchez le lecteur de triage en direct que vous avez créé au bureau sur l'ordinateur du suspect +
      • Lancer Autopsy à partir du fichier .bat +
      • \ref cases_page "Créer un cas" (enregistrement sur votre clé USB) +
      • Ajouter en \ref ds_local "source de données le lecteur local" +
          +
        • "C:" +
        • Choisissez de créer un VHD et de conserver l'emplacement par défaut +
        +
      +
    • Au fur et à mesure que l'analyse automatisée se poursuit: +
        +
      • Choisissez View->File Types->Images dans l'\ref tree_viewer_page "arborescence" et passez en revue les miniatures +
      • Attendez les hits de l'ensemble de hachage +
      • Examinez les fichiers EXIF +
      • \ref tagging_page "Marquez" tous les fichiers notables trouvés +
      +
    • Vous pouvez arrêter l'analyse à tout moment. Toutes les données lues jusqu'à présent seront dans le fichier VHD. +
    + +*/ \ No newline at end of file diff --git a/docs/doxygen-user_fr/troubleshooting.dox b/docs/doxygen-user_fr/troubleshooting.dox new file mode 100644 index 0000000000..a053e56f57 --- /dev/null +++ b/docs/doxygen-user_fr/troubleshooting.dox @@ -0,0 +1,134 @@ +/*! \page troubleshooting_page Dépannage + +[TOC] + + +Si vous rencontrez une erreur, nous vous encourageons à publier sur le forum (https://sleuthkit.discourse.group/), en précisant autant d'informations que possible: +
      +
    • Votre système d'exploitation et la version d'Autopsy +
    • Qu'est-ce qui a conduit à l'erreur. Par exemple: +
        +
      • Quel type de source de données était en cours de traitement? +
      • Quels modules d'acquisition étaient en cours d'exécution? Vous pouvez générer un \ref ingest_monitoring "instantané de la progression de l'acquisition" pour afficher l'état actuel de l'acquisition. +
      • Quelle visionneuse spécialisée utilisiez-vous? +
      +
    • L'erreur affichée à l'écran (le cas échéant) +
    • Une \ref troubleshooting_stack "capture du thread d'activité" ou une capture écran de l'\ref ingest_monitoring "instantané de la progression de l'acquisition" si Autopsy semble bloqué +
    • S'il y avait des erreurs dans les \ref troubleshooting_logs "logs" +
    + +\section troubleshooting_specific_issues Problèmes spécifiques +\subsection troubleshooting_fond_size Taille de police trop petite + +Sous Windows, vous pouvez apporter les modifications suivantes s'il est difficile de naviguer dans l'application dans les systèmes à haute résolution d'écran: + +
      +
    1. Faites un clic droit sur l'icône de l'application sur votre bureau, menu Démarrer, etc... +
    2. Choisissez Propriétés. +
    3. Accédez à l'onglet Compatibilité. +
    4. Cliquez sur le bouton "Modifier les paramètres PPP élevés". +
    5. Sélectionnez "Remplacer le comportement de mise à l'échelle PPP élevé". +
    6. Modifiez dans la liste déroulante "Mise à l'échelle effectuée par:" sur "Système". +
    7. Redémarrez Autopsy. +
    + +Sous Linux, vous pouvez fournir la taille de la police avec l'argument de ligne de commande "--fontsize XX", mais toutes les boîtes de dialogue ne répondent pas correctement et une partie du texte risque d'être coupée. + +\section troubleshooting_general Dépannage général + +\subsection troubleshooting_reset_ui Réinitialiser l'interface utilisateur + +Si la fenêtre d'Autopsy ne ressemble plus à la fenêtre par défaut : \ref uilayout_page (par exemple, si une visionneuse a disparu ou s'il y a un espace vide étrange), vous pouvez la réinitialiser. Pour ce faire, allez dans Window->Reset Windows. Cela entraînera le redémarrage d'Autopsy. Si vous avez un cas ouvert, il se rouvrira après la réinitialisation. + +\image html reset_windows.png + +Si la réinitialisation des fenêtres ne résout pas le problème, vous devrez peut-être supprimer votre dossier utilisateur comme décrit dans la section suivante. + +\subsection troubleshooting_user_folder Suppression du dossier utilisateur Autopsy + +Si Autopsy commence à se comporter de manière étrange, arrête complètement de se charger ou si des éléments de menu disparaissent, vous devrez probablement supprimer votre dossier utilisateur. Cela entrainera essentiellement une nouvelle installation. Sous Windows, le dossier utilisateur se trouve dans "C:\Users\(nom d'utilisateur)\AppData\Roaming\autopsy". +Notez que si vous supprimez ce dossier, vous perdrez tous vos paramètres d'Autopsy, y compris les listes de mots clés, les ensembles de fichiers intéressants et la configuration générale. Si vous souhaitez conserver ces paramètres, vous pouvez faire ce qui suit: +
      +
    • Faites une copie du dossier d'Autopsy. +
    • Supprimer le dossier d'Autopsy. +
    • Ouvrez Autopsy pour régénérer le dossier avec les paramètres par défaut. +
    • Fermez Autopsy et copiez les anciens fichiers de configuration qui semblent pertinents. Par exemple, si vous souhaitez restaurer vos ensembles de hachage, vous pourrez recopier le dossier "HashDatabases" et le fichier "hashLookup.settings". +
    + +Vous pouvez également copier le nouveau dossier utilisateur quelque part, déplacer votre ancienne version et remplacer les dossiers jusqu'à ce qu'il fonctionne à nouveau. + +\subsection troubleshooting_logs Affichage des journaux (logs) + +Les journaux sont généralement les plus utiles pour déterminer pourquoi une erreur s'est produite. Il existe deux ensembles de journaux: les journaux système et les journaux de cas. Il existe une option dans l'interface utilisateur pour ouvrir le dossier des journaux: + +\image html troubleshooting_log_menu.png + +Si vous avez un cas ouvert, cliquez sur "Help" puis "Open Log Folder" pour ouvrir le dossier contenant les journaux de cas. Sinon, ce sera le dossier des journaux système qui s'ouvrira. Vous pouvez également accéder à ces dossiers de manière classique: +
      +
    • Journaux de cas: (dossier du cas)\\Logs +
    • Journaux système: C:\\Users\\(nom d'utilisateur)\\AppData\\Roaming\\autopsy\\var\\log (pour Windows) +
    + +Dans les deux cas, le journal probablement le plus intéressante est "autopsy.log.0", bien qu'il puisse s'agir de l'une des anciennes versions si vous avez fermé et réouvert Autopsy depuis que l'erreur s'est produite. Vous rechercherez des entrées commençant par "SEVERE" et éventuellement "WARNING" s'il n'y a pas d'erreurs graves. Notez qu'il n'est pas inhabituel d'avoir de nombreux avertissements dans le journal. Voici un exemple d'erreur grave avec une trace de pile: + +\verbatim +Sep 23, 2020 9:48:24 AM org.sleuthkit.autopsy.casemodule.services.TagNameDefinition saveToCase +SEVERE: Error saving tag name definition +org.sleuthkit.datamodel.TskCoreException: Error adding row for Follow Up tag name to tag_names table + at org.sleuthkit.datamodel.SleuthkitCase.addOrUpdateTagName(SleuthkitCase.java:9846) + at org.sleuthkit.autopsy.casemodule.services.TagNameDefinition.saveToCase(TagNameDefinition.java:239) + at org.sleuthkit.autopsy.casemodule.services.TagsManager.(TagsManager.java:288) + at org.sleuthkit.autopsy.casemodule.services.Services.(Services.java:50) + at org.sleuthkit.autopsy.casemodule.Case.openCaseLevelServices(Case.java:2480) + at org.sleuthkit.autopsy.casemodule.Case.open(Case.java:1993) + at org.sleuthkit.autopsy.casemodule.Case.lambda$doOpenCaseAction$6(Case.java:1863) + at java.util.concurrent.FutureTask.run(FutureTask.java:266) + at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) + at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) + at java.lang.Thread.run(Thread.java:748) +Caused by: java.sql.SQLException: ResultSet closed + at org.sqlite.core.CoreResultSet.checkOpen(CoreResultSet.java:76) + at org.sqlite.jdbc3.JDBC3ResultSet.findColumn(JDBC3ResultSet.java:39) + at org.sqlite.jdbc3.JDBC3ResultSet.getLong(JDBC3ResultSet.java:422) + at com.mchange.v2.c3p0.impl.NewProxyResultSet.getLong(NewProxyResultSet.java:424) + at org.sleuthkit.datamodel.SleuthkitCase.addOrUpdateTagName(SleuthkitCase.java:9843) + ... 10 more +\endverbatim + +Si le message d'erreur ne vous aide pas à résoudre le problème vous-même, veuillez poster sur le forum y compris la trace de pile complète (si disponible). + +\subsection troubleshooting_stack Création d'une capture du thread d'activité + +Vous pouvez également générer une capture du thread de l'état actuel. Ceci est utile si un module d'acquisition ou un autre processus semble être bloqué. Pour générer une capture de thread, allez sur "Help" puis "Thread Dump" dans l'interface utilisateur. + +\image html troubleshooting_thread.png + +Vous verrez alors un fichier similaire à celui-ci dans une visionneuse de texte: + +\verbatim"Module-Actions" Id=222 RUNNABLE + at sun.management.ThreadImpl.getThreadInfo1(Native Method) + at sun.management.ThreadImpl.getThreadInfo(ThreadImpl.java:178) + at org.sleuthkit.autopsy.actions.ThreadDumpAction$ThreadDumper.createThreadDump(ThreadDumpAction.java:120) + at org.sleuthkit.autopsy.actions.ThreadDumpAction$ThreadDumper.doInBackground(ThreadDumpAction.java:91) + at org.sleuthkit.autopsy.actions.ThreadDumpAction$ThreadDumper.doInBackground(ThreadDumpAction.java:87) + at javax.swing.SwingWorker$1.call(SwingWorker.java:295) + at java.util.concurrent.FutureTask.run(FutureTask.java:266) + at javax.swing.SwingWorker.run(SwingWorker.java:334) + ... + + +"IM-start-ingest-jobs-0" Id=218 WAITING on java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject@7ceb341e + at sun.misc.Unsafe.park(Native Method) + - waiting on java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject@7ceb341e + at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) + at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039) + at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442) + at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074) + at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134) + at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) + at java.lang.Thread.run(Thread.java:748) +\endverbatim + +Si la capture de thread indique quelque chose à propos d'un blocage, cela vous indiquera d'où vient le problème. Veuillez signaler tout blocage sur le forum. Même si cela ne vous semble pas être le cas, la capture de thread pourra vous aider à diagnostiquer votre problème, alors pensez à l'inclure dans votre message. + +*/ \ No newline at end of file diff --git a/docs/doxygen-user_fr/ui_quick_search.dox b/docs/doxygen-user_fr/ui_quick_search.dox new file mode 100644 index 0000000000..76563ebfbd --- /dev/null +++ b/docs/doxygen-user_fr/ui_quick_search.dox @@ -0,0 +1,27 @@ +/*! \page ui_quick_search Recherche rapide de l'interface utilisateur + +[TOC] + + +La fonction de recherche rapide de l'interface utilisateur vous permet de rechercher une chaîne de caractères donnée dans les données d'un panneau. Elle ne recherchera pas les données dans les colonnes masquées ou les nœuds réduits. + +Comment l'utiliser +----- +Pour utiliser la recherche, vous devez sélectionner n'importe quel élément dans la zone où vous souhaitez lancer la recherche et commencer à taper des caractères au clavier. Si la recherche rapide de l'interface utilisateur est disponible dans la zone que vous avez sélectionnée, un champ de recherche apparaîtra dans le coin inférieur gauche de la zone. Au fur et à mesure que vous tapez la chaîne de caractères que vous souhaitez rechercher, elle se met à jour automatiquement pour sélectionner l'un des résultats correspondant à votre chaîne. Vous pouvez basculer entre les résultats qui correspondent à la chaîne de caractères que vous avez tapée avec les touches haut et bas. La recherche ne prend pas en charge l'utilisation d'expressions régulières mais prendra en compte n'importe quelle sous-chaîne dans les champs qu'elle recherche, pas seulement au début du champ. +\image html quick_search_result.png + +Configuration +----- +Par défaut, la recherche s'effectuera sur les données de tous les champs qui se trouvent dans la zone actuellement sélectionnée. La recherche ignorera également la casse par défaut. Si vous souhaitez modifier l'un de ces comportements par défaut, vous pouvez cliquer sur la loupe avec la flèche vers le bas et configurer les colonnes sur lesquelles la recherche devra s'effectuer, ainsi que le respect ou non de la casse. +\image html quick_search_configuration.png + +Où elle peut être utilisé +----- +- L'\ref tree_viewer_page "arborescence" +- La \ref result_viewer_page "vue tableau" +- Le \ref case_open "panneau d'ouverture des cas multi-utilisateurs" +- La vue tableau de l’outil de visualisation \ref timeline_page "Timeline" +- Le panneau de navigation de l'outil de visualisation \ref communications_page "Communications" +- Le panneau de messages de l'outil de visualisation \ref communications_page "Communications" + +*/ diff --git a/docs/doxygen-user_fr/uilayout.dox b/docs/doxygen-user_fr/uilayout.dox new file mode 100644 index 0000000000..ac46fed6b4 --- /dev/null +++ b/docs/doxygen-user_fr/uilayout.dox @@ -0,0 +1,44 @@ +/*! \page uilayout_page Dispositions de l'interface utilisateur + + +[TOC] + + +
    +\section ui_overview Aperçu + +Les principales zones de l'interface utilisateur (UI) d'Autopsy sont les suivants: +- \ref ui_tree, encadrée en vert sur le côté gauche +- \ref ui_results, encadrée en bleu sur le côté supérieur droit +- \ref ui_content, encadrée en rouge en bas à droite +- \ref ui_keyword, encadrée en magenta dans le coin supérieur droit +- \ref ui_status, encadrée en violet dans le coin inférieur droit + +Vous pouvez personnaliser l'affichage des données dans l'interface utilisateur via le panneau \ref view_options_page. + +\image html ui-layout-1.PNG + +\section ui_tree Tree Viewer (Arborescence) + +L'arborescence sur le côté gauche est le niveau supérieur de l'interface utilisateur. La sélection d'éléments dans l'arborescence entraînera l'affichage de leur contenu dans la visionneuse de résultats à droite. Vous pouvez parcourir les fichiers de l'image, trouver les résultats enregistrés générés par les \ref ingest_page "modules d'acquisition", et voir les résultats de \ref tagging_page et les \ref reporting_page. Voir la page \subpage tree_viewer_page pour plus d'informations. + +\section ui_results Result Viewer (Visionneuse de résultats) + +Les fenêtres de la visionneuse de résultats se trouvent dans la zone supérieure droite de l'interface et affichent les résultats de la sélection d'un élément dans l'arborescence. Les colonnes affichées dépendront de ce qui a été sélectionné dans l'arborescence - les fichiers afficheront des éléments tels que le chemin, la taille et la date de création tandis qu'un contact affichera son nom, son numéro de téléphone et son adresse e-mail. La sélection d'un élément dans la visionneuse de résultats affichera des détails sur l'élément dans la visionneuse de contenu ci-dessous. Voir la page \ref result_viewer_page pour plus d'informations. + +\section ui_content Content Viewer (Visionneuse de contenu) + +La visionneuse de contenu se trouve dans la zone inférieure droite de l'interface. Cette zone est utilisée pour afficher un fichier spécifique dans une variété de formats. Il existe différents onglets pour différents visualiseurs. Tous les onglets ne prennent pas en charge tous les types de fichiers, seuls certains d'entre eux seront donc activés. Pour afficher les données dans cette zone, un fichier doit être sélectionné dans la fenêtre de la visionneuse de résultats. + +Cette zone fait partie d'un framework de plug-ins, ce qui signifie que vous pouvez installer des modules qui ajouteront plus de types de visualiseurs. + +Pour plus d'informations, voir la page \ref content_viewer_page page. + +\section ui_keyword Keyword Search (Recherche par mots clés) +La fonction de recherche par mot-clé permet à l'utilisateur de rechercher des mots-clés dans une ou plusieurs sources de données contenues dans le cas actuel. Elle est traitée plus en détail ici: \ref keyword_search_page + +\section ui_status Status Area (Zone d'Etat) +La zone d'état affichera des barres de progression pendant l'exécution des modules d'acquisition. Cela indique visuellement quelle partie du traitement est déjà terminée. Vous pouvez cliquer sur les barres de progression pour voir plus de détails ou pour annuler les travaux d'acquisition. +
    + +*/ diff --git a/docs/doxygen-user_fr/updating_interesting_file_sets.dox b/docs/doxygen-user_fr/updating_interesting_file_sets.dox new file mode 100644 index 0000000000..a81783922d --- /dev/null +++ b/docs/doxygen-user_fr/updating_interesting_file_sets.dox @@ -0,0 +1,26 @@ +/*! \page update_interesting_files_page Mise à jour des ensembles officiels de fichiers intéressants + +Le module \ref interesting_files_identifier_page contient plusieurs ensembles de règles officiels. Vous pouvez sélectionner un ensemble de règles pour afficher les règles qu'il contient au milieu de la fenêtre, sur le côté droit. + +\image html InterestingFiles/if_official_rule_details.png + +Si vous pensez qu'une ou plusieurs règles devraient être incluses dans un ensemble de règles officiel, vous pouvez soumettre vos nouvelles règles en utilisant le processus ci-dessous. Consultez la section \ref interesting_files_config pour des instructions générales sur la création et l'édition d'ensembles de fichiers intéressants. + +
      +
    1. Créez un nouvel ensemble de fichiers intéressants. Donnez-lui un nom similaire à celui de l'ensemble que vous souhaitez mettre à jour pour indiquer clairement à quel ensemble appartiennent vos nouvelles règles. Ne copiez pas l'ensemble de règles existant. + +\image html InterestingFiles/if_create_set.png + +
    2. Créez votre(vos) règle(s). Assurez-vous que chaque règle a un "Nom de règle" qui identifie l'application qu'elle doit détecter. Cliquez sur le bouton "Apply" sur le panneau principal lorsque vous avez terminé. + +\image html InterestingFiles/if_new_rule.png + +
    3. Exportez l'ensemble au format XML. + +\image html InterestingFiles/if_export.png + +
    4. Créez une "Issue" sur le Github Autopsy qui identifie l'ensemble à mettre à jour et quelles applications ont été ajoutées, puis joignez le XML. Aller sur: https://github.com/sleuthkit/autopsy/issues +
    + + +*/ \ No newline at end of file diff --git a/docs/doxygen-user_fr/view_options.dox b/docs/doxygen-user_fr/view_options.dox new file mode 100644 index 0000000000..ae52c3b1fa --- /dev/null +++ b/docs/doxygen-user_fr/view_options.dox @@ -0,0 +1,91 @@ +/*! \page view_options_page Options d'affichage + +[TOC] + + +Les options "View" vous permettent de configurer la façon dont les données sont affichées dans l'interface utilisateur Autopsy. + +Il existe deux façons d'accéder aux options. La première méthode consiste à utiliser l'icône "engrenage" au-dessus de l'arborescence des répertoires: + +\image html view_options_gear.png + +La deuxième façon consiste à aller dans Tools->Options puis sélectionner l'onglet "Views": + +\image html view_options_options_panel.png + + +\section view_options_global Paramètres globaux ("Global Settings") + +Les paramètres de cette section persistent jusqu'à la fermeture de l'application. + +\subsection view_options_hide_known Masquer les fichiers connus ("Hide known files") + +Cette option vous permet de masquer les fichiers marqués comme "known" par le module \ref hash_db_page. L'option permettant de masquer les fichiers connus dans la zone des sources de données empêchera ces fichiers d'être affichés dans la vue des résultats. De même, l'option permettant de masquer le slack dans la zone des vues empêchera les fichiers slack d'apparaître sous la section "Views" de l'arborescence. + +\subsection view_options_hide_slack Masquer les fichiers slack ("Hide slack files") + +Autopsy cré des fichiers slack (avec l'extension "-slack") à partir de tout espace supplémentaire à la fin d'un fichier. Ces fichiers peuvent être affichés ou masqués dans la zone des sources de données et/ou dans la zone des vues. Ce qui suit montre un fichier slack dans la visionneuse de résultats: + +\image html view_options_show_slack.png + +Cochez l'option permettant de masquer le slack dans la zone des sources de données ("Data Sources area") empêchera l'affichage du fichier de slack: + +\image html view_options_hide_slack.png + +De même, l'option permettant de masquer le slack dans la zone des vues ("Views area") empêchera les fichiers slack d'apparaître sous la section "Views" de l'arborescence. + +\subsection view_options_hide_tags Masquer les balises des autres utilisateurs ("Hide other user's tags") + +Cette option vous permet de masquer les balises des autres utilisateurs dans la section "Tags" de l'arborescence. Voir \ref user_tags pour plus de détails. + +\subsection view_options_cr_columns Ne pas ajouter les colonnes pour ("Do not add columns for") S(core), C(omments) et (O)ccurrences + +Par défaut, les trois premières colonnes de la visionneuse de résultats après le nom de fichier sont nommées "S", "C" et "O". Le remplissage de ces colonnes peut augmenter les temps de chargement. Voir la section \ref result_viewer_sco pour plus d'informations. + +\subsection view_options_paging Pagination ("Maximum number of Results to show in table") + +Par défaut, seuls 10 000 résultats seront affichés dans la visionneuse de résultats. Vous pouvez modifier ce seuil ici. Le mettre à zéro désactivera la pagination. + +\subsection view_options_content_viewer Sélection de la visionneuse de contenu ("When selecting a file") + +Par défaut, la \ref content_viewer_page tente de sélectionner l'onglet le plus pertinent à afficher lors du choix d'un nœud. Si vous souhaitez modifier ce comportement pour rester sur la même visionneuse de contenu lors du changement de nœuds, choisissez l'option "Stay on the same file viewer". + +\subsection view_options_time Format de l'heure ("When displaying times") + +Les horodatages peuvent être affichés en heure locale ou dans un fuseau horaire sélectionné dans la liste déroulante. + +\image html view_options_local_time.png +
    +\image html view_options_gmt.png + +\subsection view_options_translate Traduire du texte ("Translate text") + +Si vous avez une module de \ref machine_translation_page installé, cette option ajoutera une colonne à la \ref result_viewer_page pour afficher le nom traduit des fichiers et des dossiers. + +\section view_options_case Paramètres de cas actuels ("Current Case Settings") + +Les paramètres de cette section s'appliquent uniquement au cas actuel. + +\subsection view_options_group Regroupement des sources de données + +Les options ici vous permettent de choisir comment afficher les données dans l'\ref ui_tree "Arborescence". La première option ("Group by Data Type") affiche les résultats combinés pour toutes les sources de données. Tous les nœuds de l'arborescence contiendront des résultats combinés pour toutes les sources de données du cas. + +\image html views_standard_tree.png + +La deuxième option ("Group by Person/Host") sépare les résultats de chaque source de données et organise les sources de données en \ref ui_tree_persons "personne" et \ref ui_tree_hosts "hôte". + +\image html views_grouped_tree.png + +\section view_options_session Paramètres de session actuels ("Current Session Settings") + +Les paramètres de la session en cours seront en vigueur jusqu'à ce que vous fermiez l'application. + +\subsection view_options_rejected Masquer les résultats rejetés ("Hide redjected results") + +Les comptes peuvent être approuvés ou rejetés par l'utilisateur, comme indiqué dans la capture d'écran ci-dessous. + +\image html view_options_reject_account.png + +Les comptes rejetés ne seront pas inclus dans le rapport et seront par défaut masqués dans l'interface utilisateur. Si vous rejetez accidentellement un compte et devez changer son statut, ou si vous souhaitez simplement afficher les comptes rejetés, vous pouvez décocher l'option "Hide rejected results". + +*/ \ No newline at end of file diff --git a/docs/doxygen-user_fr/vm_module.dox b/docs/doxygen-user_fr/vm_module.dox new file mode 100644 index 0000000000..7da4ffa774 --- /dev/null +++ b/docs/doxygen-user_fr/vm_module.dox @@ -0,0 +1,10 @@ +/*! \page vm_extractor_page Virtual Machine Extractor (Extracteur de machine virtuelle) + +Le module "Virtual Machine Extractor" ajoute au cas toutes les machines virtuelles qu'il trouve dans une source de données en tant que nouvelles sources de données. Cela inclut les fichiers de machines virtuelles (.vmdk) et fichiers de disque dur virtuel (.vhd). Notez que chaque disque virtuel sera extrait dans le dossier du cas. + +Dans l'exemple ci-dessous, la source de données d'origine "testImage.img" contenait un fichier VHD. Ce fichier "alphaFiles.vhd" a été ajouté au cas en tant que nouvelle source de données, et il a été +traité par les mêmes modules d’acquisition que ceux exécutés sur l’image d’origine. + +\image html virtual_machine_extractor_results.png + +*/ \ No newline at end of file diff --git a/docs/doxygen-user_fr/volatility_dsp.dox b/docs/doxygen-user_fr/volatility_dsp.dox new file mode 100644 index 0000000000..7bbe4c0321 --- /dev/null +++ b/docs/doxygen-user_fr/volatility_dsp.dox @@ -0,0 +1,37 @@ +/*! \page volatility_dsp_page Processeur de source de données Volatility + +[TOC] + + +\section Aperçu + +Le processeur de source de données Volatility exécute Volatility sur une image mémoire et enregistre les résultats individuels du module Volatility. Si l'image disque associée à l'image mémoire est également disponible, elle créera des artefacts d'élément intéressant reliant les résultats de Volatility aux fichiers de l'image disque. + +Le module \ref experimental_page doit être activé pour exécuter ce module. + +\section Usage + +Si une image disque est associée à votre image mémoire, commencez par intégrer l'image disque dans le cas. Ensuite allez sur "Add Data Source" et sélectionnez "Memory Image File". + +\image html volatility_dsp_select.png + +Sur l'écran suivant, vous pouvez sélectionner votre image mémoire, puis ajuster les paramètres pour choisir un profil et les plugins de Volatility à exécuter. + +\image html volatility_dsp_config.PNG + +Ensuite, vous verrez le panneau de configuration des modules d'acquisition. Aucun module d'acquisition ne sera exécuté lors de l'utilisation du processeur de source de données Volatility, il vous suffit donc de cliquer sur le bouton "Next". Quand il se termine, vous pouvez avoir des erreurs non critiques. Celles-ci proviennent souvent du fait que le processeur de source de données est incapable de trouver des fichiers dans l'image disque d'origine. Si vous n'avez pas ajouté d'image disque associée avant d'exécuter le processeur de source de données Volatility sur l'image mémoire, il y aura un grand nombre d'erreurs mais la sortie du module Volatility sera toujours disponible. + +\section Résultats + +Il existe deux types de résultats qui proviennent de l'exécution du processeur de source de données Volatility: "Module Output" (sortie du module) et "Interesting Items" (éléments intéressants) (si l'image disque a été ajoutée). La section "Module Output" se trouve sous l'image mémoire dans l'arborescence. + +\image html volatility_dsp_module_output.PNG + +Vous pouvez également voir la sortie de Volatility sous "ModuleOutput/Volatility" dans le dossier du cas d'Autopsy. La section "Interesting Items" lie les chemins d'éléments trouvés par Volatility avec les fichiers de l'image disque. Si aucune image disque n'a été ajoutée, il n'y aura pas de "Interesting Items". + +\image html volatility_dsp_interesting_items.PNG + + + + +*/ \ No newline at end of file diff --git a/docs/doxygen-user_fr/workflow.dox b/docs/doxygen-user_fr/workflow.dox new file mode 100644 index 0000000000..28dc80ce67 --- /dev/null +++ b/docs/doxygen-user_fr/workflow.dox @@ -0,0 +1,10 @@ +/*! \page workflow_page Flux de travail d'Autopsy + +L'analyse des données dans Autopsy utilise le flux de travail suivant: +-# Créer un cas: un cas est un conteneur pour une ou plusieurs sources de données. Il faut en créer un avant l'analyse des données. Voir \ref cases_page pour plus de détails. +-# Ajouter une source de données: une ou plusieurs sources de données sont ajoutées au cas. Les sources de données incluent les images disque et les fichiers locaux. Voir \ref ds_page pour plus de détails. +-# Analyser avec des Ingest Modules (modules d'acquisition): une fois la source de données ajoutée, les modules d'acquisition fonctionnent en arrière-plan pour analyser les données. Les résultats s’affichent dans l'interface en temps réel et fournissent des alertes si nécessaire. Exemples de modules d'acquisition: \ref hash_db_page "calcul et recherche de hachage", \ref keyword_search_page "recherche de mots-clés" ou \ref recent_activity_page "extraction d'artefacts Web". Des modules tiers peuvent être développés et ajoutés aux pipelines. Voir \ref ingest_page. +-# Analyser manuellement: l'utilisateur navigue dans l'interface, le contenu du fichier et les résultats du module d'acquisition pour identifier les preuves. Les éléments intéressants peuvent être marqués pour un rapport et une analyse ultérieurs. +-# Générer un rapport: l'utilisateur lance un rapport final basé sur les marquages ou les résultats sélectionnés. + +*/ diff --git a/docs/doxygen-user_fr/yara.dox b/docs/doxygen-user_fr/yara.dox new file mode 100644 index 0000000000..9d7dd98fe6 --- /dev/null +++ b/docs/doxygen-user_fr/yara.dox @@ -0,0 +1,50 @@ +/*! \page yara_page YARA Analyzer (Analyseur YARA) + +[TOC] + + +\section yara_overview Aperçu + +Le module "YARA Analyzer" utilise un ensemble de règles pour rechercher dans les fichiers des modèles textuels ou binaires. YARA a été conçu pour l'analyse des logiciels malveillants, mais peut être utilisé pour rechercher tout type de fichiers. Pour plus d'informations sur YARA, voir https://virustotal.github.io/yara/. + +\section yara_config Configuration + +Pour créer et modifier vos ensembles de règles, allez dans "Tools", "Options" puis sélectionnez l'onglet "Yara Rule Sets". + +\image html yara_options.png + +Les ensembles de règles YARA sont stockés dans les répertoires du dossier Autopsy de l'utilisateur. Pour créer un nouvel ensemble de règles, cliquez sur le bouton "New Set" en bas à gauche et saisissez le nom de votre nouvel ensemble. + +\image html yara_new_rule_set.png + +Une fois votre nouvel ensemble de règles sélectionné, cliquez sur le bouton "Open Folder" pour accéder au dossier de règles nouvellement créé. Vous pouvez désormais copier les fichiers YARA existants dans ce dossier pour les inclure dans l'ensemble de règles. Vous trouverez des informations sur la rédaction des règles YARA ici et de nombreuses règles YARA existantes peuvent être trouvées grâce à une recherche sur le Web. À titre d'exemple très simple, nous ajouterons cette règle à un ensemble de règles pour rechercher les fichiers contenant les mots "hello" et "world": + +\verbatim +rule HelloWorldRule +{ + strings: + $part1 = "hello" nocase + $part2 = "world" nocase + + condition: + $part1 and $part2 +} +\endverbatim + +Une fois que vous avez ajouté vos règles au dossier, cliquez sur le bouton "Refresh File List" pour les afficher dans le panneau d'options. + +\section yara_running Exécution du module + +Pour activer le module d'acquisition YARA Analyzer, cochez la case dans l'\ref ingest_configure "écran de configuration des modules d'acquisition (Configure Ingest Modules)". + +\image html yara_ingest_settings.png + +Assurez-vous que tous les ensembles de règles que vous souhaitez exécuter sont cochés. Vous pouvez également choisir de les appliquer sur tous les fichiers ou uniquement sur des fichiers exécutables. + +\section yara_results Affichage des résultats + +Les résultats sont affichés dans l'arborescence sous "Extracted Content". + +\image html yara_results.png + +*/ diff --git a/docs/doxygen/Doxyfile b/docs/doxygen/Doxyfile index fba973919f..7c230015ff 100644 --- a/docs/doxygen/Doxyfile +++ b/docs/doxygen/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NAME = "Autopsy" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 4.18.0 +PROJECT_NUMBER = 4.19.0 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears a the top of each page and should give viewer a @@ -1066,7 +1066,7 @@ GENERATE_HTML = YES # The default directory is: html. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_OUTPUT = api-docs/4.18.0/ +HTML_OUTPUT = api-docs/4.19.0/ # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each # generated HTML page (for example: .htm, .php, .asp). diff --git a/nbproject/project.properties b/nbproject/project.properties index 2b71bc4a1f..16be0556f0 100644 --- a/nbproject/project.properties +++ b/nbproject/project.properties @@ -4,7 +4,7 @@ app.title=Autopsy ### lowercase version of above app.name=${branding.token} ### if left unset, version will default to today's date -app.version=4.18.0 +app.version=4.19.0 ### build.type must be one of: DEVELOPMENT, RELEASE #build.type=RELEASE build.type=DEVELOPMENT diff --git a/pythonExamples/dataSourceIngestModule.py b/pythonExamples/dataSourceIngestModule.py index 3645945aa7..bfe745b3a4 100644 --- a/pythonExamples/dataSourceIngestModule.py +++ b/pythonExamples/dataSourceIngestModule.py @@ -37,6 +37,7 @@ from java.lang import System from java.util.logging import Level from org.sleuthkit.datamodel import SleuthkitCase from org.sleuthkit.datamodel import AbstractFile +from org.sleuthkit.datamodel import Score from org.sleuthkit.datamodel import ReadContentInputStream from org.sleuthkit.datamodel import BlackboardArtifact from org.sleuthkit.datamodel import BlackboardAttribute @@ -85,6 +86,7 @@ class SampleJythonDataSourceIngestModuleFactory(IngestModuleFactoryAdapter): # Data Source-level ingest module. One gets created per data source. # TODO: Rename this to something more specific. Could just remove "Factory" from above name. class SampleJythonDataSourceIngestModule(DataSourceIngestModule): + LIKELY_NOTABLE_SCORE = Score(Score.Significance.LIKELY_NOTABLE, Score.MethodCategory.AUTO) _logger = Logger.getLogger(SampleJythonDataSourceIngestModuleFactory.moduleName) @@ -142,7 +144,7 @@ class SampleJythonDataSourceIngestModule(DataSourceIngestModule): # artfiact. Refer to the developer docs for other examples. attrs = ArrayList() attrs.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME, SampleJythonDataSourceIngestModuleFactory.moduleName, "Test file")) - art = file.newAnalysisResult(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT, Score.SCORE_UNKNOWN, None, None, None, attrs) + art = file.newAnalysisResult(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT, self.LIKELY_NOTABLE_SCORE, None, "Test file", None, attrs) try: # index the artifact for keyword search diff --git a/pythonExamples/fileIngestModule.py b/pythonExamples/fileIngestModule.py index a76d5c240e..e4aa12bab7 100644 --- a/pythonExamples/fileIngestModule.py +++ b/pythonExamples/fileIngestModule.py @@ -35,6 +35,7 @@ import jarray import inspect from java.lang import System from java.util.logging import Level +from org.sleuthkit.datamodel import Score from org.sleuthkit.datamodel import SleuthkitCase from org.sleuthkit.datamodel import AbstractFile from org.sleuthkit.datamodel import ReadContentInputStream @@ -88,6 +89,7 @@ class SampleJythonFileIngestModuleFactory(IngestModuleFactoryAdapter): # TODO: Rename this to something more specific. Could just remove "Factory" from above name. # Looks at the attributes of the passed in file. class SampleJythonFileIngestModule(FileIngestModule): + LIKELY_NOTABLE_SCORE = Score(Score.Significance.LIKELY_NOTABLE, Score.MethodCategory.AUTO) _logger = Logger.getLogger(SampleJythonFileIngestModuleFactory.moduleName) @@ -130,7 +132,7 @@ class SampleJythonFileIngestModule(FileIngestModule): attrs = ArrayList() attrs.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME, SampleJythonFileIngestModuleFactory.moduleName, "Text Files")) - art = file.newAnalysisResult(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT, Score.SCORE_UNKNOWN, None, None, None, attrs) + art = file.newAnalysisResult(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT, self.LIKELY_NOTABLE_SCORE, None, "Text Files", None, attrs) try: diff --git a/release_scripts/localization_scripts/lastupdated.properties b/release_scripts/localization_scripts/lastupdated.properties index c31c7c9180..7039028e04 100644 --- a/release_scripts/localization_scripts/lastupdated.properties +++ b/release_scripts/localization_scripts/lastupdated.properties @@ -1,2 +1,2 @@ -#Fri Feb 12 16:56:29 UTC 2021 +#Mon Jul 12 13:22:00 UTC 2021 bundles.ja.lastupdated=c2a4ececfba59d230d1a263f7124e67f88e8d3e6 diff --git a/test/script/tskdbdiff.py b/test/script/tskdbdiff.py index 796d0f1f9f..fc9498d4c6 100644 --- a/test/script/tskdbdiff.py +++ b/test/script/tskdbdiff.py @@ -412,13 +412,14 @@ class TskGuidUtils: """ @staticmethod - def _get_guid_dict(db_conn, select_statement, delim=""): + def _get_guid_dict(db_conn, select_statement, delim="", normalizer: Union[Callable[[str], str], None] = None): """ Retrieves a dictionary mapping the first item selected to a concatenation of the remaining values. Args: db_conn: The database connection. select_statement: The select statement. delim: The delimiter for how row data from index 1 to end shall be concatenated. + normalizer: Means of normalizing the generated string or None. Returns: A dictionary mapping the key (the first item in the select statement) to a concatenation of the remaining values. @@ -428,7 +429,10 @@ class TskGuidUtils: ret_dict = {} for row in cursor: # concatenate value rows with delimiter filtering out any null values. - ret_dict[row[0]] = delim.join([str(col) for col in filter(lambda col: col is not None, row[1:])]) + value_str = delim.join([str(col) for col in filter(lambda col: col is not None, row[1:])]) + if normalizer: + value_str = normalizer(value_str) + ret_dict[row[0]] = value_str return ret_dict @@ -442,14 +446,16 @@ class TskGuidUtils: Returns: The instance of this class. """ - guid_files = TskGuidUtils._get_guid_dict(db_conn, "SELECT obj_id, parent_path, name FROM tsk_files") + guid_files = TskGuidUtils._get_guid_dict(db_conn, "SELECT obj_id, parent_path, name FROM tsk_files", + normalizer=normalize_file_path) guid_vs_parts = TskGuidUtils._get_guid_dict(db_conn, "SELECT obj_id, addr, start FROM tsk_vs_parts", "_") guid_vs_info = TskGuidUtils._get_guid_dict(db_conn, "SELECT obj_id, vs_type, img_offset FROM tsk_vs_info", "_") guid_fs_info = TskGuidUtils._get_guid_dict(db_conn, "SELECT obj_id, img_offset, fs_type FROM tsk_fs_info", "_") guid_image_names = TskGuidUtils._get_guid_dict(db_conn, "SELECT obj_id, name FROM tsk_image_names " "WHERE sequence=0") guid_os_accounts = TskGuidUtils._get_guid_dict(db_conn, "SELECT os_account_obj_id, addr FROM tsk_os_accounts") - guid_reports = TskGuidUtils._get_guid_dict(db_conn, "SELECT obj_id, path FROM reports") + guid_reports = TskGuidUtils._get_guid_dict(db_conn, "SELECT obj_id, path FROM reports", + normalizer=normalize_file_path) objid_artifacts = TskGuidUtils._get_guid_dict(db_conn, "SELECT blackboard_artifacts.artifact_obj_id, " @@ -862,7 +868,6 @@ def normalize_unalloc_files(path_str: Union[str, None]) -> Union[str, None]: Returns: The path string where timestamps are removed from unalloc strings. """ - # takes a file name like "Unalloc_30580_7466496_2980941312" and removes the object id to become # "Unalloc_7466496_2980941312" return None if path_str is None else re.sub('Unalloc_[0-9]+_', 'Unalloc_', path_str) @@ -881,6 +886,17 @@ def normalize_regripper_files(path_str: Union[str, None]) -> Union[str, None]: return None if path_str is None else re.sub(r'regripper-[0-9]+-full', 'regripper-full', path_str) +def normalize_file_path(path_str: Union[str, None]) -> Union[str, None]: + """ + Normalizes file paths removing or replacing pieces that will change from run to run (i.e. object id) + Args: + path_str: The original path string. + + Returns: The normalized path string + """ + return normalize_unalloc_files(normalize_regripper_files(path_str)) + + def normalize_tsk_files(guid_util: TskGuidUtils, row: Dict[str, any]) -> Dict[str, any]: """ Normalizes files table rows. @@ -902,8 +918,8 @@ def normalize_tsk_files(guid_util: TskGuidUtils, row: Dict[str, any]) -> Dict[st row_copy['obj_id'] = MASKED_OBJ_ID row_copy['os_account_obj_id'] = 'MASKED_OS_ACCOUNT_OBJ_ID' - row_copy['parent_path'] = normalize_unalloc_files(row['parent_path']) - row_copy['name'] = normalize_unalloc_files(row['name']) + row_copy['parent_path'] = normalize_file_path(row['parent_path']) + row_copy['name'] = normalize_file_path(row['name']) return row_copy @@ -971,7 +987,7 @@ def normalize_tsk_objects_path(guid_util: TskGuidUtils, objid: int, path = os.path.join(*path_parts) if len(path_parts) > 0 else '/' - return normalize_regripper_files(normalize_unalloc_files(path)) + return path def normalize_tsk_objects(guid_util: TskGuidUtils, row: Dict[str, any]) -> Dict[str, any]: @@ -1004,43 +1020,51 @@ TableNormalization = Union[IGNORE_TABLE, NormalizeRow] This dictionary maps tables where data should be specially handled to how they should be handled. """ TABLE_NORMALIZATIONS: Dict[str, TableNormalization] = { - "image_gallery_groups_seen": IGNORE_TABLE, "blackboard_artifacts": IGNORE_TABLE, "blackboard_attributes": IGNORE_TABLE, - "tsk_files": NormalizeRow(normalize_tsk_files), - "tsk_vs_parts": NormalizeColumns({ - "obj_id": MASKED_OBJ_ID + "data_source_info": NormalizeColumns({ + "device_id": "{device id}", + "added_date_time": "{dateTime}" }), "image_gallery_groups": NormalizeColumns({ "group_id": MASKED_ID }), - "tsk_files_path": NormalizeRow(normalize_tsk_files_path), - "tsk_file_layout": NormalizeColumns({ - "obj_id": lambda guid_util, col: normalize_unalloc_files(guid_util.get_guid_for_file_objid(col)) - }), - "tsk_objects": NormalizeRow(normalize_tsk_objects), + "image_gallery_groups_seen": IGNORE_TABLE, + "ingest_jobs": NormalizeRow(normalize_ingest_jobs), "reports": NormalizeColumns({ "obj_id": MASKED_OBJ_ID, "path": "AutopsyTestCase", "crtime": 0 }), - "data_source_info": NormalizeColumns({ - "device_id": "{device id}", - "added_date_time": "{dateTime}" + "tsk_aggregate_score": NormalizeColumns({ + "obj_id": lambda guid_util, col: guid_util.get_guid_for_objid(col, omitted_value="Object ID Omitted"), + "data_source_obj_id": lambda guid_util, col: guid_util.get_guid_for_objid(col, omitted_value="Data Source Object ID Omitted"), }), - "ingest_jobs": NormalizeRow(normalize_ingest_jobs), - "tsk_examiners": NormalizeColumns({ - "login_name": "{examiner_name}" + "tsk_analysis_results": NormalizeColumns({ + "artifact_obj_id": + lambda guid_util, col: guid_util.get_guid_for_objid(col, omitted_value="Artifact Object ID Omitted"), }), + "tsk_data_artifacts": NormalizeColumns({ + "artifact_obj_id": + lambda guid_util, col: guid_util.get_guid_for_file_objid(col, omitted_value="Artifact Object ID Omitted"), + "os_account_obj_id": + lambda guid_util, col: guid_util.get_guid_for_file_objid(col, omitted_value="Account Object ID Omitted"), + }), + "tsk_event_descriptions": NormalizeRow(normalize_tsk_event_descriptions), "tsk_events": NormalizeColumns({ "event_id": "MASKED_EVENT_ID", "event_description_id": None, "time": None, }), - "tsk_event_descriptions": NormalizeRow(normalize_tsk_event_descriptions), - "tsk_os_accounts": NormalizeColumns({ - "os_account_obj_id": MASKED_OBJ_ID + "tsk_examiners": NormalizeColumns({ + "login_name": "{examiner_name}" }), + "tsk_files": NormalizeRow(normalize_tsk_files), + "tsk_file_layout": NormalizeColumns({ + "obj_id": lambda guid_util, col: guid_util.get_guid_for_file_objid(col) + }), + "tsk_files_path": NormalizeRow(normalize_tsk_files_path), + "tsk_objects": NormalizeRow(normalize_tsk_objects), "tsk_os_account_attributes": NormalizeColumns({ "id": MASKED_ID, "os_account_obj_id": lambda guid_util, col: guid_util.get_guid_for_accountid(col), @@ -1050,11 +1074,11 @@ TABLE_NORMALIZATIONS: Dict[str, TableNormalization] = { "id": MASKED_ID, "os_account_obj_id": lambda guid_util, col: guid_util.get_guid_for_accountid(col) }), - "tsk_data_artifacts": NormalizeColumns({ - "artifact_obj_id": - lambda guid_util, col: guid_util.get_guid_for_file_objid(col, omitted_value="Artifact Object ID Omitted"), - "os_account_obj_id": - lambda guid_util, col: guid_util.get_guid_for_file_objid(col, omitted_value="Account Object ID Omitted"), + "tsk_os_accounts": NormalizeColumns({ + "os_account_obj_id": MASKED_OBJ_ID + }), + "tsk_vs_parts": NormalizeColumns({ + "obj_id": MASKED_OBJ_ID }) } diff --git a/thirdparty/rr-full/plugins/samparse.pl b/thirdparty/rr-full/plugins/samparse.pl index 8046708b3b..f8997b632f 100644 --- a/thirdparty/rr-full/plugins/samparse.pl +++ b/thirdparty/rr-full/plugins/samparse.pl @@ -23,6 +23,7 @@ #----------------------------------------------------------- package samparse; use strict; +use Encode::Unicode; my %config = (hive => "SAM", hivemask => 2, @@ -364,7 +365,8 @@ sub _translateSID { #--------------------------------------------------------------------- sub _uniToAscii { my $str = $_[0]; - $str =~ s/\x00//g; + Encode::from_to($str,'UTF-16LE','utf8'); + $str = Encode::decode_utf8($str); return $str; } diff --git a/thunderbirdparser/nbproject/project.xml b/thunderbirdparser/nbproject/project.xml index 318b4e36ee..333bbf6578 100644 --- a/thunderbirdparser/nbproject/project.xml +++ b/thunderbirdparser/nbproject/project.xml @@ -54,7 +54,7 @@ 10 - 10.23 + 10.24 diff --git a/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/Bundle_ja.properties b/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/Bundle_ja.properties index 2453e9652b..9f786a7b38 100644 --- a/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/Bundle_ja.properties +++ b/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/Bundle_ja.properties @@ -1,21 +1,26 @@ -#Tue Aug 18 18:09:21 UTC 2020 +#Mon Jul 12 13:22:00 UTC 2021 MboxParser.handleAttch.errMsg.failedToCreateOnDisk=MBOX\u306e\u6dfb\u4ed8\u30d5\u30a1\u30a4\u30eb\u3092\u30c7\u30a3\u30b9\u30af\: {0}\u3078\u62bd\u51fa\u3059\u308b\u306e\u306b\u5931\u6557\u3057\u307e\u3057\u305f MboxParser.handleAttch.failedWriteToDisk=\u6dfb\u4ed8\u30d5\u30a1\u30a4\u30eb\u3092\u30c7\u30a3\u30b9\u30af\: {0}\u3078\u62bd\u51fa\u3059\u308b\u306e\u306b\u5931\u6557\u3057\u307e\u3057\u305f MboxParser.parse.errMsg.couldntFindCharset=\u9069\u5207\u306a\u6587\u5b57\u30bb\u30c3\u30c8\u30a8\u30f3\u30b3\u30fc\u30c0\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f\u3002 MboxParser.parse.errMsg.failedToParseNMsgs={0}\u500b\u306eEmail\u30e1\u30c3\u30bb\u30fc\u30b8\u306e\u62bd\u51fa\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 MboxParser.parse.errMsg.failedToReadFile=\u30c7\u30a3\u30b9\u30af\u304b\u3089mbox\u30d5\u30a1\u30a4\u30eb\u3092\u8aad\u307f\u53d6\u308c\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +MimeJ4MessageParser.handleAttch.noOpenCase.errMsg=\u30aa\u30fc\u30d7\u30f3\u30b1\u30fc\u30b9\u53d6\u5f97\u4e2d\u306e\u4f8b\u5916\u3002 OpenIDE-Module-Display-Category=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb OpenIDE-Module-Long-Description=\ Email\u30d1\u30fc\u30b5\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u3002\n\n\u3053\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u306fMBOX\u3068PST e-mail\u30d5\u30a1\u30a4\u30eb\u3092\u62bd\u51fa\u3057\u3001Blackboard\u306b\u8f09\u305b\u307e\u3059\u3002 \nThunderbird\u306eMBOX\u30d5\u30a1\u30a4\u30eb\u306e\u30d5\u30a9\u30eb\u30c0\u69cb\u9020\u3092\u628a\u63e1\u3057\u3066\u3044\u307e\u3059\u3002 OpenIDE-Module-Name=Email\u30d1\u30fc\u30b5 OpenIDE-Module-Short-Description=MOBX\u3068PST\u30d5\u30a1\u30a4\u30eb\u3092\u30d1\u30fc\u30b9\u3057\u307e\u3059 PstParser.extractAttch.errMsg.failedToExtractToDisk=PST\u306e\u6dfb\u4ed8\u30d5\u30a1\u30a4\u30eb\u3092\u30c7\u30a3\u30b9\u30af\: {0}\u3078\u62bd\u51fa\u3059\u308b\u306e\u306b\u5931\u6557\u3057\u307e\u3057\u305f +PstParser.noOpenCase.errMsg=\u30aa\u30fc\u30d7\u30f3\u30b1\u30fc\u30b9\u53d6\u5f97\u4e2d\u306e\u4f8b\u5916\u3002 PstParser.parse.errMsg.failedToParseNMsgs={0}\u500b\u306eEmail\u30e1\u30c3\u30bb\u30fc\u30b8\u306e\u62bd\u51fa\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 +ThunderbirdMboxFileIngestModule.addArtifact.indexError.message=\u30ad\u30fc\u30ef\u30fc\u30c9\u691c\u7d22\u3067\u63a2\u3057\u305f\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u306e\u96fb\u5b50\u30e1\u30fc\u30eb\u30e1\u30c3\u30bb\u30fc\u30b8\u306e\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u4f5c\u6210\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 ThunderbirdMboxFileIngestModule.encryptionFileLevel=\u30d5\u30a1\u30a4\u30eb\u30ec\u30d9\u30eb\u6697\u53f7\u5316 +ThunderbirdMboxFileIngestModule.errorMessage.outOfDiskSpace=\u30c7\u30a3\u30b9\u30af\u5bb9\u91cf\u304c\u4e0d\u8db3\u3057\u3066\u3044\u307e\u3059\u3002 '{0}'\uff08id \= {1}\uff09\u3092\u30b3\u30d4\u30fc\u3057\u3066\u89e3\u6790\u3067\u304d\u307e\u305b\u3093\u3002 ThunderbirdMboxFileIngestModule.getDesc.text=\u3053\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u306fmbox\u304a\u3088\u3073pst/ost\u30d5\u30a1\u30a4\u30eb\u3092\u691c\u51fa\u3001\u30d1\u30fc\u30b9\u3057\u3001blackboard\u306eEmail\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u306b\u7d50\u679c\u3092\u6295\u5165\u3057\u307e\u3059\u3002 ThunderbirdMboxFileIngestModule.handleAttch.addAttachmentsErrorMsg=\u30e1\u30fc\u30eb\u30e1\u30c3\u30bb\u30fc\u30b8\u306b\u6dfb\u4ed8\u30d5\u30a1\u30a4\u30eb\u3092\u8ffd\u52a0\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 ThunderbirdMboxFileIngestModule.handleAttch.errMsg={0}\u306e\u51e6\u7406\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f ThunderbirdMboxFileIngestModule.handleAttch.errMsg.details={0}\u306e\u540d\u79f0\u3092\u6301\u3064\u6dfb\u4ed8\u30d5\u30a1\u30a4\u30eb\u3092\u30b1\u30fc\u30b9\u306b\u8ffd\u52a0\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 ThunderbirdMboxFileIngestModule.moduleName=Email\u30d1\u30fc\u30b5 +ThunderbirdMboxFileIngestModule.noOpenCase.errMsg=\u30aa\u30fc\u30d7\u30f3\u30b1\u30fc\u30b9\u53d6\u5f97\u4e2d\u306e\u4f8b\u5916\u3002 ThunderbirdMboxFileIngestModule.notAvail=\u4f7f\u7528\u3067\u304d\u307e\u305b\u3093 ThunderbirdMboxFileIngestModule.processMBox.errProcFile.msg={0}\u306e\u51e6\u7406\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f ThunderbirdMboxFileIngestModule.processMBox.errProcFile.msg2={0}\u306e\u51e6\u7406\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f @@ -24,3 +29,5 @@ ThunderbirdMboxFileIngestModule.processPst.errMsg.outOfDiskSpace=\u30c7\u30a3\u3 ThunderbirdMboxFileIngestModule.processPst.errProcFile.details=Outlook 2003\u304a\u3088\u3073\u305d\u308c\u4ee5\u964d\u306e\u30d0\u30fc\u30b8\u30e7\u30f3\u304b\u3089\u306e\u30d5\u30a1\u30a4\u30eb\u3057\u304b\u30b5\u30dd\u30fc\u30c8\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002 ThunderbirdMboxFileIngestModule.processPst.errProcFile.msg={0}\u306e\u51e6\u7406\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f ThunderbirdMboxFileIngestModule.processPst.errProcFile.msg2={0}\u306e\u51e6\u7406\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f +ThunderbirdMboxFileIngestModule.processPst.indexError.message=\u30ad\u30fc\u30ef\u30fc\u30c9\u691c\u7d22\u3067\u6697\u53f7\u5316\u3055\u308c\u305f\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u306e\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u4f5c\u6210\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 +VcardParser.addContactArtifact.indexError=\u30ad\u30fc\u30ef\u30fc\u30c9\u691c\u7d22\u306e\u9023\u7d61\u5148\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u306e\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u4f5c\u6210\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002 diff --git a/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdMboxFileIngestModule.java b/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdMboxFileIngestModule.java index f18dfd3ae8..ddeb88e7da 100644 --- a/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdMboxFileIngestModule.java +++ b/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdMboxFileIngestModule.java @@ -242,13 +242,14 @@ public final class ThunderbirdMboxFileIngestModule implements FileIngestModule { // encrypted pst: Add encrypted file artifact try { + String encryptionFileLevel = NbBundle.getMessage(this.getClass(), + "ThunderbirdMboxFileIngestModule.encryptionFileLevel"); BlackboardArtifact artifact = abstractFile.newAnalysisResult( - new BlackboardArtifact.Type(BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_DETECTED), - Score.SCORE_UNKNOWN, null, null, null, Arrays.asList( + BlackboardArtifact.Type.TSK_ENCRYPTION_DETECTED, + Score.SCORE_NOTABLE, null, null, encryptionFileLevel, Arrays.asList( new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, EmailParserModuleFactory.getModuleName(), - NbBundle.getMessage(this.getClass(), - "ThunderbirdMboxFileIngestModule.encryptionFileLevel")) + encryptionFileLevel) )) .getAnalysisResult(); diff --git a/unix_setup.sh b/unix_setup.sh index 40b1d858b4..6554689384 100644 --- a/unix_setup.sh +++ b/unix_setup.sh @@ -5,7 +5,7 @@ # NOTE: update_sleuthkit_version.pl updates this value and relies # on it keeping the same name and whitespace. Don't change it. -TSK_VERSION=4.10.2 +TSK_VERSION=4.11.0 # In the beginning...