diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2020-05-19 22:38:17 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2020-05-19 22:38:17 (GMT) |
commit | 5d09d85a5e606e5ac458abd37e72b73ce52541cb (patch) | |
tree | 9e9bd0581cc433fc7d8392a137b5a83dc46a9098 /plugins/pychrysalide/format | |
parent | 93b452d5258aa07d24ec233f2de930343be1d974 (diff) |
Improved the use of the known format object.
Diffstat (limited to 'plugins/pychrysalide/format')
-rw-r--r-- | plugins/pychrysalide/format/known.c | 427 |
1 files changed, 399 insertions, 28 deletions
diff --git a/plugins/pychrysalide/format/known.c b/plugins/pychrysalide/format/known.c index e19a4a2..c3b5b9d 100644 --- a/plugins/pychrysalide/format/known.c +++ b/plugins/pychrysalide/format/known.c @@ -28,19 +28,48 @@ #include <pygobject.h> -#include <format/known.h> +#include <i18n.h> +#include <format/known-int.h> +#include <plugins/dt.h> #include "../access.h" #include "../helpers.h" +#include "../analysis/content.h" +/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */ + + +/* Accompagne la création d'une instance dérivée en Python. */ +static PyObject *py_known_format_new(PyTypeObject *, PyObject *, PyObject *); + +/* Initialise la classe des descriptions de fichier binaire. */ +static void py_known_format_init_gclass(GKnownFormatClass *, gpointer); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_known_format_init(PyObject *, PyObject *, PyObject *); + +/* Indique la désignation interne du format. */ +static char *py_known_format_get_key_wrapper(const GKnownFormat *); + +/* Fournit une description humaine du format. */ +static char *py_known_format_get_description_wrapper(const GKnownFormat *); + +/* Assure l'interprétation d'un format en différé. */ +static bool py_known_format_analyze_wrapper(GKnownFormat *, wgroup_id_t, GtkStatusStack *); + + + +/* --------------------------- DEFINITION DU FORMAT CONNU --------------------------- */ + + /* Assure l'interprétation d'un format en différé. */ static PyObject *py_known_format_analyze(PyObject *, PyObject *); /* Indique la désignation interne du format. */ -static PyObject *py_known_format_get_name(PyObject *, void *); +static PyObject *py_known_format_get_key(PyObject *, void *); /* Indique la désignation humaine du format. */ static PyObject *py_known_format_get_description(PyObject *, void *); @@ -50,9 +79,332 @@ static PyObject *py_known_format_get_content(PyObject *, void *); -#define KNOWN_FORMAT_DOC \ - "KnownFormat is a small class providing basic features for recognized formats." +/* ---------------------------------------------------------------------------------- */ +/* GLUE POUR CREATION DEPUIS PYTHON */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : type = type du nouvel objet à mettre en place. * +* args = éventuelle liste d'arguments. * +* kwds = éventuel dictionnaire de valeurs mises à disposition. * +* * +* Description : Accompagne la création d'une instance dérivée en Python. * +* * +* Retour : Nouvel objet Python mis en place ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_known_format_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyObject *result; /* Objet à retourner */ + PyTypeObject *base; /* Type de base à dériver */ + bool first_time; /* Evite les multiples passages*/ + GType gtype; /* Nouveau type de processeur */ + bool status; /* Bilan d'un enregistrement */ + + /* Validations diverses */ + + base = get_python_known_format_type(); + + if (type == base) + { + result = NULL; + PyErr_Format(PyExc_RuntimeError, _("%s is an abstract class"), type->tp_name); + goto exit; + } + + /* Mise en place d'un type dédié */ + + first_time = (g_type_from_name(type->tp_name) == 0); + + gtype = build_dynamic_type(G_TYPE_KNOWN_FORMAT, type->tp_name, + (GClassInitFunc)py_known_format_init_gclass, NULL, NULL); + + if (first_time) + { + status = register_class_for_dynamic_pygobject(gtype, type, base); + + if (!status) + { + result = NULL; + goto exit; + } + + } + + /* On crée, et on laisse ensuite la main à PyGObject_Type.tp_init() */ + + result = PyType_GenericNew(type, args, kwds); + + exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : class = classe à initialiser. * +* unused = données non utilisées ici. * +* * +* Description : Initialise la classe générique des processeurs. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void py_known_format_init_gclass(GKnownFormatClass *class, gpointer unused) +{ + class->get_key = py_known_format_get_key_wrapper; + class->get_desc = py_known_format_get_description_wrapper; + + class->analyze = py_known_format_analyze_wrapper; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet à initialiser (théoriquement). * +* args = arguments fournis à l'appel. * +* kwds = arguments de type key=val fournis. * +* * +* Description : Initialise une instance sur la base du dérivé de GObject. * +* * +* Retour : 0. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int py_known_format_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + GBinContent *content; /* Contenu à intégrer au format*/ + int ret; /* Bilan de lecture des args. */ + GKnownFormat *format; /* Format à manipuler */ + +#define KNOWN_FORMAT_DOC \ + "KnownFormat is a small class providing basic features for" \ + " recognized formats.\n" \ + "\n" \ + "One item has to be defined as class attribute in the final" \ + " class:\n" \ + "* *_key*: a string providing a small name used to identify the" \ + " format.\n" \ + "\n" \ + "The following methods have to be defined for new classes:\n" \ + "* pychrysalide.format.KnownFormat._get_description();\n" \ + "* pychrysalide.format.KnownFormat._analyze().\n" \ + "\n" \ + "Calls to the *__init__* constructor of this abstract object expect"\ + " only one argument: a binary content, provided as a" \ + " pychrysalide.analysis.BinContent instance." + + /* Récupération des paramètres */ + + ret = PyArg_ParseTuple(args, "O&", convert_to_binary_content, &content); + if (!ret) return -1; + + /* Initialisation d'un objet GLib */ + + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; + + /* Eléments de base */ + + format = G_KNOWN_FORMAT(pygobject_get(self)); + + g_known_format_set_content(format, content); + + return 0; + +} + + +/****************************************************************************** +* * +* Paramètres : format = description du format connu à consulter. * +* * +* Description : Indique la désignation interne du format. * +* * +* Retour : Désignation du format. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *py_known_format_get_key_wrapper(const GKnownFormat *format) +{ + char *result; /* Désignation à renvoyer */ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ + PyObject *pyobj; /* Objet Python concerné */ + PyObject *pykey; /* Clef en objet Python */ + int ret; /* Bilan d'une conversion */ + + result = NULL; + + gstate = PyGILState_Ensure(); + + pyobj = pygobject_new(G_OBJECT(format)); + + if (PyObject_HasAttrString(pyobj, "_key")) + { + pykey = PyObject_GetAttrString(pyobj, "_key"); + + if (pykey != NULL) + { + ret = PyUnicode_Check(pykey); + + if (ret) + result = strdup(PyUnicode_AsUTF8(pykey)); + + Py_DECREF(pykey); + + } + + } + + PyGILState_Release(gstate); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = description du format connu à consulter. * +* * +* Description : Fournit une description humaine du format. * +* * +* Retour : Description du format. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *py_known_format_get_description_wrapper(const GKnownFormat *format) +{ + char *result; /* Description à retourner */ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ + PyObject *pyobj; /* Objet Python concerné */ + PyObject *pyret; /* Bilan de consultation */ + int ret; /* Bilan d'une conversion */ + +#define KNOWN_FORMAT_GET_DESCRIPTION_WRAPPER PYTHON_WRAPPER_DEF \ +( \ + _get_description, "$self, /", \ + METH_NOARGS, \ + "Abstract method used to build a description of the format.\n" \ + "\n" \ + "The result is expected to be a string." \ +) + + gstate = PyGILState_Ensure(); + + pyobj = pygobject_new(G_OBJECT(format)); + + if (has_python_method(pyobj, "_get_description")) + { + pyret = run_python_method(pyobj, "_get_description", NULL); + + if (pyret != NULL) + { + ret = PyUnicode_Check(pyret); + + if (ret) + result = strdup(PyUnicode_AsUTF8(pyret)); + + Py_DECREF(pyret); + + } + + } + + PyGILState_Release(gstate); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = format chargé dont l'analyse est lancée. * +* gid = groupe de travail dédié. * +* status = barre de statut à tenir informée. * +* * +* Description : Assure l'interprétation d'un format en différé. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool py_known_format_analyze_wrapper(GKnownFormat *format, wgroup_id_t gid, GtkStatusStack *status) +{ + bool result; /* Bilan à retourner */ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ + PyObject *pyobj; /* Objet Python concerné */ + PyObject *args; /* Arguments pour l'appel */ + PyObject *pyret; /* Bilan d'exécution */ + +#define KNOWN_FORMAT_ANALYZE_WRAPPER PYTHON_WRAPPER_DEF \ +( \ + _analyze, "$self, gid, status, /", \ + METH_VARARGS, \ + "Abstract method used to start the analysis of the known" \ + " format and return its status.\n" \ + "\n" \ + "The identifier refers to the working queue used to process" \ + " the analysis. A reference to the main status bar may also be" \ + " provided, as a pychrysalide.gtkext.StatusStack instance if" \ + " running in graphical mode or None otherwise.\n" \ + "\n" \ + "The expected result of the call is a boolean." \ +) + + result = false; + + gstate = PyGILState_Ensure(); + pyobj = pygobject_new(G_OBJECT(format)); + + if (has_python_method(pyobj, "_analyze")) + { + args = PyTuple_New(2); + + PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(gid)); + PyTuple_SetItem(args, 1, pygobject_new(G_OBJECT(status))); + + pyret = run_python_method(pyobj, "_analyze", args); + + result = (pyret == Py_True); + + Py_DECREF(args); + Py_XDECREF(pyret); + + } + + PyGILState_Release(gstate); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* DEFINITION DU FORMAT CONNU */ +/* ---------------------------------------------------------------------------------- */ /****************************************************************************** @@ -75,11 +427,21 @@ static PyObject *py_known_format_analyze(PyObject *self, PyObject *args) GKnownFormat *format; /* Format connu manipulé */ bool status; /* Bilan de l'opération */ -#define KNOWN_FORMAT_ANALYZE_METHOD PYTHON_METHOD_DEF \ -( \ - analyze, "$self, /, gid, status", \ - METH_VARARGS, py_known_format, \ - "Start the analysis of the known format and return its status." \ +#define KNOWN_FORMAT_ANALYZE_METHOD PYTHON_METHOD_DEF \ +( \ + analyze, "$self, gid, status, /", \ + METH_VARARGS, py_known_format, \ + "Start the analysis of the known format and return its status." \ + "\n" \ + "Once this analysis is done, a few early symbols and the" \ + " mapped sections are expected to be defined, if any.\n" \ + "\n" \ + "The identifier refers to the working queue used to process" \ + " the analysis. A reference to the main status bar may also be" \ + " provided, as a pychrysalide.gtkext.StatusStack instance if" \ + " running in graphical mode or None otherwise.\n" \ + "\n" \ + "The return value is a boolean status of the operation." \ ) ret = PyArg_ParseTuple(args, "");//|KO!", &gid, &status); @@ -104,29 +466,31 @@ static PyObject *py_known_format_analyze(PyObject *self, PyObject *args) * * * Description : Indique la désignation interne du format. * * * -* Retour : Description du format. * +* Retour : Désignation du format. * * * * Remarques : - * * * ******************************************************************************/ -static PyObject *py_known_format_get_name(PyObject *self, void *closure) +static PyObject *py_known_format_get_key(PyObject *self, void *closure) { PyObject *result; /* Trouvailles à retourner */ GKnownFormat *format; /* Format de binaire manipulé */ - const char *name; /* Description interne */ + char *key; /* Désignation interne */ -#define KNOWN_FORMAT_NAME_ATTRIB PYTHON_GET_DEF_FULL \ -( \ - name, py_known_format, \ - "Internal name of the known format." \ +#define KNOWN_FORMAT_KEY_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + key, py_known_format, \ + "Internal name of the known format, provided as a (tiny) string." \ ) format = G_KNOWN_FORMAT(pygobject_get(self)); - name = g_known_format_get_name(format); + key = g_known_format_get_key(format); + + result = PyUnicode_FromString(key); - result = PyUnicode_FromString(name); + free(key); return result; @@ -150,12 +514,12 @@ static PyObject *py_known_format_get_description(PyObject *self, void *closure) { PyObject *result; /* Trouvailles à retourner */ GKnownFormat *format; /* Format de binaire manipulé */ - const char *desc; /* Description humaine */ + char *desc; /* Description humaine */ #define KNOWN_FORMAT_DESCRIPTION_ATTRIB PYTHON_GET_DEF_FULL \ ( \ description, py_known_format, \ - "Human description of the known format." \ + "Human description of the known format, as a string." \ ) format = G_KNOWN_FORMAT(pygobject_get(self)); @@ -164,6 +528,8 @@ static PyObject *py_known_format_get_description(PyObject *self, void *closure) result = PyUnicode_FromString(desc); + free(desc); + return result; } @@ -188,10 +554,12 @@ static PyObject *py_known_format_get_content(PyObject *self, void *closure) GKnownFormat *format; /* Format de binaire manipulé */ GBinContent *content; /* Instance GLib correspondante*/ -#define KNOWN_FORMAT_CONTENT_ATTRIB PYTHON_GET_DEF_FULL \ -( \ - content, py_known_format, \ - "Binary content linked to the known format." \ +#define KNOWN_FORMAT_CONTENT_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + content, py_known_format, \ + "Binary content linked to the known format." \ + "\n" \ + "The result is a pychrysalide.analysis.BinContent instance." \ ) format = G_KNOWN_FORMAT(pygobject_get(self)); @@ -222,12 +590,14 @@ static PyObject *py_known_format_get_content(PyObject *self, void *closure) PyTypeObject *get_python_known_format_type(void) { static PyMethodDef py_known_format_methods[] = { + KNOWN_FORMAT_GET_DESCRIPTION_WRAPPER, + KNOWN_FORMAT_ANALYZE_WRAPPER, KNOWN_FORMAT_ANALYZE_METHOD, { NULL } }; static PyGetSetDef py_known_format_getseters[] = { - KNOWN_FORMAT_NAME_ATTRIB, + KNOWN_FORMAT_KEY_ATTRIB, KNOWN_FORMAT_DESCRIPTION_ATTRIB, KNOWN_FORMAT_CONTENT_ATTRIB, { NULL } @@ -245,7 +615,10 @@ PyTypeObject *get_python_known_format_type(void) .tp_doc = KNOWN_FORMAT_DOC, .tp_methods = py_known_format_methods, - .tp_getset = py_known_format_getseters + .tp_getset = py_known_format_getseters, + + .tp_init = py_known_format_init, + .tp_new = py_known_format_new, }; @@ -278,8 +651,6 @@ bool ensure_python_known_format_is_registered(void) { module = get_access_to_python_module("pychrysalide.format"); - APPLY_ABSTRACT_FLAG(type); - dict = PyModule_GetDict(module); if (!register_class_for_pygobject(dict, G_TYPE_KNOWN_FORMAT, type, &PyGObject_Type)) |