diff options
Diffstat (limited to 'plugins/pychrysalide/glibext')
19 files changed, 2470 insertions, 451 deletions
diff --git a/plugins/pychrysalide/glibext/Makefile.am b/plugins/pychrysalide/glibext/Makefile.am index af1d9f2..6d3d746 100644 --- a/plugins/pychrysalide/glibext/Makefile.am +++ b/plugins/pychrysalide/glibext/Makefile.am @@ -1,14 +1,11 @@ -noinst_LTLIBRARIES = libpychrysaglibext.la +noinst_LTLIBRARIES = libpychrysaglibext.la libpychrysaglibextui.la # libpychrysaglibext_la_SOURCES = \ # binarycursor.h binarycursor.c \ # buffercache.h buffercache.c \ -# bufferline.h bufferline.c \ # configuration.h configuration.c \ -# linecursor.h linecursor.c \ -# linegen.h linegen.c \ -# module.h module.c +# linecursor.h linecursor.c # if BUILD_GTK_SUPPORT @@ -27,7 +24,9 @@ libpychrysaglibext_la_SOURCES = \ objhole.h objhole.c \ portion.h portion.c \ secstorage.h secstorage.c \ + serialize.h serialize.c \ singleton.h singleton.c \ + storage.h storage.c \ strbuilder.h strbuilder.c \ work.h work.c \ workqueue.h workqueue.c @@ -36,6 +35,16 @@ libpychrysaglibext_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT +libpychrysaglibextui_la_SOURCES = \ + bufferline.h bufferline.c \ + constants-ui.h constants-ui.c \ + generator.h generator.c \ + module-ui.h module-ui.c + +libpychrysaglibextui_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBPYTHON_INTERPRETER_CFLAGS) $(LIBPYGOBJECT_CFLAGS) \ + -I$(top_srcdir)/src -DNO_IMPORT_PYGOBJECT + + devdir = $(includedir)/chrysalide/$(subdir) -dev_HEADERS = $(libpychrysaglibext_la_SOURCES:%c=) +dev_HEADERS = $(libpychrysaglibext_la_SOURCES:%c=) $(libpychrysaglibextui_la_SOURCES:%c=) diff --git a/plugins/pychrysalide/glibext/bufferline.c b/plugins/pychrysalide/glibext/bufferline.c index 09404bc..c5b3664 100644 --- a/plugins/pychrysalide/glibext/bufferline.c +++ b/plugins/pychrysalide/glibext/bufferline.c @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * bufferline.c - équivalent Python du fichier "glibext/bufferline.h" * - * Copyright (C) 2018-2019 Cyrille Bagard + * Copyright (C) 2018-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -26,25 +26,38 @@ #include <assert.h> -#include <malloc.h> +//#include <malloc.h> #include <pygobject.h> -#include <i18n.h> -#include <glibext/bufferline.h> -#include <plugins/dt.h> +#include <glibext/bufferline-int.h> -#include "constants.h" +//#include "constants.h" #include "../access.h" #include "../helpers.h" -#include "../arch/vmpa.h" +//#include "../arch/vmpa.h" +/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */ + + +CREATE_DYN_CONSTRUCTOR(buffer_line, G_TYPE_BUFFER_LINE); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_buffer_line_init(PyObject *, PyObject *, PyObject *); + + + +/* ------------------ LIAISON DE FONCTIONNALITES AVEC L'API PYTHON ------------------ */ + + /* Accompagne la création d'une instance dérivée en Python. */ static PyObject *py_buffer_line_new(PyTypeObject *, PyObject *, PyObject *); +#if 0 + /* Ajoute du texte à formater dans une ligne donnée. */ static PyObject *py_buffer_line_append_text(PyObject *, PyObject *); @@ -54,29 +67,34 @@ static PyObject *py_buffer_line_get_text(PyObject *, PyObject *); /* Renseigne sur les propriétés particulières liées à une ligne. */ static PyObject *py_buffer_line_get_flags(PyObject *, void *); +#endif + + + +/* ---------------------------------------------------------------------------------- */ +/* 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. * +* Paramètres : self = objet à initialiser (théoriquement). * +* args = arguments fournis à l'appel. * +* kwds = arguments de type key=val fournis. * * * -* Description : Accompagne la création d'une instance dérivée en Python. * +* Description : Initialise une instance sur la base du dérivé de GObject. * * * -* Retour : Nouvel objet Python mis en place ou NULL en cas d'échec. * +* Retour : 0. * * * * Remarques : - * * * ******************************************************************************/ -static PyObject *py_buffer_line_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static int py_buffer_line_init(PyObject *self, 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 */ + unsigned char col_count; /* Qté de colonnes attendues */ + int ret; /* Bilan de lecture des args. */ + GBufferLine *line; /* Ligne en version native */ #define BUFFER_LINE_DOC \ "The BufferLine object is used to display processed data: disassembled" \ @@ -84,51 +102,40 @@ static PyObject *py_buffer_line_new(PyTypeObject *type, PyObject *args, PyObject "\n" \ "Instances can be created using the following constructor:\n" \ "\n" \ - " BufferLine()" \ + " BufferLine(col_count)" \ + "\n" \ + " Where *col_count* is a integer value providing the expected number of"\ + " rendering columns." \ "\n" \ "Such objets aim to be created from the Chrysalide core only, and" \ " then get populated on demand. Thus, these lines can be viewed as" \ " cached lines and their properties have to be set through the" \ " pychrysalide.glibext.BufferCache instance which contains them." - /* Validations diverses */ - - base = get_python_buffer_line_type(); + /* Récupération des paramètres */ - if (type == base) - goto simple_way; + ret = PyArg_ParseTuple(args, "B", &col_count); + if (!ret) return -1; - /* Mise en place d'un type dédié */ + /* Initialisation d'un objet GLib */ - first_time = (g_type_from_name(type->tp_name) == 0); + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; - gtype = build_dynamic_type(G_TYPE_BUFFER_LINE, type->tp_name, NULL, NULL, NULL); - - if (first_time) - { - status = register_class_for_dynamic_pygobject(gtype, type); + /* Eléments de base */ - if (!status) - { - result = NULL; - goto exit; - } - - } - - /* On crée, et on laisse ensuite la main à PyGObject_Type.tp_init() */ - - simple_way: - - result = PyType_GenericNew(type, args, kwds); + line = G_BUFFER_LINE(pygobject_get(self)); - exit: + if (!g_buffer_line_create(line, col_count)) + return -1; - return result; + return 0; } +#if 0 + /****************************************************************************** * * * Paramètres : self = classe représentant une ligne de tampon. * @@ -256,6 +263,7 @@ static PyObject *py_buffer_line_get_flags(PyObject *self, void *closure) return result; } +#endif /****************************************************************************** @@ -273,20 +281,24 @@ static PyObject *py_buffer_line_get_flags(PyObject *self, void *closure) PyTypeObject *get_python_buffer_line_type(void) { static PyMethodDef py_buffer_line_methods[] = { + /* BUFFER_LINE_APPEND_TEXT_METHOD, { "get_text", py_buffer_line_get_text, METH_VARARGS, "get_text($self, first_col, last_col, markup, /)\n--\n\nProvide the text of a buffer line." }, + */ { NULL } }; static PyGetSetDef py_buffer_line_getseters[] = { + /* { "flags", py_buffer_line_get_flags, NULL, "Current flags of the buffer line.", NULL }, + */ { NULL } }; @@ -304,7 +316,8 @@ PyTypeObject *get_python_buffer_line_type(void) .tp_methods = py_buffer_line_methods, .tp_getset = py_buffer_line_getseters, - .tp_new = py_buffer_line_new + .tp_init = py_buffer_line_init, + .tp_new = py_buffer_line_new, }; @@ -342,11 +355,13 @@ bool ensure_python_buffer_line_is_registered(void) if (!register_class_for_pygobject(dict, G_TYPE_BUFFER_LINE, type)) return false; + /* if (!define_line_segment_constants(type)) return false; if (!define_buffer_line_constants(type)) return false; + */ } diff --git a/plugins/pychrysalide/glibext/constants-ui.c b/plugins/pychrysalide/glibext/constants-ui.c new file mode 100644 index 0000000..4101600 --- /dev/null +++ b/plugins/pychrysalide/glibext/constants-ui.c @@ -0,0 +1,131 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * constants-ui.c - ajout des constantes pour les extensions graphique à la GLib + * + * Copyright (C) 2025 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "constants-ui.h" + + +#include <glibext/bufferline.h> + + +#include "../helpers.h" + + + +/****************************************************************************** +* * +* Paramètres : type = type dont le dictionnaire est à compléter. * +* * +* Description : Définit les constantes relatives aux lignes de tampon. * +* * +* Retour : true en cas de succès de l'opération, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool define_buffer_line_constants(PyTypeObject *type) +{ + bool result; /* Bilan à retourner */ + PyObject *values; /* Groupe de valeurs à établir */ + + values = PyDict_New(); + + result = add_const_to_group(values, "NONE", BLF_NONE); + if (result) result = add_const_to_group(values, "HAS_CODE", BLF_HAS_CODE); + if (result) result = add_const_to_group(values, "IS_LABEL", BLF_IS_LABEL); + if (result) result = add_const_to_group(values, "ENTRYPOINT", BLF_ENTRYPOINT); + if (result) result = add_const_to_group(values, "BOOKMARK", BLF_BOOKMARK); + if (result) result = add_const_to_group(values, "WIDTH_MANAGER", BLF_WIDTH_MANAGER); + if (result) result = add_const_to_group(values, "ALL", BLF_ALL); + + if (!result) + { + Py_DECREF(values); + goto exit; + } + + result = attach_constants_group_to_type(type, true, "BufferLineFlags", values, + "Optional flags linked to a rendering line."); + + exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : arg = argument quelconque à tenter de convertir. * +* dst = destination des valeurs récupérées en cas de succès. * +* * +* Description : Tente de convertir en constante BufferLineFlags. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_buffer_line_flags(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + unsigned long value; /* Valeur transcrite */ + + result = PyObject_IsInstance(arg, (PyObject *)&PyLong_Type); + + switch (result) + { + case -1: + /* L'exception est déjà fixée par Python */ + result = 0; + break; + + case 0: + PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to BufferLineFlags"); + break; + + case 1: + value = PyLong_AsUnsignedLong(arg); + + if ((value & BLF_ALL) != value) + { + PyErr_SetString(PyExc_TypeError, "invalid value for BufferLineFlags"); + result = 0; + } + + else + *((BufferLineFlags *)dst) = value; + + break; + + default: + assert(false); + break; + + } + + return result; + +} diff --git a/plugins/pychrysalide/glibext/constants-ui.h b/plugins/pychrysalide/glibext/constants-ui.h new file mode 100644 index 0000000..6c7bc6e --- /dev/null +++ b/plugins/pychrysalide/glibext/constants-ui.h @@ -0,0 +1,41 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * constants-ui.h - prototypes pour l'ajout des constantes pour les extensions graphique à la GLib + * + * Copyright (C) 2025 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_PYCHRYSALIDE_GLIBEXT_CONSTANTS_UI_H +#define _PLUGINS_PYCHRYSALIDE_GLIBEXT_CONSTANTS_UI_H + + +#include <Python.h> +#include <stdbool.h> + + +/* Définit les constantes relatives aux lignes de tampon. */ +bool define_buffer_line_constants(PyTypeObject *); + +/* Tente de convertir en constante BufferLineFlags. */ +int convert_to_buffer_line_flags(PyObject *, void *); + + + +#endif /* _PLUGINS_PYCHRYSALIDE_GLIBEXT_CONSTANTS_UI_H */ diff --git a/plugins/pychrysalide/glibext/constants.c b/plugins/pychrysalide/glibext/constants.c index 90ce8cd..f733cf6 100644 --- a/plugins/pychrysalide/glibext/constants.c +++ b/plugins/pychrysalide/glibext/constants.c @@ -29,7 +29,6 @@ /* #include <i18n.h> -#include <glibext/bufferline.h> #include <glibext/comparison.h> #include <glibext/configuration.h> #include <glibext/linesegment.h> @@ -159,105 +158,6 @@ int convert_to_portion_access_rights(PyObject *arg, void *dst) * * * Paramètres : type = type dont le dictionnaire est à compléter. * * * -* Description : Définit les constantes relatives aux lignes de tampon. * -* * -* Retour : true en cas de succès de l'opération, false sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool define_buffer_line_constants(PyTypeObject *type) -{ - bool result; /* Bilan à retourner */ - PyObject *values; /* Groupe de valeurs à établir */ - - values = PyDict_New(); - - result = add_const_to_group(values, "NONE", BLF_NONE); - if (result) result = add_const_to_group(values, "HAS_CODE", BLF_HAS_CODE); - if (result) result = add_const_to_group(values, "IS_LABEL", BLF_IS_LABEL); - if (result) result = add_const_to_group(values, "ENTRYPOINT", BLF_ENTRYPOINT); - if (result) result = add_const_to_group(values, "BOOKMARK", BLF_BOOKMARK); - if (result) result = add_const_to_group(values, "WIDTH_MANAGER", BLF_WIDTH_MANAGER); - if (result) result = add_const_to_group(values, "ALL", BLF_ALL); - - if (!result) - { - Py_DECREF(values); - goto exit; - } - - result = attach_constants_group_to_type(type, true, "BufferLineFlags", values, - "Optional flags linked to a rendering line."); - - exit: - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : arg = argument quelconque à tenter de convertir. * -* dst = destination des valeurs récupérées en cas de succès. * -* * -* Description : Tente de convertir en constante BufferLineFlags. * -* * -* Retour : Bilan de l'opération, voire indications supplémentaires. * -* * -* Remarques : - * -* * -******************************************************************************/ - -int convert_to_buffer_line_flags(PyObject *arg, void *dst) -{ - int result; /* Bilan à retourner */ - unsigned long value; /* Valeur transcrite */ - - result = PyObject_IsInstance(arg, (PyObject *)&PyLong_Type); - - switch (result) - { - case -1: - /* L'exception est déjà fixée par Python */ - result = 0; - break; - - case 0: - PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to BufferLineFlags"); - break; - - case 1: - value = PyLong_AsUnsignedLong(arg); - - if ((value & BLF_ALL) != value) - { - PyErr_SetString(PyExc_TypeError, "invalid value for BufferLineFlags"); - result = 0; - } - - else - *((BufferLineFlags *)dst) = value; - - break; - - default: - assert(false); - break; - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : type = type dont le dictionnaire est à compléter. * -* * * Description : Définit les constantes relatives aux modes de comparaison. * * * * Retour : true en cas de succès de l'opération, false sinon. * diff --git a/plugins/pychrysalide/glibext/constants.h b/plugins/pychrysalide/glibext/constants.h index a950125..c695aa9 100644 --- a/plugins/pychrysalide/glibext/constants.h +++ b/plugins/pychrysalide/glibext/constants.h @@ -39,12 +39,6 @@ int convert_to_portion_access_rights(PyObject *, void *); #if 0 -/* Définit les constantes relatives aux lignes de tampon. */ -bool define_buffer_line_constants(PyTypeObject *); - -/* Tente de convertir en constante BufferLineFlags. */ -int convert_to_buffer_line_flags(PyObject *, void *); - /* Définit les constantes relatives aux modes de comparaison. */ bool define_comparable_item_constants(PyTypeObject *); diff --git a/plugins/pychrysalide/glibext/linegen.c b/plugins/pychrysalide/glibext/generator.c index d7e96fd..3a9a8ab 100644 --- a/plugins/pychrysalide/glibext/linegen.c +++ b/plugins/pychrysalide/glibext/generator.c @@ -1,8 +1,8 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * linegen.c - équivalent Python du fichier "glibext/linegen.h" + * generator.c - équivalent Python du fichier "glibext/generator.h" * - * Copyright (C) 2018-2019 Cyrille Bagard + * Copyright (C) 2018-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -22,21 +22,21 @@ */ -#include "linegen.h" +#include "generator.h" #include <pygobject.h> -#include <glibext/linegen-int.h> +#include <glibext/generator-int.h> #include "bufferline.h" -#include "constants.h" -#include "linecursor.h" +#include "constants-ui.h" +//#include "linecursor.h" #include "../access.h" #include "../helpers.h" -#include "../analysis/content.h" +//#include "../analysis/content.h" @@ -44,42 +44,55 @@ /* Procède à l'initialisation de l'interface de génération. */ -static void py_line_generator_interface_init(GLineGeneratorIface *, gpointer *); +static void py_token_generator_interface_init(GTokenGeneratorInterface *, gpointer *); /* Indique le nombre de ligne prêtes à être générées. */ -static size_t py_line_generator_count_lines_wrapper(const GLineGenerator *); +static size_t py_token_generator_count_lines_wrapper(const GTokenGenerator *); + +/* Renseigne sur les propriétés liées à un générateur. */ +static BufferLineFlags py_token_generator_get_flags_wrapper(const GTokenGenerator *, size_t, size_t); + +/*Description : Etablit dans une ligne de rendu le contenu représenté. */ +static void py_token_generator_populate_line_wrappper(const GTokenGenerator *, size_t, size_t, GBufferLine *, void *); + + +#if 0 + /* Retrouve l'emplacement correspondant à une position donnée. */ -static void py_line_generator_compute_cursor_wrapper(const GLineGenerator *, gint, size_t, size_t, GLineCursor **); +static void py_token_generator_compute_cursor_wrapper(const GTokenGenerator *, gint, size_t, size_t, GLineCursor **); /* Détermine si le conteneur s'inscrit dans une plage donnée. */ -static int py_line_generator_contain_cursor_wrapper(const GLineGenerator *, size_t, size_t, const GLineCursor *); +static int py_token_generator_contain_cursor_wrapper(const GTokenGenerator *, size_t, size_t, const GLineCursor *); + + +#endif -/* Renseigne sur les propriétés liées à un générateur. */ -static BufferLineFlags py_line_generator_get_flags_wrapper(const GLineGenerator *, size_t, size_t); -/* Imprime dans une ligne de rendu le contenu représenté. */ -static void py_line_generator_print_wrapper(GLineGenerator *, GBufferLine *, size_t, size_t, const GBinContent *); +/* ------------------ LIAISON DE FONCTIONNALITES AVEC L'API PYTHON ------------------ */ -/* ------------------------- CONNEXION AVEC L'API DE PYTHON ------------------------- */ +/* Renseigne sur les propriétés liées à un générateur. */ +static PyObject *py_token_generator_get_flags(PyObject *, PyObject *); + +/* Etablit dans une ligne de rendu le contenu représenté. */ +static PyObject *py_token_generator_populate_line(PyObject *self, PyObject *args); + +#if 0 /* Retrouve l'emplacement correspondant à une position donnée. */ -static PyObject *py_line_generator_compute_cursor(PyObject *, PyObject *); +static PyObject *py_token_generator_compute_cursor(PyObject *, PyObject *); /* Détermine si le conteneur s'inscrit dans une plage donnée. */ -static PyObject *py_line_generator_contain_cursor(PyObject *, PyObject *); +static PyObject *py_token_generator_contain_cursor(PyObject *, PyObject *); -/* Renseigne sur les propriétés liées à un générateur. */ -static PyObject *py_line_generator_get_flags(PyObject *, PyObject *); +#endif -/* Imprime dans une ligne de rendu le contenu représenté. */ -static PyObject *py_line_generator_print(PyObject *, PyObject *); /* Indique le nombre de ligne prêtes à être générées. */ -static PyObject *py_line_generator_get_lines_count(PyObject *, void *); +static PyObject *py_token_generator_get_lines_count(PyObject *, void *); @@ -101,31 +114,33 @@ static PyObject *py_line_generator_get_lines_count(PyObject *, void *); * * ******************************************************************************/ -static void py_line_generator_interface_init(GLineGeneratorIface *iface, gpointer *unused) +static void py_token_generator_interface_init(GTokenGeneratorInterface *iface, gpointer *unused) { -#define LINE_GENERATOR_DOC \ - "LineGenerator gives an interface to all objects which aim to produce" \ +#define TOKEN_GENERATOR_DOC \ + "TokenGenerator gives an interface to all objects which aim to produce" \ " content for rendering lines. Such lines can be exported to graphical" \ " interfaces or text files.\n" \ "\n" \ "A typical class declaration for a new implementation looks like:\n" \ "\n" \ - " class NewImplem(GObject.Object, LineGenerator):\n" \ + " class NewImplem(GObject.Object, TokenGenerator):\n" \ " ...\n" \ "\n" \ "The following methods have to be defined for new implementations:\n" \ - "* pychrysalide.glibext.LineGenerator._count_lines();\n" \ - "* pychrysalide.glibext.LineGenerator._compute_cursor();\n" \ - "* pychrysalide.glibext.LineGenerator._contain_cursor();\n" \ - "* pychrysalide.glibext.LineGenerator._get_flags();\n" \ - "* pychrysalide.glibext.LineGenerator._print();\n" \ - - iface->count = py_line_generator_count_lines_wrapper; - iface->compute = py_line_generator_compute_cursor_wrapper; - iface->contain = py_line_generator_contain_cursor_wrapper; - iface->get_flags = py_line_generator_get_flags_wrapper; - iface->print = py_line_generator_print_wrapper; + "* pychrysalide.glibext.TokenGenerator._count_lines();\n" \ + "* pychrysalide.glibext.TokenGenerator._get_flags();\n" \ + "* pychrysalide.glibext.TokenGenerator._populate_line();\n" \ + "* pychrysalide.glibext.TokenGenerator._compute_cursor();\n" \ + "* pychrysalide.glibext.TokenGenerator._contain_cursor().\n" + + iface->count = py_token_generator_count_lines_wrapper; + iface->get_flags = py_token_generator_get_flags_wrapper; + iface->populate = py_token_generator_populate_line_wrappper; +#if 0 + iface->compute = py_token_generator_compute_cursor_wrapper; + iface->contain = py_token_generator_contain_cursor_wrapper; +#endif } @@ -142,7 +157,7 @@ static void py_line_generator_interface_init(GLineGeneratorIface *iface, gpointe * * ******************************************************************************/ -static size_t py_line_generator_count_lines_wrapper(const GLineGenerator *generator) +static size_t py_token_generator_count_lines_wrapper(const GTokenGenerator *generator) { size_t result; /* Décompte à retourner */ PyGILState_STATE gstate; /* Sauvegarde d'environnement */ @@ -150,7 +165,7 @@ static size_t py_line_generator_count_lines_wrapper(const GLineGenerator *genera PyObject *pyret; /* Bilan de consultation */ int ret; /* Bilan d'une conversion */ -#define LINE_GENERATOR_COUNT_LINES_WRAPPER PYTHON_WRAPPER_DEF \ +#define TOKEN_GENERATOR_COUNT_LINES_WRAPPER PYTHON_WRAPPER_DEF \ ( \ _count_lines, "$self, /", \ METH_NOARGS, \ @@ -193,61 +208,61 @@ static size_t py_line_generator_count_lines_wrapper(const GLineGenerator *genera /****************************************************************************** * * * Paramètres : generator = générateur à consulter. * -* x = position géographique sur la ligne concernée. * * index = indice de cette même ligne dans le tampon global.* * repeat = indice d'utilisations successives du générateur. * * * -* Description : Retrouve l'emplacement correspondant à une position donnée. * +* Description : Renseigne sur les propriétés liées à un générateur. * * * -* Retour : Emplacement constitué. * +* Retour : Propriétés particulières associées. * * * * Remarques : - * * * ******************************************************************************/ -static void py_line_generator_compute_cursor_wrapper(const GLineGenerator *generator, gint x, size_t index, size_t repeat, GLineCursor **cursor) +static BufferLineFlags py_token_generator_get_flags_wrapper(const GTokenGenerator *generator, size_t index, size_t repeat) { + BufferLineFlags result; /* Fanions à retourner */ PyGILState_STATE gstate; /* Sauvegarde d'environnement */ PyObject *pyobj; /* Objet Python concerné */ PyObject *args; /* Arguments pour l'appel */ PyObject *pyret; /* Bilan de consultation */ int ret; /* Bilan d'une conversion */ -#define LINE_GENERATOR_COMPUTE_CURSOR_WRAPPER PYTHON_WRAPPER_DEF \ +#define TOKEN_GENERATOR_GET_FLAGS_WRAPPER PYTHON_WRAPPER_DEF \ ( \ - _compute_cursor, "$self, x, index, repeat, /", \ + _get_flags, "$self, index, repeat, /", \ METH_VARARGS, \ - "Abstract method used to create a new cursor for a given" \ - " location inside displayed lines.\n" \ + "Abstract method used to provide flags for a given rendering" \ + " line.\n" \ "\n" \ - "The position on the horizontal axis, the line index and the" \ - " number of repetitions (only relevant if the generator" \ - " produces several lines) give indications about the active" \ - " position.\n" \ + "The line index and the number of repetitions (only relevant" \ + " if the generator produces several lines) give indications" \ + " about the active position.\n" \ "\n" \ - "The result has to be a pychrysalide.glibext.LineCursor" \ - " instance." \ + "The result has to be a" \ + " pychrysalide.glibext.BufferLine.BufferLineFlags value.\n" \ ) + result = BLF_NONE; + gstate = PyGILState_Ensure(); pyobj = pygobject_new(G_OBJECT(generator)); - if (has_python_method(pyobj, "_compute_cursor")) + if (has_python_method(pyobj, "_get_flags")) { - args = PyTuple_New(3); - PyTuple_SetItem(args, 0, PyLong_FromSize_t(x)); - PyTuple_SetItem(args, 1, PyLong_FromSize_t(index)); - PyTuple_SetItem(args, 2, PyLong_FromSize_t(repeat)); + args = PyTuple_New(2); + PyTuple_SetItem(args, 0, PyLong_FromSize_t(index)); + PyTuple_SetItem(args, 1, PyLong_FromSize_t(repeat)); - pyret = run_python_method(pyobj, "_compute_cursor", args); + pyret = run_python_method(pyobj, "_get_flags", args); if (pyret != NULL) { - ret = convert_to_line_cursor(pyret, cursor); + ret = convert_to_buffer_line_flags(pyret, &result); if (ret != 1) - *cursor = NULL; + result = BLF_NONE; Py_DECREF(pyret); @@ -261,75 +276,66 @@ static void py_line_generator_compute_cursor_wrapper(const GLineGenerator *gener PyGILState_Release(gstate); + return result; + } /****************************************************************************** * * -* Paramètres : generator = générateur à consulter. * +* Paramètres : generator = générateur à utiliser pour l'impression. * * index = indice de cette même ligne dans le tampon global.* * repeat = indice d'utilisations successives du générateur. * -* cursor = emplacement à analyser. * +* line = ligne de rendu à compléter. * +* data = éventuelle donnée complémentaire fournie. * * * -* Description : Détermine si le conteneur s'inscrit dans une plage donnée. * +* Description : Etablit dans une ligne de rendu le contenu représenté. * * * -* Retour : Bilan de la détermination, utilisable en comparaisons. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -static int py_line_generator_contain_cursor_wrapper(const GLineGenerator *generator, size_t index, size_t repeat, const GLineCursor *cursor) +static void py_token_generator_populate_line_wrappper(const GTokenGenerator *generator, size_t index, size_t repeat, GBufferLine *line, void *data) { - int result; /* Bilan d'analyse à retourner */ PyGILState_STATE gstate; /* Sauvegarde d'environnement */ PyObject *pyobj; /* Objet Python concerné */ PyObject *args; /* Arguments pour l'appel */ PyObject *pyret; /* Bilan de consultation */ - int ret; /* Bilan d'une conversion */ -#define LINE_GENERATOR_CONTAIN_CURSOR_WRAPPER PYTHON_WRAPPER_DEF \ +#define TOKEN_GENERATOR_POPULATE_LINE_WRAPPER PYTHON_WRAPPER_DEF \ ( \ - _contain_cursor, "$self, index, repeat, cursor, /", \ + _populate_line, "$self, index, repeat, line, /", \ METH_VARARGS, \ - "Abstract method used to check the position of a cursor in" \ - " relation to rendering lines.\n" \ + "Abstract method used to generate content into a rendering" \ + " line.\n" \ "\n" \ - "The line index and the number of repetitions (only relevant" \ + "This rendering output is pointed by the *line* argument, which"\ + " is a provided pychrysalide.glibext.BufferLine instance. The" \ + " line *index* and the number of repetitions (only relevant" \ " if the generator produces several lines) give indications" \ - " about the active position. The cursor is a" \ - " pychrysalide.glibext.LineCursor instance.\n" \ + " about the current rendering position.\n" \ "\n" \ - "The result has to be an integer less than, equal to, or" \ - " greater than zero if the cursor is, respectively, before," \ - " inside or after the area covered by the generator." \ + "If set, the content is a pychrysalide.analysis.BinContent" \ + " instance providing access to the processed binary data." \ ) - result = 0; - gstate = PyGILState_Ensure(); pyobj = pygobject_new(G_OBJECT(generator)); - if (has_python_method(pyobj, "_contain_cursor")) + if (has_python_method(pyobj, "_populate_line")) { args = PyTuple_New(3); PyTuple_SetItem(args, 0, PyLong_FromSize_t(index)); PyTuple_SetItem(args, 1, PyLong_FromSize_t(repeat)); - PyTuple_SetItem(args, 2, pygobject_new(G_OBJECT(cursor))); + PyTuple_SetItem(args, 2, pygobject_new(G_OBJECT(line))); + //PyTuple_SetItem(args, 3, pygobject_new(G_OBJECT(content))); - pyret = run_python_method(pyobj, "_contain_cursor", args); - - if (pyret != NULL) - { - ret = PyLong_Check(pyret); + pyret = run_python_method(pyobj, "_populate_line", args); - if (ret) - result = PyLong_AsLong(pyret); - - Py_DECREF(pyret); - - } + Py_XDECREF(pyret); Py_DECREF(args); @@ -339,69 +345,70 @@ static int py_line_generator_contain_cursor_wrapper(const GLineGenerator *genera PyGILState_Release(gstate); - return result; - } +#if 0 + + /****************************************************************************** * * * Paramètres : generator = générateur à consulter. * +* x = position géographique sur la ligne concernée. * * index = indice de cette même ligne dans le tampon global.* * repeat = indice d'utilisations successives du générateur. * * * -* Description : Renseigne sur les propriétés liées à un générateur. * +* Description : Retrouve l'emplacement correspondant à une position donnée. * * * -* Retour : Propriétés particulières associées. * +* Retour : Emplacement constitué. * * * * Remarques : - * * * ******************************************************************************/ -static BufferLineFlags py_line_generator_get_flags_wrapper(const GLineGenerator *generator, size_t index, size_t repeat) +static void py_token_generator_compute_cursor_wrapper(const GTokenGenerator *generator, gint x, size_t index, size_t repeat, GLineCursor **cursor) { - BufferLineFlags result; /* Fanions à retourner */ PyGILState_STATE gstate; /* Sauvegarde d'environnement */ PyObject *pyobj; /* Objet Python concerné */ PyObject *args; /* Arguments pour l'appel */ PyObject *pyret; /* Bilan de consultation */ int ret; /* Bilan d'une conversion */ -#define LINE_GENERATOR_GET_FLAGS_WRAPPER PYTHON_WRAPPER_DEF \ +#define TOKEN_GENERATOR_COMPUTE_CURSOR_WRAPPER PYTHON_WRAPPER_DEF \ ( \ - _get_flags, "$self, index, repeat, /", \ + _compute_cursor, "$self, x, index, repeat, /", \ METH_VARARGS, \ - "Abstract method used to provide flags for a given rendering" \ - " line.\n" \ + "Abstract method used to create a new cursor for a given" \ + " location inside displayed lines.\n" \ "\n" \ - "The line index and the number of repetitions (only relevant" \ - " if the generator produces several lines) give indications" \ - " about the active position.\n" \ + "The position on the horizontal axis, the line index and the" \ + " number of repetitions (only relevant if the generator" \ + " produces several lines) give indications about the active" \ + " position.\n" \ "\n" \ - "The result has to be a" \ - " pychrysalide.glibext.BufferLine.BufferLineFlags value.\n" \ + "The result has to be a pychrysalide.glibext.LineCursor" \ + " instance." \ ) - result = BLF_NONE; - gstate = PyGILState_Ensure(); pyobj = pygobject_new(G_OBJECT(generator)); - if (has_python_method(pyobj, "_get_flags")) + if (has_python_method(pyobj, "_compute_cursor")) { - args = PyTuple_New(2); - PyTuple_SetItem(args, 0, PyLong_FromSize_t(index)); - PyTuple_SetItem(args, 1, PyLong_FromSize_t(repeat)); + args = PyTuple_New(3); + PyTuple_SetItem(args, 0, PyLong_FromSize_t(x)); + PyTuple_SetItem(args, 1, PyLong_FromSize_t(index)); + PyTuple_SetItem(args, 2, PyLong_FromSize_t(repeat)); - pyret = run_python_method(pyobj, "_get_flags", args); + pyret = run_python_method(pyobj, "_compute_cursor", args); if (pyret != NULL) { - ret = convert_to_buffer_line_flags(pyret, &result); + ret = convert_to_line_cursor(pyret, cursor); if (ret != 1) - result = BLF_NONE; + *cursor = NULL; Py_DECREF(pyret); @@ -415,65 +422,75 @@ static BufferLineFlags py_line_generator_get_flags_wrapper(const GLineGenerator PyGILState_Release(gstate); - return result; - } /****************************************************************************** * * -* Paramètres : generator = générateur à utiliser pour l'impression. * -* line = ligne de rendu à compléter. * +* Paramètres : generator = générateur à consulter. * * index = indice de cette même ligne dans le tampon global.* * repeat = indice d'utilisations successives du générateur. * -* content = éventuel contenu binaire brut à imprimer. * +* cursor = emplacement à analyser. * * * -* Description : Imprime dans une ligne de rendu le contenu représenté. * +* Description : Détermine si le conteneur s'inscrit dans une plage donnée. * * * -* Retour : - * +* Retour : Bilan de la détermination, utilisable en comparaisons. * * * * Remarques : - * * * ******************************************************************************/ -static void py_line_generator_print_wrapper(GLineGenerator *generator, GBufferLine *line, size_t index, size_t repeat, const GBinContent *content) +static int py_token_generator_contain_cursor_wrapper(const GTokenGenerator *generator, size_t index, size_t repeat, const GLineCursor *cursor) { + int result; /* Bilan d'analyse à retourner */ PyGILState_STATE gstate; /* Sauvegarde d'environnement */ PyObject *pyobj; /* Objet Python concerné */ PyObject *args; /* Arguments pour l'appel */ PyObject *pyret; /* Bilan de consultation */ + int ret; /* Bilan d'une conversion */ -#define LINE_GENERATOR_PRINT_WRAPPER PYTHON_WRAPPER_DEF \ +#define TOKEN_GENERATOR_CONTAIN_CURSOR_WRAPPER PYTHON_WRAPPER_DEF \ ( \ - _print, "$self, line, index, repeat, content, /", \ + _contain_cursor, "$self, index, repeat, cursor, /", \ METH_VARARGS, \ - "Abstract method used to generate content into a rendering" \ - " line, which is a provided pychrysalide.glibext.BufferLine" \ - " instance.\n" \ + "Abstract method used to check the position of a cursor in" \ + " relation to rendering lines.\n" \ "\n" \ "The line index and the number of repetitions (only relevant" \ " if the generator produces several lines) give indications" \ - " about the current rendering position.\n" \ + " about the active position. The cursor is a" \ + " pychrysalide.glibext.LineCursor instance.\n" \ "\n" \ - "If set, the content is a pychrysalide.analysis.BinContent" \ - " instance providing access to the processed binary data." \ + "The result has to be an integer less than, equal to, or" \ + " greater than zero if the cursor is, respectively, before," \ + " inside or after the area covered by the generator." \ ) + result = 0; + gstate = PyGILState_Ensure(); pyobj = pygobject_new(G_OBJECT(generator)); - if (has_python_method(pyobj, "_print")) + if (has_python_method(pyobj, "_contain_cursor")) { - args = PyTuple_New(4); - PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(line))); - PyTuple_SetItem(args, 1, PyLong_FromSize_t(index)); - PyTuple_SetItem(args, 2, PyLong_FromSize_t(repeat)); - PyTuple_SetItem(args, 3, pygobject_new(G_OBJECT(content))); + args = PyTuple_New(3); + PyTuple_SetItem(args, 0, PyLong_FromSize_t(index)); + PyTuple_SetItem(args, 1, PyLong_FromSize_t(repeat)); + PyTuple_SetItem(args, 2, pygobject_new(G_OBJECT(cursor))); - pyret = run_python_method(pyobj, "_print", args); + pyret = run_python_method(pyobj, "_contain_cursor", args); - Py_XDECREF(pyret); + if (pyret != NULL) + { + ret = PyLong_Check(pyret); + + if (ret) + result = PyLong_AsLong(pyret); + + Py_DECREF(pyret); + + } Py_DECREF(args); @@ -483,12 +500,16 @@ static void py_line_generator_print_wrapper(GLineGenerator *generator, GBufferLi PyGILState_Release(gstate); + return result; + } +#endif + /* ---------------------------------------------------------------------------------- */ -/* CONNEXION AVEC L'API DE PYTHON */ +/* LIAISON DE FONCTIONNALITES AVEC L'API PYTHON */ /* ---------------------------------------------------------------------------------- */ @@ -497,57 +518,45 @@ static void py_line_generator_print_wrapper(GLineGenerator *generator, GBufferLi * Paramètres : self = classe représentant un générateur à manipuler. * * args = arguments fournis à l'appel. * * * -* Description : Retrouve l'emplacement correspondant à une position donnée. * +* Description : Renseigne sur les propriétés liées à un générateur. * * * -* Retour : Emplacement constitué. * +* Retour : Propriétés particulières associées. * * * * Remarques : - * * * ******************************************************************************/ -static PyObject *py_line_generator_compute_cursor(PyObject *self, PyObject *args) +static PyObject *py_token_generator_get_flags(PyObject *self, PyObject *args) { PyObject *result; /* Propriétés à retourner */ - int x; /* Position horizontale */ size_t index; /* Indice dans le tampon */ size_t repeat; /* Utilisations successives */ int ret; /* Bilan de lecture des args. */ - GLineGenerator *generator; /* Version native */ - GLineCursor *cursor; /* Curseur nouveau obtenu */ + GTokenGenerator *generator; /* Version native */ + BufferLineFlags flags; /* Propriétés courantes */ -#define LINE_GENERATOR_COMPUTE_CURSOR_METHOD PYTHON_METHOD_DEF \ -( \ - compute_cursor, "$self, x, index, repeat, /", \ - METH_VARARGS, py_line_generator, \ - "Create a a new cursor for a given location inside displayed" \ - " lines.\n" \ - "\n" \ - "The position on the horizontal axis, the line index and the" \ - " number of repetitions (only relevant if the generator" \ - " produces several lines) give indications about the active" \ - " position.\n" \ - "\n" \ - "The result has to be a pychrysalide.glibext.LineCursor" \ - " instance." \ +#define TOKEN_GENERATOR_GET_FLAGS_METHOD PYTHON_METHOD_DEF \ +( \ + get_flags, "$self, index, repeat, /", \ + METH_VARARGS, py_token_generator, \ + "Get the flags of a given position from the generator.\n" \ + "\n" \ + "The line index and the number of repetitions (only relevant" \ + " if the generator produces several lines) give indications" \ + " about the active position.\n" \ + "\n" \ + "The result is a pychrysalide.glibext.BufferLine.BufferLineFlags" \ + " value." \ ) - ret = PyArg_ParseTuple(args, "inn", &x, &index, &repeat); + ret = PyArg_ParseTuple(args, "nn", &index, &repeat); if (!ret) return NULL; - generator = G_LINE_GENERATOR(pygobject_get(self)); + generator = G_TOKEN_GENERATOR(pygobject_get(self)); - cursor = g_line_generator_compute_cursor(generator, x, index, repeat); + flags = g_token_generator_get_flags(generator, index, repeat); - if (cursor != NULL) - { - result = pygobject_new(G_OBJECT(cursor)); - g_object_unref(G_OBJECT(cursor)); - } - else - { - result = Py_None; - Py_INCREF(result); - } + result = cast_with_constants_group_from_type(get_python_buffer_line_type(), "BufferLineFlags", flags); return result; @@ -559,99 +568,108 @@ static PyObject *py_line_generator_compute_cursor(PyObject *self, PyObject *args * Paramètres : self = classe représentant un générateur à manipuler. * * args = arguments fournis à l'appel. * * * -* Description : Détermine si le conteneur s'inscrit dans une plage donnée. * +* Description : Etablit dans une ligne de rendu le contenu représenté. * * * -* Retour : Bilan de la détermination, utilisable en comparaisons. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -static PyObject *py_line_generator_contain_cursor(PyObject *self, PyObject *args) +static PyObject *py_token_generator_populate_line(PyObject *self, PyObject *args) { - PyObject *result; /* Propriétés à retourner */ + GBufferLine *line; /* Ligne de rendu à compléter */ size_t index; /* Indice dans le tampon */ size_t repeat; /* Utilisations successives */ - GLineCursor *cursor; /* Curseur à venir situer */ + GTokenGenerator *generator; /* Version native */ int ret; /* Bilan de lecture des args. */ - GLineGenerator *generator; /* Version native */ - int status; /* Bilan d'une analyse */ -#define LINE_GENERATOR_CONTAIN_CURSOR_METHOD PYTHON_METHOD_DEF \ +#define TOKEN_GENERATOR_POPULATE_LINE_METHOD PYTHON_METHOD_DEF \ ( \ - contain_cursor, "$self, index, repeat, cursor, /", \ - METH_VARARGS, py_line_generator, \ - "Check the position of a cursor in relation to rendering" \ - " lines.\n" \ + populate_line, "$self, index, repeat, line, /", \ + METH_VARARGS, py_token_generator, \ + "Produce output into a rendering line with optional content.\n" \ "\n" \ - "The line index and the number of repetitions (only relevant" \ - " if the generator produces several lines) give indications" \ - " about the active position. The cursor is a" \ - " pychrysalide.glibext.LineCursor instance.\n" \ + "The provided *line* is a pychrysalide.glibext.BufferLine" \ + " instance. The *index* and the number of repetitions (only" \ + " relevant if the generator produces several lines) give" \ + " indications about the current rendering position.\n" \ "\n" \ - "The result has to be an integer less than, equal to, or" \ - " greater than zero if the cursor is, respectively, before," \ - " inside or after the area covered by the generator." \ + "If set, the content is a pychrysalide.analysis.BinContent" \ + " instance providing access to the processed binary data." \ ) - ret = PyArg_ParseTuple(args, "nnO&", &index, &repeat, convert_to_line_cursor, &cursor); + ret = PyArg_ParseTuple(args, "nnO&", &index, &repeat, convert_to_buffer_line, &line); if (!ret) return NULL; - generator = G_LINE_GENERATOR(pygobject_get(self)); + generator = G_TOKEN_GENERATOR(pygobject_get(self)); - status = g_line_generator_contain_cursor(generator, index, repeat, cursor); + g_token_generator_populate_line(generator, index, repeat, line, NULL); - result = PyLong_FromLong(status); - - return result; + Py_RETURN_NONE; } + +#if 0 + /****************************************************************************** * * * Paramètres : self = classe représentant un générateur à manipuler. * * args = arguments fournis à l'appel. * * * -* Description : Renseigne sur les propriétés liées à un générateur. * +* Description : Retrouve l'emplacement correspondant à une position donnée. * * * -* Retour : Propriétés particulières associées. * +* Retour : Emplacement constitué. * * * * Remarques : - * * * ******************************************************************************/ -static PyObject *py_line_generator_get_flags(PyObject *self, PyObject *args) +static PyObject *py_token_generator_compute_cursor(PyObject *self, PyObject *args) { PyObject *result; /* Propriétés à retourner */ + int x; /* Position horizontale */ size_t index; /* Indice dans le tampon */ size_t repeat; /* Utilisations successives */ int ret; /* Bilan de lecture des args. */ - GLineGenerator *generator; /* Version native */ - BufferLineFlags flags; /* Propriétés courantes */ + GTokenGenerator *generator; /* Version native */ + GLineCursor *cursor; /* Curseur nouveau obtenu */ -#define LINE_GENERATOR_GET_FLAGS_METHOD PYTHON_METHOD_DEF \ -( \ - get_flags, "$self, index, repeat, /", \ - METH_VARARGS, py_line_generator, \ - "Get the flags of a given position from the generator.\n" \ - "\n" \ - "The line index and the number of repetitions (only relevant" \ - " if the generator produces several lines) give indications" \ - " about the active position.\n" \ - "\n" \ - "The result is a pychrysalide.glibext.BufferLine.BufferLineFlags" \ - " value." \ +#define TOKEN_GENERATOR_COMPUTE_CURSOR_METHOD PYTHON_METHOD_DEF \ +( \ + compute_cursor, "$self, x, index, repeat, /", \ + METH_VARARGS, py_token_generator, \ + "Create a a new cursor for a given location inside displayed" \ + " lines.\n" \ + "\n" \ + "The position on the horizontal axis, the line index and the" \ + " number of repetitions (only relevant if the generator" \ + " produces several lines) give indications about the active" \ + " position.\n" \ + "\n" \ + "The result has to be a pychrysalide.glibext.LineCursor" \ + " instance." \ ) - ret = PyArg_ParseTuple(args, "nn", &index, &repeat); + ret = PyArg_ParseTuple(args, "inn", &x, &index, &repeat); if (!ret) return NULL; - generator = G_LINE_GENERATOR(pygobject_get(self)); + generator = G_TOKEN_GENERATOR(pygobject_get(self)); - flags = g_line_generator_get_flags(generator, index, repeat); + cursor = g_token_generator_compute_cursor(generator, x, index, repeat); - result = cast_with_constants_group_from_type(get_python_buffer_line_type(), "BufferLineFlags", flags); + if (cursor != NULL) + { + result = pygobject_new(G_OBJECT(cursor)); + g_object_unref(G_OBJECT(cursor)); + } + else + { + result = Py_None; + Py_INCREF(result); + } return result; @@ -663,50 +681,56 @@ static PyObject *py_line_generator_get_flags(PyObject *self, PyObject *args) * Paramètres : self = classe représentant un générateur à manipuler. * * args = arguments fournis à l'appel. * * * -* Description : Imprime dans une ligne de rendu le contenu représenté. * +* Description : Détermine si le conteneur s'inscrit dans une plage donnée. * * * -* Retour : - * +* Retour : Bilan de la détermination, utilisable en comparaisons. * * * * Remarques : - * * * ******************************************************************************/ -static PyObject *py_line_generator_print(PyObject *self, PyObject *args) +static PyObject *py_token_generator_contain_cursor(PyObject *self, PyObject *args) { - GBufferLine *line; /* Ligne de rendu à compléter */ + PyObject *result; /* Propriétés à retourner */ size_t index; /* Indice dans le tampon */ size_t repeat; /* Utilisations successives */ - GBinContent *content; /* Contenu binaire associé */ - GLineGenerator *generator; /* Version native */ + GLineCursor *cursor; /* Curseur à venir situer */ int ret; /* Bilan de lecture des args. */ + GTokenGenerator *generator; /* Version native */ + int status; /* Bilan d'une analyse */ -#define LINE_GENERATOR_PRINT_METHOD PYTHON_METHOD_DEF \ +#define TOKEN_GENERATOR_CONTAIN_CURSOR_METHOD PYTHON_METHOD_DEF \ ( \ - print, "$self, line, index, repeat, content, /", \ - METH_VARARGS, py_line_generator, \ - "Produce output into a rendering line with optional content.\n" \ + contain_cursor, "$self, index, repeat, cursor, /", \ + METH_VARARGS, py_token_generator, \ + "Check the position of a cursor in relation to rendering" \ + " lines.\n" \ "\n" \ - "The provided line is a pychrysalide.glibext.BufferLine" \ - " instance. The index and the number of repetitions (only" \ - " relevant if the generator produces several lines) give" \ - " indications about the current rendering position.\n" \ + "The line index and the number of repetitions (only relevant" \ + " if the generator produces several lines) give indications" \ + " about the active position. The cursor is a" \ + " pychrysalide.glibext.LineCursor instance.\n" \ "\n" \ - "If set, the content is a pychrysalide.analysis.BinContent" \ - " instance providing access to the processed binary data." \ + "The result has to be an integer less than, equal to, or" \ + " greater than zero if the cursor is, respectively, before," \ + " inside or after the area covered by the generator." \ ) - ret = PyArg_ParseTuple(args, "O&nnO&", convert_to_buffer_line, &line, &index, - &repeat, convert_to_binary_content, &content); + ret = PyArg_ParseTuple(args, "nnO&", &index, &repeat, convert_to_line_cursor, &cursor); if (!ret) return NULL; - generator = G_LINE_GENERATOR(pygobject_get(self)); + generator = G_TOKEN_GENERATOR(pygobject_get(self)); - g_line_generator_print(generator, line, index, repeat, content); + status = g_token_generator_contain_cursor(generator, index, repeat, cursor); - Py_RETURN_NONE; + result = PyLong_FromLong(status); + + return result; } +#endif + /****************************************************************************** * * @@ -721,24 +745,24 @@ static PyObject *py_line_generator_print(PyObject *self, PyObject *args) * * ******************************************************************************/ -static PyObject *py_line_generator_get_lines_count(PyObject *self, void *closure) +static PyObject *py_token_generator_get_lines_count(PyObject *self, void *closure) { PyObject *result; /* Décompte à retourner */ - GLineGenerator *generator; /* Version native */ + GTokenGenerator *generator; /* Version native */ size_t count; /* Nombre de lignes présentes */ -#define LINE_GENERATOR_LINES_COUNT_ATTRIB PYTHON_GET_DEF_FULL \ +#define TOKEN_GENERATOR_LINES_COUNT_ATTRIB PYTHON_GET_DEF_FULL \ ( \ - lines_count, py_line_generator, \ + lines_count, py_token_generator, \ "Quantity of lines produced by the generator.\n" \ "\n" \ "This number may vary between calls, if a width has changed" \ " for instance." \ ) - generator = G_LINE_GENERATOR(pygobject_get(self)); + generator = G_TOKEN_GENERATOR(pygobject_get(self)); - count = g_line_generator_count_lines(generator); + count = g_token_generator_count_lines(generator); result = PyLong_FromSize_t(count); @@ -759,43 +783,47 @@ static PyObject *py_line_generator_get_lines_count(PyObject *self, void *closure * * ******************************************************************************/ -PyTypeObject *get_python_line_generator_type(void) +PyTypeObject *get_python_token_generator_type(void) { - static PyMethodDef py_line_generator_methods[] = { - LINE_GENERATOR_COUNT_LINES_WRAPPER, - LINE_GENERATOR_COMPUTE_CURSOR_WRAPPER, - LINE_GENERATOR_CONTAIN_CURSOR_WRAPPER, - LINE_GENERATOR_GET_FLAGS_WRAPPER, - LINE_GENERATOR_PRINT_WRAPPER, - LINE_GENERATOR_COMPUTE_CURSOR_METHOD, - LINE_GENERATOR_CONTAIN_CURSOR_METHOD, - LINE_GENERATOR_GET_FLAGS_METHOD, - LINE_GENERATOR_PRINT_METHOD, + static PyMethodDef py_token_generator_methods[] = { + TOKEN_GENERATOR_COUNT_LINES_WRAPPER, + TOKEN_GENERATOR_GET_FLAGS_WRAPPER, + TOKEN_GENERATOR_POPULATE_LINE_WRAPPER, + /* + TOKEN_GENERATOR_COMPUTE_CURSOR_WRAPPER, + TOKEN_GENERATOR_CONTAIN_CURSOR_WRAPPER, + */ + TOKEN_GENERATOR_GET_FLAGS_METHOD, + TOKEN_GENERATOR_POPULATE_LINE_METHOD, + /* + TOKEN_GENERATOR_COMPUTE_CURSOR_METHOD, + TOKEN_GENERATOR_CONTAIN_CURSOR_METHOD, + */ { NULL } }; - static PyGetSetDef py_line_generator_getseters[] = { - LINE_GENERATOR_LINES_COUNT_ATTRIB, + static PyGetSetDef py_token_generator_getseters[] = { + TOKEN_GENERATOR_LINES_COUNT_ATTRIB, { NULL } }; - static PyTypeObject py_line_generator_type = { + static PyTypeObject py_token_generator_type = { PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "pychrysalide.glibext.LineGenerator", + .tp_name = "pychrysalide.glibext.TokenGenerator", .tp_basicsize = sizeof(PyObject), .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, - .tp_doc = LINE_GENERATOR_DOC, + .tp_doc = TOKEN_GENERATOR_DOC, - .tp_methods = py_line_generator_methods, - .tp_getset = py_line_generator_getseters, + .tp_methods = py_token_generator_methods, + .tp_getset = py_token_generator_getseters, }; - return &py_line_generator_type; + return &py_token_generator_type; } @@ -804,7 +832,7 @@ PyTypeObject *get_python_line_generator_type(void) * * * Paramètres : module = module dont la définition est à compléter. * * * -* Description : Prend en charge l'objet 'pychrysalide.glibext.LineGenerator'.* +* Description : Prend en charge l'objet 'pychrysalide.....TokenGenerator'. * * * * Retour : Bilan de l'opération. * * * @@ -812,21 +840,21 @@ PyTypeObject *get_python_line_generator_type(void) * * ******************************************************************************/ -bool ensure_python_line_generator_is_registered(void) +bool ensure_python_token_generator_is_registered(void) { - PyTypeObject *type; /* Type Python 'LineGenerator' */ + PyTypeObject *type; /* Type Python 'TokenGenerator'*/ PyObject *module; /* Module à recompléter */ PyObject *dict; /* Dictionnaire du module */ static GInterfaceInfo info = { /* Paramètres d'inscription */ - .interface_init = (GInterfaceInitFunc)py_line_generator_interface_init, + .interface_init = (GInterfaceInitFunc)py_token_generator_interface_init, .interface_finalize = NULL, .interface_data = NULL, }; - type = get_python_line_generator_type(); + type = get_python_token_generator_type(); if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) { @@ -834,7 +862,7 @@ bool ensure_python_line_generator_is_registered(void) dict = PyModule_GetDict(module); - if (!register_interface_for_pygobject(dict, G_TYPE_LINE_GENERATOR, type, &info)) + if (!register_interface_for_pygobject(dict, G_TYPE_TOKEN_GENERATOR, type, &info)) return false; } @@ -857,11 +885,11 @@ bool ensure_python_line_generator_is_registered(void) * * ******************************************************************************/ -int convert_to_line_generator(PyObject *arg, void *dst) +int convert_to_token_generator(PyObject *arg, void *dst) { int result; /* Bilan à retourner */ - result = PyObject_IsInstance(arg, (PyObject *)get_python_line_generator_type()); + result = PyObject_IsInstance(arg, (PyObject *)get_python_token_generator_type()); switch (result) { @@ -871,11 +899,11 @@ int convert_to_line_generator(PyObject *arg, void *dst) break; case 0: - PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to line generator"); + PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to token generator"); break; case 1: - *((GLineGenerator **)dst) = G_LINE_GENERATOR(pygobject_get(arg)); + *((GTokenGenerator **)dst) = G_TOKEN_GENERATOR(pygobject_get(arg)); break; default: diff --git a/plugins/pychrysalide/glibext/linegen.h b/plugins/pychrysalide/glibext/generator.h index bfad885..b2672a8 100644 --- a/plugins/pychrysalide/glibext/linegen.h +++ b/plugins/pychrysalide/glibext/generator.h @@ -1,8 +1,8 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * linegen.h - prototypes pour l'équivalent Python du fichier "glibext/linegen.h" + * generator.h - prototypes pour l'équivalent Python du fichier "glibext/generator.h" * - * Copyright (C) 2018 Cyrille Bagard + * Copyright (C) 2018-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -22,8 +22,8 @@ */ -#ifndef _PLUGINS_PYCHRYSALIDE_GLIBEXT_LINEGEN_H -#define _PLUGINS_PYCHRYSALIDE_GLIBEXT_LINEGEN_H +#ifndef _PLUGINS_PYCHRYSALIDE_GLIBEXT_GENERATOR_H +#define _PLUGINS_PYCHRYSALIDE_GLIBEXT_GENERATOR_H #include <Python.h> @@ -32,14 +32,14 @@ /* Fournit un accès à une définition de type à diffuser. */ -PyTypeObject *get_python_line_generator_type(void); +PyTypeObject *get_python_token_generator_type(void); -/* Prend en charge l'objet 'pychrysalide.glibext.LineGenerator'. */ -bool ensure_python_line_generator_is_registered(void); +/* Prend en charge l'objet 'pychrysalide.glibext.TokenGenerator'. */ +bool ensure_python_token_generator_is_registered(void); /* Tente de convertir en générateur de lignes. */ -int convert_to_line_generator(PyObject *, void *); +int convert_to_token_generator(PyObject *, void *); -#endif /* _PLUGINS_PYCHRYSALIDE_GLIBEXT_LINEGEN_H */ +#endif /* _PLUGINS_PYCHRYSALIDE_GLIBEXT_GENERATOR_H */ diff --git a/plugins/pychrysalide/glibext/module-ui.c b/plugins/pychrysalide/glibext/module-ui.c new file mode 100644 index 0000000..8fa6d0e --- /dev/null +++ b/plugins/pychrysalide/glibext/module-ui.c @@ -0,0 +1,62 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * module.c - intégration du répertoire glibext (forme graphique) en tant que module + * + * Copyright (C) 2025 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "module-ui.h" + + +#include <assert.h> + + +#include "bufferline.h" +#include "generator.h" + + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Intègre les objets du module 'glibext' (mode UI). * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool populate_glibext_module_ui(void) +{ + bool result; /* Bilan à retourner */ + + result = true; + + if (result) result = ensure_python_token_generator_is_registered(); + + if (result) result = ensure_python_buffer_line_is_registered(); + + assert(result); + + return result; + +} diff --git a/plugins/pychrysalide/glibext/module-ui.h b/plugins/pychrysalide/glibext/module-ui.h new file mode 100644 index 0000000..d91a2fa --- /dev/null +++ b/plugins/pychrysalide/glibext/module-ui.h @@ -0,0 +1,38 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * module.h - prototypes pour l'intégration du répertoire glibext (forme graphique) en tant que module + * + * Copyright (C) 2025 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_PYCHRYSALIDE_GLIBEXT_MODULE_UI_H +#define _PLUGINS_PYCHRYSALIDE_GLIBEXT_MODULE_UI_H + + +#include <Python.h> +#include <stdbool.h> + + +/* Intègre les objets du module 'glibext' (mode UI). */ +bool populate_glibext_module_ui(void); + + + +#endif /* _PLUGINS_PYCHRYSALIDE_GLIBEXT_MODULE_UI_H */ diff --git a/plugins/pychrysalide/glibext/module.c b/plugins/pychrysalide/glibext/module.c index 6ce0709..bbe357d 100644 --- a/plugins/pychrysalide/glibext/module.c +++ b/plugins/pychrysalide/glibext/module.c @@ -44,7 +44,9 @@ #include "objhole.h" #include "portion.h" #include "secstorage.h" +#include "serialize.h" #include "singleton.h" +#include "storage.h" #include "strbuilder.h" #include "work.h" #include "workqueue.h" @@ -116,12 +118,14 @@ bool populate_glibext_module(void) if (result) result = ensure_python_comparable_object_is_registered(); if (result) result = ensure_python_hashable_object_is_registered(); + if (result) result = ensure_python_serializable_object_is_registered(); if (result) result = ensure_python_singleton_candidate_is_registered(); if (result) result = ensure_python_string_builder_is_registered(); if (result) result = ensure_python_thick_object_is_registered(); if (result) result = ensure_python_binary_portion_is_registered(); if (result) result = ensure_python_generic_work_is_registered(); + if (result) result = ensure_python_object_storage_is_registered(); if (result) result = ensure_python_secret_storage_is_registered(); if (result) result = ensure_python_singleton_factory_is_registered(); if (result) result = ensure_python_work_queue_is_registered(); diff --git a/plugins/pychrysalide/glibext/objhole.c b/plugins/pychrysalide/glibext/objhole.c index 2a3ad6f..6bea5d1 100644 --- a/plugins/pychrysalide/glibext/objhole.c +++ b/plugins/pychrysalide/glibext/objhole.c @@ -37,12 +37,25 @@ -CREATE_DYN_CONSTRUCTOR(thick_object, G_TYPE_THICK_OBJECT); +/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */ + +CREATE_DYN_CONSTRUCTOR(thick_object, G_TYPE_THICK_OBJECT); /* Initialise une instance sur la base du dérivé de GObject. */ static int py_thick_object_init(PyObject *, PyObject *, PyObject *); + + +/* ------------------ LIAISON DE FONCTIONNALITES AVEC L'API PYTHON ------------------ */ + + +/* Pose un verrou à l'aide du bit dédié de GObject. */ +static PyObject *py_thick_object_lock(PyObject *, PyObject *); + +/* Retire un verrou via le bit dédié de GObject. */ +static PyObject *py_thick_object_unlock(PyObject *, PyObject *); + /* Indique le nombre de bits accaparés par la GLib. */ static PyObject *py_thick_object_get__GOBJECT_RESERVED_EXTRA_BITS(PyObject *, void *); @@ -54,6 +67,11 @@ static int py_thick_object_set_extra(PyObject *, PyObject *, void *); +/* ---------------------------------------------------------------------------------- */ +/* GLUE POUR CREATION DEPUIS PYTHON */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * * Paramètres : self = objet à initialiser (théoriquement). * @@ -92,6 +110,86 @@ static int py_thick_object_init(PyObject *self, PyObject *args, PyObject *kwds) } + +/* ---------------------------------------------------------------------------------- */ +/* LIAISON DE FONCTIONNALITES AVEC L'API PYTHON */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : self = instance représentant une extension d'objet. * +* args = arguments fournis à l'appel, non utilisé ici. * +* * +* Description : Pose un verrou à l'aide du bit dédié de GObject. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_thick_object_lock(PyObject *self, PyObject *args) +{ + PyObject *result; /* Résultat à retourner */ + GThickObject *obj; /* Version GLib de l'instance */ + +#define THICK_OBJECT_LOCK_METHOD PYTHON_METHOD_DEF \ +( \ + lock, "$self", \ + METH_NOARGS, py_thick_object, \ + "Lock the object using the internal GLib bit.\n" \ +) + + obj = G_THICK_OBJECT(pygobject_get(self)); + + g_thick_object_lock(obj); + + result = Py_None; + Py_INCREF(result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = instance représentant une extension d'objet. * +* args = arguments fournis à l'appel, non utilisé ici. * +* * +* Description : Retire un verrou via le bit dédié de GObject. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_thick_object_unlock(PyObject *self, PyObject *args) +{ + PyObject *result; /* Résultat à retourner */ + GThickObject *obj; /* Version GLib de l'instance */ + +#define THICK_OBJECT_UNLOCK_METHOD PYTHON_METHOD_DEF \ +( \ + unlock, "$self", \ + METH_NOARGS, py_thick_object, \ + "Unlock the object using the internal GLib bit.\n" \ +) + + obj = G_THICK_OBJECT(pygobject_get(self)); + + g_thick_object_unlock(obj); + + result = Py_None; + Py_INCREF(result); + + return result; + +} + + /****************************************************************************** * * * Paramètres : self = objet Python concerné par l'appel. * @@ -215,6 +313,8 @@ static int py_thick_object_set_extra(PyObject *self, PyObject *value, void *clos PyTypeObject *get_python_thick_object_type(void) { static PyMethodDef py_thick_object_methods[] = { + THICK_OBJECT_LOCK_METHOD, + THICK_OBJECT_UNLOCK_METHOD, { NULL } }; diff --git a/plugins/pychrysalide/glibext/secstorage.c b/plugins/pychrysalide/glibext/secstorage.c index b5adb7c..5935d29 100644 --- a/plugins/pychrysalide/glibext/secstorage.c +++ b/plugins/pychrysalide/glibext/secstorage.c @@ -106,14 +106,15 @@ static int py_secret_storage_init(PyObject *self, PyObject *args, PyObject *kwds "\n" \ "Instances can be created using the following constructor:\n" \ "\n" \ - " SecretStorage(settings)" \ + " SecretStorage(settings=None)" \ "\n" \ - "The *settings* arguement must point to a GSettings intance;" \ - " the main configuration settings are used by default." \ + "The *settings* arguement may point to a GSettings instance." \ + " This optional argument is mainly used for testing purpose;" \ + " the main configuration settings are used by default." settings = NULL; - ret = PyArg_ParseTuple(args, "|O&", convert_to_gsettings, &settings); + ret = PyArg_ParseTuple(args, "|O&", convert_to_gsettings_or_none, &settings); if (!ret) return -1; /* Initialisation d'un objet GLib */ diff --git a/plugins/pychrysalide/glibext/serialize.c b/plugins/pychrysalide/glibext/serialize.c new file mode 100644 index 0000000..61f359f --- /dev/null +++ b/plugins/pychrysalide/glibext/serialize.c @@ -0,0 +1,478 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * serialize.c - équivalent Python du fichier "glibext/serialize.h" + * + * Copyright (C) 2020-2025 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "serialize.h" + + +#include <pygobject.h> + + +#include <glibext/serialize-int.h> + + +#include "storage.h" +#include "../access.h" +#include "../helpers.h" + + + +/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */ + + +/* Procède à l'initialisation de l'interface de génération. */ +static void py_serializable_object_interface_init(GSerializableObjectInterface *, gpointer *); + +/* Charge un objet depuis un flux de données. */ +static bool py_serializable_object_load_wrapper(GSerializableObject *, GObjectStorage *, int); + +/* Sauvegarde un objet dans un flux de données. */ +static bool py_serializable_object_store_wrapper(const GSerializableObject *, GObjectStorage *, int); + + + +/* ------------------------- CONNEXION AVEC L'API DE PYTHON ------------------------- */ + + +/* Charge un objet depuis un flux de données. */ +static bool py_serializable_object_load(PyObject *, PyObject *); + +/* Sauvegarde un objet dans un flux de données. */ +static bool py_serializable_object_store(PyObject *, PyObject *); + + + +/* ---------------------------------------------------------------------------------- */ +/* GLUE POUR CREATION DEPUIS PYTHON */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* unused = adresse non utilisée ici. * +* * +* Description : Procède à l'initialisation de l'interface de génération. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void py_serializable_object_interface_init(GSerializableObjectInterface *iface, gpointer *unused) +{ + +#define SERIALIZABLE_OBJECT_DOC \ + "SerializableObject defines an interface used to store and load" \ + " objects to and from a data buffer.\n" \ + "\n" \ + "A typical class declaration for a new implementation looks like:\n" \ + "\n" \ + " class NewImplem(GObject.Object, SerializableObject):\n" \ + " ...\n" \ + "\n" \ + "The following methods have to be defined for new implementations:\n" \ + "* pychrysalide.glibext.SerializableObject._load();\n" \ + "* pychrysalide.glibext.SerializableObject._store();\n" + + iface->load = py_serializable_object_load_wrapper; + iface->store = py_serializable_object_store_wrapper; + +} + + +/****************************************************************************** +* * +* Paramètres : object = instruction d'assemblage à consulter. * +* storage = conservateur de données à manipuler. * +* fd = flux ouvert en lecture. * +* * +* Description : Charge un objet depuis un flux de données. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool py_serializable_object_load_wrapper(GSerializableObject *object, GObjectStorage *storage, int fd) +{ + bool result; /* Bilan à retourner */ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ + PyObject *args; /* Arguments pour l'appel */ + PyObject *pyobj; /* Objet Python concerné */ + PyObject *pyret; /* Bilan de consultation */ + +#define SERIALIZABLE_OBJECT_LOAD_WRAPPER PYTHON_WRAPPER_DEF \ +( \ + _load, "$self, storage, fd, /", \ + METH_VARARGS, \ + "Abstract method used to load an object definition from a data stream.\n" \ + "\n" \ + "The *storage* is a pychrysalide.glibext.ObjectStorage instance" \ + " provided to store inner objects. The *fd* argument is an integer value" \ + " provided as a file descriptor which as to be kept open after" \ + " processing.\n" \ + "\n" \ + "The result is a boolean indicating the status of the operation." \ +) + + result = false; + + gstate = PyGILState_Ensure(); + + pyobj = pygobject_new(G_OBJECT(object)); + + if (has_python_method(pyobj, "_load")) + { + args = PyTuple_New(2); + PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(storage))); + PyTuple_SetItem(args, 1, PyLong_FromLong(fd)); + + pyret = run_python_method(pyobj, "_load", args); + + result = (pyret == Py_True ? true : false); + + Py_XDECREF(pyret); + + Py_DECREF(args); + + } + + Py_DECREF(pyobj); + + PyGILState_Release(gstate); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : object = instruction d'assemblage à consulter. * +* storage = conservateur de données à manipuler. * +* fd = flux ouvert en écriture. * +* * +* Description : Sauvegarde un objet dans un flux de données. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool py_serializable_object_store_wrapper(const GSerializableObject *object, GObjectStorage *storage, int fd) +{ + bool result; /* Bilan à retourner */ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ + PyObject *args; /* Arguments pour l'appel */ + PyObject *pyobj; /* Objet Python concerné */ + PyObject *pyret; /* Bilan de consultation */ + +#define SERIALIZABLE_OBJECT_STORE_WRAPPER PYTHON_WRAPPER_DEF \ +( \ + _store, "$self, storage, fd, /", \ + METH_VARARGS, \ + "Abstract method used to store an object definition into a data stream.\n" \ + "\n" \ + "The *storage* is a pychrysalide.glibext.ObjectStorage instance" \ + " provided to store inner objects. The *fd* argument is an integer value" \ + " provided as a file descriptor which as to be kept open after" \ + " processing.\n" \ + "\n" \ + "The result is a boolean indicating the status of the operation." \ +) + + result = false; + + gstate = PyGILState_Ensure(); + + pyobj = pygobject_new(G_OBJECT(object)); + + if (has_python_method(pyobj, "_store")) + { + args = PyTuple_New(2); + PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(storage))); + PyTuple_SetItem(args, 1, PyLong_FromLong(fd)); + + pyret = run_python_method(pyobj, "_store", args); + + result = (pyret == Py_True ? true : false); + + Py_XDECREF(pyret); + + Py_DECREF(args); + + } + + Py_DECREF(pyobj); + + PyGILState_Release(gstate); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* CONNEXION AVEC L'API DE PYTHON */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : self = classe représentant un générateur à manipuler. * +* args = arguments fournis à l'appel. * +* * +* Description : Charge un objet depuis un flux de données. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool py_serializable_object_load(PyObject *self, PyObject *args) +{ + PyObject *result; /* Bilan à retourner */ + GObjectStorage *storage; /* Conservateur à manipuler */ + int fd; /* Flux ouvert (en lecture) */ + int ret; /* Bilan de lecture des args. */ + GSerializableObject *object; /* Version native */ + bool status; /* Bilan de l'opération */ + +#define SERIALIZABLE_OBJECT_LOAD_METHOD PYTHON_METHOD_DEF \ +( \ + load, "$self, storage, fd, /", \ + METH_VARARGS, py_serializable_object, \ + "Load an object definition from a data stream.\n" \ + "\n" \ + "The *storage* is a pychrysalide.glibext.ObjectStorage instance" \ + " provided to store inner objects. The *fd* argument is an integer value" \ + " used as a file descriptor for writing data\n" \ + "\n" \ + "The result is a boolean indicating the status of the operation." \ +) + + ret = PyArg_ParseTuple(args, "O&i", convert_to_object_storage, &storage, &fd); + if (!ret) return NULL; + + object = G_SERIALIZABLE_OBJECT(pygobject_get(self)); + + status = g_serializable_object_load(object, storage, fd); + + result = status ? Py_True : Py_False; + Py_INCREF(result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = classe représentant un générateur à manipuler. * +* args = arguments fournis à l'appel. * +* * +* Description : Sauvegarde un objet dans un flux de données. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool py_serializable_object_store(PyObject *self, PyObject *args) +{ + PyObject *result; /* Bilan à retourner */ + GObjectStorage *storage; /* Conservateur à manipuler */ + int fd; /* Flux ouvert (en lecture) */ + int ret; /* Bilan de lecture des args. */ + GSerializableObject *object; /* Version native */ + bool status; /* Bilan de l'opération */ + +#define SERIALIZABLE_OBJECT_STORE_METHOD PYTHON_METHOD_DEF \ +( \ + store, "$self, storage, fd, /", \ + METH_VARARGS, py_serializable_object, \ + "Store an object definition into a data stream.\n" \ + "\n" \ + "The *storage* is a pychrysalide.glibext.ObjectStorage instance" \ + " provided to store inner objects. The *fd* argument is an integer value" \ + " used as a file descriptor for writing data\n" \ + "\n" \ + "The result is a boolean indicating the status of the operation." \ +) + + ret = PyArg_ParseTuple(args, "O&i", convert_to_object_storage, &storage, &fd); + if (!ret) return NULL; + + object = G_SERIALIZABLE_OBJECT(pygobject_get(self)); + + status = g_serializable_object_store(object, storage, fd); + + result = status ? Py_True : Py_False; + Py_INCREF(result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_serializable_object_type(void) +{ + static PyMethodDef py_serializable_object_methods[] = { + SERIALIZABLE_OBJECT_LOAD_WRAPPER, + SERIALIZABLE_OBJECT_STORE_WRAPPER, + SERIALIZABLE_OBJECT_LOAD_METHOD, + SERIALIZABLE_OBJECT_STORE_METHOD, + { NULL } + }; + + static PyGetSetDef py_serializable_object_getseters[] = { + { NULL } + }; + + static PyTypeObject py_serializable_object_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.glibext.SerializableObject", + .tp_basicsize = sizeof(PyObject), + + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + + .tp_doc = SERIALIZABLE_OBJECT_DOC, + + .tp_methods = py_serializable_object_methods, + .tp_getset = py_serializable_object_getseters, + + }; + + return &py_serializable_object_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide....SerializableObject'.* +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_python_serializable_object_is_registered(void) +{ + PyTypeObject *type; /* Type 'SerializableObject' */ + PyObject *module; /* Module à recompléter */ + PyObject *dict; /* Dictionnaire du module */ + + static GInterfaceInfo info = { /* Paramètres d'inscription */ + + .interface_init = (GInterfaceInitFunc)py_serializable_object_interface_init, + .interface_finalize = NULL, + .interface_data = NULL, + + }; + + type = get_python_serializable_object_type(); + + if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) + { + module = get_access_to_python_module("pychrysalide.glibext"); + + dict = PyModule_GetDict(module); + + if (!register_interface_for_pygobject(dict, G_TYPE_SERIALIZABLE_OBJECT, type, &info)) + return false; + + } + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : arg = argument quelconque à tenter de convertir. * +* dst = destination des valeurs récupérées en cas de succès. * +* * +* Description : Tente de convertir en objet adapté à une mise en cache. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_serializable_object(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + result = PyObject_IsInstance(arg, (PyObject *)get_python_serializable_object_type()); + + switch (result) + { + case -1: + /* L'exception est déjà fixée par Python */ + result = 0; + break; + + case 0: + PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to serializable object"); + break; + + case 1: + *((GSerializableObject **)dst) = G_SERIALIZABLE_OBJECT(pygobject_get(arg)); + break; + + default: + assert(false); + break; + + } + + return result; + +} diff --git a/plugins/pychrysalide/glibext/serialize.h b/plugins/pychrysalide/glibext/serialize.h new file mode 100644 index 0000000..90688ba --- /dev/null +++ b/plugins/pychrysalide/glibext/serialize.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * serialize.h - prototypes pour l'équivalent Python du fichier "glibext/serialize.h" + * + * Copyright (C) 2020-2025 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_PYCHRYSALIDE_GLIBEXT_SERIALIZE_H +#define _PLUGINS_PYCHRYSALIDE_GLIBEXT_SERIALIZE_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_serializable_object_type(void); + +/* Prend en charge l'objet 'pychrysalide.glibext.SerializableObject'. */ +bool ensure_python_serializable_object_is_registered(void); + +/* Tente de convertir en objet adapté à une mise en cache. */ +int convert_to_serializable_object(PyObject *, void *); + + + +#endif /* _PLUGINS_PYCHRYSALIDE_GLIBEXT_SERIALIZE_H */ diff --git a/plugins/pychrysalide/glibext/storage.c b/plugins/pychrysalide/glibext/storage.c new file mode 100644 index 0000000..f2962bf --- /dev/null +++ b/plugins/pychrysalide/glibext/storage.c @@ -0,0 +1,572 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * storage.c - équivalent Python du fichier "glibext/storage.c" + * + * Copyright (C) 2020-2025 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "storage.h" + + +#include <assert.h> +#include <pygobject.h> + + +#include <glibext/storage-int.h> + + +#include "serialize.h" +#include "../access.h" +#include "../helpers.h" + + + +/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */ + + +CREATE_DYN_CONSTRUCTOR(object_storage, G_TYPE_OBJECT_STORAGE); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_object_storage_init(PyObject *, PyObject *, PyObject *); + + + +/* -------------------------- TAMPON POUR CODE DESASSEMBLE -------------------------- */ + + +/* Charge le support d'une conservation d'objets en place. */ +static PyObject *py_object_storage_load(PyObject *, PyObject *); + +/* Sauvegarde le support d'une conservation d'objets en place. */ +static PyObject *py_object_storage_store(PyObject *, PyObject *); + +/* Charge un objet à partir de données rassemblées. */ +static PyObject *py_object_storage_load_object(PyObject *, PyObject *); + +/* Charge un objet interne à partir de données rassemblées. */ +static PyObject *py_object_storage_unpack_object(PyObject *, PyObject *); + +/* Sauvegarde un object sous forme de données rassemblées. */ +static PyObject *py_object_storage_store_object(PyObject *, PyObject *); + + + +/* ---------------------------------------------------------------------------------- */ +/* GLUE POUR CREATION DEPUIS PYTHON */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* 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_object_storage_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + const char *type; /* Type global de conservation */ + unsigned char version; /* Version de ce type */ + const char *uid; /* Identifiant de distinction */ + int ret; /* Bilan de lecture des args. */ + GObjectStorage *storage; /* Mécanismes natifs */ + +#define OBJECT_STORAGE_DOC \ + "The ObjectStorage object manages the generic storage of GLib" \ + " objects through serialization.\n" \ + "\n" \ + "Instances can be created using the following constructor:\n" \ + "\n" \ + " ObjectStorage(type, version uid)" \ + "\n" \ + "Where *type* is a short string describing the storage kind," \ + " *version* provides a version control for this type and *uid* is" \ + " an arbitrary unique identifier used for creating temporary files." + + /* Récupération des paramètres */ + + ret = PyArg_ParseTuple(args, "sbs", &type, &version, &uid); + if (!ret) return -1; + + /* Initialisation d'un objet GLib */ + + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; + + /* Eléments de base */ + + storage = G_OBJECT_STORAGE(pygobject_get(self)); + + if (!g_object_storage_create(storage, type, version, uid)) + return -1; + + return 0; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* TAMPON POUR CODE DESASSEMBLE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : self = classe représentant une mémorisation de types. * +* args = arguments fournis à l'appel. * +* * +* Description : Charge le support d'une conservation d'objets en place. * +* * +* Retour : Gestionnaire de conservations construit ou None si erreur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_object_storage_load(PyObject *self, PyObject *args) +{ + PyObject *result; /* Emplacement à retourner */ + const char *filename; /* Fichier de source à traiter */ + int ret; /* Bilan de lecture des args. */ + GObjectStorage *storage; /* Mécanismes natifs */ + +#define OBJECT_STORAGE_LOAD_METHOD PYTHON_METHOD_DEF \ +( \ + load, "filename, /", \ + METH_STATIC | METH_VARARGS, py_object_storage, \ + "Construct a new storage from a filename.\n" \ + "\n" \ + "The *filename* argument points to the source file to" \ + " read.\n" \ + "\n" \ + "The result is a new pychrysalide.glibext.ObjectStorage" \ + " object on success, *None* otherwise." \ +) + + ret = PyArg_ParseTuple(args, "s", &filename); + if (!ret) return NULL; + + storage = g_object_storage_load(filename); + + if (storage == NULL) + { + result = Py_None; + Py_INCREF(result); + } + else + { + result = pygobject_new(G_OBJECT(storage)); + unref_object(storage); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = classe représentant une mémorisation de types. * +* args = arguments fournis à l'appel. * +* * +* Description : Sauvegarde le support d'une conservation d'objets en place. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_object_storage_store(PyObject *self, PyObject *args) +{ + PyObject *result; /* Emplacement à retourner */ + const char *filename; /* Fichier de destination */ + int ret; /* Bilan de lecture des args. */ + GObjectStorage *storage; /* Mécanismes natifs */ + bool status; /* Bilan de l'opération */ + +#define OBJECT_STORAGE_STORE_METHOD PYTHON_METHOD_DEF \ +( \ + store, "$self, filename, /", \ + METH_VARARGS, py_object_storage, \ + "Save a storage into a file.\n" \ + "\n" \ + "The *filename* argument points to the destination" \ + " file to write.\n" \ + "\n" \ + "The result is *True* on success, *False* otherwise." \ +) + + ret = PyArg_ParseTuple(args, "s", &filename); + if (!ret) return NULL; + + storage = G_OBJECT_STORAGE(pygobject_get(self)); + + status = g_object_storage_store(storage, filename); + + result = status ? Py_True : Py_False; + Py_INCREF(result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = classe représentant une mémorisation de types. * +* args = arguments fournis à l'appel. * +* * +* Description : Charge un objet à partir de données rassemblées. * +* * +* Retour : Objet restauré en mémoire ou None en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_object_storage_load_object(PyObject *self, PyObject *args) +{ + PyObject *result; /* Bilan à retourner */ + const char *name; /* Désignation de groupe */ + unsigned long long pos; /* Emplacement des données */ + int ret; /* Bilan de lecture des args. */ + GObjectStorage *storage; /* Mécanismes natifs */ + GSerializableObject *object; /* Objet reconstruit ou NULL */ + +#define OBJECT_STORAGE_LOAD_OBJECT_METHOD PYTHON_METHOD_DEF \ +( \ + load_object, "$self, name, pos, /", \ + METH_VARARGS, py_object_storage, \ + "Load an object from serialized data.\n" \ + "\n" \ + "The *name* is a string label for the group of target objects and" \ + " *pos* is an offset into the data stream indicating the start of" \ + " the data to unserialize.\n" \ + "\n" \ + "The result is a pychrysalide.analysis.storage.SerializableObject" \ + " instancet in case of success, or *None* in case of failure." \ +) + + ret = PyArg_ParseTuple(args, "sK", &name, &pos); + if (!ret) return NULL; + + storage = G_OBJECT_STORAGE(pygobject_get(self)); + + object = g_object_storage_load_object(storage, name, pos); + + if (object != NULL) + result = pygobject_new(G_OBJECT(object)); + else + { + result = Py_None; + Py_INCREF(result); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = classe représentant une mémorisation de types. * +* args = arguments fournis à l'appel. * +* * +* Description : Charge un objet interne à partir de données rassemblées. * +* * +* Retour : Objet restauré en mémoire ou None en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_object_storage_unpack_object(PyObject *self, PyObject *args) +{ + PyObject *result; /* Bilan à retourner */ + int fd; /* Flux de fonnées courant */ + const char *name; /* Désignation de groupe */ + int ret; /* Bilan de lecture des args. */ + GObjectStorage *storage; /* Mécanismes natifs */ + GSerializableObject *object; /* Objet reconstruit ou NULL */ + +#define OBJECT_STORAGE_UNPACK_OBJECT_METHOD PYTHON_METHOD_DEF \ +( \ + unpack_object, "$self, fd, name, /", \ + METH_VARARGS, py_object_storage, \ + "Load an object from a reference to serialized data.\n" \ + "\n" \ + "The *fd* argument is a file descriptor pointing to the data" \ + " stream for a current object being restored. A reference to" \ + " another object belonging to a group pointed by the string *name*" \ + " should be available at the current read position for this data" \ + " stream.\n" \ + "\n" \ + "The result is a pychrysalide.analysis.storage.SerializableObject" \ + " instancet in case of success, or *None* in case of failure." \ +) + + ret = PyArg_ParseTuple(args, "is", &fd, &name); + if (!ret) return NULL; + + storage = G_OBJECT_STORAGE(pygobject_get(self)); + + object = g_object_storage_unpack_object(storage, fd, name); + + if (object != NULL) + result = pygobject_new(G_OBJECT(object)); + else + { + result = Py_None; + Py_INCREF(result); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = classe représentant une mémorisation de types. * +* args = arguments fournis à l'appel. * +* * +* Description : Sauvegarde un object sous forme de données rassemblées. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_object_storage_store_object(PyObject *self, PyObject *args) +{ + PyObject *result; /* Emplacement à retourner */ + const char *name; /* Désignation de groupe */ + GSerializableObject *object; /* Objet à traiter */ + int ret; /* Bilan de lecture des args. */ + GObjectStorage *storage; /* Mécanismes natifs */ + off64_t pos; /* Emplacement d'enregistrement*/ + bool status; /* Bilan de l'opération */ + +#define OBJECT_STORAGE_STORE_OBJECT_METHOD PYTHON_METHOD_DEF \ +( \ + store_object, "$self, name, object, /", \ + METH_VARARGS, py_object_storage, \ + "Save an object as serialized data.\n" \ + "\n" \ + "The *name* is a string label for the group of target objects" \ + " and the processed *object* has to be a" \ + " pychrysalide.analysis.storage.SerializableObject instance.\n" \ + "\n" \ + "The result is the position of the data for stored object," \ + " provided as an integer offset, in case of success or *None*" \ + " in case of failure." \ +) + + ret = PyArg_ParseTuple(args, "sO&", &name, convert_to_serializable_object, &object); + if (!ret) return NULL; + + storage = G_OBJECT_STORAGE(pygobject_get(self)); + + status = g_object_storage_store_object(storage, name, object, &pos); + + if (status) + result = PyLong_FromUnsignedLongLong((unsigned long long)pos); + else + { + result = Py_None; + Py_INCREF(result); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_object_storage_type(void) +{ + static PyMethodDef py_object_storage_methods[] = { + OBJECT_STORAGE_LOAD_METHOD, + OBJECT_STORAGE_STORE_METHOD, + OBJECT_STORAGE_LOAD_OBJECT_METHOD, + OBJECT_STORAGE_UNPACK_OBJECT_METHOD, + OBJECT_STORAGE_STORE_OBJECT_METHOD, + { NULL } + }; + + static PyGetSetDef py_object_storage_getseters[] = { + { NULL } + }; + + static PyTypeObject py_object_storage_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.glibext.ObjectStorage", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT, + + .tp_doc = OBJECT_STORAGE_DOC, + + .tp_methods = py_object_storage_methods, + .tp_getset = py_object_storage_getseters, + + .tp_init = py_object_storage_init, + .tp_new = py_object_storage_new + + }; + + return &py_object_storage_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide.glibext.ObjectStorage'.* +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_python_object_storage_is_registered(void) +{ + PyTypeObject *type; /* Type Python 'ObjectStorage' */ + PyObject *module; /* Module à recompléter */ + PyObject *dict; /* Dictionnaire du module */ + + type = get_python_object_storage_type(); + + if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) + { + module = get_access_to_python_module("pychrysalide.glibext"); + + dict = PyModule_GetDict(module); + + if (!register_class_for_pygobject(dict, G_TYPE_OBJECT_STORAGE, type)) + return false; + + } + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : arg = argument quelconque à tenter de convertir. * +* dst = destination des valeurs récupérées en cas de succès. * +* * +* Description : Tente de convertir en conservateur d'objets. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_object_storage(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + result = PyObject_IsInstance(arg, (PyObject *)get_python_object_storage_type()); + + switch (result) + { + case -1: + /* L'exception est déjà fixée par Python */ + result = 0; + break; + + case 0: + PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to object storage"); + break; + + case 1: + *((GObjectStorage **)dst) = G_OBJECT_STORAGE(pygobject_get(arg)); + break; + + default: + assert(false); + break; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : arg = argument quelconque à tenter de convertir. * +* dst = destination des valeurs récupérées en cas de succès. * +* * +* Description : Tente de convertir en conservateur d'objets ou NULL. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_object_storage_or_none(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + if (arg == Py_None) + { + *((GTypeMemory **)dst) = NULL; + result = 1; + } + + else + result = convert_to_object_storage(arg, dst); + + return result; + +} diff --git a/plugins/pychrysalide/glibext/storage.h b/plugins/pychrysalide/glibext/storage.h new file mode 100644 index 0000000..681f99a --- /dev/null +++ b/plugins/pychrysalide/glibext/storage.h @@ -0,0 +1,48 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * storage.h - prototypes pour l'équivalent Python du fichier "glibext/storage.h" + * + * Copyright (C) 2020-2025 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_PYCHRYSALIDE_GLIBEXT_STORAGE_H +#define _PLUGINS_PYCHRYSALIDE_GLIBEXT_STORAGE_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_object_storage_type(void); + +/* Prend en charge l'objet 'pychrysalide.glibext.ObjectStorage'. */ +bool ensure_python_object_storage_is_registered(void); + +/* Tente de convertir en conservateur d'objets. */ +int convert_to_object_storage(PyObject *, void *); + +/* Tente de convertir en conservateur d'objets ou NULL. */ +int convert_to_object_storage_or_none(PyObject *, void *); + + + +#endif /* _PLUGINS_PYCHRYSALIDE_GLIBEXT_STORAGE_H */ diff --git a/plugins/pychrysalide/glibext/tpmem.c b/plugins/pychrysalide/glibext/tpmem.c new file mode 100644 index 0000000..ae07008 --- /dev/null +++ b/plugins/pychrysalide/glibext/tpmem.c @@ -0,0 +1,508 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * tpmem.c - équivalent Python du fichier "analysis/storage/tpmem.c" + * + * Copyright (C) 2020 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "tpmem.h" + + +#include <pygobject.h> + + +#include <analysis/storage/tpmem.h> +#include <plugins/dt.h> + + +#include "../../access.h" +#include "../../helpers.h" +#include "../../common/packed.h" + + + +/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */ + + +/* Accompagne la création d'une instance dérivée en Python. */ +static PyObject *py_type_memory_new(PyTypeObject *, PyObject *, PyObject *); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_type_memory_init(PyObject *, PyObject *, PyObject *); + + + +/* -------------------------- TAMPON POUR CODE DESASSEMBLE -------------------------- */ + + +/* Apprend tous les types mémorisés dans un tampon. */ +static PyObject *py_type_memory_load_types(PyObject *, PyObject *); + +/* Crée une nouvelle instance d'objet à partir de son type. */ +static PyObject *py_type_memory_create_object(PyObject *, PyObject *); + +/* Sauvegarde le type d'un objet instancié. */ +static PyObject *py_type_memory_store_object_gtype(PyObject *, PyObject *); + +/* Enregistre tous les types mémorisés dans un tampon. */ +static PyObject *py_type_memory_store_types(PyObject *, PyObject *); + + + +/* ---------------------------------------------------------------------------------- */ +/* 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_type_memory_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_type_memory_type(); + + if (type == base) + goto simple_way; + + /* Mise en place d'un type dédié */ + + first_time = (g_type_from_name(type->tp_name) == 0); + + gtype = build_dynamic_type(G_TYPE_TYPE_MEMORY, type->tp_name, NULL, NULL, NULL); + + if (first_time) + { + status = register_class_for_dynamic_pygobject(gtype, type); + + if (!status) + { + result = NULL; + goto exit; + } + + } + + /* On crée, et on laisse ensuite la main à PyGObject_Type.tp_init() */ + + simple_way: + + result = PyType_GenericNew(type, args, kwds); + + exit: + + return result; + +} + + +/****************************************************************************** +* * +* 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_type_memory_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + int ret; /* Bilan de lecture des args. */ + +#define TYPE_MEMORY_DOC \ + "The TypeMemory remembers all the types of objects involved in" \ + " a serialization process.\n" \ + "\n" \ + "Instances can be created using the following constructor:\n" \ + "\n" \ + " TypeMemory()" \ + + /* Initialisation d'un objet GLib */ + + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; + + return 0; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* TAMPON POUR CODE DESASSEMBLE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : self = classe représentant une mémorisation de types. * +* args = arguments fournis à l'appel. * +* * +* Description : Apprend tous les types mémorisés dans un tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_type_memory_load_types(PyObject *self, PyObject *args) +{ + PyObject *result; /* Bilan à retourner */ + packed_buffer_t *pbuf; /* Tampon à consulter */ + int ret; /* Bilan de lecture des args. */ + GTypeMemory *tpmem; /* Mémorisation native */ + bool status; /* Bilan de l'opération */ + +#define TYPE_MEMORY_LOAD_TYPES_METHOD PYTHON_METHOD_DEF \ +( \ + load_types, "$self, pbuf", \ + METH_VARARGS, py_type_memory, \ + "Read types from a buffer.\n" \ + "\n" \ + "This operation is usually handled internally by the" \ + " Chrysalide's core.\n" \ + "\n" \ + "The *pbuf* parameter is a pychrysalide.common.PackedBuffer"\ + " instance providing buffered data to read." \ + "\n" \ + "The result is a boolean value indicating the status of" \ + " the operation: True for success, False for failure." \ +) + + ret = PyArg_ParseTuple(args, "O&", convert_to_packed_buffer, &pbuf); + if (!ret) return NULL; + + tpmem = G_TYPE_MEMORY(pygobject_get(self)); + + status = g_type_memory_load_types(tpmem, pbuf); + + result = status ? Py_True : Py_False; + Py_INCREF(result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = classe représentant une mémorisation de types. * +* args = arguments fournis à l'appel. * +* * +* Description : Crée une nouvelle instance d'objet à partir de son type. * +* * +* Retour : Instance issue de l'opération ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_type_memory_create_object(PyObject *self, PyObject *args) +{ + PyObject *result; /* Instance à retourner */ + packed_buffer_t *pbuf; /* Tampon à consulter */ + int ret; /* Bilan de lecture des args. */ + GTypeMemory *tpmem; /* Mémorisation native */ + GObject *obj; /* Instance retournée */ + +#define TYPE_MEMORY_CREATE_OBJECT_METHOD PYTHON_METHOD_DEF \ +( \ + create_object, "$self, pbuf", \ + METH_VARARGS, py_type_memory, \ + "Create a new GLib object from serialized data.\n" \ + "\n" \ + "The *pbuf* parameter is a pychrysalide.common.PackedBuffer" \ + " instance providing buffered data to read." \ + "\n" \ + "The result is a Python object linked to a native GLib" \ + " object instance." \ +) + + ret = PyArg_ParseTuple(args, "O&", convert_to_packed_buffer, &pbuf); + if (!ret) return NULL; + + tpmem = G_TYPE_MEMORY(pygobject_get(self)); + + obj = g_type_memory_create_object(tpmem, pbuf); + + result = pygobject_new(obj); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = classe représentant une mémorisation de types. * +* args = arguments fournis à l'appel. * +* * +* Description : Sauvegarde le type d'un objet instancié. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_type_memory_store_object_gtype(PyObject *self, PyObject *args) +{ + PyObject *result; /* Bilan à retourner */ + GObject *obj; /* Instance à traiter */ + packed_buffer_t *pbuf; /* Tampon à consulter */ + int ret; /* Bilan de lecture des args. */ + GTypeMemory *tpmem; /* Mémorisation native */ + bool status; /* Bilan de l'opération */ + +#define TYPE_MEMORY_STORE_OBJECT_GTYPE_METHOD PYTHON_METHOD_DEF \ +( \ + store_object_gtype, "$self, obj, pbuf", \ + METH_VARARGS, py_type_memory, \ + "Create a new GLib object from serialized data.\n" \ + "\n" \ + "The *obj* parameter is the Python version of the GObject" \ + " whose type is to process and the *pbuf* parameter is a" \ + " pychrysalide.common.PackedBuffer instance providing buffered" \ + " data to extend." \ + "\n" \ + "The result is a boolean value indicating the status of the" \ + " operation: True for success, False for failure." \ +) + + ret = PyArg_ParseTuple(args, "O!O&", PyGObject_Type, &obj, convert_to_packed_buffer, &pbuf); + if (!ret) return NULL; + + tpmem = G_TYPE_MEMORY(pygobject_get(self)); + + status = g_type_memory_store_object_gtype(tpmem, obj, pbuf); + + result = status ? Py_True : Py_False; + Py_INCREF(result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = classe représentant une mémorisation de types. * +* args = arguments fournis à l'appel. * +* * +* Description : Enregistre tous les types mémorisés dans un tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_type_memory_store_types(PyObject *self, PyObject *args) +{ + PyObject *result; /* Bilan à retourner */ + packed_buffer_t *pbuf; /* Tampon à consulter */ + int ret; /* Bilan de lecture des args. */ + GTypeMemory *tpmem; /* Mémorisation native */ + bool status; /* Bilan de l'opération */ + +#define TYPE_MEMORY_STORE_TYPES_METHOD PYTHON_METHOD_DEF \ +( \ + store_types, "$self, pbuf", \ + METH_VARARGS, py_type_memory, \ + "Write types into a buffer.\n" \ + "\n" \ + "This operation is usually handled internally by the" \ + " Chrysalide's core.\n" \ + "\n" \ + "The *pbuf* parameter is a pychrysalide.common.PackedBuffer"\ + " instance providing buffered data to read." \ + "\n" \ + "The result is a boolean value indicating the status of" \ + " the operation: True for success, False for failure." \ +) + + ret = PyArg_ParseTuple(args, "O&", convert_to_packed_buffer, &pbuf); + if (!ret) return NULL; + + tpmem = G_TYPE_MEMORY(pygobject_get(self)); + + status = g_type_memory_store_types(tpmem, pbuf); + + result = status ? Py_True : Py_False; + Py_INCREF(result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Fournit un accès à une définition de type à diffuser. * +* * +* Retour : Définition d'objet pour Python. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PyTypeObject *get_python_type_memory_type(void) +{ + static PyMethodDef py_type_memory_methods[] = { + TYPE_MEMORY_LOAD_TYPES_METHOD, + TYPE_MEMORY_CREATE_OBJECT_METHOD, + TYPE_MEMORY_STORE_OBJECT_GTYPE_METHOD, + TYPE_MEMORY_STORE_TYPES_METHOD, + { NULL } + }; + + static PyGetSetDef py_type_memory_getseters[] = { + { NULL } + }; + + static PyTypeObject py_type_memory_type = { + + PyVarObject_HEAD_INIT(NULL, 0) + + .tp_name = "pychrysalide.analysis.storage.TypeMemory", + .tp_basicsize = sizeof(PyGObject), + + .tp_flags = Py_TPFLAGS_DEFAULT, + + .tp_doc = TYPE_MEMORY_DOC, + + .tp_methods = py_type_memory_methods, + .tp_getset = py_type_memory_getseters, + + .tp_init = py_type_memory_init, + .tp_new = py_type_memory_new + + }; + + return &py_type_memory_type; + +} + + +/****************************************************************************** +* * +* Paramètres : module = module dont la définition est à compléter. * +* * +* Description : Prend en charge l'objet 'pychrysalide.analysis...TypeMemory'.* +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool ensure_python_type_memory_is_registered(void) +{ + PyTypeObject *type; /* Type Python 'BufferCache' */ + PyObject *module; /* Module à recompléter */ + PyObject *dict; /* Dictionnaire du module */ + + type = get_python_type_memory_type(); + + if (!PyType_HasFeature(type, Py_TPFLAGS_READY)) + { + module = get_access_to_python_module("pychrysalide.analysis.storage"); + + dict = PyModule_GetDict(module); + + if (!register_class_for_pygobject(dict, G_TYPE_TYPE_MEMORY, type)) + return false; + + } + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : arg = argument quelconque à tenter de convertir. * +* dst = destination des valeurs récupérées en cas de succès. * +* * +* Description : Tente de convertir en mémorisation de types. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_type_memory(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + + result = PyObject_IsInstance(arg, (PyObject *)get_python_type_memory_type()); + + switch (result) + { + case -1: + /* L'exception est déjà fixée par Python */ + result = 0; + break; + + case 0: + PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to buffer cache"); + break; + + case 1: + *((GTypeMemory **)dst) = G_TYPE_MEMORY(pygobject_get(arg)); + break; + + default: + assert(false); + break; + + } + + return result; + +} diff --git a/plugins/pychrysalide/glibext/tpmem.h b/plugins/pychrysalide/glibext/tpmem.h new file mode 100644 index 0000000..1085632 --- /dev/null +++ b/plugins/pychrysalide/glibext/tpmem.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * tpmem.h - prototypes pour l'équivalent Python du fichier "analysis/storage/tpmem.h" + * + * Copyright (C) 2020 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_PYCHRYSALIDE_ANALYSIS_STORAGE_TPMEM_H +#define _PLUGINS_PYCHRYSALIDE_ANALYSIS_STORAGE_TPMEM_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_type_memory_type(void); + +/* Prend en charge l'objet 'pychrysalide.analysis.storage.TypeMemory'. */ +bool ensure_python_type_memory_is_registered(void); + +/* Tente de convertir en mémorisation de types. */ +int convert_to_type_memory(PyObject *, void *); + + + +#endif /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_STORAGE_TPMEM_H */ |