diff options
Diffstat (limited to 'plugins/pyoida/plugin.c')
-rw-r--r-- | plugins/pyoida/plugin.c | 250 |
1 files changed, 244 insertions, 6 deletions
diff --git a/plugins/pyoida/plugin.c b/plugins/pyoida/plugin.c index 23934a9..e652949 100644 --- a/plugins/pyoida/plugin.c +++ b/plugins/pyoida/plugin.c @@ -46,6 +46,7 @@ struct _GPythonPlugin GPluginModule parent; /* Instance parente */ PyObject *module; /* Script Python chargé */ + PyObject *instance; /* Instance Python du greffon */ }; @@ -64,6 +65,12 @@ static void g_python_plugin_class_init(GPythonPluginClass *); /* Initialise l'instance d'un greffon Python. */ static void g_python_plugin_init(GPythonPlugin *); +/* Indique l'utilité pratique du greffon. */ +static PluginAction g_python_plugin_get_action(const GPythonPlugin *); + +/* Indentifie un format à associer à un contenu binaire. */ +static MatchingFormatAction g_python_plugin_is_matching(const GPythonPlugin *, char **, bin_t **, off_t *); + /* Exécute une action définie sur un binaire chargé. */ static bool g_python_plugin_execute(GPythonPlugin *, GOpenidaBinary *, PluginAction); @@ -94,7 +101,11 @@ static PyObject *pyoida_plugin_run(PyObject *, PyObject *); /* Définit les constantes pour les greffons en Python. */ static bool pyoida_plugin_define_constants(PyObject *); +/* Définit le comportement par défaut d'un greffon Python. */ +static PyObject *pyoida_plugin_get_action(PyObject *, PyObject *); +/* Définit l'issue de la recherche d'un format par défaut. */ +static PyObject *pyoida_plugin_is_matching(PyObject *, PyObject *); @@ -260,7 +271,8 @@ PyObject *run_python_method(PyObject *module, const char *method, PyObject *args /****************************************************************************** * * -* Paramètres : filename = chemin d'accès au code Python à charger. * +* Paramètres : modname = nom du module à charger. * +* filename = chemin d'accès au code Python à charger. * * * * Description : Crée un greffon à partir de code Python. * * * @@ -270,18 +282,20 @@ PyObject *run_python_method(PyObject *module, const char *method, PyObject *args * * ******************************************************************************/ -GPluginModule *g_python_plugin_new(const char *filename) +GPluginModule *g_python_plugin_new(const char *modname, const char *filename) { GPythonPlugin *result; /* Structure à retourner */ PyObject *name; /* Chemin d'accès pour Python */ PyObject *module; /* Script Python chargé */ + PyObject *dict; /* Dictionnaire associé */ + PyObject *class; /* Classe à instancier */ + PyObject *instance; /* Instance Python du greffon */ #if PY_VERSION_HEX >= 0x03000000 name = PyUnicode_FromString(filename); #else name = PyString_FromString(filename); #endif - name = PyString_FromString/*PyUnicode_FromString*/(filename); if (name == NULL) goto gppn_bad_exit; module = PyImport_Import(name); @@ -293,20 +307,37 @@ GPluginModule *g_python_plugin_new(const char *filename) goto gppn_bad_exit; } + dict = PyModule_GetDict(module); + class = PyDict_GetItemString(dict, modname); + Py_DECREF(dict); + if (class == NULL) goto gppn_no_class; + if (!PyType_Check(class->ob_type)) goto gppn_no_class; - //Py_DECREF(module); - + instance = PyObject_CallFunction(class, NULL); + if (instance == NULL) goto gppn_no_instance; + Py_DECREF(class); result = g_object_new(G_TYPE_PYTHON_PLUGIN, NULL); - G_PLUGIN_MODULE(result)->action = PGA_CODE_PROCESS; + G_PLUGIN_MODULE(result)->get_action = g_python_plugin_get_action; + + G_PLUGIN_MODULE(result)->is_matching = g_python_plugin_is_matching; result->module = module; + result->instance = instance; return G_PLUGIN_MODULE(result); + gppn_no_instance: + + Py_DECREF(class); + + gppn_no_class: + + Py_DECREF(module); + gppn_bad_exit: return NULL; @@ -317,6 +348,138 @@ GPluginModule *g_python_plugin_new(const char *filename) /****************************************************************************** * * * Paramètres : plugin = greffon de prise en charge à utiliser. * +* * +* Description : Indique l'utilité pratique du greffon. * +* * +* Retour : Action(s) codifiée(s), PGA_NONE par défaut. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PluginAction g_python_plugin_get_action(const GPythonPlugin *plugin) +{ + PluginAction result; /* Valeur à retourner */ + PyObject *value; /* Valeur obtenue */ + + value = run_python_method(plugin->instance, "get_action", NULL); + + result = PyLong_AsLong(value); + Py_DECREF(value); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : plugin = greffon de prise en charge à utiliser. * +* filename = éventuel nom de fichier associé ou NULL. [OUT] * +* data = données chargées. [OUT] * +* length = quantité de ces données. [OUT] * +* * +* Description : Indentifie un format à associer à un contenu binaire. * +* * +* Retour : Bilan de la recherche de correspondances. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static MatchingFormatAction g_python_plugin_is_matching(const GPythonPlugin *plugin, char **filename, bin_t **data, off_t *length) +{ + MatchingFormatAction result; /* Valeur à retourner */ + PyObject *args; /* Arguments pour l'appel */ + PyObject *value; /* Valeurs obtenues */ + PyObject *action; /* Action à faire suivre */ + PyObject *new_filename; /* Nouveau fichier */ + PyObject *new_data; /* Nouvelles données */ + char *tmp; /* Stockage avant recopie */ + + if (*filename == NULL) + return MFA_NONE; + + args = PyTuple_New(2); + + PyTuple_SetItem(args, 0, PyString_FromString(*filename)); + PyTuple_SetItem(args, 1, PyByteArray_FromStringAndSize(*data, *length)); + + value = run_python_method(plugin->instance, "is_matching", args); + + if (value != NULL && PyTuple_Check(value) && PyTuple_Size(value) == 3) + { + action = PyTuple_GetItem(value, 0); + new_filename = PyTuple_GetItem(value, 1); + new_data = PyTuple_GetItem(value, 2); + + if (action == NULL || new_filename == NULL || new_data == NULL) + goto is_matching_bad; + + if (!PyInt_Check(action) + || (new_filename != Py_None && !PyString_Check(new_filename)) + || (new_data != Py_None && !PyByteArray_Check(new_data))) + goto is_matching_bad; + + result = PyInt_AsLong(action); + if (result >= MFA_COUNT) goto is_matching_bad; + + if (result != MFA_NONE && new_data == Py_None) goto is_matching_bad; + + if (new_filename != Py_None) + *filename = strdup(PyString_AsString(new_filename)); + /** + * La suppression de la part du greffon n'est permise que + * si une prise en charge est assurée. + */ + else if (result != MFA_NONE) + *filename = NULL; + + /** + * Pareil que précédemment. + */ + if (new_data != Py_None) + { + tmp = PyByteArray_AsString(new_data); + *length = PyByteArray_Size(new_data); + + *data = (bin_t *)calloc(*length, sizeof(bin_t)); + memcpy(*data, tmp, *length * sizeof(bin_t)); + + } + + goto is_matching_ok; + + } + + is_matching_bad: + + printf("<LOG>Bad result from is_matching() plugin function.\n"); + + result = MFA_NONE; + + is_matching_ok: + + Py_XDECREF(value); + Py_DECREF(args); + + return result; + +} + + + + + + + + + + + +/****************************************************************************** +* * +* Paramètres : plugin = greffon de prise en charge à utiliser. * * binary = représentation binaire à traiter. * * action = action attendue. * * * @@ -421,12 +584,29 @@ static bool pyoida_plugin_define_constants(PyObject *dict) { int ret; /* Bilan d'un ajout */ + ret = PyDict_SetItemString(dict, "PGA_NONE", PyInt_FromLong(PGA_NONE)); + if (ret == -1) return false; + + ret = PyDict_SetItemString(dict, "PGA_FORMAT_MATCHER", PyInt_FromLong(PGA_FORMAT_MATCHER)); + if (ret == -1) return false; + ret = PyDict_SetItemString(dict, "PGA_DISASSEMBLE", PyInt_FromLong(PGA_DISASSEMBLE)); if (ret == -1) return false; ret = PyDict_SetItemString(dict, "PGA_CODE_PROCESS", PyInt_FromLong(PGA_CODE_PROCESS)); if (ret == -1) return false; + /* PGA_FORMAT_MATCHER */ + + ret = PyDict_SetItemString(dict, "MFA_NONE", PyInt_FromLong(MFA_NONE)); + if (ret == -1) return false; + + ret = PyDict_SetItemString(dict, "MFA_MATCHED", PyInt_FromLong(MFA_MATCHED)); + if (ret == -1) return false; + + ret = PyDict_SetItemString(dict, "MFA_RELOAD", PyInt_FromLong(MFA_RELOAD)); + if (ret == -1) return false; + return true; } @@ -437,6 +617,58 @@ static bool pyoida_plugin_define_constants(PyObject *dict) * Paramètres : self = classe assurant le lien avec l'éditeur de messages. * * args = arguments fournis à l'appel. * * * +* Description : Définit le comportement par défaut d'un greffon Python. * +* * +* Retour : Rien en équivalent Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *pyoida_plugin_get_action(PyObject *self, PyObject *args) +{ + return PyInt_FromLong(PGA_NONE); + +} + + +/****************************************************************************** +* * +* Paramètres : self = classe assurant le lien avec l'éditeur de messages. * +* args = arguments fournis à l'appel. * +* * +* Description : Définit l'issue de la recherche d'un format par défaut. * +* * +* Retour : Rien en équivalent Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *pyoida_plugin_is_matching(PyObject *self, PyObject *args) +{ + PyObject *result; /* Liste à retourner */ + + result = PyTuple_New(3); + + PyTuple_SetItem(result, 0, PyInt_FromLong(MFA_NONE)); + PyTuple_SetItem(result, 1, Py_None); + PyTuple_SetItem(result, 2, Py_None); + + return result; + +} + + + + + + +/****************************************************************************** +* * +* Paramètres : self = classe assurant le lien avec l'éditeur de messages. * +* args = arguments fournis à l'appel. * +* * * Description : Exécute une action valide pour le greffon Python. * * * * Retour : Rien en équivalent Python. * @@ -474,6 +706,12 @@ bool add_plugin_to_python_module(PyObject *module) static PyMethodDef pyoida_plugin_methods[] = { + { "get_action", (PyCFunction)pyoida_plugin_get_action, METH_NOARGS, + "Register the plugin for given actions." + }, + { "is_matching", (PyCFunction)pyoida_plugin_is_matching, METH_VARARGS, + "Define if the given file can be handled." + }, { "run", (PyCFunction)pyoida_plugin_run, METH_VARARGS, "Run the plugin for a specific action." }, |