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))  | 
