From 48ec3d7aa7e2545448cdeb03e35b9437928a093b Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Tue, 20 Jul 2021 08:01:20 -0400 Subject: [PATCH 01/17] updates for analysis results in sample code --- pythonExamples/dataSourceIngestModule.py | 6 ++---- pythonExamples/fileIngestModule.py | 5 ++--- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/pythonExamples/dataSourceIngestModule.py b/pythonExamples/dataSourceIngestModule.py index bfe745b3a4..1ae5e97593 100644 --- a/pythonExamples/dataSourceIngestModule.py +++ b/pythonExamples/dataSourceIngestModule.py @@ -86,8 +86,6 @@ 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) def log(self, level, msg): @@ -143,8 +141,8 @@ class SampleJythonDataSourceIngestModule(DataSourceIngestModule): # Make an artifact on the blackboard. TSK_INTERESTING_FILE_HIT is a generic type of # 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, self.LIKELY_NOTABLE_SCORE, None, "Test file", None, attrs) + attrs.add(BlackboardAttribute(BlackboardAttribute.Type.TSK_SET_NAME, SampleJythonDataSourceIngestModuleFactory.moduleName, "Test file")) + art = file.newAnalysisResult(BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT, Score.SCORE_LIKELY_NOTABLE, None, "Test file", None, attrs).getAnalysisResult() try: # index the artifact for keyword search diff --git a/pythonExamples/fileIngestModule.py b/pythonExamples/fileIngestModule.py index e4aa12bab7..8ac292ab1f 100644 --- a/pythonExamples/fileIngestModule.py +++ b/pythonExamples/fileIngestModule.py @@ -89,7 +89,6 @@ 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,9 +129,9 @@ class SampleJythonFileIngestModule(FileIngestModule): # Make an artifact on the blackboard. TSK_INTERESTING_FILE_HIT is a generic type of # artifact. Refer to the developer docs for other examples. attrs = ArrayList() - attrs.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME, + attrs.add(BlackboardAttribute(BlackboardAttribute.Type.TSK_SET_NAME, SampleJythonFileIngestModuleFactory.moduleName, "Text Files")) - art = file.newAnalysisResult(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT, self.LIKELY_NOTABLE_SCORE, None, "Text Files", None, attrs) + art = file.newAnalysisResult(BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT, Score.SCORE_LIKELY_NOTABLE, None, "Text Files", None, attrs).getAnalysisResult() try: From 8279df1a3b4db57888a9b0743af34152d9681104 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Tue, 20 Jul 2021 12:02:02 -0400 Subject: [PATCH 02/17] updates to sample code --- .../FindContactsDb.py | 31 +++++++------------ .../FindBigRoundFiles.py | 21 ++++++------- pythonExamples/Registry_Example.py | 25 +++++++-------- pythonExamples/dataSourceIngestModule.py | 15 ++++----- pythonExamples/fileIngestModule.py | 18 ++++------- 5 files changed, 47 insertions(+), 63 deletions(-) diff --git a/pythonExamples/Aug2015DataSourceTutorial/FindContactsDb.py b/pythonExamples/Aug2015DataSourceTutorial/FindContactsDb.py index 7217584315..d3071bfe4b 100644 --- a/pythonExamples/Aug2015DataSourceTutorial/FindContactsDb.py +++ b/pythonExamples/Aug2015DataSourceTutorial/FindContactsDb.py @@ -40,7 +40,7 @@ from java.lang import Class from java.lang import System from java.sql import DriverManager, SQLException from java.util.logging import Level -from java.util import ArrayList +from java.util import Arrays from java.io import File from org.sleuthkit.datamodel import SleuthkitCase from org.sleuthkit.datamodel import AbstractFile @@ -162,30 +162,21 @@ class ContactsDbIngestModule(DataSourceIngestModule): # Make an artifact on the blackboard, TSK_CONTACT and give it attributes for each of the fields - art = file.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT) - attributes = ArrayList() + art = file.newDataArtifact(BlackboardArtifact.Type.TSK_CONTACT, Arrays.asList( + BlackboardAttribute(BlackboardAttribute.Type.TSK_NAME_PERSON, + ContactsDbIngestModuleFactory.moduleName, name), + BlackboardAttribute(BlackboardAttribute.Type.TSK_EMAIL, + ContactsDbIngestModuleFactory.moduleName, email), + BlackboardAttribute(BlackboardAttribute.Type.TSK_PHONE_NUMBER, + ContactsDbIngestModuleFactory.moduleName, phone) + )) - attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME_PERSON.getTypeID(), - ContactsDbIngestModuleFactory.moduleName, name)) - - attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL.getTypeID(), - ContactsDbIngestModuleFactory.moduleName, email)) - - attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER.getTypeID(), - ContactsDbIngestModuleFactory.moduleName, phone)) - - art.addAttributes(attributes) try: # index the artifact for keyword search - blackboard.indexArtifact(art) + blackboard.postArtifact(art, ContactsDbIngestModuleFactory.moduleName) except Blackboard.BlackboardException as e: self.log(Level.SEVERE, "Error indexing artifact " + art.getDisplayName()) - - # Fire an event to notify the UI and others that there are new artifacts - IngestServices.getInstance().fireModuleDataEvent( - ModuleDataEvent(ContactsDbIngestModuleFactory.moduleName, - BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT, None)) - + # Clean up stmt.close() dbConn.close() diff --git a/pythonExamples/July2015FileTutorial_BigRound/FindBigRoundFiles.py b/pythonExamples/July2015FileTutorial_BigRound/FindBigRoundFiles.py index e24a8395fc..ae8235d007 100644 --- a/pythonExamples/July2015FileTutorial_BigRound/FindBigRoundFiles.py +++ b/pythonExamples/July2015FileTutorial_BigRound/FindBigRoundFiles.py @@ -57,6 +57,8 @@ from org.sleuthkit.autopsy.casemodule import Case from org.sleuthkit.autopsy.casemodule.services import Services from org.sleuthkit.autopsy.casemodule.services import FileManager from org.sleuthkit.autopsy.casemodule.services import Blackboard +from org.sleuthkit.datamodel import Score +from java.util import Arrays # Factory that defines the name and details of the module and allows Autopsy # to create instances of the modules that will do the anlaysis. @@ -120,22 +122,19 @@ class FindBigRoundFilesIngestModule(FileIngestModule): # Make an artifact on the blackboard. TSK_INTERESTING_FILE_HIT is a generic type of # artifact. Refer to the developer docs for other examples. - art = file.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT) - att = BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID(), - FindBigRoundFilesIngestModuleFactory.moduleName, "Big and Round Files") - art.addAttribute(att) + art = file.newAnalysisResult(BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT, Score.SCORE_LIKELY_NOTABLE, + None, "Big and Round Files", None, + Arrays.asList( + BlackboardAttribute(BlackboardAttribute.Type.TSK_SET_NAME, + FindBigRoundFilesIngestModuleFactory.moduleName, + "Big and Round Files"))).getAnalysisResult() try: - # index the artifact for keyword search - blackboard.indexArtifact(art) + # post the artifact for listeners of artifact events + blackboard.postArtifact(art) except Blackboard.BlackboardException as e: self.log(Level.SEVERE, "Error indexing artifact " + art.getDisplayName()) - # Fire an event to notify the UI and others that there is a new artifact - IngestServices.getInstance().fireModuleDataEvent( - ModuleDataEvent(FindBigRoundFilesIngestModuleFactory.moduleName, - BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT, None)) - return IngestModule.ProcessResult.OK # Where any shutdown code is run and resources are freed. diff --git a/pythonExamples/Registry_Example.py b/pythonExamples/Registry_Example.py index 885d682ab5..b980d4b831 100644 --- a/pythonExamples/Registry_Example.py +++ b/pythonExamples/Registry_Example.py @@ -45,7 +45,7 @@ from java.lang import Class from java.lang import System from java.sql import DriverManager, SQLException from java.util.logging import Level -from java.util import ArrayList +from java.util import Arrays from org.sleuthkit.datamodel import SleuthkitCase from org.sleuthkit.datamodel import AbstractFile from org.sleuthkit.datamodel import ReadContentInputStream @@ -171,11 +171,12 @@ class RegistryExampleIngestModule(DataSourceIngestModule): # Setup Artifact and Attributes try: - artID = skCase.addArtifactType( "TSK_REGISTRY_RUN_KEYS", "Registry Run Keys") + skCase.addBlackboardArtifactType("TSK_REGISTRY_RUN_KEYS", "Registry Run Keys", + BlackboardArtifact.Category.DATA_ARTIFACT) except: self.log(Level.INFO, "Artifacts Creation Error, some artifacts may not exist now. ==> ") - artId = skCase.getArtifactTypeID("TSK_REGISTRY_RUN_KEYS") + artType = skCase.getArtifactType("TSK_REGISTRY_RUN_KEYS") try: attributeIdRunKeyName = skCase.addArtifactAttributeType("TSK_REG_RUN_KEY_NAME", BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, "Run Key Name") @@ -198,17 +199,15 @@ class RegistryExampleIngestModule(DataSourceIngestModule): # RefistryKeysFound is a list that contains a list with the following records abstractFile, Registry Key Location, Key Name, Key value for registryKey in self.registryKeysFound: - attributes = ArrayList() - art = registryKey[0].newArtifact(artId) - - attributes.add(BlackboardAttribute(attributeIdRegKeyLoc, moduleName, registryKey[1])) - attributes.add(BlackboardAttribute(attributeIdRunKeyName, moduleName, registryKey[2])) - attributes.add(BlackboardAttribute(attributeIdRunKeyValue, moduleName, registryKey[3])) - art.addAttributes(attributes) + art = registryKey[0].newDataArtifact(artType, Arrays.asList( + BlackboardAttribute(attributeIdRegKeyLoc, moduleName, registryKey[1]), + BlackboardAttribute(attributeIdRunKeyName, moduleName, registryKey[2]), + BlackboardAttribute(attributeIdRunKeyValue, moduleName, registryKey[3]) + )) - # index the artifact for keyword search + # post the artifact for listeners of artifact events try: - blackboard.indexArtifact(art) + skCase.getBlackboard().postArtifact(art) except: self._logger.log(Level.WARNING, "Error indexing artifact " + art.getDisplayName()) @@ -278,7 +277,7 @@ class RegistryExampleIngestModule(DataSourceIngestModule): return currentKey except: # Key not found - return null + return None diff --git a/pythonExamples/dataSourceIngestModule.py b/pythonExamples/dataSourceIngestModule.py index 1ae5e97593..1ecd859d9e 100644 --- a/pythonExamples/dataSourceIngestModule.py +++ b/pythonExamples/dataSourceIngestModule.py @@ -53,9 +53,8 @@ from org.sleuthkit.autopsy.casemodule import Case from org.sleuthkit.autopsy.casemodule.services import Services from org.sleuthkit.autopsy.casemodule.services import FileManager from org.sleuthkit.autopsy.casemodule.services import Blackboard -from org.sleuthkit.autopsy.casemodule.services import Blackboard from org.sleuthkit.datamodel import Score -from java.util import ArrayList +from java.util import Arrays # Factory that defines the name and details of the module and allows Autopsy # to create instances of the modules that will do the analysis. @@ -140,13 +139,15 @@ class SampleJythonDataSourceIngestModule(DataSourceIngestModule): # Make an artifact on the blackboard. TSK_INTERESTING_FILE_HIT is a generic type of # artfiact. Refer to the developer docs for other examples. - attrs = ArrayList() - attrs.add(BlackboardAttribute(BlackboardAttribute.Type.TSK_SET_NAME, SampleJythonDataSourceIngestModuleFactory.moduleName, "Test file")) - art = file.newAnalysisResult(BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT, Score.SCORE_LIKELY_NOTABLE, None, "Test file", None, attrs).getAnalysisResult() + attrs = Arrays.asList(BlackboardAttribute(BlackboardAttribute.Type.TSK_SET_NAME, + SampleJythonDataSourceIngestModuleFactory.moduleName, + "Test file")) + art = file.newAnalysisResult(BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT, Score.SCORE_LIKELY_NOTABLE, + None, "Test file", None, attrs).getAnalysisResult() try: - # index the artifact for keyword search - blackboard.indexArtifact(art) + # post the artifact for listeners of artifact events. + blackboard.postArtifact(art) except Blackboard.BlackboardException as e: self.log(Level.SEVERE, "Error indexing artifact " + art.getDisplayName()) diff --git a/pythonExamples/fileIngestModule.py b/pythonExamples/fileIngestModule.py index 8ac292ab1f..ea759ab144 100644 --- a/pythonExamples/fileIngestModule.py +++ b/pythonExamples/fileIngestModule.py @@ -55,8 +55,7 @@ from org.sleuthkit.autopsy.casemodule import Case from org.sleuthkit.autopsy.casemodule.services import Services from org.sleuthkit.autopsy.casemodule.services import FileManager from org.sleuthkit.autopsy.casemodule.services import Blackboard -from org.sleuthkit.datamodel import Score -from java.util import ArrayList +from java.util import Arrays # Factory that defines the name and details of the module and allows Autopsy # to create instances of the modules that will do the anlaysis. @@ -128,23 +127,18 @@ class SampleJythonFileIngestModule(FileIngestModule): # Make an artifact on the blackboard. TSK_INTERESTING_FILE_HIT is a generic type of # artifact. Refer to the developer docs for other examples. - attrs = ArrayList() - attrs.add(BlackboardAttribute(BlackboardAttribute.Type.TSK_SET_NAME, + attrs = Arrays.asList(BlackboardAttribute(BlackboardAttribute.Type.TSK_SET_NAME, SampleJythonFileIngestModuleFactory.moduleName, "Text Files")) - art = file.newAnalysisResult(BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT, Score.SCORE_LIKELY_NOTABLE, None, "Text Files", None, attrs).getAnalysisResult() + art = file.newAnalysisResult(BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT, Score.SCORE_LIKELY_NOTABLE, + None, "Text Files", None, attrs).getAnalysisResult() try: - # index the artifact for keyword search - blackboard.indexArtifact(art) + # post the artifact for listeners of artifact events + blackboard.postArtifact(art) except Blackboard.BlackboardException as e: self.log(Level.SEVERE, "Error indexing artifact " + art.getDisplayName()) - # Fire an event to notify the UI and others that there is a new artifact - IngestServices.getInstance().fireModuleDataEvent( - ModuleDataEvent(SampleJythonFileIngestModuleFactory.moduleName, - BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT, None)) - # For the example (this wouldn't be needed normally), we'll query the blackboard for data that was added # by other modules. We then iterate over its attributes. We'll just print them, but you would probably # want to do something with them. From c32ab89922a0d1b69fea957a5278cb0fb59e3d0d Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Tue, 20 Jul 2021 13:09:53 -0400 Subject: [PATCH 03/17] bug fixes --- pythonExamples/Aug2015DataSourceTutorial/FindContactsDb.py | 2 +- pythonExamples/Aug2015DataSourceTutorial/RunExe.py | 2 +- .../July2015FileTutorial_BigRound/FindBigRoundFiles.py | 4 ++-- pythonExamples/Registry_Example.py | 6 +++++- pythonExamples/dataSourceIngestModule.py | 4 ++-- pythonExamples/fileIngestModule.py | 4 ++-- 6 files changed, 13 insertions(+), 9 deletions(-) diff --git a/pythonExamples/Aug2015DataSourceTutorial/FindContactsDb.py b/pythonExamples/Aug2015DataSourceTutorial/FindContactsDb.py index d3071bfe4b..27f9be6161 100644 --- a/pythonExamples/Aug2015DataSourceTutorial/FindContactsDb.py +++ b/pythonExamples/Aug2015DataSourceTutorial/FindContactsDb.py @@ -113,7 +113,7 @@ class ContactsDbIngestModule(DataSourceIngestModule): progressBar.switchToIndeterminate() # Use blackboard class to index blackboard artifacts for keyword search - blackboard = Case.getCurrentCase().getServices().getBlackboard() + blackboard = Case.getCurrentCase().getSleuthkitCase().getBlackboard() # Find files named contacts.db, regardless of parent path fileManager = Case.getCurrentCase().getServices().getFileManager() diff --git a/pythonExamples/Aug2015DataSourceTutorial/RunExe.py b/pythonExamples/Aug2015DataSourceTutorial/RunExe.py index 4544c1884c..230aba11f8 100644 --- a/pythonExamples/Aug2015DataSourceTutorial/RunExe.py +++ b/pythonExamples/Aug2015DataSourceTutorial/RunExe.py @@ -145,7 +145,7 @@ class RunExeIngestModule(DataSourceIngestModule): # Add each argument in its own line. I.e. "-f foo" would be two calls to .add() cmd.add(imagePaths[0]) - processBuilder = ProcessBuilder(cmd); + processBuilder = ProcessBuilder(cmd) processBuilder.redirectOutput(reportFile) ExecUtil.execute(processBuilder, DataSourceIngestModuleProcessTerminator(self.context)) diff --git a/pythonExamples/July2015FileTutorial_BigRound/FindBigRoundFiles.py b/pythonExamples/July2015FileTutorial_BigRound/FindBigRoundFiles.py index ae8235d007..5bf710e9d5 100644 --- a/pythonExamples/July2015FileTutorial_BigRound/FindBigRoundFiles.py +++ b/pythonExamples/July2015FileTutorial_BigRound/FindBigRoundFiles.py @@ -109,7 +109,7 @@ class FindBigRoundFilesIngestModule(FileIngestModule): def process(self, file): # Use blackboard class to index blackboard artifacts for keyword search - blackboard = Case.getCurrentCase().getServices().getBlackboard() + blackboard = Case.getCurrentCase().getSleuthkitCase().getBlackboard() # Skip non-files if ((file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) or @@ -131,7 +131,7 @@ class FindBigRoundFilesIngestModule(FileIngestModule): try: # post the artifact for listeners of artifact events - blackboard.postArtifact(art) + blackboard.postArtifact(art, FindBigRoundFilesIngestModuleFactory.moduleName) except Blackboard.BlackboardException as e: self.log(Level.SEVERE, "Error indexing artifact " + art.getDisplayName()) diff --git a/pythonExamples/Registry_Example.py b/pythonExamples/Registry_Example.py index b980d4b831..fb06e5c971 100644 --- a/pythonExamples/Registry_Example.py +++ b/pythonExamples/Registry_Example.py @@ -179,6 +179,10 @@ class RegistryExampleIngestModule(DataSourceIngestModule): artType = skCase.getArtifactType("TSK_REGISTRY_RUN_KEYS") try: + addArtifactAttributeType(String + attrTypeString, TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE + valueType, String + displayName) attributeIdRunKeyName = skCase.addArtifactAttributeType("TSK_REG_RUN_KEY_NAME", BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, "Run Key Name") except: self.log(Level.INFO, "Attributes Creation Error, TSK_REG_RUN_KEY_NAME, May already exist. ") @@ -207,7 +211,7 @@ class RegistryExampleIngestModule(DataSourceIngestModule): # post the artifact for listeners of artifact events try: - skCase.getBlackboard().postArtifact(art) + skCase.getBlackboard().postArtifact(art, moduleName) except: self._logger.log(Level.WARNING, "Error indexing artifact " + art.getDisplayName()) diff --git a/pythonExamples/dataSourceIngestModule.py b/pythonExamples/dataSourceIngestModule.py index 1ecd859d9e..ecb4f01477 100644 --- a/pythonExamples/dataSourceIngestModule.py +++ b/pythonExamples/dataSourceIngestModule.py @@ -115,7 +115,7 @@ class SampleJythonDataSourceIngestModule(DataSourceIngestModule): progressBar.switchToIndeterminate() # Use blackboard class to index blackboard artifacts for keyword search - blackboard = Case.getCurrentCase().getServices().getBlackboard() + blackboard = Case.getCurrentCase().getSleuthkitCase().getBlackboard() # For our example, we will use FileManager to get all # files with the word "test" @@ -147,7 +147,7 @@ class SampleJythonDataSourceIngestModule(DataSourceIngestModule): try: # post the artifact for listeners of artifact events. - blackboard.postArtifact(art) + blackboard.postArtifact(art, SampleJythonDataSourceIngestModuleFactory.moduleName) except Blackboard.BlackboardException as e: self.log(Level.SEVERE, "Error indexing artifact " + art.getDisplayName()) diff --git a/pythonExamples/fileIngestModule.py b/pythonExamples/fileIngestModule.py index ea759ab144..f72f1c4792 100644 --- a/pythonExamples/fileIngestModule.py +++ b/pythonExamples/fileIngestModule.py @@ -117,7 +117,7 @@ class SampleJythonFileIngestModule(FileIngestModule): return IngestModule.ProcessResult.OK # Use blackboard class to index blackboard artifacts for keyword search - blackboard = Case.getCurrentCase().getServices().getBlackboard() + blackboard = Case.getCurrentCase().getSleuthkitCase().getBlackboard() # For an example, we will flag files with .txt in the name and make a blackboard artifact. if file.getName().lower().endswith(".txt"): @@ -135,7 +135,7 @@ class SampleJythonFileIngestModule(FileIngestModule): try: # post the artifact for listeners of artifact events - blackboard.postArtifact(art) + blackboard.postArtifact(art, SampleJythonFileIngestModuleFactory.moduleName) except Blackboard.BlackboardException as e: self.log(Level.SEVERE, "Error indexing artifact " + art.getDisplayName()) From 928ef9e33d9035f4d7b39404683f4d80f4936472 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Tue, 20 Jul 2021 13:50:03 -0400 Subject: [PATCH 04/17] bug fixes --- pythonExamples/Registry_Example.py | 10 +++------- .../Sept2015ReportTutorial_CSV/CsvReportModule.py | 7 ++++--- pythonExamples/reportmodule.py | 4 ++-- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/pythonExamples/Registry_Example.py b/pythonExamples/Registry_Example.py index fb06e5c971..c9228d376f 100644 --- a/pythonExamples/Registry_Example.py +++ b/pythonExamples/Registry_Example.py @@ -179,20 +179,16 @@ class RegistryExampleIngestModule(DataSourceIngestModule): artType = skCase.getArtifactType("TSK_REGISTRY_RUN_KEYS") try: - addArtifactAttributeType(String - attrTypeString, TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE - valueType, String - displayName) attributeIdRunKeyName = skCase.addArtifactAttributeType("TSK_REG_RUN_KEY_NAME", BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, "Run Key Name") - except: + except: self.log(Level.INFO, "Attributes Creation Error, TSK_REG_RUN_KEY_NAME, May already exist. ") try: attributeIdRunKeyValue = skCase.addArtifactAttributeType("TSK_REG_RUN_KEY_VALUE", BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, "Run Key Value") - except: + except: self.log(Level.INFO, "Attributes Creation Error, TSK_REG_RUN_KEY_VALUE, May already exist. ") try: attributeIdRegKeyLoc = skCase.addArtifactAttributeType("TSK_REG_KEY_LOCATION", BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, "Registry Key Location") - except: + except: self.log(Level.INFO, "Attributes Creation Error, TSK_REG_KEY_LOCATION, May already exist. ") attributeIdRunKeyName = skCase.getAttributeType("TSK_REG_RUN_KEY_NAME") diff --git a/pythonExamples/Sept2015ReportTutorial_CSV/CsvReportModule.py b/pythonExamples/Sept2015ReportTutorial_CSV/CsvReportModule.py index 5cf87cdc93..11bf862b95 100644 --- a/pythonExamples/Sept2015ReportTutorial_CSV/CsvReportModule.py +++ b/pythonExamples/Sept2015ReportTutorial_CSV/CsvReportModule.py @@ -37,6 +37,7 @@ import os +import codecs from java.lang import System from java.util.logging import Level from org.sleuthkit.datamodel import TskData @@ -72,11 +73,11 @@ class CSVReportModule(GeneralReportModuleAdapter): # The 'baseReportDir' object being passed in is a string with the directory that reports are being stored in. Report should go into baseReportDir + getRelativeFilePath(). # The 'progressBar' object is of type ReportProgressPanel. # See: http://sleuthkit.org/autopsy/docs/api-docs/latest/classorg_1_1sleuthkit_1_1autopsy_1_1report_1_1_report_progress_panel.html - def generateReport(self, baseReportDir, progressBar): + def generateReport(self, reportSettings, progressBar): # Open the output file. - fileName = os.path.join(baseReportDir, self.getRelativeFilePath()) - report = open(fileName, 'w') + fileName = os.path.join(reportSettings.getReportDirectoryPath(), self.getRelativeFilePath()) + report = codecs.open(fileName, "w", "utf-8") # Query the database for the files (ignore the directories) sleuthkitCase = Case.getCurrentCase().getSleuthkitCase() diff --git a/pythonExamples/reportmodule.py b/pythonExamples/reportmodule.py index 33c6941eda..b1b194b3c4 100644 --- a/pythonExamples/reportmodule.py +++ b/pythonExamples/reportmodule.py @@ -70,7 +70,7 @@ class SampleGeneralReportModule(GeneralReportModuleAdapter): # The 'baseReportDir' object being passed in is a string with the directory that reports are being stored in. Report should go into baseReportDir + getRelativeFilePath(). # The 'progressBar' object is of type ReportProgressPanel. # See: http://sleuthkit.org/autopsy/docs/api-docs/latest/classorg_1_1sleuthkit_1_1autopsy_1_1report_1_1_report_progress_panel.html - def generateReport(self, baseReportDir, progressBar): + def generateReport(self, reportSettings, progressBar): # For an example, we write a file with the number of files created in the past 2 weeks # Configure progress bar for 2 tasks @@ -95,7 +95,7 @@ class SampleGeneralReportModule(GeneralReportModuleAdapter): progressBar.increment() # Write the count to the report file. - fileName = os.path.join(baseReportDir, self.getRelativeFilePath()) + fileName = os.path.join(reportSettings.getReportDirectoryPath(), self.getRelativeFilePath()) report = open(fileName, 'w') report.write("file count = %d" % fileCount) report.close() From 9ece3e41ed0078d68e3cf5d8e1bb3700d2ea14c0 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Tue, 20 Jul 2021 13:54:00 -0400 Subject: [PATCH 05/17] revert registry example --- pythonExamples/Registry_Example.py | 31 +++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/pythonExamples/Registry_Example.py b/pythonExamples/Registry_Example.py index c9228d376f..885d682ab5 100644 --- a/pythonExamples/Registry_Example.py +++ b/pythonExamples/Registry_Example.py @@ -45,7 +45,7 @@ from java.lang import Class from java.lang import System from java.sql import DriverManager, SQLException from java.util.logging import Level -from java.util import Arrays +from java.util import ArrayList from org.sleuthkit.datamodel import SleuthkitCase from org.sleuthkit.datamodel import AbstractFile from org.sleuthkit.datamodel import ReadContentInputStream @@ -171,24 +171,23 @@ class RegistryExampleIngestModule(DataSourceIngestModule): # Setup Artifact and Attributes try: - skCase.addBlackboardArtifactType("TSK_REGISTRY_RUN_KEYS", "Registry Run Keys", - BlackboardArtifact.Category.DATA_ARTIFACT) + artID = skCase.addArtifactType( "TSK_REGISTRY_RUN_KEYS", "Registry Run Keys") except: self.log(Level.INFO, "Artifacts Creation Error, some artifacts may not exist now. ==> ") - artType = skCase.getArtifactType("TSK_REGISTRY_RUN_KEYS") + artId = skCase.getArtifactTypeID("TSK_REGISTRY_RUN_KEYS") try: attributeIdRunKeyName = skCase.addArtifactAttributeType("TSK_REG_RUN_KEY_NAME", BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, "Run Key Name") - except: + except: self.log(Level.INFO, "Attributes Creation Error, TSK_REG_RUN_KEY_NAME, May already exist. ") try: attributeIdRunKeyValue = skCase.addArtifactAttributeType("TSK_REG_RUN_KEY_VALUE", BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, "Run Key Value") - except: + except: self.log(Level.INFO, "Attributes Creation Error, TSK_REG_RUN_KEY_VALUE, May already exist. ") try: attributeIdRegKeyLoc = skCase.addArtifactAttributeType("TSK_REG_KEY_LOCATION", BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, "Registry Key Location") - except: + except: self.log(Level.INFO, "Attributes Creation Error, TSK_REG_KEY_LOCATION, May already exist. ") attributeIdRunKeyName = skCase.getAttributeType("TSK_REG_RUN_KEY_NAME") @@ -199,15 +198,17 @@ class RegistryExampleIngestModule(DataSourceIngestModule): # RefistryKeysFound is a list that contains a list with the following records abstractFile, Registry Key Location, Key Name, Key value for registryKey in self.registryKeysFound: - art = registryKey[0].newDataArtifact(artType, Arrays.asList( - BlackboardAttribute(attributeIdRegKeyLoc, moduleName, registryKey[1]), - BlackboardAttribute(attributeIdRunKeyName, moduleName, registryKey[2]), - BlackboardAttribute(attributeIdRunKeyValue, moduleName, registryKey[3]) - )) + attributes = ArrayList() + art = registryKey[0].newArtifact(artId) + + attributes.add(BlackboardAttribute(attributeIdRegKeyLoc, moduleName, registryKey[1])) + attributes.add(BlackboardAttribute(attributeIdRunKeyName, moduleName, registryKey[2])) + attributes.add(BlackboardAttribute(attributeIdRunKeyValue, moduleName, registryKey[3])) + art.addAttributes(attributes) - # post the artifact for listeners of artifact events + # index the artifact for keyword search try: - skCase.getBlackboard().postArtifact(art, moduleName) + blackboard.indexArtifact(art) except: self._logger.log(Level.WARNING, "Error indexing artifact " + art.getDisplayName()) @@ -277,7 +278,7 @@ class RegistryExampleIngestModule(DataSourceIngestModule): return currentKey except: # Key not found - return None + return null From ad9b499fee861da454e44245e57d0cc20a6a6800 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Tue, 20 Jul 2021 14:23:04 -0400 Subject: [PATCH 06/17] comment update --- pythonExamples/reportmodule.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pythonExamples/reportmodule.py b/pythonExamples/reportmodule.py index b1b194b3c4..df973e05fb 100644 --- a/pythonExamples/reportmodule.py +++ b/pythonExamples/reportmodule.py @@ -67,7 +67,9 @@ class SampleGeneralReportModule(GeneralReportModuleAdapter): return "sampleReport.txt" # TODO: Update this method to make a report - # The 'baseReportDir' object being passed in is a string with the directory that reports are being stored in. Report should go into baseReportDir + getRelativeFilePath(). + # The 'reportSettings' object being passed in is an instance of org.sleuthkit.autopsy.report.GeneralReportSettings. + # GeneralReportSettings.getReportDirectoryPath() is the directory that reports are being stored in. + # Report should go into GeneralReportSettings.getReportDirectoryPath() + getRelativeFilePath(). # The 'progressBar' object is of type ReportProgressPanel. # See: http://sleuthkit.org/autopsy/docs/api-docs/latest/classorg_1_1sleuthkit_1_1autopsy_1_1report_1_1_report_progress_panel.html def generateReport(self, reportSettings, progressBar): From 4e69e4c471af329e4078dffe56c6167c342d3079 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Wed, 21 Jul 2021 09:35:26 -0400 Subject: [PATCH 07/17] updates to registry example --- pythonExamples/Registry_Example.py | 58 +++++++++++++++--------------- 1 file changed, 30 insertions(+), 28 deletions(-) diff --git a/pythonExamples/Registry_Example.py b/pythonExamples/Registry_Example.py index 885d682ab5..f99ead8086 100644 --- a/pythonExamples/Registry_Example.py +++ b/pythonExamples/Registry_Example.py @@ -45,12 +45,13 @@ from java.lang import Class from java.lang import System from java.sql import DriverManager, SQLException from java.util.logging import Level -from java.util import ArrayList +from java.util import Arrays from org.sleuthkit.datamodel import SleuthkitCase from org.sleuthkit.datamodel import AbstractFile from org.sleuthkit.datamodel import ReadContentInputStream from org.sleuthkit.datamodel import BlackboardArtifact from org.sleuthkit.datamodel import BlackboardAttribute +from org.sleuthkit.datamodel import Blackboard from org.sleuthkit.datamodel import TskData from org.sleuthkit.autopsy.ingest import IngestModule from org.sleuthkit.autopsy.ingest.IngestModule import IngestModuleException @@ -130,12 +131,13 @@ class RegistryExampleIngestModule(DataSourceIngestModule): tempDir = os.path.join(Case.getCurrentCase().getTempDirectory(), "RegistryExample") self.log(Level.INFO, "create Directory " + tempDir) try: - os.mkdir(tempDir) + os.mkdir(tempDir) except: - self.log(Level.INFO, "ExampleRegistry Directory already exists " + tempDir) + self.log(Level.INFO, "ExampleRegistry Directory already exists " + tempDir) # Set the database to be read to the once created by the prefetch parser program - skCase = Case.getCurrentCase().getSleuthkitCase(); + skCase = Case.getCurrentCase().getSleuthkitCase() + blackboard = Case.getCurrentCase().getSleuthkitCase().getBlackboard() fileManager = Case.getCurrentCase().getServices().getFileManager() # Look for files to process @@ -170,13 +172,13 @@ class RegistryExampleIngestModule(DataSourceIngestModule): # Setup Artifact and Attributes - try: - artID = skCase.addArtifactType( "TSK_REGISTRY_RUN_KEYS", "Registry Run Keys") - except: - self.log(Level.INFO, "Artifacts Creation Error, some artifacts may not exist now. ==> ") - - artId = skCase.getArtifactTypeID("TSK_REGISTRY_RUN_KEYS") - + artType = skCase.getArtifactType("TSK_REGISTRY_RUN_KEYS") + if not artType: + try: + artType = skCase.addBlackboardArtifactType( "TSK_REGISTRY_RUN_KEYS", "Registry Run Keys") + except: + self.log(Level.WARNING, "Artifacts Creation Error, some artifacts may not exist now. ==> ") + try: attributeIdRunKeyName = skCase.addArtifactAttributeType("TSK_REG_RUN_KEY_NAME", BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, "Run Key Name") except: @@ -198,25 +200,24 @@ class RegistryExampleIngestModule(DataSourceIngestModule): # RefistryKeysFound is a list that contains a list with the following records abstractFile, Registry Key Location, Key Name, Key value for registryKey in self.registryKeysFound: - attributes = ArrayList() - art = registryKey[0].newArtifact(artId) + self.log(Level.INFO, "Creating artifact for registry key with path: " + registryKey[1] + " and key: " + registryKey[2]) + art = registryKey[0].newDataArtifact(artType, Arrays.asList( + BlackboardAttribute(attributeIdRegKeyLoc, moduleName, registryKey[1]), + BlackboardAttribute(attributeIdRunKeyName, moduleName, registryKey[2]), + BlackboardAttribute(attributeIdRunKeyValue, moduleName, registryKey[3]) + )) - attributes.add(BlackboardAttribute(attributeIdRegKeyLoc, moduleName, registryKey[1])) - attributes.add(BlackboardAttribute(attributeIdRunKeyName, moduleName, registryKey[2])) - attributes.add(BlackboardAttribute(attributeIdRunKeyValue, moduleName, registryKey[3])) - art.addAttributes(attributes) - # index the artifact for keyword search try: - blackboard.indexArtifact(art) - except: - self._logger.log(Level.WARNING, "Error indexing artifact " + art.getDisplayName()) + blackboard.postArtifact(art, moduleName) + except Blackboard.BlackboardException as ex: + self.log(Level.SEVERE, "Unable to index blackboard artifact " + str(art.getArtifactTypeName()), ex) #Clean up registryExample directory and files try: - shutil.rmtree(tempDir) + shutil.rmtree(tempDir) except: - self.log(Level.INFO, "removal of directory tree failed " + tempDir) + self.log(Level.INFO, "removal of directory tree failed " + tempDir) # After all databases, post a message to the ingest messages in box. message = IngestMessage.createMessage(IngestMessage.MessageType.DATA, @@ -236,7 +237,7 @@ class RegistryExampleIngestModule(DataSourceIngestModule): softwareRegFile = RegistryHiveFile(File(softwareHive)) for runKey in self.registrySoftwareRunKeys: currentKey = self.findRegistryKey(softwareRegFile, runKey) - if len(currentKey.getValueList()) > 0: + if currentKey and len(currentKey.getValueList()) > 0: skValues = currentKey.getValueList() for skValue in skValues: regKey = [] @@ -255,7 +256,7 @@ class RegistryExampleIngestModule(DataSourceIngestModule): ntuserRegFile = RegistryHiveFile(File(ntuserHive)) for runKey in self.registryNTUserRunKeys: currentKey = self.findRegistryKey(ntuserRegFile, runKey) - if len(currentKey.getValueList()) > 0: + if currentKey and len(currentKey.getValueList()) > 0: skValues = currentKey.getValueList() for skValue in skValues: regKey = [] @@ -276,9 +277,10 @@ class RegistryExampleIngestModule(DataSourceIngestModule): for key in regKeyList: currentKey = currentKey.getSubkey(key) return currentKey - except: - # Key not found - return null + except Exception as ex: + # Key not found + self.log(Level.SEVERE, "registry key parsing issue:", ex) + return None From cc7cbe8a9483a458f7369b98723392dbad7dcb09 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Fri, 23 Jul 2021 10:07:42 -0400 Subject: [PATCH 08/17] Added TagName and TagSet events --- .../sleuthkit/autopsy/casemodule/Case.java | 56 +++++++- .../casemodule/events/TagNamesEvent.java | 126 ++++++++++++++++++ .../casemodule/events/TagSetsEvent.java | 103 ++++++++++++++ .../services/TagNameDefinition.java | 2 +- .../casemodule/services/TagsManager.java | 68 ++++++++-- .../PortableCaseReportModule.java | 2 +- .../imagegallery/ImageGalleryService.java | 2 +- 7 files changed, 343 insertions(+), 16 deletions(-) create mode 100755 Core/src/org/sleuthkit/autopsy/casemodule/events/TagNamesEvent.java create mode 100755 Core/src/org/sleuthkit/autopsy/casemodule/events/TagSetsEvent.java diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index 6f2e6f0816..417239c99d 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -98,6 +98,11 @@ import org.sleuthkit.autopsy.casemodule.events.PersonsAddedEvent; 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.events.TagNamesEvent.TagNamesAddedEvent; +import org.sleuthkit.autopsy.casemodule.events.TagNamesEvent.TagNamesDeletedEvent; +import org.sleuthkit.autopsy.casemodule.events.TagNamesEvent.TagNamesUpdatedEvent; +import org.sleuthkit.autopsy.casemodule.events.TagSetsEvent.TagSetsAddedEvent; +import org.sleuthkit.autopsy.casemodule.events.TagSetsEvent.TagSetsDeletedEvent; import org.sleuthkit.autopsy.casemodule.multiusercases.CaseNodeData.CaseNodeDataException; import org.sleuthkit.autopsy.casemodule.multiusercases.CoordinationServiceUtils; import org.sleuthkit.autopsy.casemodule.services.Services; @@ -484,7 +489,32 @@ public class Case { /** * One or more hosts have been removed from a person. */ - HOSTS_REMOVED_FROM_PERSON; + HOSTS_REMOVED_FROM_PERSON, + + /** + * One or more TagNames have been added. + */ + TAG_NAMES_ADDED, + + /** + * One or more TagNames have been updated. + */ + TAG_NAMES_UPDATED, + + /** + * One or more TagNames have been deleted. + */ + TAG_NAMES_DELETED, + + /** + * One or more TagSets have been added. + */ + TAG_SETS_ADDED, + + /** + * One or more TagSets have been removed. + */ + TAG_SETS_DELETED; }; @@ -627,7 +657,31 @@ public class Case { public void publisHostsRemovedFromPersonEvent(TskEvent.HostsRemovedFromPersonTskEvent event) { eventPublisher.publish(new HostsRemovedFromPersonEvent(event.getPerson(), event.getHostIds())); } + + @Subscribe + public void publicTagNamesAdded(TskEvent.TagNamesAddedTskEvent event) { + eventPublisher.publish(new TagNamesAddedEvent(event.getTagNames())); + } + @Subscribe + public void publicTagNamesUpdated(TskEvent.TagNamesUpdatedTskEvent event) { + eventPublisher.publish(new TagNamesUpdatedEvent(event.getTagNames())); + } + + @Subscribe + public void publicTagNamesDeleted(TskEvent.TagNamesDeletedTskEvent event) { + eventPublisher.publish(new TagNamesDeletedEvent(event.getTagNameIds())); + } + + @Subscribe + public void publicTagSetsAdded(TskEvent.TagSetsAddedTskEvent event) { + eventPublisher.publish(new TagSetsAddedEvent(event.getTagSets())); + } + + @Subscribe + public void publicTagSetsDeleted(TskEvent.TagSetsDeletedTskEvent event) { + eventPublisher.publish(new TagSetsDeletedEvent(event.getTagSetIds())); + } } /** diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/events/TagNamesEvent.java b/Core/src/org/sleuthkit/autopsy/casemodule/events/TagNamesEvent.java new file mode 100755 index 0000000000..60ac94ff23 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/events/TagNamesEvent.java @@ -0,0 +1,126 @@ +/* + * 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.autopsy.casemodule.Case; +import org.sleuthkit.datamodel.SleuthkitCase; +import org.sleuthkit.datamodel.TagName; +import org.sleuthkit.datamodel.TaggingManager; +import org.sleuthkit.datamodel.TskCoreException; + +/** + * A base class for TagName added and update events. + */ +public class TagNamesEvent extends TskDataModelChangedEvent { + + private static final long serialVersionUID = 1L; + + /** + * Construct the base event for TagNames that have been added or updated. + * + * @param eventName The name of the event. + * @param tagNames The TagNames that have been modified. + */ + private TagNamesEvent(String eventName, List tagNames) { + super(eventName, null, null, tagNames, TagName::getId); + } + + /** + * Returns a list of the added or modified TagNames. + * + * @return The event list of TagNames. + */ + public List getTagNames() { + return getNewValue(); + } + + @Override + protected List getNewValueObjects(SleuthkitCase caseDb, List ids) throws TskCoreException { + List tagNames = new ArrayList<>(); + TaggingManager taggingMrg = caseDb.getTaggingManager(); + for (Long id : ids) { + tagNames.add(taggingMrg.getTagName(id)); + } + + return tagNames; + } + + /** + * Application events published when TagNames have been Added from the + * Sleuth Kit data model for a case. + */ + public static class TagNamesAddedEvent extends TagNamesEvent { + + private static final long serialVersionUID = 1L; + + /** + * Construct an application event published when TagNames have been + * added to the Sleuth Kit data model. + * + * @param tagNames The TagNames that have been added. + */ + public TagNamesAddedEvent(List tagNames) { + super(Case.Events.TAG_NAMES_ADDED.name(), tagNames); + } + } + + /** + * Application events published when TagNames have been updated from the + * Sleuth Kit data model for a case. + */ + public static class TagNamesUpdatedEvent extends TagNamesEvent { + + private static final long serialVersionUID = 1L; + + /** + * Construct an application event published when TagNames have been + * updated in the Sleuth Kit data model. + * + * @param tagNames The TagNames that have been updated. + */ + public TagNamesUpdatedEvent(List tagNames) { + super(Case.Events.TAG_NAMES_UPDATED.name(), tagNames); + } + } + + /** + * Application events published when TagNames have been deleted from the + * Sleuth Kit data model for a case. + */ + public static class TagNamesDeletedEvent extends TskDataModelObjectsDeletedEvent { + + private static final long serialVersionUID = 1L; + + /** + * Constructs an application event published when the TagNames have been + * deleted from the Sleuth Kit data model for a case. + * + * @param tagNameIds The IDs of the TagNames that have been deleted. + */ + public TagNamesDeletedEvent(List tagNameIds) { + super(Case.Events.TAG_NAMES_DELETED.name(), tagNameIds); + } + + public List getTagNameIds() { + return getOldValue(); + } + } +} diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/events/TagSetsEvent.java b/Core/src/org/sleuthkit/autopsy/casemodule/events/TagSetsEvent.java new file mode 100755 index 0000000000..0896241e7d --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/events/TagSetsEvent.java @@ -0,0 +1,103 @@ +/* + * 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.autopsy.casemodule.Case; +import org.sleuthkit.datamodel.SleuthkitCase; +import org.sleuthkit.datamodel.TagSet; +import org.sleuthkit.datamodel.TaggingManager; +import org.sleuthkit.datamodel.TskCoreException; + +/** + * A base class for TagSet added and update events. + */ +public class TagSetsEvent extends TskDataModelChangedEvent { + + private static final long serialVersionUID = 1L; + + /** + * Construct a new TagSetEvent. + * + * @param eventName + * @param tagSets + */ + private TagSetsEvent(String eventName, List tagSets) { + super(eventName, null, null, tagSets, TagSet::getId); + } + + /** + * Returns a list of the TagSet objects that were added or modified for this + * event. + * + * @return A list of TagSet objects. + */ + public List getTagSets() { + return this.getNewValue(); + } + + @Override + protected List getNewValueObjects(SleuthkitCase caseDb, List ids) throws TskCoreException { + List tagSets = new ArrayList<>(); + TaggingManager taggingMrg = caseDb.getTaggingManager(); + for (Long id : ids) { + tagSets.add(taggingMrg.getTagSet(id)); + } + return tagSets; + } + + /** + * Application events published when TagSets have been Added from the Sleuth + * Kit data model for a case. + */ + public static class TagSetsAddedEvent extends TagSetsEvent { + + private static final long serialVersionUID = 1L; + + /** + * Construct an application event published when TagSetss have been + * added to the Sleuth Kit data model. + * + * @param tagSets The TagSets that have been added. + */ + public TagSetsAddedEvent(List tagSets) { + super(Case.Events.TAG_SETS_ADDED.name(), tagSets); + } + } + + /** + * Application events published when TagSets have been deleted from the + * Sleuth Kit data model for a case. + */ + public static class TagSetsDeletedEvent extends TskDataModelObjectsDeletedEvent { + + private static final long serialVersionUID = 1L; + + /** + * Constructs an application event published when the TagSets have been + * deleted from the Sleuth Kit data model for a case. + * + * @param tagNameIds The IDs of the TagNames that have been deleted. + */ + public TagSetsDeletedEvent(List tagNameIds) { + super(Case.Events.TAG_SETS_DELETED.name(), tagNameIds); + } + } +} diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java index ff07662e64..f3645fd7c6 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java @@ -236,7 +236,7 @@ final public class TagNameDefinition implements Comparable { TagName saveToCase(SleuthkitCase caseDb) { TagName tagName = null; try { - tagName = caseDb.addOrUpdateTagName(displayName, description, color, knownStatus); + tagName = caseDb.getTaggingManager().addOrUpdateTagName(displayName, description, color, knownStatus); } catch (TskCoreException ex) { LOGGER.log(Level.SEVERE, "Error saving tag name definition", ex); } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java index 4bb813a779..a4bd51bcce 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java @@ -18,9 +18,12 @@ */ package org.sleuthkit.autopsy.casemodule.services; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import java.io.Closeable; import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; @@ -29,8 +32,11 @@ import java.util.Map; import java.util.Set; import java.util.logging.Level; import org.openide.util.NbBundle; +import org.openide.util.WeakListeners; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; +import org.sleuthkit.autopsy.casemodule.events.TagNamesEvent; +import org.sleuthkit.autopsy.casemodule.events.TagNamesEvent.TagNamesDeletedEvent; import org.sleuthkit.autopsy.casemodule.services.contentviewertags.ContentViewerTagManager; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.BlackboardArtifact; @@ -60,6 +66,37 @@ public class TagsManager implements Closeable { private static String PROJECT_VIC_TAG_SET_NAME = "Project VIC"; private static final Object lock = new Object(); + + private final Map allTagNameMap = Collections.synchronizedMap(new HashMap<>()); + + private final PropertyChangeListener listener = new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (evt.getPropertyName().equals(Case.Events.TAG_NAMES_ADDED.name()) + || evt.getPropertyName().equals(Case.Events.TAG_NAMES_UPDATED.name())) { + TagNamesEvent tagEvent = (TagNamesEvent) evt; + List addTagNames = tagEvent.getTagNames(); + for (TagName tag : addTagNames) { + allTagNameMap.put(tag.getDisplayName(), tag); + } + } else if (evt.getPropertyName().equals(Case.Events.TAG_NAMES_DELETED.name())) { + TagNamesDeletedEvent tagEvent = (TagNamesDeletedEvent) evt; + List deletedIds = tagEvent.getTagNameIds(); + List keysToRemove = new ArrayList<>(); + for (TagName tagName : getAllTagNames()) { + if (deletedIds.contains(tagName.getId())) { + keysToRemove.add(tagName.getDisplayName()); + } + } + + for (String key : keysToRemove) { + allTagNameMap.remove(key); + } + } + } + }; + + private final PropertyChangeListener weakListener = WeakListeners.propertyChange(listener, null); static { @@ -177,8 +214,6 @@ public class TagsManager implements Closeable { /* * No current case, nothing more to add to the set. */ - } catch (TskCoreException ex) { - LOGGER.log(Level.SEVERE, "Failed to get list of TagNames from TagsManager.", ex); } return tagDisplayNames; } @@ -268,21 +303,26 @@ public class TagsManager implements Closeable { // add the standard tag names for (TagNameDefinition def : TagNameDefinition.getStandardTagNameDefinitions()) { - caseDb.addOrUpdateTagName(def.getDisplayName(), def.getDescription(), def.getColor(), def.getKnownStatus()); + taggingMgr.addOrUpdateTagName(def.getDisplayName(), def.getDescription(), def.getColor(), def.getKnownStatus()); } //Assume new case and add all tag sets for (TagSetDefinition setDef : TagSetDefinition.readTagSetDefinitions()) { List tagNamesInSet = new ArrayList<>(); for (TagNameDefinition tagNameDef : setDef.getTagNameDefinitions()) { - tagNamesInSet.add(caseDb.addOrUpdateTagName(tagNameDef.getDisplayName(), tagNameDef.getDescription(), tagNameDef.getColor(), tagNameDef.getKnownStatus())); + tagNamesInSet.add(taggingMgr.addOrUpdateTagName(tagNameDef.getDisplayName(), tagNameDef.getDescription(), tagNameDef.getColor(), tagNameDef.getKnownStatus())); } if (!tagNamesInSet.isEmpty()) { taggingMgr.addTagSet(setDef.getName(), tagNamesInSet); } } + } + + for(TagName tagName: caseDb.getAllTagNames()) { + allTagNameMap.put(tagName.getDisplayName(), tagName); } + } catch (TskCoreException ex) { LOGGER.log(Level.SEVERE, "Error updating standard tag name and tag set definitions", ex); } catch (IOException ex) { @@ -292,6 +332,10 @@ public class TagsManager implements Closeable { for (TagNameDefinition tagName : TagNameDefinition.getTagNameDefinitions()) { tagName.saveToCase(caseDb); } + + Case.addEventTypeSubscriber(Collections.singleton(Case.Events.TAG_NAMES_UPDATED), weakListener); + Case.addEventTypeSubscriber(Collections.singleton(Case.Events.TAG_NAMES_ADDED), weakListener); + Case.addEventTypeSubscriber(Collections.singleton(Case.Events.TAG_NAMES_DELETED), weakListener); } /** @@ -337,11 +381,12 @@ public class TagsManager implements Closeable { * Gets a list of all tag names currently in the case database. * * @return A list, possibly empty, of TagName objects. - * - * @throws TskCoreException If there is an error querying the case database. */ - public List getAllTagNames() throws TskCoreException { - return caseDb.getAllTagNames(); + public synchronized List getAllTagNames() { + + List tagNames = new ArrayList<>(); + tagNames.addAll(allTagNameMap.values()); + return tagNames; } /** @@ -439,7 +484,7 @@ public class TagsManager implements Closeable { */ public Map getDisplayNamesToTagNamesMap() throws TskCoreException { Map tagNames = new HashMap<>(); - for (TagName tagName : caseDb.getAllTagNames()) { + for (TagName tagName : getAllTagNames()) { tagNames.put(tagName.getDisplayName(), tagName); } return tagNames; @@ -521,13 +566,13 @@ public class TagsManager implements Closeable { public TagName addTagName(String displayName, String description, TagName.HTML_COLOR color, TskData.FileKnown knownStatus) throws TagNameAlreadyExistsException, TskCoreException { synchronized (lock) { try { - TagName tagName = caseDb.addOrUpdateTagName(displayName, description, color, knownStatus); + TagName tagName = caseDb.getTaggingManager().addOrUpdateTagName(displayName, description, color, knownStatus); Set customTypes = TagNameDefinition.getTagNameDefinitions(); customTypes.add(new TagNameDefinition(displayName, description, color, knownStatus)); TagNameDefinition.setTagNameDefinitions(customTypes); return tagName; } catch (TskCoreException ex) { - List existingTagNames = caseDb.getAllTagNames(); + List existingTagNames = getAllTagNames(); for (TagName tagName : existingTagNames) { if (tagName.getDisplayName().equals(displayName)) { throw new TagNameAlreadyExistsException(); @@ -1039,5 +1084,4 @@ public class TagsManager implements Closeable { @Override public void close() throws IOException { } - } 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 3efcd51250..f18f05f61f 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/portablecase/PortableCaseReportModule.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/portablecase/PortableCaseReportModule.java @@ -340,7 +340,7 @@ public class PortableCaseReportModule implements ReportModule { progressPanel.updateStatusLabel(Bundle.PortableCaseReportModule_generateReport_copyingTags()); try { for (TagName tagName : tagNames) { - TagName newTagName = portableSkCase.addOrUpdateTagName(tagName.getDisplayName(), tagName.getDescription(), tagName.getColor(), tagName.getKnownStatus()); + TagName newTagName = portableSkCase.getTaggingManager().addOrUpdateTagName(tagName.getDisplayName(), tagName.getDescription(), tagName.getColor(), tagName.getKnownStatus()); oldTagNameToNewTagName.put(tagName, newTagName); } } catch (TskCoreException ex) { diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryService.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryService.java index 4a8664eb6f..897b50ae2b 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryService.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryService.java @@ -149,7 +149,7 @@ public class ImageGalleryService implements AutopsyService { private void addProjetVicTagSet(Case currentCase) throws TskCoreException { List tagNames = new ArrayList<>(); for (TagNameDefinition def : PROJECT_VIC_US_CATEGORIES) { - tagNames.add(currentCase.getSleuthkitCase().addOrUpdateTagName(def.getDisplayName(), def.getDescription(), def.getColor(), def.getKnownStatus())); + tagNames.add(currentCase.getSleuthkitCase().getTaggingManager().addOrUpdateTagName(def.getDisplayName(), def.getDescription(), def.getColor(), def.getKnownStatus())); } currentCase.getServices().getTagsManager().addTagSet(PROJECT_VIC_TAG_SET_NAME, tagNames); } From 0e33cd3ace666919beb497d69b2c0397536bae99 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Mon, 26 Jul 2021 14:14:50 -0400 Subject: [PATCH 09/17] Added a content reference to the waypoint objects --- .../sleuthkit/autopsy/geolocation/MapWaypoint.java | 2 +- .../autopsy/geolocation/datamodel/Waypoint.java | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/MapWaypoint.java b/Core/src/org/sleuthkit/autopsy/geolocation/MapWaypoint.java index 6fba326497..662cf7a067 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/MapWaypoint.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/MapWaypoint.java @@ -219,7 +219,7 @@ public final class MapWaypoint extends KdTree.XYZPoint implements org.jxmapviewe JMenuItem[] getMenuItems() throws TskCoreException { List menuItems = new ArrayList<>(); BlackboardArtifact artifact = dataModelWaypoint.getArtifact(); - Content content = artifact.getSleuthkitCase().getContentById(artifact.getObjectID()); + Content content = dataModelWaypoint.getContent(); menuItems.addAll(getTimelineMenuItems(dataModelWaypoint.getArtifact())); menuItems.addAll(getDataModelActionFactoryMenuItems(artifact, content)); diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Waypoint.java b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Waypoint.java index 223b1e9cb3..13fda6f7e1 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Waypoint.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Waypoint.java @@ -28,6 +28,7 @@ import java.util.Set; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; +import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.TskCoreException; /** @@ -44,6 +45,7 @@ public class Waypoint { final private AbstractFile image; final private BlackboardArtifact artifact; final private GeoPath parentGeoPath; + final private Content content; final private List propertiesList; @@ -93,6 +95,11 @@ public class Waypoint { this.parentGeoPath = parentGeoPath; propertiesList = createGeolocationProperties(attributeMap); + try { + content = artifact.getSleuthkitCase().getContentById(artifact.getObjectID()); + } catch (TskCoreException ex) { + throw new GeoLocationDataException(String.format("Failed to get contend for artifact id (%d)", artifact.getId()), ex); + } } /** @@ -248,6 +255,10 @@ public class Waypoint { } return list; } + + public Content getContent() { + return content; + } /** * Simple property class for waypoint properties that a purely From e4185a85c644aee5648db7f925b114e8918d75e6 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Mon, 26 Jul 2021 16:05:38 -0400 Subject: [PATCH 10/17] 7802 initial move of file search by attrs off EDT --- .../autopsy/filesearch/FileSearchPanel.java | 156 +++++++++++------- 1 file changed, 92 insertions(+), 64 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchPanel.java b/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchPanel.java index 4801227416..fb13a317fa 100644 --- a/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchPanel.java +++ b/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchPanel.java @@ -1,15 +1,15 @@ /* * Autopsy Forensic Browser - * + * * Copyright 2011-2019 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. @@ -29,15 +29,19 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; 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.JPanel; +import javax.swing.SwingWorker; import javax.swing.border.EmptyBorder; import org.openide.DialogDisplayer; import org.openide.NotifyDescriptor; import org.openide.nodes.Node; import org.openide.util.NbBundle; import org.openide.windows.TopComponent; +import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent; @@ -56,9 +60,12 @@ import org.sleuthkit.datamodel.TskCoreException; @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives class FileSearchPanel extends javax.swing.JPanel { + private static final Logger logger = Logger.getLogger(FileSearchPanel.class.getName()); + private static final long serialVersionUID = 1L; private final List filters = new ArrayList<>(); private static int resultWindowCount = 0; //keep track of result windows so they get unique names private static final String EMPTY_WHERE_CLAUSE = NbBundle.getMessage(DateSearchFilter.class, "FileSearchPanel.emptyWhereClause.text"); + private static SwingWorker searchWorker = null; enum EVENT { CHECKED @@ -77,39 +84,39 @@ class FileSearchPanel extends javax.swing.JPanel { * This method is called from within the constructor to initialize the form. */ private void customizeComponents() { - + JLabel label = new JLabel(NbBundle.getMessage(this.getClass(), "FileSearchPanel.custComp.label.text")); label.setAlignmentX(Component.LEFT_ALIGNMENT); label.setBorder(new EmptyBorder(0, 0, 10, 0)); - + JPanel panel1 = new JPanel(); - panel1.setLayout(new GridLayout(1,2)); + panel1.setLayout(new GridLayout(1, 2)); panel1.add(new JLabel("")); JPanel panel2 = new JPanel(); - panel2.setLayout(new GridLayout(1,2, 20, 0)); + panel2.setLayout(new GridLayout(1, 2, 20, 0)); JPanel panel3 = new JPanel(); - panel3.setLayout(new GridLayout(1,2, 20, 0)); + panel3.setLayout(new GridLayout(1, 2, 20, 0)); JPanel panel4 = new JPanel(); - panel4.setLayout(new GridLayout(1,2, 20, 0)); + panel4.setLayout(new GridLayout(1, 2, 20, 0)); JPanel panel5 = new JPanel(); - panel5.setLayout(new GridLayout(1,2, 20, 0)); + panel5.setLayout(new GridLayout(1, 2, 20, 0)); // Create and add filter areas - NameSearchFilter nameFilter = new NameSearchFilter(); + NameSearchFilter nameFilter = new NameSearchFilter(); SizeSearchFilter sizeFilter = new SizeSearchFilter(); DateSearchFilter dateFilter = new DateSearchFilter(); KnownStatusSearchFilter knowStatusFilter = new KnownStatusSearchFilter(); HashSearchFilter hashFilter = new HashSearchFilter(); MimeTypeFilter mimeTypeFilter = new MimeTypeFilter(); DataSourceFilter dataSourceFilter = new DataSourceFilter(); - - panel2.add(new FilterArea(NbBundle.getMessage(this.getClass(), "FileSearchPanel.filterTitle.name"),nameFilter)); - - panel3.add(new FilterArea(NbBundle.getMessage(this.getClass(), "FileSearchPanel.filterTitle.metadata"),sizeFilter)); - - panel2.add(new FilterArea(NbBundle.getMessage(this.getClass(), "FileSearchPanel.filterTitle.metadata"), dateFilter)); + + panel2.add(new FilterArea(NbBundle.getMessage(this.getClass(), "FileSearchPanel.filterTitle.name"), nameFilter)); + + panel3.add(new FilterArea(NbBundle.getMessage(this.getClass(), "FileSearchPanel.filterTitle.metadata"), sizeFilter)); + + panel2.add(new FilterArea(NbBundle.getMessage(this.getClass(), "FileSearchPanel.filterTitle.metadata"), dateFilter)); panel3.add(new FilterArea(NbBundle.getMessage(this.getClass(), "FileSearchPanel.filterTitle.knownStatus"), knowStatusFilter)); - + panel5.add(new FilterArea(NbBundle.getMessage(this.getClass(), "HashSearchPanel.md5CheckBox.text"), hashFilter)); panel5.add(new JLabel("")); panel4.add(new FilterArea(NbBundle.getMessage(this.getClass(), "FileSearchPanel.filterTitle.metadata"), mimeTypeFilter)); @@ -119,7 +126,7 @@ class FileSearchPanel extends javax.swing.JPanel { filterPanel.add(panel3); filterPanel.add(panel4); filterPanel.add(panel5); - + filters.add(nameFilter); filters.add(sizeFilter); filters.add(dateFilter); @@ -127,7 +134,7 @@ class FileSearchPanel extends javax.swing.JPanel { filters.add(hashFilter); filters.add(mimeTypeFilter); filters.add(dataSourceFilter); - + for (FileSearchFilter filter : this.getFilters()) { filter.addPropertyChangeListener(new PropertyChangeListener() { @Override @@ -141,7 +148,7 @@ class FileSearchPanel extends javax.swing.JPanel { public void actionPerformed(ActionEvent e) { search(); } - }); + }); searchButton.setEnabled(isValidSearch()); } @@ -170,54 +177,77 @@ class FileSearchPanel extends javax.swing.JPanel { */ @NbBundle.Messages("FileSearchPanel.emptyNode.display.text=No results found.") private void search() { - // change the cursor to "waiting cursor" for this operation - this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + if (searchWorker != null && searchWorker.isDone()) { + searchWorker.cancel(true); + } try { if (this.isValidSearch()) { - String title = NbBundle.getMessage(this.getClass(), "FileSearchPanel.search.results.title", ++resultWindowCount); - String pathText = NbBundle.getMessage(this.getClass(), "FileSearchPanel.search.results.pathText"); - + // change the cursor to "waiting cursor" for this operation + WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); // try to get the number of matches first Case currentCase = Case.getCurrentCaseThrows(); // get the most updated case - long totalMatches = 0; - List contentList = null; - try { - SleuthkitCase tskDb = currentCase.getSleuthkitCase(); - contentList = tskDb.findAllFilesWhere(this.getQuery()); + searchWorker = new SwingWorker() { + List contentList = null; + TableFilterNode tableFilterNode = null; - } catch (TskCoreException ex) { - Logger logger = Logger.getLogger(this.getClass().getName()); - logger.log(Level.WARNING, "Error while trying to get the number of matches.", ex); //NON-NLS - } + @Override + protected Void doInBackground() throws Exception { + try { + SleuthkitCase tskDb = currentCase.getSleuthkitCase(); + contentList = tskDb.findAllFilesWhere(getQuery()); - if (contentList == null) { - contentList = Collections.emptyList(); - } + } catch (TskCoreException ex) { + Logger logger = Logger.getLogger(this.getClass().getName()); + logger.log(Level.WARNING, "Error while trying to get the number of matches.", ex); //NON-NLS + } + if (contentList == null) { + contentList = Collections.emptyList(); + } + SearchNode sn = new SearchNode(contentList); + tableFilterNode = new TableFilterNode(sn, true, sn.getName()); + return null; + } - SearchNode sn = new SearchNode(contentList); - TableFilterNode tableFilterNode = new TableFilterNode(sn, true, sn.getName()); - final TopComponent searchResultWin; - if (contentList.isEmpty()) { - Node emptyNode = new TableFilterNode(new EmptyNode(Bundle.FileSearchPanel_emptyNode_display_text()), true); - searchResultWin = DataResultTopComponent.createInstance(title, pathText, - emptyNode, 0); - } else { - searchResultWin = DataResultTopComponent.createInstance(title, pathText, - tableFilterNode, contentList.size()); - } - searchResultWin.requestActive(); // make it the active top component + @Override + protected void done() { - /** - * If total matches more than 1000, pop up a dialog box that say - * the performance maybe be slow and to increase the - * performance, tell the users to refine their search. - */ - if (totalMatches > 10000) { - // show info - String msg = NbBundle.getMessage(this.getClass(), "FileSearchPanel.search.results.msg", totalMatches); - String details = NbBundle.getMessage(this.getClass(), "FileSearchPanel.search.results.details"); - MessageNotifyUtil.Notify.info(msg, details); - } + try { + get(); + String title = NbBundle.getMessage(this.getClass(), "FileSearchPanel.search.results.title", ++resultWindowCount); + String pathText = NbBundle.getMessage(this.getClass(), "FileSearchPanel.search.results.pathText"); + final TopComponent searchResultWin; + if (contentList.isEmpty() || tableFilterNode == null) { + Node emptyNode = new TableFilterNode(new EmptyNode(Bundle.FileSearchPanel_emptyNode_display_text()), true); + searchResultWin = DataResultTopComponent.createInstance(title, pathText, + emptyNode, 0); + } else { + searchResultWin = DataResultTopComponent.createInstance(title, pathText, + tableFilterNode, contentList.size()); + } + searchResultWin.requestActive(); // make it the active top component + + /** + * If total matches more than 1000, pop up a dialog + * box that say the performance maybe be slow and to + * increase the performance, tell the users to + * refine their search. + */ + if (contentList.size() > 10000) { + // show info + String msg = NbBundle.getMessage(this.getClass(), "FileSearchPanel.search.results.msg", contentList.size()); + String details = NbBundle.getMessage(this.getClass(), "FileSearchPanel.search.results.details"); + MessageNotifyUtil.Notify.info(msg, details); + } + } catch (InterruptedException | ExecutionException ex) { + logger.log(Level.SEVERE, "Error while performing file search by attributes", ex); + } catch (CancellationException ex) { + logger.log(Level.INFO, "File search by attributes was cancelled", ex); + } finally { + WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } + } + }; + searchWorker.execute(); } else { throw new FilterValidationException( NbBundle.getMessage(this.getClass(), "FileSearchPanel.search.exception.noFilterSelected.msg")); @@ -226,8 +256,6 @@ class FileSearchPanel extends javax.swing.JPanel { NotifyDescriptor d = new NotifyDescriptor.Message( NbBundle.getMessage(this.getClass(), "FileSearchPanel.search.validationErr.msg", ex.getMessage())); DialogDisplayer.getDefault().notify(d); - } finally { - this.setCursor(null); } } From 0e5598f4614ca75c45aa239365b0a63daaf4cdcc Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 30 Jul 2021 16:36:09 -0400 Subject: [PATCH 11/17] 7802 improve search in progress indicator and cancellation support --- .../filesearch/Bundle.properties-MERGED | 3 + .../autopsy/filesearch/FileSearchPanel.java | 60 ++++++++++++------- 2 files changed, 41 insertions(+), 22 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/filesearch/Bundle.properties-MERGED index 3f2af1ea8a..075a0e7afb 100755 --- a/Core/src/org/sleuthkit/autopsy/filesearch/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/filesearch/Bundle.properties-MERGED @@ -1,7 +1,10 @@ DataSourceFilter.errorMessage.emptyDataSource=At least one data source must be selected. DateSearchFilter.errorMessage.endDateBeforeStartDate=The end date should be after the start date. DateSearchFilter.errorMessage.noCheckboxSelected=At least one date type checkbox must be selected. +FileSearchPanel.cancelledSearch.text=Search Was Cancelled FileSearchPanel.emptyNode.display.text=No results found. +FileSearchPanel.searchingNode.display.text=Performing file search by attributes. Please wait. +FileSearchPanel.searchingPath.text=File Search In Progress HashSearchFilter.errorMessage.emptyHash=Hash data is empty. HashSearchFilter.errorMessage.wrongCharacter=MD5 contains invalid hex characters. # {0} - hash data length diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchPanel.java b/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchPanel.java index fb13a317fa..c76892a192 100644 --- a/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchPanel.java +++ b/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchPanel.java @@ -65,7 +65,7 @@ class FileSearchPanel extends javax.swing.JPanel { private final List filters = new ArrayList<>(); private static int resultWindowCount = 0; //keep track of result windows so they get unique names private static final String EMPTY_WHERE_CLAUSE = NbBundle.getMessage(DateSearchFilter.class, "FileSearchPanel.emptyWhereClause.text"); - private static SwingWorker searchWorker = null; + private static SwingWorker searchWorker = null; enum EVENT { CHECKED @@ -175,23 +175,30 @@ class FileSearchPanel extends javax.swing.JPanel { * Action when the "Search" button is pressed. * */ - @NbBundle.Messages("FileSearchPanel.emptyNode.display.text=No results found.") + @NbBundle.Messages({"FileSearchPanel.emptyNode.display.text=No results found.", + "FileSearchPanel.searchingNode.display.text=Performing file search by attributes. Please wait.", + "FileSearchPanel.searchingPath.text=File Search In Progress", + "FileSearchPanel.cancelledSearch.text=Search Was Cancelled"}) private void search() { if (searchWorker != null && searchWorker.isDone()) { searchWorker.cancel(true); } try { if (this.isValidSearch()) { - // change the cursor to "waiting cursor" for this operation - WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); // try to get the number of matches first Case currentCase = Case.getCurrentCaseThrows(); // get the most updated case - searchWorker = new SwingWorker() { + Node emptyNode = new TableFilterNode(new EmptyNode(Bundle.FileSearchPanel_emptyNode_display_text()), true); + String title = NbBundle.getMessage(this.getClass(), "FileSearchPanel.search.results.title", ++resultWindowCount); + String pathText = Bundle.FileSearchPanel_searchingPath_text(); + final DataResultTopComponent searchResultWin = DataResultTopComponent.createInstance(title, pathText, + emptyNode, 0); + searchResultWin.requestActive(); // make it the active top component + searchResultWin.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + searchWorker = new SwingWorker() { List contentList = null; - TableFilterNode tableFilterNode = null; @Override - protected Void doInBackground() throws Exception { + protected TableFilterNode doInBackground() throws Exception { try { SleuthkitCase tskDb = currentCase.getSleuthkitCase(); contentList = tskDb.findAllFilesWhere(getQuery()); @@ -203,27 +210,23 @@ class FileSearchPanel extends javax.swing.JPanel { if (contentList == null) { contentList = Collections.emptyList(); } + if (contentList.isEmpty()) { + return new TableFilterNode(new EmptyNode(Bundle.FileSearchPanel_emptyNode_display_text()), true); + } SearchNode sn = new SearchNode(contentList); - tableFilterNode = new TableFilterNode(sn, true, sn.getName()); - return null; + return new TableFilterNode(sn, true, sn.getName()); } @Override protected void done() { - + String pathText = NbBundle.getMessage(this.getClass(), "FileSearchPanel.search.results.pathText"); try { - get(); - String title = NbBundle.getMessage(this.getClass(), "FileSearchPanel.search.results.title", ++resultWindowCount); - String pathText = NbBundle.getMessage(this.getClass(), "FileSearchPanel.search.results.pathText"); - final TopComponent searchResultWin; - if (contentList.isEmpty() || tableFilterNode == null) { - Node emptyNode = new TableFilterNode(new EmptyNode(Bundle.FileSearchPanel_emptyNode_display_text()), true); - searchResultWin = DataResultTopComponent.createInstance(title, pathText, - emptyNode, 0); - } else { - searchResultWin = DataResultTopComponent.createInstance(title, pathText, - tableFilterNode, contentList.size()); + TableFilterNode tableFilterNode = get(); + if (tableFilterNode == null) { //just incase this get() gets modified to return null or somehow can return null + tableFilterNode = new TableFilterNode(new EmptyNode(Bundle.FileSearchPanel_emptyNode_display_text()), true); } + + searchResultWin.setNode(tableFilterNode); searchResultWin.requestActive(); // make it the active top component /** @@ -241,12 +244,25 @@ class FileSearchPanel extends javax.swing.JPanel { } catch (InterruptedException | ExecutionException ex) { logger.log(Level.SEVERE, "Error while performing file search by attributes", ex); } catch (CancellationException ex) { + Node emptyNode = new TableFilterNode(new EmptyNode(Bundle.FileSearchPanel_cancelledSearch_text()), true); + searchResultWin.setNode(emptyNode); + pathText = Bundle.FileSearchPanel_cancelledSearch_text(); logger.log(Level.INFO, "File search by attributes was cancelled", ex); } finally { - WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + searchResultWin.setPath(pathText); + searchResultWin.requestActive(); // make it the active top component + searchResultWin.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); } } }; + searchResultWin.addPropertyChangeListener(new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (evt.getPropertyName().equals("tcClosed") && !searchWorker.isDone() && evt.getOldValue() == null) { + searchWorker.cancel(true); + } + } + }); searchWorker.execute(); } else { throw new FilterValidationException( From 802d1235cabe74060db98d83bb160b17fba3177c Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 30 Jul 2021 16:46:12 -0400 Subject: [PATCH 12/17] 7802 fix text for search in progress node --- Core/src/org/sleuthkit/autopsy/filesearch/FileSearchPanel.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchPanel.java b/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchPanel.java index c76892a192..c55ab46d17 100644 --- a/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchPanel.java +++ b/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchPanel.java @@ -187,7 +187,7 @@ class FileSearchPanel extends javax.swing.JPanel { if (this.isValidSearch()) { // try to get the number of matches first Case currentCase = Case.getCurrentCaseThrows(); // get the most updated case - Node emptyNode = new TableFilterNode(new EmptyNode(Bundle.FileSearchPanel_emptyNode_display_text()), true); + Node emptyNode = new TableFilterNode(new EmptyNode(Bundle.FileSearchPanel_searchingNode_display_text()), true); String title = NbBundle.getMessage(this.getClass(), "FileSearchPanel.search.results.title", ++resultWindowCount); String pathText = Bundle.FileSearchPanel_searchingPath_text(); final DataResultTopComponent searchResultWin = DataResultTopComponent.createInstance(title, pathText, @@ -260,6 +260,7 @@ class FileSearchPanel extends javax.swing.JPanel { public void propertyChange(PropertyChangeEvent evt) { if (evt.getPropertyName().equals("tcClosed") && !searchWorker.isDone() && evt.getOldValue() == null) { searchWorker.cancel(true); + logger.log(Level.INFO, "User has closed the results window while search was in progress, search will be cancelled"); } } }); From b37d5fd3516fb4215d0b96f3a2c21ee430875433 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 30 Jul 2021 18:05:28 -0400 Subject: [PATCH 13/17] 7802 protect against NPE when search cancelled --- .../autopsy/filesearch/FileSearchPanel.java | 42 +++++++++++-------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchPanel.java b/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchPanel.java index c55ab46d17..62f6332c83 100644 --- a/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchPanel.java +++ b/Core/src/org/sleuthkit/autopsy/filesearch/FileSearchPanel.java @@ -225,10 +225,10 @@ class FileSearchPanel extends javax.swing.JPanel { if (tableFilterNode == null) { //just incase this get() gets modified to return null or somehow can return null tableFilterNode = new TableFilterNode(new EmptyNode(Bundle.FileSearchPanel_emptyNode_display_text()), true); } - - searchResultWin.setNode(tableFilterNode); - searchResultWin.requestActive(); // make it the active top component - + if (searchResultWin != null && searchResultWin.isOpened()) { + searchResultWin.setNode(tableFilterNode); + searchResultWin.requestActive(); // make it the active top component + } /** * If total matches more than 1000, pop up a dialog * box that say the performance maybe be slow and to @@ -244,26 +244,32 @@ class FileSearchPanel extends javax.swing.JPanel { } catch (InterruptedException | ExecutionException ex) { logger.log(Level.SEVERE, "Error while performing file search by attributes", ex); } catch (CancellationException ex) { - Node emptyNode = new TableFilterNode(new EmptyNode(Bundle.FileSearchPanel_cancelledSearch_text()), true); - searchResultWin.setNode(emptyNode); - pathText = Bundle.FileSearchPanel_cancelledSearch_text(); + if (searchResultWin != null && searchResultWin.isOpened()) { + Node emptyNode = new TableFilterNode(new EmptyNode(Bundle.FileSearchPanel_cancelledSearch_text()), true); + searchResultWin.setNode(emptyNode); + pathText = Bundle.FileSearchPanel_cancelledSearch_text(); + } logger.log(Level.INFO, "File search by attributes was cancelled", ex); } finally { - searchResultWin.setPath(pathText); - searchResultWin.requestActive(); // make it the active top component - searchResultWin.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + if (searchResultWin != null && searchResultWin.isOpened()) { + searchResultWin.setPath(pathText); + searchResultWin.requestActive(); // make it the active top component + searchResultWin.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } } } }; - searchResultWin.addPropertyChangeListener(new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (evt.getPropertyName().equals("tcClosed") && !searchWorker.isDone() && evt.getOldValue() == null) { - searchWorker.cancel(true); - logger.log(Level.INFO, "User has closed the results window while search was in progress, search will be cancelled"); + if (searchResultWin != null && searchResultWin.isOpened()) { + searchResultWin.addPropertyChangeListener(new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (evt.getPropertyName().equals("tcClosed") && !searchWorker.isDone() && evt.getOldValue() == null) { + searchWorker.cancel(true); + logger.log(Level.INFO, "User has closed the results window while search was in progress, search will be cancelled"); + } } - } - }); + }); + } searchWorker.execute(); } else { throw new FilterValidationException( From 5c19ae52959bc3a2d29fadd805dfd95a6ea12bda Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Mon, 2 Aug 2021 16:53:34 -0400 Subject: [PATCH 14/17] 7673 Fix just introduced bug in IngestJobPipeline.hasFileIngestModules() --- .../org/sleuthkit/autopsy/ingest/IngestJobPipeline.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestJobPipeline.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobPipeline.java index 59fa6c4dcc..c68dde5911 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestJobPipeline.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobPipeline.java @@ -538,7 +538,10 @@ final class IngestJobPipeline { * @return True or false. */ boolean hasFileIngestModules() { - return (fileIngestPipelines.isEmpty() == false); + if (!fileIngestPipelines.isEmpty()) { + return !fileIngestPipelines.get(0).isEmpty(); + } + return false; } /** @@ -1438,7 +1441,7 @@ final class IngestJobPipeline { } pausedIngestThreads.clear(); } - + // If a data source had no tasks in progress it may now be complete. checkForStageCompleted(); } From 375bdcdc011bef79d4a178badb964e3b341cf3e6 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Mon, 2 Aug 2021 17:13:55 -0400 Subject: [PATCH 15/17] Support processing of multiple reports --- .../CommandLineIngestSettingsPanel.java | 6 ++- .../CommandLineOptionProcessor.java | 44 ++++++++++++------- 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineIngestSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineIngestSettingsPanel.java index db60e7a0af..bc3c419412 100755 --- a/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineIngestSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineIngestSettingsPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2019-2020 Basis Technology Corp. + * Copyright 2019-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -288,6 +288,10 @@ public class CommandLineIngestSettingsPanel extends javax.swing.JPanel { String reportName = getReportName(); if (reportName.equals(Bundle.CommandListIngestSettingsPanel_Make_Config())) { reportName = JOptionPane.showInputDialog(this, Bundle.CommandListIngestSettingsPanel_Report_Name_Msg()); + + // sanitize report name. Remove all commas because in CommandLineOptionProcessor we use commas + // to separate multiple report names + reportName = reportName.replaceAll(",", ""); // User hit cancel if (reportName == null) { diff --git a/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineOptionProcessor.java b/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineOptionProcessor.java index ad84bdcd0f..2f5644928e 100755 --- a/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineOptionProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineOptionProcessor.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2019-2020 Basis Technology Corp. + * Copyright 2019-2021 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,12 +20,15 @@ package org.sleuthkit.autopsy.commandlineingest; import java.io.File; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.logging.Level; +import java.util.stream.Collectors; +import java.util.stream.Stream; import org.sleuthkit.autopsy.coreutils.Logger; import org.netbeans.api.sendopts.CommandException; import org.netbeans.spi.sendopts.Env; @@ -291,7 +294,6 @@ public class CommandLineOptionProcessor extends OptionProcessor { } // Add "GENERATE_REPORTS" command, if present - String reportProfile = null; if (values.containsKey(generateReportsOption)) { // 'caseDir' must only be specified if the case is not being created during the current run @@ -300,24 +302,34 @@ public class CommandLineOptionProcessor extends OptionProcessor { handleError("'caseDir' argument is empty"); } + List reportProfiles; argDirs = values.get(generateReportsOption); if (argDirs.length > 0) { - reportProfile = argDirs[0]; + // use custom report configuration(s) + reportProfiles = Stream.of(argDirs[0].split(",")) + .map(String::trim) + .collect(Collectors.toList()); + + if (reportProfiles == null || reportProfiles.isEmpty()) { + handleError("'generateReports' argument is empty"); + } + + for (String reportProfile : reportProfiles) { + if (reportProfile.isEmpty()) { + handleError("Empty report profile name"); + } + CommandLineCommand newCommand = new CommandLineCommand(CommandLineCommand.CommandType.GENERATE_REPORTS); + newCommand.addInputValue(CommandLineCommand.InputType.CASE_FOLDER_PATH.name(), caseDir); + newCommand.addInputValue(CommandLineCommand.InputType.REPORT_PROFILE_NAME.name(), reportProfile); + commands.add(newCommand); + } + } else { + // use default report configuration + CommandLineCommand newCommand = new CommandLineCommand(CommandLineCommand.CommandType.GENERATE_REPORTS); + newCommand.addInputValue(CommandLineCommand.InputType.CASE_FOLDER_PATH.name(), caseDir); + commands.add(newCommand); } - // If the user doesn't supply an options for generateReports the - // argsDirs length will be 0, so if reportProfile is empty - // something is not right. - if (reportProfile != null && reportProfile.isEmpty()) { - handleError("'generateReports' argument is empty"); - } - - CommandLineCommand newCommand = new CommandLineCommand(CommandLineCommand.CommandType.GENERATE_REPORTS); - newCommand.addInputValue(CommandLineCommand.InputType.CASE_FOLDER_PATH.name(), caseDir); - if (reportProfile != null) { - newCommand.addInputValue(CommandLineCommand.InputType.REPORT_PROFILE_NAME.name(), reportProfile); - } - commands.add(newCommand); runFromCommandLine = true; } } From 9b9665b2d92dd2b6e16a5fd222241d4f754c554f Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Mon, 2 Aug 2021 17:49:51 -0400 Subject: [PATCH 16/17] Changed dialog text --- .../autopsy/commandlineingest/Bundle.properties-MERGED | 2 +- .../commandlineingest/CommandLineIngestSettingsPanel.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/commandlineingest/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/commandlineingest/Bundle.properties-MERGED index 90e7cc4a11..447b4e3038 100755 --- a/Core/src/org/sleuthkit/autopsy/commandlineingest/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/commandlineingest/Bundle.properties-MERGED @@ -2,7 +2,7 @@ CommandLineIngestSettingPanel_empty_report_name_mgs=Report profile name was empt CommandLineIngestSettingPanel_existing_report_name_mgs=Report profile name was already exists, no profile created. CommandListIngestSettingsPanel_Default_Report_DisplayName=Default CommandListIngestSettingsPanel_Make_Config=Make new profile... -CommandListIngestSettingsPanel_Report_Name_Msg=Please supply a report profile name: +CommandListIngestSettingsPanel_Report_Name_Msg=Please supply a report profile name (commas not allowed): OpenIDE-Module-Name=CommandLineAutopsy OptionsCategory_Keywords_Command_Line_Ingest_Settings=Command Line Ingest Settings OptionsCategory_Keywords_General=Options diff --git a/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineIngestSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineIngestSettingsPanel.java index bc3c419412..ca11d03f13 100755 --- a/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineIngestSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineIngestSettingsPanel.java @@ -280,7 +280,7 @@ public class CommandLineIngestSettingsPanel extends javax.swing.JPanel { add(nodePanel, java.awt.BorderLayout.CENTER); }// //GEN-END:initComponents @Messages({ - "CommandListIngestSettingsPanel_Report_Name_Msg=Please supply a report profile name:", + "CommandListIngestSettingsPanel_Report_Name_Msg=Please supply a report profile name (commas not allowed):", "CommandLineIngestSettingPanel_empty_report_name_mgs=Report profile name was empty, no profile created.", "CommandLineIngestSettingPanel_existing_report_name_mgs=Report profile name was already exists, no profile created." }) From 834984c7829dbd2346a2b486d8e9788f1d67921e Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Tue, 3 Aug 2021 11:23:05 -0400 Subject: [PATCH 17/17] Change OsAccountViewer.isPreferred() ret val to 1 --- .../autopsy/contentviewers/osaccount/OsAccountViewer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountViewer.java index 4b2b4ac972..a45d96046a 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountViewer.java @@ -141,7 +141,7 @@ public class OsAccountViewer extends javax.swing.JPanel implements DataContentVi @Override public int isPreferred(Node node) { - return 5; + return 1; } /**