From 2bd3ea7249d1234204c1b70abac8bc46e221fb95 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sun, 12 Jul 2020 15:52:22 +0200
Subject: Improved the API for loaded contents.

---
 plugins/pychrysalide/analysis/loaded.c            | 791 +++++++++++++++++++++-
 plugins/pychrysalide/analysis/storage/serialize.c |   2 +-
 plugins/pychrysalide/gtkext/dockable.c            |  32 +-
 plugins/pychrysalide/gtkext/graph/cluster.c       |   6 -
 plugins/pychrysalide/helpers.c                    |  56 ++
 plugins/pychrysalide/helpers.h                    |   3 +
 src/analysis/binary.c                             |  30 +-
 src/analysis/content.c                            |   5 +-
 src/analysis/loaded-int.h                         |   6 +-
 src/analysis/loaded.c                             |  20 +-
 src/analysis/loaded.h                             |   6 +-
 src/analysis/project.c                            |  11 +-
 src/gui/dialogs/loading.c                         |  12 +-
 src/gui/editor.c                                  |   8 +-
 src/gui/menus/project.c                           |   4 +-
 src/gui/menus/view.c                              |   6 +-
 src/gui/panel.c                                   |   4 +-
 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);
-- 
cgit v0.11.2-87-g4458