mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-17 18:17:43 +00:00
Merge pull request #1315 from sidheshenator/python_module_reload_and_logging
Python module reload and logging
This commit is contained in:
commit
fd70adfc55
@ -70,6 +70,7 @@ public final class JythonModuleLoader {
|
|||||||
private static <T> List<T> getInterfaceImplementations(LineFilter filter, Class<T> interfaceClass) {
|
private static <T> List<T> getInterfaceImplementations(LineFilter filter, Class<T> interfaceClass) {
|
||||||
List<T> objects = new ArrayList<>();
|
List<T> objects = new ArrayList<>();
|
||||||
Set<File> pythonModuleDirs = new HashSet<>();
|
Set<File> pythonModuleDirs = new HashSet<>();
|
||||||
|
PythonInterpreter interpreter = new PythonInterpreter();
|
||||||
|
|
||||||
// add python modules from 'autospy/build/cluster/InternalPythonModules' folder
|
// add python modules from 'autospy/build/cluster/InternalPythonModules' folder
|
||||||
// which are copied from 'autopsy/*/release/InternalPythonModules' folders.
|
// which are copied from 'autopsy/*/release/InternalPythonModules' folders.
|
||||||
@ -90,7 +91,7 @@ public final class JythonModuleLoader {
|
|||||||
if (line.startsWith("class ") && filter.accept(line)) { //NON-NLS
|
if (line.startsWith("class ") && filter.accept(line)) { //NON-NLS
|
||||||
String className = line.substring(6, line.indexOf("("));
|
String className = line.substring(6, line.indexOf("("));
|
||||||
try {
|
try {
|
||||||
objects.add( createObjectFromScript(script, className, interfaceClass));
|
objects.add( createObjectFromScript(interpreter, script, className, interfaceClass));
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
logger.log(Level.SEVERE, String.format("Failed to load %s from %s", className, script.getAbsolutePath()), ex); //NON-NLS
|
logger.log(Level.SEVERE, String.format("Failed to load %s from %s", className, script.getAbsolutePath()), ex); //NON-NLS
|
||||||
// NOTE: using ex.toString() because the current version is always returning null for ex.getMessage().
|
// NOTE: using ex.toString() because the current version is always returning null for ex.getMessage().
|
||||||
@ -112,23 +113,23 @@ public final class JythonModuleLoader {
|
|||||||
return objects;
|
return objects;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <T> T createObjectFromScript(File script, String className, Class<T> interfaceClass) {
|
private static <T> T createObjectFromScript(PythonInterpreter interpreter, File script, String className, Class<T> interfaceClass) {
|
||||||
// Make a "fresh" interpreter every time to avoid name collisions, etc.
|
|
||||||
PythonInterpreter interpreter = new PythonInterpreter();
|
|
||||||
|
|
||||||
// Add the directory where the Python script resides to the Python
|
// Add the directory where the Python script resides to the Python
|
||||||
// module search path to allow the script to use other scripts bundled
|
// module search path to allow the script to use other scripts bundled
|
||||||
// with it.
|
// with it.
|
||||||
interpreter.exec("import sys"); //NON-NLS
|
interpreter.exec("import sys"); //NON-NLS
|
||||||
String path = Matcher.quoteReplacement(script.getParent());
|
String path = Matcher.quoteReplacement(script.getParent());
|
||||||
interpreter.exec("sys.path.append('" + path + "')"); //NON-NLS
|
interpreter.exec("sys.path.append('" + path + "')"); //NON-NLS
|
||||||
|
String moduleName = script.getName().replaceAll(".py", ""); //NON-NLS
|
||||||
|
|
||||||
|
// reload the module so that the changes made to it can be loaded.
|
||||||
|
interpreter.exec("import " + moduleName); //NON-NLS
|
||||||
|
interpreter.exec("reload(" + moduleName + ")"); //NON-NLS
|
||||||
|
|
||||||
// Execute the script and create an instance of the desired class.
|
|
||||||
interpreter.execfile(script.getAbsolutePath());
|
|
||||||
// Importing the appropriate class from the Py Script which contains multiple classes.
|
// Importing the appropriate class from the Py Script which contains multiple classes.
|
||||||
interpreter.exec("from " + script.getName().replaceAll(".py", "") + " import " + className);
|
interpreter.exec("from " + moduleName + " import " + className);
|
||||||
interpreter.exec("obj = " + className + "()"); //NON-NLS
|
interpreter.exec("obj = " + className + "()"); //NON-NLS
|
||||||
|
|
||||||
T obj = interpreter.get("obj", interfaceClass); //NON-NLS
|
T obj = interpreter.get("obj", interfaceClass); //NON-NLS
|
||||||
|
|
||||||
// Remove the directory where the Python script resides from the Python
|
// Remove the directory where the Python script resides from the Python
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
# See http://sleuthkit.org/autopsy/docs/api-docs/3.1/index.html for documentation
|
# See http://sleuthkit.org/autopsy/docs/api-docs/3.1/index.html for documentation
|
||||||
|
|
||||||
import jarray
|
import jarray
|
||||||
|
import inspect
|
||||||
from java.lang import System
|
from java.lang import System
|
||||||
from java.util.logging import Level
|
from java.util.logging import Level
|
||||||
from org.sleuthkit.datamodel import SleuthkitCase
|
from org.sleuthkit.datamodel import SleuthkitCase
|
||||||
@ -58,11 +59,11 @@ from org.sleuthkit.autopsy.casemodule.services import FileManager
|
|||||||
class SampleJythonDataSourceIngestModuleFactory(IngestModuleFactoryAdapter):
|
class SampleJythonDataSourceIngestModuleFactory(IngestModuleFactoryAdapter):
|
||||||
|
|
||||||
# TODO: give it a unique name. Will be shown in module list, logs, etc.
|
# TODO: give it a unique name. Will be shown in module list, logs, etc.
|
||||||
moduleName = "Sample Data Source Module"
|
moduleName = "Sample Data Source Module"
|
||||||
|
|
||||||
def getModuleDisplayName(self):
|
def getModuleDisplayName(self):
|
||||||
return self.moduleName
|
return self.moduleName
|
||||||
|
|
||||||
# TODO: Give it a description
|
# TODO: Give it a description
|
||||||
def getModuleDescription(self):
|
def getModuleDescription(self):
|
||||||
return "Sample module that does X, Y, and Z."
|
return "Sample module that does X, Y, and Z."
|
||||||
@ -82,6 +83,11 @@ class SampleJythonDataSourceIngestModuleFactory(IngestModuleFactoryAdapter):
|
|||||||
# TODO: Rename this to something more specific. Could just remove "Factory" from above name.
|
# TODO: Rename this to something more specific. Could just remove "Factory" from above name.
|
||||||
class SampleJythonDataSourceIngestModule(DataSourceIngestModule):
|
class SampleJythonDataSourceIngestModule(DataSourceIngestModule):
|
||||||
|
|
||||||
|
_logger = Logger.getLogger(SampleJythonDataSourceIngestModuleFactory.moduleName)
|
||||||
|
|
||||||
|
def log(self, level, msg):
|
||||||
|
self._logger.logp(level, self.__class__.__name__, inspect.stack()[1][3], msg)
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.context = None
|
self.context = None
|
||||||
|
|
||||||
@ -93,8 +99,7 @@ class SampleJythonDataSourceIngestModule(DataSourceIngestModule):
|
|||||||
self.context = context
|
self.context = context
|
||||||
# Throw an IngestModule.IngestModuleException exception if there was a problem setting up
|
# Throw an IngestModule.IngestModuleException exception if there was a problem setting up
|
||||||
# raise IngestModuleException(IngestModule(), "Oh No!")
|
# raise IngestModuleException(IngestModule(), "Oh No!")
|
||||||
|
|
||||||
|
|
||||||
# Where the analysis is done.
|
# Where the analysis is done.
|
||||||
# The 'dataSource' object being passed in is of type org.sleuthkit.datamodel.Content.
|
# The 'dataSource' object being passed in is of type org.sleuthkit.datamodel.Content.
|
||||||
# See: http://www.sleuthkit.org/sleuthkit/docs/jni-docs/interfaceorg_1_1sleuthkit_1_1datamodel_1_1_content.html
|
# See: http://www.sleuthkit.org/sleuthkit/docs/jni-docs/interfaceorg_1_1sleuthkit_1_1datamodel_1_1_content.html
|
||||||
@ -104,8 +109,6 @@ class SampleJythonDataSourceIngestModule(DataSourceIngestModule):
|
|||||||
def process(self, dataSource, progressBar):
|
def process(self, dataSource, progressBar):
|
||||||
if self.context.isJobCancelled():
|
if self.context.isJobCancelled():
|
||||||
return IngestModule.ProcessResult.OK
|
return IngestModule.ProcessResult.OK
|
||||||
|
|
||||||
logger = Logger.getLogger(SampleJythonDataSourceIngestModuleFactory.moduleName)
|
|
||||||
|
|
||||||
# we don't know how much work there is yet
|
# we don't know how much work there is yet
|
||||||
progressBar.switchToIndeterminate()
|
progressBar.switchToIndeterminate()
|
||||||
@ -115,13 +118,13 @@ class SampleJythonDataSourceIngestModule(DataSourceIngestModule):
|
|||||||
services = Services(sleuthkitCase)
|
services = Services(sleuthkitCase)
|
||||||
fileManager = services.getFileManager()
|
fileManager = services.getFileManager()
|
||||||
|
|
||||||
# For our example, we will use FileManager to get all
|
# For our example, we will use FileManager to get all
|
||||||
# files with the word "test"
|
# files with the word "test"
|
||||||
# in the name and then count and read them
|
# in the name and then count and read them
|
||||||
files = fileManager.findFiles(dataSource, "%test%")
|
files = fileManager.findFiles(dataSource, "%test%")
|
||||||
|
|
||||||
numFiles = len(files)
|
numFiles = len(files)
|
||||||
logger.logp(Level.INFO, SampleJythonDataSourceIngestModule.__name__, "process", "found " + str(numFiles) + " files")
|
self.log(Level.INFO, "found " + str(numFiles) + " files")
|
||||||
progressBar.switchToDeterminate(numFiles)
|
progressBar.switchToDeterminate(numFiles)
|
||||||
fileCount = 0;
|
fileCount = 0;
|
||||||
for file in files:
|
for file in files:
|
||||||
@ -130,7 +133,7 @@ class SampleJythonDataSourceIngestModule(DataSourceIngestModule):
|
|||||||
if self.context.isJobCancelled():
|
if self.context.isJobCancelled():
|
||||||
return IngestModule.ProcessResult.OK
|
return IngestModule.ProcessResult.OK
|
||||||
|
|
||||||
logger.logp(Level.INFO, SampleJythonDataSourceIngestModule.__name__, "process", "Processing file: " + file.getName())
|
self.log(Level.INFO, "Processing file: " + file.getName())
|
||||||
fileCount += 1
|
fileCount += 1
|
||||||
|
|
||||||
# Make an artifact on the blackboard. TSK_INTERESTING_FILE_HIT is a generic type of
|
# Make an artifact on the blackboard. TSK_INTERESTING_FILE_HIT is a generic type of
|
||||||
@ -139,7 +142,7 @@ class SampleJythonDataSourceIngestModule(DataSourceIngestModule):
|
|||||||
att = BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID(), SampleJythonDataSourceIngestModuleFactory.moduleName, "Test file")
|
att = BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID(), SampleJythonDataSourceIngestModuleFactory.moduleName, "Test file")
|
||||||
art.addAttribute(att)
|
art.addAttribute(att)
|
||||||
|
|
||||||
|
|
||||||
# To further the example, this code will read the contents of the file and count the number of bytes
|
# To further the example, this code will read the contents of the file and count the number of bytes
|
||||||
inputStream = ReadContentInputStream(file)
|
inputStream = ReadContentInputStream(file)
|
||||||
buffer = jarray.zeros(1024, "b")
|
buffer = jarray.zeros(1024, "b")
|
||||||
@ -159,4 +162,4 @@ class SampleJythonDataSourceIngestModule(DataSourceIngestModule):
|
|||||||
"Sample Jython Data Source Ingest Module", "Found %d files" % fileCount)
|
"Sample Jython Data Source Ingest Module", "Found %d files" % fileCount)
|
||||||
IngestServices.getInstance().postMessage(message)
|
IngestServices.getInstance().postMessage(message)
|
||||||
|
|
||||||
return IngestModule.ProcessResult.OK;
|
return IngestModule.ProcessResult.OK;
|
@ -32,6 +32,7 @@
|
|||||||
# See http://sleuthkit.org/autopsy/docs/api-docs/3.1/index.html for documentation
|
# See http://sleuthkit.org/autopsy/docs/api-docs/3.1/index.html for documentation
|
||||||
|
|
||||||
import jarray
|
import jarray
|
||||||
|
import inspect
|
||||||
from java.lang import System
|
from java.lang import System
|
||||||
from java.util.logging import Level
|
from java.util.logging import Level
|
||||||
from org.sleuthkit.datamodel import SleuthkitCase
|
from org.sleuthkit.datamodel import SleuthkitCase
|
||||||
@ -84,12 +85,16 @@ class SampleJythonFileIngestModuleFactory(IngestModuleFactoryAdapter):
|
|||||||
# Looks at the attributes of the passed in file.
|
# Looks at the attributes of the passed in file.
|
||||||
class SampleJythonFileIngestModule(FileIngestModule):
|
class SampleJythonFileIngestModule(FileIngestModule):
|
||||||
|
|
||||||
|
_logger = Logger.getLogger(SampleJythonFileIngestModuleFactory.moduleName)
|
||||||
|
|
||||||
|
def log(self, level, msg):
|
||||||
|
self._logger.logp(level, self.__class__.__name__, inspect.stack()[1][3], msg)
|
||||||
|
|
||||||
# Where any setup and configuration is done
|
# Where any setup and configuration is done
|
||||||
# 'context' is an instance of org.sleuthkit.autopsy.ingest.IngestJobContext.
|
# '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/3.1/classorg_1_1sleuthkit_1_1autopsy_1_1ingest_1_1_ingest_job_context.html
|
||||||
# TODO: Add any setup code that you need here.
|
# TODO: Add any setup code that you need here.
|
||||||
def startUp(self, context):
|
def startUp(self, context):
|
||||||
self.logger = Logger.getLogger(SampleJythonFileIngestModuleFactory.moduleName)
|
|
||||||
self.filesFound = 0
|
self.filesFound = 0
|
||||||
|
|
||||||
# Throw an IngestModule.IngestModuleException exception if there was a problem setting up
|
# Throw an IngestModule.IngestModuleException exception if there was a problem setting up
|
||||||
@ -101,7 +106,6 @@ class SampleJythonFileIngestModule(FileIngestModule):
|
|||||||
# See: http://www.sleuthkit.org/sleuthkit/docs/jni-docs/classorg_1_1sleuthkit_1_1datamodel_1_1_abstract_file.html
|
# See: http://www.sleuthkit.org/sleuthkit/docs/jni-docs/classorg_1_1sleuthkit_1_1datamodel_1_1_abstract_file.html
|
||||||
# TODO: Add your analysis code in here.
|
# TODO: Add your analysis code in here.
|
||||||
def process(self, file):
|
def process(self, file):
|
||||||
|
|
||||||
# Skip non-files
|
# 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 (file.isFile() == False)):
|
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
|
return IngestModule.ProcessResult.OK
|
||||||
@ -109,7 +113,7 @@ class SampleJythonFileIngestModule(FileIngestModule):
|
|||||||
# For an example, we will flag files with .txt in the name and make a blackboard artifact.
|
# For an example, we will flag files with .txt in the name and make a blackboard artifact.
|
||||||
if file.getName().find(".txt") != -1:
|
if file.getName().find(".txt") != -1:
|
||||||
|
|
||||||
self.logger.logp(Level.INFO, SampleJythonFileIngestModule.__name__, "process", "Found a text file: " + file.getName())
|
self.log(Level.INFO, "Found a text file: " + file.getName())
|
||||||
self.filesFound+=1
|
self.filesFound+=1
|
||||||
|
|
||||||
# Make an artifact on the blackboard. TSK_INTERESTING_FILE_HIT is a generic type of
|
# Make an artifact on the blackboard. TSK_INTERESTING_FILE_HIT is a generic type of
|
||||||
@ -125,7 +129,7 @@ class SampleJythonFileIngestModule(FileIngestModule):
|
|||||||
for artifact in artifactList:
|
for artifact in artifactList:
|
||||||
attributeList = artifact.getAttributes();
|
attributeList = artifact.getAttributes();
|
||||||
for attrib in attributeList:
|
for attrib in attributeList:
|
||||||
self.logger.logp(Level.INFO, SampleJythonFileIngestModule.__name__, "process", attrib.toString())
|
self.log(Level.INFO, attrib.toString())
|
||||||
|
|
||||||
# To further the example, this code will read the contents of the file and count the number of bytes
|
# To further the example, this code will read the contents of the file and count the number of bytes
|
||||||
inputStream = ReadContentInputStream(file)
|
inputStream = ReadContentInputStream(file)
|
||||||
@ -143,4 +147,4 @@ class SampleJythonFileIngestModule(FileIngestModule):
|
|||||||
def shutDown(self):
|
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)
|
# 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, str(self.filesFound) + " files found")
|
message = IngestMessage.createMessage(IngestMessage.MessageType.DATA, SampleJythonFileIngestModuleFactory.moduleName, str(self.filesFound) + " files found")
|
||||||
ingestServices = IngestServices.getInstance().postMessage(message)
|
ingestServices = IngestServices.getInstance().postMessage(message)
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
|
|
||||||
|
|
||||||
import jarray
|
import jarray
|
||||||
|
import inspect
|
||||||
from java.lang import System
|
from java.lang import System
|
||||||
from java.util.logging import Level
|
from java.util.logging import Level
|
||||||
from javax.swing import JCheckBox
|
from javax.swing import JCheckBox
|
||||||
@ -68,10 +69,10 @@ class SampleFileIngestModuleWithUIFactory(IngestModuleFactoryAdapter):
|
|||||||
|
|
||||||
# TODO: give it a unique name. Will be shown in module list, logs, etc.
|
# TODO: give it a unique name. Will be shown in module list, logs, etc.
|
||||||
moduleName = "Sample Data Source Module with UI"
|
moduleName = "Sample Data Source Module with UI"
|
||||||
|
|
||||||
def getModuleDisplayName(self):
|
def getModuleDisplayName(self):
|
||||||
return self.moduleName
|
return self.moduleName
|
||||||
|
|
||||||
# TODO: Give it a description
|
# TODO: Give it a description
|
||||||
def getModuleDescription(self):
|
def getModuleDescription(self):
|
||||||
return "Sample module that does X, Y, and Z."
|
return "Sample module that does X, Y, and Z."
|
||||||
@ -109,6 +110,11 @@ class SampleFileIngestModuleWithUIFactory(IngestModuleFactoryAdapter):
|
|||||||
# Looks at the attributes of the passed in file.
|
# Looks at the attributes of the passed in file.
|
||||||
class SampleFileIngestModuleWithUI(FileIngestModule):
|
class SampleFileIngestModuleWithUI(FileIngestModule):
|
||||||
|
|
||||||
|
_logger = Logger.getLogger(SampleFileIngestModuleWithUIFactory.moduleName)
|
||||||
|
|
||||||
|
def log(self, level, msg):
|
||||||
|
self._logger.logp(level, self.__class__.__name__, inspect.stack()[1][3], msg)
|
||||||
|
|
||||||
# Autopsy will pass in the settings from the UI panel
|
# Autopsy will pass in the settings from the UI panel
|
||||||
def __init__(self, settings):
|
def __init__(self, settings):
|
||||||
self.local_settings = settings
|
self.local_settings = settings
|
||||||
@ -117,14 +123,12 @@ class SampleFileIngestModuleWithUI(FileIngestModule):
|
|||||||
# Where any setup and configuration is done
|
# Where any setup and configuration is done
|
||||||
# TODO: Add any setup code that you need here.
|
# TODO: Add any setup code that you need here.
|
||||||
def startUp(self, context):
|
def startUp(self, context):
|
||||||
self.logger = Logger.getLogger(SampleFileIngestModuleWithUIFactory.moduleName)
|
|
||||||
|
|
||||||
# As an example, determine if user configured a flag in UI
|
# As an example, determine if user configured a flag in UI
|
||||||
if self.local_settings.getFlag():
|
if self.local_settings.getFlag():
|
||||||
self.logger.logp(Level.INFO, SampleFileIngestModuleWithUI.__name__, "startUp", "flag is set")
|
self.log(Level.INFO, "flag is set")
|
||||||
else:
|
else:
|
||||||
self.logger.logp(Level.INFO, SampleFileIngestModuleWithUI.__name__, "startUp", "flag is not set")
|
self.log(Level.INFO, "flag is not set")
|
||||||
|
|
||||||
# Throw an IngestModule.IngestModuleException exception if there was a problem setting up
|
# Throw an IngestModule.IngestModuleException exception if there was a problem setting up
|
||||||
# raise IngestModuleException(IngestModule(), "Oh No!")
|
# raise IngestModuleException(IngestModule(), "Oh No!")
|
||||||
pass
|
pass
|
||||||
@ -171,7 +175,7 @@ class SampleFileIngestModuleWithUISettingsPanel(IngestModuleIngestJobSettingsPan
|
|||||||
# is present, it creates a read-only 'settings' property. This auto-
|
# is present, it creates a read-only 'settings' property. This auto-
|
||||||
# generated read-only property overshadows the instance-variable -
|
# generated read-only property overshadows the instance-variable -
|
||||||
# 'settings'
|
# 'settings'
|
||||||
|
|
||||||
# We get passed in a previous version of the settings so that we can
|
# We get passed in a previous version of the settings so that we can
|
||||||
# prepopulate the UI
|
# prepopulate the UI
|
||||||
# TODO: Update this for your UI
|
# TODO: Update this for your UI
|
||||||
@ -179,7 +183,7 @@ class SampleFileIngestModuleWithUISettingsPanel(IngestModuleIngestJobSettingsPan
|
|||||||
self.local_settings = settings
|
self.local_settings = settings
|
||||||
self.initComponents()
|
self.initComponents()
|
||||||
self.customizeComponents()
|
self.customizeComponents()
|
||||||
|
|
||||||
# TODO: Update this for your UI
|
# TODO: Update this for your UI
|
||||||
def checkBoxEvent(self, event):
|
def checkBoxEvent(self, event):
|
||||||
if self.checkbox.isSelected():
|
if self.checkbox.isSelected():
|
||||||
@ -201,4 +205,3 @@ class SampleFileIngestModuleWithUISettingsPanel(IngestModuleIngestJobSettingsPan
|
|||||||
def getSettings(self):
|
def getSettings(self):
|
||||||
return self.local_settings
|
return self.local_settings
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user