From 5c1932f1fc70d8acb8fea7a94b47241a1415d82f Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Tue, 18 Oct 2016 17:35:00 -0400 Subject: [PATCH 01/37] Updated docs link and uncommented 4.0-only code --- .../FindContactsDb.py | 24 +++++++-------- .../FindBigRoundFiles.py | 19 +++++------- .../CsvReportModule.py | 4 +-- pythonExamples/dataSourceIngestModule.py | 30 +++++++++---------- pythonExamples/fileIngestModule.py | 21 ++++++------- pythonExamples/fileIngestModuleWithGui.py | 2 +- pythonExamples/reportmodule.py | 4 +-- 7 files changed, 46 insertions(+), 58 deletions(-) diff --git a/pythonExamples/Aug2015DataSourceTutorial/FindContactsDb.py b/pythonExamples/Aug2015DataSourceTutorial/FindContactsDb.py index 6852a3534b..6abdd85b5c 100755 --- a/pythonExamples/Aug2015DataSourceTutorial/FindContactsDb.py +++ b/pythonExamples/Aug2015DataSourceTutorial/FindContactsDb.py @@ -58,8 +58,7 @@ from org.sleuthkit.autopsy.casemodule import Case from org.sleuthkit.autopsy.datamodel import ContentUtils from org.sleuthkit.autopsy.casemodule.services import Services from org.sleuthkit.autopsy.casemodule.services import FileManager -# This will work in 4.0.1 and beyond -# from org.sleuthkit.autopsy.casemodule.services import Blackboard +from org.sleuthkit.autopsy.casemodule.services import Blackboard @@ -98,25 +97,22 @@ class ContactsDbIngestModule(DataSourceIngestModule): # Where any setup and configuration is done # 'context' is an instance of org.sleuthkit.autopsy.ingest.IngestJobContext. - # See: http://sleuthkit.org/autopsy/docs/api-docs/3.1/classorg_1_1sleuthkit_1_1autopsy_1_1ingest_1_1_ingest_job_context.html + # See: http://sleuthkit.org/autopsy/docs/api-docs/4.1/classorg_1_1sleuthkit_1_1autopsy_1_1ingest_1_1_ingest_job_context.html def startUp(self, context): self.context = context - # Throw an IngestModule.IngestModuleException exception if there was a problem setting up - # raise IngestModuleException("Oh No!") # Where the analysis is done. # The 'dataSource' object being passed in is of type org.sleuthkit.datamodel.Content. # See: http://www.sleuthkit.org/sleuthkit/docs/jni-docs/4.3/interfaceorg_1_1sleuthkit_1_1datamodel_1_1_content.html # 'progressBar' is of type org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProgress - # See: http://sleuthkit.org/autopsy/docs/api-docs/3.1/classorg_1_1sleuthkit_1_1autopsy_1_1ingest_1_1_data_source_ingest_module_progress.html + # See: http://sleuthkit.org/autopsy/docs/api-docs/4.1/classorg_1_1sleuthkit_1_1autopsy_1_1ingest_1_1_data_source_ingest_module_progress.html def process(self, dataSource, progressBar): # we don't know how much work there is yet progressBar.switchToIndeterminate() - # This will work in 4.0.1 and beyond # Use blackboard class to index blackboard artifacts for keyword search - # blackboard = Case.getCurrentCase().getServices().getBlackboard() + blackboard = Case.getCurrentCase().getServices().getBlackboard() # Find files named contacts.db, regardless of parent path fileManager = Case.getCurrentCase().getServices().getFileManager() @@ -176,12 +172,12 @@ class ContactsDbIngestModule(DataSourceIngestModule): art.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER.getTypeID(), ContactsDbIngestModuleFactory.moduleName, phone)) - # This will work in 4.0.1 and beyond - #try: - # # index the artifact for keyword search - # blackboard.indexArtifact(art) - #except Blackboard.BlackboardException as e: - # self.log(Level.SEVERE, "Error indexing artifact " + art.getDisplayName()) + + try: + # index the artifact for keyword search + blackboard.indexArtifact(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 are new artifacts IngestServices.getInstance().fireModuleDataEvent( diff --git a/pythonExamples/July2015FileTutorial_BigRound/FindBigRoundFiles.py b/pythonExamples/July2015FileTutorial_BigRound/FindBigRoundFiles.py index 7aea6ffd3c..e7df254dc3 100755 --- a/pythonExamples/July2015FileTutorial_BigRound/FindBigRoundFiles.py +++ b/pythonExamples/July2015FileTutorial_BigRound/FindBigRoundFiles.py @@ -56,8 +56,7 @@ from org.sleuthkit.autopsy.coreutils import Logger from org.sleuthkit.autopsy.casemodule import Case from org.sleuthkit.autopsy.casemodule.services import Services from org.sleuthkit.autopsy.casemodule.services import FileManager -# This will work in 4.0.1 and beyond -# from org.sleuthkit.autopsy.casemodule.services import Blackboard +from org.sleuthkit.autopsy.casemodule.services import Blackboard # Factory that defines the name and details of the module and allows Autopsy # to create instances of the modules that will do the anlaysis. @@ -93,7 +92,7 @@ class FindBigRoundFilesIngestModule(FileIngestModule): # Where any setup and configuration is done # 'context' is an instance of org.sleuthkit.autopsy.ingest.IngestJobContext. - # See: http://sleuthkit.org/autopsy/docs/api-docs/3.1/classorg_1_1sleuthkit_1_1autopsy_1_1ingest_1_1_ingest_job_context.html + # See: http://sleuthkit.org/autopsy/docs/api-docs/4.1/classorg_1_1sleuthkit_1_1autopsy_1_1ingest_1_1_ingest_job_context.html # TODO: Add any setup code that you need here. def startUp(self, context): self.filesFound = 0 @@ -107,9 +106,8 @@ class FindBigRoundFilesIngestModule(FileIngestModule): # See: http://www.sleuthkit.org/sleuthkit/docs/jni-docs/4.3/classorg_1_1sleuthkit_1_1datamodel_1_1_abstract_file.html def process(self, file): - # This will work in 4.0.1 and beyond # Use blackboard class to index blackboard artifacts for keyword search - # blackboard = Case.getCurrentCase().getServices().getBlackboard() + blackboard = Case.getCurrentCase().getServices().getBlackboard() # Skip non-files if ((file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) or @@ -127,12 +125,11 @@ class FindBigRoundFilesIngestModule(FileIngestModule): FindBigRoundFilesIngestModuleFactory.moduleName, "Big and Round Files") art.addAttribute(att) - # This will work in 4.0.1 and beyond - #try: - # # index the artifact for keyword search - # blackboard.indexArtifact(art) - #except Blackboard.BlackboardException as e: - # self.log(Level.SEVERE, "Error indexing artifact " + art.getDisplayName()) + try: + # index the artifact for keyword search + blackboard.indexArtifact(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( diff --git a/pythonExamples/Sept2015ReportTutorial_CSV/CsvReportModule.py b/pythonExamples/Sept2015ReportTutorial_CSV/CsvReportModule.py index 137af15d26..4b5b9df83b 100755 --- a/pythonExamples/Sept2015ReportTutorial_CSV/CsvReportModule.py +++ b/pythonExamples/Sept2015ReportTutorial_CSV/CsvReportModule.py @@ -27,7 +27,7 @@ # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR # OTHER DEALINGS IN THE SOFTWARE. -# See http://sleuthkit.org/autopsy/docs/api-docs/3.1/index.html for documentation +# See http://sleuthkit.org/autopsy/docs/api-docs/4.1/index.html for documentation # Simple report module for Autopsy. # Used as part of Python tutorials from Basis Technology - September 2015 @@ -71,7 +71,7 @@ class CSVReportModule(GeneralReportModuleAdapter): # 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 'progressBar' object is of type ReportProgressPanel. - # See: http://sleuthkit.org/autopsy/docs/api-docs/3.1/classorg_1_1sleuthkit_1_1autopsy_1_1report_1_1_report_progress_panel.html + # See: http://sleuthkit.org/autopsy/docs/api-docs/4.1/classorg_1_1sleuthkit_1_1autopsy_1_1report_1_1_report_progress_panel.html def generateReport(self, baseReportDir, progressBar): # Open the output file. diff --git a/pythonExamples/dataSourceIngestModule.py b/pythonExamples/dataSourceIngestModule.py index 0c1961b60f..41166398bb 100755 --- a/pythonExamples/dataSourceIngestModule.py +++ b/pythonExamples/dataSourceIngestModule.py @@ -29,7 +29,7 @@ # Simple data source-level ingest module for Autopsy. # Search for TODO for the things that you need to change -# See http://sleuthkit.org/autopsy/docs/api-docs/3.1/index.html for documentation +# See http://sleuthkit.org/autopsy/docs/api-docs/4.1/index.html for documentation import jarray import inspect @@ -51,8 +51,7 @@ from org.sleuthkit.autopsy.coreutils import Logger from org.sleuthkit.autopsy.casemodule import Case from org.sleuthkit.autopsy.casemodule.services import Services from org.sleuthkit.autopsy.casemodule.services import FileManager -# This will work in 4.0.1 and beyond -# from org.sleuthkit.autopsy.casemodule.services import Blackboard +from org.sleuthkit.autopsy.casemodule.services import Blackboard # Factory that defines the name and details of the module and allows Autopsy @@ -95,32 +94,32 @@ class SampleJythonDataSourceIngestModule(DataSourceIngestModule): # Where any setup and configuration is done # 'context' is an instance of org.sleuthkit.autopsy.ingest.IngestJobContext. - # See: http://sleuthkit.org/autopsy/docs/api-docs/3.1/classorg_1_1sleuthkit_1_1autopsy_1_1ingest_1_1_ingest_job_context.html + # See: http://sleuthkit.org/autopsy/docs/api-docs/4.1/classorg_1_1sleuthkit_1_1autopsy_1_1ingest_1_1_ingest_job_context.html # TODO: Add any setup code that you need here. def startUp(self, context): - self.context = context + # Throw an IngestModule.IngestModuleException exception if there was a problem setting up - # raise IngestModuleException("Oh No!") + # raise IngestModuleException("Oh No!") + self.context = context # Where the analysis is done. # The 'dataSource' object being passed in is of type org.sleuthkit.datamodel.Content. # See: http://www.sleuthkit.org/sleuthkit/docs/jni-docs/4.3/interfaceorg_1_1sleuthkit_1_1datamodel_1_1_content.html # 'progressBar' is of type org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProgress - # See: http://sleuthkit.org/autopsy/docs/api-docs/3.1/classorg_1_1sleuthkit_1_1autopsy_1_1ingest_1_1_data_source_ingest_module_progress.html + # See: http://sleuthkit.org/autopsy/docs/api-docs/4.1/classorg_1_1sleuthkit_1_1autopsy_1_1ingest_1_1_data_source_ingest_module_progress.html # TODO: Add your analysis code in here. def process(self, dataSource, progressBar): # we don't know how much work there is yet progressBar.switchToIndeterminate() - # This will work in 4.0.1 and beyond # Use blackboard class to index blackboard artifacts for keyword search - # blackboard = Case.getCurrentCase().getServices().getBlackboard() + blackboard = Case.getCurrentCase().getServices().getBlackboard() # For our example, we will use FileManager to get all # files with the word "test" # in the name and then count and read them - # FileManager API: http://sleuthkit.org/autopsy/docs/api-docs/3.1/classorg_1_1sleuthkit_1_1autopsy_1_1casemodule_1_1services_1_1_file_manager.html + # FileManager API: http://sleuthkit.org/autopsy/docs/api-docs/4.1/classorg_1_1sleuthkit_1_1autopsy_1_1casemodule_1_1services_1_1_file_manager.html fileManager = Case.getCurrentCase().getServices().getFileManager() files = fileManager.findFiles(dataSource, "%test%") @@ -143,12 +142,11 @@ class SampleJythonDataSourceIngestModule(DataSourceIngestModule): att = BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME, SampleJythonDataSourceIngestModuleFactory.moduleName, "Test file") art.addAttribute(att) - # This will work in 4.0.1 and beyond - #try: - # # index the artifact for keyword search - # blackboard.indexArtifact(art) - #except Blackboard.BlackboardException as e: - # self.log(Level.SEVERE, "Error indexing artifact " + art.getDisplayName()) + try: + # index the artifact for keyword search + blackboard.indexArtifact(art) + except Blackboard.BlackboardException as e: + self.log(Level.SEVERE, "Error indexing artifact " + art.getDisplayName()) # To further the example, this code will read the contents of the file and count the number of bytes inputStream = ReadContentInputStream(file) diff --git a/pythonExamples/fileIngestModule.py b/pythonExamples/fileIngestModule.py index 43d486204e..dceabac199 100755 --- a/pythonExamples/fileIngestModule.py +++ b/pythonExamples/fileIngestModule.py @@ -29,7 +29,7 @@ # Simple file-level ingest module for Autopsy. # Search for TODO for the things that you need to change -# See http://sleuthkit.org/autopsy/docs/api-docs/3.1/index.html for documentation +# See http://sleuthkit.org/autopsy/docs/api-docs/4.1/index.html for documentation import jarray import inspect @@ -53,8 +53,7 @@ from org.sleuthkit.autopsy.coreutils import Logger from org.sleuthkit.autopsy.casemodule import Case from org.sleuthkit.autopsy.casemodule.services import Services from org.sleuthkit.autopsy.casemodule.services import FileManager -# This will work in 4.0.1 and beyond -# from org.sleuthkit.autopsy.casemodule.services import Blackboard +from org.sleuthkit.autopsy.casemodule.services import Blackboard # Factory that defines the name and details of the module and allows Autopsy # to create instances of the modules that will do the anlaysis. @@ -95,7 +94,7 @@ class SampleJythonFileIngestModule(FileIngestModule): # Where any setup and configuration is done # 'context' is an instance of org.sleuthkit.autopsy.ingest.IngestJobContext. - # See: http://sleuthkit.org/autopsy/docs/api-docs/3.1/classorg_1_1sleuthkit_1_1autopsy_1_1ingest_1_1_ingest_job_context.html + # See: http://sleuthkit.org/autopsy/docs/api-docs/4.1/classorg_1_1sleuthkit_1_1autopsy_1_1ingest_1_1_ingest_job_context.html # TODO: Add any setup code that you need here. def startUp(self, context): self.filesFound = 0 @@ -115,9 +114,8 @@ class SampleJythonFileIngestModule(FileIngestModule): (file.isFile() == False)): return IngestModule.ProcessResult.OK - # This will work in 4.0.1 and beyond # Use blackboard class to index blackboard artifacts for keyword search - # blackboard = Case.getCurrentCase().getServices().getBlackboard() + blackboard = Case.getCurrentCase().getServices().getBlackboard() # For an example, we will flag files with .txt in the name and make a blackboard artifact. if file.getName().lower().endswith(".txt"): @@ -132,12 +130,11 @@ class SampleJythonFileIngestModule(FileIngestModule): SampleJythonFileIngestModuleFactory.moduleName, "Text Files") art.addAttribute(att) - # This will work in 4.0.1 and beyond - #try: - # # index the artifact for keyword search - # blackboard.indexArtifact(art) - #except Blackboard.BlackboardException as e: - # self.log(Level.SEVERE, "Error indexing artifact " + art.getDisplayName()) + try: + # index the artifact for keyword search + blackboard.indexArtifact(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( diff --git a/pythonExamples/fileIngestModuleWithGui.py b/pythonExamples/fileIngestModuleWithGui.py index f34c7289b6..ad2e36e984 100755 --- a/pythonExamples/fileIngestModuleWithGui.py +++ b/pythonExamples/fileIngestModuleWithGui.py @@ -35,7 +35,7 @@ # don't need a configuration UI, start with the other sample module. # # Search for TODO for the things that you need to change -# See http://sleuthkit.org/autopsy/docs/api-docs/3.1/index.html for documentation +# See http://sleuthkit.org/autopsy/docs/api-docs/4.1/index.html for documentation import jarray diff --git a/pythonExamples/reportmodule.py b/pythonExamples/reportmodule.py index 759602bdb6..b4810dca34 100755 --- a/pythonExamples/reportmodule.py +++ b/pythonExamples/reportmodule.py @@ -31,7 +31,7 @@ # Sample report module for Autopsy. Use as a starting point for new modules. # # Search for TODO for the things that you need to change -# See http://sleuthkit.org/autopsy/docs/api-docs/3.1/index.html for documentation +# See http://sleuthkit.org/autopsy/docs/api-docs/4.1/index.html for documentation import os from java.lang import System @@ -69,7 +69,7 @@ class SampleGeneralReportModule(GeneralReportModuleAdapter): # 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 'progressBar' object is of type ReportProgressPanel. - # See: http://sleuthkit.org/autopsy/docs/api-docs/3.1/classorg_1_1sleuthkit_1_1autopsy_1_1report_1_1_report_progress_panel.html + # See: http://sleuthkit.org/autopsy/docs/api-docs/4.1/classorg_1_1sleuthkit_1_1autopsy_1_1report_1_1_report_progress_panel.html def generateReport(self, baseReportDir, progressBar): # For an example, we write a file with the number of files created in the past 2 weeks From e41e52e40c90787ba000e8c3b0eb4402d7dd009a Mon Sep 17 00:00:00 2001 From: Sophie Mori Date: Tue, 13 Dec 2016 10:18:17 -0500 Subject: [PATCH 02/37] Add python files for module --- .../android/browserlocation.py | 105 +++++++++++++ .../android/cachelocation.py | 128 ++++++++++++++++ .../InternalPythonModules/android/calllog.py | 126 ++++++++++++++++ .../InternalPythonModules/android/contact.py | 142 ++++++++++++++++++ .../InternalPythonModules/android/general.py | 9 ++ .../android/googlemap.py | 124 +++++++++++++++ .../InternalPythonModules/android/module.py | 109 ++++++++++++++ .../android/tangomessage.py | 121 +++++++++++++++ .../android/textmessage.py | 110 ++++++++++++++ .../android/wwfmessage.py | 103 +++++++++++++ 10 files changed, 1077 insertions(+) create mode 100755 Core/release/InternalPythonModules/android/browserlocation.py create mode 100755 Core/release/InternalPythonModules/android/cachelocation.py create mode 100755 Core/release/InternalPythonModules/android/calllog.py create mode 100755 Core/release/InternalPythonModules/android/contact.py create mode 100755 Core/release/InternalPythonModules/android/general.py create mode 100755 Core/release/InternalPythonModules/android/googlemap.py create mode 100755 Core/release/InternalPythonModules/android/module.py create mode 100755 Core/release/InternalPythonModules/android/tangomessage.py create mode 100755 Core/release/InternalPythonModules/android/textmessage.py create mode 100755 Core/release/InternalPythonModules/android/wwfmessage.py diff --git a/Core/release/InternalPythonModules/android/browserlocation.py b/Core/release/InternalPythonModules/android/browserlocation.py new file mode 100755 index 0000000000..a528f2d66e --- /dev/null +++ b/Core/release/InternalPythonModules/android/browserlocation.py @@ -0,0 +1,105 @@ +from java.io import File +from java.lang import Class +from java.lang import ClassNotFoundException +from java.lang import Double +from java.lang import Long +from java.sql import Connection +from java.sql import DriverManager +from java.sql import ResultSet +from java.sql import SQLException +from java.sql import Statement +from java.util.logging import Level +from org.sleuthkit.autopsy.casemodule import Case +from org.sleuthkit.autopsy.casemodule.services import Blackboard +from org.sleuthkit.autopsy.casemodule.services import FileManager +from org.sleuthkit.autopsy.coreutils import Logger +from org.sleuthkit.autopsy.coreutils import MessageNotifyUtil +from org.sleuthkit.autopsy.datamodel import ContentUtils +from org.sleuthkit.autopsy.ingest import IngestJobContext +from org.sleuthkit.datamodel import AbstractFile +from org.sleuthkit.datamodel import BlackboardArtifact +from org.sleuthkit.datamodel import BlackboardAttribute +from org.sleuthkit.datamodel import Content +from org.sleuthkit.datamodel import TskCoreException + +import traceback +import general + +""" +Analyzes database created by browser that stores GEO location info. +""" +class BrowserLocationAnalyzer(general.AndroidComponentAnalyzer): + + def __init__(self): + self._logger = Logger.getLogger(self.__class__.__name__) + + def analyze(self, dataSource, fileManager, context): + try: + abstractFiles = fileManager.findFiles(dataSource, "CachedGeoposition%.db") + for abstractFile in abstractFiles: + if abstractFile.getSize() == 0: + continue + try: + jFile = File(Case.getCurrentCase().getTempDirectory(), abstractFile.getName()) + ContentUtils.writeToFile(abstractFile, jFile, context.dataSourceIngestIsCancelled) + self.findGeoLocationsInDB(jFile.toString(), abstractFile) + except Exception as ex: + self._logger.log(Level.SEVERE, "Error parsing Browser Location files", ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) + except TskCoreException as ex: + self._logger.log(Level.SEVERE, "Error finding Browser Location files", ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) + + def findGeoLocationsInDB(self, databasePath, abstractFile): + connection = None + resultSet = None + statement = None + + if not databasePath: + return + + try: + Class.forName("org.sqlite.JDBC") #load JDBC driver + connection = DriverManager.getConnection("jdbc:sqlite:" + databasePath) + statement = connection.createStatement() + except (ClassNotFoundException, SQLException) as ex: + self._logger.log(Level.SEVERE, "Error connecting to sql database", ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) + return + + try: + resultSet = statement.executeQuery("SELECT timestamp, latitude, longitude, accuracy FROM CachedPosition;") + while resultSet.next(): + timestamp = Long.valueOf(resultSet.getString("timestamp")) / 1000 + latitude = Double.valueOf(resultSet.getString("latitude")) + longitude = Double.valueOf(resultSet.getString("longitude")) + + artifact = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT) + artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE, general.MODULE_NAME, latitude)) + artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE, general.MODULE_NAME, longitude)) + artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, general.MODULE_NAME, timestamp)) + artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME, general.MODULE_NAME, "Browser Location History")) + # artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_VALUE.getTypeID(),moduleName, accuracy)) + # NOTE: originally commented out + + try: + # index the artifact for keyword search + blackboard = Case.getCurrentCase().getServices().getBlackboard() + blackboard.indexArtifact(artifact) + except Blackboard.BlackboardException as ex: + self._logger.log(Level.SEVERE, "Unable to index blackboard artifact " + artifact.getArtifactTypeName(), ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) + MessageNotifyUtil.Notify.error("Failed to index GPS trackpoint artifact for keyword search.", artifact.getDisplayName()) + + except Exception as ex: + self._logger.log(Level.SEVERE, "Error Putting artifacts to Blackboard", ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) + finally: + try: + if resultSet is not None: + resultSet.close() + statement.close() + connection.close() + except Exception as ex: + self._logger.log(Level.SEVERE, "Error closing database", ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) diff --git a/Core/release/InternalPythonModules/android/cachelocation.py b/Core/release/InternalPythonModules/android/cachelocation.py new file mode 100755 index 0000000000..92d52ae987 --- /dev/null +++ b/Core/release/InternalPythonModules/android/cachelocation.py @@ -0,0 +1,128 @@ +from java.io import File +from java.io import FileInputStream +from java.io import InputStream +from java.lang import Class +from java.lang import ClassNotFoundException +from java.math import BigInteger +from java.nio import ByteBuffer +from java.util.logging import Level +from org.sleuthkit.autopsy.casemodule import Case +from org.sleuthkit.autopsy.casemodule.services import Blackboard +from org.sleuthkit.autopsy.casemodule.services import FileManager +from org.sleuthkit.autopsy.coreutils import Logger +from org.sleuthkit.autopsy.coreutils import MessageNotifyUtil +from org.sleuthkit.autopsy.datamodel import ContentUtils +from org.sleuthkit.autopsy.ingest import IngestJobContext +from org.sleuthkit.datamodel import AbstractFile +from org.sleuthkit.datamodel import BlackboardArtifact +from org.sleuthkit.datamodel import BlackboardAttribute +from org.sleuthkit.datamodel import Content +from org.sleuthkit.datamodel import TskCoreException + +import traceback +import general + +""" +Parses cache files that Android maintains for Wifi and cell towers. Adds GPS points to blackboard. +""" +class CacheLocationAnalyzer(general.AndroidComponentAnalyzer): + + def __init__(self): + self._logger = Logger.getLogger("CacheLocationAnalyzer") + + """ + cache.cell stores mobile tower GPS locations and cache.wifi stores GPS + and MAC info from Wifi points. + """ + def analyze(self, dataSource, fileManager, context): + try: + abstractFiles = fileManager.findFiles(dataSource, "cache.cell") + abstractFiles.addAll(fileManager.findFiles(dataSource, "cache.wifi")) + for abstractFile in abstractFiles: + if abstractFile.getSize() == 0: + continue + try: + jFile = File(Case.getCurrentCase().getTempDirectory(), abstractFile.getName()) + ContentUtils.writeToFile(abstractFile, jFile, context.dataSourceIngestIsCancelled) + self.findGeoLocationsInFile(jFile, abstractFile) + except Exception as ex: + self._logger.log(Level.SEVERE, "Error parsing cached Location files", ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) + except TskCoreException as ex: + self._logger.log(Level.SEVERE, "Error finding cached Location files", ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) + + def findGeoLocationsInFile(self, file, abstractFile): + + tempBytes = bytearray([0] * 2) # will temporarily hold bytes to be converted into the correct data types + + try: + inputStream = FileInputStream(file) + + inputStream.read(tempBytes) # version + + tempBytes = bytearray([0] * 2) + inputStream.read(tempBytes) # number of location entries + + iterations = BigInteger(tempBytes).intValue() + + for i in range(iterations): # loop through every entry + tempBytes = bytearray([0] * 2) + inputStream.read(tempBytes) + + tempBytes = bytearray([0]) + inputStream.read(tempBytes) + + while BigInteger(tempBytes).intValue() != 0: # pass through non important values until the start of accuracy(around 7-10 bytes) + if 0 > inputStream.read(tempBytes): + break # we've passed the end of the file, so stop + + tempBytes = bytearray([0] * 3) + inputStream.read(tempBytes) + if BigInteger(tempBytes).intValue() <= 0: # This refers to a location that could not be calculated + tempBytes = bytearray([0] * 28) # read rest of the row's bytes + inputStream.read(tempBytes) + continue + accuracy = "" + BigInteger(tempBytes).intValue() + + tempBytes = bytearray([0] * 4) + inputStream.read(tempBytes) + confidence = "" + BigInteger(tempBytes).intValue() + + tempBytes = bytearray([0] * 8) + inputStream.read(tempBytes) + latitude = CacheLocationAnalyzer.toDouble(bytes) + + tempBytes = bytearray([0] * 8) + inputStream.read(tempBytes) + longitude = CacheLocationAnalyzer.toDouble(bytes) + + tempBytes = bytearray([0] * 8) + inputStream.read(tempBytes) + timestamp = BigInteger(tempBytes).longValue() / 1000 + + artifact = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT) + artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE, AndroidAnalyzer.MODULE_NAME, latitude)) + artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE, AndroidAnalyzer.MODULE_NAME, longitude)) + artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, AndroidModuleFactorymodule.Name, timestamp)) + artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME, AndroidAnalyzer.MODULE_NAME, + file.getName() + "Location History")) + + #Not storing these for now. + # artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_VALUE.getTypeID(), AndroidModuleFactorymodule.moduleName, accuracy)) + # artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT.getTypeID(), AndroidModuleFactorymodule.moduleName, confidence)) + try: + # index the artifact for keyword search + blackboard = Case.getCurrentCase().getServices().getBlackboard() + blackboard.indexArtifact(artifact) + except Blackboard.BlackboardException as ex: + self._logger.log(Level.SEVERE, "Unable to index blackboard artifact " + artifact.getArtifactID(), ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) + MessageNotifyUtil.Notify.error("Failed to index GPS trackpoint artifact for keyword search.", artifact.getDisplayName()) + + except Exception as ex: + self._logger.log(Level.SEVERE, "Error parsing Cached GPS locations to Blackboard", ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) + + def toDouble(byteArray): + return ByteBuffer.wrap(byteArray).getDouble() diff --git a/Core/release/InternalPythonModules/android/calllog.py b/Core/release/InternalPythonModules/android/calllog.py new file mode 100755 index 0000000000..d118c6c6d9 --- /dev/null +++ b/Core/release/InternalPythonModules/android/calllog.py @@ -0,0 +1,126 @@ +from java.io import File +from java.io import IOException +from java.lang import Class +from java.lang import ClassNotFoundException +from java.lang import String +from java.sql import Connection +from java.sql import DriverManager +from java.sql import ResultSet +from java.sql import SQLException +from java.sql import Statement +from java.util.logging import Level +from org.sleuthkit.autopsy.casemodule import Case +from org.sleuthkit.autopsy.casemodule.services import Blackboard +from org.sleuthkit.autopsy.casemodule.services import FileManager +from org.sleuthkit.autopsy.coreutils import Logger +from org.sleuthkit.autopsy.coreutils import MessageNotifyUtil +from org.sleuthkit.autopsy.datamodel import ContentUtils +from org.sleuthkit.autopsy.ingest import IngestJobContext +from org.sleuthkit.datamodel import AbstractFile +from org.sleuthkit.datamodel import BlackboardArtifact +from org.sleuthkit.datamodel import BlackboardAttribute +from org.sleuthkit.datamodel.BlackboardAttribute import ATTRIBUTE_TYPE +from org.sleuthkit.datamodel import Content +from org.sleuthkit.datamodel import TskCoreException + +import traceback +import general + +""" +Locates a variety of different call log databases, parses them, and populates the blackboard. +""" +class CallLogAnalyzer(general.AndroidComponentAnalyzer): + + def __init__(self): + self._logger = Logger.getLogger("CallLogAnalyzer") + + # the names of tables that potentially hold call logs in the dbs + _tableNames = ["calls", "logs"] + + class CallDirection: + + def __init__(self, type, displayName): + self.type = type + self.displayName = displayName + + def getDisplayName(self): + return self.displayName + + INCOMING = CallDirection(1, "Incoming") + OUTGOING = CallDirection(2, "Outgoing") + MISSED = CallDirection(3, "Missed") + + @staticmethod + def fromType(t): + return { + 1: CallLogAnalyzer.INCOMING, + 2: CallLogAnalyzer.OUTGOING, + 3: CallLogAnalyzer.MISSED + }.get(t, None) + + def analyze(self, dataSource, fileManager, context): + try: + absFiles = fileManager.findFiles(dataSource, "logs.db") + absFiles.addAll(fileManager.findFiles(dataSource, "contacts.db")) + absFiles.addAll(fileManager.findFiles(dataSource, "contacts2.db")) + for abstractFile in absFiles: + try: + file = File(Case.getCurrentCase().getTempDirectory(), abstractFile.getName()) + ContentUtils.writeToFile(abstractFile, file, context.dataSourceIngestIsCancelled) + self.findCallLogsInDB(file.toString(), abstractFile) + except IOException as ex: + self._logger.log(Level.SEVERE, "Error writing temporary call log db to disk", ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) + except TskCoreException as ex: + self._logger.log(Level.SEVERE, "Error finding call logs", ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) + + def findCallLogsInDB(self, databasePath, abstractFile): + if not databasePath: + return + + try: + connection = DriverManager.getConnection("jdbc:sqlite:" + databasePath) + statement = connection.createStatement() + + for tableName in CallLogAnalyzer._tableNames: + try: + resultSet = statement.executeQuery("SELECT number, date, duration, type, name FROM " + tableName + " ORDER BY date DESC;") + self._logger.log(Level.INFO, "Reading call log from table {0} in db {1}", [tableName, databasePath]) + while resultSet.next(): + date = resultSet.getLong("date") / 1000 + direction = CallLogAnalyzer.fromType(resultSet.getInt("type")) + directionString = direction.getDisplayName() if direction is not None else "" + number = resultSet.getString("number") + duration = resultSet.getLong("duration") # duration of call is in seconds + name = resultSet.getString("name") # name of person dialed or called. None if unregistered + + try: + artifact = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG) # create a call log and then add attributes from result set. + if direction == CallLogAnalyzer.OUTGOING: + artifact.addAttribute(BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO, general.MODULE_NAME, number)) + else: # Covers INCOMING and MISSED + artifact.addAttribute(BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM, general.MODULE_NAME, number)) + + artifact.addAttribute(BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_START, general.MODULE_NAME, date)) + artifact.addAttribute(BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_END, general.MODULE_NAME, duration + date)) + artifact.addAttribute(BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DIRECTION, general.MODULE_NAME, directionString)) + artifact.addAttribute(BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, general.MODULE_NAME, name)) + + try: + # index the artifact for keyword search + blackboard = Case.getCurrentCase().getServices().getBlackboard() + blackboard.indexArtifact(artifact) + except Blackboard.BlackboardException as ex: + self._logger.log(Level.SEVERE, "Unable to index blackboard artifact " + artifact.getArtifactID(), ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) + MessageNotifyUtil.Notify.error("Failed to index call log artifact for keyword search.", artifact.getDisplayName()) + + except TskCoreException as ex: + self._logger.log(Level.SEVERE, "Error posting call log record to the Blackboard", ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) + except SQLException as ex: + self._logger.log(Level.WARNING, String.format("Could not read table %s in db %s", tableName, databasePath), ex) + except SQLException as ex: + self._logger.log(Level.SEVERE, "Could not parse call log; error connecting to db " + databasePath, ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) diff --git a/Core/release/InternalPythonModules/android/contact.py b/Core/release/InternalPythonModules/android/contact.py new file mode 100755 index 0000000000..27b6976cf3 --- /dev/null +++ b/Core/release/InternalPythonModules/android/contact.py @@ -0,0 +1,142 @@ +from java.io import File +from java.lang import Class +from java.lang import ClassNotFoundException +from java.sql import Connection +from java.sql import DatabaseMetaData +from java.sql import DriverManager +from java.sql import ResultSet +from java.sql import SQLException +from java.sql import Statement +from java.util.logging import Level +from org.sleuthkit.autopsy.casemodule import Case +from org.sleuthkit.autopsy.casemodule.services import Blackboard +from org.sleuthkit.autopsy.casemodule.services import FileManager +from org.sleuthkit.autopsy.coreutils import Logger +from org.sleuthkit.autopsy.coreutils import MessageNotifyUtil +from org.sleuthkit.autopsy.datamodel import ContentUtils +from org.sleuthkit.autopsy.ingest import IngestJobContext +from org.sleuthkit.datamodel import AbstractFile +from org.sleuthkit.datamodel import BlackboardArtifact +from org.sleuthkit.datamodel import BlackboardAttribute +from org.sleuthkit.datamodel import Content +from org.sleuthkit.datamodel import TskCoreException + +import traceback +import general + +""" +Locates a variety of different contacts databases, parses them, and populates the blackboard. +""" +class ContactAnalyzer(general.AndroidComponentAnalyzer): + + def __init__(self): + self._logger = Logger.getLogger("ContactAnalyzer") + + def analyze(self, dataSource, fileManager, context): + try: + absFiles = fileManager.findFiles(dataSource, "contacts.db") + absFiles.addAll(fileManager.findFiles(dataSource, "contacts2.db")) + if absFiles.isEmpty(): + return + for abstractFile in absFiles: + try: + jFile = File(Case.getCurrentCase().getTempDirectory(), abstractFile.getName()) + ContentUtils.writeToFile(abstractFile, jFile, context.dataSourceIngestIsCancelled) + self.findContactsInDB(str(jFile.toString()), abstractFile) + except Exception as ex: + self._logger.log(Level.SEVERE, "Error parsing Contacts", ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) + except TskCoreException as ex: + self._logger.log(Level.SEVERE, "Error finding Contacts", ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) + + """ + Will create artifact from a database given by the path + The fileId will be the abstract file associated with the artifacts + """ + def findContactsInDB(self, databasePath, abstractFile): + connection = None + resultSet = None + statement = None + blackboard = Case.getCurrentCase().getServices().getBlackboard() + + if not databasePath: + return + + try: + Class.forName("org.sqlite.JDBC") # load JDBC driver + connection = DriverManager.getConnection("jdbc:sqlite:" + databasePath) + statement = connection.createStatement() + except (ClassNotFoundException, SQLException) as ex: + self._logger.log(Level.SEVERE, "Error opening database", ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) + return + + try: + # get display_name, mimetype(email or phone number) and data1 (phonenumber or email address depending on mimetype) + # sorted by name, so phonenumber/email would be consecutive for a person if they exist. + # check if contacts.name_raw_contact_id exists. Modify the query accordingly. + columnFound = False + metadata = connection.getMetaData() + columnListResultSet = metadata.getColumns(None, None, "contacts", None) + while columnListResultSet.next(): + if columnListResultSet.getString("COLUMN_NAME") == "name_raw_contact_id": + columnFound = True + break + if columnFound: + resultSet = statement.executeQuery( + "SELECT mimetype, data1, name_raw_contact.display_name AS display_name \n" + + "FROM raw_contacts JOIN contacts ON (raw_contacts.contact_id=contacts._id) \n" + + "JOIN raw_contacts AS name_raw_contact ON(name_raw_contact_id=name_raw_contact._id) " + + "LEFT OUTER JOIN data ON (data.raw_contact_id=raw_contacts._id) \n" + + "LEFT OUTER JOIN mimetypes ON (data.mimetype_id=mimetypes._id) \n" + + "WHERE mimetype = 'vnd.android.cursor.item/phone_v2' OR mimetype = 'vnd.android.cursor.item/email_v2'\n" + + "ORDER BY name_raw_contact.display_name ASC;") + else: + resultSet = statement.executeQuery( + "SELECT mimetype, data1, raw_contacts.display_name AS display_name \n" + + "FROM raw_contacts JOIN contacts ON (raw_contacts.contact_id=contacts._id) \n" + + "LEFT OUTER JOIN data ON (data.raw_contact_id=raw_contacts._id) \n" + + "LEFT OUTER JOIN mimetypes ON (data.mimetype_id=mimetypes._id) \n" + + "WHERE mimetype = 'vnd.android.cursor.item/phone_v2' OR mimetype = 'vnd.android.cursor.item/email_v2'\n" + + "ORDER BY raw_contacts.display_name ASC;") + + artifact = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT) + oldName = "" + while resultSet.next(): + name = resultSet.getString("display_name") + data1 = resultSet.getString("data1") # the phone number or email + mimetype = resultSet.getString("mimetype") # either phone or email + if name != oldName: + artifact = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT) + artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME, general.MODULE_NAME, name)) + if mimetype == "vnd.android.cursor.item/phone_v2": + artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER, general.MODULE_NAME, data1)) + else: + artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL, general.MODULE_NAME, data1)) + + oldName = name + + try: + # index the artifact for keyword search + blackboard = Case.getCurrentCase().getServices().getBlackboard() + blackboard.indexArtifact(artifact) + except Blackboard.BlackboardException as ex: + self._logger.log(Level.SEVERE, "Unable to index blackboard artifact " + artifact.getArtifactID(), ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) + MessageNotifyUtil.Notify.error("Failed to index contact artifact for keyword search.", artifact.getDisplayName()) + + except SQLException as ex: + self._logger.log(Level.WARNING, "Unable to execute contacts SQL query against {0} : {1}", [databasePath, ex]) + except TskCoreException as ex: + self._logger.log(Level.SEVERE, "Error posting to blackboard", ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) + finally: + try: + if resultSet is not None: + resultSet.close() + statement.close() + connection.close() + except Exception as ex: + self._logger.log(Level.SEVERE, "Error closing database", ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) diff --git a/Core/release/InternalPythonModules/android/general.py b/Core/release/InternalPythonModules/android/general.py new file mode 100755 index 0000000000..3316e89e6d --- /dev/null +++ b/Core/release/InternalPythonModules/android/general.py @@ -0,0 +1,9 @@ +MODULE_NAME = "Android Analyzer Python" + +""" +A parent class of the analyzers +""" +class AndroidComponentAnalyzer: + # The Analyzer should implement this method + def analyze(self, dataSource, fileManager, context): + raise NotImplementedError diff --git a/Core/release/InternalPythonModules/android/googlemap.py b/Core/release/InternalPythonModules/android/googlemap.py new file mode 100755 index 0000000000..c10eef51ea --- /dev/null +++ b/Core/release/InternalPythonModules/android/googlemap.py @@ -0,0 +1,124 @@ +from java.io import File +from java.lang import Class +from java.lang import ClassNotFoundException +from java.lang import Double +from java.lang import Long +from java.sql import Connection +from java.sql import DriverManager +from java.sql import ResultSet +from java.sql import SQLException +from java.sql import Statement +from java.util.logging import Level +from org.sleuthkit.autopsy.casemodule import Case +from org.sleuthkit.autopsy.casemodule.services import Blackboard +from org.sleuthkit.autopsy.casemodule.services import FileManager +from org.sleuthkit.autopsy.coreutils import Logger +from org.sleuthkit.autopsy.coreutils import MessageNotifyUtil +from org.sleuthkit.autopsy.datamodel import ContentUtils +from org.sleuthkit.autopsy.ingest import IngestJobContext +from org.sleuthkit.datamodel import AbstractFile +from org.sleuthkit.datamodel import BlackboardArtifact +from org.sleuthkit.datamodel import BlackboardAttribute +from org.sleuthkit.datamodel import Content +from org.sleuthkit.datamodel import TskCoreException + +import traceback +import general + +""" +Finds and parses the Google Maps database. +""" +class GoogleMapLocationAnalyzer(general.AndroidComponentAnalyzer): + + def __init__(self): + self._logger = Logger.getLogger("GoogleMapLocationAnalyzer") + + def analyze(self, dataSource, fileManager, context): + try: + absFiles = fileManager.findFiles(dataSource, "da_destination_history") + if absFiles.isEmpty(): + return + for abstractFile in absFiles: + try: + jFile = File(Case.getCurrentCase().getTempDirectory(), abstractFile.getName()) + ContentUtils.writeToFile(abstractFile, jFile, context.dataSourceIngestIsCancelled) + self.findGeoLocationsInDB(jFile.toString(), abstractFile) + except Exception as ex: + self._logger.log(Level.SEVERE, "Error parsing Google map locations", ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) + except TskCoreException as ex: + self._logger.log(Level.SEVERE, "Error finding Google map locations", ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) + + def findGeoLocationsInDB(self, databasePath, abstractFile): + connection = None + resultSet = None + statement = None + + if not databasePath: + return + + try: + Class.forName("org.sqlite.JDBC") # load JDBC driver + connection = DriverManager.getConnection("jdbc:sqlite:" + databasePath) + statement = connection.createStatement() + except (ClassNotFoundException, SQLException) as ex: + self._logger.log(Level.SEVERE, "Error opening database", ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) + return + + try: + resultSet = statement.executeQuery( + "SELECT time, dest_lat, dest_lng, dest_title, dest_address, source_lat, source_lng FROM destination_history;") + + while resultSet.next(): + time = Long.valueOf(resultSet.getString("time")) / 1000 + dest_title = resultSet.getString("dest_title") + dest_address = resultSet.getString("dest_address") + + dest_lat = GoogleMapLocationAnalyzer.convertGeo(resultSet.getString("dest_lat")) + dest_lng = GoogleMapLocationAnalyzer.convertGeo(resultSet.getString("dest_lng")) + source_lat = GoogleMapLocationAnalyzer.convertGeo(resultSet.getString("source_lat")) + source_lng = GoogleMapLocationAnalyzer.convertGeo(resultSet.getString("source_lng")) + + artifact = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_ROUTE) + artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CATEGORY, general.MODULE_NAME, "Destination")) + artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, general.MODULE_NAME, time)) + artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_END, general.MODULE_NAME, dest_lat)) + artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_END, general.MODULE_NAME, dest_lng)) + artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_START, general.MODULE_NAME, source_lat)) + artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_START, general.MODULE_NAME, source_lng)) + artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME, general.MODULE_NAME, dest_title)) + artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_LOCATION, general.MODULE_NAME, dest_address)) + artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME, general.MODULE_NAME, "Google Maps History")) + + try: + # index the artifact for keyword search + blackboard = Case.getCurrentCase().getServices().getBlackboard() + blackboard.indexArtifact(artifact) + except Blackboard.BlackboardException as ex: + self._logger.log(Level.SEVERE, "Unable to index blackboard artifact " + artifact.getArtifactID(), ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) + MessageNotifyUtil.Notify.error("Failed to index GPS route artifact for keyword search.", artifact.getDisplayName()) + + except Exception as ex: + self._logger.log(Level.SEVERE, "Error parsing Google map locations to the Blackboard", ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) + finally: + try: + if resultSet is not None: + resultSet.close() + statement.close() + connection.close() + except Exception as ex: + self._logger.log(Level.SEVERE, "Error closing the database", ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) + + # add periods 6 decimal places before the end. + @staticmethod + def convertGeo(s): + length = len(s) + if length > 6: + return Double.valueOf(s[0 : length-6] + "." + s[length-6 : length]) + else: + return Double.valueOf(s) diff --git a/Core/release/InternalPythonModules/android/module.py b/Core/release/InternalPythonModules/android/module.py new file mode 100755 index 0000000000..83ea9002c5 --- /dev/null +++ b/Core/release/InternalPythonModules/android/module.py @@ -0,0 +1,109 @@ +import jarray +import inspect +import traceback + +from java.util.logging import Level +from org.openide.util.lookup import ServiceProvider +from org.openide.util import NbBundle +from org.sleuthkit.autopsy.coreutils import Version +from org.sleuthkit.autopsy.ingest import IngestModuleFactory +from org.sleuthkit.autopsy.ingest import DataSourceIngestModule +from org.sleuthkit.autopsy.ingest import IngestModuleFactoryAdapter +from org.sleuthkit.autopsy.ingest import IngestModuleIngestJobSettings +from org.sleuthkit.autopsy.casemodule import Case +from org.sleuthkit.autopsy.casemodule.services import FileManager +from org.sleuthkit.autopsy.coreutils import Logger +from org.sleuthkit.autopsy.ingest import DataSourceIngestModuleProgress +from org.sleuthkit.autopsy.ingest import IngestModule +from org.sleuthkit.datamodel import Content +from org.sleuthkit.autopsy.ingest import DataSourceIngestModule +from org.sleuthkit.autopsy.ingest import IngestJobContext +from org.sleuthkit.autopsy.ingest import IngestMessage + +import general +import browserlocation +import cachelocation +import calllog +import contact +import googlemap +import tangomessage +import textmessage +import wwfmessage + +class AndroidModuleFactory(IngestModuleFactoryAdapter): + + moduleName = general.MODULE_NAME + + def getModuleDisplayName(self): + return self.moduleName + + def getModuleDescription(self): + return "Extracts Android system and third-party app data." + + def getModuleVersionNumber(self): + return Version.getVersion() + + def isDataSourceIngestModuleFactory(self): + return True + + def createDataSourceIngestModule(self, ingestOptions): + return AndroidIngestModule() + + +class AndroidIngestModule(DataSourceIngestModule): + + _logger = Logger.getLogger(AndroidModuleFactory.moduleName) + + def log(self, level, msg): + self._logger.logp(level, self.__class__.__name__, inspect.stack()[1][3], msg) + + def __init__(self): + self.context = None + + def startUp(self, context): + self.context = context + + # Throw an IngestModule.IngestModuleException exception if there was a problem setting up + + # Where the analysis is done. + def process(self, dataSource, progressBar): + + errors = [] + fileManager = Case.getCurrentCase().getServices().getFileManager() + analyzers = [contact.ContactAnalyzer(), calllog.CallLogAnalyzer(), textmessage.TextMessageAnalyzer(), tangomessage.TangoMessageAnalyzer(), wwfmessage.WWFMessageAnalyzer(), googlemap.GoogleMapLocationAnalyzer(), browserlocation.BrowserLocationAnalyzer(), cachelocation.CacheLocationAnalyzer()] + self.log(Level.INFO, "running " + str(len(analyzers)) + " analyzers") + progressBar.switchToDeterminate(len(analyzers)) + + n = 0 + for analyzer in analyzers: + if self.context.dataSourceIngestIsCancelled(): + return IngestModule.ProcessResult.OK + try: + analyzer.analyze(dataSource, fileManager, self.context) + n += 1 + progressBar.progress(n) + except Exception as ex: + errors.append("Error getting Contacts") + self.log(Level.SEVERE, traceback.format_exc()) + errorMessage = [] # NOTE: this isn't used? + errorMessageSubject = "" # NOTE: this isn't used? + msgLevel = IngestMessage.MessageType.INFO + + if errors: + msgLevel = IngestMessage.MessageType.ERROR + errorMessage.append("Errors were encountered") + + errorMessage.append("\n") + + if len(errors) == 1: + errorMsgSubject = "One error was found" + else: + errorMsgSubject = "errors found: " + str(len(errors)) + else: + errorMessage.append("No errors") + errorMsgSubject = "No errors" + + return IngestModule.ProcessResult.OK diff --git a/Core/release/InternalPythonModules/android/tangomessage.py b/Core/release/InternalPythonModules/android/tangomessage.py new file mode 100755 index 0000000000..b77e75a78a --- /dev/null +++ b/Core/release/InternalPythonModules/android/tangomessage.py @@ -0,0 +1,121 @@ +from java.io import File +from java.lang import Class +from java.lang import ClassNotFoundException +from java.lang import Long +from java.lang import String +from java.sql import Connection +from java.sql import DriverManager +from java.sql import ResultSet +from java.sql import SQLException +from java.sql import Statement +from java.util.logging import Level +from org.apache.commons.codec.binary import Base64 +from org.sleuthkit.autopsy.casemodule import Case +from org.sleuthkit.autopsy.casemodule.services import Blackboard +from org.sleuthkit.autopsy.casemodule.services import FileManager +from org.sleuthkit.autopsy.coreutils import Logger +from org.sleuthkit.autopsy.coreutils import MessageNotifyUtil +from org.sleuthkit.autopsy.datamodel import ContentUtils +from org.sleuthkit.autopsy.ingest import IngestJobContext +from org.sleuthkit.datamodel import AbstractFile +from org.sleuthkit.datamodel import BlackboardArtifact +from org.sleuthkit.datamodel import BlackboardAttribute +from org.sleuthkit.datamodel import Content +from org.sleuthkit.datamodel import TskCoreException + +import traceback +import general + +""" +Locates database for the Tango app and adds info to blackboard. +""" +class TangoMessageAnalyzer(general.AndroidComponentAnalyzer): + + def __init__(self): + self._logger = Logger.getLogger("TangoMessageAnalyzer") + + def analyze(self, dataSource, fileManager, context): + try: + absFiles = fileManager.findFiles(dataSource, "tc.db") + for abstractFile in absFiles: + try: + jFile = File(Case.getCurrentCase().getTempDirectory(), abstractFile.getName()) + ContentUtils.writeToFile(abstractFile, jFile, context.dataSourceIngestIsCancelled) + self.findTangoMessagesInDB(jFile.toString(), abstractFile) + except Exception as ex: + self._logger.log(Level.SEVERE, "Error parsing Tango messages", ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) + except TskCoreException as ex: + self._logger.log(Level.SEVERE, "Error finding Tango messages", ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) + + def findTangoMessagesInDB(self, databasePath, abstractFile): + connection = None + resultSet = None + statement = None + + if not databasePath: + return + + try: + Class.forName("org.sqlite.JDBC") # load JDBC driver + connection = DriverManager.getConnection("jdbc:sqlite:" + databasePath) + statement = connection.createStatement() + except (ClassNotFoundException, SQLException) as ex: + self._logger.log(Level.SEVERE, "Error opening database", ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) + return + + try: + resultSet = statement.executeQuery( + "SELECT conv_id, create_time, direction, payload FROM messages ORDER BY create_time DESC;") + + while resultSet.next(): + conv_id = resultSet.getString("conv_id") # seems to wrap around the message found in payload after decoding from base-64 + create_time = Long.valueOf(resultSet.getString("create_time")) / 1000 + if resultSet.getString("direction") == "1": # 1 incoming, 2 outgoing + direction = "Incoming" + else: + direction = "Outgoing" + payload = resultSet.getString("payload") + + artifact = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE) #create a call log and then add attributes from result set. + artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, general.MODULE_NAME, create_time)) + artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION, general.MODULE_NAME, direction)) + artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT, general.MODULE_NAME, TangoMessageAnalyzer.decodeMessage(conv_id, payload))) + artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE, general.MODULE_NAME, "Tango Message")) + + try: + # index the artifact for keyword search + blackboard = Case.getCurrentCase().getServices().getBlackboard() + blackboard.indexArtifact(artifact) + except Blackboard.BlackboardException as ex: + self._logger.log(Level.SEVERE, "Unable to index blackboard artifact " + artifact.getArtifactID(), ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) + MessageNotifyUtil.Notify.error("Failed to index Tango message artifact for keyword search.", artifact.getDisplayName()) + + except Exception as ex: + self._logger.log(Level.SEVERE, "Error parsing Tango messages to the Blackboard", ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) + finally: + try: + if resultSet is not None: + resultSet.close() + statement.close() + connection.close() + except Exception as ex: + self._logger.log(Level.SEVERE, "Error closing database", ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) + + # take the message string which is wrapped by a certain string, and return the text enclosed. + @staticmethod + def decodeMessage(wrapper, message): + result = "" + decoded = Base64.decodeBase64(message) + try: + Z = String(decoded, "UTF-8") # NOTE CHECK THIS + result = Z.split(wrapper)[1] + except Exception as ex: + self._logger.log(Level.SEVERE, "Error decoding a Tango message", ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) + return result diff --git a/Core/release/InternalPythonModules/android/textmessage.py b/Core/release/InternalPythonModules/android/textmessage.py new file mode 100755 index 0000000000..44ce811a46 --- /dev/null +++ b/Core/release/InternalPythonModules/android/textmessage.py @@ -0,0 +1,110 @@ +from java.io import File +from java.lang import Class +from java.lang import ClassNotFoundException +from java.lang import Integer +from java.lang import Long +from java.sql import Connection +from java.sql import DriverManager +from java.sql import ResultSet +from java.sql import SQLException +from java.sql import Statement +from java.util.logging import Level +from org.sleuthkit.autopsy.casemodule import Case +from org.sleuthkit.autopsy.casemodule.services import Blackboard +from org.sleuthkit.autopsy.casemodule.services import FileManager +from org.sleuthkit.autopsy.coreutils import Logger +from org.sleuthkit.autopsy.coreutils import MessageNotifyUtil +from org.sleuthkit.autopsy.datamodel import ContentUtils +from org.sleuthkit.autopsy.ingest import IngestJobContext +from org.sleuthkit.datamodel import AbstractFile +from org.sleuthkit.datamodel import BlackboardArtifact +from org.sleuthkit.datamodel import BlackboardAttribute +from org.sleuthkit.datamodel import Content +from org.sleuthkit.datamodel import TskCoreException + +import traceback +import general + +""" +Finds database with SMS/MMS messages and adds them to blackboard. +""" +class TextMessageAnalyzer(general.AndroidComponentAnalyzer): + + def __init__(self): + self._logger = Logger.getLogger("TextMessageAnalyzer") + + def analyze(self, dataSource, fileManager, context): + try: + absFiles = fileManager.findFiles(dataSource, "mmssms.db") + for abstractFile in absFiles: + try: + jFile = File(Case.getCurrentCase().getTempDirectory(), abstractFile.getName()) + ContentUtils.writeToFile(abstractFile, jFile, context.dataSourceIngestIsCancelled) + self.findTextsInDB(jFile.toString(), abstractFile) + except Exception as ex: + self._logger.log(Level.SEVERE, "Error parsing text messages", ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) + except TskCoreException as ex: + self._logger.log(Level.SEVERE, "Error finding text messages", ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) + + def findTextsInDB(self, databasePath, abstractFile): + connection = None + resultSet = None + statement = None + + if not databasePath: + return + + try: + Class.forName("org.sqlite.JDBC") # load JDBC driver + connection = DriverManager.getConnection("jdbc:sqlite:" + databasePath) + statement = connection.createStatement() + except (ClassNotFoundException, SQLException) as ex: + self._logger.log(Level.SEVERE, "Error opening database", ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) + return + + try: + resultSet = statement.executeQuery( + "SELECT address, date, read, type, subject, body FROM sms;") + while resultSet.next(): + address = resultSet.getString("address") # may be phone number, or other addresses + date = Long.valueOf(resultSet.getString("date")) / 1000 + read = resultSet.getInt("read") # may be unread = 0, read = 1 + subject = resultSet.getString("subject") # message subject + body = resultSet.getString("body") # message body + artifact = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE); #create Message artifact and then add attributes from result set. + if resultSet.getString("type") == "1": + artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION, general.MODULE_NAME, "Incoming")) + artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM, general.MODULE_NAME, address)) + else: + artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION, general.MODULE_NAME, "Outgoing")) + artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO, general.MODULE_NAME, address)) + artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, general.MODULE_NAME, date)) + artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_READ_STATUS, general.MODULE_NAME, Integer(read))) + artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SUBJECT, general.MODULE_NAME, subject)) + artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT, general.MODULE_NAME, body)) + artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE, general.MODULE_NAME, "SMS Message")) + + try: + # index the artifact for keyword search + blackboard = Case.getCurrentCase().getServices().getBlackboard() + blackboard.indexArtifact(artifact) + except Blackboard.BlackboardException as ex: + self._logger.log(Level.SEVERE, "Unable to index blackboard artifact " + artifact.getArtifactID(), ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) + MessageNotifyUtil.Notify.error("Failed to index text message artifact for keyword search.", artifact.getDisplayName()) + + except Exception as ex: + self._logger.log(Level.SEVERE, "Error parsing text messages to Blackboard", ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) + finally: + try: + if resultSet is not None: + resultSet.close() + statement.close() + connection.close() + except Exception as ex: + self._logger.log(Level.SEVERE, "Error closing database", ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) diff --git a/Core/release/InternalPythonModules/android/wwfmessage.py b/Core/release/InternalPythonModules/android/wwfmessage.py new file mode 100755 index 0000000000..c096a74b52 --- /dev/null +++ b/Core/release/InternalPythonModules/android/wwfmessage.py @@ -0,0 +1,103 @@ +from java.io import File +from java.lang import Class +from java.lang import ClassNotFoundException +from java.sql import Connection +from java.sql import DriverManager +from java.sql import ResultSet +from java.sql import SQLException +from java.sql import Statement +from java.util.logging import Level +from org.sleuthkit.autopsy.casemodule import Case +from org.sleuthkit.autopsy.casemodule.services import Blackboard +from org.sleuthkit.autopsy.casemodule.services import FileManager +from org.sleuthkit.autopsy.coreutils import Logger +from org.sleuthkit.autopsy.coreutils import MessageNotifyUtil +from org.sleuthkit.autopsy.datamodel import ContentUtils +from org.sleuthkit.autopsy.ingest import IngestJobContext +from org.sleuthkit.datamodel import AbstractFile +from org.sleuthkit.datamodel import BlackboardArtifact +from org.sleuthkit.datamodel import BlackboardAttribute +from org.sleuthkit.datamodel import Content +from org.sleuthkit.datamodel import TskCoreException + +import traceback +import general + +""" +Analyzes messages from Words With Friends +""" +class WWFMessageAnalyzer(general.AndroidComponentAnalyzer): + + def __init__(self): + self._logger = Logger.getLogger("WWFMessageAnalyzer") + + def analyze(self, dataSource, fileManager, context): + try: + absFiles = fileManager.findFiles(dataSource, "WordsFramework") + for abstractFile in absFiles: + try: + jFile = File(Case.getCurrentCase().getTempDirectory(), abstractFile.getName()) + ContentUtils.writeToFile(abstractFile, jFile, context.dataSourceIngestIsCancelled) + self.findWWFMessagesInDB(jFile.toString(), abstractFile) + except Exception as ex: + self._logger.log(Level.SEVERE, "Error parsing WWF messages", ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) + except TskCoreException as ex: + self._logger.log(Level.SEVERE, "Error finding WWF messages", ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) + + def findWWFMessagesInDB(self, databasePath, abstractFile): + connection = None + resultSet = None + statement = None + + if not databasePath: + return + + try: + Class.forName("org.sqlite.JDBC"); # load JDBC driver + connection = DriverManager.getConnection("jdbc:sqlite:" + databasePath) + statement = connection.createStatement() + except (ClassNotFoundException, SQLException) as ex: + self._logger.log(Level.SEVERE, "Error opening database", ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) + return + + try: + resultSet = statement.executeQuery( + "SELECT message, strftime('%s' ,created_at) as datetime, user_id, game_id FROM chat_messages ORDER BY game_id DESC, created_at DESC;") + + while resultSet.next(): + message = resultSet.getString("message") # WWF Message + created_at = resultSet.getLong("datetime") + user_id = resultSet.getString("user_id") # the ID of the user who sent the message. + game_id = resultSet.getString("game_id") # ID of the game which the the message was sent. + + artifact = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE) # create a call log and then add attributes from result set. + artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, general.MODULE_NAME, created_at)) + artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME, general.MODULE_NAME, user_id)) + artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MSG_ID, general.MODULE_NAME, game_id)) + artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT, general.MODULE_NAME, message)) + artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE, general.MODULE_NAME, "Words With Friends Message")) + + try: + # index the artifact for keyword search + blackboard = Case.getCurrentCase().getServices().getBlackboard() + blackboard.indexArtifact(artifact) + except Blackboard.BlackboardException as ex: + self._logger.log(Level.SEVERE, "Unable to index blackboard artifact " + artifact.getArtifactID(), ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) + MessageNotifyUtil.Notify.error("Failed to index WWF message artifact for keyword search.", artifact.getDisplayName()) + + except Exception as ex: + self._logger.log(Level.SEVERE, "Error parsing WWF messages to the Blackboard", ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) + finally: + try: + if resultSet is not None: + resultSet.close() + statement.close() + connection.close() + except Exception as ex: + self._logger.log(Level.SEVERE, "Error closing database", ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) From a885f2924e34f6ee2409de606c191f5424f85548 Mon Sep 17 00:00:00 2001 From: Sophie Mori Date: Tue, 13 Dec 2016 10:25:02 -0500 Subject: [PATCH 03/37] Rename google map location module --- .../android/{googlemap.py => googlemaplocation.py} | 0 Core/release/InternalPythonModules/android/module.py | 4 +--- 2 files changed, 1 insertion(+), 3 deletions(-) rename Core/release/InternalPythonModules/android/{googlemap.py => googlemaplocation.py} (100%) diff --git a/Core/release/InternalPythonModules/android/googlemap.py b/Core/release/InternalPythonModules/android/googlemaplocation.py similarity index 100% rename from Core/release/InternalPythonModules/android/googlemap.py rename to Core/release/InternalPythonModules/android/googlemaplocation.py diff --git a/Core/release/InternalPythonModules/android/module.py b/Core/release/InternalPythonModules/android/module.py index 83ea9002c5..bff6c8d05e 100755 --- a/Core/release/InternalPythonModules/android/module.py +++ b/Core/release/InternalPythonModules/android/module.py @@ -3,8 +3,6 @@ import inspect import traceback from java.util.logging import Level -from org.openide.util.lookup import ServiceProvider -from org.openide.util import NbBundle from org.sleuthkit.autopsy.coreutils import Version from org.sleuthkit.autopsy.ingest import IngestModuleFactory from org.sleuthkit.autopsy.ingest import DataSourceIngestModule @@ -25,7 +23,7 @@ import browserlocation import cachelocation import calllog import contact -import googlemap +import googlemaplocation import tangomessage import textmessage import wwfmessage From 91cc9b278212cb425aa86cb3016982f86b745f6c Mon Sep 17 00:00:00 2001 From: Sophie Mori Date: Tue, 13 Dec 2016 10:25:46 -0500 Subject: [PATCH 04/37] Remove Java implementions of Android module --- .../modules/android/AndroidIngestModule.java | 148 -------------- .../modules/android/AndroidModuleFactory.java | 61 ------ .../android/BrowserLocationAnalyzer.java | 135 ------------- .../autopsy/modules/android/Bundle.properties | 11 -- .../modules/android/Bundle_ja.properties | 10 - .../android/CacheLocationAnalyzer.java | 163 ---------------- .../modules/android/CallLogAnalyzer.java | 166 ---------------- .../modules/android/ContactAnalyzer.java | 181 ------------------ .../android/GoogleMapLocationAnalyzer.java | 170 ---------------- .../modules/android/TangoMessageAnalyzer.java | 154 --------------- .../modules/android/TextMessageAnalyzer.java | 153 --------------- .../modules/android/WWFMessageAnalyzer.java | 140 -------------- 12 files changed, 1492 deletions(-) delete mode 100755 Core/src/org/sleuthkit/autopsy/modules/android/AndroidIngestModule.java delete mode 100755 Core/src/org/sleuthkit/autopsy/modules/android/AndroidModuleFactory.java delete mode 100755 Core/src/org/sleuthkit/autopsy/modules/android/BrowserLocationAnalyzer.java delete mode 100755 Core/src/org/sleuthkit/autopsy/modules/android/Bundle.properties delete mode 100644 Core/src/org/sleuthkit/autopsy/modules/android/Bundle_ja.properties delete mode 100755 Core/src/org/sleuthkit/autopsy/modules/android/CacheLocationAnalyzer.java delete mode 100755 Core/src/org/sleuthkit/autopsy/modules/android/CallLogAnalyzer.java delete mode 100755 Core/src/org/sleuthkit/autopsy/modules/android/ContactAnalyzer.java delete mode 100755 Core/src/org/sleuthkit/autopsy/modules/android/GoogleMapLocationAnalyzer.java delete mode 100755 Core/src/org/sleuthkit/autopsy/modules/android/TangoMessageAnalyzer.java delete mode 100755 Core/src/org/sleuthkit/autopsy/modules/android/TextMessageAnalyzer.java delete mode 100755 Core/src/org/sleuthkit/autopsy/modules/android/WWFMessageAnalyzer.java diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/AndroidIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/android/AndroidIngestModule.java deleted file mode 100755 index 8dea2a95a2..0000000000 --- a/Core/src/org/sleuthkit/autopsy/modules/android/AndroidIngestModule.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2011-2016 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.modules.android; - -import java.util.ArrayList; - -import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.casemodule.services.FileManager; -import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProgress; -import org.sleuthkit.autopsy.ingest.IngestModule; -import org.sleuthkit.datamodel.Content; -import org.sleuthkit.autopsy.ingest.DataSourceIngestModule; -import org.sleuthkit.autopsy.ingest.IngestJobContext; -import org.sleuthkit.autopsy.ingest.IngestMessage; - -class AndroidIngestModule implements DataSourceIngestModule { - - private IngestJobContext context = null; - - @Override - public void startUp(IngestJobContext context) throws IngestModuleException { - this.context = context; - } - - @Override - public ProcessResult process(Content dataSource, DataSourceIngestModuleProgress progressBar) { - ArrayList errors = new ArrayList<>(); - progressBar.switchToDeterminate(9); - FileManager fileManager = Case.getCurrentCase().getServices().getFileManager(); - - try { - ContactAnalyzer.findContacts(dataSource, fileManager, context); - progressBar.progress(1); - if (context.dataSourceIngestIsCancelled()) { - return IngestModule.ProcessResult.OK; - } - } catch (Exception e) { - errors.add("Error getting Contacts"); //NON-NLS - } - - try { - CallLogAnalyzer.findCallLogs(dataSource, fileManager, context); - progressBar.progress(2); - if (context.dataSourceIngestIsCancelled()) { - return IngestModule.ProcessResult.OK; - } - } catch (Exception e) { - errors.add("Error getting Call Logs"); //NON-NLS - } - - try { - TextMessageAnalyzer.findTexts(dataSource, fileManager, context); - progressBar.progress(3); - if (context.dataSourceIngestIsCancelled()) { - return IngestModule.ProcessResult.OK; - } - } catch (Exception e) { - errors.add("Error getting Text Messages"); //NON-NLS - } - - try { - TangoMessageAnalyzer.findTangoMessages(dataSource, fileManager, context); - progressBar.progress(4); - if (context.dataSourceIngestIsCancelled()) { - return IngestModule.ProcessResult.OK; - } - } catch (Exception e) { - errors.add("Error getting Tango Messages"); //NON-NLS - } - - try { - WWFMessageAnalyzer.findWWFMessages(dataSource, fileManager, context); - progressBar.progress(5); - if (context.dataSourceIngestIsCancelled()) { - return IngestModule.ProcessResult.OK; - } - } catch (Exception e) { - errors.add("Error getting Words with Friends Messages"); //NON-NLS - } - - try { - GoogleMapLocationAnalyzer.findGeoLocations(dataSource, fileManager, context); - progressBar.progress(6); - if (context.dataSourceIngestIsCancelled()) { - return IngestModule.ProcessResult.OK; - } - } catch (Exception e) { - errors.add("Error getting Google Map Locations"); //NON-NLS - } - - try { - BrowserLocationAnalyzer.findGeoLocations(dataSource, fileManager, context); - progressBar.progress(7); - if (context.dataSourceIngestIsCancelled()) { - return IngestModule.ProcessResult.OK; - } - } catch (Exception e) { - errors.add("Error getting Browser Locations"); //NON-NLS - } - - try { - CacheLocationAnalyzer.findGeoLocations(dataSource, fileManager, context); - progressBar.progress(8); - } catch (Exception e) { - errors.add("Error getting Cache Locations"); //NON-NLS - } - - // create the final message for inbox - StringBuilder errorMessage = new StringBuilder(); - String errorMsgSubject; - IngestMessage.MessageType msgLevel = IngestMessage.MessageType.INFO; - if (errors.isEmpty() == false) { - msgLevel = IngestMessage.MessageType.ERROR; - errorMessage.append("Errors were encountered"); //NON-NLS - for (String msg : errors) { - errorMessage.append("
  • ").append(msg).append("
  • \n"); //NON-NLS - } - errorMessage.append("\n"); //NON-NLS - - if (errors.size() == 1) { - errorMsgSubject = "One error was found"; //NON-NLS - } else { - errorMsgSubject = "errors found: " + errors.size(); //NON-NLS - } - } else { - errorMessage.append("No errors"); //NON-NLS - errorMsgSubject = "No errors"; //NON-NLS - } - - return IngestModule.ProcessResult.OK; - } -} diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/AndroidModuleFactory.java b/Core/src/org/sleuthkit/autopsy/modules/android/AndroidModuleFactory.java deleted file mode 100755 index c30e7c3c64..0000000000 --- a/Core/src/org/sleuthkit/autopsy/modules/android/AndroidModuleFactory.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2014 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.modules.android; - -import org.openide.util.lookup.ServiceProvider; -import org.openide.util.NbBundle; -import org.sleuthkit.autopsy.coreutils.Version; -import org.sleuthkit.autopsy.ingest.IngestModuleFactory; -import org.sleuthkit.autopsy.ingest.DataSourceIngestModule; -import org.sleuthkit.autopsy.ingest.IngestModuleFactoryAdapter; -import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; - -@ServiceProvider(service = IngestModuleFactory.class) // -public class AndroidModuleFactory extends IngestModuleFactoryAdapter { - - static String getModuleName() { - return NbBundle.getMessage(AndroidModuleFactory.class, "AndroidModuleFactory.moduleName"); - } - - @Override - public String getModuleDisplayName() { - return getModuleName(); - } - - @Override - public String getModuleDescription() { - return NbBundle.getMessage(AndroidModuleFactory.class, "AndroidModuleFactory.moduleDescription"); - } - - @Override - public String getModuleVersionNumber() { - return Version.getVersion(); - } - - @Override - public boolean isDataSourceIngestModuleFactory() { - return true; - } - - @Override - public DataSourceIngestModule createDataSourceIngestModule(IngestModuleIngestJobSettings settings) { - return new AndroidIngestModule(); - } - -} diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/BrowserLocationAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/android/BrowserLocationAnalyzer.java deleted file mode 100755 index 38592e432d..0000000000 --- a/Core/src/org/sleuthkit/autopsy/modules/android/BrowserLocationAnalyzer.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2014 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.modules.android; - -import java.io.File; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.List; -import java.util.logging.Level; -import org.openide.util.NbBundle; -import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.casemodule.services.Blackboard; -import org.sleuthkit.autopsy.casemodule.services.FileManager; -import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; -import org.sleuthkit.autopsy.datamodel.ContentUtils; -import org.sleuthkit.autopsy.ingest.IngestJobContext; -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; - -/** - * Analyzes database created by browser that stores GEO location info. - */ -class BrowserLocationAnalyzer { - - private static final String moduleName = AndroidModuleFactory.getModuleName(); - private static final Logger logger = Logger.getLogger(BrowserLocationAnalyzer.class.getName()); - private static Blackboard blackboard; - - public static void findGeoLocations(Content dataSource, FileManager fileManager, - IngestJobContext context) { - blackboard = Case.getCurrentCase().getServices().getBlackboard(); - try { - List abstractFiles = fileManager.findFiles(dataSource, "CachedGeoposition%.db"); //NON-NLS - - for (AbstractFile abstractFile : abstractFiles) { - try { - if (abstractFile.getSize() == 0) { - continue; - } - File jFile = new File(Case.getCurrentCase().getTempDirectory(), abstractFile.getName()); - ContentUtils.writeToFile(abstractFile, jFile, context::dataSourceIngestIsCancelled); - findGeoLocationsInDB(jFile.toString(), abstractFile); - } catch (Exception e) { - logger.log(Level.SEVERE, "Error parsing Browser Location files", e); //NON-NLS - } - } - } catch (TskCoreException e) { - logger.log(Level.SEVERE, "Error finding Browser Location files", e); //NON-NLS - - } - } - - @NbBundle.Messages({"BrowserLocationAnalyzer.indexError.message=Failed to index GPS trackpoint artifact for keyword search."}) - private static void findGeoLocationsInDB(String DatabasePath, AbstractFile f) { - Connection connection = null; - ResultSet resultSet = null; - Statement statement = null; - if (DatabasePath == null || DatabasePath.isEmpty()) { - return; - } - try { - Class.forName("org.sqlite.JDBC"); //NON-NLS //load JDBC driver - connection = DriverManager.getConnection("jdbc:sqlite:" + DatabasePath); //NON-NLS - statement = connection.createStatement(); - } catch (ClassNotFoundException | SQLException e) { - logger.log(Level.SEVERE, "Error connecting to sql database", e); //NON-NLS - return; - } - - try { - resultSet = statement.executeQuery( - "SELECT timestamp, latitude, longitude, accuracy FROM CachedPosition;"); //NON-NLS - - while (resultSet.next()) { - Long timestamp = Long.valueOf(resultSet.getString("timestamp")) / 1000; //NON-NLS - double latitude = Double.valueOf(resultSet.getString("latitude")); //NON-NLS - double longitude = Double.valueOf(resultSet.getString("longitude")); //NON-NLS - - BlackboardArtifact bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE, moduleName, latitude)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE, moduleName, longitude)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, moduleName, timestamp)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME, moduleName, - NbBundle.getMessage(BrowserLocationAnalyzer.class, - "BrowserLocationAnalyzer.bbAttribute.browserLocationHistory"))); - // bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_VALUE.getTypeID(),moduleName, accuracy)); - - try { - // index the artifact for keyword search - blackboard.indexArtifact(bba); - } catch (Blackboard.BlackboardException ex) { - logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bba.getArtifactTypeName(), ex); //NON-NLS - MessageNotifyUtil.Notify.error( - Bundle.BrowserLocationAnalyzer_indexError_message(), bba.getDisplayName()); - } - } - } catch (Exception e) { - logger.log(Level.SEVERE, "Error Putting artifacts to Blackboard", e); //NON-NLS - } finally { - try { - if (resultSet != null) { - resultSet.close(); - } - statement.close(); - connection.close(); - } catch (Exception e) { - logger.log(Level.SEVERE, "Error closing database", e); //NON-NLS - } - } - - } -} diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/Bundle.properties b/Core/src/org/sleuthkit/autopsy/modules/android/Bundle.properties deleted file mode 100755 index 9ef8ab1338..0000000000 --- a/Core/src/org/sleuthkit/autopsy/modules/android/Bundle.properties +++ /dev/null @@ -1,11 +0,0 @@ -AndroidModuleFactory.moduleName=Android Analyzer -AndroidModuleFactory.moduleDescription=Extracts Android system and third-party app data. -BrowserLocationAnalyzer.bbAttribute.browserLocationHistory=Browser Location History -CacheLocationAnalyzer.bbAttribute.fileLocationHistory={0} Location History -GoogleMapLocationAnalyzer.bbAttribute.destination=Destination -GoogleMapLocationAnalyzer.bbAttribute.googleMapsHistory=Google Maps History -TangoMessageAnalyzer.bbAttribute.tangoMessage=Tango Message -TextMessageAnalyzer.bbAttribute.incoming=Incoming -TextMessageAnalyzer.bbAttribute.outgoing=Outgoing -TextMessageAnalyzer.bbAttribute.smsMessage=SMS Message -WWFMessageAnalyzer.bbAttribute.wordsWithFriendsMsg=Words With Friends Message diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/modules/android/Bundle_ja.properties deleted file mode 100644 index e555ddc54c..0000000000 --- a/Core/src/org/sleuthkit/autopsy/modules/android/Bundle_ja.properties +++ /dev/null @@ -1,10 +0,0 @@ -AndroidModuleFactory.moduleDescription=Android\u30b7\u30b9\u30c6\u30e0\u304a\u3088\u3073\u7b2c\u4e09\u8005\u30a2\u30d7\u30ea\u30c7\u30fc\u30bf\u3092\u62bd\u51fa -BrowserLocationAnalyzer.bbAttribute.browserLocationHistory=\u30d6\u30e9\u30a6\u30b6\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3\u5c65\u6b74 -CacheLocationAnalyzer.bbAttribute.fileLocationHistory={0} \u30ed\u30b1\u30fc\u30b7\u30e7\u30f3\u5c65\u6b74 -GoogleMapLocationAnalyzer.bbAttribute.destination=\u76ee\u7684\u5730 -GoogleMapLocationAnalyzer.bbAttribute.googleMapsHistory=Google\u30de\u30c3\u30d7\u5c65\u6b74 -TangoMessageAnalyzer.bbAttribute.tangoMessage=Tango\u30e1\u30c3\u30bb\u30fc\u30b8 -TextMessageAnalyzer.bbAttribute.incoming=\u53d7\u4fe1 -TextMessageAnalyzer.bbAttribute.outgoing=\u9001\u4fe1 -TextMessageAnalyzer.bbAttribute.smsMessage=SMS\u30e1\u30c3\u30bb\u30fc\u30b8 -WWFMessageAnalyzer.bbAttribute.wordsWithFriendsMsg=Words With Friends\u30e1\u30c3\u30bb\u30fc\u30b8 \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/CacheLocationAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/android/CacheLocationAnalyzer.java deleted file mode 100755 index debc4a0066..0000000000 --- a/Core/src/org/sleuthkit/autopsy/modules/android/CacheLocationAnalyzer.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2014 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.modules.android; - -import java.io.File; -import java.io.FileInputStream; -import java.io.InputStream; -import java.math.BigInteger; -import java.nio.ByteBuffer; -import java.util.List; -import java.util.logging.Level; -import org.openide.util.NbBundle; -import org.openide.util.NbBundle.Messages; -import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.casemodule.services.Blackboard; -import org.sleuthkit.autopsy.casemodule.services.FileManager; -import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; -import org.sleuthkit.autopsy.datamodel.ContentUtils; -import org.sleuthkit.autopsy.ingest.IngestJobContext; -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; - -/** - * Parses cache files that Android maintains for Wifi and cell towers. Adds GPS - * points to blackboard. - */ -class CacheLocationAnalyzer { - - private static final String moduleName = AndroidModuleFactory.getModuleName(); - private static final Logger logger = Logger.getLogger(CacheLocationAnalyzer.class.getName()); - private static Blackboard blackboard; - - /** - * cache.cell stores mobile tower GPS locations and cache.wifi stores GPS - * and MAC info from Wifi points. - */ - public static void findGeoLocations(Content dataSource, FileManager fileManager, - IngestJobContext context) { - blackboard = Case.getCurrentCase().getServices().getBlackboard(); - try { - List abstractFiles = fileManager.findFiles(dataSource, "cache.cell"); //NON-NLS - abstractFiles.addAll(fileManager.findFiles(dataSource, "cache.wifi")); //NON-NLS - - for (AbstractFile abstractFile : abstractFiles) { - try { - if (abstractFile.getSize() == 0) { - continue; - } - File jFile = new File(Case.getCurrentCase().getTempDirectory(), abstractFile.getName()); - ContentUtils.writeToFile(abstractFile, jFile, context::dataSourceIngestIsCancelled); - - findGeoLocationsInFile(jFile, abstractFile); - } catch (Exception e) { - logger.log(Level.SEVERE, "Error parsing cached Location files", e); //NON-NLS - } - } - } catch (TskCoreException e) { - logger.log(Level.SEVERE, "Error finding cached Location files", e); //NON-NLS - } - } - - @Messages({"CacheLocationAnalyzer.indexError.message=Failed to index GPS trackpoint artifact for keyword search."}) - private static void findGeoLocationsInFile(File file, AbstractFile f) { - byte[] bytes; // will temporarily hold bytes to be converted into the correct data types - - try { - InputStream inputStream = new FileInputStream(file); - - bytes = new byte[2]; // version - inputStream.read(bytes); - - bytes = new byte[2]; - inputStream.read(bytes); //number of location entries - - int iterations = new BigInteger(bytes).intValue(); - - for (int i = 0; i < iterations; i++) { //loop through every entry - bytes = new byte[2]; - inputStream.read(bytes); - - bytes = new byte[1]; - inputStream.read(bytes); - while (new BigInteger(bytes).intValue() != 0) { //pass through non important values until the start of accuracy(around 7-10 bytes) - if (0 > inputStream.read(bytes)) { - break; /// we've passed the end of the file, so stop - } - } - bytes = new byte[3]; - inputStream.read(bytes); - if (new BigInteger(bytes).intValue() <= 0) {//This refers to a location that could not be calculated. - bytes = new byte[28]; //read rest of the row's bytes - inputStream.read(bytes); - continue; - } - String accuracy = "" + new BigInteger(bytes).intValue(); - - bytes = new byte[4]; - inputStream.read(bytes); - String confidence = "" + new BigInteger(bytes).intValue(); - - bytes = new byte[8]; - inputStream.read(bytes); - double latitude = toDouble(bytes); - - bytes = new byte[8]; - inputStream.read(bytes); - double longitude = toDouble(bytes); - - bytes = new byte[8]; - inputStream.read(bytes); - Long timestamp = new BigInteger(bytes).longValue() / 1000; - - BlackboardArtifact bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE, moduleName, latitude)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE, moduleName, longitude)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, moduleName, timestamp)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME, moduleName, - NbBundle.getMessage(CacheLocationAnalyzer.class, - "CacheLocationAnalyzer.bbAttribute.fileLocationHistory", - file.getName()))); - - //Not storing these for now. - // bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_VALUE.getTypeID(),moduleName, accuracy)); - // bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT.getTypeID(),moduleName, confidence)); - try { - // index the artifact for keyword search - blackboard.indexArtifact(bba); - } catch (Blackboard.BlackboardException ex) { - logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bba.getArtifactID(), ex); //NON-NLS - MessageNotifyUtil.Notify.error( - Bundle.CacheLocationAnalyzer_indexError_message(), bba.getDisplayName()); - } - } - - } catch (Exception e) { - logger.log(Level.SEVERE, "Error parsing Cached GPS locations to Blackboard", e); //NON-NLS - } - } - - private static double toDouble(byte[] bytes) { - return ByteBuffer.wrap(bytes).getDouble(); - } -} diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/CallLogAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/android/CallLogAnalyzer.java deleted file mode 100755 index 8075d8c3fe..0000000000 --- a/Core/src/org/sleuthkit/autopsy/modules/android/CallLogAnalyzer.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2014 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.modules.android; - -import java.io.File; -import java.io.IOException; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.Arrays; -import java.util.List; -import java.util.logging.Level; -import org.openide.util.NbBundle.Messages; -import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.casemodule.services.Blackboard; -import org.sleuthkit.autopsy.casemodule.services.FileManager; -import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; -import org.sleuthkit.autopsy.datamodel.ContentUtils; -import org.sleuthkit.autopsy.ingest.IngestJobContext; -import org.sleuthkit.datamodel.AbstractFile; -import org.sleuthkit.datamodel.BlackboardArtifact; -import org.sleuthkit.datamodel.BlackboardAttribute; -import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE; -import org.sleuthkit.datamodel.Content; -import org.sleuthkit.datamodel.TskCoreException; - -/** - * Locates a variety of different call log databases, parses them, and populates - * the blackboard. - */ -class CallLogAnalyzer { - - private static final String moduleName = AndroidModuleFactory.getModuleName(); - private static final Logger logger = Logger.getLogger(CallLogAnalyzer.class.getName()); - private static Blackboard blackboard; - - /** - * the names of tables that potentially hold call logs in the dbs - */ - private static final Iterable tableNames = Arrays.asList("calls", "logs"); //NON-NLS - - public static void findCallLogs(Content dataSource, FileManager fileManager, - IngestJobContext context) { - blackboard = Case.getCurrentCase().getServices().getBlackboard(); - try { - List absFiles = fileManager.findFiles(dataSource, "logs.db"); //NON-NLS - absFiles.addAll(fileManager.findFiles(dataSource, "contacts.db")); //NON-NLS - absFiles.addAll(fileManager.findFiles(dataSource, "contacts2.db")); //NON-NLS - for (AbstractFile abstractFile : absFiles) { - try { - File file = new File(Case.getCurrentCase().getTempDirectory(), abstractFile.getName()); - ContentUtils.writeToFile(abstractFile, file, context::dataSourceIngestIsCancelled); - findCallLogsInDB(file.toString(), abstractFile); - } catch (IOException e) { - logger.log(Level.SEVERE, "Error writing temporary call log db to disk", e); //NON-NLS - } - } - } catch (TskCoreException e) { - logger.log(Level.SEVERE, "Error finding call logs", e); //NON-NLS - } - } - - @Messages({"CallLogAnalyzer.indexError.message=Failed to index call log artifact for keyword search."}) - private static void findCallLogsInDB(String DatabasePath, AbstractFile f) { - - if (DatabasePath == null || DatabasePath.isEmpty()) { - return; - } - try (Connection connection = DriverManager.getConnection("jdbc:sqlite:" + DatabasePath); //NON-NLS - Statement statement = connection.createStatement();) { - - for (String tableName : tableNames) { - try (ResultSet resultSet = statement.executeQuery( - "SELECT number,date,duration,type, name FROM " + tableName + " ORDER BY date DESC;");) { //NON-NLS - logger.log(Level.INFO, "Reading call log from table {0} in db {1}", new Object[]{tableName, DatabasePath}); //NON-NLS - while (resultSet.next()) { - Long date = resultSet.getLong("date") / 1000; - final CallDirection direction = CallDirection.fromType(resultSet.getInt("type")); //NON-NLS - String directionString = direction != null ? direction.getDisplayName() : ""; - final String number = resultSet.getString("number"); //NON-NLS - final long duration = resultSet.getLong("duration"); //NON-NLS //duration of call is in seconds - final String name = resultSet.getString("name"); //NON-NLS // name of person dialed or called. null if unregistered - - try { - BlackboardArtifact bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG); //create a call log and then add attributes from result set. - if (direction == CallDirection.OUTGOING) { - bba.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO, moduleName, number)); - } else { /// Covers INCOMING and MISSED - bba.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM, moduleName, number)); - } - bba.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_START, moduleName, date)); - bba.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_END, moduleName, duration + date)); - bba.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DIRECTION, moduleName, directionString)); - bba.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, moduleName, name)); - - try { - // index the artifact for keyword search - blackboard.indexArtifact(bba); - } catch (Blackboard.BlackboardException ex) { - logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bba.getArtifactID(), ex); //NON-NLS - MessageNotifyUtil.Notify.error( - Bundle.CallLogAnalyzer_indexError_message(), bba.getDisplayName()); - } - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Error posting call log record to the Blackboard", ex); //NON-NLS - } - } - } catch (SQLException e) { - logger.log(Level.WARNING, String.format("Could not read table %s in db %s", tableName, DatabasePath), e); //NON-NLS - } - } - } catch (SQLException e) { - logger.log(Level.SEVERE, "Could not parse call log; error connecting to db " + DatabasePath, e); //NON-NLS - } - } - - private static enum CallDirection { - - INCOMING(1, "Incoming"), OUTGOING(2, "Outgoing"), MISSED(3, "Missed"); //NON-NLS - - private final int type; - - private final String displayName; - - public String getDisplayName() { - return displayName; - } - - private CallDirection(int type, String displayName) { - this.type = type; - this.displayName = displayName; - } - - static CallDirection fromType(int t) { - switch (t) { - case 1: - return INCOMING; - case 2: - return OUTGOING; - case 3: - return MISSED; - default: - return null; - } - } - } -} diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/ContactAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/android/ContactAnalyzer.java deleted file mode 100755 index 58384f3235..0000000000 --- a/Core/src/org/sleuthkit/autopsy/modules/android/ContactAnalyzer.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2014 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.modules.android; - -import java.io.File; -import java.sql.Connection; -import java.sql.DatabaseMetaData; -import java.sql.DriverManager; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.List; -import java.util.logging.Level; -import org.openide.util.NbBundle.Messages; -import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.casemodule.services.Blackboard; -import org.sleuthkit.autopsy.casemodule.services.FileManager; -import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; -import org.sleuthkit.autopsy.datamodel.ContentUtils; -import org.sleuthkit.autopsy.ingest.IngestJobContext; -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; - -/** - * Locates a variety of different contacts databases, parses them, and populates - * the blackboard. - */ -class ContactAnalyzer { - - private static final String moduleName = AndroidModuleFactory.getModuleName(); - private static final Logger logger = Logger.getLogger(ContactAnalyzer.class.getName()); - - public static void findContacts(Content dataSource, FileManager fileManager, - IngestJobContext context) { - List absFiles; - try { - absFiles = fileManager.findFiles(dataSource, "contacts.db"); //NON-NLS - absFiles.addAll(fileManager.findFiles(dataSource, "contacts2.db")); //NON-NLS - if (absFiles.isEmpty()) { - return; - } - for (AbstractFile AF : absFiles) { - try { - File jFile = new File(Case.getCurrentCase().getTempDirectory(), AF.getName()); - ContentUtils.writeToFile(AF, jFile, context::dataSourceIngestIsCancelled); - findContactsInDB(jFile.toString(), AF); - } catch (Exception e) { - logger.log(Level.SEVERE, "Error parsing Contacts", e); //NON-NLS - } - } - } catch (TskCoreException e) { - logger.log(Level.SEVERE, "Error finding Contacts", e); //NON-NLS - } - } - - /** - * - * @param databasePath - * @param fId Will create artifact from a database given by the - * path The fileId will be the Abstract file associated - * with the artifacts - */ - @Messages({"ContactAnalyzer.indexError.message=Failed to index contact artifact for keyword search."}) - private static void findContactsInDB(String databasePath, AbstractFile f) { - Connection connection = null; - ResultSet resultSet = null; - Statement statement = null; - Blackboard blackboard = Case.getCurrentCase().getServices().getBlackboard(); - - if (databasePath == null || databasePath.isEmpty()) { - return; - } - try { - Class.forName("org.sqlite.JDBC"); //NON-NLS //load JDBC driver - connection = DriverManager.getConnection("jdbc:sqlite:" + databasePath); //NON-NLS - statement = connection.createStatement(); - } catch (ClassNotFoundException | SQLException e) { - logger.log(Level.SEVERE, "Error opening database", e); //NON-NLS - return; - } - - try { - // get display_name, mimetype(email or phone number) and data1 (phonenumber or email address depending on mimetype) - //sorted by name, so phonenumber/email would be consecutive for a person if they exist. - // check if contacts.name_raw_contact_id exists. Modify the query accordingly. - Boolean column_found = false; - DatabaseMetaData metadata = connection.getMetaData(); - ResultSet columnListResultSet = metadata.getColumns(null, null, "contacts", null); //NON-NLS - while (columnListResultSet.next()) { - if (columnListResultSet.getString("COLUMN_NAME").equals("name_raw_contact_id")) { //NON-NLS - column_found = true; - break; - } - } - if (column_found) { - resultSet = statement.executeQuery( - "SELECT mimetype,data1, name_raw_contact.display_name AS display_name \n" //NON-NLS - + "FROM raw_contacts JOIN contacts ON (raw_contacts.contact_id=contacts._id) \n" //NON-NLS - + "JOIN raw_contacts AS name_raw_contact ON(name_raw_contact_id=name_raw_contact._id) " //NON-NLS - + "LEFT OUTER JOIN data ON (data.raw_contact_id=raw_contacts._id) \n" //NON-NLS - + "LEFT OUTER JOIN mimetypes ON (data.mimetype_id=mimetypes._id) \n" //NON-NLS - + "WHERE mimetype = 'vnd.android.cursor.item/phone_v2' OR mimetype = 'vnd.android.cursor.item/email_v2'\n" //NON-NLS - + "ORDER BY name_raw_contact.display_name ASC;"); //NON-NLS - } else { - resultSet = statement.executeQuery( - "SELECT mimetype,data1, raw_contacts.display_name AS display_name \n" //NON-NLS - + "FROM raw_contacts JOIN contacts ON (raw_contacts.contact_id=contacts._id) \n" //NON-NLS - + "LEFT OUTER JOIN data ON (data.raw_contact_id=raw_contacts._id) \n" //NON-NLS - + "LEFT OUTER JOIN mimetypes ON (data.mimetype_id=mimetypes._id) \n" //NON-NLS - + "WHERE mimetype = 'vnd.android.cursor.item/phone_v2' OR mimetype = 'vnd.android.cursor.item/email_v2'\n" //NON-NLS - + "ORDER BY raw_contacts.display_name ASC;"); //NON-NLS - } - - BlackboardArtifact bba; - bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT); - String name; - String oldName = ""; - String mimetype; // either phone or email - String data1; // the phone number or email - while (resultSet.next()) { - name = resultSet.getString("display_name"); //NON-NLS - data1 = resultSet.getString("data1"); //NON-NLS - mimetype = resultSet.getString("mimetype"); //NON-NLS - if (name.equals(oldName) == false) { - bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME, moduleName, name)); - } - if (mimetype.equals("vnd.android.cursor.item/phone_v2")) { //NON-NLS - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER, moduleName, data1)); - } else { - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL, moduleName, data1)); - } - oldName = name; - - try { - // index the artifact for keyword search - blackboard.indexArtifact(bba); - } catch (Blackboard.BlackboardException ex) { - logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bba.getArtifactID(), ex); //NON-NLS - MessageNotifyUtil.Notify.error( - Bundle.ContactAnalyzer_indexError_message(), bba.getDisplayName()); - } - } - - } catch (SQLException e) { - logger.log(Level.WARNING, "Unable to execute contacts SQL query against {0} : {1}", new Object[]{databasePath, e}); //NON-NLS - } catch (TskCoreException e) { - logger.log(Level.SEVERE, "Error posting to blackboard", e); //NON-NLS - } finally { - try { - if (resultSet != null) { - resultSet.close(); - } - statement.close(); - connection.close(); - } catch (Exception e) { - logger.log(Level.SEVERE, "Error closing database", e); //NON-NLS - } - } - } -} diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/GoogleMapLocationAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/android/GoogleMapLocationAnalyzer.java deleted file mode 100755 index f39e8620d9..0000000000 --- a/Core/src/org/sleuthkit/autopsy/modules/android/GoogleMapLocationAnalyzer.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2014 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.modules.android; - -import java.io.File; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.List; -import java.util.logging.Level; -import org.openide.util.NbBundle; -import org.openide.util.NbBundle.Messages; -import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.casemodule.services.Blackboard; -import org.sleuthkit.autopsy.casemodule.services.FileManager; -import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; -import org.sleuthkit.autopsy.datamodel.ContentUtils; -import org.sleuthkit.autopsy.ingest.IngestJobContext; -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; - -/** - * Finds and parses the Google Maps database. - */ -class GoogleMapLocationAnalyzer { - - private static final String moduleName = AndroidModuleFactory.getModuleName(); - private static final Logger logger = Logger.getLogger(GoogleMapLocationAnalyzer.class.getName()); - private static Blackboard blackboard; - - public static void findGeoLocations(Content dataSource, FileManager fileManager, - IngestJobContext context) { - List absFiles; - blackboard = Case.getCurrentCase().getServices().getBlackboard(); - try { - absFiles = fileManager.findFiles(dataSource, "da_destination_history"); //NON-NLS - if (absFiles.isEmpty()) { - return; - } - for (AbstractFile abstractFile : absFiles) { - try { - File jFile = new java.io.File(Case.getCurrentCase().getTempDirectory(), abstractFile.getName()); - ContentUtils.writeToFile(abstractFile, jFile, context::dataSourceIngestIsCancelled); - findGeoLocationsInDB(jFile.toString(), abstractFile); - } catch (Exception e) { - logger.log(Level.SEVERE, "Error parsing Google map locations", e); //NON-NLS - } - } - } catch (TskCoreException e) { - logger.log(Level.SEVERE, "Error finding Google map locations", e); //NON-NLS - } - } - - @Messages({"GoogleMapLocationAnalyzer.indexError.message=Failed to index GPS route artifact for keyword search."}) - private static void findGeoLocationsInDB(String DatabasePath, AbstractFile f) { - Connection connection = null; - ResultSet resultSet = null; - Statement statement = null; - - if (DatabasePath == null || DatabasePath.isEmpty()) { - return; - } - try { - Class.forName("org.sqlite.JDBC"); //NON-NLS //load JDBC driver - connection = DriverManager.getConnection("jdbc:sqlite:" + DatabasePath); //NON-NLS - statement = connection.createStatement(); - } catch (ClassNotFoundException | SQLException e) { - logger.log(Level.SEVERE, "Error opening database", e); //NON-NLS - return; - } - - try { - resultSet = statement.executeQuery( - "SELECT time,dest_lat,dest_lng,dest_title,dest_address,source_lat,source_lng FROM destination_history;"); //NON-NLS - - while (resultSet.next()) { - Long time = Long.valueOf(resultSet.getString("time")) / 1000; //NON-NLS - String dest_title = resultSet.getString("dest_title"); //NON-NLS - String dest_address = resultSet.getString("dest_address"); //NON-NLS - - double dest_lat = convertGeo(resultSet.getString("dest_lat")); //NON-NLS - double dest_lng = convertGeo(resultSet.getString("dest_lng")); //NON-NLS - double source_lat = convertGeo(resultSet.getString("source_lat")); //NON-NLS - double source_lng = convertGeo(resultSet.getString("source_lng")); //NON-NLS - -// bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT);//src -// bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CATEGORY.getTypeID(), moduleName, "Source")); -// bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID(), moduleName, source_lat)); -// bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE.getTypeID(), moduleName, source_lng)); -// bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(), moduleName, time)); -// bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DESCRIPTION.getTypeID(), moduleName, "Google Maps History")); -// -// bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT);//dest -// bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CATEGORY.getTypeID(), moduleName, "Destination")); -// bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(), moduleName, time)); -// bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID(), moduleName, dest_lat)); -// bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE.getTypeID(), moduleName, dest_lng)); -// bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), moduleName, dest_title)); -// bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_LOCATION.getTypeID(), moduleName, dest_address)); -// bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(), moduleName, "Google Maps History")); - BlackboardArtifact bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_ROUTE); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CATEGORY, moduleName, - NbBundle.getMessage(GoogleMapLocationAnalyzer.class, - "GoogleMapLocationAnalyzer.bbAttribute.destination"))); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, moduleName, time)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_END, moduleName, dest_lat)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_END, moduleName, dest_lng)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_START, moduleName, source_lat)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_START, moduleName, source_lng)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME, moduleName, dest_title)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_LOCATION, moduleName, dest_address)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME, moduleName, - NbBundle.getMessage(GoogleMapLocationAnalyzer.class, - "GoogleMapLocationAnalyzer.bbAttribute.googleMapsHistory"))); - - try { - // index the artifact for keyword search - blackboard.indexArtifact(bba); - } catch (Blackboard.BlackboardException ex) { - logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bba.getArtifactID(), ex); //NON-NLS - MessageNotifyUtil.Notify.error( - Bundle.GoogleMapLocationAnalyzer_indexError_message(), bba.getDisplayName()); - } - } - } catch (Exception e) { - logger.log(Level.SEVERE, "Error parsing Google map locations to the Blackboard", e); //NON-NLS - } finally { - try { - if (resultSet != null) { - resultSet.close(); - } - statement.close(); - connection.close(); - } catch (Exception e) { - logger.log(Level.SEVERE, "Error closing the database", e); //NON-NLS - } - } - } - - //add periods 6 decimal places before the end. - private static double convertGeo(String s) { - if (s.length() > 6) { - return Double.valueOf(s.substring(0, s.length() - 6) + "." + s.substring(s.length() - 6, s.length())); - } else { - return Double.valueOf(s); - } - } -} diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/TangoMessageAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/android/TangoMessageAnalyzer.java deleted file mode 100755 index 8da1c167ef..0000000000 --- a/Core/src/org/sleuthkit/autopsy/modules/android/TangoMessageAnalyzer.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2014 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.modules.android; - -import java.io.File; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.List; -import java.util.logging.Level; -import org.apache.commons.codec.binary.Base64; -import org.openide.util.NbBundle; -import org.openide.util.NbBundle.Messages; -import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.casemodule.services.Blackboard; -import org.sleuthkit.autopsy.casemodule.services.FileManager; -import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; -import org.sleuthkit.autopsy.datamodel.ContentUtils; -import org.sleuthkit.autopsy.ingest.IngestJobContext; -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; - -/** - * Locates database for the Tango app and adds info to blackboard. - */ -class TangoMessageAnalyzer { - - private static final String moduleName = AndroidModuleFactory.getModuleName(); - private static final Logger logger = Logger.getLogger(TangoMessageAnalyzer.class.getName()); - private static Blackboard blackboard; - - public static void findTangoMessages(Content dataSource, FileManager fileManager, - IngestJobContext context) { - blackboard = Case.getCurrentCase().getServices().getBlackboard(); - List absFiles; - try { - absFiles = fileManager.findFiles(dataSource, "tc.db"); //NON-NLS - for (AbstractFile abstractFile : absFiles) { - try { - File jFile = new File(Case.getCurrentCase().getTempDirectory(), abstractFile.getName()); - ContentUtils.writeToFile(abstractFile, jFile, context::dataSourceIngestIsCancelled); - findTangoMessagesInDB(jFile.toString(), abstractFile); - } catch (Exception e) { - logger.log(Level.SEVERE, "Error parsing Tango messages", e); //NON-NLS - } - } - } catch (TskCoreException e) { - logger.log(Level.SEVERE, "Error finding Tango messages", e); //NON-NLS - } - } - - @Messages({"TangoMessageAnalyzer.indexError.message=Failed to index Tango message artifact for keyword search."}) - private static void findTangoMessagesInDB(String DatabasePath, AbstractFile f) { - Connection connection = null; - ResultSet resultSet = null; - Statement statement = null; - - if (DatabasePath == null || DatabasePath.isEmpty()) { - return; - } - try { - Class.forName("org.sqlite.JDBC"); //NON-NLS //load JDBC driver - connection = DriverManager.getConnection("jdbc:sqlite:" + DatabasePath); //NON-NLS - statement = connection.createStatement(); - } catch (ClassNotFoundException | SQLException e) { - logger.log(Level.SEVERE, "Error opening database", e); //NON-NLS - return; - } - - try { - resultSet = statement.executeQuery( - "SELECT conv_id, create_time,direction,payload FROM messages ORDER BY create_time DESC;"); //NON-NLS - - String conv_id; // seems to wrap around the message found in payload after decoding from base-64 - String direction; // 1 incoming, 2 outgoing - String payload; // seems to be a base64 message wrapped by the conv_id - - while (resultSet.next()) { - conv_id = resultSet.getString("conv_id"); //NON-NLS - Long create_time = Long.valueOf(resultSet.getString("create_time")) / 1000; //NON-NLS - if (resultSet.getString("direction").equals("1")) { //NON-NLS - direction = "Incoming"; //NON-NLS - } else { - direction = "Outgoing"; //NON-NLS - } - payload = resultSet.getString("payload"); //NON-NLS - - BlackboardArtifact bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE); //create a call log and then add attributes from result set. - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, moduleName, create_time)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION, moduleName, direction)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT, moduleName, decodeMessage(conv_id, payload))); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE, moduleName, - NbBundle.getMessage(TangoMessageAnalyzer.class, - "TangoMessageAnalyzer.bbAttribute.tangoMessage"))); - - try { - // index the artifact for keyword search - blackboard.indexArtifact(bba); - } catch (Blackboard.BlackboardException ex) { - MessageNotifyUtil.Notify.error( - Bundle.TangoMessageAnalyzer_indexError_message(), bba.getDisplayName()); - logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bba.getArtifactID(), ex); //NON-NLS - } - } - } catch (Exception e) { - logger.log(Level.SEVERE, "Error parsing Tango messages to the Blackboard", e); //NON-NLS - } finally { - try { - if (resultSet != null) { - resultSet.close(); - } - statement.close(); - connection.close(); - } catch (Exception e) { - logger.log(Level.SEVERE, "Error closing database", e); //NON-NLS - } - } - } - - //take the message string which is wrapped by a certain string, and return the text enclosed. - private static String decodeMessage(String wrapper, String message) { - String result = ""; - byte[] decoded = Base64.decodeBase64(message); - try { - String Z = new String(decoded, "UTF-8"); - result = Z.split(wrapper)[1]; - } catch (Exception e) { - logger.log(Level.SEVERE, "Error decoding a Tango message", e); //NON-NLS - } - return result; - } -} diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/TextMessageAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/android/TextMessageAnalyzer.java deleted file mode 100755 index 2971f07fed..0000000000 --- a/Core/src/org/sleuthkit/autopsy/modules/android/TextMessageAnalyzer.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2014 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.modules.android; - -import java.io.File; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.List; -import java.util.logging.Level; -import org.openide.util.NbBundle; -import org.openide.util.NbBundle.Messages; -import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.casemodule.services.Blackboard; -import org.sleuthkit.autopsy.casemodule.services.FileManager; -import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; -import org.sleuthkit.autopsy.datamodel.ContentUtils; -import org.sleuthkit.autopsy.ingest.IngestJobContext; -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; - -/** - * Finds database with SMS/MMS messages and adds them to blackboard. - */ -class TextMessageAnalyzer { - - private static final String moduleName = AndroidModuleFactory.getModuleName(); - private static final Logger logger = Logger.getLogger(TextMessageAnalyzer.class.getName()); - private static Blackboard blackboard; - - public static void findTexts(Content dataSource, FileManager fileManager, - IngestJobContext context) { - blackboard = Case.getCurrentCase().getServices().getBlackboard(); - try { - - List absFiles = fileManager.findFiles(dataSource, "mmssms.db"); //NON-NLS - for (AbstractFile abstractFile : absFiles) { - try { - File jFile = new File(Case.getCurrentCase().getTempDirectory(), abstractFile.getName()); - ContentUtils.writeToFile(abstractFile, jFile, context::dataSourceIngestIsCancelled); - findTextsInDB(jFile.toString(), abstractFile); - } catch (Exception e) { - logger.log(Level.SEVERE, "Error parsing text messages", e); //NON-NLS - } - } - } catch (TskCoreException e) { - logger.log(Level.SEVERE, "Error finding text messages", e); //NON-NLS - } - } - - @Messages({"TextMessageAnalyzer.indexError.message=Failed to index text message artifact for keyword search."}) - private static void findTextsInDB(String DatabasePath, AbstractFile f) { - Connection connection = null; - ResultSet resultSet = null; - Statement statement = null; - - if (DatabasePath == null || DatabasePath.isEmpty()) { - return; - } - try { - Class.forName("org.sqlite.JDBC"); //NON-NLS //load JDBC driver - connection = DriverManager.getConnection("jdbc:sqlite:" + DatabasePath); //NON-NLS - statement = connection.createStatement(); - } catch (ClassNotFoundException | SQLException e) { - logger.log(Level.SEVERE, "Error opening database", e); //NON-NLS - return; - } - - try { - resultSet = statement.executeQuery( - "SELECT address,date,read,type,subject,body FROM sms;"); //NON-NLS - - String address; // may be phone number, or other addresses - - String direction; // message received in inbox = 1, message sent = 2 - String subject;//message subject - Integer read; // may be unread = 0, read = 1 - String body; //message body - while (resultSet.next()) { - address = resultSet.getString("address"); //NON-NLS - Long date = Long.valueOf(resultSet.getString("date")) / 1000; //NON-NLS - - read = resultSet.getInt("read"); //NON-NLS - subject = resultSet.getString("subject"); //NON-NLS - body = resultSet.getString("body"); //NON-NLS - - BlackboardArtifact bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE); //create Message artifact and then add attributes from result set. - if (resultSet.getString("type").equals("1")) { //NON-NLS - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION, moduleName, - NbBundle.getMessage(TextMessageAnalyzer.class, - "TextMessageAnalyzer.bbAttribute.incoming"))); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM, moduleName, address)); - } else { - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION, moduleName, - NbBundle.getMessage(TextMessageAnalyzer.class, - "TextMessageAnalyzer.bbAttribute.outgoing"))); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO, moduleName, address)); - } - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, moduleName, date)); - - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_READ_STATUS, moduleName, read)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SUBJECT, moduleName, subject)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT, moduleName, body)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE, moduleName, - NbBundle.getMessage(TextMessageAnalyzer.class, - "TextMessageAnalyzer.bbAttribute.smsMessage"))); - - try { - // index the artifact for keyword search - blackboard.indexArtifact(bba); - } catch (Blackboard.BlackboardException ex) { - logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bba.getArtifactID(), ex); //NON-NLS - MessageNotifyUtil.Notify.error( - Bundle.TextMessageAnalyzer_indexError_message(), bba.getDisplayName()); - } - } - } catch (Exception e) { - logger.log(Level.SEVERE, "Error parsing text messages to Blackboard", e); //NON-NLS - } finally { - try { - if (resultSet != null) { - resultSet.close(); - } - statement.close(); - connection.close(); - } catch (Exception e) { - logger.log(Level.SEVERE, "Error closing database", e); //NON-NLS - } - } - } -} diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/WWFMessageAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/android/WWFMessageAnalyzer.java deleted file mode 100755 index 5685880afc..0000000000 --- a/Core/src/org/sleuthkit/autopsy/modules/android/WWFMessageAnalyzer.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2014 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.modules.android; - -import java.io.File; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.List; -import java.util.logging.Level; -import org.openide.util.NbBundle; -import org.openide.util.NbBundle.Messages; -import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.casemodule.services.Blackboard; -import org.sleuthkit.autopsy.casemodule.services.FileManager; -import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; -import org.sleuthkit.autopsy.datamodel.ContentUtils; -import org.sleuthkit.autopsy.ingest.IngestJobContext; -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; - -/** - * Finds database for words with friends, parses it, and adds info to - * blackboard. - */ -class WWFMessageAnalyzer { - - private static final String moduleName = AndroidModuleFactory.getModuleName(); - private static final Logger logger = Logger.getLogger(WWFMessageAnalyzer.class.getName()); - private static Blackboard blackboard; - - public static void findWWFMessages(Content dataSource, FileManager fileManager, - IngestJobContext context) { - List absFiles; - blackboard = Case.getCurrentCase().getServices().getBlackboard(); - try { - absFiles = fileManager.findFiles(dataSource, "WordsFramework"); //NON-NLS - - for (AbstractFile abstractFile : absFiles) { - try { - File jFile = new File(Case.getCurrentCase().getTempDirectory(), abstractFile.getName()); - ContentUtils.writeToFile(abstractFile, jFile, context::dataSourceIngestIsCancelled); - - findWWFMessagesInDB(jFile.toString(), abstractFile); - } catch (Exception e) { - logger.log(Level.SEVERE, "Error parsing WWF messages", e); //NON-NLS - } - } - } catch (TskCoreException e) { - logger.log(Level.SEVERE, "Error finding WWF messages", e); //NON-NLS - } - } - - @Messages({"WWFMessageAnalyzer.indexError.message=Failed to index WWF message artifact for keyword search."}) - private static void findWWFMessagesInDB(String DatabasePath, AbstractFile f) { - Connection connection = null; - ResultSet resultSet = null; - Statement statement = null; - - if (DatabasePath == null || DatabasePath.isEmpty()) { - return; - } - try { - Class.forName("org.sqlite.JDBC"); //load JDBC driver - connection = DriverManager.getConnection("jdbc:sqlite:" + DatabasePath); //NON-NLS - statement = connection.createStatement(); - } catch (ClassNotFoundException | SQLException e) { - logger.log(Level.SEVERE, "Error opening database", e); //NON-NLS - return; - } - - try { - resultSet = statement.executeQuery( - "SELECT message,strftime('%s' ,created_at) as datetime,user_id,game_id FROM chat_messages ORDER BY game_id DESC, created_at DESC;"); //NON-NLS - - String message; // WWF Message - String user_id; // the ID of the user who sent the message. - String game_id; // ID of the game which the the message was sent. - - while (resultSet.next()) { - message = resultSet.getString("message"); //NON-NLS - Long created_at = resultSet.getLong("datetime"); //NON-NLS - user_id = resultSet.getString("user_id"); //NON-NLS - game_id = resultSet.getString("game_id"); //NON-NLS - - BlackboardArtifact bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE); //create a call log and then add attributes from result set. - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, moduleName, created_at)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME, moduleName, user_id)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MSG_ID, moduleName, game_id)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT, moduleName, message)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE, moduleName, - NbBundle.getMessage(WWFMessageAnalyzer.class, - "WWFMessageAnalyzer.bbAttribute.wordsWithFriendsMsg"))); - - try { - // index the artifact for keyword search - blackboard.indexArtifact(bba); - } catch (Blackboard.BlackboardException ex) { - logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bba.getArtifactID(), ex); //NON-NLS - MessageNotifyUtil.Notify.error( - Bundle.WWFMessageAnalyzer_indexError_message(), bba.getDisplayName()); - } - } - } catch (Exception e) { - logger.log(Level.SEVERE, "Error parsing WWF messages to the Blackboard", e); //NON-NLS - } finally { - try { - if (resultSet != null) { - resultSet.close(); - } - statement.close(); - connection.close(); - } catch (Exception e) { - logger.log(Level.SEVERE, "Error closing database", e); //NON-NLS - } - } - } -} From 4e633490787215d068776b1158c894a63f14f757 Mon Sep 17 00:00:00 2001 From: Sophie Mori Date: Tue, 13 Dec 2016 11:37:36 -0500 Subject: [PATCH 05/37] Remove unnecessary lines --- .../release/InternalPythonModules/android/browserlocation.py | 4 ---- Core/release/InternalPythonModules/android/contact.py | 5 ----- .../InternalPythonModules/android/googlemaplocation.py | 4 ---- Core/release/InternalPythonModules/android/module.py | 2 +- Core/release/InternalPythonModules/android/tangomessage.py | 4 ---- Core/release/InternalPythonModules/android/textmessage.py | 4 ---- Core/release/InternalPythonModules/android/wwfmessage.py | 4 ---- 7 files changed, 1 insertion(+), 26 deletions(-) diff --git a/Core/release/InternalPythonModules/android/browserlocation.py b/Core/release/InternalPythonModules/android/browserlocation.py index a528f2d66e..f2a38b61db 100755 --- a/Core/release/InternalPythonModules/android/browserlocation.py +++ b/Core/release/InternalPythonModules/android/browserlocation.py @@ -51,10 +51,6 @@ class BrowserLocationAnalyzer(general.AndroidComponentAnalyzer): self._logger.log(Level.SEVERE, traceback.format_exc()) def findGeoLocationsInDB(self, databasePath, abstractFile): - connection = None - resultSet = None - statement = None - if not databasePath: return diff --git a/Core/release/InternalPythonModules/android/contact.py b/Core/release/InternalPythonModules/android/contact.py index 27b6976cf3..44659c0e84 100755 --- a/Core/release/InternalPythonModules/android/contact.py +++ b/Core/release/InternalPythonModules/android/contact.py @@ -55,11 +55,6 @@ class ContactAnalyzer(general.AndroidComponentAnalyzer): The fileId will be the abstract file associated with the artifacts """ def findContactsInDB(self, databasePath, abstractFile): - connection = None - resultSet = None - statement = None - blackboard = Case.getCurrentCase().getServices().getBlackboard() - if not databasePath: return diff --git a/Core/release/InternalPythonModules/android/googlemaplocation.py b/Core/release/InternalPythonModules/android/googlemaplocation.py index c10eef51ea..ed8c2ef9df 100755 --- a/Core/release/InternalPythonModules/android/googlemaplocation.py +++ b/Core/release/InternalPythonModules/android/googlemaplocation.py @@ -51,10 +51,6 @@ class GoogleMapLocationAnalyzer(general.AndroidComponentAnalyzer): self._logger.log(Level.SEVERE, traceback.format_exc()) def findGeoLocationsInDB(self, databasePath, abstractFile): - connection = None - resultSet = None - statement = None - if not databasePath: return diff --git a/Core/release/InternalPythonModules/android/module.py b/Core/release/InternalPythonModules/android/module.py index bff6c8d05e..e1a6d873cb 100755 --- a/Core/release/InternalPythonModules/android/module.py +++ b/Core/release/InternalPythonModules/android/module.py @@ -68,7 +68,7 @@ class AndroidIngestModule(DataSourceIngestModule): errors = [] fileManager = Case.getCurrentCase().getServices().getFileManager() - analyzers = [contact.ContactAnalyzer(), calllog.CallLogAnalyzer(), textmessage.TextMessageAnalyzer(), tangomessage.TangoMessageAnalyzer(), wwfmessage.WWFMessageAnalyzer(), googlemap.GoogleMapLocationAnalyzer(), browserlocation.BrowserLocationAnalyzer(), cachelocation.CacheLocationAnalyzer()] + analyzers = [contact.ContactAnalyzer(), calllog.CallLogAnalyzer(), textmessage.TextMessageAnalyzer(), tangomessage.TangoMessageAnalyzer(), wwfmessage.WWFMessageAnalyzer(), googlemaplocation.GoogleMapLocationAnalyzer(), browserlocation.BrowserLocationAnalyzer(), cachelocation.CacheLocationAnalyzer()] self.log(Level.INFO, "running " + str(len(analyzers)) + " analyzers") progressBar.switchToDeterminate(len(analyzers)) diff --git a/Core/release/InternalPythonModules/android/tangomessage.py b/Core/release/InternalPythonModules/android/tangomessage.py index b77e75a78a..7de7c3f028 100755 --- a/Core/release/InternalPythonModules/android/tangomessage.py +++ b/Core/release/InternalPythonModules/android/tangomessage.py @@ -50,10 +50,6 @@ class TangoMessageAnalyzer(general.AndroidComponentAnalyzer): self._logger.log(Level.SEVERE, traceback.format_exc()) def findTangoMessagesInDB(self, databasePath, abstractFile): - connection = None - resultSet = None - statement = None - if not databasePath: return diff --git a/Core/release/InternalPythonModules/android/textmessage.py b/Core/release/InternalPythonModules/android/textmessage.py index 44ce811a46..eb99d15cb9 100755 --- a/Core/release/InternalPythonModules/android/textmessage.py +++ b/Core/release/InternalPythonModules/android/textmessage.py @@ -49,10 +49,6 @@ class TextMessageAnalyzer(general.AndroidComponentAnalyzer): self._logger.log(Level.SEVERE, traceback.format_exc()) def findTextsInDB(self, databasePath, abstractFile): - connection = None - resultSet = None - statement = None - if not databasePath: return diff --git a/Core/release/InternalPythonModules/android/wwfmessage.py b/Core/release/InternalPythonModules/android/wwfmessage.py index c096a74b52..0a1e27bab6 100755 --- a/Core/release/InternalPythonModules/android/wwfmessage.py +++ b/Core/release/InternalPythonModules/android/wwfmessage.py @@ -47,10 +47,6 @@ class WWFMessageAnalyzer(general.AndroidComponentAnalyzer): self._logger.log(Level.SEVERE, traceback.format_exc()) def findWWFMessagesInDB(self, databasePath, abstractFile): - connection = None - resultSet = None - statement = None - if not databasePath: return From 000547e5e74ae6d980013a167d9ddffa9a925873 Mon Sep 17 00:00:00 2001 From: Sophie Mori Date: Tue, 13 Dec 2016 11:39:23 -0500 Subject: [PATCH 06/37] Change midsentence word to lowercase --- Core/release/InternalPythonModules/android/browserlocation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/release/InternalPythonModules/android/browserlocation.py b/Core/release/InternalPythonModules/android/browserlocation.py index f2a38b61db..2b17f1f8f9 100755 --- a/Core/release/InternalPythonModules/android/browserlocation.py +++ b/Core/release/InternalPythonModules/android/browserlocation.py @@ -88,7 +88,7 @@ class BrowserLocationAnalyzer(general.AndroidComponentAnalyzer): MessageNotifyUtil.Notify.error("Failed to index GPS trackpoint artifact for keyword search.", artifact.getDisplayName()) except Exception as ex: - self._logger.log(Level.SEVERE, "Error Putting artifacts to Blackboard", ex) + self._logger.log(Level.SEVERE, "Error putting artifacts to Blackboard", ex) self._logger.log(Level.SEVERE, traceback.format_exc()) finally: try: From 6c17e9465da3ee742cc4ff241ec70188e1689d67 Mon Sep 17 00:00:00 2001 From: Sophie Mori Date: Tue, 13 Dec 2016 12:13:13 -0500 Subject: [PATCH 07/37] Remove comment --- Core/release/InternalPythonModules/android/tangomessage.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/release/InternalPythonModules/android/tangomessage.py b/Core/release/InternalPythonModules/android/tangomessage.py index 7de7c3f028..d8e68f48d8 100755 --- a/Core/release/InternalPythonModules/android/tangomessage.py +++ b/Core/release/InternalPythonModules/android/tangomessage.py @@ -109,7 +109,7 @@ class TangoMessageAnalyzer(general.AndroidComponentAnalyzer): result = "" decoded = Base64.decodeBase64(message) try: - Z = String(decoded, "UTF-8") # NOTE CHECK THIS + Z = String(decoded, "UTF-8") result = Z.split(wrapper)[1] except Exception as ex: self._logger.log(Level.SEVERE, "Error decoding a Tango message", ex) From 734f233e58cbdbbc7cc29f0f4e43879c86665e46 Mon Sep 17 00:00:00 2001 From: Sophie Mori Date: Tue, 13 Dec 2016 16:19:30 -0500 Subject: [PATCH 08/37] Add license header and make python methods 'private' --- .../android/browserlocation.py | 23 +++++++++++++++++-- .../android/cachelocation.py | 23 +++++++++++++++++-- .../InternalPythonModules/android/calllog.py | 23 +++++++++++++++++-- .../InternalPythonModules/android/contact.py | 23 +++++++++++++++++-- .../InternalPythonModules/android/general.py | 19 +++++++++++++++ .../android/googlemaplocation.py | 23 +++++++++++++++++-- .../InternalPythonModules/android/module.py | 19 +++++++++++++++ .../android/tangomessage.py | 23 +++++++++++++++++-- .../android/textmessage.py | 23 +++++++++++++++++-- .../android/wwfmessage.py | 23 +++++++++++++++++-- 10 files changed, 206 insertions(+), 16 deletions(-) diff --git a/Core/release/InternalPythonModules/android/browserlocation.py b/Core/release/InternalPythonModules/android/browserlocation.py index 2b17f1f8f9..81da60cc0c 100755 --- a/Core/release/InternalPythonModules/android/browserlocation.py +++ b/Core/release/InternalPythonModules/android/browserlocation.py @@ -1,3 +1,22 @@ +""" +Autopsy Forensic Browser + +Copyright 2016 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. +""" + from java.io import File from java.lang import Class from java.lang import ClassNotFoundException @@ -42,7 +61,7 @@ class BrowserLocationAnalyzer(general.AndroidComponentAnalyzer): try: jFile = File(Case.getCurrentCase().getTempDirectory(), abstractFile.getName()) ContentUtils.writeToFile(abstractFile, jFile, context.dataSourceIngestIsCancelled) - self.findGeoLocationsInDB(jFile.toString(), abstractFile) + self.__findGeoLocationsInDB(jFile.toString(), abstractFile) except Exception as ex: self._logger.log(Level.SEVERE, "Error parsing Browser Location files", ex) self._logger.log(Level.SEVERE, traceback.format_exc()) @@ -50,7 +69,7 @@ class BrowserLocationAnalyzer(general.AndroidComponentAnalyzer): self._logger.log(Level.SEVERE, "Error finding Browser Location files", ex) self._logger.log(Level.SEVERE, traceback.format_exc()) - def findGeoLocationsInDB(self, databasePath, abstractFile): + def __findGeoLocationsInDB(self, databasePath, abstractFile): if not databasePath: return diff --git a/Core/release/InternalPythonModules/android/cachelocation.py b/Core/release/InternalPythonModules/android/cachelocation.py index 92d52ae987..125141ecee 100755 --- a/Core/release/InternalPythonModules/android/cachelocation.py +++ b/Core/release/InternalPythonModules/android/cachelocation.py @@ -1,3 +1,22 @@ +""" +Autopsy Forensic Browser + +Copyright 2016 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. +""" + from java.io import File from java.io import FileInputStream from java.io import InputStream @@ -44,7 +63,7 @@ class CacheLocationAnalyzer(general.AndroidComponentAnalyzer): try: jFile = File(Case.getCurrentCase().getTempDirectory(), abstractFile.getName()) ContentUtils.writeToFile(abstractFile, jFile, context.dataSourceIngestIsCancelled) - self.findGeoLocationsInFile(jFile, abstractFile) + self.__findGeoLocationsInFile(jFile, abstractFile) except Exception as ex: self._logger.log(Level.SEVERE, "Error parsing cached Location files", ex) self._logger.log(Level.SEVERE, traceback.format_exc()) @@ -52,7 +71,7 @@ class CacheLocationAnalyzer(general.AndroidComponentAnalyzer): self._logger.log(Level.SEVERE, "Error finding cached Location files", ex) self._logger.log(Level.SEVERE, traceback.format_exc()) - def findGeoLocationsInFile(self, file, abstractFile): + def __findGeoLocationsInFile(self, file, abstractFile): tempBytes = bytearray([0] * 2) # will temporarily hold bytes to be converted into the correct data types diff --git a/Core/release/InternalPythonModules/android/calllog.py b/Core/release/InternalPythonModules/android/calllog.py index d118c6c6d9..fab4ee7805 100755 --- a/Core/release/InternalPythonModules/android/calllog.py +++ b/Core/release/InternalPythonModules/android/calllog.py @@ -1,3 +1,22 @@ +""" +Autopsy Forensic Browser + +Copyright 2016 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. +""" + from java.io import File from java.io import IOException from java.lang import Class @@ -67,7 +86,7 @@ class CallLogAnalyzer(general.AndroidComponentAnalyzer): try: file = File(Case.getCurrentCase().getTempDirectory(), abstractFile.getName()) ContentUtils.writeToFile(abstractFile, file, context.dataSourceIngestIsCancelled) - self.findCallLogsInDB(file.toString(), abstractFile) + self.__findCallLogsInDB(file.toString(), abstractFile) except IOException as ex: self._logger.log(Level.SEVERE, "Error writing temporary call log db to disk", ex) self._logger.log(Level.SEVERE, traceback.format_exc()) @@ -75,7 +94,7 @@ class CallLogAnalyzer(general.AndroidComponentAnalyzer): self._logger.log(Level.SEVERE, "Error finding call logs", ex) self._logger.log(Level.SEVERE, traceback.format_exc()) - def findCallLogsInDB(self, databasePath, abstractFile): + def __findCallLogsInDB(self, databasePath, abstractFile): if not databasePath: return diff --git a/Core/release/InternalPythonModules/android/contact.py b/Core/release/InternalPythonModules/android/contact.py index 44659c0e84..480d9dcbc1 100755 --- a/Core/release/InternalPythonModules/android/contact.py +++ b/Core/release/InternalPythonModules/android/contact.py @@ -1,3 +1,22 @@ +""" +Autopsy Forensic Browser + +Copyright 2016 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. +""" + from java.io import File from java.lang import Class from java.lang import ClassNotFoundException @@ -42,7 +61,7 @@ class ContactAnalyzer(general.AndroidComponentAnalyzer): try: jFile = File(Case.getCurrentCase().getTempDirectory(), abstractFile.getName()) ContentUtils.writeToFile(abstractFile, jFile, context.dataSourceIngestIsCancelled) - self.findContactsInDB(str(jFile.toString()), abstractFile) + self.__findContactsInDB(str(jFile.toString()), abstractFile) except Exception as ex: self._logger.log(Level.SEVERE, "Error parsing Contacts", ex) self._logger.log(Level.SEVERE, traceback.format_exc()) @@ -54,7 +73,7 @@ class ContactAnalyzer(general.AndroidComponentAnalyzer): Will create artifact from a database given by the path The fileId will be the abstract file associated with the artifacts """ - def findContactsInDB(self, databasePath, abstractFile): + def __findContactsInDB(self, databasePath, abstractFile): if not databasePath: return diff --git a/Core/release/InternalPythonModules/android/general.py b/Core/release/InternalPythonModules/android/general.py index 3316e89e6d..02944fc3d2 100755 --- a/Core/release/InternalPythonModules/android/general.py +++ b/Core/release/InternalPythonModules/android/general.py @@ -1,3 +1,22 @@ +""" +Autopsy Forensic Browser + +Copyright 2016 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. +""" + MODULE_NAME = "Android Analyzer Python" """ diff --git a/Core/release/InternalPythonModules/android/googlemaplocation.py b/Core/release/InternalPythonModules/android/googlemaplocation.py index ed8c2ef9df..e9da2d9e99 100755 --- a/Core/release/InternalPythonModules/android/googlemaplocation.py +++ b/Core/release/InternalPythonModules/android/googlemaplocation.py @@ -1,3 +1,22 @@ +""" +Autopsy Forensic Browser + +Copyright 2016 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. +""" + from java.io import File from java.lang import Class from java.lang import ClassNotFoundException @@ -42,7 +61,7 @@ class GoogleMapLocationAnalyzer(general.AndroidComponentAnalyzer): try: jFile = File(Case.getCurrentCase().getTempDirectory(), abstractFile.getName()) ContentUtils.writeToFile(abstractFile, jFile, context.dataSourceIngestIsCancelled) - self.findGeoLocationsInDB(jFile.toString(), abstractFile) + self.__findGeoLocationsInDB(jFile.toString(), abstractFile) except Exception as ex: self._logger.log(Level.SEVERE, "Error parsing Google map locations", ex) self._logger.log(Level.SEVERE, traceback.format_exc()) @@ -50,7 +69,7 @@ class GoogleMapLocationAnalyzer(general.AndroidComponentAnalyzer): self._logger.log(Level.SEVERE, "Error finding Google map locations", ex) self._logger.log(Level.SEVERE, traceback.format_exc()) - def findGeoLocationsInDB(self, databasePath, abstractFile): + def __findGeoLocationsInDB(self, databasePath, abstractFile): if not databasePath: return diff --git a/Core/release/InternalPythonModules/android/module.py b/Core/release/InternalPythonModules/android/module.py index e1a6d873cb..41de9f7ab2 100755 --- a/Core/release/InternalPythonModules/android/module.py +++ b/Core/release/InternalPythonModules/android/module.py @@ -1,3 +1,22 @@ +""" +Autopsy Forensic Browser + +Copyright 2016 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. +""" + import jarray import inspect import traceback diff --git a/Core/release/InternalPythonModules/android/tangomessage.py b/Core/release/InternalPythonModules/android/tangomessage.py index d8e68f48d8..c9e17f8244 100755 --- a/Core/release/InternalPythonModules/android/tangomessage.py +++ b/Core/release/InternalPythonModules/android/tangomessage.py @@ -1,3 +1,22 @@ +""" +Autopsy Forensic Browser + +Copyright 2016 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. +""" + from java.io import File from java.lang import Class from java.lang import ClassNotFoundException @@ -41,7 +60,7 @@ class TangoMessageAnalyzer(general.AndroidComponentAnalyzer): try: jFile = File(Case.getCurrentCase().getTempDirectory(), abstractFile.getName()) ContentUtils.writeToFile(abstractFile, jFile, context.dataSourceIngestIsCancelled) - self.findTangoMessagesInDB(jFile.toString(), abstractFile) + self.__findTangoMessagesInDB(jFile.toString(), abstractFile) except Exception as ex: self._logger.log(Level.SEVERE, "Error parsing Tango messages", ex) self._logger.log(Level.SEVERE, traceback.format_exc()) @@ -49,7 +68,7 @@ class TangoMessageAnalyzer(general.AndroidComponentAnalyzer): self._logger.log(Level.SEVERE, "Error finding Tango messages", ex) self._logger.log(Level.SEVERE, traceback.format_exc()) - def findTangoMessagesInDB(self, databasePath, abstractFile): + def __findTangoMessagesInDB(self, databasePath, abstractFile): if not databasePath: return diff --git a/Core/release/InternalPythonModules/android/textmessage.py b/Core/release/InternalPythonModules/android/textmessage.py index eb99d15cb9..f59220edc3 100755 --- a/Core/release/InternalPythonModules/android/textmessage.py +++ b/Core/release/InternalPythonModules/android/textmessage.py @@ -1,3 +1,22 @@ +""" +Autopsy Forensic Browser + +Copyright 2016 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. +""" + from java.io import File from java.lang import Class from java.lang import ClassNotFoundException @@ -40,7 +59,7 @@ class TextMessageAnalyzer(general.AndroidComponentAnalyzer): try: jFile = File(Case.getCurrentCase().getTempDirectory(), abstractFile.getName()) ContentUtils.writeToFile(abstractFile, jFile, context.dataSourceIngestIsCancelled) - self.findTextsInDB(jFile.toString(), abstractFile) + self.__findTextsInDB(jFile.toString(), abstractFile) except Exception as ex: self._logger.log(Level.SEVERE, "Error parsing text messages", ex) self._logger.log(Level.SEVERE, traceback.format_exc()) @@ -48,7 +67,7 @@ class TextMessageAnalyzer(general.AndroidComponentAnalyzer): self._logger.log(Level.SEVERE, "Error finding text messages", ex) self._logger.log(Level.SEVERE, traceback.format_exc()) - def findTextsInDB(self, databasePath, abstractFile): + def __findTextsInDB(self, databasePath, abstractFile): if not databasePath: return diff --git a/Core/release/InternalPythonModules/android/wwfmessage.py b/Core/release/InternalPythonModules/android/wwfmessage.py index 0a1e27bab6..902b0816bc 100755 --- a/Core/release/InternalPythonModules/android/wwfmessage.py +++ b/Core/release/InternalPythonModules/android/wwfmessage.py @@ -1,3 +1,22 @@ +""" +Autopsy Forensic Browser + +Copyright 2016 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. +""" + from java.io import File from java.lang import Class from java.lang import ClassNotFoundException @@ -38,7 +57,7 @@ class WWFMessageAnalyzer(general.AndroidComponentAnalyzer): try: jFile = File(Case.getCurrentCase().getTempDirectory(), abstractFile.getName()) ContentUtils.writeToFile(abstractFile, jFile, context.dataSourceIngestIsCancelled) - self.findWWFMessagesInDB(jFile.toString(), abstractFile) + self.__findWWFMessagesInDB(jFile.toString(), abstractFile) except Exception as ex: self._logger.log(Level.SEVERE, "Error parsing WWF messages", ex) self._logger.log(Level.SEVERE, traceback.format_exc()) @@ -46,7 +65,7 @@ class WWFMessageAnalyzer(general.AndroidComponentAnalyzer): self._logger.log(Level.SEVERE, "Error finding WWF messages", ex) self._logger.log(Level.SEVERE, traceback.format_exc()) - def findWWFMessagesInDB(self, databasePath, abstractFile): + def __findWWFMessagesInDB(self, databasePath, abstractFile): if not databasePath: return From d8bd360782e3db40851e1eeaf1d52dee6ae01b59 Mon Sep 17 00:00:00 2001 From: Sophie Mori Date: Tue, 13 Dec 2016 16:37:48 -0500 Subject: [PATCH 09/37] Clean up some messages and code --- .../InternalPythonModules/android/browserlocation.py | 8 ++++---- .../InternalPythonModules/android/cachelocation.py | 8 ++++---- Core/release/InternalPythonModules/android/calllog.py | 4 ++-- Core/release/InternalPythonModules/android/contact.py | 2 +- .../InternalPythonModules/android/googlemaplocation.py | 4 ++-- Core/release/InternalPythonModules/android/module.py | 2 +- .../release/InternalPythonModules/android/tangomessage.py | 4 ++-- Core/release/InternalPythonModules/android/textmessage.py | 4 ++-- Core/release/InternalPythonModules/android/wwfmessage.py | 4 ++-- 9 files changed, 20 insertions(+), 20 deletions(-) diff --git a/Core/release/InternalPythonModules/android/browserlocation.py b/Core/release/InternalPythonModules/android/browserlocation.py index 81da60cc0c..18ae46af4d 100755 --- a/Core/release/InternalPythonModules/android/browserlocation.py +++ b/Core/release/InternalPythonModules/android/browserlocation.py @@ -63,10 +63,10 @@ class BrowserLocationAnalyzer(general.AndroidComponentAnalyzer): ContentUtils.writeToFile(abstractFile, jFile, context.dataSourceIngestIsCancelled) self.__findGeoLocationsInDB(jFile.toString(), abstractFile) except Exception as ex: - self._logger.log(Level.SEVERE, "Error parsing Browser Location files", ex) + self._logger.log(Level.SEVERE, "Error parsing browser location files", ex) self._logger.log(Level.SEVERE, traceback.format_exc()) except TskCoreException as ex: - self._logger.log(Level.SEVERE, "Error finding Browser Location files", ex) + self._logger.log(Level.SEVERE, "Error finding browser location files", ex) self._logger.log(Level.SEVERE, traceback.format_exc()) def __findGeoLocationsInDB(self, databasePath, abstractFile): @@ -78,7 +78,7 @@ class BrowserLocationAnalyzer(general.AndroidComponentAnalyzer): connection = DriverManager.getConnection("jdbc:sqlite:" + databasePath) statement = connection.createStatement() except (ClassNotFoundException, SQLException) as ex: - self._logger.log(Level.SEVERE, "Error connecting to sql database", ex) + self._logger.log(Level.SEVERE, "Error connecting to SQL database", ex) self._logger.log(Level.SEVERE, traceback.format_exc()) return @@ -107,7 +107,7 @@ class BrowserLocationAnalyzer(general.AndroidComponentAnalyzer): MessageNotifyUtil.Notify.error("Failed to index GPS trackpoint artifact for keyword search.", artifact.getDisplayName()) except Exception as ex: - self._logger.log(Level.SEVERE, "Error putting artifacts to Blackboard", ex) + self._logger.log(Level.SEVERE, "Error putting artifacts to blackboard", ex) self._logger.log(Level.SEVERE, traceback.format_exc()) finally: try: diff --git a/Core/release/InternalPythonModules/android/cachelocation.py b/Core/release/InternalPythonModules/android/cachelocation.py index 125141ecee..4458594bb3 100755 --- a/Core/release/InternalPythonModules/android/cachelocation.py +++ b/Core/release/InternalPythonModules/android/cachelocation.py @@ -47,7 +47,7 @@ Parses cache files that Android maintains for Wifi and cell towers. Adds GPS poi class CacheLocationAnalyzer(general.AndroidComponentAnalyzer): def __init__(self): - self._logger = Logger.getLogger("CacheLocationAnalyzer") + self._logger = Logger.getLogger(self.__class__.__name__) """ cache.cell stores mobile tower GPS locations and cache.wifi stores GPS @@ -65,10 +65,10 @@ class CacheLocationAnalyzer(general.AndroidComponentAnalyzer): ContentUtils.writeToFile(abstractFile, jFile, context.dataSourceIngestIsCancelled) self.__findGeoLocationsInFile(jFile, abstractFile) except Exception as ex: - self._logger.log(Level.SEVERE, "Error parsing cached Location files", ex) + self._logger.log(Level.SEVERE, "Error parsing cached location files", ex) self._logger.log(Level.SEVERE, traceback.format_exc()) except TskCoreException as ex: - self._logger.log(Level.SEVERE, "Error finding cached Location files", ex) + self._logger.log(Level.SEVERE, "Error finding cached location files", ex) self._logger.log(Level.SEVERE, traceback.format_exc()) def __findGeoLocationsInFile(self, file, abstractFile): @@ -140,7 +140,7 @@ class CacheLocationAnalyzer(general.AndroidComponentAnalyzer): MessageNotifyUtil.Notify.error("Failed to index GPS trackpoint artifact for keyword search.", artifact.getDisplayName()) except Exception as ex: - self._logger.log(Level.SEVERE, "Error parsing Cached GPS locations to Blackboard", ex) + self._logger.log(Level.SEVERE, "Error parsing Cached GPS locations to blackboard", ex) self._logger.log(Level.SEVERE, traceback.format_exc()) def toDouble(byteArray): diff --git a/Core/release/InternalPythonModules/android/calllog.py b/Core/release/InternalPythonModules/android/calllog.py index fab4ee7805..49914006b2 100755 --- a/Core/release/InternalPythonModules/android/calllog.py +++ b/Core/release/InternalPythonModules/android/calllog.py @@ -51,7 +51,7 @@ Locates a variety of different call log databases, parses them, and populates th class CallLogAnalyzer(general.AndroidComponentAnalyzer): def __init__(self): - self._logger = Logger.getLogger("CallLogAnalyzer") + self._logger = Logger.getLogger(self.__class__.__name__) # the names of tables that potentially hold call logs in the dbs _tableNames = ["calls", "logs"] @@ -136,7 +136,7 @@ class CallLogAnalyzer(general.AndroidComponentAnalyzer): MessageNotifyUtil.Notify.error("Failed to index call log artifact for keyword search.", artifact.getDisplayName()) except TskCoreException as ex: - self._logger.log(Level.SEVERE, "Error posting call log record to the Blackboard", ex) + self._logger.log(Level.SEVERE, "Error posting call log record to the blackboard", ex) self._logger.log(Level.SEVERE, traceback.format_exc()) except SQLException as ex: self._logger.log(Level.WARNING, String.format("Could not read table %s in db %s", tableName, databasePath), ex) diff --git a/Core/release/InternalPythonModules/android/contact.py b/Core/release/InternalPythonModules/android/contact.py index 480d9dcbc1..6d7fed93a6 100755 --- a/Core/release/InternalPythonModules/android/contact.py +++ b/Core/release/InternalPythonModules/android/contact.py @@ -49,7 +49,7 @@ Locates a variety of different contacts databases, parses them, and populates th class ContactAnalyzer(general.AndroidComponentAnalyzer): def __init__(self): - self._logger = Logger.getLogger("ContactAnalyzer") + self._logger = Logger.getLogger(self.__class__.__name__) def analyze(self, dataSource, fileManager, context): try: diff --git a/Core/release/InternalPythonModules/android/googlemaplocation.py b/Core/release/InternalPythonModules/android/googlemaplocation.py index e9da2d9e99..465fe3909c 100755 --- a/Core/release/InternalPythonModules/android/googlemaplocation.py +++ b/Core/release/InternalPythonModules/android/googlemaplocation.py @@ -50,7 +50,7 @@ Finds and parses the Google Maps database. class GoogleMapLocationAnalyzer(general.AndroidComponentAnalyzer): def __init__(self): - self._logger = Logger.getLogger("GoogleMapLocationAnalyzer") + self._logger = Logger.getLogger(self.__class__.__name__) def analyze(self, dataSource, fileManager, context): try: @@ -117,7 +117,7 @@ class GoogleMapLocationAnalyzer(general.AndroidComponentAnalyzer): MessageNotifyUtil.Notify.error("Failed to index GPS route artifact for keyword search.", artifact.getDisplayName()) except Exception as ex: - self._logger.log(Level.SEVERE, "Error parsing Google map locations to the Blackboard", ex) + self._logger.log(Level.SEVERE, "Error parsing Google map locations to the blackboard", ex) self._logger.log(Level.SEVERE, traceback.format_exc()) finally: try: diff --git a/Core/release/InternalPythonModules/android/module.py b/Core/release/InternalPythonModules/android/module.py index 41de9f7ab2..07ef78ed8d 100755 --- a/Core/release/InternalPythonModules/android/module.py +++ b/Core/release/InternalPythonModules/android/module.py @@ -100,7 +100,7 @@ class AndroidIngestModule(DataSourceIngestModule): n += 1 progressBar.progress(n) except Exception as ex: - errors.append("Error getting Contacts") + errors.append("Error running " + analyzer.__class__.__name__) self.log(Level.SEVERE, traceback.format_exc()) errorMessage = [] # NOTE: this isn't used? errorMessageSubject = "" # NOTE: this isn't used? diff --git a/Core/release/InternalPythonModules/android/tangomessage.py b/Core/release/InternalPythonModules/android/tangomessage.py index c9e17f8244..31db3bd0ab 100755 --- a/Core/release/InternalPythonModules/android/tangomessage.py +++ b/Core/release/InternalPythonModules/android/tangomessage.py @@ -51,7 +51,7 @@ Locates database for the Tango app and adds info to blackboard. class TangoMessageAnalyzer(general.AndroidComponentAnalyzer): def __init__(self): - self._logger = Logger.getLogger("TangoMessageAnalyzer") + self._logger = Logger.getLogger(self.__class__.__name__) def analyze(self, dataSource, fileManager, context): try: @@ -110,7 +110,7 @@ class TangoMessageAnalyzer(general.AndroidComponentAnalyzer): MessageNotifyUtil.Notify.error("Failed to index Tango message artifact for keyword search.", artifact.getDisplayName()) except Exception as ex: - self._logger.log(Level.SEVERE, "Error parsing Tango messages to the Blackboard", ex) + self._logger.log(Level.SEVERE, "Error parsing Tango messages to the blackboard", ex) self._logger.log(Level.SEVERE, traceback.format_exc()) finally: try: diff --git a/Core/release/InternalPythonModules/android/textmessage.py b/Core/release/InternalPythonModules/android/textmessage.py index f59220edc3..7e23d8f15b 100755 --- a/Core/release/InternalPythonModules/android/textmessage.py +++ b/Core/release/InternalPythonModules/android/textmessage.py @@ -50,7 +50,7 @@ Finds database with SMS/MMS messages and adds them to blackboard. class TextMessageAnalyzer(general.AndroidComponentAnalyzer): def __init__(self): - self._logger = Logger.getLogger("TextMessageAnalyzer") + self._logger = Logger.getLogger(self.__class__.__name__) def analyze(self, dataSource, fileManager, context): try: @@ -112,7 +112,7 @@ class TextMessageAnalyzer(general.AndroidComponentAnalyzer): MessageNotifyUtil.Notify.error("Failed to index text message artifact for keyword search.", artifact.getDisplayName()) except Exception as ex: - self._logger.log(Level.SEVERE, "Error parsing text messages to Blackboard", ex) + self._logger.log(Level.SEVERE, "Error parsing text messages to blackboard", ex) self._logger.log(Level.SEVERE, traceback.format_exc()) finally: try: diff --git a/Core/release/InternalPythonModules/android/wwfmessage.py b/Core/release/InternalPythonModules/android/wwfmessage.py index 902b0816bc..2f51409f34 100755 --- a/Core/release/InternalPythonModules/android/wwfmessage.py +++ b/Core/release/InternalPythonModules/android/wwfmessage.py @@ -48,7 +48,7 @@ Analyzes messages from Words With Friends class WWFMessageAnalyzer(general.AndroidComponentAnalyzer): def __init__(self): - self._logger = Logger.getLogger("WWFMessageAnalyzer") + self._logger = Logger.getLogger(self.__class__.__name__) def analyze(self, dataSource, fileManager, context): try: @@ -105,7 +105,7 @@ class WWFMessageAnalyzer(general.AndroidComponentAnalyzer): MessageNotifyUtil.Notify.error("Failed to index WWF message artifact for keyword search.", artifact.getDisplayName()) except Exception as ex: - self._logger.log(Level.SEVERE, "Error parsing WWF messages to the Blackboard", ex) + self._logger.log(Level.SEVERE, "Error parsing WWF messages to the blackboard", ex) self._logger.log(Level.SEVERE, traceback.format_exc()) finally: try: From b4ef211c12a44fa66efd777208c3cf8b2e116687 Mon Sep 17 00:00:00 2001 From: Sophie Mori Date: Wed, 14 Dec 2016 09:39:34 -0500 Subject: [PATCH 10/37] Add file id to file name in temporary folder --- Core/release/InternalPythonModules/android/browserlocation.py | 2 +- Core/release/InternalPythonModules/android/cachelocation.py | 2 +- Core/release/InternalPythonModules/android/calllog.py | 2 +- Core/release/InternalPythonModules/android/contact.py | 2 +- Core/release/InternalPythonModules/android/googlemaplocation.py | 2 +- Core/release/InternalPythonModules/android/tangomessage.py | 2 +- Core/release/InternalPythonModules/android/textmessage.py | 2 +- Core/release/InternalPythonModules/android/wwfmessage.py | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Core/release/InternalPythonModules/android/browserlocation.py b/Core/release/InternalPythonModules/android/browserlocation.py index 18ae46af4d..ef79a623c2 100755 --- a/Core/release/InternalPythonModules/android/browserlocation.py +++ b/Core/release/InternalPythonModules/android/browserlocation.py @@ -59,7 +59,7 @@ class BrowserLocationAnalyzer(general.AndroidComponentAnalyzer): if abstractFile.getSize() == 0: continue try: - jFile = File(Case.getCurrentCase().getTempDirectory(), abstractFile.getName()) + jFile = File(Case.getCurrentCase().getTempDirectory(), str(abstractFile.getId()) + abstractFile.getName()) ContentUtils.writeToFile(abstractFile, jFile, context.dataSourceIngestIsCancelled) self.__findGeoLocationsInDB(jFile.toString(), abstractFile) except Exception as ex: diff --git a/Core/release/InternalPythonModules/android/cachelocation.py b/Core/release/InternalPythonModules/android/cachelocation.py index 4458594bb3..c28aa48fc3 100755 --- a/Core/release/InternalPythonModules/android/cachelocation.py +++ b/Core/release/InternalPythonModules/android/cachelocation.py @@ -61,7 +61,7 @@ class CacheLocationAnalyzer(general.AndroidComponentAnalyzer): if abstractFile.getSize() == 0: continue try: - jFile = File(Case.getCurrentCase().getTempDirectory(), abstractFile.getName()) + jFile = File(Case.getCurrentCase().getTempDirectory(), str(abstractFile.getId()) + abstractFile.getName()) ContentUtils.writeToFile(abstractFile, jFile, context.dataSourceIngestIsCancelled) self.__findGeoLocationsInFile(jFile, abstractFile) except Exception as ex: diff --git a/Core/release/InternalPythonModules/android/calllog.py b/Core/release/InternalPythonModules/android/calllog.py index 49914006b2..886a918449 100755 --- a/Core/release/InternalPythonModules/android/calllog.py +++ b/Core/release/InternalPythonModules/android/calllog.py @@ -84,7 +84,7 @@ class CallLogAnalyzer(general.AndroidComponentAnalyzer): absFiles.addAll(fileManager.findFiles(dataSource, "contacts2.db")) for abstractFile in absFiles: try: - file = File(Case.getCurrentCase().getTempDirectory(), abstractFile.getName()) + file = File(Case.getCurrentCase().getTempDirectory(), str(abstractFile.getId()) + abstractFile.getName()) ContentUtils.writeToFile(abstractFile, file, context.dataSourceIngestIsCancelled) self.__findCallLogsInDB(file.toString(), abstractFile) except IOException as ex: diff --git a/Core/release/InternalPythonModules/android/contact.py b/Core/release/InternalPythonModules/android/contact.py index 6d7fed93a6..202ddbdc02 100755 --- a/Core/release/InternalPythonModules/android/contact.py +++ b/Core/release/InternalPythonModules/android/contact.py @@ -59,7 +59,7 @@ class ContactAnalyzer(general.AndroidComponentAnalyzer): return for abstractFile in absFiles: try: - jFile = File(Case.getCurrentCase().getTempDirectory(), abstractFile.getName()) + jFile = File(Case.getCurrentCase().getTempDirectory(), str(abstractFile.getId()) + abstractFile.getName()) ContentUtils.writeToFile(abstractFile, jFile, context.dataSourceIngestIsCancelled) self.__findContactsInDB(str(jFile.toString()), abstractFile) except Exception as ex: diff --git a/Core/release/InternalPythonModules/android/googlemaplocation.py b/Core/release/InternalPythonModules/android/googlemaplocation.py index 465fe3909c..066ed2f792 100755 --- a/Core/release/InternalPythonModules/android/googlemaplocation.py +++ b/Core/release/InternalPythonModules/android/googlemaplocation.py @@ -59,7 +59,7 @@ class GoogleMapLocationAnalyzer(general.AndroidComponentAnalyzer): return for abstractFile in absFiles: try: - jFile = File(Case.getCurrentCase().getTempDirectory(), abstractFile.getName()) + jFile = File(Case.getCurrentCase().getTempDirectory(), str(abstractFile.getId()) + abstractFile.getName()) ContentUtils.writeToFile(abstractFile, jFile, context.dataSourceIngestIsCancelled) self.__findGeoLocationsInDB(jFile.toString(), abstractFile) except Exception as ex: diff --git a/Core/release/InternalPythonModules/android/tangomessage.py b/Core/release/InternalPythonModules/android/tangomessage.py index 31db3bd0ab..04223f7fe1 100755 --- a/Core/release/InternalPythonModules/android/tangomessage.py +++ b/Core/release/InternalPythonModules/android/tangomessage.py @@ -58,7 +58,7 @@ class TangoMessageAnalyzer(general.AndroidComponentAnalyzer): absFiles = fileManager.findFiles(dataSource, "tc.db") for abstractFile in absFiles: try: - jFile = File(Case.getCurrentCase().getTempDirectory(), abstractFile.getName()) + jFile = File(Case.getCurrentCase().getTempDirectory(), str(abstractFile.getId()) + abstractFile.getName()) ContentUtils.writeToFile(abstractFile, jFile, context.dataSourceIngestIsCancelled) self.__findTangoMessagesInDB(jFile.toString(), abstractFile) except Exception as ex: diff --git a/Core/release/InternalPythonModules/android/textmessage.py b/Core/release/InternalPythonModules/android/textmessage.py index 7e23d8f15b..f618faa29a 100755 --- a/Core/release/InternalPythonModules/android/textmessage.py +++ b/Core/release/InternalPythonModules/android/textmessage.py @@ -57,7 +57,7 @@ class TextMessageAnalyzer(general.AndroidComponentAnalyzer): absFiles = fileManager.findFiles(dataSource, "mmssms.db") for abstractFile in absFiles: try: - jFile = File(Case.getCurrentCase().getTempDirectory(), abstractFile.getName()) + jFile = File(Case.getCurrentCase().getTempDirectory(), str(abstractFile.getId()) + abstractFile.getName()) ContentUtils.writeToFile(abstractFile, jFile, context.dataSourceIngestIsCancelled) self.__findTextsInDB(jFile.toString(), abstractFile) except Exception as ex: diff --git a/Core/release/InternalPythonModules/android/wwfmessage.py b/Core/release/InternalPythonModules/android/wwfmessage.py index 2f51409f34..97f35869ed 100755 --- a/Core/release/InternalPythonModules/android/wwfmessage.py +++ b/Core/release/InternalPythonModules/android/wwfmessage.py @@ -55,7 +55,7 @@ class WWFMessageAnalyzer(general.AndroidComponentAnalyzer): absFiles = fileManager.findFiles(dataSource, "WordsFramework") for abstractFile in absFiles: try: - jFile = File(Case.getCurrentCase().getTempDirectory(), abstractFile.getName()) + jFile = File(Case.getCurrentCase().getTempDirectory(), str(abstractFile.getId()) + abstractFile.getName()) ContentUtils.writeToFile(abstractFile, jFile, context.dataSourceIngestIsCancelled) self.__findWWFMessagesInDB(jFile.toString(), abstractFile) except Exception as ex: From 242cc392e2cee914d70c32d5abc6036aba9f0ebb Mon Sep 17 00:00:00 2001 From: Sophie Mori Date: Fri, 16 Dec 2016 15:16:43 -0500 Subject: [PATCH 11/37] Allow user to add agency logo --- .../autopsy/casemodule/Bundle.properties | 1 + .../autopsy/casemodule/GeneralFilter.java | 9 +- .../autopsy/core/UserPreferences.java | 27 +++-- .../corecomponents/AutopsyOptionsPanel.form | 46 +++++++- .../corecomponents/AutopsyOptionsPanel.java | 111 +++++++++++++----- .../autopsy/corecomponents/Bundle.properties | 40 ++++--- .../corecomponents/Bundle_ja.properties | 30 ++--- .../autopsy/report/ReportBranding.java | 14 +-- .../report/ReportBrandingProviderI.java | 8 +- .../sleuthkit/autopsy/report/ReportHTML.java | 14 +-- 10 files changed, 202 insertions(+), 98 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties index b58268dce3..3822a7a09b 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties @@ -159,6 +159,7 @@ GeneralFilter.rawImageDesc.text=Raw Images (*.img, *.dd, *.001, *.aa, *.raw, *.b GeneralFilter.encaseImageDesc.text=Encase Images (*.e01) GeneralFilter.virtualMachineImageDesc.text=Virtual Machines (*.vmdk, *.vhd) GeneralFilter.executableDesc.text=Executables (*.exe) +GeneralFilter.graphicImageDesc.text=Images (*.png, *.jpg, *.jpeg, *.gif) ImageDSProcessor.dsType.text=Image or VM File ImageDSProcessor.allDesc.text=All Supported Types ImageFilePanel.moduleErr=Module Error diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/GeneralFilter.java b/Core/src/org/sleuthkit/autopsy/casemodule/GeneralFilter.java index 0f90bc9fae..25598f5349 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/GeneralFilter.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/GeneralFilter.java @@ -37,14 +37,17 @@ public class GeneralFilter extends FileFilter { public static final List ENCASE_IMAGE_EXTS = Arrays.asList(new String[]{".e01"}); //NON-NLS public static final String ENCASE_IMAGE_DESC = NbBundle.getMessage(GeneralFilter.class, "GeneralFilter.encaseImageDesc.text"); - + public static final List VIRTUAL_MACHINE_EXTS = Arrays.asList(new String[]{".vmdk", ".vhd"}); //NON-NLS public static final String VIRTUAL_MACHINE_DESC = NbBundle.getMessage(GeneralFilter.class, - "GeneralFilter.virtualMachineImageDesc.text"); + "GeneralFilter.virtualMachineImageDesc.text"); public static final List EXECUTABLE_EXTS = Arrays.asList(new String[]{".exe"}); //NON-NLS public static final String EXECUTABLE_DESC = NbBundle.getMessage(GeneralFilter.class, "GeneralFilter.executableDesc.text"); - + + public static final List GRAPHIC_IMAGE_EXTS = Arrays.asList(new String[]{".png", ".jpeg", ".jpg", ".gif"}); //NON-NLS + public static final String GRAPHIC_IMG_DECR = NbBundle.getMessage(GeneralFilter.class, "GeneralFilter.graphicImageDesc.text"); + private List extensions; private String desc; diff --git a/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java b/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java index 473c8fe1ab..bb5133bef8 100755 --- a/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java +++ b/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java @@ -42,11 +42,11 @@ public final class UserPreferences { private static final boolean isWindowsOS = PlatformUtil.isWindowsOS(); private static final Preferences preferences = NbPreferences.forModule(UserPreferences.class); - public static final String KEEP_PREFERRED_VIEWER = "KeepPreferredViewer"; // NON-NLS - public static final String HIDE_KNOWN_FILES_IN_DATA_SOURCES_TREE = "HideKnownFilesInDataSourcesTree"; //NON-NLS - public static final String HIDE_KNOWN_FILES_IN_VIEWS_TREE = "HideKnownFilesInViewsTree"; //NON-NLS - public static final String HIDE_SLACK_FILES_IN_DATA_SOURCES_TREE = "HideSlackFilesInDataSourcesTree"; //NON-NLS - public static final String HIDE_SLACK_FILES_IN_VIEWS_TREE = "HideSlackFilesInViewsTree"; //NON-NLS + public static final String KEEP_PREFERRED_VIEWER = "KeepPreferredViewer"; // NON-NLS + public static final String HIDE_KNOWN_FILES_IN_DATA_SOURCES_TREE = "HideKnownFilesInDataSourcesTree"; //NON-NLS + public static final String HIDE_KNOWN_FILES_IN_VIEWS_TREE = "HideKnownFilesInViewsTree"; //NON-NLS + public static final String HIDE_SLACK_FILES_IN_DATA_SOURCES_TREE = "HideSlackFilesInDataSourcesTree"; //NON-NLS + public static final String HIDE_SLACK_FILES_IN_VIEWS_TREE = "HideSlackFilesInViewsTree"; //NON-NLS public static final String DISPLAY_TIMES_IN_LOCAL_TIME = "DisplayTimesInLocalTime"; //NON-NLS public static final String NUMBER_OF_FILE_INGEST_THREADS = "NumberOfFileIngestThreads"; //NON-NLS public static final String IS_MULTI_USER_MODE_ENABLED = "IsMultiUserModeEnabled"; //NON-NLS @@ -55,15 +55,16 @@ public final class UserPreferences { public static final String EXTERNAL_DATABASE_NAME = "ExternalDatabaseName"; //NON-NLS public static final String EXTERNAL_DATABASE_USER = "ExternalDatabaseUsername"; //NON-NLS public static final String EXTERNAL_DATABASE_PASSWORD = "ExternalDatabasePassword"; //NON-NLS - public static final String EXTERNAL_DATABASE_TYPE = "ExternalDatabaseType"; //NON-NLS + public static final String EXTERNAL_DATABASE_TYPE = "ExternalDatabaseType"; //NON-NLS public static final String INDEXING_SERVER_HOST = "IndexingServerHost"; //NON-NLS public static final String INDEXING_SERVER_PORT = "IndexingServerPort"; //NON-NLS private static final String MESSAGE_SERVICE_PASSWORD = "MessageServicePassword"; //NON-NLS private static final String MESSAGE_SERVICE_USER = "MessageServiceUser"; //NON-NLS private static final String MESSAGE_SERVICE_HOST = "MessageServiceHost"; //NON-NLS private static final String MESSAGE_SERVICE_PORT = "MessageServicePort"; //NON-NLS - public static final String PROCESS_TIME_OUT_ENABLED = "ProcessTimeOutEnabled"; //NON-NLS - public static final String PROCESS_TIME_OUT_HOURS = "ProcessTimeOutHours"; //NON-NLS + public static final String PROCESS_TIME_OUT_ENABLED = "ProcessTimeOutEnabled"; //NON-NLS + public static final String PROCESS_TIME_OUT_HOURS = "ProcessTimeOutHours"; //NON-NLS + public static final String AGENCY_LOGO_IMAGE_PATH = "AgencyLogoImagePath"; //NON-NLS private static final int DEFAULT_PROCESS_TIMEOUT_HR = 60; private static final String DEFAULT_PORT_STRING = "61616"; private static final int DEFAULT_PORT_INT = 61616; @@ -302,7 +303,7 @@ public final class UserPreferences { public static void setIsTimeOutEnabled(boolean enabled) { preferences.putBoolean(PROCESS_TIME_OUT_ENABLED, enabled); } - + /** * Get the display name for this program * @return Name of this program @@ -310,17 +311,17 @@ public final class UserPreferences { public static String getAppName(){ return preferences.get(APP_NAME, "Autopsy"); } - + /** * Set the display name for this program - * + * * @param name Display name */ public static void setAppName(String name){ preferences.put(APP_NAME, name); } - - + + /** * Provides ability to convert text to hex text. */ diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form index 5a169b7329..dc96588a30 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form @@ -27,7 +27,7 @@ - + @@ -98,8 +98,8 @@ - - + + @@ -108,7 +108,11 @@ + + + + @@ -159,7 +163,14 @@ - + + + + + + + + @@ -358,6 +369,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java index de9a6e5429..b40592d75b 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java @@ -18,22 +18,34 @@ */ package org.sleuthkit.autopsy.corecomponents; +import java.io.File; import java.text.NumberFormat; import javax.swing.DefaultComboBoxModel; +import javax.swing.JFileChooser; import javax.swing.JFormattedTextField; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import org.netbeans.spi.options.OptionsPanelController; import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.casemodule.GeneralFilter; import org.sleuthkit.autopsy.core.UserPreferences; +import org.sleuthkit.autopsy.coreutils.ModuleSettings; +import org.sleuthkit.autopsy.report.ReportBranding; /** * Options panel that allow users to set application preferences. */ final class AutopsyOptionsPanel extends javax.swing.JPanel { + private final JFileChooser fc; + AutopsyOptionsPanel() { initComponents(); + fc = new JFileChooser(); + fc.setFileSelectionMode(JFileChooser.FILES_ONLY); + fc.setMultiSelectionEnabled(false); + fc.setFileFilter(new GeneralFilter(GeneralFilter.GRAPHIC_IMAGE_EXTS, GeneralFilter.GRAPHIC_IMG_DECR)); + int availableProcessors = Runtime.getRuntime().availableProcessors(); Integer fileIngestThreadCountChoices[]; int recommendedFileIngestThreadCount; @@ -92,7 +104,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { } }; this.jFormattedTextFieldProcTimeOutHrs.getDocument().addDocumentListener(docListener); - + } void load() { @@ -120,6 +132,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { int timeOutHrs = UserPreferences.getProcessTimeOutHrs(); jFormattedTextFieldProcTimeOutHrs.setValue((long) timeOutHrs); } + agencyLogoPathField.setText(ModuleSettings.getConfigSetting(ReportBranding.MODULE_NAME, ReportBranding.AGENCY_LOGO_PATH_PROP)); } void store() { @@ -137,8 +150,14 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { long timeOutHrs = (long) jFormattedTextFieldProcTimeOutHrs.getValue(); UserPreferences.setProcessTimeOutHrs((int) timeOutHrs); } + if (!agencyLogoPathField.getText().isEmpty()) { + File image = new File(agencyLogoPathField.getText()); + if (image.exists()) { + ModuleSettings.setConfigSetting(ReportBranding.MODULE_NAME, ReportBranding.AGENCY_LOGO_PATH_PROP, agencyLogoPathField.getText()); + } + } } - + boolean valid() { return true; } @@ -174,6 +193,9 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { dataSourcesHideSlackCB = new javax.swing.JCheckBox(); viewsHideSlackCB = new javax.swing.JCheckBox(); jLabelHideSlackFiles = new javax.swing.JLabel(); + agencyLogoImageLabel = new javax.swing.JLabel(); + agencyLogoPathField = new javax.swing.JTextField(); + browseLogosButton = new javax.swing.JButton(); jScrollPane1.setBorder(null); @@ -276,6 +298,18 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { org.openide.awt.Mnemonics.setLocalizedText(jLabelHideSlackFiles, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.jLabelHideSlackFiles.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(agencyLogoImageLabel, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.agencyLogoImageLabel.text")); // NOI18N + agencyLogoImageLabel.setToolTipText(org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.agencyLogoImageLabel.toolTipText")); // NOI18N + + agencyLogoPathField.setText(org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.agencyLogoPathField.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(browseLogosButton, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.browseLogosButton.text")); // NOI18N + browseLogosButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + browseLogosButtonActionPerformed(evt); + } + }); + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); jPanel1.setLayout(jPanel1Layout); jPanel1Layout.setHorizontalGroup( @@ -321,13 +355,17 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { .addComponent(viewsHideKnownCB)))) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addGroup(jPanel1Layout.createSequentialGroup() - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addComponent(jLabelHideSlackFiles) .addGroup(jPanel1Layout.createSequentialGroup() .addGap(10, 10, 10) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(dataSourcesHideSlackCB) - .addComponent(viewsHideSlackCB)))) + .addComponent(viewsHideSlackCB))) + .addComponent(agencyLogoImageLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(agencyLogoPathField)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(browseLogosButton) .addGap(0, 0, Short.MAX_VALUE)))) ); jPanel1Layout.setVerticalGroup( @@ -371,7 +409,13 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jFormattedTextFieldProcTimeOutHrs, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jLabelProcessTimeOutUnits))) - .addContainerGap(49, Short.MAX_VALUE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(agencyLogoImageLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(agencyLogoPathField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(browseLogosButton)) + .addContainerGap(52, Short.MAX_VALUE)) ); jScrollPane1.setViewportView(jPanel1); @@ -384,56 +428,69 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane1) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 471, Short.MAX_VALUE) ); }// //GEN-END:initComponents + private void viewsHideSlackCBActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_viewsHideSlackCBActionPerformed + firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); + }//GEN-LAST:event_viewsHideSlackCBActionPerformed + + private void dataSourcesHideSlackCBActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_dataSourcesHideSlackCBActionPerformed + firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); + }//GEN-LAST:event_dataSourcesHideSlackCBActionPerformed + + private void jFormattedTextFieldProcTimeOutHrsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jFormattedTextFieldProcTimeOutHrsActionPerformed + firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); + }//GEN-LAST:event_jFormattedTextFieldProcTimeOutHrsActionPerformed + private void jCheckBoxEnableProcTimeoutActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jCheckBoxEnableProcTimeoutActionPerformed jFormattedTextFieldProcTimeOutHrs.setEditable(jCheckBoxEnableProcTimeout.isSelected()); firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); }//GEN-LAST:event_jCheckBoxEnableProcTimeoutActionPerformed - private void useBestViewerRBActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_useBestViewerRBActionPerformed + private void numberOfFileIngestThreadsComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_numberOfFileIngestThreadsComboBoxActionPerformed firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); - }//GEN-LAST:event_useBestViewerRBActionPerformed - - private void keepCurrentViewerRBActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_keepCurrentViewerRBActionPerformed - firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); - }//GEN-LAST:event_keepCurrentViewerRBActionPerformed - - private void dataSourcesHideKnownCBActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_dataSourcesHideKnownCBActionPerformed - firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); - }//GEN-LAST:event_dataSourcesHideKnownCBActionPerformed + }//GEN-LAST:event_numberOfFileIngestThreadsComboBoxActionPerformed private void viewsHideKnownCBActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_viewsHideKnownCBActionPerformed firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); }//GEN-LAST:event_viewsHideKnownCBActionPerformed - private void useLocalTimeRBActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_useLocalTimeRBActionPerformed + private void dataSourcesHideKnownCBActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_dataSourcesHideKnownCBActionPerformed firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); - }//GEN-LAST:event_useLocalTimeRBActionPerformed + }//GEN-LAST:event_dataSourcesHideKnownCBActionPerformed private void useGMTTimeRBActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_useGMTTimeRBActionPerformed firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); }//GEN-LAST:event_useGMTTimeRBActionPerformed - private void numberOfFileIngestThreadsComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_numberOfFileIngestThreadsComboBoxActionPerformed + private void useLocalTimeRBActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_useLocalTimeRBActionPerformed firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); - }//GEN-LAST:event_numberOfFileIngestThreadsComboBoxActionPerformed + }//GEN-LAST:event_useLocalTimeRBActionPerformed - private void jFormattedTextFieldProcTimeOutHrsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jFormattedTextFieldProcTimeOutHrsActionPerformed + private void keepCurrentViewerRBActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_keepCurrentViewerRBActionPerformed firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); - }//GEN-LAST:event_jFormattedTextFieldProcTimeOutHrsActionPerformed + }//GEN-LAST:event_keepCurrentViewerRBActionPerformed - private void dataSourcesHideSlackCBActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_dataSourcesHideSlackCBActionPerformed + private void useBestViewerRBActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_useBestViewerRBActionPerformed firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); - }//GEN-LAST:event_dataSourcesHideSlackCBActionPerformed + }//GEN-LAST:event_useBestViewerRBActionPerformed - private void viewsHideSlackCBActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_viewsHideSlackCBActionPerformed - firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); - }//GEN-LAST:event_viewsHideSlackCBActionPerformed + private void browseLogosButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseLogosButtonActionPerformed + int returnState = fc.showOpenDialog(this); + if (returnState == JFileChooser.APPROVE_OPTION) { + String path = fc.getSelectedFile().getPath(); + agencyLogoPathField.setText(path); + firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); + } + + }//GEN-LAST:event_browseLogosButtonActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel agencyLogoImageLabel; + private javax.swing.JTextField agencyLogoPathField; + private javax.swing.JButton browseLogosButton; private javax.swing.ButtonGroup buttonGroup1; private javax.swing.ButtonGroup buttonGroup3; private javax.swing.JCheckBox dataSourcesHideKnownCB; diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties index 824f195ca4..ca52f6fca0 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties @@ -131,19 +131,6 @@ FXVideoPanel.pauseButton.infoLabel.playbackErr=Unable to play video. GstVideoPanel.progress.infoLabel.updateErr=Error updating video progress\: {0} GstVideoPanel.ExtractMedia.progress.buffering=Buffering {0} AboutWindowPanel.actVerboseLogging.text=Activate verbose logging -AutopsyOptionsPanel.viewsHideKnownCB.text=Views area -AutopsyOptionsPanel.dataSourcesHideKnownCB.text=Data Sources area (the directory hierarchy) -AutopsyOptionsPanel.useBestViewerRB.toolTipText=For example, change from Hex to Media when a JPEG is selected. -AutopsyOptionsPanel.useBestViewerRB.text=Change to the most specific file viewer -AutopsyOptionsPanel.useGMTTimeRB.text=Use GMT -AutopsyOptionsPanel.useLocalTimeRB.text=Use local time zone -AutopsyOptionsPanel.keepCurrentViewerRB.toolTipText=For example, stay in Hex view when a JPEG is selected. -AutopsyOptionsPanel.keepCurrentViewerRB.text=Stay on the same file viewer -AutopsyOptionsPanel.restartRequiredLabel.text=For this computer, a maximum of {0} file ingest threads should be used. Application restart required to take effect. -AutopsyOptionsPanel.jLabelSelectFile.text=When selecting a file: -AutopsyOptionsPanel.jLabelHideKnownFiles.text=Hide known files (i.e. those in the NIST NSRL) in the: -AutopsyOptionsPanel.jLabelTimeDisplay.text=When displaying times: -AutopsyOptionsPanel.jLabelNumThreads.text=Number of threads to use for file ingest: FXVideoPanel.progress.bufferingCancelled=media buffering was canceled FXVideoPanel.progress.bufferingInterrupted=media buffering was interrupted FXVideoPanel.progress.errorWritingVideoToDisk=Error writing video to disk @@ -158,10 +145,6 @@ MultiUserSettingsPanel.validationErrMsg.invalidDatabasePort=Invalid database por MultiUserSettingsPanel.validationErrMsg.invalidMessageServicePort=Invalid message service port number MultiUserSettingsPanel.validationErrMsg.invalidIndexingServerPort=Invalid Solr server port number MultiUserSettingsPanel.validationErrMsg.invalidMessgeServiceURI=Message service host and/or port not valid -AutopsyOptionsPanel.jCheckBoxEnableProcTimeout.text= -AutopsyOptionsPanel.jFormattedTextFieldProcTimeOutHrs.text=60 -AutopsyOptionsPanel.jLabelProcessTimeOutUnits.text=hour(s) -AutopsyOptionsPanel.jLabelSetProcessTimeOut.text=Enable timeout to allow modules to automatically terminate after a set amount of time\: DataContentViewerHex.goToOffsetLabel.text=Jump to Offset DataContentViewerHex.goToOffsetTextField.text= DataContentViewerHex.goToOffsetTextField.msgDlg=Invalid Offset\: {0} @@ -197,6 +180,27 @@ MultiUserSettingsPanel.lbTestSolrWarning.text= MultiUserSettingsPanel.lbTestDbWarning.text= MultiUserSettingsPanel.KeywordSearchNull=Cannot find keyword search service MultiUserSettingsPanel.InvalidPortNumber=Invalid port number +AutopsyOptionsPanel.useBestViewerRB.text=Change to the most specific file viewer AutopsyOptionsPanel.jLabelHideSlackFiles.text=Hide slack files in the: -AutopsyOptionsPanel.dataSourcesHideSlackCB.text=Data Sources area (the directory hierarchy) AutopsyOptionsPanel.viewsHideSlackCB.text=Views area +AutopsyOptionsPanel.dataSourcesHideSlackCB.text=Data Sources area (the directory hierarchy) +AutopsyOptionsPanel.jFormattedTextFieldProcTimeOutHrs.text=60 +AutopsyOptionsPanel.jLabelProcessTimeOutUnits.text=hour(s) +AutopsyOptionsPanel.jCheckBoxEnableProcTimeout.text= +AutopsyOptionsPanel.jLabelSetProcessTimeOut.text=Enable timeout to allow modules to automatically terminate after a set amount of time: +AutopsyOptionsPanel.restartRequiredLabel.text=For this computer, a maximum of {0} file ingest threads should be used. Application restart required to take effect. +AutopsyOptionsPanel.jLabelNumThreads.text=Number of threads to use for file ingest: +AutopsyOptionsPanel.viewsHideKnownCB.text=Views area +AutopsyOptionsPanel.dataSourcesHideKnownCB.text=Data Sources area (the directory hierarchy) +AutopsyOptionsPanel.jLabelHideKnownFiles.text=Hide known files (i.e. those in the NIST NSRL) in the: +AutopsyOptionsPanel.useGMTTimeRB.text=Use GMT +AutopsyOptionsPanel.useLocalTimeRB.text=Use local time zone +AutopsyOptionsPanel.jLabelTimeDisplay.text=When displaying times: +AutopsyOptionsPanel.jLabelSelectFile.text=When selecting a file: +AutopsyOptionsPanel.keepCurrentViewerRB.toolTipText=For example, stay in Hex view when a JPEG is selected. +AutopsyOptionsPanel.keepCurrentViewerRB.text=Stay on the same file viewer +AutopsyOptionsPanel.useBestViewerRB.toolTipText=For example, change from Hex to Media when a JPEG is selected. +AutopsyOptionsPanel.agencyLogoImageLabel.toolTipText= +AutopsyOptionsPanel.agencyLogoImageLabel.text=Image to use as the agency logo for HTML reports: +AutopsyOptionsPanel.browseLogosButton.text=Browse +AutopsyOptionsPanel.agencyLogoPathField.text= diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle_ja.properties index b5977466ba..ee5836ad5b 100755 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle_ja.properties @@ -108,19 +108,6 @@ FXVideoPanel.pauseButton.infoLabel.playbackErr=\u30d3\u30c7\u30aa\u3092\u518d\u7 GstVideoPanel.progress.infoLabel.updateErr=\u30d3\u30c7\u30aa\u30d7\u30ed\u30b0\u30ec\u30b9\u306e\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\uff1a {0} GstVideoPanel.ExtractMedia.progress.buffering={0}\u3092\u30d0\u30c3\u30d5\u30a1\u30ea\u30f3\u30b0\u4e2d AboutWindowPanel.actVerboseLogging.text=Verbose\u30ed\u30b0\u3092\u30a2\u30af\u30c6\u30a3\u30d9\u30fc\u30c8 -AutopsyOptionsPanel.viewsHideKnownCB.text=\u30d3\u30e5\u30fc\u30a8\u30ea\u30a2 -AutopsyOptionsPanel.dataSourcesHideKnownCB.text=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u30a8\u30ea\u30a2\uff08\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u968e\u5c64\uff09 -AutopsyOptionsPanel.useBestViewerRB.toolTipText=\u4f8b\u3048\u3070\u3001JPEG\u304c\u9078\u629e\u3055\u308c\u305f\u5834\u5408\u306b\u306fHEX\u304b\u3089\u30e1\u30c7\u30a3\u30a2\u306b\u5909\u66f4\u3059\u308b\u3002 -AutopsyOptionsPanel.useBestViewerRB.text=\u6700\u3082\u5c02\u9580\u7684\u306a\u30d5\u30a1\u30a4\u30eb\u30d3\u30e5\u30fc\u30a2\u306b\u5909\u66f4 -AutopsyOptionsPanel.useGMTTimeRB.text=GMT\u3092\u4f7f\u7528 -AutopsyOptionsPanel.useLocalTimeRB.text=\u30ed\u30fc\u30ab\u30eb\u30bf\u30a4\u30e0\u30be\u30fc\u30f3\u3092\u4f7f\u7528 -AutopsyOptionsPanel.keepCurrentViewerRB.toolTipText=\u4f8b\u3048\u3070\u3001JPEG\u304c\u9078\u629e\u3055\u308c\u305f\u5834\u5408\u306b\u305d\u306e\u307e\u307eHEX\u30d3\u30e5\u30fc\u3092\u4f7f\u7528\u3002 -AutopsyOptionsPanel.keepCurrentViewerRB.text=\u305d\u306e\u307e\u307e\u540c\u3058\u30d5\u30a1\u30a4\u30eb\u30d3\u30e5\u30fc\u30a2\u3092\u4f7f\u7528 -AutopsyOptionsPanel.restartRequiredLabel.text=\u3053\u306e\u30b3\u30f3\u30d4\u30e5\u30fc\u30bf\u30fc\u3067\u306f\u6700\u5927{0}\u306e\u30d5\u30a1\u30a4\u30eb\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30b9\u30ec\u30c3\u30c9\u3092\u4f7f\u7528\u3059\u3079\u304d\u3067\u3059\u3002\u6709\u52b9\u306b\u3059\u308b\u306b\u306f\u518d\u8d77\u52d5\u304c\u5fc5\u8981\u3067\u3059\u3002 -AutopsyOptionsPanel.jLabelSelectFile.text=\u30d5\u30a1\u30a4\u30eb\u3092\u9078\u629e\u3059\u308b\u5834\u5408\uff1a -AutopsyOptionsPanel.jLabelHideKnownFiles.text=\u65e2\u77e5\u30d5\u30a1\u30a4\u30eb\uff08NIST NSRL\u5185\u306e\uff09\u3092\u6b21\u306b\u96a0\u3059\uff1a -AutopsyOptionsPanel.jLabelTimeDisplay.text=\u6642\u9593\u3092\u8868\u793a\u3059\u308b\u5834\u5408\uff1a -AutopsyOptionsPanel.jLabelNumThreads.text=\u30d5\u30a1\u30a4\u30eb\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u306b\u4f7f\u7528\u3059\u308b\u30b9\u30ec\u30c3\u30c9\u6570\uff1a FXVideoPanel.progress.bufferingCancelled=\u30e1\u30c7\u30a3\u30a2\u306e\u30d0\u30c3\u30d5\u30a1\u30ea\u30f3\u30b0\u304c\u30ad\u30e3\u30f3\u30bb\u30eb\u3055\u308c\u307e\u3057\u305f FXVideoPanel.progress.bufferingInterrupted=\u30e1\u30c7\u30a3\u30a2\u306e\u30d0\u30c3\u30d5\u30a1\u30ea\u30f3\u30b0\u304c\u4e2d\u65ad\u3055\u308c\u307e\u3057\u305f FXVideoPanel.progress.errorWritingVideoToDisk=\u30d3\u30c7\u30aa\u3092\u30c7\u30a3\u30b9\u30af\u3078\u66f8\u304d\u8fbc\u307f\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f @@ -135,8 +122,6 @@ MultiUserSettingsPanel.validationErrMsg.invalidDatabasePort=\u7121\u52b9\u306a\u MultiUserSettingsPanel.validationErrMsg.invalidMessageServicePort=\u7121\u52b9\u306a\u30e1\u30c3\u30bb\u30fc\u30b8\u30b5\u30fc\u30d3\u30b9\u30dd\u30fc\u30c8\u756a\u53f7 MultiUserSettingsPanel.validationErrMsg.invalidIndexingServerPort=\u7121\u52b9\u306aSolr\u30b5\u30fc\u30d0\u30fc\u30dd\u30fc\u30c8\u756a\u53f7 MultiUserSettingsPanel.validationErrMsg.invalidMessgeServiceURI=\u7121\u52b9\u306a\u30e1\u30c3\u30bb\u30fc\u30b8\u30b5\u30fc\u30d3\u30b9\u30db\u30b9\u30c8\u3084\u30dd\u30fc\u30c8\u756a\u53f7 -AutopsyOptionsPanel.jLabelProcessTimeOutUnits.text=\u6642\u9593 -AutopsyOptionsPanel.jLabelSetProcessTimeOut.text=\u4e00\u5b9a\u306e\u6642\u9593\u304c\u904e\u304e\u305f\u5f8c\u306b\u81ea\u52d5\u7684\u306b\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u505c\u6b62\u3067\u304d\u308b\u3088\u3046\u306b\u30bf\u30a4\u30e0\u30a2\u30a6\u30c8\u3092\u6709\u52b9\u5316\uff1a DataContentViewerHex.goToOffsetLabel.text=\u30aa\u30d5\u30bb\u30c3\u30c8\u306b\u30b8\u30e3\u30f3\u30d7 DataContentViewerHex.goToOffsetTextField.msgDlg=\u7121\u52b9\u306a\u30aa\u30d5\u30bb\u30c3\u30c8\uff1a{0} DataContentViewerHex.setDataView.invalidOffset.negativeOffsetValue=\u8a08\u7b97\u3055\u308c\u305f\u30aa\u30d5\u30bb\u30c3\u30c8\u306b\u30b8\u30e3\u30f3\u30d7\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f @@ -164,3 +149,18 @@ DataResultViewerThumbnail.thumbnailSizeComboBox.small=\u30b5\u30e0\u30cd\u30a4\u MediaViewImagePanel.errorLabel.OOMText=\u30d5\u30a1\u30a4\u30eb\u3092\u30e1\u30c7\u30a3\u30a2\u30d3\u30e5\u30fc\u306b\u8aad\u307f\u8fbc\u3081\u307e\u305b\u3093\u3067\u3057\u305f\uff1a\u30e1\u30e2\u30ea\u4e0d\u8db3\u3002 MediaViewImagePanel.errorLabel.text=\u30d5\u30a1\u30a4\u30eb\u3092\u30e1\u30c7\u30a3\u30a2\u30d3\u30e5\u30fc\u306b\u8aad\u307f\u8fbc\u3081\u307e\u305b\u3093\u3067\u3057\u305f\u3002 MediaViewImagePanel.externalViewerButton.text=\u5916\u90e8\u30d3\u30e5\u30fc\u30a2\u30fc\u3067\u958b\u304f +AutopsyOptionsPanel.useBestViewerRB.text=\u6700\u3082\u5c02\u9580\u7684\u306a\u30d5\u30a1\u30a4\u30eb\u30d3\u30e5\u30fc\u30a2\u306b\u5909\u66f4 +AutopsyOptionsPanel.jLabelProcessTimeOutUnits.text=\u6642\u9593 +AutopsyOptionsPanel.jLabelSetProcessTimeOut.text=\u4e00\u5b9a\u306e\u6642\u9593\u304c\u904e\u304e\u305f\u5f8c\u306b\u81ea\u52d5\u7684\u306b\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u505c\u6b62\u3067\u304d\u308b\u3088\u3046\u306b\u30bf\u30a4\u30e0\u30a2\u30a6\u30c8\u3092\u6709\u52b9\u5316\uff1a +AutopsyOptionsPanel.restartRequiredLabel.text=\u3053\u306e\u30b3\u30f3\u30d4\u30e5\u30fc\u30bf\u30fc\u3067\u306f\u6700\u5927{0}\u306e\u30d5\u30a1\u30a4\u30eb\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30b9\u30ec\u30c3\u30c9\u3092\u4f7f\u7528\u3059\u3079\u304d\u3067\u3059\u3002\u6709\u52b9\u306b\u3059\u308b\u306b\u306f\u518d\u8d77\u52d5\u304c\u5fc5\u8981\u3067\u3059\u3002 +AutopsyOptionsPanel.jLabelNumThreads.text=\u30d5\u30a1\u30a4\u30eb\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u306b\u4f7f\u7528\u3059\u308b\u30b9\u30ec\u30c3\u30c9\u6570\uff1a +AutopsyOptionsPanel.viewsHideKnownCB.text=\u30d3\u30e5\u30fc\u30a8\u30ea\u30a2 +AutopsyOptionsPanel.dataSourcesHideKnownCB.text=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u30a8\u30ea\u30a2\uff08\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u968e\u5c64\uff09 +AutopsyOptionsPanel.jLabelHideKnownFiles.text=\u65e2\u77e5\u30d5\u30a1\u30a4\u30eb\uff08NIST NSRL\u5185\u306e\uff09\u3092\u6b21\u306b\u96a0\u3059\uff1a +AutopsyOptionsPanel.useGMTTimeRB.text=GMT\u3092\u4f7f\u7528 +AutopsyOptionsPanel.useLocalTimeRB.text=\u30ed\u30fc\u30ab\u30eb\u30bf\u30a4\u30e0\u30be\u30fc\u30f3\u3092\u4f7f\u7528 +AutopsyOptionsPanel.jLabelTimeDisplay.text=\u6642\u9593\u3092\u8868\u793a\u3059\u308b\u5834\u5408\uff1a +AutopsyOptionsPanel.jLabelSelectFile.text=\u30d5\u30a1\u30a4\u30eb\u3092\u9078\u629e\u3059\u308b\u5834\u5408\uff1a +AutopsyOptionsPanel.keepCurrentViewerRB.toolTipText=\u4f8b\u3048\u3070\u3001JPEG\u304c\u9078\u629e\u3055\u308c\u305f\u5834\u5408\u306b\u305d\u306e\u307e\u307eHEX\u30d3\u30e5\u30fc\u3092\u4f7f\u7528\u3002 +AutopsyOptionsPanel.keepCurrentViewerRB.text=\u305d\u306e\u307e\u307e\u540c\u3058\u30d5\u30a1\u30a4\u30eb\u30d3\u30e5\u30fc\u30a2\u3092\u4f7f\u7528 +AutopsyOptionsPanel.useBestViewerRB.toolTipText=\u4f8b\u3048\u3070\u3001JPEG\u304c\u9078\u629e\u3055\u308c\u305f\u5834\u5408\u306b\u306fHEX\u304b\u3089\u30e1\u30c7\u30a3\u30a2\u306b\u5909\u66f4\u3059\u308b\u3002 diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportBranding.java b/Core/src/org/sleuthkit/autopsy/report/ReportBranding.java index e79eba45d5..66970eae9b 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportBranding.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportBranding.java @@ -1,15 +1,15 @@ /* * * Autopsy Forensic Browser - * + * * Copyright 2013-2014 Basis Technology Corp. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -36,7 +36,7 @@ import org.sleuthkit.autopsy.coreutils.PlatformUtil; public final class ReportBranding implements ReportBrandingProviderI { //property names - private static final String AGENCY_LOGO_PATH_PROP = "AgencyLogoPath"; //NON-NLS + public static final String AGENCY_LOGO_PATH_PROP = "AgencyLogoPath"; //NON-NLS private static final String REPORT_TITLE_PROP = "ReportTitle"; //NON-NLS private static final String REPORT_FOOTER_PROP = "ReportFooter"; //NON-NLS //default settings @@ -46,7 +46,7 @@ public final class ReportBranding implements ReportBrandingProviderI { private static final String DEFAULT_REPORT_FOOTER = NbBundle .getMessage(ReportBranding.class, "ReportBranding.defaultReportFooter.text"); private String reportsBrandingDir; //dir with extracted reports branding resources - private static final String MODULE_NAME = ReportBranding.class.getSimpleName(); + public static final String MODULE_NAME = ReportBranding.class.getSimpleName(); private static final Logger logger = Logger.getLogger(ReportBranding.class.getName()); // this is static so that it can be set by another object @@ -130,7 +130,7 @@ public final class ReportBranding implements ReportBrandingProviderI { @Override public void setAgencyLogoPath(String path) { - // Use properties to persist the logo to use. + // Use properties to persist the logo to use. // Should use static variable instead ModuleSettings.setConfigSetting(MODULE_NAME, AGENCY_LOGO_PATH_PROP, path); } diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportBrandingProviderI.java b/Core/src/org/sleuthkit/autopsy/report/ReportBrandingProviderI.java index e59d6dd866..7c495823e5 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportBrandingProviderI.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportBrandingProviderI.java @@ -1,15 +1,15 @@ /* * * Autopsy Forensic Browser - * + * * Copyright 2013 Basis Technology Corp. - * + * * 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. diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java b/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java index 3a7da57e3f..6780bae314 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java @@ -1,19 +1,19 @@ /* * * Autopsy Forensic Browser - * + * * Copyright 2012-2014 Basis Technology Corp. - * + * * Copyright 2012 42six Solutions. * Contact: aebadirad 42six com * Project Contact/Architect: 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. @@ -628,7 +628,7 @@ class ReportHTML implements TableReportModule { } if (totalCount == MAX_THUMBS_PER_PAGE) { - // manually set the row count so the count of items shown in the + // manually set the row count so the count of items shown in the // navigation page reflects the number of thumbnails instead of // the number of rows. rowCount = totalCount; @@ -759,7 +759,7 @@ class ReportHTML implements TableReportModule { localFilePath.append(File.separator); localFilePath.append(fileName); - // If the local file doesn't already exist, create it now. + // If the local file doesn't already exist, create it now. // The existence check is necessary because it is possible to apply multiple tags with the same tagName to a file. File localFile = new File(localFilePath.toString()); if (!localFile.exists()) { From 42d81be8dc9df9c999ae01fe1740bab765a6051e Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Thu, 13 Apr 2017 16:30:38 -0400 Subject: [PATCH 12/37] New catch blocks added to silently catch/return on errors. --- .../embeddedfileextractor/ImageExtractor.java | 41 ++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/ImageExtractor.java b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/ImageExtractor.java index efc5ec6504..1493bb7dca 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/ImageExtractor.java +++ b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/ImageExtractor.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2015 Basis Technology Corp. + * Copyright 2011-2017 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,6 +25,8 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; +import org.apache.poi.OldFileFormatException; +import org.apache.poi.POIXMLException; import org.apache.poi.hslf.model.Picture; import org.apache.poi.hslf.usermodel.PictureData; import org.apache.poi.hslf.usermodel.SlideShow; @@ -211,6 +213,13 @@ class ImageExtractor { HWPFDocument doc = null; try { doc = new HWPFDocument(new ReadContentInputStream(af)); + } catch (OldFileFormatException ex) { + // Thrown when the document version is unsupported (Word 95 and + // older) + return null; + } catch (IOException ex) { + // Thrown when the document has issues being read. + return null; } catch (Throwable ex) { // instantiating POI containers throw RuntimeExceptions logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.docContainer.init.err", af.getName()), ex); //NON-NLS @@ -269,6 +278,12 @@ class ImageExtractor { XWPFDocument docx = null; try { docx = new XWPFDocument(new ReadContentInputStream(af)); + } catch (POIXMLException ex) { + // Thrown when document fails to load + return null; + } catch (IOException ex) { + // Thrown when the document has issues being read. + return null; } catch (Throwable ex) { // instantiating POI containers throw RuntimeExceptions logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.docxContainer.init.err", af.getName()), ex); //NON-NLS @@ -325,6 +340,12 @@ class ImageExtractor { SlideShow ppt = null; try { ppt = new SlideShow(new ReadContentInputStream(af)); + } catch (OldFileFormatException ex) { + // Thrown when the document version is unsupported + return null; + } catch (IOException ex) { + // Thrown when the document has issues being read + return null; } catch (Throwable ex) { // instantiating POI containers throw RuntimeExceptions logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.pptContainer.init.err", af.getName()), ex); //NON-NLS @@ -412,6 +433,12 @@ class ImageExtractor { XMLSlideShow pptx; try { pptx = new XMLSlideShow(new ReadContentInputStream(af)); + } catch (POIXMLException ex) { + // Thrown when document fails to load. + return null; + } catch (IOException ex) { + // Thrown when the document has issues being read + return null; } catch (Throwable ex) { // instantiating POI containers throw RuntimeExceptions logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.pptxContainer.init.err", af.getName()), ex); //NON-NLS @@ -476,6 +503,12 @@ class ImageExtractor { Workbook xls; try { xls = new HSSFWorkbook(new ReadContentInputStream(af)); + } catch (OldFileFormatException ex) { + // Thrown when the document version is unsupported + return null; + } catch (IOException ex) { + // Thrown when the document has issues being read + return null; } catch (Throwable ex) { // instantiating POI containers throw RuntimeExceptions logger.log(Level.WARNING, String.format("%s%s", NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.xlsContainer.init.err", af.getName()), af.getName()), ex); //NON-NLS @@ -537,6 +570,12 @@ class ImageExtractor { Workbook xlsx; try { xlsx = new XSSFWorkbook(new ReadContentInputStream(af)); + } catch (POIXMLException ex) { + // Thrown when document fails to load. + return null; + } catch (IOException ex) { + // Thrown when the document has issues being read + return null; } catch (Throwable ex) { // instantiating POI containers throw RuntimeExceptions logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.xlsxContainer.init.err", af.getName()), ex); //NON-NLS From 805bb381d73c1eeb3c3da7bf2597f63ea7af2989 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 14 Apr 2017 15:59:46 -0400 Subject: [PATCH 13/37] 2453 prevent possible hang from cancelling add image inhumanly fast --- .../autopsy/casemodule/AddImageTask.java | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java index 05668a5087..6b6fa63e35 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java @@ -61,7 +61,7 @@ class AddImageTask implements Runnable { * TODO (AUT-2021): Merge SleuthkitJNI.AddImageProcess and AddImageTask */ private final Object tskAddImageProcessLock; - private boolean tskAddImageProcessStopped; + volatile private boolean tskAddImageProcessStopped; private SleuthkitJNI.CaseDbHandle.AddImageProcess tskAddImageProcess; /** @@ -77,8 +77,9 @@ class AddImageTask implements Runnable { * java.util.TimeZone.getID. * @param ignoreFatOrphanFiles Whether to parse orphans if the image has a * FAT filesystem. - * @param imageWriterPath Path that a copy of the image should be written to. - * Use empty string to disable image writing + * @param imageWriterPath Path that a copy of the image should be + * written to. Use empty string to disable image + * writing * @param progressMonitor Progress monitor to report progress during * processing. * @param callback Callback to call when processing is done. @@ -104,7 +105,7 @@ class AddImageTask implements Runnable { progressMonitor.setProgress(0); Case currentCase = Case.getCurrentCase(); String imageWriterPath = ""; - if(imageWriterSettings != null){ + if (imageWriterSettings != null) { imageWriterPath = imageWriterSettings.getPath(); } List errorMessages = new ArrayList<>(); @@ -112,8 +113,12 @@ class AddImageTask implements Runnable { try { currentCase.getSleuthkitCase().acquireExclusiveLock(); synchronized (tskAddImageProcessLock) { - tskAddImageProcess = currentCase.getSleuthkitCase().makeAddImageProcess(timeZone, true, - ignoreFatOrphanFiles, imageWriterPath); + if (!tskAddImageProcessStopped) { //if we have already cancelled don't bother making an addImageProcess + tskAddImageProcess = currentCase.getSleuthkitCase().makeAddImageProcess(timeZone, true, + ignoreFatOrphanFiles, imageWriterPath); + } else { + return; //we have already cancelled so we do not want to add the image, returning will execute the finally block + } } Thread progressUpdateThread = new Thread(new ProgressUpdater(progressMonitor, tskAddImageProcess)); progressUpdateThread.start(); @@ -142,6 +147,7 @@ class AddImageTask implements Runnable { */ public void cancelTask() { synchronized (tskAddImageProcessLock) { + tskAddImageProcessStopped = true; if (null != tskAddImageProcess) { try { /* @@ -153,7 +159,7 @@ class AddImageTask implements Runnable { * called. */ tskAddImageProcess.stop(); - tskAddImageProcessStopped = true; + } catch (TskCoreException ex) { logger.log(Level.SEVERE, String.format("Error cancelling adding image %s to the case database", imagePath), ex); //NON-NLS } @@ -213,13 +219,13 @@ class AddImageTask implements Runnable { if (!verificationError.isEmpty()) { errorMessages.add(verificationError); } - if(imageWriterSettings != null){ - ImageWriterService.createImageWriter(imageId, imageWriterSettings); + if (imageWriterSettings != null) { + ImageWriterService.createImageWriter(imageId, imageWriterSettings); } newDataSources.add(newImage); } else { String errorMessage = String.format("Error commiting adding image %s to the case database, no object id returned", imagePath); //NON-NLS - logger.log(Level.SEVERE, errorMessage); + logger.log(Level.SEVERE, errorMessage); errorMessages.add(errorMessage); criticalErrorOccurred = true; } From 25e091229e32d9dcd0382c026c8abe8a6221be1c Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Wed, 19 Apr 2017 12:31:05 -0400 Subject: [PATCH 14/37] Added 'Remove File Tag' and 'Remove Result Tag' options. --- .../AddBlackboardArtifactTagAction.java | 6 + .../autopsy/actions/AddContentTagAction.java | 14 +- .../autopsy/actions/Bundle.properties | 17 -- .../autopsy/actions/Bundle_ja.properties | 104 ++++--- .../DeleteBlackboardArtifactTagAction.java | 80 +++-- .../actions/DeleteContentTagAction.java | 64 +++- ...DeleteFileBlackboardArtifactTagAction.java | 205 +++++++++++++ .../actions/DeleteFileContentTagAction.java | 202 +++++++++++++ .../datamodel/DataModelActionsFactory.java | 275 ++++++++++++------ .../autopsy/datamodel/DirectoryNode.java | 39 ++- .../sleuthkit/autopsy/datamodel/FileNode.java | 15 +- .../autopsy/datamodel/LayoutFileNode.java | 14 +- .../autopsy/datamodel/LocalFileNode.java | 16 +- .../autopsy/datamodel/SlackFileNode.java | 13 +- .../directorytree/DataResultFilterNode.java | 59 ++-- .../ExplorerNodeActionVisitor.java | 89 ++++-- .../imagegallery/actions/DeleteTagAction.java | 164 +++++++++++ .../gui/drawableviews/DrawableTileBase.java | 11 +- .../KeywordSearchFilterNode.java | 32 +- 19 files changed, 1161 insertions(+), 258 deletions(-) create mode 100755 Core/src/org/sleuthkit/autopsy/actions/DeleteFileBlackboardArtifactTagAction.java create mode 100755 Core/src/org/sleuthkit/autopsy/actions/DeleteFileContentTagAction.java create mode 100755 ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/DeleteTagAction.java diff --git a/Core/src/org/sleuthkit/autopsy/actions/AddBlackboardArtifactTagAction.java b/Core/src/org/sleuthkit/autopsy/actions/AddBlackboardArtifactTagAction.java index 4ac2e31ab1..85d5b7b668 100755 --- a/Core/src/org/sleuthkit/autopsy/actions/AddBlackboardArtifactTagAction.java +++ b/Core/src/org/sleuthkit/autopsy/actions/AddBlackboardArtifactTagAction.java @@ -34,6 +34,12 @@ import org.sleuthkit.datamodel.TskCoreException; /** * Instances of this Action allow users to apply tags to blackboard artifacts. */ +@NbBundle.Messages({ + "AddBlackboardArtifactTagAction.singularTagResult=Tag Result", + "AddBlackboardArtifactTagAction.pluralTagResult=Tag Results", + "AddBlackboardArtifactTagAction.unableToTag.msg=Unable to tag {0}.", + "AddBlackboardArtifactTagAction.taggingErr=Tagging Error" +}) public class AddBlackboardArtifactTagAction extends AddTagAction { // This class is a singleton to support multi-selection of nodes, since diff --git a/Core/src/org/sleuthkit/autopsy/actions/AddContentTagAction.java b/Core/src/org/sleuthkit/autopsy/actions/AddContentTagAction.java index c386858aa4..d6442c9b0a 100755 --- a/Core/src/org/sleuthkit/autopsy/actions/AddContentTagAction.java +++ b/Core/src/org/sleuthkit/autopsy/actions/AddContentTagAction.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2016 Basis Technology Corp. + * Copyright 2011-2017 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -29,15 +29,21 @@ import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Content; -import org.sleuthkit.datamodel.FsContent; -import org.sleuthkit.datamodel.LayoutFile; -import org.sleuthkit.datamodel.LocalFile; import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TskCoreException; /** * Instances of this Action allow users to apply tags to content. */ +@NbBundle.Messages({ + "AddContentTagAction.singularTagFile=Tag File", + "AddContentTagAction.pluralTagFile=Tag Files", + "AddContentTagAction.unableToTag.msg=Unable to tag {0}, not a regular file.", + "AddContentTagAction.cannotApplyTagErr=Cannot Apply Tag", + "AddContentTagAction.unableToTag.msg2=Unable to tag {0}.", + "AddContentTagAction.taggingErr=Tagging Error", + "AddContentTagAction.tagExists={0} has been tagged as {1}. Cannot reapply the same tag." +}) public class AddContentTagAction extends AddTagAction { // This class is a singleton to support multi-selection of nodes, since diff --git a/Core/src/org/sleuthkit/autopsy/actions/Bundle.properties b/Core/src/org/sleuthkit/autopsy/actions/Bundle.properties index 6314dc6f40..28d4e4006a 100755 --- a/Core/src/org/sleuthkit/autopsy/actions/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/actions/Bundle.properties @@ -14,29 +14,12 @@ GetTagNameAndCommentDialog.commentLabel.text=Comment: GetTagNameAndCommentDialog.cancelButton.text=Cancel GetTagNameAndCommentDialog.tagCombo.toolTipText=Select tag to use GetTagNameAndCommentDialog.tagLabel.text=Tag: -AddBlackboardArtifactTagAction.singularTagResult=Tag Result -AddBlackboardArtifactTagAction.pluralTagResult=Tag Results -AddBlackboardArtifactTagAction.unableToTag.msg=Unable to tag {0}. -AddBlackboardArtifactTagAction.taggingErr=Tagging Error -AddContentTagAction.singularTagFile=Tag File -AddContentTagAction.pluralTagFile=Tag Files -AddContentTagAction.unableToTag.msg=Unable to tag {0}, not a regular file. -AddContentTagAction.cannotApplyTagErr=Cannot Apply Tag -AddContentTagAction.unableToTag.msg2=Unable to tag {0}. -AddContentTagAction.taggingErr=Tagging Error -AddContentTagAction.tagExists={0} has been tagged as {1}. Cannot reapply the same tag. AddTagAction.bookmarkFile=Bookmark file AddTagAction.quickTag=Quick Tag AddTagAction.noTags=No tags AddTagAction.newTag=New Tag... AddTagAction.tagAndComment=Tag and Comment... AddBookmarkTagAction.bookmark.text=Bookmark -DeleteBlackboardArtifactTagAction.deleteTags=Delete Tag(s) -DeleteBlackboardArtifactTagAction.unableToDelTag.msg=Unable to delete tag {0}. -DeleteBlackboardArtifactTagAction.tagDelErr=Tag Deletion Error -DeleteContentTagAction.deleteTags=Delete Tag(s) -DeleteContentTagAction.unableToDelTag.msg=Unable to delete tag {0}. -DeleteContentTagAction.tagDelErr=Tag Deletion Error GetTagNameAndCommentDialog.noTags=No Tags GetTagNameAndCommentDialog.createTag=Create Tag GetTagNameAndCommentDialog.cancelName=cancel diff --git a/Core/src/org/sleuthkit/autopsy/actions/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/actions/Bundle_ja.properties index 28b9af065b..195d12c695 100644 --- a/Core/src/org/sleuthkit/autopsy/actions/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/actions/Bundle_ja.properties @@ -1,57 +1,51 @@ -GetTagNameDialog.cancelButton.text=\u30AD\u30E3\u30F3\u30BB\u30EB +GetTagNameDialog.cancelButton.text=\u30ad\u30e3\u30f3\u30bb\u30eb GetTagNameDialog.okButton.text=OK -GetTagNameDialog.preexistingLabel.text=\u65E2\u5B58\u30BF\u30B0\uFF1A -GetTagNameDialog.newTagPanel.border.title=\u65B0\u898F\u30BF\u30B0 -GetTagNameDialog.tagNameLabel.text=\u30BF\u30B0\u540D\uFF1A -GetTagNameAndCommentDialog.newTagButton.text=\u65B0\u898F\u30BF\u30B0 +GetTagNameDialog.preexistingLabel.text=\u65e2\u5b58\u30bf\u30b0\uff1a +GetTagNameDialog.newTagPanel.border.title=\u65b0\u898f\u30bf\u30b0 +GetTagNameDialog.tagNameLabel.text=\u30bf\u30b0\u540d\uff1a +GetTagNameAndCommentDialog.newTagButton.text=\u65b0\u898f\u30bf\u30b0 GetTagNameAndCommentDialog.okButton.text=OK -GetTagNameAndCommentDialog.commentText.toolTipText=\u30BF\u30B0\u306E\u30AA\u30D7\u30B7\u30E7\u30CA\u30EB\u306E\u30B3\u30E1\u30F3\u30C8\u3092\u5165\u529B\u307E\u305F\u306F\u7A7A\u6B04\u306B\u3057\u3066\u304F\u3060\u3055\u3044 -GetTagNameAndCommentDialog.commentLabel.text=\u30B3\u30E1\u30F3\u30C8\uFF1A -GetTagNameAndCommentDialog.cancelButton.text=\u30AD\u30E3\u30F3\u30BB\u30EB -GetTagNameAndCommentDialog.tagCombo.toolTipText=\u4F7F\u7528\u3059\u308B\u30BF\u30B0\u3092\u9078\u629E -GetTagNameAndCommentDialog.tagLabel.text=\u30BF\u30B0\uFF1A -AddBlackboardArtifactTagAction.singularTagResult=\u7D50\u679C\u306B\u30BF\u30B0\u3092\u8FFD\u52A0 -AddBlackboardArtifactTagAction.pluralTagResult=\u7D50\u679C\u306B\u30BF\u30B0\u3092\u8FFD\u52A0 -AddBlackboardArtifactTagAction.unableToTag.msg={0}\u306B\u30BF\u30B0\u3092\u8FFD\u52A0\u3067\u304D\u307E\u305B\u3093\u3002 -AddBlackboardArtifactTagAction.taggingErr=\u30BF\u30B0\u4ED8\u3051\u30A8\u30E9\u30FC -AddContentTagAction.singularTagFile=\u30D5\u30A1\u30A4\u30EB\u306B\u30BF\u30B0\u3092\u8FFD\u52A0 -AddContentTagAction.pluralTagFile=\u30D5\u30A1\u30A4\u30EB\u306B\u30BF\u30B0\u3092\u8FFD\u52A0 -AddContentTagAction.unableToTag.msg={0}\u306B\u30BF\u30B0\u3092\u8FFD\u52A0\u3067\u304D\u307E\u305B\u3093\u3002\u901A\u5E38\u30D5\u30A1\u30A4\u30EB\u3067\u306F\u3042\u308A\u307E\u305B\u3093\u3002 -AddContentTagAction.unableToTag.msg2={0}\u306B\u30BF\u30B0\u3092\u8FFD\u52A0\u3067\u304D\u307E\u305B\u3093\u3002 -AddContentTagAction.taggingErr=\u30BF\u30B0\u4ED8\u3051\u30A8\u30E9\u30FC -AddTagAction.quickTag=\u30AF\u30A4\u30C3\u30AF\u30BF\u30B0 -AddTagAction.noTags=\u30BF\u30B0\u7121\u3057 -AddTagAction.newTag=\u65B0\u898F\u30BF\u30B0\u2026 -AddTagAction.tagAndComment=\u30BF\u30B0\u3068\u30B3\u30E1\u30F3\u30C8\u3092\u8FFD\u52A0\u2026 -DeleteBlackboardArtifactTagAction.deleteTags=\u30BF\u30B0\u3092\u524A\u9664 -DeleteBlackboardArtifactTagAction.unableToDelTag.msg=\u30BF\u30B0{0}\u3092\u524A\u9664\u3067\u304D\u307E\u305B\u3093\u3002 -DeleteBlackboardArtifactTagAction.tagDelErr=\u30BF\u30B0\u524A\u9664\u30A8\u30E9\u30FC -DeleteContentTagAction.deleteTags=\u30BF\u30B0\u3092\u524A\u9664 -DeleteContentTagAction.unableToDelTag.msg=\u30BF\u30B0{0}\u3092\u524A\u9664\u3067\u304D\u307E\u305B\u3093\u3002 -DeleteContentTagAction.tagDelErr=\u30BF\u30B0\u306E\u524A\u9664\u30A8\u30E9\u30FC -GetTagNameAndCommentDialog.noTags=\u30BF\u30B0\u7121\u3057 -GetTagNameAndCommentDialog.createTag=\u30BF\u30B0\u3092\u4F5C\u6210 -GetTagNameAndCommentDialog.cancelName=\u30AD\u30E3\u30F3\u30BB\u30EB -GetTagNameDialog.createTag=\u30BF\u30B0\u3092\u4F5C\u6210 -GetTagNameDialog.cancelName=\u30AD\u30E3\u30F3\u30BB\u30EB -GetTagNameDialog.mustSupplyTtagName.msg=\u30BF\u30B0\u540D\u3092\u6307\u5B9A\u3057\u306A\u3051\u308C\u3070\u5148\u306B\u9032\u3081\u307E\u305B\u3093\u3002 -GetTagNameDialog.tagNameErr=\u30BF\u30B0\u540D -GetTagNameDialog.illegalCharsErr=\u4F7F\u7528\u3067\u304D\u306A\u3044\u6587\u5B57 -GetTagNameDialog.unableToAddTagNameToCase.msg=\u30BF\u30B0\u540D{0}\u3092\u30B1\u30FC\u30B9\u306B\u8FFD\u52A0\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002 -GetTagNameDialog.taggingErr=\u30BF\u30B0\u4ED8\u3051\u30A8\u30E9\u30FC -GetTagNameDialog.tagNameAlreadyDef.msg=\u30BF\u30B0\u540D{0}\u306F\u65E2\u306B\u5B9A\u7FA9\u3055\u308C\u3066\u3044\u307E\u3059\u3002 -GetTagNameDialog.dupTagErr=\u30BF\u30B0\u306E\u91CD\u8907\u30A8\u30E9\u30FC -AddContentTagAction.cannotApplyTagErr=\u30BF\u30B0\u3092\u9069\u7528\u3067\u304D\u307E\u305B\u3093 -OpenLogFolder.error1=\u30ED\u30B0\u30D5\u30A1\u30A4\u30EB\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F\uFF1A{0} -CTL_OpenLogFolder=\u30ED\u30B0\u30D5\u30A9\u30EB\u30C0\u3092\u958B\u304F -ShowIngestProgressSnapshotAction.actionName.text=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30D7\u30ED\u30B0\u30EC\u30B9\u306E\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\u3092\u53D6\u5F97 -CTL_OpenPythonModulesFolderAction=Python\u30D7\u30E9\u30B0\u30A4\u30F3 -OpenPythonModulesFolderAction.actionName.text=Python\u30D7\u30E9\u30B0\u30A4\u30F3 -OpenPythonModulesFolderAction.errorMsg.folderNotFound=Python\u30D7\u30E9\u30B0\u30A4\u30F3\u30D5\u30A9\u30EB\u30C0\u30FC\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F\uFF1A{0} -AddContentTagAction.tagExists={0}\u306F\u65E2\u306B{1}\u3068\u30BF\u30B0\u3055\u308C\u3066\u3044\u307E\u3059\u3002\u540C\u3058\u30BF\u30B0\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093\u3002 -OpenLogFolder.CouldNotOpenLogFolder=\u30ED\u30B0\u30D5\u30A9\u30EB\u30C0\u30FC\u3092\u958B\u3051\u307E\u305B\u3093\u3067\u3057\u305F -CTL_OpenOutputFolder=\u30A2\u30A6\u30C8\u30D7\u30C3\u30C8\u30D5\u30A9\u30EB\u30C0\u3092\u3092\u958B\u304F -OpenOutputFolder.error1=\u6B21\u306E\u30A2\u30A6\u30C8\u30D7\u30C3\u30C8\u30D5\u30A9\u30EB\u30C0\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F\uFF1A{0} -OpenOutputFolder.noCaseOpen=\u30AA\u30FC\u30D7\u30F3\u30B1\u30FC\u30B9\u304C\u306A\u3044\u306E\u3067\u3001\u4F5C\u696D\u4E2D\u306E\u30A2\u30A6\u30C8\u30D7\u30C3\u30C8\u30D5\u30A9\u30EB\u30C0\u304C\u3042\u308A\u307E\u305B\u3093\u3002 -GetTagNameDialog.illegalChars.msg=\u4F7F\u7528\u3067\u304D\u306A\u3044\u6587\u5B57\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\u3002\n\u6B21\u306E\u6587\u5B57\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093\uFF1A\\ \: * ? " < > | -OpenOutputFolder.CouldNotOpenOutputFolder=\u30A2\u30A6\u30C8\u30D7\u30C3\u30C8\u30D5\u30A9\u30EB\u30C0\u304C\u304C\u958B\u3051\u307E\u305B\u3093\u3067\u3057\u305F \ No newline at end of file +GetTagNameAndCommentDialog.commentText.toolTipText=\u30bf\u30b0\u306e\u30aa\u30d7\u30b7\u30e7\u30ca\u30eb\u306e\u30b3\u30e1\u30f3\u30c8\u3092\u5165\u529b\u307e\u305f\u306f\u7a7a\u6b04\u306b\u3057\u3066\u304f\u3060\u3055\u3044 +GetTagNameAndCommentDialog.commentLabel.text=\u30b3\u30e1\u30f3\u30c8\uff1a +GetTagNameAndCommentDialog.cancelButton.text=\u30ad\u30e3\u30f3\u30bb\u30eb +GetTagNameAndCommentDialog.tagCombo.toolTipText=\u4f7f\u7528\u3059\u308b\u30bf\u30b0\u3092\u9078\u629e +GetTagNameAndCommentDialog.tagLabel.text=\u30bf\u30b0\uff1a +AddBlackboardArtifactTagAction.singularTagResult=\u7d50\u679c\u306b\u30bf\u30b0\u3092\u8ffd\u52a0 +AddBlackboardArtifactTagAction.pluralTagResult=\u7d50\u679c\u306b\u30bf\u30b0\u3092\u8ffd\u52a0 +AddBlackboardArtifactTagAction.unableToTag.msg={0}\u306b\u30bf\u30b0\u3092\u8ffd\u52a0\u3067\u304d\u307e\u305b\u3093\u3002 +AddBlackboardArtifactTagAction.taggingErr=\u30bf\u30b0\u4ed8\u3051\u30a8\u30e9\u30fc +AddContentTagAction.singularTagFile=\u30d5\u30a1\u30a4\u30eb\u306b\u30bf\u30b0\u3092\u8ffd\u52a0 +AddContentTagAction.pluralTagFile=\u30d5\u30a1\u30a4\u30eb\u306b\u30bf\u30b0\u3092\u8ffd\u52a0 +AddContentTagAction.unableToTag.msg={0}\u306b\u30bf\u30b0\u3092\u8ffd\u52a0\u3067\u304d\u307e\u305b\u3093\u3002\u901a\u5e38\u30d5\u30a1\u30a4\u30eb\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002 +AddContentTagAction.unableToTag.msg2={0}\u306b\u30bf\u30b0\u3092\u8ffd\u52a0\u3067\u304d\u307e\u305b\u3093\u3002 +AddContentTagAction.taggingErr=\u30bf\u30b0\u4ed8\u3051\u30a8\u30e9\u30fc +AddTagAction.quickTag=\u30af\u30a4\u30c3\u30af\u30bf\u30b0 +AddTagAction.noTags=\u30bf\u30b0\u7121\u3057 +AddTagAction.newTag=\u65b0\u898f\u30bf\u30b0\u2026 +AddTagAction.tagAndComment=\u30bf\u30b0\u3068\u30b3\u30e1\u30f3\u30c8\u3092\u8ffd\u52a0\u2026 +GetTagNameAndCommentDialog.noTags=\u30bf\u30b0\u7121\u3057 +GetTagNameAndCommentDialog.createTag=\u30bf\u30b0\u3092\u4f5c\u6210 +GetTagNameAndCommentDialog.cancelName=\u30ad\u30e3\u30f3\u30bb\u30eb +GetTagNameDialog.createTag=\u30bf\u30b0\u3092\u4f5c\u6210 +GetTagNameDialog.cancelName=\u30ad\u30e3\u30f3\u30bb\u30eb +GetTagNameDialog.mustSupplyTtagName.msg=\u30bf\u30b0\u540d\u3092\u6307\u5b9a\u3057\u306a\u3051\u308c\u3070\u5148\u306b\u9032\u3081\u307e\u305b\u3093\u3002 +GetTagNameDialog.tagNameErr=\u30bf\u30b0\u540d +GetTagNameDialog.illegalCharsErr=\u4f7f\u7528\u3067\u304d\u306a\u3044\u6587\u5b57 +GetTagNameDialog.unableToAddTagNameToCase.msg=\u30bf\u30b0\u540d{0}\u3092\u30b1\u30fc\u30b9\u306b\u8ffd\u52a0\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +GetTagNameDialog.taggingErr=\u30bf\u30b0\u4ed8\u3051\u30a8\u30e9\u30fc +GetTagNameDialog.tagNameAlreadyDef.msg=\u30bf\u30b0\u540d{0}\u306f\u65e2\u306b\u5b9a\u7fa9\u3055\u308c\u3066\u3044\u307e\u3059\u3002 +GetTagNameDialog.dupTagErr=\u30bf\u30b0\u306e\u91cd\u8907\u30a8\u30e9\u30fc +AddContentTagAction.cannotApplyTagErr=\u30bf\u30b0\u3092\u9069\u7528\u3067\u304d\u307e\u305b\u3093 +OpenLogFolder.error1=\u30ed\u30b0\u30d5\u30a1\u30a4\u30eb\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f\uff1a{0} +CTL_OpenLogFolder=\u30ed\u30b0\u30d5\u30a9\u30eb\u30c0\u3092\u958b\u304f +ShowIngestProgressSnapshotAction.actionName.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30d7\u30ed\u30b0\u30ec\u30b9\u306e\u30b9\u30ca\u30c3\u30d7\u30b7\u30e7\u30c3\u30c8\u3092\u53d6\u5f97 +CTL_OpenPythonModulesFolderAction=Python\u30d7\u30e9\u30b0\u30a4\u30f3 +OpenPythonModulesFolderAction.actionName.text=Python\u30d7\u30e9\u30b0\u30a4\u30f3 +OpenPythonModulesFolderAction.errorMsg.folderNotFound=Python\u30d7\u30e9\u30b0\u30a4\u30f3\u30d5\u30a9\u30eb\u30c0\u30fc\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f\uff1a{0} +AddContentTagAction.tagExists={0}\u306f\u65e2\u306b{1}\u3068\u30bf\u30b0\u3055\u308c\u3066\u3044\u307e\u3059\u3002\u540c\u3058\u30bf\u30b0\u306f\u4f7f\u7528\u3067\u304d\u307e\u305b\u3093\u3002 +OpenLogFolder.CouldNotOpenLogFolder=\u30ed\u30b0\u30d5\u30a9\u30eb\u30c0\u30fc\u3092\u958b\u3051\u307e\u305b\u3093\u3067\u3057\u305f +CTL_OpenOutputFolder=\u30a2\u30a6\u30c8\u30d7\u30c3\u30c8\u30d5\u30a9\u30eb\u30c0\u3092\u3092\u958b\u304f +OpenOutputFolder.error1=\u6b21\u306e\u30a2\u30a6\u30c8\u30d7\u30c3\u30c8\u30d5\u30a9\u30eb\u30c0\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f\uff1a{0} +OpenOutputFolder.noCaseOpen=\u30aa\u30fc\u30d7\u30f3\u30b1\u30fc\u30b9\u304c\u306a\u3044\u306e\u3067\u3001\u4f5c\u696d\u4e2d\u306e\u30a2\u30a6\u30c8\u30d7\u30c3\u30c8\u30d5\u30a9\u30eb\u30c0\u304c\u3042\u308a\u307e\u305b\u3093\u3002 +GetTagNameDialog.illegalChars.msg=\u4f7f\u7528\u3067\u304d\u306a\u3044\u6587\u5b57\u304c\u542b\u307e\u308c\u3066\u3044\u307e\u3059\u3002\n\u6b21\u306e\u6587\u5b57\u306f\u4f7f\u7528\u3067\u304d\u307e\u305b\u3093\uff1a\\ \: * ? " < > | +OpenOutputFolder.CouldNotOpenOutputFolder=\u30a2\u30a6\u30c8\u30d7\u30c3\u30c8\u30d5\u30a9\u30eb\u30c0\u304c\u304c\u958b\u3051\u307e\u305b\u3093\u3067\u3057\u305f \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/actions/DeleteBlackboardArtifactTagAction.java b/Core/src/org/sleuthkit/autopsy/actions/DeleteBlackboardArtifactTagAction.java index 2ce4ebd666..cda4eb39a8 100755 --- a/Core/src/org/sleuthkit/autopsy/actions/DeleteBlackboardArtifactTagAction.java +++ b/Core/src/org/sleuthkit/autopsy/actions/DeleteBlackboardArtifactTagAction.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013-2016 Basis Technology Corp. + * Copyright 2013-2017 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,26 +20,41 @@ package org.sleuthkit.autopsy.actions; import java.awt.event.ActionEvent; import java.util.Collection; +import java.util.HashSet; +import java.util.concurrent.ExecutionException; import java.util.logging.Level; +import javafx.application.Platform; +import javafx.scene.control.Alert; import javax.swing.AbstractAction; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; +import javax.swing.SwingWorker; import org.openide.util.NbBundle; import org.openide.util.Utilities; import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.casemodule.services.TagsManager; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifactTag; +import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TskCoreException; /** * Instances of this Action allow users to delete tags applied to blackboard * artifacts. */ +@NbBundle.Messages({ + "DeleteBlackboardArtifactTagAction.deleteTag=Delete Tag", + "DeleteBlackboardArtifactTagAction.unableToDelTag.msg=Unable to delete tag {0}.", + "DeleteBlackboardArtifactTagAction.tagDelErr=Tag Deletion Error" +}) public class DeleteBlackboardArtifactTagAction extends AbstractAction { + + private static final Logger LOGGER = Logger.getLogger(DeleteBlackboardArtifactTagAction.class.getName()); private static final long serialVersionUID = 1L; private static final String MENU_TEXT = NbBundle.getMessage(DeleteBlackboardArtifactTagAction.class, - "DeleteBlackboardArtifactTagAction.deleteTags"); + "DeleteBlackboardArtifactTagAction.deleteTag"); // This class is a singleton to support multi-selection of nodes, since // org.openide.nodes.NodeOp.findActions(Node[] nodes) will only pick up an Action if every @@ -65,7 +80,7 @@ public class DeleteBlackboardArtifactTagAction extends AbstractAction { try { Case.getCurrentCase().getServices().getTagsManager().deleteBlackboardArtifactTag(tag); } catch (TskCoreException ex) { - Logger.getLogger(AddContentTagAction.class.getName()).log(Level.SEVERE, "Error deleting tag", ex); //NON-NLS + Logger.getLogger(DeleteBlackboardArtifactTagAction.class.getName()).log(Level.SEVERE, "Error deleting tag", ex); //NON-NLS SwingUtilities.invokeLater(() -> { JOptionPane.showMessageDialog(null, NbBundle.getMessage(this.getClass(), @@ -81,28 +96,47 @@ public class DeleteBlackboardArtifactTagAction extends AbstractAction { }).start(); } - /** - * Deprecated, use actionPerformed() instead. - * - * @param event The event associated with the action. - * - * @deprecated - */ - @Deprecated - protected void doAction(ActionEvent event) { - actionPerformed(event); + protected String getActionDisplayName() { + return MENU_TEXT; } - /** - * Deprecated, does nothing. The TagManager methods to create, update or - * delete tags now notify the case that there is a tag change. The case then - * publishes an event that triggers a refresh of the tags sub-tree in the - * tree view. - * - * @deprecated - */ - @Deprecated - protected void refreshDirectoryTree() { + @NbBundle.Messages({"# {0} - artifactID", + "DeleteBlackboardArtifactTagAction.deleteTag.alert=Unable to untag artifact {0}."}) + protected void deleteTag(TagName tagName, BlackboardArtifactTag artifactTag, long artifactId) { + new SwingWorker() { + + @Override + protected Void doInBackground() throws Exception { + TagsManager tagsManager = Case.getCurrentCase().getServices().getTagsManager(); + + // Pull the from the global context to avoid unnecessary calls + // to the database. + final Collection selectedFilesList = + new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class)); + AbstractFile file = selectedFilesList.iterator().next(); + + try { + LOGGER.log(Level.INFO, "Removing tag {0} from {1}", new Object[]{tagName.getDisplayName(), file.getName()}); //NON-NLS + tagsManager.deleteBlackboardArtifactTag(artifactTag); + } catch (TskCoreException tskCoreException) { + LOGGER.log(Level.SEVERE, "Error untagging artifact", tskCoreException); //NON-NLS + Platform.runLater(() -> + new Alert(Alert.AlertType.ERROR, Bundle.DeleteBlackboardArtifactTagAction_deleteTag_alert(artifactId)).show() + ); + } + return null; + } + + @Override + protected void done() { + super.done(); + try { + get(); + } catch (InterruptedException | ExecutionException ex) { + LOGGER.log(Level.SEVERE, "Unexpected exception while untagging artifact", ex); //NON-NLS + } + } + }.execute(); } } diff --git a/Core/src/org/sleuthkit/autopsy/actions/DeleteContentTagAction.java b/Core/src/org/sleuthkit/autopsy/actions/DeleteContentTagAction.java index aabc483247..afa7e49506 100755 --- a/Core/src/org/sleuthkit/autopsy/actions/DeleteContentTagAction.java +++ b/Core/src/org/sleuthkit/autopsy/actions/DeleteContentTagAction.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013-2015 Basis Technology Corp. + * Copyright 2013-2017 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,25 +20,40 @@ package org.sleuthkit.autopsy.actions; import java.awt.event.ActionEvent; import java.util.Collection; +import java.util.HashSet; +import java.util.concurrent.ExecutionException; import java.util.logging.Level; +import javafx.application.Platform; +import javafx.scene.control.Alert; import javax.swing.AbstractAction; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; +import javax.swing.SwingWorker; import org.openide.util.NbBundle; import org.openide.util.Utilities; import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.casemodule.services.TagsManager; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.ContentTag; +import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TskCoreException; /** * Instances of this Action allow users to delete tags applied to content. */ +@NbBundle.Messages({ + "DeleteContentTagAction.deleteTag=Delete Tag", + "DeleteContentTagAction.unableToDelTag.msg=Unable to delete tag {0}.", + "DeleteContentTagAction.tagDelErr=Tag Deletion Error" +}) public class DeleteContentTagAction extends AbstractAction { + + private static final Logger LOGGER = Logger.getLogger(DeleteContentTagAction.class.getName()); private static final long serialVersionUID = 1L; private static final String MENU_TEXT = NbBundle.getMessage(DeleteContentTagAction.class, - "DeleteContentTagAction.deleteTags"); + "DeleteContentTagAction.deleteTag"); // This class is a singleton to support multi-selection of nodes, since // org.openide.nodes.NodeOp.findActions(Node[] nodes) will only pick up an Action if every @@ -64,7 +79,7 @@ public class DeleteContentTagAction extends AbstractAction { try { Case.getCurrentCase().getServices().getTagsManager().deleteContentTag(tag); } catch (TskCoreException ex) { - Logger.getLogger(AddContentTagAction.class.getName()).log(Level.SEVERE, "Error deleting tag", ex); //NON-NLS + Logger.getLogger(DeleteContentTagAction.class.getName()).log(Level.SEVERE, "Error deleting tag", ex); //NON-NLS SwingUtilities.invokeLater(() -> { JOptionPane.showMessageDialog(null, NbBundle.getMessage(this.getClass(), @@ -103,4 +118,47 @@ public class DeleteContentTagAction extends AbstractAction { protected void refreshDirectoryTree() { } + protected String getActionDisplayName() { + return MENU_TEXT; + } + + @NbBundle.Messages({"# {0} - fileID", + "DeleteContentTagAction.deleteTag.alert=Unable to untag file {0}."}) + protected void deleteTag(TagName tagName, ContentTag contentTag, long fileId) { + new SwingWorker() { + + @Override + protected Void doInBackground() throws Exception { + TagsManager tagsManager = Case.getCurrentCase().getServices().getTagsManager(); + + // Pull the from the global context to avoid unnecessary calls + // to the database. + final Collection selectedFilesList = + new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class)); + AbstractFile file = selectedFilesList.iterator().next(); + + try { + LOGGER.log(Level.INFO, "Removing tag {0} from {1}", new Object[]{tagName.getDisplayName(), file.getName()}); //NON-NLS + tagsManager.deleteContentTag(contentTag); + } catch (TskCoreException tskCoreException) { + LOGGER.log(Level.SEVERE, "Error untagging file", tskCoreException); //NON-NLS + Platform.runLater(() -> + new Alert(Alert.AlertType.ERROR, Bundle.DeleteContentTagAction_deleteTag_alert(fileId)).show() + ); + } + return null; + } + + @Override + protected void done() { + super.done(); + try { + get(); + } catch (InterruptedException | ExecutionException ex) { + LOGGER.log(Level.SEVERE, "Unexpected exception while untagging file", ex); //NON-NLS + } + } + }.execute(); + } + } diff --git a/Core/src/org/sleuthkit/autopsy/actions/DeleteFileBlackboardArtifactTagAction.java b/Core/src/org/sleuthkit/autopsy/actions/DeleteFileBlackboardArtifactTagAction.java new file mode 100755 index 0000000000..4c1e52d828 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/actions/DeleteFileBlackboardArtifactTagAction.java @@ -0,0 +1,205 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2017 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.actions; + +import java.awt.event.ActionEvent; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.concurrent.ExecutionException; +import java.util.logging.Level; +import javafx.application.Platform; +import javafx.scene.control.Alert; +import javax.swing.AbstractAction; +import javax.swing.JMenu; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; +import javax.swing.SwingWorker; +import org.openide.util.NbBundle; +import org.openide.util.Utilities; +import org.openide.util.actions.Presenter; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.casemodule.services.TagsManager; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.BlackboardArtifact; +import org.sleuthkit.datamodel.BlackboardArtifactTag; +import org.sleuthkit.datamodel.TagName; +import org.sleuthkit.datamodel.TskCoreException; + +/** + * Instances of this Action allow users to delete tags applied to blackboard + * artifacts. + */ +@NbBundle.Messages({ + "DeleteFileBlackboardArtifactTagAction.deleteTag=Remove Result Tag" +}) +public class DeleteFileBlackboardArtifactTagAction extends AbstractAction implements Presenter.Popup { + + private static final Logger LOGGER = Logger.getLogger(DeleteFileBlackboardArtifactTagAction.class.getName()); + + private static final long serialVersionUID = 1L; + private static final String MENU_TEXT = NbBundle.getMessage(DeleteFileBlackboardArtifactTagAction.class, + "DeleteFileBlackboardArtifactTagAction.deleteTag"); + + // This class is a singleton to support multi-selection of nodes, since + // org.openide.nodes.NodeOp.findActions(Node[] nodes) will only pick up an Action if every + // node in the array returns a reference to the same action object from Node.getActions(boolean). + private static DeleteFileBlackboardArtifactTagAction instance; + + public static synchronized DeleteFileBlackboardArtifactTagAction getInstance() { + if (null == instance) { + instance = new DeleteFileBlackboardArtifactTagAction(); + } + return instance; + } + + private DeleteFileBlackboardArtifactTagAction() { + super(MENU_TEXT); + } + + @Override + public JMenuItem getPopupPresenter() { + return new TagMenu(); + } + + @Override + public void actionPerformed(ActionEvent event) { + } + + protected String getActionDisplayName() { + return MENU_TEXT; + } + + @NbBundle.Messages({"# {0} - artifactID", + "DeleteFileBlackboardArtifactTagAction.deleteTag.alert=Unable to untag artifact {0}."}) + protected void deleteTag(TagName tagName, BlackboardArtifactTag artifactTag, long artifactId) { + new SwingWorker() { + + @Override + protected Void doInBackground() throws Exception { + TagsManager tagsManager = Case.getCurrentCase().getServices().getTagsManager(); + + // Pull the from the global context to avoid unnecessary calls + // to the database. + final Collection selectedFilesList = + new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class)); + AbstractFile file = selectedFilesList.iterator().next(); + + try { + LOGGER.log(Level.INFO, "Removing tag {0} from {1}", new Object[]{tagName.getDisplayName(), file.getName()}); //NON-NLS + tagsManager.deleteBlackboardArtifactTag(artifactTag); + } catch (TskCoreException tskCoreException) { + LOGGER.log(Level.SEVERE, "Error untagging artifact", tskCoreException); //NON-NLS + Platform.runLater(() -> + new Alert(Alert.AlertType.ERROR, Bundle.DeleteFileBlackboardArtifactTagAction_deleteTag_alert(artifactId)).show() + ); + } + return null; + } + + @Override + protected void done() { + super.done(); + try { + get(); + } catch (InterruptedException | ExecutionException ex) { + LOGGER.log(Level.SEVERE, "Unexpected exception while untagging artifact", ex); //NON-NLS + } + } + }.execute(); + } + + /** + * Instances of this class implement a context menu user interface for + * creating or selecting a tag name for a tag and specifying an optional tag + * comment. + */ + // @@@ This user interface has some significant usability issues and needs + // to be reworked. + @NbBundle.Messages({"# {0} - artifactID", + "DeleteFileBlackboardArtifactTagAction.deleteTags.alert=Unable to untag artifact {0}."}) + private class TagMenu extends JMenu { + + private static final long serialVersionUID = 1L; + + TagMenu() { + super(getActionDisplayName()); + + final Collection selectedBlackboardArtifactsList = + new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class)); + + if(!selectedBlackboardArtifactsList.isEmpty()) { + BlackboardArtifact artifact = + selectedBlackboardArtifactsList.iterator().next(); + + // Get the current set of tag names. + TagsManager tagsManager = Case.getCurrentCase().getServices().getTagsManager(); + + Map tagNamesMap = null; + try { + tagNamesMap = new TreeMap<>(tagsManager.getDisplayNamesToTagNamesMap()); + } catch (TskCoreException ex) { + Logger.getLogger(TagsManager.class.getName()).log(Level.SEVERE, "Failed to get tag names", ex); //NON-NLS + } + + // Each tag name in the current set of tags gets its own menu item in + // the "Quick Tags" sub-menu. Selecting one of these menu items adds + // a tag with the associated tag name. + if (null != tagNamesMap && !tagNamesMap.isEmpty()) { + try { + List existingTagsList = + Case.getCurrentCase().getServices().getTagsManager() + .getBlackboardArtifactTagsByArtifact(artifact); + + for (Map.Entry entry : tagNamesMap.entrySet()) { + String tagDisplayName = entry.getKey(); + + TagName tagName = entry.getValue(); + for(BlackboardArtifactTag artifactTag : existingTagsList) { + if(tagDisplayName.equals(artifactTag.getName().getDisplayName())) { + JMenuItem tagNameItem = new JMenuItem(tagDisplayName); + // for the bookmark tag name only, added shortcut label + if (tagDisplayName.equals(NbBundle.getMessage(AddTagAction.class, "AddBookmarkTagAction.bookmark.text"))) { + tagNameItem.setAccelerator(AddBookmarkTagAction.BOOKMARK_SHORTCUT); + } + tagNameItem.addActionListener((ActionEvent e) -> { + deleteTag(tagName, artifactTag, artifact.getArtifactID()); + }); + add(tagNameItem); + } + } + } + } catch (TskCoreException ex) { + Logger.getLogger(TagMenu.class.getName()) + .log(Level.SEVERE, "Error retrieving tags for TagMenu", ex); //NON-NLS + } + } + + if(getItemCount() == 0) { + setEnabled(false); + } + } + } + } + +} diff --git a/Core/src/org/sleuthkit/autopsy/actions/DeleteFileContentTagAction.java b/Core/src/org/sleuthkit/autopsy/actions/DeleteFileContentTagAction.java new file mode 100755 index 0000000000..0da884c34e --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/actions/DeleteFileContentTagAction.java @@ -0,0 +1,202 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2017 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.actions; + +import java.awt.event.ActionEvent; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.concurrent.ExecutionException; +import java.util.logging.Level; +import javafx.application.Platform; +import javafx.scene.control.Alert; +import javax.swing.AbstractAction; +import javax.swing.JMenu; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; +import javax.swing.SwingWorker; +import org.openide.util.NbBundle; +import org.openide.util.Utilities; +import org.openide.util.actions.Presenter; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.casemodule.services.TagsManager; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.ContentTag; +import org.sleuthkit.datamodel.TagName; +import org.sleuthkit.datamodel.TskCoreException; + +/** + * Instances of this Action allow users to delete tags applied to content. + */ +@NbBundle.Messages({ + "DeleteFileContentTagAction.deleteTag=Remove File Tag" +}) +public class DeleteFileContentTagAction extends AbstractAction implements Presenter.Popup { + + private static final Logger LOGGER = Logger.getLogger(DeleteFileContentTagAction.class.getName()); + + private static final long serialVersionUID = 1L; + private static final String MENU_TEXT = NbBundle.getMessage(DeleteFileContentTagAction.class, + "DeleteFileContentTagAction.deleteTag"); + + // This class is a singleton to support multi-selection of nodes, since + // org.openide.nodes.NodeOp.findActions(Node[] nodes) will only pick up an Action if every + // node in the array returns a reference to the same action object from Node.getActions(boolean). + private static DeleteFileContentTagAction instance; + + public static synchronized DeleteFileContentTagAction getInstance() { + if (null == instance) { + instance = new DeleteFileContentTagAction(); + } + return instance; + } + + private DeleteFileContentTagAction() { + super(MENU_TEXT); + } + + @Override + public JMenuItem getPopupPresenter() { + return new TagMenu(); + } + + @Override + public void actionPerformed(ActionEvent e) { + } + + protected String getActionDisplayName() { + return MENU_TEXT; + } + + @NbBundle.Messages({"# {0} - fileID", + "DeleteFileContentTagAction.deleteTag.alert=Unable to untag file {0}."}) + protected void deleteTag(TagName tagName, ContentTag contentTag, long fileId) { + new SwingWorker() { + + @Override + protected Void doInBackground() throws Exception { + TagsManager tagsManager = Case.getCurrentCase().getServices().getTagsManager(); + + // Pull the from the global context to avoid unnecessary calls + // to the database. + final Collection selectedFilesList = + new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class)); + AbstractFile file = selectedFilesList.iterator().next(); + + try { + LOGGER.log(Level.INFO, "Removing tag {0} from {1}", new Object[]{tagName.getDisplayName(), file.getName()}); //NON-NLS + tagsManager.deleteContentTag(contentTag); + } catch (TskCoreException tskCoreException) { + LOGGER.log(Level.SEVERE, "Error untagging file", tskCoreException); //NON-NLS + Platform.runLater(() -> + new Alert(Alert.AlertType.ERROR, Bundle.DeleteFileContentTagAction_deleteTag_alert(fileId)).show() + ); + } + return null; + } + + @Override + protected void done() { + super.done(); + try { + get(); + } catch (InterruptedException | ExecutionException ex) { + LOGGER.log(Level.SEVERE, "Unexpected exception while untagging file", ex); //NON-NLS + } + } + }.execute(); + } + + /** + * Instances of this class implement a context menu user interface for + * creating or selecting a tag name for a tag and specifying an optional tag + * comment. + */ + // @@@ This user interface has some significant usability issues and needs + // to be reworked. + private class TagMenu extends JMenu { + + private static final long serialVersionUID = 1L; + + TagMenu() { + super(getActionDisplayName()); + + final Collection selectedAbstractFilesList = + new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class)); + + if(!selectedAbstractFilesList.isEmpty()) { + AbstractFile file = selectedAbstractFilesList.iterator().next(); + + // Get the current set of tag names. + TagsManager tagsManager = Case.getCurrentCase().getServices().getTagsManager(); + + Map tagNamesMap = null; + try { + tagNamesMap = new TreeMap<>(tagsManager.getDisplayNamesToTagNamesMap()); + } catch (TskCoreException ex) { + Logger.getLogger(TagsManager.class.getName()).log(Level.SEVERE, "Failed to get tag names", ex); //NON-NLS + } + + // Each tag name in the current set of tags gets its own menu item in + // the "Quick Tags" sub-menu. Selecting one of these menu items adds + // a tag with the associated tag name. + if (null != tagNamesMap && !tagNamesMap.isEmpty()) { + try { + /*List existingTagsList = + Case.getCurrentCase().getServices().getTagsManager().getBlackboardArtifactTagsByArtifact(artifact);*/ + List existingTagsList = + Case.getCurrentCase().getServices().getTagsManager() + .getContentTagsByContent(file); + + for (Map.Entry entry : tagNamesMap.entrySet()) { + String tagDisplayName = entry.getKey(); + + TagName tagName = entry.getValue(); + for(ContentTag contentTag : existingTagsList) { + if(tagDisplayName.equals(contentTag.getName().getDisplayName())) { + JMenuItem tagNameItem = new JMenuItem(tagDisplayName); + // for the bookmark tag name only, added shortcut label + if (tagDisplayName.equals(NbBundle.getMessage(AddTagAction.class, "AddBookmarkTagAction.bookmark.text"))) { + tagNameItem.setAccelerator(AddBookmarkTagAction.BOOKMARK_SHORTCUT); + } + tagNameItem.addActionListener((ActionEvent e) -> { + deleteTag(tagName, contentTag, file.getId()); + }); + add(tagNameItem); + } + } + } + } catch (TskCoreException ex) { + Logger.getLogger(TagMenu.class.getName()) + .log(Level.SEVERE, "Error retrieving tags for TagMenu", ex); //NON-NLS + } + } + + if(getItemCount() == 0) { + setEnabled(false); + } + } + } + } + +} diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DataModelActionsFactory.java b/Core/src/org/sleuthkit/autopsy/datamodel/DataModelActionsFactory.java index 7ab744d712..dc1aa9a8bf 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DataModelActionsFactory.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DataModelActionsFactory.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013 Basis Technology Corp. + * Copyright 2013-2017 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,18 +19,25 @@ package org.sleuthkit.autopsy.datamodel; import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; import java.util.List; import javax.swing.Action; import org.openide.util.NbBundle; +import org.openide.util.Utilities; import org.sleuthkit.autopsy.actions.AddBlackboardArtifactTagAction; import org.sleuthkit.autopsy.actions.AddContentTagAction; +import org.sleuthkit.autopsy.actions.DeleteFileBlackboardArtifactTagAction; +import org.sleuthkit.autopsy.actions.DeleteFileContentTagAction; import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint; import org.sleuthkit.autopsy.directorytree.ExternalViewerAction; import org.sleuthkit.autopsy.directorytree.ExtractAction; import org.sleuthkit.autopsy.directorytree.HashSearchAction; import org.sleuthkit.autopsy.directorytree.NewWindowViewAction; import org.sleuthkit.autopsy.directorytree.ViewContextAction; +import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.DerivedFile; import org.sleuthkit.datamodel.Directory; @@ -64,129 +71,227 @@ public class DataModelActionsFactory { .getMessage(DataModelActionsFactory.class, "DataModelActionsFactory.srfFileSameMD5.text"); public static List getActions(File file, boolean isArtifactSource) { - List actions = new ArrayList<>(); - actions.add(new ViewContextAction((isArtifactSource ? VIEW_SOURCE_FILE_IN_DIR : VIEW_FILE_IN_DIR), file)); + List actionsList = new ArrayList<>(); + actionsList.add(new ViewContextAction((isArtifactSource ? VIEW_SOURCE_FILE_IN_DIR : VIEW_FILE_IN_DIR), file)); final FileNode fileNode = new FileNode(file); - actions.add(null); // creates a menu separator - actions.add(new NewWindowViewAction(VIEW_IN_NEW_WINDOW, fileNode)); - actions.add(new ExternalViewerAction(OPEN_IN_EXTERNAL_VIEWER, fileNode)); - actions.add(null); // creates a menu separator - actions.add(ExtractAction.getInstance()); - actions.add(new HashSearchAction(SEARCH_FOR_FILES_SAME_MD5, fileNode)); - actions.add(null); // creates a menu separator - actions.add(AddContentTagAction.getInstance()); + actionsList.add(null); // creates a menu separator + actionsList.add(new NewWindowViewAction(VIEW_IN_NEW_WINDOW, fileNode)); + actionsList.add(new ExternalViewerAction(OPEN_IN_EXTERNAL_VIEWER, fileNode)); + actionsList.add(null); // creates a menu separator + actionsList.add(ExtractAction.getInstance()); + actionsList.add(new HashSearchAction(SEARCH_FOR_FILES_SAME_MD5, fileNode)); + actionsList.add(null); // creates a menu separator + actionsList.add(AddContentTagAction.getInstance()); if (isArtifactSource) { - actions.add(AddBlackboardArtifactTagAction.getInstance()); + actionsList.add(AddBlackboardArtifactTagAction.getInstance()); } - actions.addAll(ContextMenuExtensionPoint.getActions()); - return actions; + + final Collection selectedFilesList = + new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class)); + if(selectedFilesList.size() == 1) { + actionsList.add(DeleteFileContentTagAction.getInstance()); + } + if(isArtifactSource) { + final Collection selectedArtifactsList = + new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class)); + if(selectedArtifactsList.size() == 1) { + actionsList.add(DeleteFileBlackboardArtifactTagAction.getInstance()); + } + } + + actionsList.addAll(ContextMenuExtensionPoint.getActions()); + return actionsList; } public static List getActions(SlackFile slackFile, boolean isArtifactSource) { - List actions = new ArrayList<>(); - actions.add(new ViewContextAction((isArtifactSource ? VIEW_SOURCE_FILE_IN_DIR : VIEW_FILE_IN_DIR), slackFile)); + List actionsList = new ArrayList<>(); + actionsList.add(new ViewContextAction((isArtifactSource ? VIEW_SOURCE_FILE_IN_DIR : VIEW_FILE_IN_DIR), slackFile)); final SlackFileNode slackFileNode = new SlackFileNode(slackFile); - actions.add(null); // creates a menu separator - actions.add(new NewWindowViewAction(VIEW_IN_NEW_WINDOW, slackFileNode)); - actions.add(null); // creates a menu separator - actions.add(ExtractAction.getInstance()); - actions.add(null); // creates a menu separator - actions.add(AddContentTagAction.getInstance()); + actionsList.add(null); // creates a menu separator + actionsList.add(new NewWindowViewAction(VIEW_IN_NEW_WINDOW, slackFileNode)); + actionsList.add(null); // creates a menu separator + actionsList.add(ExtractAction.getInstance()); + actionsList.add(null); // creates a menu separator + actionsList.add(AddContentTagAction.getInstance()); if (isArtifactSource) { - actions.add(AddBlackboardArtifactTagAction.getInstance()); + actionsList.add(AddBlackboardArtifactTagAction.getInstance()); } - actions.addAll(ContextMenuExtensionPoint.getActions()); - return actions; + + final Collection selectedFilesList = + new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class)); + if(selectedFilesList.size() == 1) { + actionsList.add(DeleteFileContentTagAction.getInstance()); + } + if(isArtifactSource) { + final Collection selectedArtifactsList = + new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class)); + if(selectedArtifactsList.size() == 1) { + actionsList.add(DeleteFileBlackboardArtifactTagAction.getInstance()); + } + } + + actionsList.addAll(ContextMenuExtensionPoint.getActions()); + return actionsList; } public static List getActions(LayoutFile file, boolean isArtifactSource) { - List actions = new ArrayList<>(); - actions.add(new ViewContextAction((isArtifactSource ? VIEW_SOURCE_FILE_IN_DIR : VIEW_FILE_IN_DIR), file)); + List actionsList = new ArrayList<>(); + actionsList.add(new ViewContextAction((isArtifactSource ? VIEW_SOURCE_FILE_IN_DIR : VIEW_FILE_IN_DIR), file)); LayoutFileNode layoutFileNode = new LayoutFileNode(file); - actions.add(null); // creates a menu separator - actions.add(new NewWindowViewAction(VIEW_IN_NEW_WINDOW, layoutFileNode)); - actions.add(new ExternalViewerAction(OPEN_IN_EXTERNAL_VIEWER, layoutFileNode)); - actions.add(null); // creates a menu separator - actions.add(ExtractAction.getInstance());// - actions.add(null); // creates a menu separator - actions.add(AddContentTagAction.getInstance()); + actionsList.add(null); // creates a menu separator + actionsList.add(new NewWindowViewAction(VIEW_IN_NEW_WINDOW, layoutFileNode)); + actionsList.add(new ExternalViewerAction(OPEN_IN_EXTERNAL_VIEWER, layoutFileNode)); + actionsList.add(null); // creates a menu separator + actionsList.add(ExtractAction.getInstance());// + actionsList.add(null); // creates a menu separator + actionsList.add(AddContentTagAction.getInstance()); if (isArtifactSource) { - actions.add(AddBlackboardArtifactTagAction.getInstance()); + actionsList.add(AddBlackboardArtifactTagAction.getInstance()); } - actions.addAll(ContextMenuExtensionPoint.getActions()); - return actions; + + final Collection selectedFilesList = + new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class)); + if(selectedFilesList.size() == 1) { + actionsList.add(DeleteFileContentTagAction.getInstance()); + } + if(isArtifactSource) { + final Collection selectedArtifactsList = + new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class)); + if(selectedArtifactsList.size() == 1) { + actionsList.add(DeleteFileBlackboardArtifactTagAction.getInstance()); + } + } + + actionsList.addAll(ContextMenuExtensionPoint.getActions()); + return actionsList; } public static List getActions(Directory directory, boolean isArtifactSource) { - List actions = new ArrayList<>(); - actions.add(new ViewContextAction((isArtifactSource ? VIEW_SOURCE_FILE_IN_DIR : VIEW_FILE_IN_DIR), directory)); + List actionsList = new ArrayList<>(); + actionsList.add(new ViewContextAction((isArtifactSource ? VIEW_SOURCE_FILE_IN_DIR : VIEW_FILE_IN_DIR), directory)); DirectoryNode directoryNode = new DirectoryNode(directory); - actions.add(null); // creates a menu separator - actions.add(new NewWindowViewAction(VIEW_IN_NEW_WINDOW, directoryNode)); - actions.add(new ExternalViewerAction(OPEN_IN_EXTERNAL_VIEWER, directoryNode)); - actions.add(null); // creates a menu separator - actions.add(ExtractAction.getInstance()); - actions.add(null); // creates a menu separator - actions.add(AddContentTagAction.getInstance()); + actionsList.add(null); // creates a menu separator + actionsList.add(new NewWindowViewAction(VIEW_IN_NEW_WINDOW, directoryNode)); + actionsList.add(new ExternalViewerAction(OPEN_IN_EXTERNAL_VIEWER, directoryNode)); + actionsList.add(null); // creates a menu separator + actionsList.add(ExtractAction.getInstance()); + actionsList.add(null); // creates a menu separator + actionsList.add(AddContentTagAction.getInstance()); if (isArtifactSource) { - actions.add(AddBlackboardArtifactTagAction.getInstance()); + actionsList.add(AddBlackboardArtifactTagAction.getInstance()); } - actions.addAll(ContextMenuExtensionPoint.getActions()); - return actions; + + final Collection selectedFilesList = + new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class)); + if(selectedFilesList.size() == 1) { + actionsList.add(DeleteFileContentTagAction.getInstance()); + } + if(isArtifactSource) { + final Collection selectedArtifactsList = + new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class)); + if(selectedArtifactsList.size() == 1) { + actionsList.add(DeleteFileBlackboardArtifactTagAction.getInstance()); + } + } + + actionsList.addAll(ContextMenuExtensionPoint.getActions()); + return actionsList; } public static List getActions(VirtualDirectory directory, boolean isArtifactSource) { - List actions = new ArrayList<>(); - actions.add(new ViewContextAction((isArtifactSource ? VIEW_SOURCE_FILE_IN_DIR : VIEW_FILE_IN_DIR), directory)); + List actionsList = new ArrayList<>(); + actionsList.add(new ViewContextAction((isArtifactSource ? VIEW_SOURCE_FILE_IN_DIR : VIEW_FILE_IN_DIR), directory)); VirtualDirectoryNode directoryNode = new VirtualDirectoryNode(directory); - actions.add(null); // creates a menu separator - actions.add(new NewWindowViewAction(VIEW_IN_NEW_WINDOW, directoryNode)); - actions.add(new ExternalViewerAction(OPEN_IN_EXTERNAL_VIEWER, directoryNode)); - actions.add(null); // creates a menu separator - actions.add(ExtractAction.getInstance()); - actions.add(null); // creates a menu separator - actions.add(AddContentTagAction.getInstance()); + actionsList.add(null); // creates a menu separator + actionsList.add(new NewWindowViewAction(VIEW_IN_NEW_WINDOW, directoryNode)); + actionsList.add(new ExternalViewerAction(OPEN_IN_EXTERNAL_VIEWER, directoryNode)); + actionsList.add(null); // creates a menu separator + actionsList.add(ExtractAction.getInstance()); + actionsList.add(null); // creates a menu separator + actionsList.add(AddContentTagAction.getInstance()); if (isArtifactSource) { - actions.add(AddBlackboardArtifactTagAction.getInstance()); + actionsList.add(AddBlackboardArtifactTagAction.getInstance()); } - actions.addAll(ContextMenuExtensionPoint.getActions()); - return actions; + + final Collection selectedFilesList = + new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class)); + if(selectedFilesList.size() == 1) { + actionsList.add(DeleteFileContentTagAction.getInstance()); + } + if(isArtifactSource) { + final Collection selectedArtifactsList = + new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class)); + if(selectedArtifactsList.size() == 1) { + actionsList.add(DeleteFileBlackboardArtifactTagAction.getInstance()); + } + } + + actionsList.addAll(ContextMenuExtensionPoint.getActions()); + return actionsList; } public static List getActions(LocalFile file, boolean isArtifactSource) { - List actions = new ArrayList<>(); - actions.add(new ViewContextAction((isArtifactSource ? VIEW_SOURCE_FILE_IN_DIR : VIEW_FILE_IN_DIR), file)); + List actionsList = new ArrayList<>(); + actionsList.add(new ViewContextAction((isArtifactSource ? VIEW_SOURCE_FILE_IN_DIR : VIEW_FILE_IN_DIR), file)); final LocalFileNode localFileNode = new LocalFileNode(file); - actions.add(null); // creates a menu separator - actions.add(new NewWindowViewAction(VIEW_IN_NEW_WINDOW, localFileNode)); - actions.add(new ExternalViewerAction(OPEN_IN_EXTERNAL_VIEWER, localFileNode)); - actions.add(null); // creates a menu separator - actions.add(ExtractAction.getInstance()); - actions.add(null); // creates a menu separator - actions.add(AddContentTagAction.getInstance()); + actionsList.add(null); // creates a menu separator + actionsList.add(new NewWindowViewAction(VIEW_IN_NEW_WINDOW, localFileNode)); + actionsList.add(new ExternalViewerAction(OPEN_IN_EXTERNAL_VIEWER, localFileNode)); + actionsList.add(null); // creates a menu separator + actionsList.add(ExtractAction.getInstance()); + actionsList.add(null); // creates a menu separator + actionsList.add(AddContentTagAction.getInstance()); if (isArtifactSource) { - actions.add(AddBlackboardArtifactTagAction.getInstance()); + actionsList.add(AddBlackboardArtifactTagAction.getInstance()); } - actions.addAll(ContextMenuExtensionPoint.getActions()); - return actions; + + final Collection selectedFilesList = + new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class)); + if(selectedFilesList.size() == 1) { + actionsList.add(DeleteFileContentTagAction.getInstance()); + } + if(isArtifactSource) { + final Collection selectedArtifactsList = + new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class)); + if(selectedArtifactsList.size() == 1) { + actionsList.add(DeleteFileBlackboardArtifactTagAction.getInstance()); + } + } + + actionsList.addAll(ContextMenuExtensionPoint.getActions()); + return actionsList; } public static List getActions(DerivedFile file, boolean isArtifactSource) { - List actions = new ArrayList<>(); - actions.add(new ViewContextAction((isArtifactSource ? VIEW_SOURCE_FILE_IN_DIR : VIEW_FILE_IN_DIR), file)); + List actionsList = new ArrayList<>(); + actionsList.add(new ViewContextAction((isArtifactSource ? VIEW_SOURCE_FILE_IN_DIR : VIEW_FILE_IN_DIR), file)); final LocalFileNode localFileNode = new LocalFileNode(file); - actions.add(null); // creates a menu separator - actions.add(new NewWindowViewAction(VIEW_IN_NEW_WINDOW, localFileNode)); - actions.add(new ExternalViewerAction(OPEN_IN_EXTERNAL_VIEWER, localFileNode)); - actions.add(null); // creates a menu separator - actions.add(ExtractAction.getInstance()); - actions.add(null); // creates a menu separator - actions.add(AddContentTagAction.getInstance()); + actionsList.add(null); // creates a menu separator + actionsList.add(new NewWindowViewAction(VIEW_IN_NEW_WINDOW, localFileNode)); + actionsList.add(new ExternalViewerAction(OPEN_IN_EXTERNAL_VIEWER, localFileNode)); + actionsList.add(null); // creates a menu separator + actionsList.add(ExtractAction.getInstance()); + actionsList.add(null); // creates a menu separator + actionsList.add(AddContentTagAction.getInstance()); if (isArtifactSource) { - actions.add(AddBlackboardArtifactTagAction.getInstance()); + actionsList.add(AddBlackboardArtifactTagAction.getInstance()); } - actions.addAll(ContextMenuExtensionPoint.getActions()); - return actions; + + final Collection selectedFilesList = + new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class)); + if(selectedFilesList.size() == 1) { + actionsList.add(DeleteFileContentTagAction.getInstance()); + } + if(isArtifactSource) { + final Collection selectedArtifactsList = + new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class)); + if(selectedArtifactsList.size() == 1) { + actionsList.add(DeleteFileBlackboardArtifactTagAction.getInstance()); + } + } + + actionsList.addAll(ContextMenuExtensionPoint.getActions()); + return actionsList; } public static List getActions(Content content, boolean isArtifactSource) { diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DirectoryNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/DirectoryNode.java index 59240d204a..68aeb01e8c 100755 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DirectoryNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DirectoryNode.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011 - 2013 Basis Technology Corp. + * Copyright 2011-2017 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,11 +19,16 @@ package org.sleuthkit.autopsy.datamodel; import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; import java.util.List; import javax.swing.Action; import org.openide.util.NbBundle; +import org.openide.util.Utilities; import org.sleuthkit.autopsy.actions.AddContentTagAction; +import org.sleuthkit.autopsy.actions.DeleteFileContentTagAction; import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint; +import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.directorytree.ExtractAction; import org.sleuthkit.autopsy.directorytree.NewWindowViewAction; import org.sleuthkit.autopsy.directorytree.ViewContextAction; @@ -37,6 +42,8 @@ import org.sleuthkit.datamodel.TskData.TSK_FS_NAME_FLAG_ENUM; * are more directories. */ public class DirectoryNode extends AbstractFsContentNode { + + private static final Logger LOGGER = Logger.getLogger(DirectoryNode.class.getName()); public static final String DOTDOTDIR = NbBundle.getMessage(DirectoryNode.class, "DirectoryNode.parFolder.text"); public static final String DOTDIR = NbBundle.getMessage(DirectoryNode.class, "DirectoryNode.curFolder.text"); @@ -71,23 +78,29 @@ public class DirectoryNode extends AbstractFsContentNode { */ @Override public Action[] getActions(boolean popup) { - List actions = new ArrayList<>(); + List actionsList = new ArrayList<>(); for (Action a : super.getActions(true)) { - actions.add(a); + actionsList.add(a); } if (!getDirectoryBrowseMode()) { - actions.add(new ViewContextAction( + actionsList.add(new ViewContextAction( NbBundle.getMessage(this.getClass(), "DirectoryNode.getActions.viewFileInDir.text"), this)); - actions.add(null); // creates a menu separator + actionsList.add(null); // creates a menu separator } - actions.add(new NewWindowViewAction(NbBundle.getMessage(this.getClass(), "DirectoryNode.viewInNewWin.text"), this)); - actions.add(ViewFileInTimelineAction.createViewFileAction(getContent())); - actions.add(null); // creates a menu separator - actions.add(ExtractAction.getInstance()); - actions.add(null); // creates a menu separator - actions.add(AddContentTagAction.getInstance()); - actions.addAll(ContextMenuExtensionPoint.getActions()); - return actions.toArray(new Action[actions.size()]); + actionsList.add(new NewWindowViewAction(NbBundle.getMessage(this.getClass(), "DirectoryNode.viewInNewWin.text"), this)); + actionsList.add(ViewFileInTimelineAction.createViewFileAction(getContent())); + actionsList.add(null); // creates a menu separator + actionsList.add(ExtractAction.getInstance()); + actionsList.add(null); // creates a menu separator + actionsList.add(AddContentTagAction.getInstance()); + + final Collection selectedFilesList = new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class)); + if(selectedFilesList.size() == 1) { + actionsList.add(DeleteFileContentTagAction.getInstance()); + } + + actionsList.addAll(ContextMenuExtensionPoint.getActions()); + return actionsList.toArray(new Action[actionsList.size()]); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileNode.java index 7ee5acf08f..10ba139efd 100755 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileNode.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2016 Basis Technology Corp. + * Copyright 2011-2017 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,13 +19,18 @@ package org.sleuthkit.autopsy.datamodel; import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; import java.util.List; import javax.swing.Action; import org.apache.commons.lang3.StringUtils; import org.openide.util.NbBundle; +import org.openide.util.Utilities; import org.sleuthkit.autopsy.actions.AddContentTagAction; +import org.sleuthkit.autopsy.actions.DeleteFileContentTagAction; import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint; import org.sleuthkit.autopsy.coreutils.ImageUtils; +import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.directorytree.ExternalViewerAction; import org.sleuthkit.autopsy.directorytree.ExtractAction; import org.sleuthkit.autopsy.directorytree.HashSearchAction; @@ -41,6 +46,8 @@ import org.sleuthkit.datamodel.TskData.TSK_FS_NAME_FLAG_ENUM; * children. */ public class FileNode extends AbstractFsContentNode { + + private static final Logger LOGGER = Logger.getLogger(FileNode.class.getName()); /** * Constructor @@ -96,6 +103,12 @@ public class FileNode extends AbstractFsContentNode { actionsList.add(new HashSearchAction(Bundle.FileNode_getActions_searchFilesSameMD5_text(), this)); actionsList.add(null); // creates a menu separator actionsList.add(AddContentTagAction.getInstance()); + + final Collection selectedFilesList = new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class)); + if(selectedFilesList.size() == 1) { + actionsList.add(DeleteFileContentTagAction.getInstance()); + } + actionsList.addAll(ContextMenuExtensionPoint.getActions()); return actionsList.toArray(new Action[actionsList.size()]); } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/LayoutFileNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/LayoutFileNode.java index 495737488b..c759b425d7 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/LayoutFileNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/LayoutFileNode.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2014 Basis Technology Corp. + * Copyright 2011-2017 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,17 +19,22 @@ package org.sleuthkit.autopsy.datamodel; import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import javax.swing.Action; import org.openide.nodes.Sheet; import org.openide.util.NbBundle; +import org.openide.util.Utilities; import org.sleuthkit.autopsy.actions.AddContentTagAction; +import org.sleuthkit.autopsy.actions.DeleteFileContentTagAction; import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint; import org.sleuthkit.autopsy.directorytree.ExternalViewerAction; import org.sleuthkit.autopsy.directorytree.ExtractAction; import org.sleuthkit.autopsy.directorytree.NewWindowViewAction; +import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.LayoutFile; import org.sleuthkit.datamodel.TskData; @@ -121,6 +126,13 @@ public class LayoutFileNode extends AbstractAbstractFileNode { actionsList.add(ExtractAction.getInstance()); actionsList.add(null); // creates a menu separator actionsList.add(AddContentTagAction.getInstance()); + + final Collection selectedFilesList = + new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class)); + if(selectedFilesList.size() == 1) { + actionsList.add(DeleteFileContentTagAction.getInstance()); + } + actionsList.addAll(ContextMenuExtensionPoint.getActions()); return actionsList.toArray(new Action[0]); } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/LocalFileNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/LocalFileNode.java index ecccb26272..5738356c46 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/LocalFileNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/LocalFileNode.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013-2016 Basis Technology Corp. + * Copyright 2013-2017 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,14 +20,19 @@ package org.sleuthkit.autopsy.datamodel; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import javax.swing.Action; import org.openide.nodes.Sheet; import org.openide.util.NbBundle; +import org.openide.util.Utilities; import org.sleuthkit.autopsy.actions.AddContentTagAction; +import org.sleuthkit.autopsy.actions.DeleteFileContentTagAction; import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint; +import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.directorytree.ExternalViewerAction; import org.sleuthkit.autopsy.directorytree.ExtractAction; import org.sleuthkit.autopsy.directorytree.HashSearchAction; @@ -39,6 +44,8 @@ import org.sleuthkit.datamodel.AbstractFile; * A Node for a LocalFile or DerivedFile content object. */ public class LocalFileNode extends AbstractAbstractFileNode { + + private static final Logger LOGGER = Logger.getLogger(LocalFileNode.class.getName()); public LocalFileNode(AbstractFile af) { super(af); @@ -98,6 +105,13 @@ public class LocalFileNode extends AbstractAbstractFileNode { NbBundle.getMessage(this.getClass(), "LocalFileNode.getActions.searchFilesSameMd5.text"), this)); actionsList.add(null); // creates a menu separator actionsList.add(AddContentTagAction.getInstance()); + + final Collection selectedFilesList = + new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class)); + if(selectedFilesList.size() == 1) { + actionsList.add(DeleteFileContentTagAction.getInstance()); + } + actionsList.addAll(ContextMenuExtensionPoint.getActions()); return actionsList.toArray(new Action[0]); } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/SlackFileNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/SlackFileNode.java index 863de3d9d8..742b75ddcb 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/SlackFileNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/SlackFileNode.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2016 Basis Technology Corp. + * Copyright 2011-2017 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,10 +19,14 @@ package org.sleuthkit.autopsy.datamodel; import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; import java.util.List; import javax.swing.Action; import org.openide.util.NbBundle; +import org.openide.util.Utilities; import org.sleuthkit.autopsy.actions.AddContentTagAction; +import org.sleuthkit.autopsy.actions.DeleteFileContentTagAction; import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint; import org.sleuthkit.autopsy.directorytree.ExtractAction; import org.sleuthkit.autopsy.directorytree.NewWindowViewAction; @@ -84,6 +88,13 @@ public class SlackFileNode extends AbstractFsContentNode { actionsList.add(ExtractAction.getInstance()); actionsList.add(null); // creates a menu separator actionsList.add(AddContentTagAction.getInstance()); + + final Collection selectedFilesList = + new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class)); + if(selectedFilesList.size() == 1) { + actionsList.add(DeleteFileContentTagAction.getInstance()); + } + actionsList.addAll(ContextMenuExtensionPoint.getActions()); return actionsList.toArray(new Action[actionsList.size()]); } diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java index 81820218ec..58cba4102f 100755 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java @@ -21,6 +21,8 @@ package org.sleuthkit.autopsy.directorytree; import java.awt.event.ActionEvent; import java.beans.PropertyVetoException; import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; import java.util.List; import java.util.logging.Level; import java.util.prefs.PreferenceChangeEvent; @@ -33,8 +35,11 @@ import org.openide.nodes.FilterNode; import org.openide.nodes.Node; import org.openide.nodes.Sheet; import org.openide.util.NbBundle; +import org.openide.util.Utilities; import org.sleuthkit.autopsy.actions.AddBlackboardArtifactTagAction; import org.sleuthkit.autopsy.actions.AddContentTagAction; +import org.sleuthkit.autopsy.actions.DeleteFileBlackboardArtifactTagAction; +import org.sleuthkit.autopsy.actions.DeleteFileContentTagAction; import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint; import org.sleuthkit.autopsy.coreutils.Logger; @@ -70,6 +75,8 @@ import org.sleuthkit.datamodel.VirtualDirectory; * defines the actions that the node should have. */ public class DataResultFilterNode extends FilterNode { + + private static final Logger LOGGER = Logger.getLogger(DataResultFilterNode.class.getName()); private static boolean filterKnownFromDataSources = UserPreferences.hideKnownFilesInDataSourcesTree(); private static boolean filterKnownFromViews = UserPreferences.hideKnownFilesInViewsTree(); @@ -260,29 +267,29 @@ public class DataResultFilterNode extends FilterNode { //they should be set in individual Node subclass and using a utility to get Actions per Content sub-type // TODO UPDATE: There is now a DataModelActionsFactory utility; - List actions = new ArrayList<>(); + List actionsList = new ArrayList<>(); //merge predefined specific node actions if bban subclasses have their own for (Action a : ban.getActions(true)) { - actions.add(a); + actionsList.add(a); } BlackboardArtifact ba = ban.getLookup().lookup(BlackboardArtifact.class); final int artifactTypeID = ba.getArtifactTypeID(); if (artifactTypeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID() || artifactTypeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) { - actions.add(new ViewContextAction( + actionsList.add(new ViewContextAction( NbBundle.getMessage(this.getClass(), "DataResultFilterNode.action.viewFileInDir.text"), ban)); } else { // if the artifact links to another file, add an action to go to // that file Content c = findLinked(ban); if (c != null) { - actions.add(new ViewContextAction( + actionsList.add(new ViewContextAction( NbBundle.getMessage(this.getClass(), "DataResultFilterNode.action.viewFileInDir.text"), c)); } // action to go to the source file of the artifact - actions.add(new ViewContextAction( + actionsList.add(new ViewContextAction( NbBundle.getMessage(this.getClass(), "DataResultFilterNode.action.viewSrcFileInDir.text"), ban)); } Content c = ban.getLookup().lookup(File.class); @@ -304,28 +311,44 @@ public class DataResultFilterNode extends FilterNode { n = new SlackFileNode((SlackFile) c); } if (n != null) { - actions.add(null); // creates a menu separator - actions.add(new NewWindowViewAction( + actionsList.add(null); // creates a menu separator + actionsList.add(new NewWindowViewAction( NbBundle.getMessage(this.getClass(), "DataResultFilterNode.action.viewInNewWin.text"), n)); - actions.add(new ExternalViewerAction( + actionsList.add(new ExternalViewerAction( NbBundle.getMessage(this.getClass(), "DataResultFilterNode.action.openInExtViewer.text"), n)); - actions.add(null); // creates a menu separator - actions.add(ExtractAction.getInstance()); + actionsList.add(null); // creates a menu separator + actionsList.add(ExtractAction.getInstance()); if (md5Action) { - actions.add(new HashSearchAction( + actionsList.add(new HashSearchAction( NbBundle.getMessage(this.getClass(), "DataResultFilterNode.action.searchFilesSameMd5.text"), n)); } - actions.add(null); // creates a menu separator - actions.add(AddContentTagAction.getInstance()); - actions.add(AddBlackboardArtifactTagAction.getInstance()); - actions.addAll(ContextMenuExtensionPoint.getActions()); + actionsList.add(null); // creates a menu separator + actionsList.add(AddContentTagAction.getInstance()); + actionsList.add(AddBlackboardArtifactTagAction.getInstance()); + + final Collection selectedFilesList = + new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class)); + if(selectedFilesList.size() == 1) { + actionsList.add(DeleteFileContentTagAction.getInstance()); + } } else { // There's no specific file associated with the artifact, but // we can still tag the artifact itself - actions.add(null); - actions.add(AddBlackboardArtifactTagAction.getInstance()); + actionsList.add(null); + actionsList.add(AddBlackboardArtifactTagAction.getInstance()); } - return actions; + + final Collection selectedArtifactsList = + new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class)); + if(selectedArtifactsList.size() == 1) { + actionsList.add(DeleteFileBlackboardArtifactTagAction.getInstance()); + } + + if(n != null) { + actionsList.addAll(ContextMenuExtensionPoint.getActions()); + } + + return actionsList; } @Override diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ExplorerNodeActionVisitor.java b/Core/src/org/sleuthkit/autopsy/directorytree/ExplorerNodeActionVisitor.java index 27cc6dbcca..86c3df1fe3 100755 --- a/Core/src/org/sleuthkit/autopsy/directorytree/ExplorerNodeActionVisitor.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/ExplorerNodeActionVisitor.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2014 Basis Technology Corp. + * Copyright 2011-2017 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,13 +19,18 @@ package org.sleuthkit.autopsy.directorytree; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.List; import javax.swing.AbstractAction; import javax.swing.Action; import org.openide.util.NbBundle; +import org.openide.util.Utilities; import org.sleuthkit.autopsy.actions.AddContentTagAction; +import org.sleuthkit.autopsy.actions.DeleteFileContentTagAction; import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint; +import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.ContentVisitor; import org.sleuthkit.datamodel.DerivedFile; @@ -85,48 +90,82 @@ public class ExplorerNodeActionVisitor extends ContentVisitor.Default visit(final Directory d) { - List actions = new ArrayList<>(); - actions.add(AddContentTagAction.getInstance()); - actions.addAll(ContextMenuExtensionPoint.getActions()); - return actions; + List actionsList = new ArrayList<>(); + actionsList.add(AddContentTagAction.getInstance()); + + final Collection selectedFilesList = + new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class)); + if(selectedFilesList.size() == 1) { + actionsList.add(DeleteFileContentTagAction.getInstance()); + } + + actionsList.addAll(ContextMenuExtensionPoint.getActions()); + return actionsList; } @Override public List visit(final VirtualDirectory d) { - List actions = new ArrayList<>(); + List actionsList = new ArrayList<>(); if (!d.isDataSource()) { - actions.add(AddContentTagAction.getInstance()); + actionsList.add(AddContentTagAction.getInstance()); + + final Collection selectedFilesList = + new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class)); + if(selectedFilesList.size() == 1) { + actionsList.add(DeleteFileContentTagAction.getInstance()); + } } - actions.add(ExtractAction.getInstance()); - actions.addAll(ContextMenuExtensionPoint.getActions()); - return actions; + actionsList.add(ExtractAction.getInstance()); + actionsList.addAll(ContextMenuExtensionPoint.getActions()); + return actionsList; } @Override public List visit(final DerivedFile d) { - List actions = new ArrayList<>(); - actions.add(ExtractAction.getInstance()); - actions.add(AddContentTagAction.getInstance()); - actions.addAll(ContextMenuExtensionPoint.getActions()); - return actions; + List actionsList = new ArrayList<>(); + actionsList.add(ExtractAction.getInstance()); + actionsList.add(AddContentTagAction.getInstance()); + + final Collection selectedFilesList = + new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class)); + if(selectedFilesList.size() == 1) { + actionsList.add(DeleteFileContentTagAction.getInstance()); + } + + actionsList.addAll(ContextMenuExtensionPoint.getActions()); + return actionsList; } @Override public List visit(final LocalFile d) { - List actions = new ArrayList<>(); - actions.add(ExtractAction.getInstance()); - actions.add(AddContentTagAction.getInstance()); - actions.addAll(ContextMenuExtensionPoint.getActions()); - return actions; + List actionsList = new ArrayList<>(); + actionsList.add(ExtractAction.getInstance()); + actionsList.add(AddContentTagAction.getInstance()); + + final Collection selectedFilesList = + new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class)); + if(selectedFilesList.size() == 1) { + actionsList.add(DeleteFileContentTagAction.getInstance()); + } + + actionsList.addAll(ContextMenuExtensionPoint.getActions()); + return actionsList; } @Override public List visit(final org.sleuthkit.datamodel.File d) { - List actions = new ArrayList<>(); - actions.add(ExtractAction.getInstance()); - actions.add(AddContentTagAction.getInstance()); - actions.addAll(ContextMenuExtensionPoint.getActions()); - return actions; + List actionsList = new ArrayList<>(); + actionsList.add(ExtractAction.getInstance()); + actionsList.add(AddContentTagAction.getInstance()); + + final Collection selectedFilesList = + new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class)); + if(selectedFilesList.size() == 1) { + actionsList.add(DeleteFileContentTagAction.getInstance()); + } + + actionsList.addAll(ContextMenuExtensionPoint.getActions()); + return actionsList; } @Override diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/DeleteTagAction.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/DeleteTagAction.java new file mode 100755 index 0000000000..5fc73fc656 --- /dev/null +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/DeleteTagAction.java @@ -0,0 +1,164 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2017 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.imagegallery.actions; + +import java.awt.Window; +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.logging.Level; +import javafx.application.Platform; +import javafx.scene.control.Alert; +import javafx.scene.control.Menu; +import javafx.scene.control.MenuItem; +import javafx.scene.image.ImageView; +import javax.swing.SwingUtilities; +import javax.swing.SwingWorker; +import org.controlsfx.control.action.Action; +import org.controlsfx.control.action.ActionUtils; +import org.openide.util.NbBundle; +import org.openide.util.Utilities; +import org.openide.windows.TopComponent; +import org.openide.windows.WindowManager; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; +import org.sleuthkit.autopsy.imagegallery.ImageGalleryTopComponent; +import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute; +import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableTagsManager; +import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.ContentTag; +import org.sleuthkit.datamodel.TagName; +import org.sleuthkit.datamodel.TskCoreException; + +/** + * Instances of this Action allow users to remove tags from content. + */ +public class DeleteTagAction extends Action { + + private static final Logger LOGGER = Logger.getLogger(DeleteTagAction.class.getName()); + + private final ImageGalleryController controller; + private final long fileId; + private final TagName tagName; + private final ContentTag contentTag; + + public DeleteTagAction(ImageGalleryController controller, TagName tagName, ContentTag contentTag, long fileId) { + super(tagName.getDisplayName()); + this.controller = controller; + this.fileId = fileId; + this.tagName = tagName; + this.contentTag = contentTag; + setGraphic(controller.getTagsManager().getGraphic(tagName)); + setText(tagName.getDisplayName()); + setEventHandler(actionEvent -> deleteTag()); + } + + static public Menu getTagMenu(ImageGalleryController controller) { + return new TagMenu(controller); + } + + @NbBundle.Messages({"# {0} - fileID", + "DeleteDrawableTagAction.deleteTag.alert=Unable to untag file {0}."}) + private void deleteTag() { + new SwingWorker() { + + @Override + protected Void doInBackground() throws Exception { + DrawableTagsManager tagsManager = controller.getTagsManager(); + + // Pull the from the global context to avoid unnecessary calls + // to the database. + final Collection selectedFilesList = + new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class)); + AbstractFile file = selectedFilesList.iterator().next(); + + try { + LOGGER.log(Level.INFO, "Removing tag {0} from {1}", new Object[]{tagName.getDisplayName(), file.getName()}); //NON-NLS + tagsManager.deleteContentTag(contentTag); + } catch (TskCoreException tskCoreException) { + LOGGER.log(Level.SEVERE, "Error untagging file", tskCoreException); //NON-NLS + Platform.runLater(() -> + new Alert(Alert.AlertType.ERROR, Bundle.DeleteDrawableTagAction_deleteTag_alert(fileId)).show() + ); + } + return null; + } + + @Override + protected void done() { + super.done(); + try { + get(); + } catch (InterruptedException | ExecutionException ex) { + LOGGER.log(Level.SEVERE, "Unexpected exception while untagging file", ex); //NON-NLS + } + } + }.execute(); + } + + @NbBundle.Messages({"DeleteDrawableTagAction.displayName=Remove File Tag"}) + private static class TagMenu extends Menu { + + TagMenu(ImageGalleryController controller) { + setGraphic(new ImageView(DrawableAttribute.TAGS.getIcon())); + setText(Bundle.DeleteDrawableTagAction_displayName()); + + // For this menu, we shouldn't have more than one file selected. + // Therefore, we will simply grab the first file and work with that. + final Collection selectedFilesList = + new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class)); + AbstractFile file = selectedFilesList.iterator().next(); + + try { + List existingTagsList = + Case.getCurrentCase().getServices().getTagsManager() + .getContentTagsByContent(file); + + Collection tagNamesList = + controller.getTagsManager().getNonCategoryTagNames(); + Iterator tagNameIterator = tagNamesList.iterator(); + for(int i=0; tagNameIterator.hasNext(); i++) { + TagName tagName = tagNameIterator.next(); + for(ContentTag contentTag : existingTagsList) { + if(contentTag.getName().getId() == tagName.getId()) { + DeleteTagAction deleteDrawableTagAction = new DeleteTagAction(controller, tagName, contentTag, file.getId()); + MenuItem tagNameItem = ActionUtils.createMenuItem(deleteDrawableTagAction); + getItems().add(tagNameItem); + } + } + } + } catch (TskCoreException ex) { + Logger.getLogger(TagMenu.class.getName()) + .log(Level.SEVERE, "Error retrieving tags for TagMenu", ex); //NON-NLS + } + + if(getItems().isEmpty()) { + setDisable(true); + } + } + } + + static private Window getIGWindow() { + TopComponent etc = WindowManager.getDefault().findTopComponent(ImageGalleryTopComponent.PREFERRED_ID); + return SwingUtilities.getWindowAncestor(etc); + } +} diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/DrawableTileBase.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/DrawableTileBase.java index d9f93fe03c..243045d789 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/DrawableTileBase.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/DrawableTileBase.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013-16 Basis Technology Corp. + * Copyright 2013-2017 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.imagegallery.gui.drawableviews; import com.google.common.eventbus.Subscribe; import java.util.ArrayList; import java.util.Collection; +import java.util.HashSet; import java.util.Optional; import java.util.logging.Level; import javafx.application.Platform; @@ -49,6 +50,7 @@ import javax.swing.SwingUtilities; import org.controlsfx.control.action.ActionUtils; import org.openide.util.Lookup; import org.openide.util.NbBundle; +import org.openide.util.Utilities; import org.openide.util.actions.Presenter; import org.openide.windows.TopComponent; import org.openide.windows.WindowManager; @@ -66,10 +68,12 @@ import org.sleuthkit.autopsy.imagegallery.ImageGalleryTopComponent; import org.sleuthkit.autopsy.imagegallery.actions.AddTagAction; import org.sleuthkit.autopsy.imagegallery.actions.CategorizeAction; import org.sleuthkit.autopsy.imagegallery.actions.DeleteFollowUpTagAction; +import org.sleuthkit.autopsy.imagegallery.actions.DeleteTagAction; import org.sleuthkit.autopsy.imagegallery.actions.OpenExternalViewerAction; import org.sleuthkit.autopsy.imagegallery.actions.SwingMenuItemAdapter; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile; +import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.ContentTag; import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TskCoreException; @@ -184,6 +188,11 @@ public abstract class DrawableTileBase extends DrawableUIBase { menuItems.add(CategorizeAction.getCategoriesMenu(getController())); menuItems.add(AddTagAction.getTagMenu(getController())); + + final Collection selectedFilesList = new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class)); + if(selectedFilesList.size() == 1) { + menuItems.add(DeleteTagAction.getTagMenu(getController())); + } final MenuItem extractMenuItem = new MenuItem(Bundle.DrawableTileBase_menuItem_extractFiles()); extractMenuItem.setOnAction(actionEvent -> { diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchFilterNode.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchFilterNode.java index 7e147c1ba6..47b36de0be 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchFilterNode.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchFilterNode.java @@ -19,6 +19,8 @@ package org.sleuthkit.autopsy.keywordsearch; import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; import java.util.List; import javax.swing.Action; import org.openide.nodes.FilterNode; @@ -26,14 +28,17 @@ import org.openide.nodes.Node; import org.openide.nodes.Node.Property; import org.openide.nodes.Sheet; import org.openide.util.NbBundle; +import org.openide.util.Utilities; import org.openide.util.lookup.Lookups; import org.openide.util.lookup.ProxyLookup; import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint; import org.sleuthkit.autopsy.directorytree.ExternalViewerAction; import org.sleuthkit.autopsy.directorytree.ExtractAction; import org.sleuthkit.autopsy.actions.AddContentTagAction; +import org.sleuthkit.autopsy.actions.DeleteFileContentTagAction; import org.sleuthkit.autopsy.directorytree.HashSearchAction; import org.sleuthkit.autopsy.directorytree.NewWindowViewAction; +import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.ContentVisitor; import org.sleuthkit.datamodel.DerivedFile; @@ -107,16 +112,23 @@ class KeywordSearchFilterNode extends FilterNode { } private List getFileActions() { - List actions = new ArrayList<>(); - actions.add(new NewWindowViewAction(NbBundle.getMessage(this.getClass(), "KeywordSearchFilterNode.getFileActions.viewInNewWinActionLbl"), KeywordSearchFilterNode.this)); - actions.add(new ExternalViewerAction(NbBundle.getMessage(this.getClass(), "KeywordSearchFilterNode.getFileActions.openExternViewActLbl"), getOriginal())); - actions.add(null); - actions.add(ExtractAction.getInstance()); - actions.add(new HashSearchAction(NbBundle.getMessage(this.getClass(), "KeywordSearchFilterNode.getFileActions.searchSameMd5"), getOriginal())); - actions.add(null); // creates a menu separator - actions.add(AddContentTagAction.getInstance()); - actions.addAll(ContextMenuExtensionPoint.getActions()); - return actions; + List actionsList = new ArrayList<>(); + actionsList.add(new NewWindowViewAction(NbBundle.getMessage(this.getClass(), "KeywordSearchFilterNode.getFileActions.viewInNewWinActionLbl"), KeywordSearchFilterNode.this)); + actionsList.add(new ExternalViewerAction(NbBundle.getMessage(this.getClass(), "KeywordSearchFilterNode.getFileActions.openExternViewActLbl"), getOriginal())); + actionsList.add(null); + actionsList.add(ExtractAction.getInstance()); + actionsList.add(new HashSearchAction(NbBundle.getMessage(this.getClass(), "KeywordSearchFilterNode.getFileActions.searchSameMd5"), getOriginal())); + actionsList.add(null); // creates a menu separator + actionsList.add(AddContentTagAction.getInstance()); + + final Collection selectedFilesList = + new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class)); + if(selectedFilesList.size() == 1) { + actionsList.add(DeleteFileContentTagAction.getInstance()); + } + + actionsList.addAll(ContextMenuExtensionPoint.getActions()); + return actionsList; } @Override From a1272ff548e0e47c446d490c49bedec8f7a8e559 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 19 Apr 2017 13:31:19 -0400 Subject: [PATCH 15/37] 2453 remove volatile add GuardedBy annotation for guarded boolean --- Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java index 6b6fa63e35..f667a75825 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java @@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.casemodule; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; +import javax.annotation.concurrent.GuardedBy; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback.DataSourceProcessorResult; @@ -61,7 +62,9 @@ class AddImageTask implements Runnable { * TODO (AUT-2021): Merge SleuthkitJNI.AddImageProcess and AddImageTask */ private final Object tskAddImageProcessLock; - volatile private boolean tskAddImageProcessStopped; + + @GuardedBy("tskAddImageProcessLock") + private boolean tskAddImageProcessStopped; private SleuthkitJNI.CaseDbHandle.AddImageProcess tskAddImageProcess; /** From e23e48cda5dfa7a87820ddc12cdf60600791538c Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Wed, 19 Apr 2017 15:35:48 -0400 Subject: [PATCH 16/37] Addition try/catch modifications to hide more log messages. --- .../embeddedfileextractor/ImageExtractor.java | 165 +++++++----------- 1 file changed, 64 insertions(+), 101 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/ImageExtractor.java b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/ImageExtractor.java index 1493bb7dca..cfc1682f97 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/ImageExtractor.java +++ b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/ImageExtractor.java @@ -122,7 +122,7 @@ class ImageExtractor { } return false; } catch (TskCoreException ex) { - logger.log(Level.WARNING, "Error executing FileTypeDetector.getFileType()", ex); // NON-NLS + logger.log(Level.SEVERE, "Error executing FileTypeDetector.getFileType()", ex); // NON-NLS return false; } } @@ -154,7 +154,7 @@ class ImageExtractor { } } } catch (TskCoreException e) { - logger.log(Level.WARNING, String.format("Error checking if file already has been processed, skipping: %s", parentFileName), e); //NON-NLS + logger.log(Level.SEVERE, String.format("Error checking if file already has been processed, skipping: %s", parentFileName), e); //NON-NLS return; } switch (abstractFileExtractionFormat) { @@ -191,7 +191,7 @@ class ImageExtractor { extractedImage.getCtime(), extractedImage.getCrtime(), extractedImage.getAtime(), extractedImage.getAtime(), true, abstractFile, null, EmbeddedFileExtractorModuleFactory.getModuleName(), null, null, TskData.EncodingType.XOR1)); } catch (TskCoreException ex) { - logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.extractImage.addToDB.exception.msg"), ex); //NON-NLS + logger.log(Level.SEVERE, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.extractImage.addToDB.exception.msg"), ex); //NON-NLS } } if (!listOfExtractedImages.isEmpty()) { @@ -209,16 +209,20 @@ class ImageExtractor { * extracted. */ private List extractImagesFromDoc(AbstractFile af) { - List listOfExtractedImages; - HWPFDocument doc = null; + List listOfAllPictures; + try { - doc = new HWPFDocument(new ReadContentInputStream(af)); - } catch (OldFileFormatException ex) { + HWPFDocument doc = new HWPFDocument(new ReadContentInputStream(af)); + PicturesTable pictureTable = doc.getPicturesTable(); + listOfAllPictures = pictureTable.getAllPictures(); + } catch (OldFileFormatException | IOException ex) { + // OldFileFormatException: // Thrown when the document version is unsupported (Word 95 and // older) - return null; - } catch (IOException ex) { + + // IOException: // Thrown when the document has issues being read. + return null; } catch (Throwable ex) { // instantiating POI containers throw RuntimeExceptions @@ -226,17 +230,6 @@ class ImageExtractor { return null; } - PicturesTable pictureTable = null; - List listOfAllPictures = null; - try { - pictureTable = doc.getPicturesTable(); - listOfAllPictures = pictureTable.getAllPictures(); - } catch (Exception ex) { - // log internal Java and Apache errors as WARNING - logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.processing.err", af.getName()), ex); //NON-NLS - return null; - } - String outputFolderPath; if (listOfAllPictures.isEmpty()) { return null; @@ -246,7 +239,7 @@ class ImageExtractor { if (outputFolderPath == null) { return null; } - listOfExtractedImages = new ArrayList<>(); + List listOfExtractedImages = new ArrayList<>(); byte[] data = null; for (org.apache.poi.hwpf.usermodel.Picture picture : listOfAllPictures) { String fileName = picture.suggestFullFileName(); @@ -274,29 +267,24 @@ class ImageExtractor { * extracted. */ private List extractImagesFromDocx(AbstractFile af) { - List listOfExtractedImages; - XWPFDocument docx = null; + List listOfAllPictures = null; + try { - docx = new XWPFDocument(new ReadContentInputStream(af)); - } catch (POIXMLException ex) { + XWPFDocument docx = new XWPFDocument(new ReadContentInputStream(af)); + listOfAllPictures = docx.getAllPictures(); + } catch (POIXMLException | IOException ex) { + // POIXMLException: // Thrown when document fails to load - return null; - } catch (IOException ex) { + + // IOException: // Thrown when the document has issues being read. + return null; } catch (Throwable ex) { // instantiating POI containers throw RuntimeExceptions logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.docxContainer.init.err", af.getName()), ex); //NON-NLS return null; } - List listOfAllPictures = null; - try { - listOfAllPictures = docx.getAllPictures(); - } catch (Exception ex) { - // log internal Java and Apache errors as WARNING - logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.processing.err", af.getName()), ex); //NON-NLS - return null; - } // if no images are extracted from the PPT, return null, else initialize // the output folder for image extraction. @@ -310,7 +298,7 @@ class ImageExtractor { logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.extractImageFrom.outputPath.exception.msg", af.getName())); //NON-NLS return null; } - listOfExtractedImages = new ArrayList<>(); + List listOfExtractedImages = new ArrayList<>(); byte[] data = null; for (XWPFPictureData xwpfPicture : listOfAllPictures) { String fileName = xwpfPicture.getFileName(); @@ -336,15 +324,18 @@ class ImageExtractor { * extracted. */ private List extractImagesFromPpt(AbstractFile af) { - List listOfExtractedImages; - SlideShow ppt = null; + PictureData[] listOfAllPictures = null; + try { - ppt = new SlideShow(new ReadContentInputStream(af)); - } catch (OldFileFormatException ex) { + SlideShow ppt = new SlideShow(new ReadContentInputStream(af)); + listOfAllPictures = ppt.getPictureData(); + } catch (OldFileFormatException | IOException ex) { + // OldFileFormatException: // Thrown when the document version is unsupported - return null; - } catch (IOException ex) { + + // IOException: // Thrown when the document has issues being read + return null; } catch (Throwable ex) { // instantiating POI containers throw RuntimeExceptions @@ -352,16 +343,6 @@ class ImageExtractor { return null; } - //extract all pictures contained in the presentation - PictureData[] listOfAllPictures = null; - try { - listOfAllPictures = ppt.getPictureData(); - } catch (Exception ex) { - // log internal Java and Apache errors as WARNING - logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.processing.err", af.getName()), ex); //NON-NLS - return null; - } - // if no images are extracted from the PPT, return null, else initialize // the output folder for image extraction. String outputFolderPath; @@ -378,7 +359,7 @@ class ImageExtractor { // extract the images to the above initialized outputFolder. // extraction path - outputFolder/image_number.ext int i = 0; - listOfExtractedImages = new ArrayList<>(); + List listOfExtractedImages = new ArrayList<>(); byte[] data = null; for (PictureData pictureData : listOfAllPictures) { @@ -429,29 +410,24 @@ class ImageExtractor { * extracted. */ private List extractImagesFromPptx(AbstractFile af) { - List listOfExtractedImages; - XMLSlideShow pptx; + List listOfAllPictures = null; + try { - pptx = new XMLSlideShow(new ReadContentInputStream(af)); - } catch (POIXMLException ex) { + XMLSlideShow pptx = new XMLSlideShow(new ReadContentInputStream(af)); + listOfAllPictures = pptx.getAllPictures(); + } catch (POIXMLException | IOException ex) { + // POIXMLException: // Thrown when document fails to load. - return null; - } catch (IOException ex) { + + // IOException: // Thrown when the document has issues being read + return null; } catch (Throwable ex) { // instantiating POI containers throw RuntimeExceptions logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.pptxContainer.init.err", af.getName()), ex); //NON-NLS return null; } - List listOfAllPictures = null; - try { - listOfAllPictures = pptx.getAllPictures(); - } catch (Exception ex) { - // log internal Java and Apache errors as WARNING - logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.processing.err", af.getName()), ex); //NON-NLS - return null; - } // if no images are extracted from the PPT, return null, else initialize // the output folder for image extraction. @@ -466,7 +442,7 @@ class ImageExtractor { return null; } - listOfExtractedImages = new ArrayList<>(); + List listOfExtractedImages = new ArrayList<>(); byte[] data = null; for (XSLFPictureData xslsPicture : listOfAllPictures) { @@ -498,16 +474,18 @@ class ImageExtractor { * extracted. */ private List extractImagesFromXls(AbstractFile af) { - List listOfExtractedImages; - - Workbook xls; + List listOfAllPictures = null; + try { - xls = new HSSFWorkbook(new ReadContentInputStream(af)); - } catch (OldFileFormatException ex) { + Workbook xls = new HSSFWorkbook(new ReadContentInputStream(af)); + listOfAllPictures = xls.getAllPictures(); + } catch (OldFileFormatException | IOException ex) { + // OldFileFormatException: // Thrown when the document version is unsupported - return null; - } catch (IOException ex) { + + // IOException: // Thrown when the document has issues being read + return null; } catch (Throwable ex) { // instantiating POI containers throw RuntimeExceptions @@ -515,15 +493,6 @@ class ImageExtractor { return null; } - List listOfAllPictures = null; - try { - listOfAllPictures = xls.getAllPictures(); - } catch (Exception ex) { - // log internal Java and Apache errors as WARNING - logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.processing.err", af.getName()), ex); //NON-NLS - return null; - } - // if no images are extracted from the PPT, return null, else initialize // the output folder for image extraction. String outputFolderPath; @@ -538,7 +507,7 @@ class ImageExtractor { } int i = 0; - listOfExtractedImages = new ArrayList<>(); + List listOfExtractedImages = new ArrayList<>(); byte[] data = null; for (org.apache.poi.ss.usermodel.PictureData pictureData : listOfAllPictures) { String imageName = UNKNOWN_NAME_PREFIX + i + "." + pictureData.suggestFileExtension(); //NON-NLS @@ -566,15 +535,18 @@ class ImageExtractor { * extracted. */ private List extractImagesFromXlsx(AbstractFile af) { - List listOfExtractedImages; - Workbook xlsx; + List listOfAllPictures = null; + try { - xlsx = new XSSFWorkbook(new ReadContentInputStream(af)); - } catch (POIXMLException ex) { + Workbook xlsx = new XSSFWorkbook(new ReadContentInputStream(af)); + listOfAllPictures = xlsx.getAllPictures(); + } catch (POIXMLException | IOException ex) { + // POIXMLException: // Thrown when document fails to load. - return null; - } catch (IOException ex) { + + // IOException: // Thrown when the document has issues being read + return null; } catch (Throwable ex) { // instantiating POI containers throw RuntimeExceptions @@ -582,15 +554,6 @@ class ImageExtractor { return null; } - List listOfAllPictures = null; - try { - listOfAllPictures = xlsx.getAllPictures(); - } catch (Exception ex) { - // log internal Java and Apache errors as WARNING - logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.processing.err", af.getName()), ex); //NON-NLS - return null; - } - // if no images are extracted from the PPT, return null, else initialize // the output folder for image extraction. String outputFolderPath; @@ -605,7 +568,7 @@ class ImageExtractor { } int i = 0; - listOfExtractedImages = new ArrayList<>(); + List listOfExtractedImages = new ArrayList<>(); byte[] data = null; for (org.apache.poi.ss.usermodel.PictureData pictureData : listOfAllPictures) { String imageName = UNKNOWN_NAME_PREFIX + i + "." + pictureData.suggestFileExtension(); From 92e79c9a28624d5317b8852b6b3c8a92982f1ae8 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Wed, 19 Apr 2017 16:55:07 -0400 Subject: [PATCH 17/37] Cleanup work. --- .../autopsy/actions/AddBlackboardArtifactTagAction.java | 1 + .../sleuthkit/autopsy/actions/AddContentTagAction.java | 3 +++ .../actions/DeleteBlackboardArtifactTagAction.java | 5 +---- .../autopsy/actions/DeleteContentTagAction.java | 5 +---- .../actions/DeleteFileBlackboardArtifactTagAction.java | 4 ---- .../autopsy/actions/DeleteFileContentTagAction.java | 9 +++------ .../autopsy/imagegallery/actions/DeleteTagAction.java | 5 ----- 7 files changed, 9 insertions(+), 23 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/actions/AddBlackboardArtifactTagAction.java b/Core/src/org/sleuthkit/autopsy/actions/AddBlackboardArtifactTagAction.java index 85d5b7b668..3791df932f 100755 --- a/Core/src/org/sleuthkit/autopsy/actions/AddBlackboardArtifactTagAction.java +++ b/Core/src/org/sleuthkit/autopsy/actions/AddBlackboardArtifactTagAction.java @@ -37,6 +37,7 @@ import org.sleuthkit.datamodel.TskCoreException; @NbBundle.Messages({ "AddBlackboardArtifactTagAction.singularTagResult=Tag Result", "AddBlackboardArtifactTagAction.pluralTagResult=Tag Results", + "# {0} - artifactName", "AddBlackboardArtifactTagAction.unableToTag.msg=Unable to tag {0}.", "AddBlackboardArtifactTagAction.taggingErr=Tagging Error" }) diff --git a/Core/src/org/sleuthkit/autopsy/actions/AddContentTagAction.java b/Core/src/org/sleuthkit/autopsy/actions/AddContentTagAction.java index d6442c9b0a..227755e1f6 100755 --- a/Core/src/org/sleuthkit/autopsy/actions/AddContentTagAction.java +++ b/Core/src/org/sleuthkit/autopsy/actions/AddContentTagAction.java @@ -38,10 +38,13 @@ import org.sleuthkit.datamodel.TskCoreException; @NbBundle.Messages({ "AddContentTagAction.singularTagFile=Tag File", "AddContentTagAction.pluralTagFile=Tag Files", + "# {0} - fileName", "AddContentTagAction.unableToTag.msg=Unable to tag {0}, not a regular file.", "AddContentTagAction.cannotApplyTagErr=Cannot Apply Tag", + "# {0} - fileName", "AddContentTagAction.unableToTag.msg2=Unable to tag {0}.", "AddContentTagAction.taggingErr=Tagging Error", + "# {0} - fileName", "# {1} - tagName", "AddContentTagAction.tagExists={0} has been tagged as {1}. Cannot reapply the same tag." }) public class AddContentTagAction extends AddTagAction { diff --git a/Core/src/org/sleuthkit/autopsy/actions/DeleteBlackboardArtifactTagAction.java b/Core/src/org/sleuthkit/autopsy/actions/DeleteBlackboardArtifactTagAction.java index cda4eb39a8..2dd62285ba 100755 --- a/Core/src/org/sleuthkit/autopsy/actions/DeleteBlackboardArtifactTagAction.java +++ b/Core/src/org/sleuthkit/autopsy/actions/DeleteBlackboardArtifactTagAction.java @@ -45,6 +45,7 @@ import org.sleuthkit.datamodel.TskCoreException; */ @NbBundle.Messages({ "DeleteBlackboardArtifactTagAction.deleteTag=Delete Tag", + "# {0} - tagName", "DeleteBlackboardArtifactTagAction.unableToDelTag.msg=Unable to delete tag {0}.", "DeleteBlackboardArtifactTagAction.tagDelErr=Tag Deletion Error" }) @@ -96,10 +97,6 @@ public class DeleteBlackboardArtifactTagAction extends AbstractAction { }).start(); } - protected String getActionDisplayName() { - return MENU_TEXT; - } - @NbBundle.Messages({"# {0} - artifactID", "DeleteBlackboardArtifactTagAction.deleteTag.alert=Unable to untag artifact {0}."}) protected void deleteTag(TagName tagName, BlackboardArtifactTag artifactTag, long artifactId) { diff --git a/Core/src/org/sleuthkit/autopsy/actions/DeleteContentTagAction.java b/Core/src/org/sleuthkit/autopsy/actions/DeleteContentTagAction.java index afa7e49506..2170bff014 100755 --- a/Core/src/org/sleuthkit/autopsy/actions/DeleteContentTagAction.java +++ b/Core/src/org/sleuthkit/autopsy/actions/DeleteContentTagAction.java @@ -44,6 +44,7 @@ import org.sleuthkit.datamodel.TskCoreException; */ @NbBundle.Messages({ "DeleteContentTagAction.deleteTag=Delete Tag", + "# {0} - tagName", "DeleteContentTagAction.unableToDelTag.msg=Unable to delete tag {0}.", "DeleteContentTagAction.tagDelErr=Tag Deletion Error" }) @@ -118,10 +119,6 @@ public class DeleteContentTagAction extends AbstractAction { protected void refreshDirectoryTree() { } - protected String getActionDisplayName() { - return MENU_TEXT; - } - @NbBundle.Messages({"# {0} - fileID", "DeleteContentTagAction.deleteTag.alert=Unable to untag file {0}."}) protected void deleteTag(TagName tagName, ContentTag contentTag, long fileId) { diff --git a/Core/src/org/sleuthkit/autopsy/actions/DeleteFileBlackboardArtifactTagAction.java b/Core/src/org/sleuthkit/autopsy/actions/DeleteFileBlackboardArtifactTagAction.java index 4c1e52d828..afb17804b7 100755 --- a/Core/src/org/sleuthkit/autopsy/actions/DeleteFileBlackboardArtifactTagAction.java +++ b/Core/src/org/sleuthkit/autopsy/actions/DeleteFileBlackboardArtifactTagAction.java @@ -31,8 +31,6 @@ import javafx.scene.control.Alert; import javax.swing.AbstractAction; import javax.swing.JMenu; import javax.swing.JMenuItem; -import javax.swing.JOptionPane; -import javax.swing.SwingUtilities; import javax.swing.SwingWorker; import org.openide.util.NbBundle; import org.openide.util.Utilities; @@ -134,8 +132,6 @@ public class DeleteFileBlackboardArtifactTagAction extends AbstractAction implem * creating or selecting a tag name for a tag and specifying an optional tag * comment. */ - // @@@ This user interface has some significant usability issues and needs - // to be reworked. @NbBundle.Messages({"# {0} - artifactID", "DeleteFileBlackboardArtifactTagAction.deleteTags.alert=Unable to untag artifact {0}."}) private class TagMenu extends JMenu { diff --git a/Core/src/org/sleuthkit/autopsy/actions/DeleteFileContentTagAction.java b/Core/src/org/sleuthkit/autopsy/actions/DeleteFileContentTagAction.java index 0da884c34e..5cc37e3900 100755 --- a/Core/src/org/sleuthkit/autopsy/actions/DeleteFileContentTagAction.java +++ b/Core/src/org/sleuthkit/autopsy/actions/DeleteFileContentTagAction.java @@ -31,8 +31,6 @@ import javafx.scene.control.Alert; import javax.swing.AbstractAction; import javax.swing.JMenu; import javax.swing.JMenuItem; -import javax.swing.JOptionPane; -import javax.swing.SwingUtilities; import javax.swing.SwingWorker; import org.openide.util.NbBundle; import org.openide.util.Utilities; @@ -88,8 +86,9 @@ public class DeleteFileContentTagAction extends AbstractAction implements Presen return MENU_TEXT; } - @NbBundle.Messages({"# {0} - fileID", - "DeleteFileContentTagAction.deleteTag.alert=Unable to untag file {0}."}) + @NbBundle.Messages({ + "# {0} - fileID", + "DeleteFileContentTagAction.deleteTag.alert=Unable to untag file {0}."}) protected void deleteTag(TagName tagName, ContentTag contentTag, long fileId) { new SwingWorker() { @@ -132,8 +131,6 @@ public class DeleteFileContentTagAction extends AbstractAction implements Presen * creating or selecting a tag name for a tag and specifying an optional tag * comment. */ - // @@@ This user interface has some significant usability issues and needs - // to be reworked. private class TagMenu extends JMenu { private static final long serialVersionUID = 1L; diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/DeleteTagAction.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/DeleteTagAction.java index 5fc73fc656..53a033a2c9 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/DeleteTagAction.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/DeleteTagAction.java @@ -156,9 +156,4 @@ public class DeleteTagAction extends Action { } } } - - static private Window getIGWindow() { - TopComponent etc = WindowManager.getDefault().findTopComponent(ImageGalleryTopComponent.PREFERRED_ID); - return SwingUtilities.getWindowAncestor(etc); - } } From ec2c8d6abf05e3c6e1f8755b1d44f8aed97e41e6 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 19 Apr 2017 16:59:19 -0400 Subject: [PATCH 18/37] 2453 added wait cursor while cancelling addImage in case it takes a bit --- .../autopsy/casemodule/AddImageWizardAddingProgressPanel.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardAddingProgressPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardAddingProgressPanel.java index 22a6ee9762..cf206a39d8 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardAddingProgressPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardAddingProgressPanel.java @@ -19,6 +19,7 @@ package org.sleuthkit.autopsy.casemodule; import java.awt.Color; +import java.awt.Cursor; import java.awt.EventQueue; import java.awt.Window; import java.util.ArrayList; @@ -36,6 +37,7 @@ import org.openide.WizardDescriptor; import org.openide.util.HelpCtx; import org.openide.util.Lookup; import org.openide.util.NbBundle; +import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor; @@ -319,8 +321,10 @@ class AddImageWizardAddingProgressPanel extends ShortcutWizardDescriptorPanel { cleanupTask = addImageAction.new CleanupTask() { @Override void cleanup() throws Exception { + WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); cancelDataSourceProcessing(dataSourceId); cancelled = true; + WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); } }; From 57e5d5e5c98d09aa0feb59c0a07064b4abcfc9ad Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Thu, 20 Apr 2017 11:51:46 -0400 Subject: [PATCH 19/37] 2572 fix merge of bundle.properties files between agency logo and release --- .../autopsy/corecomponents/Bundle.properties | 19 +------------------ .../corecomponents/Bundle_ja.properties | 15 --------------- 2 files changed, 1 insertion(+), 33 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties index a06a7a8215..183a66a263 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties @@ -191,26 +191,9 @@ MultiUserSettingsPanel.lbTestSolrWarning.text= MultiUserSettingsPanel.lbTestDbWarning.text= MultiUserSettingsPanel.KeywordSearchNull=Cannot find keyword search service MultiUserSettingsPanel.InvalidPortNumber=Invalid port number -AutopsyOptionsPanel.useBestViewerRB.text=Change to the most specific file viewer AutopsyOptionsPanel.jLabelHideSlackFiles.text=Hide slack files in the: -AutopsyOptionsPanel.viewsHideSlackCB.text=Views area AutopsyOptionsPanel.dataSourcesHideSlackCB.text=Data Sources area (the directory hierarchy) -AutopsyOptionsPanel.jFormattedTextFieldProcTimeOutHrs.text=60 -AutopsyOptionsPanel.jLabelProcessTimeOutUnits.text=hour(s) -AutopsyOptionsPanel.jCheckBoxEnableProcTimeout.text= -AutopsyOptionsPanel.jLabelSetProcessTimeOut.text=Enable timeout to allow modules to automatically terminate after a set amount of time: -AutopsyOptionsPanel.restartRequiredLabel.text=For this computer, a maximum of {0} file ingest threads should be used. Application restart required to take effect. -AutopsyOptionsPanel.jLabelNumThreads.text=Number of threads to use for file ingest: -AutopsyOptionsPanel.viewsHideKnownCB.text=Views area -AutopsyOptionsPanel.dataSourcesHideKnownCB.text=Data Sources area (the directory hierarchy) -AutopsyOptionsPanel.jLabelHideKnownFiles.text=Hide known files (i.e. those in the NIST NSRL) in the: -AutopsyOptionsPanel.useGMTTimeRB.text=Use GMT -AutopsyOptionsPanel.useLocalTimeRB.text=Use local time zone -AutopsyOptionsPanel.jLabelTimeDisplay.text=When displaying times: -AutopsyOptionsPanel.jLabelSelectFile.text=When selecting a file: -AutopsyOptionsPanel.keepCurrentViewerRB.toolTipText=For example, stay in Hex view when a JPEG is selected. -AutopsyOptionsPanel.keepCurrentViewerRB.text=Stay on the same file viewer -AutopsyOptionsPanel.useBestViewerRB.toolTipText=For example, change from Hex to Media when a JPEG is selected. +AutopsyOptionsPanel.viewsHideSlackCB.text=Views area AutopsyOptionsPanel.agencyLogoImageLabel.toolTipText= AutopsyOptionsPanel.agencyLogoImageLabel.text=Image to use as the agency logo for HTML reports: AutopsyOptionsPanel.browseLogosButton.text=Browse diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle_ja.properties index f2772feaae..d3a5d76e4d 100755 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle_ja.properties @@ -159,18 +159,3 @@ DataResultViewerThumbnail.thumbnailSizeComboBox.small=\u30b5\u30e0\u30cd\u30a4\u MediaViewImagePanel.errorLabel.OOMText=\u30d5\u30a1\u30a4\u30eb\u3092\u30e1\u30c7\u30a3\u30a2\u30d3\u30e5\u30fc\u306b\u8aad\u307f\u8fbc\u3081\u307e\u305b\u3093\u3067\u3057\u305f\uff1a\u30e1\u30e2\u30ea\u4e0d\u8db3\u3002 MediaViewImagePanel.errorLabel.text=\u30d5\u30a1\u30a4\u30eb\u3092\u30e1\u30c7\u30a3\u30a2\u30d3\u30e5\u30fc\u306b\u8aad\u307f\u8fbc\u3081\u307e\u305b\u3093\u3067\u3057\u305f\u3002 MediaViewImagePanel.externalViewerButton.text=\u5916\u90e8\u30d3\u30e5\u30fc\u30a2\u30fc\u3067\u958b\u304f -AutopsyOptionsPanel.useBestViewerRB.text=\u6700\u3082\u5c02\u9580\u7684\u306a\u30d5\u30a1\u30a4\u30eb\u30d3\u30e5\u30fc\u30a2\u306b\u5909\u66f4 -AutopsyOptionsPanel.jLabelProcessTimeOutUnits.text=\u6642\u9593 -AutopsyOptionsPanel.jLabelSetProcessTimeOut.text=\u4e00\u5b9a\u306e\u6642\u9593\u304c\u904e\u304e\u305f\u5f8c\u306b\u81ea\u52d5\u7684\u306b\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u505c\u6b62\u3067\u304d\u308b\u3088\u3046\u306b\u30bf\u30a4\u30e0\u30a2\u30a6\u30c8\u3092\u6709\u52b9\u5316\uff1a -AutopsyOptionsPanel.restartRequiredLabel.text=\u3053\u306e\u30b3\u30f3\u30d4\u30e5\u30fc\u30bf\u30fc\u3067\u306f\u6700\u5927{0}\u306e\u30d5\u30a1\u30a4\u30eb\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30b9\u30ec\u30c3\u30c9\u3092\u4f7f\u7528\u3059\u3079\u304d\u3067\u3059\u3002\u6709\u52b9\u306b\u3059\u308b\u306b\u306f\u518d\u8d77\u52d5\u304c\u5fc5\u8981\u3067\u3059\u3002 -AutopsyOptionsPanel.jLabelNumThreads.text=\u30d5\u30a1\u30a4\u30eb\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u306b\u4f7f\u7528\u3059\u308b\u30b9\u30ec\u30c3\u30c9\u6570\uff1a -AutopsyOptionsPanel.viewsHideKnownCB.text=\u30d3\u30e5\u30fc\u30a8\u30ea\u30a2 -AutopsyOptionsPanel.dataSourcesHideKnownCB.text=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u30a8\u30ea\u30a2\uff08\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u968e\u5c64\uff09 -AutopsyOptionsPanel.jLabelHideKnownFiles.text=\u65e2\u77e5\u30d5\u30a1\u30a4\u30eb\uff08NIST NSRL\u5185\u306e\uff09\u3092\u6b21\u306b\u96a0\u3059\uff1a -AutopsyOptionsPanel.useGMTTimeRB.text=GMT\u3092\u4f7f\u7528 -AutopsyOptionsPanel.useLocalTimeRB.text=\u30ed\u30fc\u30ab\u30eb\u30bf\u30a4\u30e0\u30be\u30fc\u30f3\u3092\u4f7f\u7528 -AutopsyOptionsPanel.jLabelTimeDisplay.text=\u6642\u9593\u3092\u8868\u793a\u3059\u308b\u5834\u5408\uff1a -AutopsyOptionsPanel.jLabelSelectFile.text=\u30d5\u30a1\u30a4\u30eb\u3092\u9078\u629e\u3059\u308b\u5834\u5408\uff1a -AutopsyOptionsPanel.keepCurrentViewerRB.toolTipText=\u4f8b\u3048\u3070\u3001JPEG\u304c\u9078\u629e\u3055\u308c\u305f\u5834\u5408\u306b\u305d\u306e\u307e\u307eHEX\u30d3\u30e5\u30fc\u3092\u4f7f\u7528\u3002 -AutopsyOptionsPanel.keepCurrentViewerRB.text=\u305d\u306e\u307e\u307e\u540c\u3058\u30d5\u30a1\u30a4\u30eb\u30d3\u30e5\u30fc\u30a2\u3092\u4f7f\u7528 -AutopsyOptionsPanel.useBestViewerRB.toolTipText=\u4f8b\u3048\u3070\u3001JPEG\u304c\u9078\u629e\u3055\u308c\u305f\u5834\u5408\u306b\u306fHEX\u304b\u3089\u30e1\u30c7\u30a3\u30a2\u306b\u5909\u66f4\u3059\u308b\u3002 From 18e921847118af35d908527cd6b6f6ce2e70300d Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Thu, 20 Apr 2017 12:12:14 -0400 Subject: [PATCH 20/37] Removed unused method. --- .../DeleteBlackboardArtifactTagAction.java | 39 ------------------- .../actions/DeleteContentTagAction.java | 39 ------------------- 2 files changed, 78 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/actions/DeleteBlackboardArtifactTagAction.java b/Core/src/org/sleuthkit/autopsy/actions/DeleteBlackboardArtifactTagAction.java index 2dd62285ba..fadf1f5adb 100755 --- a/Core/src/org/sleuthkit/autopsy/actions/DeleteBlackboardArtifactTagAction.java +++ b/Core/src/org/sleuthkit/autopsy/actions/DeleteBlackboardArtifactTagAction.java @@ -97,43 +97,4 @@ public class DeleteBlackboardArtifactTagAction extends AbstractAction { }).start(); } - @NbBundle.Messages({"# {0} - artifactID", - "DeleteBlackboardArtifactTagAction.deleteTag.alert=Unable to untag artifact {0}."}) - protected void deleteTag(TagName tagName, BlackboardArtifactTag artifactTag, long artifactId) { - new SwingWorker() { - - @Override - protected Void doInBackground() throws Exception { - TagsManager tagsManager = Case.getCurrentCase().getServices().getTagsManager(); - - // Pull the from the global context to avoid unnecessary calls - // to the database. - final Collection selectedFilesList = - new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class)); - AbstractFile file = selectedFilesList.iterator().next(); - - try { - LOGGER.log(Level.INFO, "Removing tag {0} from {1}", new Object[]{tagName.getDisplayName(), file.getName()}); //NON-NLS - tagsManager.deleteBlackboardArtifactTag(artifactTag); - } catch (TskCoreException tskCoreException) { - LOGGER.log(Level.SEVERE, "Error untagging artifact", tskCoreException); //NON-NLS - Platform.runLater(() -> - new Alert(Alert.AlertType.ERROR, Bundle.DeleteBlackboardArtifactTagAction_deleteTag_alert(artifactId)).show() - ); - } - return null; - } - - @Override - protected void done() { - super.done(); - try { - get(); - } catch (InterruptedException | ExecutionException ex) { - LOGGER.log(Level.SEVERE, "Unexpected exception while untagging artifact", ex); //NON-NLS - } - } - }.execute(); - } - } diff --git a/Core/src/org/sleuthkit/autopsy/actions/DeleteContentTagAction.java b/Core/src/org/sleuthkit/autopsy/actions/DeleteContentTagAction.java index 2170bff014..44eb19a790 100755 --- a/Core/src/org/sleuthkit/autopsy/actions/DeleteContentTagAction.java +++ b/Core/src/org/sleuthkit/autopsy/actions/DeleteContentTagAction.java @@ -119,43 +119,4 @@ public class DeleteContentTagAction extends AbstractAction { protected void refreshDirectoryTree() { } - @NbBundle.Messages({"# {0} - fileID", - "DeleteContentTagAction.deleteTag.alert=Unable to untag file {0}."}) - protected void deleteTag(TagName tagName, ContentTag contentTag, long fileId) { - new SwingWorker() { - - @Override - protected Void doInBackground() throws Exception { - TagsManager tagsManager = Case.getCurrentCase().getServices().getTagsManager(); - - // Pull the from the global context to avoid unnecessary calls - // to the database. - final Collection selectedFilesList = - new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class)); - AbstractFile file = selectedFilesList.iterator().next(); - - try { - LOGGER.log(Level.INFO, "Removing tag {0} from {1}", new Object[]{tagName.getDisplayName(), file.getName()}); //NON-NLS - tagsManager.deleteContentTag(contentTag); - } catch (TskCoreException tskCoreException) { - LOGGER.log(Level.SEVERE, "Error untagging file", tskCoreException); //NON-NLS - Platform.runLater(() -> - new Alert(Alert.AlertType.ERROR, Bundle.DeleteContentTagAction_deleteTag_alert(fileId)).show() - ); - } - return null; - } - - @Override - protected void done() { - super.done(); - try { - get(); - } catch (InterruptedException | ExecutionException ex) { - LOGGER.log(Level.SEVERE, "Unexpected exception while untagging file", ex); //NON-NLS - } - } - }.execute(); - } - } From cd8b8387cb1e6e01a29d1c61786f5a079180c930 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Thu, 20 Apr 2017 12:25:00 -0400 Subject: [PATCH 21/37] 2572 re-added browse button functionality from Agency logo branch --- .../corecomponents/AutopsyOptionsPanel.form | 3 +++ .../corecomponents/AutopsyOptionsPanel.java | 14 ++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form index bdcf2d9101..acc5371a90 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form @@ -277,6 +277,9 @@ + + + diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java index ffb88d16a8..4e27e85504 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java @@ -180,6 +180,11 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { agencyLogoPathField.setText(org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.agencyLogoPathField.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(browseLogosButton, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.browseLogosButton.text")); // NOI18N + browseLogosButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + browseLogosButtonActionPerformed(evt); + } + }); javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); jPanel1.setLayout(jPanel1Layout); @@ -300,6 +305,15 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); }//GEN-LAST:event_viewsHideSlackCBActionPerformed + private void browseLogosButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseLogosButtonActionPerformed + int returnState = fc.showOpenDialog(this); + if (returnState == JFileChooser.APPROVE_OPTION) { + String path = fc.getSelectedFile().getPath(); + agencyLogoPathField.setText(path); + firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); + } + }//GEN-LAST:event_browseLogosButtonActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JLabel agencyLogoImageLabel; private javax.swing.JTextField agencyLogoPathField; From 24d5a8efd7a3ff3f6515299e6caf70969a601f5e Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Thu, 20 Apr 2017 12:39:34 -0400 Subject: [PATCH 22/37] Removed additional logging. --- .../embeddedfileextractor/ImageExtractor.java | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/ImageExtractor.java b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/ImageExtractor.java index cfc1682f97..6b6ddf70d9 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/ImageExtractor.java +++ b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/ImageExtractor.java @@ -246,8 +246,6 @@ class ImageExtractor { try { data = picture.getContent(); } catch (Exception ex) { - // log internal Java and Apache errors as WARNING - logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.processing.err", af.getName()), ex); //NON-NLS return null; } writeExtractedImage(Paths.get(outputFolderPath, fileName).toString(), data); @@ -295,7 +293,6 @@ class ImageExtractor { outputFolderPath = getOutputFolderPath(this.parentFileName); } if (outputFolderPath == null) { - logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.extractImageFrom.outputPath.exception.msg", af.getName())); //NON-NLS return null; } List listOfExtractedImages = new ArrayList<>(); @@ -305,8 +302,6 @@ class ImageExtractor { try { data = xwpfPicture.getData(); } catch (Exception ex) { - // log internal Java and Apache errors as WARNING - logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.processing.err", af.getName()), ex); //NON-NLS return null; } writeExtractedImage(Paths.get(outputFolderPath, fileName).toString(), data); @@ -352,7 +347,6 @@ class ImageExtractor { outputFolderPath = getOutputFolderPath(this.parentFileName); } if (outputFolderPath == null) { - logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.extractImageFrom.outputPath.exception.msg", af.getName())); //NON-NLS return null; } @@ -390,8 +384,6 @@ class ImageExtractor { try { data = pictureData.getData(); } catch (Exception ex) { - // log internal Java and Apache errors as WARNING - logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.processing.err", af.getName()), ex); //NON-NLS return null; } writeExtractedImage(Paths.get(outputFolderPath, imageName).toString(), data); @@ -438,7 +430,6 @@ class ImageExtractor { outputFolderPath = getOutputFolderPath(this.parentFileName); } if (outputFolderPath == null) { - logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.extractImageFrom.outputPath.exception.msg", af.getName())); //NON-NLS return null; } @@ -452,8 +443,6 @@ class ImageExtractor { try { data = xslsPicture.getData(); } catch (Exception ex) { - // log internal Java and Apache errors as WARNING - logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.processing.err", af.getName()), ex); //NON-NLS return null; } writeExtractedImage(Paths.get(outputFolderPath, fileName).toString(), data); @@ -502,7 +491,6 @@ class ImageExtractor { outputFolderPath = getOutputFolderPath(this.parentFileName); } if (outputFolderPath == null) { - logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.extractImageFrom.outputPath.exception.msg", af.getName())); //NON-NLS return null; } @@ -514,8 +502,6 @@ class ImageExtractor { try { data = pictureData.getData(); } catch (Exception ex) { - // log internal Java and Apache errors as WARNING - logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.processing.err", af.getName()), ex); //NON-NLS return null; } writeExtractedImage(Paths.get(outputFolderPath, imageName).toString(), data); @@ -563,7 +549,6 @@ class ImageExtractor { outputFolderPath = getOutputFolderPath(this.parentFileName); } if (outputFolderPath == null) { - logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.extractImageFrom.outputPath.exception.msg", af.getName())); //NON-NLS return null; } @@ -575,8 +560,6 @@ class ImageExtractor { try { data = pictureData.getData(); } catch (Exception ex) { - // log internal Java and Apache errors as WARNING - logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.processing.err", af.getName()), ex); //NON-NLS return null; } writeExtractedImage(Paths.get(outputFolderPath, imageName).toString(), data); From a9534733939ce25524fa7d11acdb85f6a66e4ac1 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Thu, 20 Apr 2017 12:46:37 -0400 Subject: [PATCH 23/37] Removed unused error message. --- .../autopsy/modules/embeddedfileextractor/Bundle.properties | 1 - 1 file changed, 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/Bundle.properties b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/Bundle.properties index 015f818b56..c80ccaa863 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/Bundle.properties @@ -31,7 +31,6 @@ EmbeddedFileExtractorIngestModule.ImageExtractor.pptContainer.init.err=Ppt conta EmbeddedFileExtractorIngestModule.ImageExtractor.pptxContainer.init.err=Pptx container could not be initialized while reading: {0} EmbeddedFileExtractorIngestModule.ImageExtractor.xlsContainer.init.err=Xls container could not be initialized while reading: {0} EmbeddedFileExtractorIngestModule.ImageExtractor.xlsxContainer.init.err=Xlsx container could not be initialized while reading: {0} -EmbeddedFileExtractorIngestModule.ImageExtractor.processing.err=Embedded File Extractor is unable to read content of {0} EmbeddedFileExtractorIngestModule.ImageExtractor.extractImage.addToDB.exception.msg=Unable to add the derived files to the database. EmbeddedFileExtractorIngestModule.ImageExtractor.getOutputFolderPath.exception.msg=Could not get path for image extraction from Abstract File\: {0} EmbeddedFileExtractorIngestModule.ImageExtractor.getOutputFolderPath.exception.msg=Could not get path for image extraction from Abstract File: {0} From 3379e340c37cbac21e51fefd63cf35d54dd684ec Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Thu, 20 Apr 2017 16:15:11 -0400 Subject: [PATCH 24/37] Removed semi-colons and updated URLs to latest versions. --- .../FindContactsDb.py | 8 +++---- .../Aug2015DataSourceTutorial/RunExe.py | 6 ++--- .../FindBigRoundFiles.py | 8 +++---- .../CsvReportModule.py | 4 ++-- pythonExamples/dataSourceIngestModule.py | 14 +++++------ pythonExamples/fileIngestModule.py | 24 +++++++++---------- pythonExamples/fileIngestModuleWithGui.py | 3 +-- pythonExamples/reportmodule.py | 8 +++---- 8 files changed, 37 insertions(+), 38 deletions(-) diff --git a/pythonExamples/Aug2015DataSourceTutorial/FindContactsDb.py b/pythonExamples/Aug2015DataSourceTutorial/FindContactsDb.py index 6abdd85b5c..7a11ed913d 100755 --- a/pythonExamples/Aug2015DataSourceTutorial/FindContactsDb.py +++ b/pythonExamples/Aug2015DataSourceTutorial/FindContactsDb.py @@ -97,15 +97,15 @@ class ContactsDbIngestModule(DataSourceIngestModule): # Where any setup and configuration is done # 'context' is an instance of org.sleuthkit.autopsy.ingest.IngestJobContext. - # See: http://sleuthkit.org/autopsy/docs/api-docs/4.1/classorg_1_1sleuthkit_1_1autopsy_1_1ingest_1_1_ingest_job_context.html + # See: http://sleuthkit.org/autopsy/docs/api-docs/4.4/classorg_1_1sleuthkit_1_1autopsy_1_1ingest_1_1_ingest_job_context.html def startUp(self, context): self.context = context # Where the analysis is done. # The 'dataSource' object being passed in is of type org.sleuthkit.datamodel.Content. - # See: http://www.sleuthkit.org/sleuthkit/docs/jni-docs/4.3/interfaceorg_1_1sleuthkit_1_1datamodel_1_1_content.html + # See: http://www.sleuthkit.org/sleuthkit/docs/jni-docs/4.4/interfaceorg_1_1sleuthkit_1_1datamodel_1_1_content.html # 'progressBar' is of type org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProgress - # See: http://sleuthkit.org/autopsy/docs/api-docs/4.1/classorg_1_1sleuthkit_1_1autopsy_1_1ingest_1_1_data_source_ingest_module_progress.html + # See: http://sleuthkit.org/autopsy/docs/api-docs/4.4/classorg_1_1sleuthkit_1_1autopsy_1_1ingest_1_1_data_source_ingest_module_progress.html def process(self, dataSource, progressBar): # we don't know how much work there is yet @@ -120,7 +120,7 @@ class ContactsDbIngestModule(DataSourceIngestModule): numFiles = len(files) progressBar.switchToDeterminate(numFiles) - fileCount = 0; + fileCount = 0 for file in files: # Check if the user pressed cancel while we were busy diff --git a/pythonExamples/Aug2015DataSourceTutorial/RunExe.py b/pythonExamples/Aug2015DataSourceTutorial/RunExe.py index cc63b0d235..14477f06df 100755 --- a/pythonExamples/Aug2015DataSourceTutorial/RunExe.py +++ b/pythonExamples/Aug2015DataSourceTutorial/RunExe.py @@ -95,7 +95,7 @@ class RunExeIngestModule(DataSourceIngestModule): # Where any setup and configuration is done # 'context' is an instance of org.sleuthkit.autopsy.ingest.IngestJobContext. - # See: http://sleuthkit.org/autopsy/docs/api-docs/3.1/classorg_1_1sleuthkit_1_1autopsy_1_1ingest_1_1_ingest_job_context.html + # See: http://sleuthkit.org/autopsy/docs/api-docs/4.4/classorg_1_1sleuthkit_1_1autopsy_1_1ingest_1_1_ingest_job_context.html def startUp(self, context): self.context = context @@ -108,9 +108,9 @@ class RunExeIngestModule(DataSourceIngestModule): # Where the analysis is done. # The 'dataSource' object being passed in is of type org.sleuthkit.datamodel.Content. - # See: http://www.sleuthkit.org/sleuthkit/docs/jni-docs/4.3/interfaceorg_1_1sleuthkit_1_1datamodel_1_1_content.html + # See: http://www.sleuthkit.org/sleuthkit/docs/jni-docs/4.4/interfaceorg_1_1sleuthkit_1_1datamodel_1_1_content.html # 'progressBar' is of type org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProgress - # See: http://sleuthkit.org/autopsy/docs/api-docs/3.1/classorg_1_1sleuthkit_1_1autopsy_1_1ingest_1_1_data_source_ingest_module_progress.html + # See: http://sleuthkit.org/autopsy/docs/api-docs/4.4/classorg_1_1sleuthkit_1_1autopsy_1_1ingest_1_1_data_source_ingest_module_progress.html def process(self, dataSource, progressBar): # we don't know how much work there will be diff --git a/pythonExamples/July2015FileTutorial_BigRound/FindBigRoundFiles.py b/pythonExamples/July2015FileTutorial_BigRound/FindBigRoundFiles.py index e7df254dc3..fbcf8eaa39 100755 --- a/pythonExamples/July2015FileTutorial_BigRound/FindBigRoundFiles.py +++ b/pythonExamples/July2015FileTutorial_BigRound/FindBigRoundFiles.py @@ -92,7 +92,7 @@ class FindBigRoundFilesIngestModule(FileIngestModule): # Where any setup and configuration is done # 'context' is an instance of org.sleuthkit.autopsy.ingest.IngestJobContext. - # See: http://sleuthkit.org/autopsy/docs/api-docs/4.1/classorg_1_1sleuthkit_1_1autopsy_1_1ingest_1_1_ingest_job_context.html + # See: http://sleuthkit.org/autopsy/docs/api-docs/4.4/classorg_1_1sleuthkit_1_1autopsy_1_1ingest_1_1_ingest_job_context.html # TODO: Add any setup code that you need here. def startUp(self, context): self.filesFound = 0 @@ -103,7 +103,7 @@ class FindBigRoundFilesIngestModule(FileIngestModule): # Where the analysis is done. Each file will be passed into here. # The 'file' object being passed in is of type org.sleuthkit.datamodel.AbstractFile. - # See: http://www.sleuthkit.org/sleuthkit/docs/jni-docs/4.3/classorg_1_1sleuthkit_1_1datamodel_1_1_abstract_file.html + # See: http://www.sleuthkit.org/sleuthkit/docs/jni-docs/4.4/classorg_1_1sleuthkit_1_1datamodel_1_1_abstract_file.html def process(self, file): # Use blackboard class to index blackboard artifacts for keyword search @@ -134,11 +134,11 @@ class FindBigRoundFilesIngestModule(FileIngestModule): # 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)); + BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT, None)) return IngestModule.ProcessResult.OK # Where any shutdown code is run and resources are freed. # TODO: Add any shutdown code that you need here. def shutDown(self): - None + None \ No newline at end of file diff --git a/pythonExamples/Sept2015ReportTutorial_CSV/CsvReportModule.py b/pythonExamples/Sept2015ReportTutorial_CSV/CsvReportModule.py index 4b5b9df83b..82a0193aa2 100755 --- a/pythonExamples/Sept2015ReportTutorial_CSV/CsvReportModule.py +++ b/pythonExamples/Sept2015ReportTutorial_CSV/CsvReportModule.py @@ -27,7 +27,7 @@ # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR # OTHER DEALINGS IN THE SOFTWARE. -# See http://sleuthkit.org/autopsy/docs/api-docs/4.1/index.html for documentation +# See http://sleuthkit.org/autopsy/docs/api-docs/4.4/index.html for documentation # Simple report module for Autopsy. # Used as part of Python tutorials from Basis Technology - September 2015 @@ -71,7 +71,7 @@ class CSVReportModule(GeneralReportModuleAdapter): # 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 'progressBar' object is of type ReportProgressPanel. - # See: http://sleuthkit.org/autopsy/docs/api-docs/4.1/classorg_1_1sleuthkit_1_1autopsy_1_1report_1_1_report_progress_panel.html + # See: http://sleuthkit.org/autopsy/docs/api-docs/4.4/classorg_1_1sleuthkit_1_1autopsy_1_1report_1_1_report_progress_panel.html def generateReport(self, baseReportDir, progressBar): # Open the output file. diff --git a/pythonExamples/dataSourceIngestModule.py b/pythonExamples/dataSourceIngestModule.py index 41166398bb..9b75bfd79f 100755 --- a/pythonExamples/dataSourceIngestModule.py +++ b/pythonExamples/dataSourceIngestModule.py @@ -29,7 +29,7 @@ # Simple data source-level ingest module for Autopsy. # Search for TODO for the things that you need to change -# See http://sleuthkit.org/autopsy/docs/api-docs/4.1/index.html for documentation +# See http://sleuthkit.org/autopsy/docs/api-docs/4.4/index.html for documentation import jarray import inspect @@ -94,7 +94,7 @@ class SampleJythonDataSourceIngestModule(DataSourceIngestModule): # Where any setup and configuration is done # 'context' is an instance of org.sleuthkit.autopsy.ingest.IngestJobContext. - # See: http://sleuthkit.org/autopsy/docs/api-docs/4.1/classorg_1_1sleuthkit_1_1autopsy_1_1ingest_1_1_ingest_job_context.html + # See: http://sleuthkit.org/autopsy/docs/api-docs/4.4/classorg_1_1sleuthkit_1_1autopsy_1_1ingest_1_1_ingest_job_context.html # TODO: Add any setup code that you need here. def startUp(self, context): @@ -104,9 +104,9 @@ class SampleJythonDataSourceIngestModule(DataSourceIngestModule): # Where the analysis is done. # The 'dataSource' object being passed in is of type org.sleuthkit.datamodel.Content. - # See: http://www.sleuthkit.org/sleuthkit/docs/jni-docs/4.3/interfaceorg_1_1sleuthkit_1_1datamodel_1_1_content.html + # See: http://www.sleuthkit.org/sleuthkit/docs/jni-docs/4.4/interfaceorg_1_1sleuthkit_1_1datamodel_1_1_content.html # 'progressBar' is of type org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProgress - # See: http://sleuthkit.org/autopsy/docs/api-docs/4.1/classorg_1_1sleuthkit_1_1autopsy_1_1ingest_1_1_data_source_ingest_module_progress.html + # See: http://sleuthkit.org/autopsy/docs/api-docs/4.4/classorg_1_1sleuthkit_1_1autopsy_1_1ingest_1_1_data_source_ingest_module_progress.html # TODO: Add your analysis code in here. def process(self, dataSource, progressBar): @@ -119,14 +119,14 @@ class SampleJythonDataSourceIngestModule(DataSourceIngestModule): # For our example, we will use FileManager to get all # files with the word "test" # in the name and then count and read them - # FileManager API: http://sleuthkit.org/autopsy/docs/api-docs/4.1/classorg_1_1sleuthkit_1_1autopsy_1_1casemodule_1_1services_1_1_file_manager.html + # FileManager API: http://sleuthkit.org/autopsy/docs/api-docs/4.4/classorg_1_1sleuthkit_1_1autopsy_1_1casemodule_1_1services_1_1_file_manager.html fileManager = Case.getCurrentCase().getServices().getFileManager() files = fileManager.findFiles(dataSource, "%test%") numFiles = len(files) self.log(Level.INFO, "found " + str(numFiles) + " files") progressBar.switchToDeterminate(numFiles) - fileCount = 0; + fileCount = 0 for file in files: # Check if the user pressed cancel while we were busy @@ -167,4 +167,4 @@ class SampleJythonDataSourceIngestModule(DataSourceIngestModule): "Sample Jython Data Source Ingest Module", "Found %d files" % fileCount) IngestServices.getInstance().postMessage(message) - return IngestModule.ProcessResult.OK; \ No newline at end of file + return IngestModule.ProcessResult.OK \ No newline at end of file diff --git a/pythonExamples/fileIngestModule.py b/pythonExamples/fileIngestModule.py index dceabac199..a2fecd2410 100755 --- a/pythonExamples/fileIngestModule.py +++ b/pythonExamples/fileIngestModule.py @@ -29,7 +29,7 @@ # Simple file-level ingest module for Autopsy. # Search for TODO for the things that you need to change -# See http://sleuthkit.org/autopsy/docs/api-docs/4.1/index.html for documentation +# See http://sleuthkit.org/autopsy/docs/api-docs/4.4/index.html for documentation import jarray import inspect @@ -94,7 +94,7 @@ class SampleJythonFileIngestModule(FileIngestModule): # Where any setup and configuration is done # 'context' is an instance of org.sleuthkit.autopsy.ingest.IngestJobContext. - # See: http://sleuthkit.org/autopsy/docs/api-docs/4.1/classorg_1_1sleuthkit_1_1autopsy_1_1ingest_1_1_ingest_job_context.html + # See: http://sleuthkit.org/autopsy/docs/api-docs/4.4/classorg_1_1sleuthkit_1_1autopsy_1_1ingest_1_1_ingest_job_context.html # TODO: Add any setup code that you need here. def startUp(self, context): self.filesFound = 0 @@ -105,12 +105,12 @@ class SampleJythonFileIngestModule(FileIngestModule): # Where the analysis is done. Each file will be passed into here. # The 'file' object being passed in is of type org.sleuthkit.datamodel.AbstractFile. - # See: http://www.sleuthkit.org/sleuthkit/docs/jni-docs/4.3/classorg_1_1sleuthkit_1_1datamodel_1_1_abstract_file.html + # See: http://www.sleuthkit.org/sleuthkit/docs/jni-docs/4.4/classorg_1_1sleuthkit_1_1datamodel_1_1_abstract_file.html # TODO: Add your analysis code in here. def process(self, file): # Skip non-files - if ((file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) or - (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS) or + if ((file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) or + (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS) or (file.isFile() == False)): return IngestModule.ProcessResult.OK @@ -126,7 +126,7 @@ 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. art = file.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT) - att = BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME, + att = BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME, SampleJythonFileIngestModuleFactory.moduleName, "Text Files") art.addAttribute(att) @@ -138,15 +138,15 @@ class SampleJythonFileIngestModule(FileIngestModule): # 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)); + 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. + # want to do something with them. artifactList = file.getArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT) for artifact in artifactList: - attributeList = artifact.getAttributes(); + attributeList = artifact.getAttributes() for attrib in attributeList: self.log(Level.INFO, attrib.toString()) @@ -166,6 +166,6 @@ class SampleJythonFileIngestModule(FileIngestModule): def shutDown(self): # As a final part of this example, we'll send a message to the ingest inbox with the number of files found (in this thread) message = IngestMessage.createMessage( - IngestMessage.MessageType.DATA, SampleJythonFileIngestModuleFactory.moduleName, + IngestMessage.MessageType.DATA, SampleJythonFileIngestModuleFactory.moduleName, str(self.filesFound) + " files found") - ingestServices = IngestServices.getInstance().postMessage(message) + ingestServices = IngestServices.getInstance().postMessage(message) \ No newline at end of file diff --git a/pythonExamples/fileIngestModuleWithGui.py b/pythonExamples/fileIngestModuleWithGui.py index ad2e36e984..34814ba12b 100755 --- a/pythonExamples/fileIngestModuleWithGui.py +++ b/pythonExamples/fileIngestModuleWithGui.py @@ -35,7 +35,7 @@ # don't need a configuration UI, start with the other sample module. # # Search for TODO for the things that you need to change -# See http://sleuthkit.org/autopsy/docs/api-docs/4.1/index.html for documentation +# See http://sleuthkit.org/autopsy/docs/api-docs/4.4/index.html for documentation import jarray @@ -204,4 +204,3 @@ class SampleFileIngestModuleWithUISettingsPanel(IngestModuleIngestJobSettingsPan # Return the settings used def getSettings(self): return self.local_settings - diff --git a/pythonExamples/reportmodule.py b/pythonExamples/reportmodule.py index b4810dca34..8c3c161ee7 100755 --- a/pythonExamples/reportmodule.py +++ b/pythonExamples/reportmodule.py @@ -31,7 +31,7 @@ # Sample report module for Autopsy. Use as a starting point for new modules. # # Search for TODO for the things that you need to change -# See http://sleuthkit.org/autopsy/docs/api-docs/4.1/index.html for documentation +# See http://sleuthkit.org/autopsy/docs/api-docs/4.4/index.html for documentation import os from java.lang import System @@ -69,9 +69,9 @@ class SampleGeneralReportModule(GeneralReportModuleAdapter): # 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 'progressBar' object is of type ReportProgressPanel. - # See: http://sleuthkit.org/autopsy/docs/api-docs/4.1/classorg_1_1sleuthkit_1_1autopsy_1_1report_1_1_report_progress_panel.html + # See: http://sleuthkit.org/autopsy/docs/api-docs/4.4/classorg_1_1sleuthkit_1_1autopsy_1_1report_1_1_report_progress_panel.html def generateReport(self, baseReportDir, 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 progressBar.setIndeterminate(False) @@ -101,7 +101,7 @@ class SampleGeneralReportModule(GeneralReportModuleAdapter): report.close() # Add the report to the Case, so it is shown in the tree - Case.getCurrentCase().addReport(fileName, self.moduleName, "File Count Report"); + Case.getCurrentCase().addReport(fileName, self.moduleName, "File Count Report") progressBar.increment() From d84b3d4622d2a86a626678f74d928035e25b9946 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Fri, 21 Apr 2017 15:01:32 -0400 Subject: [PATCH 25/37] Removed references to java Android module --- .../ingest/IngestModuleFactoryLoader.java | 2 - .../modules/android/CallLogAnalyzer.java | 184 ----------------- .../modules/android/ContactAnalyzer.java | 195 ------------------ .../modules/android/TextMessageAnalyzer.java | 167 --------------- 4 files changed, 548 deletions(-) delete mode 100755 Core/src/org/sleuthkit/autopsy/modules/android/CallLogAnalyzer.java delete mode 100755 Core/src/org/sleuthkit/autopsy/modules/android/ContactAnalyzer.java delete mode 100755 Core/src/org/sleuthkit/autopsy/modules/android/TextMessageAnalyzer.java diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestModuleFactoryLoader.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestModuleFactoryLoader.java index 59b978bf24..e338b79805 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestModuleFactoryLoader.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestModuleFactoryLoader.java @@ -31,7 +31,6 @@ import org.openide.util.NbBundle; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.examples.SampleExecutableIngestModuleFactory; import org.sleuthkit.autopsy.examples.SampleIngestModuleFactory; -import org.sleuthkit.autopsy.modules.android.AndroidModuleFactory; import org.sleuthkit.autopsy.modules.e01verify.E01VerifierModuleFactory; import org.sleuthkit.autopsy.modules.exif.ExifParserModuleFactory; import org.sleuthkit.autopsy.modules.fileextmismatch.FileExtMismatchDetectorModuleFactory; @@ -63,7 +62,6 @@ final class IngestModuleFactoryLoader { add("org.sleuthkit.autopsy.thunderbirdparser.EmailParserModuleFactory"); //NON-NLS add(FileExtMismatchDetectorModuleFactory.class.getCanonicalName()); add(E01VerifierModuleFactory.class.getCanonicalName()); - add(AndroidModuleFactory.class.getCanonicalName()); add(InterestingItemsIngestModuleFactory.class.getCanonicalName()); add(PhotoRecCarverIngestModuleFactory.class.getCanonicalName()); } diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/CallLogAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/android/CallLogAnalyzer.java deleted file mode 100755 index 27129456e2..0000000000 --- a/Core/src/org/sleuthkit/autopsy/modules/android/CallLogAnalyzer.java +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2014 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.modules.android; - -import java.io.File; -import java.io.IOException; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.logging.Level; -import org.openide.util.NbBundle.Messages; -import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.casemodule.services.Blackboard; -import org.sleuthkit.autopsy.casemodule.services.FileManager; -import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; -import org.sleuthkit.autopsy.datamodel.ContentUtils; -import org.sleuthkit.autopsy.ingest.IngestJobContext; -import org.sleuthkit.autopsy.ingest.IngestServices; -import org.sleuthkit.autopsy.ingest.ModuleDataEvent; -import org.sleuthkit.datamodel.AbstractFile; -import org.sleuthkit.datamodel.BlackboardArtifact; -import org.sleuthkit.datamodel.BlackboardAttribute; -import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE; -import org.sleuthkit.datamodel.Content; -import org.sleuthkit.datamodel.TskCoreException; - -/** - * Locates a variety of different call log databases, parses them, and populates - * the blackboard. - */ -class CallLogAnalyzer { - - private static final String moduleName = AndroidModuleFactory.getModuleName(); - private static final Logger logger = Logger.getLogger(CallLogAnalyzer.class.getName()); - private static Blackboard blackboard; - - private static final IngestServices services = IngestServices.getInstance(); - - - /** - * the names of tables that potentially hold call logs in the dbs - */ - private static final Iterable tableNames = Arrays.asList("calls", "logs"); //NON-NLS - - public static void findCallLogs(Content dataSource, FileManager fileManager, - IngestJobContext context) { - blackboard = Case.getCurrentCase().getServices().getBlackboard(); - try { - List absFiles = fileManager.findFiles(dataSource, "logs.db"); //NON-NLS - absFiles.addAll(fileManager.findFiles(dataSource, "contacts.db")); //NON-NLS - absFiles.addAll(fileManager.findFiles(dataSource, "contacts2.db")); //NON-NLS - for (AbstractFile abstractFile : absFiles) { - try { - File file = new File(Case.getCurrentCase().getTempDirectory(), abstractFile.getName()); - ContentUtils.writeToFile(abstractFile, file, context::dataSourceIngestIsCancelled); - findCallLogsInDB(file.toString(), abstractFile); - } catch (IOException e) { - logger.log(Level.SEVERE, "Error writing temporary call log db to disk", e); //NON-NLS - } - } - } catch (TskCoreException e) { - logger.log(Level.SEVERE, "Error finding call logs", e); //NON-NLS - } - } - - @Messages({"CallLogAnalyzer.indexError.message=Failed to index call log artifact for keyword search."}) - private static void findCallLogsInDB(String DatabasePath, AbstractFile f) { - - if (DatabasePath == null || DatabasePath.isEmpty()) { - return; - } - - Collection bbartifacts = new ArrayList<>(); - try (Connection connection = DriverManager.getConnection("jdbc:sqlite:" + DatabasePath); //NON-NLS - Statement statement = connection.createStatement();) { - - for (String tableName : tableNames) { - try (ResultSet resultSet = statement.executeQuery( - "SELECT number,date,duration,type, name FROM " + tableName + " ORDER BY date DESC;");) { //NON-NLS - logger.log(Level.INFO, "Reading call log from table {0} in db {1}", new Object[]{tableName, DatabasePath}); //NON-NLS - while (resultSet.next()) { - Long date = resultSet.getLong("date") / 1000; - final CallDirection direction = CallDirection.fromType(resultSet.getInt("type")); //NON-NLS - String directionString = direction != null ? direction.getDisplayName() : ""; - final String number = resultSet.getString("number"); //NON-NLS - final long duration = resultSet.getLong("duration"); //NON-NLS //duration of call is in seconds - final String name = resultSet.getString("name"); //NON-NLS // name of person dialed or called. null if unregistered - - try { - BlackboardArtifact bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG); //create a call log and then add attributes from result set. - if (direction == CallDirection.OUTGOING) { - bba.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO, moduleName, number)); - } else { /// Covers INCOMING and MISSED - bba.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM, moduleName, number)); - } - bba.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_START, moduleName, date)); - bba.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_END, moduleName, duration + date)); - bba.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DIRECTION, moduleName, directionString)); - bba.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, moduleName, name)); - - bbartifacts.add(bba); - - try { - // index the artifact for keyword search - blackboard.indexArtifact(bba); - } catch (Blackboard.BlackboardException ex) { - logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bba.getArtifactID(), ex); //NON-NLS - MessageNotifyUtil.Notify.error( - Bundle.CallLogAnalyzer_indexError_message(), bba.getDisplayName()); - } - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Error posting call log record to the Blackboard", ex); //NON-NLS - } - } - } catch (SQLException e) { - logger.log(Level.WARNING, String.format("Could not read table %s in db %s", tableName, DatabasePath), e); //NON-NLS - } - } - } catch (SQLException e) { - logger.log(Level.SEVERE, "Could not parse call log; error connecting to db " + DatabasePath, e); //NON-NLS - } - finally { - if (!bbartifacts.isEmpty()) { - services.fireModuleDataEvent(new ModuleDataEvent( - moduleName, - BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG, bbartifacts)); - } - } - } - - private static enum CallDirection { - - INCOMING(1, "Incoming"), OUTGOING(2, "Outgoing"), MISSED(3, "Missed"); //NON-NLS - - private final int type; - - private final String displayName; - - public String getDisplayName() { - return displayName; - } - - private CallDirection(int type, String displayName) { - this.type = type; - this.displayName = displayName; - } - - static CallDirection fromType(int t) { - switch (t) { - case 1: - return INCOMING; - case 2: - return OUTGOING; - case 3: - return MISSED; - default: - return null; - } - } - } -} diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/ContactAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/android/ContactAnalyzer.java deleted file mode 100755 index 17cc8ad2cc..0000000000 --- a/Core/src/org/sleuthkit/autopsy/modules/android/ContactAnalyzer.java +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2014 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.modules.android; - -import java.io.File; -import java.sql.Connection; -import java.sql.DatabaseMetaData; -import java.sql.DriverManager; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.logging.Level; -import org.openide.util.NbBundle.Messages; -import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.casemodule.services.Blackboard; -import org.sleuthkit.autopsy.casemodule.services.FileManager; -import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; -import org.sleuthkit.autopsy.datamodel.ContentUtils; -import org.sleuthkit.autopsy.ingest.IngestJobContext; -import org.sleuthkit.autopsy.ingest.IngestServices; -import org.sleuthkit.autopsy.ingest.ModuleDataEvent; -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; - -/** - * Locates a variety of different contacts databases, parses them, and populates - * the blackboard. - */ -class ContactAnalyzer { - - private static final String moduleName = AndroidModuleFactory.getModuleName(); - private static final Logger logger = Logger.getLogger(ContactAnalyzer.class.getName()); - private static final IngestServices services = IngestServices.getInstance(); - - public static void findContacts(Content dataSource, FileManager fileManager, - IngestJobContext context) { - List absFiles; - try { - absFiles = fileManager.findFiles(dataSource, "contacts.db"); //NON-NLS - absFiles.addAll(fileManager.findFiles(dataSource, "contacts2.db")); //NON-NLS - if (absFiles.isEmpty()) { - return; - } - for (AbstractFile AF : absFiles) { - try { - File jFile = new File(Case.getCurrentCase().getTempDirectory(), AF.getName()); - ContentUtils.writeToFile(AF, jFile, context::dataSourceIngestIsCancelled); - findContactsInDB(jFile.toString(), AF); - } catch (Exception e) { - logger.log(Level.SEVERE, "Error parsing Contacts", e); //NON-NLS - } - } - } catch (TskCoreException e) { - logger.log(Level.SEVERE, "Error finding Contacts", e); //NON-NLS - } - } - - /** - * - * @param databasePath - * @param fId Will create artifact from a database given by the - * path The fileId will be the Abstract file associated - * with the artifacts - */ - @Messages({"ContactAnalyzer.indexError.message=Failed to index contact artifact for keyword search."}) - private static void findContactsInDB(String databasePath, AbstractFile f) { - Connection connection = null; - ResultSet resultSet = null; - Statement statement = null; - Blackboard blackboard = Case.getCurrentCase().getServices().getBlackboard(); - - if (databasePath == null || databasePath.isEmpty()) { - return; - } - try { - Class.forName("org.sqlite.JDBC"); //NON-NLS //load JDBC driver - connection = DriverManager.getConnection("jdbc:sqlite:" + databasePath); //NON-NLS - statement = connection.createStatement(); - } catch (ClassNotFoundException | SQLException e) { - logger.log(Level.SEVERE, "Error opening database", e); //NON-NLS - return; - } - - Collection bbartifacts = new ArrayList<>(); - try { - // get display_name, mimetype(email or phone number) and data1 (phonenumber or email address depending on mimetype) - //sorted by name, so phonenumber/email would be consecutive for a person if they exist. - // check if contacts.name_raw_contact_id exists. Modify the query accordingly. - Boolean column_found = false; - DatabaseMetaData metadata = connection.getMetaData(); - ResultSet columnListResultSet = metadata.getColumns(null, null, "contacts", null); //NON-NLS - while (columnListResultSet.next()) { - if (columnListResultSet.getString("COLUMN_NAME").equals("name_raw_contact_id")) { //NON-NLS - column_found = true; - break; - } - } - if (column_found) { - resultSet = statement.executeQuery( - "SELECT mimetype,data1, name_raw_contact.display_name AS display_name \n" //NON-NLS - + "FROM raw_contacts JOIN contacts ON (raw_contacts.contact_id=contacts._id) \n" //NON-NLS - + "JOIN raw_contacts AS name_raw_contact ON(name_raw_contact_id=name_raw_contact._id) " //NON-NLS - + "LEFT OUTER JOIN data ON (data.raw_contact_id=raw_contacts._id) \n" //NON-NLS - + "LEFT OUTER JOIN mimetypes ON (data.mimetype_id=mimetypes._id) \n" //NON-NLS - + "WHERE mimetype = 'vnd.android.cursor.item/phone_v2' OR mimetype = 'vnd.android.cursor.item/email_v2'\n" //NON-NLS - + "ORDER BY name_raw_contact.display_name ASC;"); //NON-NLS - } else { - resultSet = statement.executeQuery( - "SELECT mimetype,data1, raw_contacts.display_name AS display_name \n" //NON-NLS - + "FROM raw_contacts JOIN contacts ON (raw_contacts.contact_id=contacts._id) \n" //NON-NLS - + "LEFT OUTER JOIN data ON (data.raw_contact_id=raw_contacts._id) \n" //NON-NLS - + "LEFT OUTER JOIN mimetypes ON (data.mimetype_id=mimetypes._id) \n" //NON-NLS - + "WHERE mimetype = 'vnd.android.cursor.item/phone_v2' OR mimetype = 'vnd.android.cursor.item/email_v2'\n" //NON-NLS - + "ORDER BY raw_contacts.display_name ASC;"); //NON-NLS - } - - BlackboardArtifact bba; - bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT); - String name; - String oldName = ""; - String mimetype; // either phone or email - String data1; // the phone number or email - while (resultSet.next()) { - name = resultSet.getString("display_name"); //NON-NLS - data1 = resultSet.getString("data1"); //NON-NLS - mimetype = resultSet.getString("mimetype"); //NON-NLS - if (name.equals(oldName) == false) { - bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME, moduleName, name)); - } - if (mimetype.equals("vnd.android.cursor.item/phone_v2")) { //NON-NLS - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER, moduleName, data1)); - } else { - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL, moduleName, data1)); - } - oldName = name; - - bbartifacts.add(bba); - - try { - // index the artifact for keyword search - blackboard.indexArtifact(bba); - } catch (Blackboard.BlackboardException ex) { - logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bba.getArtifactID(), ex); //NON-NLS - MessageNotifyUtil.Notify.error( - Bundle.ContactAnalyzer_indexError_message(), bba.getDisplayName()); - } - } - - } catch (SQLException e) { - logger.log(Level.WARNING, "Unable to execute contacts SQL query against {0} : {1}", new Object[]{databasePath, e}); //NON-NLS - } catch (TskCoreException e) { - logger.log(Level.SEVERE, "Error posting to blackboard", e); //NON-NLS - } finally { - if (!bbartifacts.isEmpty()) { - services.fireModuleDataEvent(new ModuleDataEvent( - moduleName, - BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT, bbartifacts)); - } - - try { - if (resultSet != null) { - resultSet.close(); - } - statement.close(); - connection.close(); - } catch (Exception e) { - logger.log(Level.SEVERE, "Error closing database", e); //NON-NLS - } - } - } -} diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/TextMessageAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/android/TextMessageAnalyzer.java deleted file mode 100755 index 979291d5d3..0000000000 --- a/Core/src/org/sleuthkit/autopsy/modules/android/TextMessageAnalyzer.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2014 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.modules.android; - -import java.io.File; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.logging.Level; -import org.openide.util.NbBundle; -import org.openide.util.NbBundle.Messages; -import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.casemodule.services.Blackboard; -import org.sleuthkit.autopsy.casemodule.services.FileManager; -import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; -import org.sleuthkit.autopsy.datamodel.ContentUtils; -import org.sleuthkit.autopsy.ingest.IngestJobContext; -import org.sleuthkit.autopsy.ingest.IngestServices; -import org.sleuthkit.autopsy.ingest.ModuleDataEvent; -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; - -/** - * Finds database with SMS/MMS messages and adds them to blackboard. - */ -class TextMessageAnalyzer { - - private static final String moduleName = AndroidModuleFactory.getModuleName(); - private static final Logger logger = Logger.getLogger(TextMessageAnalyzer.class.getName()); - private static final IngestServices services = IngestServices.getInstance(); - private static Blackboard blackboard; - - public static void findTexts(Content dataSource, FileManager fileManager, - IngestJobContext context) { - blackboard = Case.getCurrentCase().getServices().getBlackboard(); - try { - - List absFiles = fileManager.findFiles(dataSource, "mmssms.db"); //NON-NLS - for (AbstractFile abstractFile : absFiles) { - try { - File jFile = new File(Case.getCurrentCase().getTempDirectory(), abstractFile.getName()); - ContentUtils.writeToFile(abstractFile, jFile, context::dataSourceIngestIsCancelled); - findTextsInDB(jFile.toString(), abstractFile); - } catch (Exception e) { - logger.log(Level.SEVERE, "Error parsing text messages", e); //NON-NLS - } - } - } catch (TskCoreException e) { - logger.log(Level.SEVERE, "Error finding text messages", e); //NON-NLS - } - } - - @Messages({"TextMessageAnalyzer.indexError.message=Failed to index text message artifact for keyword search."}) - private static void findTextsInDB(String DatabasePath, AbstractFile f) { - Connection connection = null; - ResultSet resultSet = null; - Statement statement = null; - - if (DatabasePath == null || DatabasePath.isEmpty()) { - return; - } - try { - Class.forName("org.sqlite.JDBC"); //NON-NLS //load JDBC driver - connection = DriverManager.getConnection("jdbc:sqlite:" + DatabasePath); //NON-NLS - statement = connection.createStatement(); - } catch (ClassNotFoundException | SQLException e) { - logger.log(Level.SEVERE, "Error opening database", e); //NON-NLS - return; - } - - Collection bbartifacts = new ArrayList<>(); - try { - resultSet = statement.executeQuery( - "SELECT address,date,read,type,subject,body FROM sms;"); //NON-NLS - - String address; // may be phone number, or other addresses - - String direction; // message received in inbox = 1, message sent = 2 - String subject;//message subject - Integer read; // may be unread = 0, read = 1 - String body; //message body - while (resultSet.next()) { - address = resultSet.getString("address"); //NON-NLS - Long date = Long.valueOf(resultSet.getString("date")) / 1000; //NON-NLS - - read = resultSet.getInt("read"); //NON-NLS - subject = resultSet.getString("subject"); //NON-NLS - body = resultSet.getString("body"); //NON-NLS - - BlackboardArtifact bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE); //create Message artifact and then add attributes from result set. - if (resultSet.getString("type").equals("1")) { //NON-NLS - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION, moduleName, - NbBundle.getMessage(TextMessageAnalyzer.class, - "TextMessageAnalyzer.bbAttribute.incoming"))); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM, moduleName, address)); - } else { - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION, moduleName, - NbBundle.getMessage(TextMessageAnalyzer.class, - "TextMessageAnalyzer.bbAttribute.outgoing"))); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO, moduleName, address)); - } - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, moduleName, date)); - - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_READ_STATUS, moduleName, read)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SUBJECT, moduleName, subject)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT, moduleName, body)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE, moduleName, - NbBundle.getMessage(TextMessageAnalyzer.class, - "TextMessageAnalyzer.bbAttribute.smsMessage"))); - - bbartifacts.add(bba); - - try { - // index the artifact for keyword search - blackboard.indexArtifact(bba); - } catch (Blackboard.BlackboardException ex) { - logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bba.getArtifactID(), ex); //NON-NLS - MessageNotifyUtil.Notify.error( - Bundle.TextMessageAnalyzer_indexError_message(), bba.getDisplayName()); - } - } - } catch (Exception e) { - logger.log(Level.SEVERE, "Error parsing text messages to Blackboard", e); //NON-NLS - } finally { - if (!bbartifacts.isEmpty()) { - services.fireModuleDataEvent(new ModuleDataEvent( - moduleName, - BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE, bbartifacts)); - } - - try { - if (resultSet != null) { - resultSet.close(); - } - statement.close(); - connection.close(); - } catch (Exception e) { - logger.log(Level.SEVERE, "Error closing database", e); //NON-NLS - } - } - } -} From bccda6dc8184e7369cb3763ae0dd0e7a0482afd1 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Fri, 21 Apr 2017 16:37:17 -0400 Subject: [PATCH 26/37] Modified Python scripts to add Raman's work --- .../android/browserlocation.py | 0 .../android/cachelocation.py | 0 .../android/calllog.py | 10 ++++++++++ .../android/contact.py | 8 ++++++++ .../android/general.py | 0 .../android/googlemaplocation.py | 0 .../android/module.py | 0 .../android/tangomessage.py | 0 .../android/textmessage.py | 7 +++++++ .../android/wwfmessage.py | 0 10 files changed, 25 insertions(+) rename {Core/release/InternalPythonModules => InternalPythonModules}/android/browserlocation.py (100%) mode change 100755 => 100644 rename {Core/release/InternalPythonModules => InternalPythonModules}/android/cachelocation.py (100%) mode change 100755 => 100644 rename {Core/release/InternalPythonModules => InternalPythonModules}/android/calllog.py (94%) mode change 100755 => 100644 rename {Core/release/InternalPythonModules => InternalPythonModules}/android/contact.py (95%) mode change 100755 => 100644 rename {Core/release/InternalPythonModules => InternalPythonModules}/android/general.py (100%) mode change 100755 => 100644 rename {Core/release/InternalPythonModules => InternalPythonModules}/android/googlemaplocation.py (100%) mode change 100755 => 100644 rename {Core/release/InternalPythonModules => InternalPythonModules}/android/module.py (100%) mode change 100755 => 100644 rename {Core/release/InternalPythonModules => InternalPythonModules}/android/tangomessage.py (100%) mode change 100755 => 100644 rename {Core/release/InternalPythonModules => InternalPythonModules}/android/textmessage.py (94%) mode change 100755 => 100644 rename {Core/release/InternalPythonModules => InternalPythonModules}/android/wwfmessage.py (100%) mode change 100755 => 100644 diff --git a/Core/release/InternalPythonModules/android/browserlocation.py b/InternalPythonModules/android/browserlocation.py old mode 100755 new mode 100644 similarity index 100% rename from Core/release/InternalPythonModules/android/browserlocation.py rename to InternalPythonModules/android/browserlocation.py diff --git a/Core/release/InternalPythonModules/android/cachelocation.py b/InternalPythonModules/android/cachelocation.py old mode 100755 new mode 100644 similarity index 100% rename from Core/release/InternalPythonModules/android/cachelocation.py rename to InternalPythonModules/android/cachelocation.py diff --git a/Core/release/InternalPythonModules/android/calllog.py b/InternalPythonModules/android/calllog.py old mode 100755 new mode 100644 similarity index 94% rename from Core/release/InternalPythonModules/android/calllog.py rename to InternalPythonModules/android/calllog.py index 886a918449..d27066de86 --- a/Core/release/InternalPythonModules/android/calllog.py +++ b/InternalPythonModules/android/calllog.py @@ -35,6 +35,8 @@ from org.sleuthkit.autopsy.coreutils import Logger from org.sleuthkit.autopsy.coreutils import MessageNotifyUtil from org.sleuthkit.autopsy.datamodel import ContentUtils from org.sleuthkit.autopsy.ingest import IngestJobContext +from org.sleuthkit.autopsy.ingest import IngestServices +from org.sleuthkit.autopsy.ingest import ModuleDataEvent from org.sleuthkit.datamodel import AbstractFile from org.sleuthkit.datamodel import BlackboardArtifact from org.sleuthkit.datamodel import BlackboardAttribute @@ -98,10 +100,12 @@ class CallLogAnalyzer(general.AndroidComponentAnalyzer): if not databasePath: return + bbartifacts = list() try: connection = DriverManager.getConnection("jdbc:sqlite:" + databasePath) statement = connection.createStatement() + for tableName in CallLogAnalyzer._tableNames: try: resultSet = statement.executeQuery("SELECT number, date, duration, type, name FROM " + tableName + " ORDER BY date DESC;") @@ -126,6 +130,8 @@ class CallLogAnalyzer(general.AndroidComponentAnalyzer): artifact.addAttribute(BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DIRECTION, general.MODULE_NAME, directionString)) artifact.addAttribute(BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, general.MODULE_NAME, name)) + bbartifacts.add(artifact) + try: # index the artifact for keyword search blackboard = Case.getCurrentCase().getServices().getBlackboard() @@ -143,3 +149,7 @@ class CallLogAnalyzer(general.AndroidComponentAnalyzer): except SQLException as ex: self._logger.log(Level.SEVERE, "Could not parse call log; error connecting to db " + databasePath, ex) self._logger.log(Level.SEVERE, traceback.format_exc()) + finally: + if bbartifacts: + IngestServices.getInstance().fireModuleDataEvent(ModuleDataEvent(general.MODULE_NAME, BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG, bbartifacts)) + diff --git a/Core/release/InternalPythonModules/android/contact.py b/InternalPythonModules/android/contact.py old mode 100755 new mode 100644 similarity index 95% rename from Core/release/InternalPythonModules/android/contact.py rename to InternalPythonModules/android/contact.py index 202ddbdc02..98e2cd17d0 --- a/Core/release/InternalPythonModules/android/contact.py +++ b/InternalPythonModules/android/contact.py @@ -34,6 +34,8 @@ from org.sleuthkit.autopsy.coreutils import Logger from org.sleuthkit.autopsy.coreutils import MessageNotifyUtil from org.sleuthkit.autopsy.datamodel import ContentUtils from org.sleuthkit.autopsy.ingest import IngestJobContext +from org.sleuthkit.autopsy.ingest import IngestServices +from org.sleuthkit.autopsy.ingest import ModuleDataEvent from org.sleuthkit.datamodel import AbstractFile from org.sleuthkit.datamodel import BlackboardArtifact from org.sleuthkit.datamodel import BlackboardAttribute @@ -77,6 +79,7 @@ class ContactAnalyzer(general.AndroidComponentAnalyzer): if not databasePath: return + bbartifacts = list() try: Class.forName("org.sqlite.JDBC") # load JDBC driver connection = DriverManager.getConnection("jdbc:sqlite:" + databasePath) @@ -131,6 +134,8 @@ class ContactAnalyzer(general.AndroidComponentAnalyzer): oldName = name + bbartifacts.add(artifact) + try: # index the artifact for keyword search blackboard = Case.getCurrentCase().getServices().getBlackboard() @@ -146,6 +151,9 @@ class ContactAnalyzer(general.AndroidComponentAnalyzer): self._logger.log(Level.SEVERE, "Error posting to blackboard", ex) self._logger.log(Level.SEVERE, traceback.format_exc()) finally: + if bbartifacts: + IngestServices.getInstance().fireModuleDataEvent(ModuleDataEvent(general.MODULE_NAME, BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT, bbartifacts)) + try: if resultSet is not None: resultSet.close() diff --git a/Core/release/InternalPythonModules/android/general.py b/InternalPythonModules/android/general.py old mode 100755 new mode 100644 similarity index 100% rename from Core/release/InternalPythonModules/android/general.py rename to InternalPythonModules/android/general.py diff --git a/Core/release/InternalPythonModules/android/googlemaplocation.py b/InternalPythonModules/android/googlemaplocation.py old mode 100755 new mode 100644 similarity index 100% rename from Core/release/InternalPythonModules/android/googlemaplocation.py rename to InternalPythonModules/android/googlemaplocation.py diff --git a/Core/release/InternalPythonModules/android/module.py b/InternalPythonModules/android/module.py old mode 100755 new mode 100644 similarity index 100% rename from Core/release/InternalPythonModules/android/module.py rename to InternalPythonModules/android/module.py diff --git a/Core/release/InternalPythonModules/android/tangomessage.py b/InternalPythonModules/android/tangomessage.py old mode 100755 new mode 100644 similarity index 100% rename from Core/release/InternalPythonModules/android/tangomessage.py rename to InternalPythonModules/android/tangomessage.py diff --git a/Core/release/InternalPythonModules/android/textmessage.py b/InternalPythonModules/android/textmessage.py old mode 100755 new mode 100644 similarity index 94% rename from Core/release/InternalPythonModules/android/textmessage.py rename to InternalPythonModules/android/textmessage.py index f618faa29a..3df47671c2 --- a/Core/release/InternalPythonModules/android/textmessage.py +++ b/InternalPythonModules/android/textmessage.py @@ -35,6 +35,8 @@ from org.sleuthkit.autopsy.coreutils import Logger from org.sleuthkit.autopsy.coreutils import MessageNotifyUtil from org.sleuthkit.autopsy.datamodel import ContentUtils from org.sleuthkit.autopsy.ingest import IngestJobContext +from org.sleuthkit.autopsy.ingest import IngestServices +from org.sleuthkit.autopsy.ingest import ModuleDataEvent from org.sleuthkit.datamodel import AbstractFile from org.sleuthkit.datamodel import BlackboardArtifact from org.sleuthkit.datamodel import BlackboardAttribute @@ -71,6 +73,7 @@ class TextMessageAnalyzer(general.AndroidComponentAnalyzer): if not databasePath: return + bbartifacts = list() try: Class.forName("org.sqlite.JDBC") # load JDBC driver connection = DriverManager.getConnection("jdbc:sqlite:" + databasePath) @@ -102,6 +105,7 @@ class TextMessageAnalyzer(general.AndroidComponentAnalyzer): artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT, general.MODULE_NAME, body)) artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE, general.MODULE_NAME, "SMS Message")) + bbartifacts.add(artifact) try: # index the artifact for keyword search blackboard = Case.getCurrentCase().getServices().getBlackboard() @@ -115,6 +119,9 @@ class TextMessageAnalyzer(general.AndroidComponentAnalyzer): self._logger.log(Level.SEVERE, "Error parsing text messages to blackboard", ex) self._logger.log(Level.SEVERE, traceback.format_exc()) finally: + if bbartifacts: + IngestServices.getInstance().fireModuleDataEvent(ModuleDataEvent(general.MODULE_NAME, BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE, bbartifacts)) + try: if resultSet is not None: resultSet.close() diff --git a/Core/release/InternalPythonModules/android/wwfmessage.py b/InternalPythonModules/android/wwfmessage.py old mode 100755 new mode 100644 similarity index 100% rename from Core/release/InternalPythonModules/android/wwfmessage.py rename to InternalPythonModules/android/wwfmessage.py From 440fac07febde3dccea6eae28b99421af8fb43ef Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Fri, 21 Apr 2017 17:39:26 -0400 Subject: [PATCH 27/37] Modify case display name/unique name handling --- .../sleuthkit/autopsy/casemodule/Case.java | 185 +++++++----------- .../autopsy/casemodule/CaseMetadata.java | 2 +- .../casemodule/NewCaseWizardPanel1.java | 22 +-- .../casemodule/SingleUserCaseConverter.java | 14 +- .../autoingest/AutoIngestManager.java | 17 +- .../experimental/autoingest/PathUtils.java | 8 +- 6 files changed, 96 insertions(+), 152 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index 474ffa18ff..ca935e7a81 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -113,10 +113,8 @@ import org.sleuthkit.datamodel.TskCoreException; */ public class Case { - private static final int NAME_LOCK_TIMOUT_HOURS = 12; - private static final int SHARED_DIR_LOCK_TIMOUT_HOURS = 12; - private static final int RESOURCE_LOCK_TIMOUT_HOURS = 12; - private static final int MAX_CASEDB_NAME_LEN_MINUS_TIMESTAMP = 47; //Truncate to 63-16=47 chars to accomodate the timestamp + private static final int DIR_LOCK_TIMOUT_HOURS = 12; + private static final int RESOURCES_LOCK_TIMOUT_HOURS = 12; private static final String SINGLE_USER_CASE_DB_NAME = "autopsy.db"; private static final String EVENT_CHANNEL_NAME = "%s-Case-Events"; //NON-NLS private static final String CACHE_FOLDER = "Cache"; //NON-NLS @@ -475,18 +473,21 @@ public class Case { } if (null != currentCase) { + String previousCaseDisplayName = currentCase.getDisplayName(); + String previousCaseName = currentCase.getName(); + String previousCaseDir = currentCase.getCaseDirectory(); try { closeCurrentCase(); } catch (CaseActionException ex) { - logger.log(Level.SEVERE, "Error closing the previous current case", ex); //NON-NLS + logger.log(Level.SEVERE, String.format("Error closing the previous current case %s (%s) in %s", previousCaseDisplayName, previousCaseName, previousCaseDir), ex); //NON-NLS } } - logger.log(Level.INFO, "Creating current case with display name {0} in {1}", new Object[]{caseDisplayName, caseDir}); //NON-NLS + logger.log(Level.INFO, "Creating current case {0} in {1}", new Object[]{caseDisplayName, caseDir}); //NON-NLS Case newCurrentCase = new Case(); - newCurrentCase.open(caseDir, caseDisplayName, caseNumber, examiner, caseType); + newCurrentCase.create(caseType, caseDir, caseDisplayName, caseNumber, examiner); currentCase = newCurrentCase; - logger.log(Level.INFO, "Created currrent case {0} (display name {1}) in {2}", new Object[]{newCurrentCase.getName(), caseDisplayName, caseDir}); //NON-NLS + logger.log(Level.INFO, "Created currrent case {0} ({1}) in {2}", new Object[]{newCurrentCase.getDisplayName(), newCurrentCase.getName(), newCurrentCase.getCaseDirectory()}); //NON-NLS if (RuntimeProperties.runningWithGUI()) { updateGUIForCaseOpened(newCurrentCase); } @@ -723,83 +724,44 @@ public class Case { } /** - * Transforms the display name for a case to make a suitable case name for - * use in case directory paths, coordination service locks, Active MQ - * message channels, etc. - * - * ActiveMQ: - * http://activemq.2283324.n4.nabble.com/What-are-limitations-restrictions-on-destination-name-td4664141.html - * may not be ? + * Transforms a case display name into a unique case name that can be used + * to identify the case even if the display name is changed. * * @param caseDisplayName A case display name. * - * @return The case display name transformed into a corresponding case name. + * @return The unique case name. * - * @throws org.sleuthkit.autopsy.casemodule.Case.IllegalCaseNameException + * @throws IllegalCaseNameException If the transformation fails. */ - public static String displayNameToCaseName(String caseDisplayName) throws IllegalCaseNameException { + private static String displayNameToUniqueName(String caseDisplayName) throws IllegalCaseNameException { + /* + * Replace all non-ASCII characters. + */ + String uniqueCaseName = caseDisplayName.replaceAll("[^\\p{ASCII}]", "_"); //NON-NLS /* - * Remove all non-ASCII characters. + * Replace all control characters. */ - String caseName = caseDisplayName.replaceAll("[^\\p{ASCII}]", "_"); //NON-NLS + uniqueCaseName = uniqueCaseName.replaceAll("[\\p{Cntrl}]", "_"); //NON-NLS /* - * Remove all control characters. + * Replace /, \, :, ?, space, ' ". */ - caseName = caseName.replaceAll("[\\p{Cntrl}]", "_"); //NON-NLS - - /* - * Remove /, \, :, ?, space, ' ". - */ - caseName = caseName.replaceAll("[ /?:'\"\\\\]", "_"); //NON-NLS + uniqueCaseName = uniqueCaseName.replaceAll("[ /?:'\"\\\\]", "_"); //NON-NLS /* * Make it all lowercase. */ - caseName = caseName.toLowerCase(); - - if (caseName.isEmpty()) { - throw new IllegalCaseNameException(String.format("Failed to convert case name '%s'", caseDisplayName)); - } - - return caseName; - } - - /** - * Transforms a case name into a name for a PostgreSQL database that can be - * safely used in SQL commands as described at - * http://www.postgresql.org/docs/9.4/static/sql-syntax-lexical.html: 63 - * chars max, must start with a letter or underscore, following chars can be - * letters, underscores, or digits. A timestamp suffix is added to ensure - * uniqueness. - * - * @param caseName The case name. - * - * @return The case name transformed into a corresponding PostgreSQL case - * database name. - */ - private static String caseNameToCaseDbName(String caseName) throws IllegalCaseNameException { - /* - * Must start with letter or underscore. If not, prepend an underscore. - */ - String dbName = caseName; - if (dbName.length() > 0 && !(Character.isLetter(dbName.codePointAt(0))) && !(dbName.codePointAt(0) == '_')) { - dbName = "_" + dbName; - } + uniqueCaseName = uniqueCaseName.toLowerCase(); /* - * Truncate to 63-16=47 chars to accomodate the timestamp, then add the - * timestamp. + * Add a time stamp for uniqueness. */ - if (dbName.length() > MAX_CASEDB_NAME_LEN_MINUS_TIMESTAMP) { - dbName = dbName.substring(0, MAX_CASEDB_NAME_LEN_MINUS_TIMESTAMP); - } SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss"); Date date = new Date(); - dbName = dbName + "_" + dateFormat.format(date); + uniqueCaseName = uniqueCaseName + "_" + dateFormat.format(date); - return dbName; + return uniqueCaseName; } /** @@ -973,7 +935,7 @@ public class Case { private static CoordinationService.Lock acquireExclusiveCaseResourcesLock(String caseDir) throws CaseActionException { try { String resourcesNodeName = caseDir + "_resources"; - Lock lock = CoordinationService.getInstance().tryGetExclusiveLock(CategoryNode.CASES, resourcesNodeName, RESOURCE_LOCK_TIMOUT_HOURS, TimeUnit.HOURS); + Lock lock = CoordinationService.getInstance().tryGetExclusiveLock(CategoryNode.CASES, resourcesNodeName, RESOURCES_LOCK_TIMOUT_HOURS, TimeUnit.HOURS); if (null == lock) { throw new CaseActionException(Bundle.Case_creationException_couldNotAcquireResourcesLock()); } @@ -1585,6 +1547,7 @@ public class Case { } /** + * @param caseType The type of case (single-user or multi-user). * @param caseDir The full path of the case directory. The directory * will be created if it doesn't already exist; if it * exists, it is ASSUMED it was created by calling @@ -1594,7 +1557,6 @@ public class Case { * @param caseNumber The case number, can be the empty string. * @param examiner The examiner to associate with the case, can be * the empty string. - * @param caseType The type of case (single-user or multi-user). * * @throws CaseActionException if there is a problem creating the case. The * exception will have a user-friendly message @@ -1602,24 +1564,12 @@ public class Case { * exception. */ @Messages({ - "Case.exceptionMessage.illegalCaseName=Case name contains illegal characters.", "Case.progressIndicatorTitle.creatingCase=Creating Case", "Case.progressIndicatorCancelButton.label=Cancel", "Case.progressMessage.preparing=Preparing...", "Case.progressMessage.openingCaseResources=Preparing to open case resources.
    This may take time if another user is upgrading the case." }) - private void open(String caseDir, String caseDisplayName, String caseNumber, String examiner, CaseType caseType) throws CaseActionException { - /* - * Clean up the display name for the case to make a suitable immutable - * case name. - */ - String caseName; - try { - caseName = displayNameToCaseName(caseDisplayName); - } catch (IllegalCaseNameException ex) { - throw new CaseActionException(Bundle.Case_exceptionMessage_wrapperMessage(Bundle.Case_exceptionMessage_illegalCaseName()), ex); - } - + private void create(CaseType caseType, String caseDir, String caseDisplayName, String caseNumber, String examiner) throws CaseActionException { /* * Set up either a GUI progress indicator or a logging progress * indicator. @@ -1648,7 +1598,7 @@ public class Case { caseLockingExecutor = Executors.newSingleThreadExecutor(); Future future = caseLockingExecutor.submit(() -> { if (CaseType.SINGLE_USER_CASE == caseType) { - open(caseDir, caseName, caseDisplayName, caseNumber, examiner, caseType, progressIndicator); + create(caseType, caseDir, caseDisplayName, caseNumber, examiner, progressIndicator); } else { /* * Acquire a shared case directory lock that will be held as @@ -1657,6 +1607,7 @@ public class Case { */ progressIndicator.start(Bundle.Case_progressMessage_openingCaseResources()); acquireSharedCaseDirLock(caseDir); + /* * Acquire an exclusive case resources lock to ensure only one * node at a time can create/open/upgrade/close the case @@ -1665,14 +1616,14 @@ public class Case { try (CoordinationService.Lock resourcesLock = acquireExclusiveCaseResourcesLock(caseDir)) { assert (null != resourcesLock); try { - open(caseDir, caseName, caseDisplayName, caseNumber, examiner, caseType, progressIndicator); + create(caseType, caseDir, caseDisplayName, caseNumber, examiner, progressIndicator); } catch (CaseActionException ex) { /* * Release the case directory lock immediately if there * was a problem opening the case. */ if (CaseType.MULTI_USER_CASE == caseType) { - releaseSharedCaseDirLock(caseName); + releaseSharedCaseDirLock(caseDir); } throw ex; } @@ -1696,7 +1647,6 @@ public class Case { */ try { future.get(); - } catch (InterruptedException ex) { throw new CaseActionException(Bundle.Case_exceptionMessage_wrapperMessage(ex.getMessage()), ex); } catch (ExecutionException ex) { @@ -1711,18 +1661,20 @@ public class Case { } /** - * Creates and opens a new case. + * Creates a new case. * - * @param caseDir The full path of the case directory. The directory - * will be created if it doesn't already exist; if it - * exists, it is ASSUMED it was created by calling - * createCaseDirectory. - * @param caseDisplayName The display name of case, which may be changed - * later by the user. - * @param caseNumber The case number, can be the empty string. - * @param examiner The examiner to associate with the case, can be - * the empty string. - * @param caseType The type of case (single-user or multi-user). + * @param caseType The type of case (single-user or multi-user). + * @param caseDir The full path of the case directory. The + * directory will be created if it doesn't already + * exist; if it exists, it is ASSUMED it was + * created by calling createCaseDirectory. + * @param caseName The case name. + * @param caseDisplayName The display name of case, which may be changed + * later by the user. + * @param caseNumber The case number, can be the empty string. + * @param examiner The examiner to associate with the case, can be + * the empty string. + * @param progressIndicator A progress indicator. * * @throws CaseActionException if there is a problem creating the case. The * exception will have a user-friendly message @@ -1730,6 +1682,7 @@ public class Case { * exception. */ @Messages({ + "Case.exceptionMessage.illegalCaseName=Case name contains one or more illegal characters (\\,/,:,*,?,<,>,|).", "Case.progressMessage.creatingCaseDirectory=Creating case directory...", "Case.progressMessage.creatingCaseDatabase=Creating case database...", "Case.exceptionMessage.couldNotCreateCaseDatabaseName=Failed to create case database name from case name.", @@ -1737,7 +1690,7 @@ public class Case { "Case.exceptionMessage.couldNotCreateMetadataFile=Failed to create case metadata file.", "Case.exceptionMessage.couldNotCreateCaseDatabase=Failed to create case database." }) - private void open(String caseDir, String caseName, String caseDisplayName, String caseNumber, String examiner, CaseType caseType, ProgressIndicator progressIndicator) throws CaseActionException { + private void create(CaseType caseType, String caseDir, String caseDisplayName, String caseNumber, String examiner, ProgressIndicator progressIndicator) throws CaseActionException { /* * Create the case directory, if it does not already exist. * @@ -1763,37 +1716,41 @@ public class Case { Case.createCaseDirectory(caseDir, caseType); } + /* + * Create a unique and immutable case name from the case display name. + */ + String caseName; + try { + caseName = displayNameToUniqueName(caseDisplayName); + } catch (IllegalCaseNameException ex) { + throw new CaseActionException(Bundle.Case_exceptionMessage_wrapperMessage(Bundle.Case_exceptionMessage_illegalCaseName()), ex); + } + /* * Create the case database. */ progressIndicator.progress(Bundle.Case_progressMessage_creatingCaseDatabase()); String dbName = null; - try { - if (CaseType.SINGLE_USER_CASE == caseType) { - dbName = SINGLE_USER_CASE_DB_NAME; - } else if (CaseType.MULTI_USER_CASE == caseType) { - dbName = caseNameToCaseDbName(caseName); - } - } catch (IllegalCaseNameException ex) { - throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotCreateCaseDatabaseName(), ex); - } try { if (CaseType.SINGLE_USER_CASE == caseType) { /* * For single-user cases, the case database is a SQLite database - * physically located in the root of the case directory. + * with a standard name, physically located in the root of the + * case directory. */ + dbName = SINGLE_USER_CASE_DB_NAME; this.caseDb = SleuthkitCase.newCase(Paths.get(caseDir, SINGLE_USER_CASE_DB_NAME).toString()); } else if (CaseType.MULTI_USER_CASE == caseType) { /* * For multi-user cases, the case database is a PostgreSQL - * database physically located on the database server. + * database with a name derived from the case display name, + * physically located on the database server. */ - this.caseDb = SleuthkitCase.newCase(dbName, UserPreferences.getDatabaseConnectionInfo(), caseDir); + this.caseDb = SleuthkitCase.newCase(caseDisplayName, UserPreferences.getDatabaseConnectionInfo(), caseDir); + dbName = this.caseDb.getDatabaseName(); } } catch (TskCoreException ex) { throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotCreateCaseDatabase(), ex); - } catch (UserPreferencesException ex) { throw new CaseActionException(NbBundle.getMessage(Case.class, "Case.databaseConnectionInfo.error.msg"), ex); } @@ -1814,7 +1771,7 @@ public class Case { /** * Opens an existing case. * - * @param caseMetadataFilePath The apth to the case metadata file. + * @param caseMetadataFilePath The path to the case metadata file. * * @throws CaseActionException if there is a problem creating the case. The * exception will have a user-friendly message @@ -1980,7 +1937,8 @@ public class Case { "Case.progressMessage.settingUpNetworkCommunications=Setting up network communications...",}) private void openServices(ProgressIndicator progressIndicator) throws CaseActionException { /* - * Switch to writing to the application logs in the logs subdirectory. + * Switch to writing to the application logs in the logs subdirectory of + * the case directory. */ progressIndicator.progress(Bundle.Case_progressMessage_switchingLogDirectory()); Logger.setLogDirectory(getLogDirectoryPath()); @@ -1989,12 +1947,11 @@ public class Case { * Hook up a SleuthKit layer error reporter. */ progressIndicator.progress(Bundle.Case_progressMessage_settingUpTskErrorReporting()); - this.sleuthkitErrorReporter = new SleuthkitErrorReporter(MIN_SECS_BETWEEN_TSK_ERROR_REPORTS, NbBundle.getMessage(Case.class, "IntervalErrorReport.ErrorText")); this.caseDb.addErrorObserver(this.sleuthkitErrorReporter); /* - * Clear the temp subdirectory. + * Clear the temp subdirectory of the case directory. */ progressIndicator.progress(Bundle.Case_progressMessage_clearingTempDirectory()); Case.clearTempSubDir(this.getTempDirectory()); @@ -2335,7 +2292,7 @@ public class Case { @Messages({"Case.creationException.couldNotAcquireDirLock=Failed to get lock on case directory."}) private void acquireSharedCaseDirLock(String caseDir) throws CaseActionException { try { - caseDirLock = CoordinationService.getInstance().tryGetSharedLock(CategoryNode.CASES, caseDir, SHARED_DIR_LOCK_TIMOUT_HOURS, TimeUnit.HOURS); + caseDirLock = CoordinationService.getInstance().tryGetSharedLock(CategoryNode.CASES, caseDir, DIR_LOCK_TIMOUT_HOURS, TimeUnit.HOURS); if (null == caseDirLock) { throw new CaseActionException(Bundle.Case_creationException_couldNotAcquireDirLock()); } @@ -2404,7 +2361,7 @@ public class Case { * An exception to throw when a case name with invalid characters is * encountered. */ - public final static class IllegalCaseNameException extends Exception { + final static class IllegalCaseNameException extends Exception { private static final long serialVersionUID = 1L; diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java index d53b8b3c66..9a870e25a2 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java @@ -125,7 +125,7 @@ public final class CaseMetadata { * created. */ CaseMetadata(String caseDirectory, Case.CaseType caseType, String caseName, String caseDisplayName, String caseNumber, String examiner, String caseDatabase) throws CaseMetadataException { - metadataFilePath = Paths.get(caseDirectory, caseName + FILE_EXTENSION); + metadataFilePath = Paths.get(caseDirectory, caseDisplayName + FILE_EXTENSION); this.caseType = caseType; this.caseName = caseName; this.caseDisplayName = caseDisplayName; diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardPanel1.java b/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardPanel1.java index 8ceda8fc2a..dcfaab449c 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardPanel1.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardPanel1.java @@ -204,25 +204,19 @@ class NewCaseWizardPanel1 implements WizardDescriptor.ValidatingPanel | - if (!Case.isValidName(caseDisplayName)) { + /* + * Check whether or not the case name is valid. To be valid, the case + * name must not contain any characters that are not allowed in file + * names, since it will be used as the name of the case directory. + */ + String caseName = getComponent().getCaseName(); + if (!Case.isValidName(caseName)) { String errorMsg = NbBundle .getMessage(this.getClass(), "NewCaseWizardPanel1.validate.errMsg.invalidSymbols"); validationError(errorMsg); } else { - String caseName = ""; - try { - caseName = Case.displayNameToCaseName(caseDisplayName); - } catch (Case.IllegalCaseNameException ex) { - String errorMsg = NbBundle - .getMessage(this.getClass(), "NewCaseWizardPanel1.validate.errMsg.invalidSymbols"); - validationError(errorMsg); - } + String caseParentDir = getComponent().getCaseParentDir(); String caseDirPath = caseParentDir + caseName; // check if the directory exist diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/SingleUserCaseConverter.java b/Core/src/org/sleuthkit/autopsy/casemodule/SingleUserCaseConverter.java index ddc0ccd1d5..50494f47a0 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/SingleUserCaseConverter.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/SingleUserCaseConverter.java @@ -43,7 +43,7 @@ import org.sleuthkit.datamodel.TskData; /** * Import a case from single-user to multi-user. - * + * * DO NOT USE, NEEDS TO BE UPDATED */ public class SingleUserCaseConverter { @@ -175,9 +175,15 @@ public class SingleUserCaseConverter { } // Create sanitized names for PostgreSQL and Solr + /* + * RJC: Removed package access sanitizeCaseName method, so this is no + * longer correct, but this whole class is currently out-of-date (out of + * synch with case database schema) and probably belongs in the TSK + * layer anyway, see JIRA-1984. + */ SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss"); //NON-NLS Date date = new Date(); - String dbName = Case.displayNameToCaseName(icd.getNewCaseName()) + "_" + dateFormat.format(date); //NON-NLS + String dbName = icd.getNewCaseName() + "_" + dateFormat.format(date); //NON-NLS icd.setPostgreSQLDbName(dbName); // Copy items to new hostname folder structure @@ -493,12 +499,12 @@ public class SingleUserCaseConverter { if (value > biggestPK) { biggestPK = value; } - + // If the entry contains an encoding type, copy it. Otherwise use NONE. // The test on column count can be removed if we upgrade the database before conversion. int encoding = TskData.EncodingType.NONE.getType(); ResultSetMetaData rsMetaData = inputResultSet.getMetaData(); - if(rsMetaData.getColumnCount() == 3){ + if (rsMetaData.getColumnCount() == 3) { encoding = inputResultSet.getInt(3); } outputStatement.executeUpdate("INSERT INTO tsk_files_path (obj_id, path, encoding_type) VALUES (" //NON-NLS diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java index 9ffec1bedc..900a5a603b 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java @@ -64,7 +64,6 @@ import javax.annotation.concurrent.ThreadSafe; import org.openide.util.Lookup; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case.CaseType; -import org.sleuthkit.autopsy.casemodule.Case.IllegalCaseNameException; import org.sleuthkit.autopsy.casemodule.CaseActionException; import org.sleuthkit.autopsy.casemodule.CaseMetadata; import org.sleuthkit.autopsy.coordinationservice.CoordinationService; @@ -1880,14 +1879,8 @@ public final class AutoIngestManager extends Observable implements PropertyChang */ private Case openCase() throws CoordinationServiceException, CaseManagementException, InterruptedException { Manifest manifest = currentJob.getManifest(); - String caseDisplayName = manifest.getCaseName(); - String caseName; - try { - caseName = Case.displayNameToCaseName(caseDisplayName); - } catch (IllegalCaseNameException ex) { - throw new CaseManagementException(String.format("Error creating or opening case %s for %s", manifest.getCaseName(), manifest.getFilePath()), ex); - } - SYS_LOGGER.log(Level.INFO, "Opening case {0} ({1}) for {2}", new Object[]{caseDisplayName, caseName, manifest.getFilePath()}); + String caseName = manifest.getCaseName(); + SYS_LOGGER.log(Level.INFO, "Opening case {0} for {2}", new Object[]{caseName, manifest.getFilePath()}); currentJob.setStage(AutoIngestJob.Stage.OPENING_CASE); /* * Acquire and hold a case name lock so that only one node at as @@ -1917,16 +1910,16 @@ public final class AutoIngestManager extends Observable implements PropertyChang return caseForJob; } catch (CaseActionException ex) { - throw new CaseManagementException(String.format("Error creating or opening case %s (%s) for %s", manifest.getCaseName(), caseName, manifest.getFilePath()), ex); + throw new CaseManagementException(String.format("Error creating or opening case %s for %s", caseName, manifest.getFilePath()), ex); } catch (IllegalStateException ex) { /* * Deal with the unfortunate fact that * Case.getCurrentCase throws IllegalStateException. */ - throw new CaseManagementException(String.format("Error getting current case %s (%s) for %s", caseName, manifest.getCaseName(), manifest.getFilePath()), ex); + throw new CaseManagementException(String.format("Error getting current case %s for %s", caseName, manifest.getFilePath()), ex); } } else { - throw new CaseManagementException(String.format("Timed out acquiring case name lock for %s for %s", manifest.getCaseName(), manifest.getFilePath())); + throw new CaseManagementException(String.format("Timed out acquiring case name lock for %s for %s", caseName, manifest.getFilePath())); } } } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PathUtils.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PathUtils.java index 9b99e8c13f..772dcf667e 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PathUtils.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PathUtils.java @@ -46,18 +46,12 @@ final class PathUtils { * @return The path of the case folder, or null if it is not found. */ static Path findCaseDirectory(Path folderToSearch, String caseName) { - String sanitizedCaseName; - try { - sanitizedCaseName = Case.displayNameToCaseName(caseName); - } catch (Case.IllegalCaseNameException unused) { - return null; - } File searchFolder = new File(folderToSearch.toString()); if (!searchFolder.isDirectory()) { return null; } Path caseFolderPath = null; - String[] candidateFolders = searchFolder.list(new CaseFolderFilter(sanitizedCaseName)); + String[] candidateFolders = searchFolder.list(new CaseFolderFilter(caseName)); long mostRecentModified = 0; for (String candidateFolder : candidateFolders) { File file = new File(candidateFolder); From a4d219648448484d7a2987268ea120d8540694b1 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Fri, 21 Apr 2017 18:10:22 -0400 Subject: [PATCH 28/37] Modify case display name/unique name handling --- .../sleuthkit/autopsy/casemodule/Case.java | 54 ++++--------------- 1 file changed, 10 insertions(+), 44 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index ca935e7a81..08880d9b9b 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -730,10 +730,8 @@ public class Case { * @param caseDisplayName A case display name. * * @return The unique case name. - * - * @throws IllegalCaseNameException If the transformation fails. */ - private static String displayNameToUniqueName(String caseDisplayName) throws IllegalCaseNameException { + private static String displayNameToUniqueName(String caseDisplayName) { /* * Replace all non-ASCII characters. */ @@ -1682,7 +1680,7 @@ public class Case { * exception. */ @Messages({ - "Case.exceptionMessage.illegalCaseName=Case name contains one or more illegal characters (\\,/,:,*,?,<,>,|).", + "Case.exceptionMessage.emptyCaseName=Case name is empty.", "Case.progressMessage.creatingCaseDirectory=Creating case directory...", "Case.progressMessage.creatingCaseDatabase=Creating case database...", "Case.exceptionMessage.couldNotCreateCaseDatabaseName=Failed to create case database name from case name.", @@ -1691,6 +1689,14 @@ public class Case { "Case.exceptionMessage.couldNotCreateCaseDatabase=Failed to create case database." }) private void create(CaseType caseType, String caseDir, String caseDisplayName, String caseNumber, String examiner, ProgressIndicator progressIndicator) throws CaseActionException { + /* + * Create a unique and immutable case name from the case display name. + */ + if (caseDisplayName.isEmpty()) { + throw new CaseActionException(Bundle.Case_exceptionMessage_emptyCaseName()); + } + String caseName = displayNameToUniqueName(caseDisplayName); + /* * Create the case directory, if it does not already exist. * @@ -1716,16 +1722,6 @@ public class Case { Case.createCaseDirectory(caseDir, caseType); } - /* - * Create a unique and immutable case name from the case display name. - */ - String caseName; - try { - caseName = displayNameToUniqueName(caseDisplayName); - } catch (IllegalCaseNameException ex) { - throw new CaseActionException(Bundle.Case_exceptionMessage_wrapperMessage(Bundle.Case_exceptionMessage_illegalCaseName()), ex); - } - /* * Create the case database. */ @@ -2357,36 +2353,6 @@ public class Case { } - /** - * An exception to throw when a case name with invalid characters is - * encountered. - */ - final static class IllegalCaseNameException extends Exception { - - private static final long serialVersionUID = 1L; - - /** - * Constructs an exception to throw when a case name with invalid - * characters is encountered. - * - * @param message The exception message. - */ - IllegalCaseNameException(String message) { - super(message); - } - - /** - * Constructs an exception to throw when a case name with invalid - * characters is encountered. - * - * @param message The exception message. - * @param cause The exceptin cause. - */ - IllegalCaseNameException(String message, Throwable cause) { - super(message, cause); - } - } - /** * Creates a new, single-user Autopsy case. * From 87a81b4701c2ba8130b981f9143b589e60f4d29d Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 21 Apr 2017 18:35:58 -0400 Subject: [PATCH 29/37] 2572 fixed Agency Logo copying for reports to work with non png files --- .../org/sleuthkit/autopsy/report/ReportHTML.java | 14 +++++++++----- .../timeline/snapshot/SnapShotReportWriter.java | 4 ++-- .../timeline/snapshot/summary_template.html | 2 +- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java b/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java index 08bf2e9b15..dd20031e0b 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java @@ -32,6 +32,9 @@ import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.UnsupportedEncodingException; import java.io.Writer; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; @@ -856,7 +859,7 @@ class ReportHTML implements TableReportModule { // use default Autopsy icon if custom icon is not set iconPath = "favicon.ico"; } else { - iconPath = "agency_logo"; //ref to writeNav() for agency_logo + iconPath = Paths.get(reportBranding.getAgencyLogoPath()).getFileName().toString(); //ref to writeNav() for agency_logo } index.append("\n").append(reportTitle).append(" ").append( NbBundle.getMessage(this.getClass(), "ReportHTML.writeIndex.title", currentCase.getDisplayName())).append( @@ -949,9 +952,8 @@ class ReportHTML implements TableReportModule { String agencyLogoPath = reportBranding.getAgencyLogoPath(); if (agencyLogoPath != null && !agencyLogoPath.isEmpty()) { - File from = new File(agencyLogoPath); - File to = new File(path); - FileUtil.copyFile(FileUtil.toFileObject(from), FileUtil.toFileObject(to), "agency_logo"); //NON-NLS + Path destinationPath = Paths.get(path); + Files.copy(Files.newInputStream(Paths.get(agencyLogoPath)), destinationPath.resolve(Paths.get(agencyLogoPath).getFileName())); //NON-NLS } in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/favicon.ico"); //NON-NLS @@ -1049,7 +1051,9 @@ class ReportHTML implements TableReportModule { summary.append("<div class=\"title\">\n"); //NON-NLS if (agencyLogoSet) { summary.append("<div class=\"left\">\n"); //NON-NLS - summary.append("<img src=\"agency_logo.png\" />\n"); //NON-NLS + summary.append("<img src=\""); + summary.append(Paths.get(reportBranding.getAgencyLogoPath()).getFileName().toString()); + summary.append("\" />\n"); //NON-NLS summary.append("</div>\n"); //NON-NLS } final String align = agencyLogoSet ? "right" : "left"; //NON-NLS NON-NLS diff --git a/Core/src/org/sleuthkit/autopsy/timeline/snapshot/SnapShotReportWriter.java b/Core/src/org/sleuthkit/autopsy/timeline/snapshot/SnapShotReportWriter.java index 4f4580bcd6..2ef3e935a8 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/snapshot/SnapShotReportWriter.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/snapshot/SnapShotReportWriter.java @@ -156,7 +156,7 @@ public class SnapShotReportWriter { summaryContext.put("generationDateTime", new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(generationDate)); //NON-NLS summaryContext.put("ingestRunning", IngestManager.getInstance().isIngestRunning()); //NON-NLS summaryContext.put("currentCase", currentCase); //NON-NLS - + summaryContext.put("agencyLogoFileName", Paths.get(reportBranding.getAgencyLogoPath()).getFileName().toString()); fillTemplateAndWrite("/org/sleuthkit/autopsy/timeline/snapshot/summary_template.html", "Summary", summaryContext, reportFolderPath.resolve("summary.html")); //NON-NLS } @@ -199,7 +199,7 @@ public class SnapShotReportWriter { } String agencyLogoPath = reportBranding.getAgencyLogoPath(); if (StringUtils.isNotBlank(agencyLogoPath)) { - Files.copy(Files.newInputStream(Paths.get(agencyLogoPath)), reportFolderPath.resolve("agency_logo.png")); //NON-NLS + Files.copy(Files.newInputStream(Paths.get(agencyLogoPath)), reportFolderPath.resolve(Paths.get(reportBranding.getAgencyLogoPath()).getFileName())); //NON-NLS } //copy navigation html diff --git a/Core/src/org/sleuthkit/autopsy/timeline/snapshot/summary_template.html b/Core/src/org/sleuthkit/autopsy/timeline/snapshot/summary_template.html index dda4a3bc1f..2d1e37a2a8 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/snapshot/summary_template.html +++ b/Core/src/org/sleuthkit/autopsy/timeline/snapshot/summary_template.html @@ -13,7 +13,7 @@ <div class="title"> {{#reportBranding.getAgencyLogoPath}} <div class="left"> - <img src="agency_logo.png" /> + <img src="{{agencyLogoFileName}}" /> </div> <div class="right"> {{/reportBranding.getAgencyLogoPath}} From be6639651bf20f6b3d32733acbdeea8b4ffc51cc Mon Sep 17 00:00:00 2001 From: William Schaefer <wschaefer@basistech.net> Date: Fri, 21 Apr 2017 18:54:13 -0400 Subject: [PATCH 30/37] 2572 now browse button MUST be used to select Agency Logo, to prevent non image files --- .../autopsy/corecomponents/AutopsyOptionsPanel.form | 6 ++++++ .../autopsy/corecomponents/AutopsyOptionsPanel.java | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form index acc5371a90..06607d7d9b 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form @@ -266,9 +266,15 @@ </Component> <Component class="javax.swing.JTextField" name="agencyLogoPathField"> <Properties> + <Property name="editable" type="boolean" value="false"/> + <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor"> + <Color blue="ff" green="ff" red="ff" type="rgb"/> + </Property> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="AutopsyOptionsPanel.agencyLogoPathField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> </Property> + <Property name="focusable" type="boolean" value="false"/> + <Property name="requestFocusEnabled" type="boolean" value="false"/> </Properties> </Component> <Component class="javax.swing.JButton" name="browseLogosButton"> diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java index 4e27e85504..4f95087f66 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java @@ -177,7 +177,11 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { org.openide.awt.Mnemonics.setLocalizedText(agencyLogoImageLabel, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.agencyLogoImageLabel.text")); // NOI18N + agencyLogoPathField.setEditable(false); + agencyLogoPathField.setBackground(new java.awt.Color(255, 255, 255)); agencyLogoPathField.setText(org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.agencyLogoPathField.text")); // NOI18N + agencyLogoPathField.setFocusable(false); + agencyLogoPathField.setRequestFocusEnabled(false); org.openide.awt.Mnemonics.setLocalizedText(browseLogosButton, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.browseLogosButton.text")); // NOI18N browseLogosButton.addActionListener(new java.awt.event.ActionListener() { From 1a351441f24a8101361b66812935dfae221e2bc8 Mon Sep 17 00:00:00 2001 From: William Schaefer <wschaefer@basistech.net> Date: Fri, 21 Apr 2017 19:08:41 -0400 Subject: [PATCH 31/37] 2572 fix for when agency logo has not been set for Snapshot report generator --- .../autopsy/timeline/snapshot/SnapShotReportWriter.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/timeline/snapshot/SnapShotReportWriter.java b/Core/src/org/sleuthkit/autopsy/timeline/snapshot/SnapShotReportWriter.java index 2ef3e935a8..a9bce0acb8 100644 --- a/Core/src/org/sleuthkit/autopsy/timeline/snapshot/SnapShotReportWriter.java +++ b/Core/src/org/sleuthkit/autopsy/timeline/snapshot/SnapShotReportWriter.java @@ -156,7 +156,11 @@ public class SnapShotReportWriter { summaryContext.put("generationDateTime", new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(generationDate)); //NON-NLS summaryContext.put("ingestRunning", IngestManager.getInstance().isIngestRunning()); //NON-NLS summaryContext.put("currentCase", currentCase); //NON-NLS - summaryContext.put("agencyLogoFileName", Paths.get(reportBranding.getAgencyLogoPath()).getFileName().toString()); + String agencyLogo = "agency_logo.png"; //default name for agency logo. + if (StringUtils.isNotBlank(reportBranding.getAgencyLogoPath())){ + agencyLogo = Paths.get(reportBranding.getAgencyLogoPath()).getFileName().toString(); + } + summaryContext.put("agencyLogoFileName", agencyLogo); fillTemplateAndWrite("/org/sleuthkit/autopsy/timeline/snapshot/summary_template.html", "Summary", summaryContext, reportFolderPath.resolve("summary.html")); //NON-NLS } From 5b6abc525eeb0c4cb620bc38fbc1230e2b870b83 Mon Sep 17 00:00:00 2001 From: William Schaefer <wschaefer@basistech.net> Date: Mon, 24 Apr 2017 09:56:53 -0400 Subject: [PATCH 32/37] 2572 bmp included in list of allowable agency logo file types --- Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties | 2 +- Core/src/org/sleuthkit/autopsy/casemodule/GeneralFilter.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties index 8d7c8db0f6..3570da2497 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties @@ -148,7 +148,7 @@ GeneralFilter.encaseImageDesc.text=Encase Images (*.e01) GeneralFilter.virtualMachineImageDesc.text=Virtual Machines (*.vmdk, *.vhd) GeneralFilter.executableDesc.text=Executables (*.exe) ImageDSProcessor.dsType.text=Disk Image or VM File -GeneralFilter.graphicImageDesc.text=Images (*.png, *.jpg, *.jpeg, *.gif) +GeneralFilter.graphicImageDesc.text=Images (*.png, *.jpg, *.jpeg, *.gif, *.bmp) ImageDSProcessor.allDesc.text=All Supported Types ImageFilePanel.moduleErr=Module Error ImageFilePanel.moduleErr.msg=A module caused an error listening to ImageFilePanel updates. See log to determine which module. Some data could be incomplete. diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/GeneralFilter.java b/Core/src/org/sleuthkit/autopsy/casemodule/GeneralFilter.java index 25598f5349..f848722953 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/GeneralFilter.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/GeneralFilter.java @@ -45,7 +45,7 @@ public class GeneralFilter extends FileFilter { public static final List<String> EXECUTABLE_EXTS = Arrays.asList(new String[]{".exe"}); //NON-NLS public static final String EXECUTABLE_DESC = NbBundle.getMessage(GeneralFilter.class, "GeneralFilter.executableDesc.text"); - public static final List<String> GRAPHIC_IMAGE_EXTS = Arrays.asList(new String[]{".png", ".jpeg", ".jpg", ".gif"}); //NON-NLS + public static final List<String> GRAPHIC_IMAGE_EXTS = Arrays.asList(new String[]{".png", ".jpeg", ".jpg", ".gif", ".bmp"}); //NON-NLS public static final String GRAPHIC_IMG_DECR = NbBundle.getMessage(GeneralFilter.class, "GeneralFilter.graphicImageDesc.text"); private List<String> extensions; From d635e3ab613cbd7de8a195e141dd74d1921d4eca Mon Sep 17 00:00:00 2001 From: Eugene Livis <elivis@basistech.com> Date: Mon, 24 Apr 2017 10:42:50 -0400 Subject: [PATCH 33/37] Fixed some python errors --- InternalPythonModules/android/calllog.py | 2 +- InternalPythonModules/android/contact.py | 2 +- InternalPythonModules/android/textmessage.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/InternalPythonModules/android/calllog.py b/InternalPythonModules/android/calllog.py index d27066de86..42e3a293a1 100644 --- a/InternalPythonModules/android/calllog.py +++ b/InternalPythonModules/android/calllog.py @@ -130,7 +130,7 @@ class CallLogAnalyzer(general.AndroidComponentAnalyzer): artifact.addAttribute(BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DIRECTION, general.MODULE_NAME, directionString)) artifact.addAttribute(BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, general.MODULE_NAME, name)) - bbartifacts.add(artifact) + bbartifacts.append(artifact) try: # index the artifact for keyword search diff --git a/InternalPythonModules/android/contact.py b/InternalPythonModules/android/contact.py index 98e2cd17d0..fe56cc1cbb 100644 --- a/InternalPythonModules/android/contact.py +++ b/InternalPythonModules/android/contact.py @@ -134,7 +134,7 @@ class ContactAnalyzer(general.AndroidComponentAnalyzer): oldName = name - bbartifacts.add(artifact) + bbartifacts.append(artifact) try: # index the artifact for keyword search diff --git a/InternalPythonModules/android/textmessage.py b/InternalPythonModules/android/textmessage.py index 3df47671c2..afca23cdf1 100644 --- a/InternalPythonModules/android/textmessage.py +++ b/InternalPythonModules/android/textmessage.py @@ -105,7 +105,7 @@ class TextMessageAnalyzer(general.AndroidComponentAnalyzer): artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT, general.MODULE_NAME, body)) artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE, general.MODULE_NAME, "SMS Message")) - bbartifacts.add(artifact) + bbartifacts.append(artifact) try: # index the artifact for keyword search blackboard = Case.getCurrentCase().getServices().getBlackboard() From dea7c6e29a67bfa42a5a4bf89615f4dfd5c70a7f Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" <dgrove@WIN-DGROV-4999.basistech.net> Date: Mon, 24 Apr 2017 12:28:45 -0400 Subject: [PATCH 34/37] Switched some 'WARNING' log levels to 'SEVERE'. --- .../embeddedfileextractor/ImageExtractor.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/ImageExtractor.java b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/ImageExtractor.java index 6b6ddf70d9..9df9927ad8 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/ImageExtractor.java +++ b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/ImageExtractor.java @@ -226,7 +226,7 @@ class ImageExtractor { return null; } catch (Throwable ex) { // instantiating POI containers throw RuntimeExceptions - logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.docContainer.init.err", af.getName()), ex); //NON-NLS + logger.log(Level.SEVERE, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.docContainer.init.err", af.getName()), ex); //NON-NLS return null; } @@ -280,7 +280,7 @@ class ImageExtractor { return null; } catch (Throwable ex) { // instantiating POI containers throw RuntimeExceptions - logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.docxContainer.init.err", af.getName()), ex); //NON-NLS + logger.log(Level.SEVERE, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.docxContainer.init.err", af.getName()), ex); //NON-NLS return null; } @@ -334,7 +334,7 @@ class ImageExtractor { return null; } catch (Throwable ex) { // instantiating POI containers throw RuntimeExceptions - logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.pptContainer.init.err", af.getName()), ex); //NON-NLS + logger.log(Level.SEVERE, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.pptContainer.init.err", af.getName()), ex); //NON-NLS return null; } @@ -417,7 +417,7 @@ class ImageExtractor { return null; } catch (Throwable ex) { // instantiating POI containers throw RuntimeExceptions - logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.pptxContainer.init.err", af.getName()), ex); //NON-NLS + logger.log(Level.SEVERE, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.pptxContainer.init.err", af.getName()), ex); //NON-NLS return null; } @@ -478,7 +478,7 @@ class ImageExtractor { return null; } catch (Throwable ex) { // instantiating POI containers throw RuntimeExceptions - logger.log(Level.WARNING, String.format("%s%s", NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.xlsContainer.init.err", af.getName()), af.getName()), ex); //NON-NLS + logger.log(Level.SEVERE, String.format("%s%s", NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.xlsContainer.init.err", af.getName()), af.getName()), ex); //NON-NLS return null; } @@ -536,7 +536,7 @@ class ImageExtractor { return null; } catch (Throwable ex) { // instantiating POI containers throw RuntimeExceptions - logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.xlsxContainer.init.err", af.getName()), ex); //NON-NLS + logger.log(Level.SEVERE, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.xlsxContainer.init.err", af.getName()), ex); //NON-NLS return null; } From e4a23322c386f02f98dcbb2c63b2183f53f2c29d Mon Sep 17 00:00:00 2001 From: esaunders <esaunders@basistech.com> Date: Mon, 24 Apr 2017 17:34:11 -0400 Subject: [PATCH 35/37] Convert view indexes to model indexes to fix problem where the wrong case was being opened if the users sorted the table. --- .../autoingest/AutoIngestCasePanel.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.java index 8b82cdcba8..20d2a989cb 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.java @@ -234,7 +234,7 @@ public final class AutoIngestCasePanel extends JPanel { try { int selectedRow = casesTable.getSelectedRow(); if (selectedRow >= 0 && selectedRow < casesTable.getRowCount()) { - return Paths.get(caseTableModel.getValueAt(selectedRow, COLUMN_HEADERS.CASE.ordinal()).toString()); + return Paths.get(caseTableModel.getValueAt(casesTable.convertRowIndexToModel(selectedRow), COLUMN_HEADERS.CASE.ordinal()).toString()); } } catch (Exception ignored) { return null; @@ -251,7 +251,7 @@ public final class AutoIngestCasePanel extends JPanel { if (path != null) { try { for (int row = 0; row < casesTable.getRowCount(); ++row) { - Path temp = Paths.get(caseTableModel.getValueAt(row, COLUMN_HEADERS.CASE.ordinal()).toString()); + Path temp = Paths.get(caseTableModel.getValueAt(casesTable.convertRowIndexToModel(row), COLUMN_HEADERS.CASE.ordinal()).toString()); if (temp.compareTo(path) == 0) { // found it casesTable.setRowSelectionInterval(row, row); return; @@ -546,9 +546,10 @@ public final class AutoIngestCasePanel extends JPanel { * @param evt -- The event that caused this to be called */ private void bnOpenActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnOpenActionPerformed - Path caseMetadataFilePath = Paths.get((String) caseTableModel.getValueAt(casesTable.getSelectedRow(), + int modelRow = casesTable.convertRowIndexToModel(casesTable.getSelectedRow()); + Path caseMetadataFilePath = Paths.get((String) caseTableModel.getValueAt(modelRow, COLUMN_HEADERS.OUTPUTFOLDER.ordinal()), - caseTableModel.getValueAt(casesTable.getSelectedRow(), COLUMN_HEADERS.CASE.ordinal()) + CaseMetadata.getFileExtension()); + caseTableModel.getValueAt(modelRow, COLUMN_HEADERS.CASE.ordinal()) + CaseMetadata.getFileExtension()); openCase(caseMetadataFilePath); }//GEN-LAST:event_bnOpenActionPerformed @@ -587,7 +588,7 @@ public final class AutoIngestCasePanel extends JPanel { }//GEN-LAST:event_rbWeeksItemStateChanged private void bnShowLogActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnShowLogActionPerformed - int selectedRow = casesTable.getSelectedRow(); + int selectedRow = casesTable.convertRowIndexToModel(casesTable.getSelectedRow()); int rowCount = casesTable.getRowCount(); if (selectedRow >= 0 && selectedRow < rowCount) { String thePath = (String) caseTableModel.getValueAt(selectedRow, COLUMN_HEADERS.OUTPUTFOLDER.ordinal()); @@ -611,9 +612,10 @@ public final class AutoIngestCasePanel extends JPanel { private void casesTableMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_casesTableMouseClicked if (evt.getClickCount() == 2) { - Path caseMetadataFilePath = Paths.get((String) caseTableModel.getValueAt(casesTable.getSelectedRow(), + int modelRow = casesTable.convertRowIndexToModel(casesTable.getSelectedRow()); + Path caseMetadataFilePath = Paths.get((String) caseTableModel.getValueAt(modelRow, COLUMN_HEADERS.OUTPUTFOLDER.ordinal()), - caseTableModel.getValueAt(casesTable.getSelectedRow(), COLUMN_HEADERS.CASE.ordinal()) + CaseMetadata.getFileExtension()); + caseTableModel.getValueAt(modelRow, COLUMN_HEADERS.CASE.ordinal()) + CaseMetadata.getFileExtension()); openCase(caseMetadataFilePath); } }//GEN-LAST:event_casesTableMouseClicked From c1c7d9f002cf5f5ff86141212134d08de80c6028 Mon Sep 17 00:00:00 2001 From: esaunders <esaunders@basistech.com> Date: Tue, 25 Apr 2017 14:38:46 -0400 Subject: [PATCH 36/37] Renamed Android Analyzer module name to be backwards compatible with the Java version. --- InternalPythonModules/android/general.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InternalPythonModules/android/general.py b/InternalPythonModules/android/general.py index 02944fc3d2..28c96be9b9 100644 --- a/InternalPythonModules/android/general.py +++ b/InternalPythonModules/android/general.py @@ -17,7 +17,7 @@ See the License for the specific language governing permissions and limitations under the License. """ -MODULE_NAME = "Android Analyzer Python" +MODULE_NAME = "Android Analyzer" """ A parent class of the analyzers From b890a896986fd8c71120f31084817fd45876c4ba Mon Sep 17 00:00:00 2001 From: esaunders <esaunders@basistech.com> Date: Tue, 25 Apr 2017 16:17:37 -0400 Subject: [PATCH 37/37] Bumped Autopsy version to 4.4.0 --- nbproject/project.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nbproject/project.properties b/nbproject/project.properties index 8261bedc39..00ab969c89 100644 --- a/nbproject/project.properties +++ b/nbproject/project.properties @@ -4,7 +4,7 @@ app.title=Autopsy ### lowercase version of above app.name=${branding.token} ### if left unset, version will default to today's date -app.version=4.3.0 +app.version=4.4.0 ### build.type must be one of: DEVELOPMENT, RELEASE #build.type=RELEASE build.type=DEVELOPMENT