summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2020-07-12 13:52:22 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2020-07-12 13:52:22 (GMT)
commit2bd3ea7249d1234204c1b70abac8bc46e221fb95 (patch)
treef6b0f71d430bda2e8d762afbf5d084ac58cee640
parent6ea1b9a8550adf84cde510c2d4446c5120c4d065 (diff)
Improved the API for loaded contents.
-rw-r--r--plugins/pychrysalide/analysis/loaded.c791
-rw-r--r--plugins/pychrysalide/analysis/storage/serialize.c2
-rw-r--r--plugins/pychrysalide/gtkext/dockable.c32
-rw-r--r--plugins/pychrysalide/gtkext/graph/cluster.c6
-rw-r--r--plugins/pychrysalide/helpers.c56
-rw-r--r--plugins/pychrysalide/helpers.h3
-rw-r--r--src/analysis/binary.c30
-rw-r--r--src/analysis/content.c5
-rw-r--r--src/analysis/loaded-int.h6
-rw-r--r--src/analysis/loaded.c20
-rw-r--r--src/analysis/loaded.h6
-rw-r--r--src/analysis/project.c11
-rw-r--r--src/gui/dialogs/loading.c12
-rw-r--r--src/gui/editor.c8
-rw-r--r--src/gui/menus/project.c4
-rw-r--r--src/gui/menus/view.c6
-rw-r--r--src/gui/panel.c4
17 files changed, 896 insertions, 106 deletions
diff --git a/plugins/pychrysalide/analysis/loaded.c b/plugins/pychrysalide/analysis/loaded.c
index 768b11c..e3b2625 100644
--- a/plugins/pychrysalide/analysis/loaded.c
+++ b/plugins/pychrysalide/analysis/loaded.c
@@ -33,22 +33,52 @@
#include <i18n.h>
-#include <analysis/loaded.h>
+#include <analysis/loaded-int.h>
#include <core/global.h>
+#include "content.h"
#include "../access.h"
#include "../helpers.h"
-#define LOADED_CONTENT_DOC \
- "The LoadedContent interface is an intermediary level of abstraction" \
- " for all loaded binary contents to analyze." \
- "\n" \
- "No matter if the loaded content comes from an ELF file or XML data," \
- " some basic features are available here."
+/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */
+
+
+/* Procède à l'initialisation de l'interface de génération. */
+static void py_loaded_content_interface_init(GLoadedContentIface *, gpointer *);
+
+/* Fournit le contenu représenté de l'élément chargé. */
+static GBinContent *py_loaded_content_get_content_wrapper(const GLoadedContent *);
+
+/* Fournit le format associé à l'élément chargé. */
+static char *py_loaded_content_get_format_name_wrapper(const GLoadedContent *);
+
+/* Lance l'analyse propre à l'élément chargé. */
+static bool py_loaded_content_analyze_wrapper(GLoadedContent *, bool, bool, wgroup_id_t, GtkStatusStack *);
+/* Fournit le désignation associée à l'élément chargé. */
+static char *py_loaded_content_describe_wrapper(const GLoadedContent *, bool);
+
+/* Détermine le nombre de vues disponibles pour un contenu. */
+static unsigned int py_loaded_content_count_views_wrapper(const GLoadedContent *);
+
+/* Fournit le nom d'une vue donnée d'un contenu chargé. */
+static char *py_loaded_content_get_view_name_wrapper(const GLoadedContent *, unsigned int);
+
+/* Met en place la vue initiale pour un contenu chargé. */
+static GtkWidget *py_loaded_content_build_default_view_wrapper(GLoadedContent *);
+
+/* Met en place la vue demandée pour un contenu chargé. */
+static GtkWidget *py_loaded_content_build_view_wrapper(GLoadedContent *, unsigned int);
+
+/* Retrouve l'indice correspondant à la vue donnée d'un contenu. */
+static unsigned int py_loaded_content_get_view_index_wrapper(GLoadedContent *, GtkWidget *);
+
+
+
+/* ------------------------- CONNEXION AVEC L'API DE PYTHON ------------------------- */
/* Lance l'analyse propre à l'élément chargé. */
@@ -83,6 +113,690 @@ static PyObject *py_loaded_content_get_format_name(PyObject *, void *);
+/* ---------------------------------------------------------------------------------- */
+/* 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_loaded_content_interface_init(GLoadedContentIface *iface, gpointer *unused)
+{
+#define LOADED_CONTENT_DOC \
+ "The LoadedContent interface is an intermediary level of abstraction" \
+ " for all loaded binary contents to analyze." \
+ "\n" \
+ "No matter if the loaded content comes from an ELF file or XML data," \
+ " some basic features are available here." \
+ "\n" \
+ "A typical class declaration for a new implementation looks like:\n" \
+ "\n" \
+ " class NewImplem(GObject.Object, LoadedContent):\n" \
+ " ...\n" \
+ "\n" \
+ "The following methods have to be defined for new implementations:\n" \
+ "* pychrysalide.analysis.storage.LoadedContent._get_content();\n" \
+ "* pychrysalide.analysis.storage.LoadedContent._get_format_name();\n" \
+ "* pychrysalide.analysis.storage.LoadedContent._analyze();\n" \
+ "* pychrysalide.analysis.storage.LoadedContent._describe();\n" \
+ "* pychrysalide.analysis.storage.LoadedContent._count_views();\n" \
+ "* pychrysalide.analysis.storage.LoadedContent._get_view_name();\n" \
+ "* pychrysalide.analysis.storage.LoadedContent._build_default_view();\n"\
+ "* pychrysalide.analysis.storage.LoadedContent._build_view();\n" \
+ "* pychrysalide.analysis.storage.LoadedContent._get_view_index();\n"
+
+ iface->get_content = py_loaded_content_get_content_wrapper;
+ iface->get_format_name = py_loaded_content_get_format_name_wrapper;
+
+ iface->analyze = py_loaded_content_analyze_wrapper;
+
+ iface->describe = py_loaded_content_describe_wrapper;
+
+ iface->count_views = py_loaded_content_count_views_wrapper;
+ iface->get_view_name = py_loaded_content_get_view_name_wrapper;
+ iface->build_def_view = py_loaded_content_build_default_view_wrapper;
+ iface->build_view = py_loaded_content_build_view_wrapper;
+ iface->get_view_index = py_loaded_content_get_view_index_wrapper;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : content = élément chargé à manipuler. *
+* *
+* Description : Fournit le contenu représenté de l'élément chargé. *
+* *
+* Retour : Contenu représenté. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GBinContent *py_loaded_content_get_content_wrapper(const GLoadedContent *content)
+{
+ GBinContent *result; /* Contenu interne à renvoyer */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *pyret; /* Bilan de consultation */
+
+#define LOADED_CONTENT_GET_CONTENT_WRAPPER PYTHON_WRAPPER_DEF \
+( \
+ _get_content, "$self", \
+ METH_VARARGS, \
+ "Abstract method used to get the binary content linked to the" \
+ " loaded content. The result is provided as a" \
+ " pychrysalide.analysis.BinContent instance." \
+)
+
+ result = NULL;
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(content));
+
+ if (has_python_method(pyobj, "_get_content"))
+ {
+ pyret = run_python_method(pyobj, "_get_content", NULL);
+
+ if (pyret != NULL)
+ {
+ if (convert_to_binary_content(pyret, &result) != 1)
+ PyErr_Clear();
+
+ Py_DECREF(pyret);
+
+ }
+
+ }
+
+ Py_DECREF(pyobj);
+
+ PyGILState_Release(gstate);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : content = élément chargé à manipuler. *
+* *
+* Description : Fournit le format associé à l'élément chargé. *
+* *
+* Retour : Format associé à l'élément chargé. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *py_loaded_content_get_format_name_wrapper(const GLoadedContent *content)
+{
+ char *result; /* Contenu interne à renvoyer */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *pyret; /* Bilan de consultation */
+ int ret; /* Validité d'une conversion */
+
+#define LOADED_CONTENT_GET_FORMAT_NAME_WRAPPER PYTHON_WRAPPER_DEF \
+( \
+ _get_format_name, "$self", \
+ METH_VARARGS, \
+ "Abstract method used to provide the aw name of the format connected" \
+ " to the loaded content.\n" \
+ "\n" \
+ "The name associated to a loaded Elf binary is for instance 'elf'." \
+)
+
+ result = NULL;
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(content));
+
+ if (has_python_method(pyobj, "_get_format_name"))
+ {
+ pyret = run_python_method(pyobj, "_get_format_name", NULL);
+
+ if (pyret != NULL)
+ {
+ ret = PyUnicode_Check(pyret);
+
+ if (ret)
+ result = strdup(PyUnicode_AsUTF8(pyret));
+
+ Py_DECREF(pyret);
+
+ }
+
+ }
+
+ Py_DECREF(pyobj);
+
+ PyGILState_Release(gstate);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : content = élément chargé à manipuler. *
+* connect = organise le lancement des connexions aux serveurs. *
+* cache = précise si la préparation d'un rendu est demandée. *
+* gid = groupe de travail dédié. *
+* status = barre de statut à tenir informée. *
+* *
+* Description : Lance l'analyse propre à l'élément chargé. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool py_loaded_content_analyze_wrapper(GLoadedContent *content, bool connect, bool cache, wgroup_id_t gid, GtkStatusStack *status)
+{
+ bool result; /* Bilan à retourner */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *connect_obj; /* Ordre de connexion */
+ PyObject *cache_obj; /* Usage du cache */
+ PyObject *args; /* Arguments pour l'appel */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *pyret; /* Bilan de consultation */
+
+#define LOADED_CONTENT_ANALYZE_WRAPPER PYTHON_WRAPPER_DEF \
+( \
+ _analyze, "$self, connect, cache, gid, status", \
+ METH_VARARGS, \
+ "Abstract method used to start the analysis of the loaded binary." \
+ "\n" \
+ "The *connect* parameter defines if connections to database servers" \
+ " (internal and/or remote) will be established. The default value" \
+ " depends on the running mode: if the analysis is run from the GUI," \
+ " the binary will get connected to servers; in batch mode, no" \
+ " connection will be made." \
+ "\n" \
+ "The *cache* parameter rules the build of the cache for rendering" \
+ " lines. The same behavior relative to the running mode applies." \
+ "\n" \
+ "The identifier refers to the working queue used to process the" \
+ " analysis. A reference to the main status bar may also be provided," \
+ " as a pychrysalide.gtkext.StatusStack instance if running in" \
+ " graphical mode or None otherwise." \
+)
+
+ result = false;
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(content));
+
+ if (has_python_method(pyobj, "_analyze"))
+ {
+ connect_obj = connect ? Py_True : Py_False;
+ Py_INCREF(connect_obj);
+
+ cache_obj = cache ? Py_True : Py_False;
+ Py_INCREF(cache_obj);
+
+ args = PyTuple_New(4);
+ PyTuple_SetItem(args, 0, connect_obj);
+ PyTuple_SetItem(args, 1, cache_obj);
+ PyTuple_SetItem(args, 2, PyLong_FromUnsignedLong(gid));
+ PyTuple_SetItem(args, 3, pygobject_new(G_OBJECT(status)));
+
+ pyret = run_python_method(pyobj, "_analyze", args);
+
+ if (pyret != NULL)
+ {
+ result = (pyret == Py_True);
+ Py_DECREF(pyret);
+ }
+
+ Py_DECREF(args);
+
+ }
+
+ Py_DECREF(pyobj);
+
+ PyGILState_Release(gstate);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : content = élément chargé à consulter. *
+* full = précise s'il s'agit d'une version longue ou non. *
+* *
+* Description : Fournit le désignation associée à l'élément chargé. *
+* *
+* Retour : Description courante. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *py_loaded_content_describe_wrapper(const GLoadedContent *content, bool full)
+{
+ char *result; /* Description à retourner */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *full_obj; /* Précision sur la longueur */
+ PyObject *args; /* Arguments pour l'appel */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *pyret; /* Bilan de consultation */
+ int ret; /* Validité d'une conversion */
+
+#define LOADED_CONTENT_DESCRIBE_WRAPPER PYTHON_WRAPPER_DEF \
+( \
+ _describe, "$self, full", \
+ METH_VARARGS, \
+ "Abstract method used to describe the loaded content.\n" \
+ "\n" \
+ "The boolean *full* parameter shapes the size of the returned string.\n" \
+ "\n" \
+ "This method is mainly used to provide a label (or a tooltip text)" \
+ " for tabs in the graphical main window." \
+)
+
+ result = NULL;
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(content));
+
+ if (has_python_method(pyobj, "_describe"))
+ {
+ full_obj = full ? Py_True : Py_False;
+ Py_INCREF(full_obj);
+
+ args = PyTuple_New(1);
+ PyTuple_SetItem(args, 0, full_obj);
+
+ pyret = run_python_method(pyobj, "_describe", args);
+
+ if (pyret != NULL)
+ {
+ ret = PyUnicode_Check(pyret);
+
+ if (ret)
+ result = strdup(PyUnicode_AsUTF8(pyret));
+
+ Py_DECREF(pyret);
+
+ }
+
+ Py_DECREF(args);
+
+ }
+
+ Py_DECREF(pyobj);
+
+ PyGILState_Release(gstate);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : content = contenu chargé à consulter. *
+* *
+* Description : Détermine le nombre de vues disponibles pour un contenu. *
+* *
+* Retour : Quantité strictement positive. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static unsigned int py_loaded_content_count_views_wrapper(const GLoadedContent *content)
+{
+ unsigned int result; /* Quantité de vues à renvoyer */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *pyret; /* Bilan de consultation */
+ int ret; /* Validité d'une conversion */
+
+#define LOADED_CONTENT_COUNT_VIEWS_WRAPPER PYTHON_WRAPPER_DEF \
+( \
+ _count_views, "$self", \
+ METH_VARARGS, \
+ "Abstract method used to compute the quantity of available" \
+ " views for the loaded binary." \
+)
+
+ result = 0;
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(content));
+
+ if (has_python_method(pyobj, "_count_views"))
+ {
+ pyret = run_python_method(pyobj, "_count_views", NULL);
+
+ if (pyret != NULL)
+ {
+ ret = PyLong_Check(pyret);
+
+ if (ret)
+ result = PyLong_AsUnsignedLong(pyret);
+
+ Py_DECREF(pyret);
+
+ }
+
+ }
+
+ Py_DECREF(pyobj);
+
+ PyGILState_Release(gstate);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : content = contenu chargé à consulter. *
+* index = indice de la vue ciblée. *
+* *
+* Description : Fournit le nom d'une vue donnée d'un contenu chargé. *
+* *
+* Retour : Désignation humainement lisible. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *py_loaded_content_get_view_name_wrapper(const GLoadedContent *content, unsigned int index)
+{
+ char *result; /* Désignation à retourner */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *args; /* Arguments pour l'appel */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *pyret; /* Bilan de consultation */
+ int ret; /* Validité d'une conversion */
+
+#define LOADED_CONTENT_GET_VIEW_NAME_WRAPPER PYTHON_WRAPPER_DEF \
+( \
+ _get_view_name, "$self, index", \
+ METH_VARARGS, \
+ "Abstract method used to provide the human readable name for" \
+ " a given view of a loaded binary.\n" \
+ "\n" \
+ "Such a method is used in the graphical main window for" \
+ " building menu labels." \
+)
+
+ result = NULL;
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(content));
+
+ if (has_python_method(pyobj, "_get_view_name"))
+ {
+ args = PyTuple_New(1);
+ PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(index));
+
+ pyret = run_python_method(pyobj, "_get_view_name", args);
+
+ if (pyret != NULL)
+ {
+ ret = PyUnicode_Check(pyret);
+
+ if (ret)
+ result = strdup(PyUnicode_AsUTF8(pyret));
+
+ Py_DECREF(pyret);
+
+ }
+
+ Py_DECREF(args);
+
+ }
+
+ Py_DECREF(pyobj);
+
+ PyGILState_Release(gstate);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : content = contenu chargé à consulter. *
+* *
+* Description : Met en place la vue initiale pour un contenu chargé. *
+* *
+* Retour : Composant graphique nouveau. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GtkWidget *py_loaded_content_build_default_view_wrapper(GLoadedContent *content)
+{
+ GtkWidget *result; /* Support à retourner */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *pyret; /* Bilan de consultation */
+ int ret; /* Validité d'une conversion */
+
+#define LOADED_CONTENT_BUILD_DEFAULT_VIEW_WRAPPER PYTHON_WRAPPER_DEF \
+( \
+ _build_default_view, "$self", \
+ METH_VARARGS, \
+ "Abstract method used to build a new widget for the default graphical" \
+ " view of the loaded content." \
+ "\n" \
+ "This method is aimed to only be called from the GUI internals." \
+ " It provides the first view displayed in the main Chrysalide window" \
+ " after a binary loading." \
+)
+
+ result = NULL;
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(content));
+
+ if (has_python_method(pyobj, "_build_default_view"))
+ {
+ pyret = run_python_method(pyobj, "_build_default_view", NULL);
+
+ if (pyret != NULL)
+ {
+ ret = convert_to_gtk_widget(pyret, &result);
+
+ if (ret == 1)
+ g_object_ref(G_OBJECT(result));
+
+ Py_DECREF(pyret);
+
+ }
+
+ }
+
+ Py_DECREF(pyobj);
+
+ PyGILState_Release(gstate);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : content = contenu chargé à consulter. *
+* index = indice de la vue ciblée. *
+* *
+* Description : Met en place la vue demandée pour un contenu chargé. *
+* *
+* Retour : Composant graphique nouveau. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GtkWidget *py_loaded_content_build_view_wrapper(GLoadedContent *content, unsigned int index)
+{
+ GtkWidget *result; /* Support à retourner */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *args; /* Arguments pour l'appel */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *pyret; /* Bilan de consultation */
+ int ret; /* Validité d'une conversion */
+
+#define LOADED_CONTENT_BUILD_VIEW_WRAPPER PYTHON_WRAPPER_DEF \
+( \
+ _build_view, "$self, index", \
+ METH_VARARGS, \
+ "Abstract method used to build a new widget for a given graphical view" \
+ " of the loaded content.\n" \
+ "\n" \
+ "This method is aimed to only be called from the GUI internals." \
+ " It provides a view displayed in the main Chrysalide window" \
+ " once the binary is loaded." \
+)
+
+ result = NULL;
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(content));
+
+ if (has_python_method(pyobj, "_build_view"))
+ {
+ args = PyTuple_New(1);
+ PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(index));
+
+ pyret = run_python_method(pyobj, "_build_view", args);
+
+ if (pyret != NULL)
+ {
+ ret = convert_to_gtk_widget(pyret, &result);
+
+ if (ret == 1)
+ g_object_ref(G_OBJECT(result));
+
+ Py_DECREF(pyret);
+
+ }
+
+ Py_DECREF(args);
+
+ }
+
+ Py_DECREF(pyobj);
+
+ PyGILState_Release(gstate);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : content = contenu chargé à consulter. *
+* index = composant graphique en place. *
+* *
+* Description : Retrouve l'indice correspondant à la vue donnée d'un contenu.*
+* *
+* Retour : Indice de la vue représentée, ou -1 en cas d'erreur. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static unsigned int py_loaded_content_get_view_index_wrapper(GLoadedContent *content, GtkWidget *view)
+{
+ unsigned int result; /* Indice à retourner */
+ PyGILState_STATE gstate; /* Sauvegarde d'environnement */
+ PyObject *args; /* Arguments pour l'appel */
+ PyObject *pyobj; /* Objet Python concerné */
+ PyObject *pyret; /* Bilan de consultation */
+ int ret; /* Validité d'une conversion */
+
+#define LOADED_CONTENT_GET_VIEW_INDEX_WRAPPER PYTHON_WRAPPER_DEF \
+( \
+ _get_view_index, "$self, view", \
+ METH_VARARGS, \
+ "Abstract method used to define the index of a given view for the" \
+ " loaded binary.\n" \
+ "\n" \
+ "The view is provided as a GTK *widget*.\n" \
+ "\n" \
+ "The result is the index of the type of view, or -1 in case of error." \
+)
+
+ result = 0;
+
+ gstate = PyGILState_Ensure();
+
+ pyobj = pygobject_new(G_OBJECT(content));
+
+ if (has_python_method(pyobj, "_get_view_index"))
+ {
+ args = PyTuple_New(1);
+ PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(view)));
+
+ pyret = run_python_method(pyobj, "_get_view_index", args);
+
+ if (pyret != NULL)
+ {
+ ret = PyLong_Check(pyret);
+
+ if (ret)
+ result = PyLong_AsUnsignedLong(pyret);
+
+ Py_DECREF(pyret);
+
+ }
+
+ Py_DECREF(args);
+
+ }
+
+ Py_DECREF(pyobj);
+
+ PyGILState_Release(gstate);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* CONNEXION AVEC L'API DE PYTHON */
+/* ---------------------------------------------------------------------------------- */
+
+
/******************************************************************************
* *
* Paramètres : self = contenu binaire à manipuler. *
@@ -416,15 +1130,16 @@ static PyObject *py_loaded_content_build_default_view(PyObject *self, PyObject *
GLoadedContent *content; /* Version GLib de l'élément */
GtkWidget *view; /* Composant GTK à transposer */
-#define LOADED_CONTENT_BUILD_DEFAULT_VIEW_METHOD PYTHON_METHOD_DEF \
-( \
- build_default_view, "$self", \
- METH_NOARGS, py_loaded_content, \
- "Build a new widget for the default graphical view of the loaded content." \
- "\n" \
- "This method is aimed to only be called from the GUI internals." \
- " It provides the first view displayed in the main Chrysalide window" \
- " after a binary loading." \
+#define LOADED_CONTENT_BUILD_DEFAULT_VIEW_METHOD PYTHON_METHOD_DEF \
+( \
+ build_default_view, "$self", \
+ METH_NOARGS, py_loaded_content, \
+ "Build a new widget for the default graphical view of the loaded" \
+ " content.\n" \
+ "\n" \
+ "This method is aimed to only be called from the GUI internals." \
+ " It provides the first view displayed in the main Chrysalide window" \
+ " after a binary loading." \
)
content = G_LOADED_CONTENT(pygobject_get(self));
@@ -461,15 +1176,16 @@ static PyObject *py_loaded_content_build_view(PyObject *self, PyObject *args)
GLoadedContent *content; /* Version GLib de l'élément */
GtkWidget *view; /* Composant GTK à transposer */
-#define LOADED_CONTENT_BUILD_VIEW_METHOD PYTHON_METHOD_DEF \
-( \
- build_view, "$self, index", \
- METH_VARARGS, py_loaded_content, \
- "Build a new widget for a given graphical view of the loaded content." \
- "\n" \
- "This method is aimed to only be called from the GUI internals." \
- " It provides a view displayed in the main Chrysalide window" \
- " once the binary is loaded." \
+#define LOADED_CONTENT_BUILD_VIEW_METHOD PYTHON_METHOD_DEF \
+( \
+ build_view, "$self, index", \
+ METH_VARARGS, py_loaded_content, \
+ "Build a new widget for a given graphical view of the loaded" \
+ " content.\n" \
+ "\n" \
+ "This method is aimed to only be called from the GUI internals." \
+ " It provides a view displayed in the main Chrysalide window" \
+ " once the binary is loaded." \
)
ret = PyArg_ParseTuple(args, "I", &index);
@@ -541,12 +1257,6 @@ static PyObject *py_loaded_content_get_view_index(PyObject *self, PyObject *args
if (!ret) return NULL;
- if (!GTK_IS_WIDGET(pygobject_get(widget_obj)))
- {
- PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to GTK widget");
- return NULL;
- }
-
content = G_LOADED_CONTENT(pygobject_get(self));
widget = GTK_WIDGET(pygobject_get(widget_obj));
@@ -653,6 +1363,15 @@ static PyObject *py_loaded_content_get_format_name(PyObject *self, void *closure
PyTypeObject *get_python_loaded_content_type(void)
{
static PyMethodDef py_loaded_content_methods[] = {
+ LOADED_CONTENT_GET_CONTENT_WRAPPER,
+ LOADED_CONTENT_GET_FORMAT_NAME_WRAPPER,
+ LOADED_CONTENT_ANALYZE_WRAPPER,
+ LOADED_CONTENT_DESCRIBE_WRAPPER,
+ LOADED_CONTENT_COUNT_VIEWS_WRAPPER,
+ LOADED_CONTENT_GET_VIEW_NAME_WRAPPER,
+ LOADED_CONTENT_BUILD_DEFAULT_VIEW_WRAPPER,
+ LOADED_CONTENT_BUILD_VIEW_WRAPPER,
+ LOADED_CONTENT_GET_VIEW_INDEX_WRAPPER,
LOADED_CONTENT_ANALYZE_METHOD,
LOADED_CONTENT_ANALYZE_AND_WAIT_METHOD,
LOADED_CONTENT_DESCRIBE_METHOD,
@@ -710,6 +1429,14 @@ bool ensure_python_loaded_content_is_registered(void)
PyObject *module; /* Module à recompléter */
PyObject *dict; /* Dictionnaire du module */
+ static GInterfaceInfo info = { /* Paramètres d'inscription */
+
+ .interface_init = (GInterfaceInitFunc)py_loaded_content_interface_init,
+ .interface_finalize = NULL,
+ .interface_data = NULL,
+
+ };
+
type = get_python_loaded_content_type();
if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
@@ -718,7 +1445,7 @@ bool ensure_python_loaded_content_is_registered(void)
dict = PyModule_GetDict(module);
- if (!register_interface_for_pygobject(dict, G_TYPE_LOADED_CONTENT, type))
+ if (!register_interface_for_pygobject_2(dict, G_TYPE_LOADED_CONTENT, type, &info))
return false;
}
diff --git a/plugins/pychrysalide/analysis/storage/serialize.c b/plugins/pychrysalide/analysis/storage/serialize.c
index 67e1256..3e94271 100644
--- a/plugins/pychrysalide/analysis/storage/serialize.c
+++ b/plugins/pychrysalide/analysis/storage/serialize.c
@@ -97,7 +97,7 @@ static void py_serializable_object_interface_init(GSerializableObjectIface *ifac
"\n" \
"The following methods have to be defined for new implementations:\n" \
"* pychrysalide.analysis.storage.SerializableObject._load();\n" \
- "* pychrysalide.analysis.storage.SerializableObject._store();\n" \
+ "* pychrysalide.analysis.storage.SerializableObject._store();\n"
iface->load = py_serializable_object_load_wrapper;
iface->store = py_serializable_object_store_wrapper;
diff --git a/plugins/pychrysalide/gtkext/dockable.c b/plugins/pychrysalide/gtkext/dockable.c
index 8bb26b7..1412589 100644
--- a/plugins/pychrysalide/gtkext/dockable.c
+++ b/plugins/pychrysalide/gtkext/dockable.c
@@ -299,8 +299,6 @@ static GtkWidget *py_dockable_get_widget_wrapper(const GtkDockable *dockable)
PyGILState_STATE gstate; /* Sauvegarde d'environnement */
PyObject *pyobj; /* Objet Python concerné */
PyObject *pyret; /* Bilan de consultation */
- PyObject *gtk_mod; /* Module Python Gtk */
- PyObject *widget_type; /* Module "GtkWidget" */
int ret; /* Bilan d'une conversion */
#define DOCKABLE_GET_WIDGET_WRAPPER PYTHON_WRAPPER_DEF \
@@ -312,6 +310,8 @@ static GtkWidget *py_dockable_get_widget_wrapper(const GtkDockable *dockable)
"The result has to be a Gtk.Widget instance." \
)
+ result = NULL;
+
gstate = PyGILState_Ensure();
pyobj = pygobject_new(G_OBJECT(dockable));
@@ -322,32 +322,10 @@ static GtkWidget *py_dockable_get_widget_wrapper(const GtkDockable *dockable)
if (pyret != NULL)
{
- gtk_mod = PyImport_ImportModule("gi.repository.Gtk");
-
- if (gtk_mod == NULL)
- {
- PyErr_SetString(PyExc_TypeError, "unable to find the Gtk Python module");
- goto done;
- }
-
- widget_type = PyObject_GetAttrString(gtk_mod, "Widget");
-
- Py_DECREF(gtk_mod);
-
- ret = PyObject_TypeCheck(pyret, (PyTypeObject *)widget_type);
-
- Py_DECREF(widget_type);
-
- if (!ret)
- {
- PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to GTK widget");
- goto done;
- }
-
- result = GTK_WIDGET(pygobject_get(pyret));
- g_object_ref(G_OBJECT(result));
+ ret = convert_to_gtk_widget(pyret, &result);
- done:
+ if (ret == 1)
+ g_object_ref(G_OBJECT(result));
Py_DECREF(pyret);
diff --git a/plugins/pychrysalide/gtkext/graph/cluster.c b/plugins/pychrysalide/gtkext/graph/cluster.c
index c87655a..fc73276 100644
--- a/plugins/pychrysalide/gtkext/graph/cluster.c
+++ b/plugins/pychrysalide/gtkext/graph/cluster.c
@@ -161,12 +161,6 @@ static PyObject *py_graph_cluster_find_by_widget(PyObject *self, PyObject *args)
if (!ret) return NULL;
- if (!GTK_IS_WIDGET(pygobject_get(widget_obj)))
- {
- PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to GTK widget");
- return NULL;
- }
-
cluster = G_GRAPH_CLUSTER(pygobject_get(self));
widget = GTK_WIDGET(pygobject_get(widget_obj));
diff --git a/plugins/pychrysalide/helpers.c b/plugins/pychrysalide/helpers.c
index 5c7ae75..3cd528e 100644
--- a/plugins/pychrysalide/helpers.c
+++ b/plugins/pychrysalide/helpers.c
@@ -32,6 +32,7 @@
#include <stdlib.h>
#include <string.h>
#include <strings.h>
+#include <gtk/gtk.h>
#include <i18n.h>
@@ -1132,6 +1133,61 @@ int convert_to_gobject(PyObject *arg, void *dst)
}
+/******************************************************************************
+* *
+* 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 instance de composant GTK. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_gtk_widget(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+ PyObject *gtk_mod; /* Module Python Gtk */
+ PyObject *widget_type; /* Module "GtkWidget" */
+ int ret; /* Bilan d'une conversion */
+
+ result = 0;
+
+ gtk_mod = PyImport_ImportModule("gi.repository.Gtk");
+
+ if (gtk_mod == NULL)
+ {
+ PyErr_SetString(PyExc_TypeError, "unable to find the Gtk Python module");
+ goto done;
+ }
+
+ widget_type = PyObject_GetAttrString(gtk_mod, "Widget");
+
+ Py_DECREF(gtk_mod);
+
+ ret = PyObject_TypeCheck(arg, (PyTypeObject *)widget_type);
+
+ Py_DECREF(widget_type);
+
+ if (!ret)
+ {
+ PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to GTK widget");
+ goto done;
+ }
+
+ *((GtkWidget **)dst) = GTK_WIDGET(pygobject_get(arg));
+
+ result = 1;
+
+ done:
+
+ return result;
+
+}
+
+
/* ---------------------------------------------------------------------------------- */
/* TRANSFERT DES VALEURS CONSTANTES */
diff --git a/plugins/pychrysalide/helpers.h b/plugins/pychrysalide/helpers.h
index fd0ece7..a74a747 100644
--- a/plugins/pychrysalide/helpers.h
+++ b/plugins/pychrysalide/helpers.h
@@ -187,6 +187,9 @@ int forward_pygobjet_init(PyObject *);
/* Tente de convertir en instance GObject. */
int convert_to_gobject(PyObject *, void *);
+/* Tente de convertir en instance de composant GTK. */
+int convert_to_gtk_widget(PyObject *, void *);
+
/* ----------------------- TRANSFERT DES VALEURS CONSTANTES ------------------------- */
diff --git a/src/analysis/binary.c b/src/analysis/binary.c
index ad4ec1f..aee4499 100644
--- a/src/analysis/binary.c
+++ b/src/analysis/binary.c
@@ -167,7 +167,7 @@ static bool g_loaded_binary_save(GLoadedBinary *, xmlDoc *, xmlXPathContext *, c
static GBinContent *g_loaded_binary_get_content(const GLoadedBinary *);
/* Fournit le contenu représenté de l'élément chargé. */
-static const char *g_loaded_binary_get_format_name(const GLoadedBinary *);
+static char *g_loaded_binary_get_format_name(const GLoadedBinary *);
/* Assure le désassemblage en différé. */
static bool g_loaded_binary_analyze(GLoadedBinary *, bool, bool, wgroup_id_t, GtkStatusStack *);
@@ -176,13 +176,13 @@ static bool g_loaded_binary_analyze(GLoadedBinary *, bool, bool, wgroup_id_t, Gt
static void on_binary_processor_changed(GArchProcessor *, GArchInstruction *, gboolean, GLoadedBinary *);
/* Fournit le désignation associée à l'élément chargé. */
-static const char *g_loaded_binary_describe(const GLoadedBinary *, bool);
+static char *g_loaded_binary_describe(const GLoadedBinary *, bool);
/* Détermine le nombre de vues disponibles pour un contenu. */
static unsigned int g_loaded_binary_count_views(const GLoadedBinary *);
/* Fournit le nom d'une vue donnée d'un contenu chargé. */
-static const char *g_loaded_binary_get_view_name(const GLoadedBinary *, unsigned int);
+static char *g_loaded_binary_get_view_name(const GLoadedBinary *, unsigned int);
/* Met en place la vue initiale pour un contenu binaire. */
static GtkWidget *g_loaded_binary_build_default_view(GLoadedBinary *);
@@ -1616,9 +1616,9 @@ static GBinContent *g_loaded_binary_get_content(const GLoadedBinary *binary)
* *
******************************************************************************/
-static const char *g_loaded_binary_get_format_name(const GLoadedBinary *binary)
+static char *g_loaded_binary_get_format_name(const GLoadedBinary *binary)
{
- const char *result; /* Désignation à retourner */
+ char *result; /* Désignation à retourner */
result = g_known_format_get_key(G_KNOWN_FORMAT(binary->format));
@@ -1845,9 +1845,9 @@ static void on_binary_processor_changed(GArchProcessor *proc, GArchInstruction *
* *
******************************************************************************/
-static const char *g_loaded_binary_describe(const GLoadedBinary *binary, bool full)
+static char *g_loaded_binary_describe(const GLoadedBinary *binary, bool full)
{
- const char *result; /* Description à retourner */
+ char *result; /* Description à retourner */
GBinContent *content; /* Contenu binaire mannipulé */
content = g_known_format_get_content(G_KNOWN_FORMAT(binary->format));
@@ -1875,7 +1875,11 @@ static const char *g_loaded_binary_describe(const GLoadedBinary *binary, bool fu
static unsigned int g_loaded_binary_count_views(const GLoadedBinary *binary)
{
- return BVW_COUNT;
+ unsigned int result; /* Quantité de vues à renvoyer */
+
+ result = BVW_COUNT;
+
+ return result;
}
@@ -1893,22 +1897,22 @@ static unsigned int g_loaded_binary_count_views(const GLoadedBinary *binary)
* *
******************************************************************************/
-static const char *g_loaded_binary_get_view_name(const GLoadedBinary *binary, unsigned int index)
+static char *g_loaded_binary_get_view_name(const GLoadedBinary *binary, unsigned int index)
{
- const char *result; /* Désignation à retourner */
+ char *result; /* Désignation à retourner */
switch (index)
{
case BVW_HEX:
- result = _("Hex view");
+ result = strdup(_("Hex view"));
break;
case BVW_BLOCK:
- result = _("Text view");
+ result = strdup(_("Text view"));
break;
case BVW_GRAPH:
- result = _("Graph view");
+ result = strdup(_("Graph view"));
break;
default:
diff --git a/src/analysis/content.c b/src/analysis/content.c
index 007d46a..86fa490 100644
--- a/src/analysis/content.c
+++ b/src/analysis/content.c
@@ -199,11 +199,14 @@ GBinContent *g_binary_content_get_root(GBinContent *content)
const char *g_binary_content_describe(const GBinContent *content, bool full)
{
+ char *result; /* Description à retourner */
GBinContentIface *iface; /* Interface utilisée */
iface = G_BIN_CONTENT_GET_IFACE(content);
- return iface->describe(content, full);
+ result = strdup(iface->describe(content, full));
+
+ return result;
}
diff --git a/src/analysis/loaded-int.h b/src/analysis/loaded-int.h
index 0aacc3f..0476af5 100644
--- a/src/analysis/loaded-int.h
+++ b/src/analysis/loaded-int.h
@@ -40,19 +40,19 @@ typedef bool (* save_content_fc) (GLoadedContent *, xmlDoc *, xmlXPathContext *,
typedef GBinContent * (* get_content_fc) (const GLoadedContent *);
/* Fournit le format associé à l'élément chargé. */
-typedef const char * (* get_format_name_fc) (const GLoadedContent *);
+typedef char * (* get_format_name_fc) (const GLoadedContent *);
/* Assure l'analyse d'un contenu chargé en différé. */
typedef bool (* analyze_loaded_fc) (GLoadedContent *, bool, bool, wgroup_id_t, GtkStatusStack *);
/* Fournit le désignation associée à l'élément chargé. */
-typedef const char * (* describe_loaded_fc) (const GLoadedContent *, bool);
+typedef char * (* describe_loaded_fc) (const GLoadedContent *, bool);
/* Détermine le nombre de vues disponibles pour un contenu. */
typedef unsigned int (* count_loaded_views_fc) (const GLoadedContent *);
/* Fournit le nom d'une vue donnée d'un contenu chargé. */
-typedef const char * (* get_loaded_view_name_fc) (const GLoadedContent *, unsigned int);
+typedef char * (* get_loaded_view_name_fc) (const GLoadedContent *, unsigned int);
/* Met en place la vue initiale pour un contenu chargé. */
typedef GtkWidget * (* build_loaded_def_view_fc) (GLoadedContent *);
diff --git a/src/analysis/loaded.c b/src/analysis/loaded.c
index 79a311f..71b1838 100644
--- a/src/analysis/loaded.c
+++ b/src/analysis/loaded.c
@@ -245,9 +245,9 @@ GBinContent *g_loaded_content_get_content(const GLoadedContent *content)
* *
******************************************************************************/
-const char *g_loaded_content_get_format_name(const GLoadedContent *content)
+char *g_loaded_content_get_format_name(const GLoadedContent *content)
{
- const char *result; /* Contenu interne à renvoyer */
+ char *result; /* Contenu interne à renvoyer */
GLoadedContentIface *iface; /* Interface utilisée */
iface = G_LOADED_CONTENT_GET_IFACE(content);
@@ -365,13 +365,16 @@ bool g_loaded_content_analyze_and_wait(GLoadedContent *content, bool connect, bo
* *
******************************************************************************/
-const char *g_loaded_content_describe(const GLoadedContent *content, bool full)
+char *g_loaded_content_describe(const GLoadedContent *content, bool full)
{
+ char *result; /* Description à retourner */
GLoadedContentIface *iface; /* Interface utilisée */
iface = G_LOADED_CONTENT_GET_IFACE(content);
- return iface->describe(content, full);
+ result = iface->describe(content, full);
+
+ return result;
}
@@ -424,11 +427,14 @@ char **g_loaded_content_detect_obfuscators(const GLoadedContent *content, bool v
unsigned int g_loaded_content_count_views(const GLoadedContent *content)
{
+ unsigned int result; /* Quantité de vues à renvoyer */
GLoadedContentIface *iface; /* Interface utilisée */
iface = G_LOADED_CONTENT_GET_IFACE(content);
- return iface->count_views(content);
+ result = iface->count_views(content);
+
+ return result;
}
@@ -446,9 +452,9 @@ unsigned int g_loaded_content_count_views(const GLoadedContent *content)
* *
******************************************************************************/
-const char *g_loaded_content_get_view_name(const GLoadedContent *content, unsigned int index)
+char *g_loaded_content_get_view_name(const GLoadedContent *content, unsigned int index)
{
- const char *result; /* Désignation à retourner */
+ char *result; /* Désignation à retourner */
GLoadedContentIface *iface; /* Interface utilisée */
iface = G_LOADED_CONTENT_GET_IFACE(content);
diff --git a/src/analysis/loaded.h b/src/analysis/loaded.h
index 9df647b..9d446c4 100644
--- a/src/analysis/loaded.h
+++ b/src/analysis/loaded.h
@@ -68,7 +68,7 @@ bool g_loaded_content_save(GLoadedContent *, xmlDoc *, xmlXPathContext *, const
GBinContent *g_loaded_content_get_content(const GLoadedContent *);
/* Fournit le format associé à l'élément chargé. */
-const char *g_loaded_content_get_format_name(const GLoadedContent *);
+char *g_loaded_content_get_format_name(const GLoadedContent *);
/* Lance l'analyse propre à l'élément chargé. */
void g_loaded_content_analyze(GLoadedContent *, bool, bool);
@@ -77,7 +77,7 @@ void g_loaded_content_analyze(GLoadedContent *, bool, bool);
bool g_loaded_content_analyze_and_wait(GLoadedContent *, bool, bool);
/* Fournit le désignation associée à l'élément chargé. */
-const char *g_loaded_content_describe(const GLoadedContent *, bool);
+char *g_loaded_content_describe(const GLoadedContent *, bool);
/* Etablit une liste d'obscurcissements présents. */
char **g_loaded_content_detect_obfuscators(const GLoadedContent *, bool, size_t *);
@@ -91,7 +91,7 @@ char **g_loaded_content_detect_obfuscators(const GLoadedContent *, bool, size_t
unsigned int g_loaded_content_count_views(const GLoadedContent *);
/* Fournit le nom d'une vue donnée d'un contenu chargé. */
-const char *g_loaded_content_get_view_name(const GLoadedContent *, unsigned int);
+char *g_loaded_content_get_view_name(const GLoadedContent *, unsigned int);
/* Met en place la vue initiale pour un contenu chargé. */
GtkWidget *g_loaded_content_build_default_view(GLoadedContent *);
diff --git a/src/analysis/project.c b/src/analysis/project.c
index 71e0f43..13985f3 100644
--- a/src/analysis/project.c
+++ b/src/analysis/project.c
@@ -388,7 +388,7 @@ bool g_study_project_save(GStudyProject *project, const char *filename)
const gchar *hash; /* Empreinte d'un contenu */
char *access; /* Chemin pour une sous-config.*/
xmlXPathObjectPtr xobject; /* Cible d'une recherche */
- const char *format; /* Format associé à un élément */
+ char *format; /* Format associé à un élément */
/* Forme générale */
@@ -470,6 +470,7 @@ bool g_study_project_save(GStudyProject *project, const char *filename)
{
format = g_loaded_content_get_format_name(project->contents[i]);
result = add_string_attribute_to_node(xdoc, context, access, "format", format);
+ free(format);
}
if (result)
@@ -597,7 +598,7 @@ void g_study_project_discover_binary_content(GStudyProject *project, GBinContent
void on_loaded_content_analyzed(GLoadedContent *content, gboolean success, GStudyProject *project)
{
- const char *desc; /* Description du contenu */
+ char *desc; /* Description du contenu */
desc = g_loaded_content_describe(content, true);
@@ -610,6 +611,8 @@ void on_loaded_content_analyzed(GLoadedContent *content, gboolean success, GStud
else
log_variadic_message(LMT_ERROR, _("Failed to load '%s'"), desc);
+ free(desc);
+
/**
* Le contenu a normalement été sur-référencé pour ne pas disparaître
* en cours d'analyse.
@@ -1291,7 +1294,7 @@ static void on_new_content_resolved(GContentResolver *resolver, wgroup_id_t wid,
size_t i; /* Boucle de parcours */
GBinContent *content; /* Contenu brut à manipuler */
const gchar *hash; /* Empreinte d'un contenu */
- const char *format; /* Format associé à un élément */
+ char *format; /* Format associé à un élément */
char *access; /* Chemin pour une sous-config.*/
xmlXPathObjectPtr xobject; /* Cible d'une recherche */
bool status; /* Bilan d'une restauration */
@@ -1316,6 +1319,8 @@ static void on_new_content_resolved(GContentResolver *resolver, wgroup_id_t wid,
asprintf(&access, "/ChrysalideProject/LoadedContents/Content[@hash='%s' and @format='%s']",
hash, format);
+ free(format);
+
xobject = get_node_xpath_object(handler->context, access);
if (XPATH_OBJ_NODES_COUNT(xobject) > 0)
diff --git a/src/gui/dialogs/loading.c b/src/gui/dialogs/loading.c
index 3e71df4..97cd892 100644
--- a/src/gui/dialogs/loading.c
+++ b/src/gui/dialogs/loading.c
@@ -457,6 +457,8 @@ static void update_loading_dialog_counter(GtkBuilder *builder)
void add_content_to_loading_dialog(GtkBuilder *builder, GLoadedContent *content, GStudyProject *project)
{
GtkListStore *store; /* Modèle de gestion */
+ char *desc; /* Description d'un contenu */
+ char *format; /* Format associé à un contenu */
char *name; /* Désignation complète */
gboolean recognized; /* Nature du contenu */
GtkTreeIter iter; /* Point d'insertion */
@@ -472,9 +474,13 @@ void add_content_to_loading_dialog(GtkBuilder *builder, GLoadedContent *content,
/* Inscription */
- asprintf(&name, "%s (%s)",
- g_loaded_content_describe(content, false),
- g_loaded_content_get_format_name(content));
+ desc = g_loaded_content_describe(content, false);
+ format = g_loaded_content_get_format_name(content);
+
+ asprintf(&name, "%s (%s)", desc, format);
+
+ free(format);
+ free(desc);
recognized = TRUE;
diff --git a/src/gui/editor.c b/src/gui/editor.c
index bdd9a78..8e20cc1 100644
--- a/src/gui/editor.c
+++ b/src/gui/editor.c
@@ -926,8 +926,8 @@ static void on_editor_content_available(GStudyProject *project, GLoadedContent *
static void on_editor_loaded_content_added(GStudyProject *project, GLoadedContent *content, void *unused)
{
GtkWidget *selected; /* Interface de prédilection */
- const char *name; /* Titre associé au binaire */
- const char *lname; /* Description du binaire */
+ char *name; /* Titre associé au binaire */
+ char *lname; /* Description du binaire */
GPanelItem *panel; /* Nouveau panneau à integrer */
selected = g_loaded_content_build_default_view(content);
@@ -936,6 +936,10 @@ static void on_editor_loaded_content_added(GStudyProject *project, GLoadedConten
lname = g_loaded_content_describe(content, true);
panel = g_panel_item_new(PIP_BINARY_VIEW, name, lname, selected, true, "M");
+
+ free(lname);
+ free(name);
+
register_panel_item(panel, get_main_configuration());
g_signal_connect(selected, "size-allocate", G_CALLBACK(scroll_for_the_first_time), content);
diff --git a/src/gui/menus/project.c b/src/gui/menus/project.c
index f0b9c17..a5992bf 100644
--- a/src/gui/menus/project.c
+++ b/src/gui/menus/project.c
@@ -117,7 +117,7 @@ void update_menu_project_for_project(GtkWidget *widget, GStudyProject *project,
size_t count; /* Nombre de contenus attachés */
GLoadedContent **contents; /* Liste de ces contenus */
size_t i; /* Boucle de parcours #2 */
- const char *desc; /* Description à afficher */
+ char *desc; /* Description à afficher */
GtkWidget *submenuitem; /* Sous-menu à ajouter */
menuitem = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), "menu_prj_remove_bin"));
@@ -145,6 +145,8 @@ void update_menu_project_for_project(GtkWidget *widget, GStudyProject *project,
g_object_set_data_full(G_OBJECT(submenuitem), "content", contents[i], g_object_unref);
gtk_container_add(GTK_CONTAINER(menubar), submenuitem);
+ free(desc);
+
/**
* Note : l'appel à g_object_unref() est réalisé lorsque la référence
* est retirée du menu.
diff --git a/src/gui/menus/view.c b/src/gui/menus/view.c
index bc833a3..b9451e0 100644
--- a/src/gui/menus/view.c
+++ b/src/gui/menus/view.c
@@ -198,6 +198,7 @@ void rebuild_menu_view_for_content(GtkWidget *widget, GObject *ref, GLoadedConte
GList *iter; /* Boucle de parcours */
unsigned int count; /* Nombre d'itérations à mener */
GSList *rgroup; /* Groupe des boutons radio */
+ char *caption; /* Etiquette pour un menu */
/* Retrait d'éventuels anciens menus */
@@ -246,12 +247,13 @@ void rebuild_menu_view_for_content(GtkWidget *widget, GObject *ref, GLoadedConte
for (i = 0; i < count; i++)
{
asprintf(&key, "mnu_view_panel_%u", i);
+ caption = g_loaded_content_get_view_name(new, i);
- submenuitem = qck_create_radio_menu_item(ref, key, rgroup,
- g_loaded_content_get_view_name(new, i),
+ submenuitem = qck_create_radio_menu_item(ref, key, rgroup, caption,
G_CALLBACK(mcb_view_change_support), NULL);
g_object_set_data(G_OBJECT(submenuitem), "kind_of_view", GUINT_TO_POINTER(i));
+ free(caption);
free(key);
asprintf(&key, "F%u", 3 + i);
diff --git a/src/gui/panel.c b/src/gui/panel.c
index a98119f..2ebcdad 100644
--- a/src/gui/panel.c
+++ b/src/gui/panel.c
@@ -258,13 +258,13 @@ GPanelItem *g_panel_item_new(PanelItemPersonality personality, const char *name,
parent = G_EDITOR_ITEM(result);
- parent->name = name;
+ parent->name = strdup(name);
parent->widget = widget;
assert(personality > PIP_INVALID && personality < PIP_COUNT);
result->personality = personality;
- result->lname = lname;
+ result->lname = strdup(lname);
result->dock_at_startup = startup;
result->path = strdup(path);