From e07a541d1dea13a19a587f2b97d12ed3443f235b Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Thu, 27 Aug 2015 00:26:20 +0000
Subject: Redefined and improved the load process for Python plugins.

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@572 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                           |  31 ++
 plugins/pychrysa/Makefile.am        |   4 +-
 plugins/pychrysa/gui/panels/panel.c |  64 +---
 plugins/pychrysa/helpers.c          |  30 ++
 plugins/pychrysa/helpers.h          |   3 +
 plugins/pychrysa/plugin.c           | 690 ++++++++++++++++++++----------------
 plugins/pychrysa/plugin.h           |  33 +-
 plugins/pychrysa/pychrysa.c         | 171 ++++++++-
 plugins/pychrysa/pychrysa.h         |   7 +
 plugins/pychrysa/quirks.c           |  12 +
 plugins/pychrysa/quirks.h           |   7 +-
 src/plugins/plugin-def.h            |   2 +-
 src/plugins/plugin-int.h            |   3 +
 src/plugins/plugin.c                |  57 ++-
 14 files changed, 718 insertions(+), 396 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 917cfba..3fa796a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,34 @@
+15-08-27  Cyrille Bagard <nocbos@gmail.com>
+
+	* plugins/pychrysa/gui/panels/panel.c:
+	Clean the code. Register properly the wrapper for PyGObjects
+
+	* plugins/pychrysa/helpers.c:
+	* plugins/pychrysa/helpers.h:
+	Provide a way to check if a Python method exists.
+
+	* plugins/pychrysa/Makefile.am:
+	Add the 'plugin.[ch]' and 'helpers.[ch]' files to pychrysalide_la_SOURCES.
+
+	* plugins/pychrysa/plugin.c:
+	* plugins/pychrysa/plugin.h:
+	* plugins/pychrysa/pychrysa.c:
+	* plugins/pychrysa/pychrysa.h:
+	Redefine and improve the load process for Python plugins.
+
+	* plugins/pychrysa/quirks.c:
+	* plugins/pychrysa/quirks.h:
+	Disable most routines.
+
+	* src/plugins/plugin.c:
+	Complete the loading of plugins in a distinct function.
+
+	* src/plugins/plugin-def.h:
+	Typo.
+
+	* src/plugins/plugin-int.h:
+	Complete the loading of plugins in a distinct function.
+
 15-08-13  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/gtkext/easygtk.c:
diff --git a/plugins/pychrysa/Makefile.am b/plugins/pychrysa/Makefile.am
index e4b9739..59e876d 100644
--- a/plugins/pychrysa/Makefile.am
+++ b/plugins/pychrysa/Makefile.am
@@ -25,7 +25,9 @@ pychrysa_la_LDFLAGS = -module -avoid-version $(LIBGTK_LIBS) $(LIBXML_LIBS) $(LIB
 
 pychrysalide_la_SOURCES =				\
 	helpers.h helpers.c					\
-	pychrysa.h pychrysa.c
+	plugin.h plugin.c					\
+	pychrysa.h pychrysa.c				\
+	quirks.h quirks.c
 
 pychrysalide_la_LIBADD =				\
 	analysis/libpychrysaanalysis.la		\
diff --git a/plugins/pychrysa/gui/panels/panel.c b/plugins/pychrysa/gui/panels/panel.c
index e713cc0..3170a66 100644
--- a/plugins/pychrysa/gui/panels/panel.c
+++ b/plugins/pychrysa/gui/panels/panel.c
@@ -32,91 +32,56 @@
 
 
 #include "../editem.h"
+#include "../../quirks.h"
 
 
 
-/* Crée un nouvel objet Python de type 'PanelItem'. */
-#if 0
-static PyObject *py_panel_item_new(PyTypeObject *, PyObject *, PyObject *);
-#endif
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_panel_item_init(PyObject *self, PyObject *args, PyObject *kwds);
 
 /* Place un panneau dans l'ensemble affiché. */
 static PyObject *py_panel_item_dock(PyObject *, PyObject *);
 
 
 
-#if 0
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : type = type de l'objet à instancier.                         *
+*  Paramètres  : self = objet à initialiser (théoriquement).                  *
 *                args = arguments fournis à l'appel.                          *
 *                kwds = arguments de type key=val fournis.                    *
 *                                                                             *
-*  Description : Crée un nouvel objet Python de type 'PanelItem'.             *
+*  Description : Initialise une instance sur la base du dérivé de GObject.    *
 *                                                                             *
-*  Retour      : Instance Python mise en place.                               *
+*  Retour      : 0.                                                           *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static PyObject *py_panel_item_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+static int py_panel_item_init(PyObject *self, PyObject *args, PyObject *kwds)
 {
-    PyObject *result;                       /* Instance à retourner        */
     const char *name;                       /* Désignation humaine         */
     const char *lname;                      /* Nom version longue          */
     PyGObject *widget;                      /* Composant visuel du panneau */
     const char *path;                       /* Placement à l'affichage     */
     int ret;                                /* Bilan de lecture des args.  */
-    GEditorItem *item;                      /* Version GLib du format      */
+    GEditorItem *item;                      /* Elément de l'éditeur        */
 
     ret = PyArg_ParseTuple(args, "ssOs", &name, &lname, &widget, &path);
-    if (!ret) Py_RETURN_NONE;
+    if (!ret) return -1;
 
     item = g_panel_item_new(get_internal_ref(), name, lname,
                             GTK_WIDGET(pygobject_get(widget)), path);
 
-    result = _py_panel_item_from_c(G_PANEL_ITEM(item), type);
-    g_object_unref(item);
+    /* Enregistrement auprès de PyGObject */
 
-    return result;
+    ((PyGObject *)self)->obj = G_OBJECT(item);
 
-}
-
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : item = instance existante GLib.                              *
-*                type = éventuel type final de l'instance Python imposé.      *
-*                                                                             *
-*  Description : Crée un nouvel objet Python de type 'PanelItem'.             *
-*                                                                             *
-*  Retour      : Instance Python mise en place.                               *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-PyObject *_py_panel_item_from_c(GPanelItem *item, PyTypeObject *type)
-{
-    PyObject *module;                       /* Module d'appartenance       */
-
-    if (type == NULL)
-    {
-        module = PyImport_ImportModule("pychrysalide.gui.panels");
-        type = (PyTypeObject *)PyObject_GetAttrString(module, "PanelItem");
-        Py_DECREF(module);
-        /* FIXME : type refcount ? */
-    }
-    else Py_INCREF(type);
-
-    pychrysalide_set_instance_data(G_OBJECT(item), type);
+    pygobject_register_wrapper(self);
 
-    return pygobject_new(G_OBJECT(item));
+    return 0;
 
 }
-#endif
 
 
 /******************************************************************************
@@ -185,8 +150,7 @@ PyTypeObject *get_python_panel_item_type(void)
 
         .tp_methods     = py_panel_item_methods,
         .tp_getset      = py_panel_item_getseters,
-        //.tp_new         = (newfunc)py_panel_item_new,
-        //.tp_init        = (initproc)pychrysalide_allow_args_for_gobjects
+        .tp_init        = (initproc)py_panel_item_init
 
     };
 
diff --git a/plugins/pychrysa/helpers.c b/plugins/pychrysa/helpers.c
index d344a7f..5ba2fb4 100644
--- a/plugins/pychrysa/helpers.c
+++ b/plugins/pychrysa/helpers.c
@@ -27,6 +27,36 @@
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : target = propriétaire de la routine visée.                   *
+*                method = désignation de la fonction à appeler.               *
+*                                                                             *
+*  Description : Indique si une routine Python existe ou non.                 *
+*                                                                             *
+*  Retour      : Bilan de l'analyse.                                          *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool has_python_method(PyObject *module, const char *method)
+{
+    bool result;                            /* Bilan à retourner           */
+    PyObject *func;                         /* Fonction visée              */
+
+    func = PyObject_GetAttrString(module, method);
+    if (func == NULL) return false;
+
+    result = PyCallable_Check(func);
+
+    Py_DECREF(func);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : func = fonction Python à appeler.                            *
 *                args = arguments à associer à l'opération.                   *
 *                                                                             *
diff --git a/plugins/pychrysa/helpers.h b/plugins/pychrysa/helpers.h
index d47d8e7..bd11459 100644
--- a/plugins/pychrysa/helpers.h
+++ b/plugins/pychrysa/helpers.h
@@ -30,6 +30,9 @@
 
 
 
+/* Indique si une routine Python existe ou non. */
+bool has_python_method(PyObject *, const char *);
+
 /* Appelle une routine Python. */
 PyObject *_run_python_method(PyObject *, PyObject *);
 
diff --git a/plugins/pychrysa/plugin.c b/plugins/pychrysa/plugin.c
index e1db3de..44cb0d8 100644
--- a/plugins/pychrysa/plugin.c
+++ b/plugins/pychrysa/plugin.c
@@ -26,20 +26,14 @@
 
 
 #include <pygobject.h>
+#include <string.h>
 
 
 #include <common/extstr.h>
-
-#include "../../src/analysis/binary.h"
-#include "../../src/plugins/plugin-int.h"
+#include <plugins/plugin-int.h>
 
 
 #include "helpers.h"
-#include "analysis/binary.h"
-//#include "debug/debugger.h"
-
-
-
 
 
 
@@ -71,9 +65,20 @@ static void g_python_plugin_class_init(GPythonPluginClass *);
 /* Initialise l'instance d'un greffon Python. */
 static void g_python_plugin_init(GPythonPlugin *);
 
+/* Reconstruit la déclaration d'interface à partir de lectures. */
+static bool g_python_plugin_read_interface(GPythonPlugin *);
+
 /* Procède à l'initialisation du greffon. */
 static bool g_python_plugin_do_init(GPythonPlugin *, GObject *);
 
+/* Procède à l'extinction du greffon. */
+static bool g_python_plugin_do_exit(GPythonPlugin *, GObject *);
+
+
+
+
+
+
 /* Indique l'utilité pratique du greffon. */
 static PluginAction g_python_plugin_get_action(const GPythonPlugin *);
 
@@ -92,49 +97,8 @@ static bool g_python_plugin_execute_on_binary(GPythonPlugin *, GLoadedBinary *,
 /* ------------------------- MODULE PYTHON POUR LES SCRIPTS ------------------------- */
 
 
-/* Classe plugin pour Python */
-typedef struct _pychrysa_plugin
-{
-    PyObject_HEAD
-
-} pychrysa_plugin;
-
-
-
-
-
-
-/* Crée un nouveau greffon Python abstrait. */
-static PyObject *pychrysa_plugin_new(PyTypeObject *, PyObject *, PyObject *);
-
-/* Exécute une action valide pour le greffon Python. */
-static PyObject *pychrysa_plugin_run(PyObject *, PyObject *);
-
-
-
 /* Définit les constantes pour les greffons en Python. */
-static bool pychrysa_plugin_define_constants(PyObject *);
-
-/* Procède à l'initialisation du greffon. */
-static PyObject *pychrysa_plugin_init(PyObject *, PyObject *);
-
-/* Définit le comportement par défaut d'un greffon Python. */
-static PyObject *pychrysa_plugin_get_action(PyObject *, PyObject *);
-
-/* Définit l'issue de la recherche d'un format par défaut. */
-static PyObject *pychrysa_plugin_is_matching(PyObject *, PyObject *);
-
-
-/* Exécute une action relative à un débogueur. */
-//static PyObject *pychrysa_plugin_handle_debugger(PyObject *, PyObject *);
-
-
-
-
-
-
-
-
+static bool py_plugin_module_define_constants(PyTypeObject *);
 
 
 
@@ -196,6 +160,7 @@ static void g_python_plugin_init(GPythonPlugin *plugin)
 *                                                                             *
 *  Paramètres  : modname  = nom du module à charger.                          *
 *                filename = chemin d'accès au code Python à charger.          *
+*                ref      = espace de référencement global.                   *
 *                                                                             *
 *  Description : Crée un greffon à partir de code Python.                     *
 *                                                                             *
@@ -205,33 +170,62 @@ static void g_python_plugin_init(GPythonPlugin *plugin)
 *                                                                             *
 ******************************************************************************/
 
-GPluginModule *g_python_plugin_new(const char *modname, const char *filename)
+GPluginModule *g_python_plugin_new(const char *modname, const char *filename, GObject *ref)
 {
     GPythonPlugin *result;                  /* Structure à retourner       */
     PyObject *name;                         /* Chemin d'accès pour Python  */
     PyObject *module;                       /* Script Python chargé        */
+    PyObject *err_type;                     /* Type d'erreur Python        */
+    PyObject *err_value;                    /* Instance Python d'erreur    */
+    PyObject *err_traceback;                /* Trace Python associée       */
+    PyObject *err_string;                   /* Description Python d'erreur */
+    const char *err_msg;                    /* Représentation humaine      */
     PyObject *dict;                         /* Dictionnaire associé        */
     PyObject *class;                        /* Classe à instancier         */
     PyObject *instance;                     /* Instance Python du greffon  */
+    size_t i;                               /* Boucle de parcours          */
+    uint32_t category;                      /* Catégorie principale        */
+    uint32_t sub;                           /* Sous-catégorie visée        */
 
-#if PY_VERSION_HEX >= 0x03000000
-    name = PyUnicode_FromString(filename);
-#else
-    name = PyString_FromString(filename);
-#endif
+    name = PyUnicode_FromString(modname);
     if (name == NULL) goto gppn_bad_exit;
 
     module = PyImport_Import(name);
     Py_DECREF(name);
 
-    if (module == NULL)
+    if (PyErr_Occurred())
     {
-        PyErr_Print();
-        goto gppn_bad_exit;
+        PyErr_Fetch(&err_type, &err_value, &err_traceback);
+
+        if (err_value == NULL)
+            log_variadic_message(LMT_ERROR,
+                                 _("An unknown error occured when importing '%s'..."), modname);
+        else
+        {
+            err_string = PyObject_Str(err_value);
+            err_msg = PyUnicode_AsUTF8(err_string);
+
+            log_variadic_message(LMT_ERROR,
+                                 _("An error occured when importing '%s': \"%s\""), modname, err_msg);
+
+            Py_DECREF(err_string);
+            Py_DECREF(err_value);
+
+        }
+
+        Py_XDECREF(err_traceback);
+        Py_XDECREF(err_type);
+
+        Py_XDECREF(module);
+
+        module = NULL;
+
     }
 
+    if (module == NULL) goto gppn_bad_exit;
+
     dict = PyModule_GetDict(module);
-    class = PyDict_GetItemString(dict, modname);
+    class = PyDict_GetItemString(dict, "AutoLoad");
 
     if (class == NULL) goto gppn_no_class;
     if (!PyType_Check(class->ob_type)) goto gppn_no_class;
@@ -241,28 +235,154 @@ GPluginModule *g_python_plugin_new(const char *modname, const char *filename)
 
     result = g_object_new(G_TYPE_PYTHON_PLUGIN, NULL);
 
-    //G_PLUGIN_MODULE(result)->name = strdup(modname);
-    //G_PLUGIN_MODULE(result)->name = stradd(G_PLUGIN_MODULE(result)->name, ".py");
-    //G_PLUGIN_MODULE(result)->filename = strdup(G_PLUGIN_MODULE(result)->name);
+    G_PLUGIN_MODULE(result)->filename = strdup(filename);
+
+    result->module = module;
+    result->instance = instance;
+
+    if (!g_python_plugin_read_interface(result))
+    {
+        printf("bad interface------------\n");
+        goto gppn_interface_error;
+    }
+
 
-    G_PLUGIN_MODULE(result)->init = (init_plugin_fc)g_python_plugin_do_init;
-    G_PLUGIN_MODULE(result)->get_action = (get_plugin_action_fc)g_python_plugin_get_action;
+    //G_PLUGIN_MODULE(result)->get_action = (get_plugin_action_fc)g_python_plugin_get_action;
 
     //G_PLUGIN_MODULE(result)->is_matching = (is_matching_fc)g_python_plugin_is_matching;
 
-    result->module = module;
-    result->instance = instance;
+
+
+
+
+
+
+    /* Localisation des différents points d'entrée déclarés */
+
+#define register_python_binding(inst, sym, binding)                                 \
+    ({                                                                              \
+        bool __result;                                                              \
+        if (!has_python_method(inst, #sym))                                         \
+        {                                                                           \
+            log_variadic_message(LMT_ERROR,                                         \
+                                 _("No '%s' entry in plugin candidate '%s'"),       \
+                                 #sym, G_PLUGIN_MODULE(result)->filename);          \
+            __result = false;                                                       \
+        }                                                                           \
+        else                                                                        \
+        {                                                                           \
+            G_PLUGIN_MODULE(result)->sym = binding;                                 \
+            __result = true;                                                        \
+        }                                                                           \
+        __result;                                                                   \
+    })
+
+    for (i = 0; i < G_PLUGIN_MODULE(result)->interface->actions_count; i++)
+    {
+        category = MASK_PLUGIN_CATEGORY(G_PLUGIN_MODULE(result)->interface->actions[i]);
+        sub = MASK_PLUGIN_SUB_CATEGORY(G_PLUGIN_MODULE(result)->interface->actions[i]);
+
+        switch (category)
+        {
+            case DPC_BASIC:
+
+                switch (sub)
+                {
+                    case DPS_NONE:
+                        break;
+
+                    case PGA_PLUGIN_INIT:
+                        if (!register_python_binding(instance, init, (pg_management_fc)g_python_plugin_do_init))
+                            goto gppn_bad_plugin;
+                        break;
+
+                    case PGA_PLUGIN_EXIT:
+                        if (!register_python_binding(instance, exit, (pg_management_fc)g_python_plugin_do_exit))
+                            goto gppn_bad_plugin;
+                        break;
+
+                    default:
+                        log_variadic_message(LMT_WARNING,
+                                             _("Unknown sub-category '0x%02x' in plugin '%s'..."), sub, filename);
+                        break;
+
+                }
+
+                break;
+#if 0
+            case DPC_BINARY_PROCESSING:
+
+                switch (sub)
+                {
+                    case DPS_FORMAT:
+
+                        switch (result->interface->actions[i])
+                        {
+
+                            case PGA_FORMAT_LOADER_LAST:
+                                if (!load_plugin_symbol(result->module,
+                                                        "handle_binary_format", &result->handle_format))
+                                    goto bad_plugin;
+                                break;
+
+                            default:
+                                log_variadic_message(LMT_WARNING,
+                                                     _("Unknown action '0x%02x' in plugin '%s'..."),
+                                                     result->interface->actions[i], filename);
+                                break;
+
+                        }
+
+                        break;
+
+                    case DPS_DISASSEMBLY:
+                        if (!load_plugin_symbol(result->module,
+                                                "process_binary_disassembly", &result->proc_disass))
+                            goto bad_plugin;
+                        break;
+
+                    default:
+                        log_variadic_message(LMT_WARNING,
+                                             _("Unknown sub-category '0x%02x' in plugin '%s'..."), sub, filename);
+                        break;
+
+                }
+
+                break;
+#endif
+            default:
+                log_variadic_message(LMT_WARNING,
+                                     _("Unknown category '0x%02x' in plugin '%s'..."), category, filename);
+                break;
+
+        }
+
+    }
+
+    /* Conclusion */
+
+    if (!g_plugin_module_load(G_PLUGIN_MODULE(result), ref))
+        goto gppn_bad_plugin;
 
     return G_PLUGIN_MODULE(result);
 
+ gppn_bad_plugin:
+
+ gppn_interface_error:
+
+    g_object_unref(G_OBJECT(result));
+
+    //Py_DECREF(instance);
+
  gppn_no_instance:
 
  gppn_no_class:
 
-    Py_DECREF(module);
+    //Py_DECREF(module);
 
  gppn_bad_exit:
 
+    printf("bad exit :(\n");
     return NULL;
 
 }
@@ -271,6 +391,105 @@ GPluginModule *g_python_plugin_new(const char *modname, const char *filename)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : plugin = greffon à initialiser.                              *
+*                                                                             *
+*  Description : Reconstruit la déclaration d'interface à partir de lectures. *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_python_plugin_read_interface(GPythonPlugin *plugin)
+{
+    bool result;                            /* Bilan à renvoyer            */
+    plugin_interface interface;             /* Recueil des éléments        */
+    PyObject *desc;                         /* Tableau de description      */
+    PyObject *str;                          /* Chaîne de caractères        */
+    PyObject *tuple;                        /* Liste d'éléments à traiter  */
+    Py_ssize_t count;                       /* Nombre d'éléments présents  */
+    Py_ssize_t i;                           /* Boucle de parcours          */
+    PyObject *action;                       /* Identifiant d'une action    */
+    plugin_interface *final;                /* Interface finale conservée  */
+
+    result = true;
+
+    desc = run_python_method(plugin->instance, "get_interface", NULL);
+    if (!PyDict_Check(desc))
+    {
+        result = false;
+        goto pgpri_end;
+    }
+
+    memset(&interface, 0, sizeof(interface));
+
+    /* Chargements des premières chaînes */
+
+#define READ_STR_FIELD(name)                            \
+    str = PyDict_GetItemString(desc, #name);            \
+    if ((result = PyUnicode_Check(str)))                \
+        interface.name = strdup(PyUnicode_DATA(str));   \
+
+    READ_STR_FIELD(name);
+    READ_STR_FIELD(desc);
+    READ_STR_FIELD(version);
+
+    /* Chargement des actions supportées */
+
+    tuple = PyDict_GetItemString(desc, "actions");
+
+    if (!PyList_Check(tuple))
+    {
+        result = false;
+        goto pgpri_failed;
+    }
+
+    count = PyList_GET_SIZE(tuple);
+
+    interface.actions = (plugin_action_t *)calloc(count, sizeof(plugin_action_t));
+    interface.actions_count = count;
+
+    for (i = 0; i < count; i++)
+    {
+        action = PyList_GET_ITEM(tuple, i);
+
+        interface.actions[i] = PyLong_AsLong(action);
+
+    }
+
+ pgpri_failed:
+
+    if (result)
+    {
+        final = (plugin_interface *)calloc(1, sizeof(plugin_interface));
+
+        memcpy(final, &interface, sizeof(interface));
+
+        G_PLUGIN_MODULE(plugin)->interface = final;
+
+    }
+    else
+    {
+        if (interface.name != NULL) free((char *)interface.name);
+        if (interface.desc != NULL) free((char *)interface.desc);
+        if (interface.version != NULL) free((char *)interface.version);
+
+        if (interface.actions != NULL) free(interface.actions);
+
+    }
+
+ pgpri_end:
+
+    Py_XDECREF(desc);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : plugin = greffon à initialiser.                              *
 *                ref    = espace de référencement global.                     *
 *                                                                             *
 *  Description : Procède à l'initialisation du greffon.                       *
@@ -286,17 +505,47 @@ static bool g_python_plugin_do_init(GPythonPlugin *plugin, GObject *ref)
     bool result;                            /* Bilan à retourner           */
     PyObject *args;                         /* Arguments pour l'appel      */
     PyObject *value;                        /* Valeur obtenue              */
-    int cmp;                                /* Bilan de la comparaison     */
 
     args = PyTuple_New(1);
     PyTuple_SetItem(args, 0, pygobject_new(ref));
 
     value = run_python_method(plugin->instance, "init", args);
 
-    if (PyObject_Cmp(value, Py_True, &cmp) == -1)
-        result = false;
-    else
-        result = (cmp == 0);
+    result = PyObject_IsTrue(value);
+
+    Py_XDECREF(value);
+    Py_DECREF(args);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : plugin = greffon à initialiser.                              *
+*                ref    = espace de référencement global.                     *
+*                                                                             *
+*  Description : Procède à l'extinction du greffon.                           *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_python_plugin_do_exit(GPythonPlugin *plugin, GObject *ref)
+{
+    bool result;                            /* Bilan à retourner           */
+    PyObject *args;                         /* Arguments pour l'appel      */
+    PyObject *value;                        /* Valeur obtenue              */
+
+    args = PyTuple_New(1);
+    PyTuple_SetItem(args, 0, pygobject_new(ref));
+
+    value = run_python_method(plugin->instance, "exit", args);
+
+    result = PyObject_IsTrue(value);
 
     Py_XDECREF(value);
     Py_DECREF(args);
@@ -306,6 +555,12 @@ static bool g_python_plugin_do_init(GPythonPlugin *plugin, GObject *ref)
 }
 
 
+
+
+
+
+
+
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : plugin = greffon de prise en charge à utiliser.              *
@@ -355,6 +610,9 @@ static PluginAction g_python_plugin_get_action(const GPythonPlugin *plugin)
 
 static MatchingFormatAction g_python_plugin_is_matching(const GPythonPlugin *plugin, char **filename, bin_t **data, off_t *length)
 {
+    return MFA_NONE;
+
+#if 0
     MatchingFormatAction result;            /* Valeur à retourner          */
     PyObject *args;                         /* Arguments pour l'appel      */
     PyObject *value;                        /* Valeurs obtenues            */
@@ -439,7 +697,7 @@ static MatchingFormatAction g_python_plugin_is_matching(const GPythonPlugin *plu
     Py_DECREF(args);
 
     return result;
-
+#endif
 }
 
 
@@ -467,7 +725,7 @@ static bool g_python_plugin_execute_on_binary(GPythonPlugin *plugin, GLoadedBina
     args = PyTuple_New(2);
 
     PyTuple_SetItem(args, 0, pygobject_new(G_OBJECT(binary)));
-    PyTuple_SetItem(args, 1, PyInt_FromLong(action));
+    PyTuple_SetItem(args, 1, Py_None);//PyInt_FromLong(action));
 
     value = run_python_method(plugin->instance, "execute_on_binary", args);
 
@@ -508,7 +766,7 @@ static bool g_python_plugin_handle_debugger(const GPythonPlugin *plugin, GBinary
     args = PyTuple_New(2);
 
     PyTuple_SetItem(args, 0, py_binary_debugger_from_c(debugger));
-    PyTuple_SetItem(args, 1, PyInt_FromLong(action));
+    PyTuple_SetItem(args, 1, Py_None);//PyInt_FromLong(action));
 
     value = run_python_method(plugin->instance, "handle_debugger", args);
 
@@ -533,29 +791,10 @@ static bool g_python_plugin_handle_debugger(const GPythonPlugin *plugin, GBinary
 /* ---------------------------------------------------------------------------------- */
 
 
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : type = type de l'objet à instancier.                         *
-*                args = arguments fournis à l'appel.                          *
-*                kwds = arguments de type key=val fournis.                    *
-*                                                                             *
-*  Description : Crée un nouveau greffon Python abstrait.                     *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
 
-static PyObject *pychrysa_plugin_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
-    pychrysa_plugin *result;                  /* Instance à retourner        */
 
-    result = (pychrysa_plugin *)type->tp_alloc(type, 0);
 
-    return (PyObject *)result;
 
-}
 
 
 
@@ -567,264 +806,123 @@ static PyObject *pychrysa_plugin_new(PyTypeObject *type, PyObject *args, PyObjec
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : dict = dictionnaire à compléter.                             *
+*  Paramètres  : obj_type = type dont le dictionnaire est à compléter.        *
 *                                                                             *
 *  Description : Définit les constantes pour les greffons en Python.          *
 *                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static bool pychrysa_plugin_define_constants(PyObject *dict)
-{
-    int ret;                                /* Bilan d'un ajout            */
-
-    //ret = PyDict_SetItemString(dict, "PGA_NONE", PyInt_FromLong(PGA_NONE));
-    //if (ret == -1) return false;
-
-    ret = PyDict_SetItemString(dict, "PGA_FORMAT_MATCHER", PyInt_FromLong(PGA_FORMAT_MATCHER));
-    if (ret == -1) return false;
-
-    ret = PyDict_SetItemString(dict, "PGA_DISASSEMBLE", PyInt_FromLong(PGA_DISASSEMBLE));
-    if (ret == -1) return false;
-
-    ret = PyDict_SetItemString(dict, "PGA_BINARY_DISASSEMBLED", PyInt_FromLong(PGA_BINARY_DISASSEMBLED));
-    if (ret == -1) return false;
-
-    ret = PyDict_SetItemString(dict, "PGA_BINARY_LINKED", PyInt_FromLong(PGA_BINARY_LINKED));
-    if (ret == -1) return false;
-
-    ret = PyDict_SetItemString(dict, "PGA_BINARY_BOUNDED", PyInt_FromLong(PGA_BINARY_BOUNDED));
-    if (ret == -1) return false;
-
-    ret = PyDict_SetItemString(dict, "PGA_BINARY_GROUPED", PyInt_FromLong(PGA_BINARY_GROUPED));
-    if (ret == -1) return false;
-
-    ret = PyDict_SetItemString(dict, "PGA_BINARY_PRINTED", PyInt_FromLong(PGA_BINARY_PRINTED));
-    if (ret == -1) return false;
-
-    ret = PyDict_SetItemString(dict, "PGA_DISASS_PROCESS", PyInt_FromLong(PGA_DISASS_PROCESS));
-    if (ret == -1) return false;
-
-    ret = PyDict_SetItemString(dict, "PGA_CODE_PROCESS", PyInt_FromLong(PGA_CODE_PROCESS));
-    if (ret == -1) return false;
-
-    ret = PyDict_SetItemString(dict, "PGA_DEBUGGER_ATTACH", PyInt_FromLong(PGA_DEBUGGER_ATTACH));
-    if (ret == -1) return false;
-
-    ret = PyDict_SetItemString(dict, "PGA_DEBUGGER_DETACH", PyInt_FromLong(PGA_DEBUGGER_DETACH));
-    if (ret == -1) return false;
-
-    /* PGA_FORMAT_MATCHER */
-
-    ret = PyDict_SetItemString(dict, "MFA_NONE", PyInt_FromLong(MFA_NONE));
-    if (ret == -1) return false;
-
-    ret = PyDict_SetItemString(dict, "MFA_MATCHED", PyInt_FromLong(MFA_MATCHED));
-    if (ret == -1) return false;
-
-    ret = PyDict_SetItemString(dict, "MFA_RELOAD", PyInt_FromLong(MFA_RELOAD));
-    if (ret == -1) return false;
-
-    return true;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : self = classe assurant le lien avec l'éditeur de messages.   *
-*                args = arguments fournis à l'appel.                          *
-*                                                                             *
-*  Description : Procède à l'initialisation du greffon.                       *
-*                                                                             *
-*  Retour      : Rien en équivalent Python.                                   *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static PyObject *pychrysa_plugin_init(PyObject *self, PyObject *args)
-{
-    Py_INCREF(Py_True);
-    return Py_True;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : self = classe assurant le lien avec l'éditeur de messages.   *
-*                args = arguments fournis à l'appel.                          *
-*                                                                             *
-*  Description : Définit le comportement par défaut d'un greffon Python.      *
-*                                                                             *
-*  Retour      : Rien en équivalent Python.                                   *
+*  Retour      : true en cas de succès de l'opération, false sinon.           *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static PyObject *pychrysa_plugin_get_action(PyObject *self, PyObject *args)
+static bool py_plugin_module_define_constants(PyTypeObject *obj_type)
 {
-    return PyInt_FromLong(0/*PGA_NONE*/);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : self = classe assurant le lien avec l'éditeur de messages.   *
-*                args = arguments fournis à l'appel.                          *
-*                                                                             *
-*  Description : Définit l'issue de la recherche d'un format par défaut.      *
-*                                                                             *
-*  Retour      : Rien en équivalent Python.                                   *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static PyObject *pychrysa_plugin_is_matching(PyObject *self, PyObject *args)
-{
-    PyObject *result;                       /* Liste à retourner           */
-
-    result = PyTuple_New(3);
+    bool result;                            /* Bilan à retourner           */
 
-    PyTuple_SetItem(result, 0, PyInt_FromLong(MFA_NONE));
-    //Py_DECREF(Py_None);
-    PyTuple_SetItem(result, 1, Py_None);
-    //Py_DECREF(Py_None);
-    PyTuple_SetItem(result, 2, Py_None);
+    result = true;
+
+    result &= PyDict_AddIntMacro(obj_type, PGA_BASIC_NONE);
+    result &= PyDict_AddIntMacro(obj_type, PGA_PLUGIN_INIT);
+    result &= PyDict_AddIntMacro(obj_type, PGA_PLUGIN_EXIT);
+    result &= PyDict_AddIntMacro(obj_type, PGA_FORMAT_MATCHER);
+    result &= PyDict_AddIntMacro(obj_type, PGA_FORMAT_LOADER_LAST);
+    result &= PyDict_AddIntMacro(obj_type, PGA_DISASSEMBLY_STARTED);
+    result &= PyDict_AddIntMacro(obj_type, PGA_DISASSEMBLY_RAW);
+    result &= PyDict_AddIntMacro(obj_type, PGA_DISASSEMBLY_HOOKED_LINK);
+    result &= PyDict_AddIntMacro(obj_type, PGA_DISASSEMBLY_HOOKED_POST);
+    result &= PyDict_AddIntMacro(obj_type, PGA_DISASSEMBLY_LIMITED);
+    result &= PyDict_AddIntMacro(obj_type, PGA_DISASSEMBLY_LOOPS);
+    result &= PyDict_AddIntMacro(obj_type, PGA_DISASSEMBLY_LINKED);
+    result &= PyDict_AddIntMacro(obj_type, PGA_DISASSEMBLY_GROUPED);
+    result &= PyDict_AddIntMacro(obj_type, PGA_DISASSEMBLY_RANKED);
+    result &= PyDict_AddIntMacro(obj_type, PGA_DISASSEMBLY_ENDED);
 
     return result;
 
 }
 
 
-
-
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : self = classe assurant le lien avec l'éditeur de messages.   *
-*                args = arguments fournis à l'appel.                          *
+*  Paramètres  : -                                                            *
 *                                                                             *
-*  Description : Exécute une action relative à un débogueur.                  *
+*  Description : Fournit un accès à une définition de type à diffuser.        *
 *                                                                             *
-*  Retour      : True en équivalent Python.                                   *
+*  Retour      : Définition d'objet pour Python.                              *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static PyObject *pychrysa_plugin_handle_debugger(PyObject *self, PyObject *args)
+PyTypeObject *get_python_plugin_module_type(void)
 {
-    Py_RETURN_TRUE;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : self = classe assurant le lien avec l'éditeur de messages.   *
-*                args = arguments fournis à l'appel.                          *
-*                                                                             *
-*  Description : Exécute une action valide pour le greffon Python.            *
-*                                                                             *
-*  Retour      : Rien en équivalent Python.                                   *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
+    static PyMethodDef py_plugin_module_methods[] = {
+        { NULL }
+    };
 
-static PyObject *pychrysa_plugin_run(PyObject *self, PyObject *args)
-{
-    Py_RETURN_NONE;
+    static PyGetSetDef py_plugin_module_getseters[] = {
+        { NULL }
+    };
 
-}
+    static PyTypeObject py_plugin_module_type = {
 
+        PyVarObject_HEAD_INIT(NULL, 0)
 
+        .tp_name        = "pychrysalide.PluginModule",
+        .tp_basicsize   = sizeof(PyGObject),
 
+        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
 
+        .tp_doc         = "Chrysalide plugin for Python.",
 
+        .tp_methods     = py_plugin_module_methods,
+        .tp_getset      = py_plugin_module_getseters
 
+    };
 
+    return &py_plugin_module_type;
 
+}
 
 
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : module = module dont la définition est à compléter.          *
 *                                                                             *
-*  Description : Ajoute l'objet 'plugin' au module Python.                    *
+*  Description : Prend en charge l'objet 'pychrysalide.PluginModule'.         *
 *                                                                             *
-*  Retour      : -                                                            *
+*  Retour      : Bilan de l'opération.                                        *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-bool add_plugin_to_python_module(PyObject *module)
+bool register_python_plugin_module(PyObject *module)
 {
+    PyTypeObject *py_plugin_module_type;    /* Type Python 'PluginModule'  */
     int ret;                                /* Bilan d'un appel            */
+    PyObject *dict;                         /* Dictionnaire du module      */
 
-    static PyMethodDef pychrysa_plugin_methods[] = {
-        {
-            "init", (PyCFunction)pychrysa_plugin_init,
-            METH_VARARGS,
-            "Initialize the plugin."
-        },
-        {
-            "get_action", (PyCFunction)pychrysa_plugin_get_action,
-            METH_NOARGS,
-            "Register the plugin for given actions."
-        },
-        {
-            "is_matching", (PyCFunction)pychrysa_plugin_is_matching,
-            METH_VARARGS,
-            "Define if the given file can be handled."
-        },
-        {
-            "handle_debugger", (PyCFunction)pychrysa_plugin_handle_debugger,
-            METH_VARARGS,
-            "Be notify about debugger attaching or detaching."
-        },
-        {
-            "run", (PyCFunction)pychrysa_plugin_run,
-            METH_VARARGS,
-            "Run the plugin for a specific action."
-        },
-        { NULL }
-    };
-
-    static PyTypeObject pychrysa_plugin_type = {
+    py_plugin_module_type = get_python_plugin_module_type();
 
-        PyObject_HEAD_INIT(NULL)
+    py_plugin_module_type->tp_base = &PyGObject_Type;
+    py_plugin_module_type->tp_basicsize = py_plugin_module_type->tp_base->tp_basicsize;
 
-        .tp_name        = "plugin.Plugin",
-        .tp_basicsize   = sizeof(pychrysa_plugin),
-
-        .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
-
-        .tp_doc         = "PyChrysalide plugin objects",
-
-
-        .tp_methods     = pychrysa_plugin_methods,
-        .tp_new         = (newfunc)pychrysa_plugin_new
-
-    };
-
-    if (PyType_Ready(&pychrysa_plugin_type) < 0)
+    if (PyType_Ready(py_plugin_module_type) != 0)
         return false;
 
-    if (!pychrysa_plugin_define_constants(pychrysa_plugin_type.tp_dict))
+    if (!py_plugin_module_define_constants(py_plugin_module_type))
         return false;
 
-    Py_INCREF(&pychrysa_plugin_type);
-    ret = PyModule_AddObject(module, "Plugin", (PyObject *)&pychrysa_plugin_type);
+    Py_INCREF(py_plugin_module_type);
+    ret = PyModule_AddObject(module, "PluginModule", (PyObject *)py_plugin_module_type);
+    if (ret != 0) return false;
+
+    dict = PyModule_GetDict(module);
+    pygobject_register_class(dict, "PluginModule", G_TYPE_PLUGIN_MODULE, py_plugin_module_type,
+                             Py_BuildValue("(O)", py_plugin_module_type->tp_base));
 
-    return (ret == 0);
+    return true;
 
 }
diff --git a/plugins/pychrysa/plugin.h b/plugins/pychrysa/plugin.h
index c86a343..74e2e26 100644
--- a/plugins/pychrysa/plugin.h
+++ b/plugins/pychrysa/plugin.h
@@ -22,8 +22,8 @@
  */
 
 
-#ifndef _PLUGINS_PYOIDA_PLUGIN_H
-#define _PLUGINS_PYOIDA_PLUGIN_H
+#ifndef _PLUGINS_PYCHRYSA_PLUGIN_H
+#define _PLUGINS_PYCHRYSA_PLUGIN_H
 
 
 #include <Python.h>
@@ -31,16 +31,13 @@
 #include <stdbool.h>
 
 
-#include "../../src/plugins/plugin.h"
+#include <plugins/plugin.h>
 
 
 
 /* --------------------- INTERFACE INTERNE POUR GREFFONS PYTHON --------------------- */
 
 
-
-
-
 #define G_TYPE_PYTHON_PLUGIN                (g_python_plugin_get_type())
 #define G_PYTHON_PLUGIN(obj)                (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_PYTHON_PLUGIN, GPythonPlugin))
 #define G_IS_PYTHON_PLUGIN(obj)             (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_PYTHON_PLUGIN))
@@ -60,29 +57,19 @@ typedef struct _GPythonPluginClass GPythonPluginClass;
 GType g_python_plugin_get_type(void);
 
 /* Crée un greffon à partir de code Python. */
-GPluginModule *g_python_plugin_new(const char *, const char *);
-
-
-
-
-
-
-
-
-int
-main2(const char *filename, const char *method);
-
-
-
+GPluginModule *g_python_plugin_new(const char *, const char *, GObject *);
 
 
 
 /* ------------------------- MODULE PYTHON POUR LES SCRIPTS ------------------------- */
 
 
-/* Ajoute l'objet 'plugin' au module Python. */
-bool add_plugin_to_python_module(PyObject *);
+/* Fournit un accès à une définition de type à diffuser. */
+PyTypeObject *get_python_plugin_module_type(void);
+
+/* Prend en charge l'objet 'pychrysalide.PluginModule'. */
+bool register_python_plugin_module(PyObject *);
 
 
 
-#endif  /* _PLUGINS_PYOIDA_PLUGIN_H */
+#endif  /* _PLUGINS_PYCHRYSA_PLUGIN_H */
diff --git a/plugins/pychrysa/pychrysa.c b/plugins/pychrysa/pychrysa.c
index b6f89a0..eafb358 100644
--- a/plugins/pychrysa/pychrysa.c
+++ b/plugins/pychrysa/pychrysa.c
@@ -214,7 +214,11 @@ bool init_plugin(GPluginModule *plugin, GObject *ref)
 
 
 
-///////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////:///////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////:///////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////:///////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////:///////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////:///////////////////////////
 
 
 #include <stdio.h>
@@ -224,18 +228,21 @@ bool init_plugin(GPluginModule *plugin, GObject *ref)
 
 
 #include <config.h>
+#include <common/environment.h>
+#include <common/extstr.h>
 #include <plugins/plugin-def.h>
 #include <plugins/plugin-int.h>
 
 
+#include "plugin.h"
+#include "quirks.h"
 #include "../../revision.h"
 
 
 
 
 
-
-DEFINE_CHRYSALIDE_ACTIVE_PLUGIN("PyChrysalide", "Provides bindings to Python", "0.1.0", PGA_ALL);
+DEFINE_CHRYSALIDE_ACTIVE_PLUGIN("PyChrysalide", "Provides bindings to Python", "0.1.0", PGA_PLUGIN_INIT);
 
 
 /* Fournit la version du programme global. */
@@ -247,7 +254,8 @@ static PyObject *py_chrysalide_mod_version(PyObject *, PyObject *);
 /* Détermine si l'interpréteur lancé est celui pris en compte. */
 static bool is_current_abi_suitable(void);
 
-
+/* Charge autant de greffons composés en Python que possible. */
+static bool load_python_plugins(GPluginModule *plugin, GObject *);
 
 
 
@@ -428,10 +436,8 @@ PyMODINIT_FUNC PyInit_pychrysalide(void)
     };
 
 
-    // TODO : à bouger !
-    //init_all_processors();
-    //init_all_formats();
 
+#if 0
     do
     {
         int argc = 0;
@@ -448,11 +454,14 @@ PyMODINIT_FUNC PyInit_pychrysalide(void)
     add_pixmap_directory(PACKAGE_SOURCE_DIR G_DIR_SEPARATOR_S "pixmaps");
 
     init_work_queue(NULL/* !! */);
-
+#endif
 
     ////////////////////////
 
 
+
+
+
     if (!is_current_abi_suitable())
         return NULL;
 
@@ -468,17 +477,25 @@ PyMODINIT_FUNC PyInit_pychrysalide(void)
         return NULL;
     }
 
+    /* Préparatifs préalables aux chargements */
+
     /**
      * Pour une raison non identifiée, si le module n'est pas préchargé,
      * le flot d'exécution plante dans la fonction insertdict() de Objects/dictobject.c:818.
      */
+
     pygobj_mod = PyImport_ImportModule("gi.repository.GObject");
     if (pygobj_mod == NULL)
+    {
+        PyErr_SetString(PyExc_ImportError, "could not import gi.gobject");
         return NULL;
+    }
+
+    /* Mise en place des fonctionnalités offertes */
 
     result = PyModule_Create(&py_chrysalide_module);
 
-    status = true;
+    status = register_python_plugin_module(result);
 
     status &= add_analysis_module_to_python_module(result);
     status &= add_arch_module_to_python_module(result);
@@ -498,3 +515,139 @@ PyMODINIT_FUNC PyInit_pychrysalide(void)
     return result;
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : plugin = instance représentant le greffon Python d'origine.  *
+*                ref    = espace de référencement global.                     *
+*                                                                             *
+*  Description : Charge autant de greffons composés en Python que possible.   *
+*                                                                             *
+*  Retour      : true.                                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool load_python_plugins(GPluginModule *plugin, GObject *ref)
+{
+    char *paths;                            /* Emplacements de greffons    */
+    char *save;                             /* Sauvegarde pour ré-entrance */
+    char *path;                             /* Chemin à fouiller           */
+    DIR *dir;                               /* Répertoire à parcourir      */
+    struct dirent entry;                    /* Elément trouvé              */
+    struct dirent *next;                    /* Prochain élément fourni     */
+    int ret;                                /* Bilan d'un appel système    */
+    char *modname;                          /* Nom du module pour Python   */
+    char *filename;                         /* Chemin d'accès reconstruit  */
+    GPluginModule *pyplugin;                /* Lien vers un grffon Python  */
+
+    paths = get_env_var("PYTHONPATH");
+
+    save = NULL;   /* gcc... */
+
+    for (path = strtok_r(paths, ";", &save);
+         path != NULL; 
+         path = strtok_r(NULL, ";", &save))
+    {
+        dir = opendir(path);
+        if (dir == NULL)
+        {
+            perror("opendir");
+            continue;
+        }
+
+        g_plugin_module_log_variadic_message(plugin, LMT_INFO, 
+                                             _("Looking for Python plugins in '%s'..."),
+                                             path);
+
+        for (ret = readdir_r(dir, &entry, &next);
+             ret == 0 && next != NULL;
+             ret = readdir_r(dir, &entry, &next))
+        {
+            if (entry.d_type != DT_DIR) continue;
+            if (entry.d_name[0] == '.') continue;
+
+            modname = strdup(entry.d_name);
+            modname = stradd(modname, ".");
+            modname = stradd(modname, "__init__");
+
+            filename = strdup(path);
+            filename = stradd(filename, G_DIR_SEPARATOR_S);
+            filename = stradd(filename, entry.d_name);
+
+            pyplugin = g_python_plugin_new(modname, filename, ref);
+
+            if (pyplugin == NULL)
+                g_plugin_module_log_variadic_message(plugin, LMT_ERROR, 
+                                                     _("No suitable Python plugin found in '%s'"),
+                                                     filename);
+            else
+            {
+                g_plugin_module_log_variadic_message(plugin, LMT_PROCESS, 
+                                                     _("Loaded the Python plugin found in the '<b>%s</b>' directory"),
+                                                     filename);
+                add_plugin_to_main_list(pyplugin);
+            }
+
+            free(filename);
+            free(modname);
+
+        }
+
+         closedir(dir);
+
+    }
+
+    return true;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : plugin = greffon à manipuler.                                *
+*                ref    = espace de référencement global.                     *
+*                                                                             *
+*  Description : Prend acte du chargement du greffon.                         *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin, GObject *ref)
+{
+    bool result;                            /* Bilan à retourner           */
+    DIR *dir;                               /* Répertoire à parcourir      */
+
+    define_internal_ref(ref);
+
+    /* Définition des zones d'influence */
+
+    dir = opendir(PLUGINS_DIR G_DIR_SEPARATOR_S "python");
+
+    if (dir != NULL)
+    {
+         closedir(dir);
+         add_to_env_var("PYTHONPATH", PLUGINS_DIR G_DIR_SEPARATOR_S "python", ";");
+    }
+    else
+        add_to_env_var("PYTHONPATH", PACKAGE_SOURCE_DIR G_DIR_SEPARATOR_S "plugins" \
+                       G_DIR_SEPARATOR_S "python", ";");
+
+    /* Chargement du module pour Python */
+
+    PyImport_AppendInittab("pychrysalide", &PyInit_pychrysalide);
+
+    Py_Initialize();
+
+    PySys_SetArgv(0, (wchar_t *[]) { NULL });
+
+    result = load_python_plugins(plugin, ref);
+
+    return result;
+
+}
diff --git a/plugins/pychrysa/pychrysa.h b/plugins/pychrysa/pychrysa.h
index 0fdc074..4e36e00 100644
--- a/plugins/pychrysa/pychrysa.h
+++ b/plugins/pychrysa/pychrysa.h
@@ -81,9 +81,16 @@ PyMODINIT_FUNC initpychrysa(void);
 
 
 
+#include <plugins/plugin.h>
+
+
+
 /* Point d'entrée pour l'initialisation de Python. */
 PyMODINIT_FUNC PyInit_pychrysalide(void);
 
+/* Prend acte du chargement du greffon. */
+G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *, GObject *);
+
 
 
 #endif  /* _PLUGINS_PYCHRYSA_H */
diff --git a/plugins/pychrysa/quirks.c b/plugins/pychrysa/quirks.c
index 4aa8536..9384b37 100644
--- a/plugins/pychrysa/quirks.c
+++ b/plugins/pychrysa/quirks.c
@@ -26,6 +26,9 @@
 
 
 
+
+#if 0
+
 //#include <pyglib.h>
 #include <pygobject.h>
 
@@ -255,6 +258,15 @@ int pychrysalide_allow_args_for_gobjects(PyObject *self, PyObject *args, PyObjec
     return 0;
 
 }
+#endif
+
+
+
+
+
+/* Mémorisation de l'espace de référencement global */
+static GObject *_ref = NULL;
+
 
 
 /******************************************************************************
diff --git a/plugins/pychrysa/quirks.h b/plugins/pychrysa/quirks.h
index 89977a0..f1364be 100644
--- a/plugins/pychrysa/quirks.h
+++ b/plugins/pychrysa/quirks.h
@@ -26,11 +26,11 @@
 #define _PLUGINS_PYOIDA_QUIRKS_H
 
 
-#include <Python.h>
+//#include <Python.h>
 #include <glib-object.h>
 
 
-
+#if 0
 /* Définit les éléments immuables pour toute association. */
 void pychrysalide_init_quirks(void);
 
@@ -45,6 +45,9 @@ PyObject *pychrysalide_get_pygobject(GObject *);
 
 /* Initialise un objet dérivé de GObject en Python. */
 int pychrysalide_allow_args_for_gobjects(PyObject *, PyObject *, PyObject *);
+#endif
+
+
 
 /* Evite à Python d'avoir à manipuler les références internes. */
 GObject *_get_internal_ref(GObject *);
diff --git a/src/plugins/plugin-def.h b/src/plugins/plugin-def.h
index 68f9942..b73ee97 100644
--- a/src/plugins/plugin-def.h
+++ b/src/plugins/plugin-def.h
@@ -103,7 +103,7 @@ typedef enum _PluginAction
     PGA_BASIC_NONE = DPC_BASIC | DPS_NONE | DEFINE_PLUGIN_ACTION(0),
 
     /**
-     * DPC_BASIC | DPS_NONE
+     * DPC_BASIC | DPS_PG_MANAGEMENT
      */
 
     /* Chargement */
diff --git a/src/plugins/plugin-int.h b/src/plugins/plugin-int.h
index 1f4e17e..f136d3f 100644
--- a/src/plugins/plugin-int.h
+++ b/src/plugins/plugin-int.h
@@ -120,6 +120,9 @@ struct _GPluginModuleClass
 
 
 
+/* Termine le chargement du greffon préparé. */
+bool g_plugin_module_load(GPluginModule *, GObject *);
+
 /* Présente dans le journal un message simple. */
 void g_plugin_module_log_simple_message(const GPluginModule *, LogMessageType, const char *);
 
diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c
index 65f3cc6..9322bcb 100644
--- a/src/plugins/plugin.c
+++ b/src/plugins/plugin.c
@@ -164,7 +164,6 @@ GPluginModule *g_plugin_module_new(const gchar *filename, GObject *ref)
     size_t i;                               /* Boucle de parcours          */
     uint32_t category;                      /* Catégorie principale        */
     uint32_t sub;                           /* Sous-catégorie visée        */
-    char *dir;                              /* Répertoire modifiable       */
 
     result = g_object_new(G_TYPE_PLUGIN_MODULE, NULL);
 
@@ -300,32 +299,62 @@ GPluginModule *g_plugin_module_new(const gchar *filename, GObject *ref)
 
     /* Conclusion */
 
-    dir = strdup(filename);
+    if (!g_plugin_module_load(result, ref))
+        goto bad_plugin;
+
+    return result;
+
+ bad_plugin:
+
+    g_object_unref(G_OBJECT(result));
+
+    return NULL;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : plugin = greffon à valider.                                  *
+*                ref    = espace de référencement global.                     *
+*                                                                             *
+*  Description : Termine le chargement du greffon préparé.                    *
+*                                                                             *
+*  Retour      : Bilan du chargement effectif.                                *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_plugin_module_load(GPluginModule *plugin, GObject *ref)
+{
+    bool result;                            /* Bilan à faire remonter      */
+    char *dir;                              /* Répertoire modifiable       */
+
+    result = true;
+
+    dir = strdup(plugin->filename);
     dir = dirname(dir);
 
-    if (result->init != NULL)
+    if (plugin->init != NULL)
     {
-        if (!result->init(result, ref))
+        if (!plugin->init(plugin, ref))
         {
             log_variadic_message(LMT_ERROR,
-                                 _("Plugin '%s' failed to load itself..."), filename);
-            goto bad_plugin;
+                                 _("Plugin '%s' failed to load itself..."), plugin->filename);
+            result = false;
         }
     }
 
-    log_variadic_message(LMT_PROCESS, _("Loaded the '<b>%s</b>' from the '<b>%s</b>' directory"),
-                         strrchr(filename, G_DIR_SEPARATOR) + 1, dir);
+    if (result)
+        log_variadic_message(LMT_PROCESS,
+                             _("Loaded the '<b>%s</b>' file as plugin from the '<b>%s</b>' directory"),
+                             strrchr(plugin->filename, G_DIR_SEPARATOR) + 1, dir);
 
     free(dir);
 
     return result;
 
- bad_plugin:
-
-    g_object_unref(G_OBJECT(result));
-
-    return NULL;
-
 }
 
 
-- 
cgit v0.11.2-87-g4458