From 02cb3aa4e7b18b644b034a5c659c332becf99c9b Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sat, 1 Oct 2011 17:20:50 +0000
Subject: Defined the first real [python] plugin.

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@210 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                           |  36 ++++++
 plugins/pyoida/plugin.c             | 250 +++++++++++++++++++++++++++++++++++-
 plugins/pyoida/plugin.h             |   2 +-
 plugins/pyoida/pyoida.c             | 118 ++++++++++++++---
 plugins/python/apkfiles/__init__.py |   2 +
 plugins/python/apkfiles/apkfiles.py |  34 +++++
 src/analysis/binary.c               |  41 +++++-
 src/common/environment.c            |   2 +-
 src/format/dex/dex.c                |   2 +
 src/format/format.c                 |  54 +++++++-
 src/format/format.h                 |   2 +-
 src/gtkext/gtksourceview.c          |   3 +
 src/plugins/plugin-def.h            |  27 +++-
 src/plugins/plugin-int.h            |  12 +-
 src/plugins/plugin.c                |  81 ++++++++++--
 src/plugins/plugin.h                |   6 +
 16 files changed, 622 insertions(+), 50 deletions(-)
 create mode 100644 plugins/python/apkfiles/__init__.py
 create mode 100644 plugins/python/apkfiles/apkfiles.py

diff --git a/ChangeLog b/ChangeLog
index 565f288..b2b399e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,39 @@
+11-10-01  Cyrille Bagard <nocbos@gmail.com>
+
+	* plugins/pyoida/plugin.c:
+	* plugins/pyoida/plugin.h:
+	Properly load a Python plugin and define some needed functions
+	for format recognition.
+
+	* plugins/pyoida/pyoida.c:
+	Browse directories for finding Python plugins.
+
+	* plugins/python/apkfiles/apkfiles.py:
+	* plugins/python/apkfiles/__init__.py:
+	New entries: define the first real [python] plugin.
+
+	* src/analysis/binary.c:
+	Start to update call to load_new_format().
+
+	* src/common/environment.c:
+	Fix a bug when getting an environment variable.
+
+	* src/format/dex/dex.c:
+	Dummy fix.
+
+	* src/format/format.c:
+	* src/format/format.h:
+	Load formats usings plugins too.
+
+	* src/gtkext/gtksourceview.c:
+	Dummy fix.
+
+	* src/plugins/plugin.c:
+	* src/plugins/plugin-def.h:
+	* src/plugins/plugin.h:
+	* src/plugins/plugin-int.h:
+	Update interfaces for plugins (mainly those which are looking for formats).
+
 11-07-11  Cyrille Bagard <nocbos@gmail.com>
 
 	* configure.ac:
diff --git a/plugins/pyoida/plugin.c b/plugins/pyoida/plugin.c
index 23934a9..e652949 100644
--- a/plugins/pyoida/plugin.c
+++ b/plugins/pyoida/plugin.c
@@ -46,6 +46,7 @@ struct _GPythonPlugin
     GPluginModule parent;                   /* Instance parente            */
 
     PyObject *module;                       /* Script Python chargé        */
+    PyObject *instance;                     /* Instance Python du greffon  */
 
 };
 
@@ -64,6 +65,12 @@ static void g_python_plugin_class_init(GPythonPluginClass *);
 /* Initialise l'instance d'un greffon Python. */
 static void g_python_plugin_init(GPythonPlugin *);
 
+/* Indique l'utilité pratique du greffon. */
+static PluginAction g_python_plugin_get_action(const GPythonPlugin *);
+
+/* Indentifie un format à associer à un contenu binaire. */
+static MatchingFormatAction g_python_plugin_is_matching(const GPythonPlugin *, char **, bin_t **, off_t *);
+
 /* Exécute une action définie sur un binaire chargé. */
 static bool g_python_plugin_execute(GPythonPlugin *, GOpenidaBinary *, PluginAction);
 
@@ -94,7 +101,11 @@ static PyObject *pyoida_plugin_run(PyObject *, PyObject *);
 /* Définit les constantes pour les greffons en Python. */
 static bool pyoida_plugin_define_constants(PyObject *);
 
+/* Définit le comportement par défaut d'un greffon Python. */
+static PyObject *pyoida_plugin_get_action(PyObject *, PyObject *);
 
+/* Définit l'issue de la recherche d'un format par défaut. */
+static PyObject *pyoida_plugin_is_matching(PyObject *, PyObject *);
 
 
 
@@ -260,7 +271,8 @@ PyObject *run_python_method(PyObject *module, const char *method, PyObject *args
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : filename = chemin d'accès au code Python à charger.          *
+*  Paramètres  : modname  = nom du module à charger.                          *
+*                filename = chemin d'accès au code Python à charger.          *
 *                                                                             *
 *  Description : Crée un greffon à partir de code Python.                     *
 *                                                                             *
@@ -270,18 +282,20 @@ PyObject *run_python_method(PyObject *module, const char *method, PyObject *args
 *                                                                             *
 ******************************************************************************/
 
-GPluginModule *g_python_plugin_new(const char *filename)
+GPluginModule *g_python_plugin_new(const char *modname, const char *filename)
 {
     GPythonPlugin *result;                  /* Structure à retourner       */
     PyObject *name;                         /* Chemin d'accès pour Python  */
     PyObject *module;                       /* Script Python chargé        */
+    PyObject *dict;                         /* Dictionnaire associé        */
+    PyObject *class;                        /* Classe à instancier         */
+    PyObject *instance;                     /* Instance Python du greffon  */
 
 #if PY_VERSION_HEX >= 0x03000000
     name = PyUnicode_FromString(filename);
 #else
     name = PyString_FromString(filename);
 #endif
-    name = PyString_FromString/*PyUnicode_FromString*/(filename);
     if (name == NULL) goto gppn_bad_exit;
 
     module = PyImport_Import(name);
@@ -293,20 +307,37 @@ GPluginModule *g_python_plugin_new(const char *filename)
         goto gppn_bad_exit;
     }
 
+    dict = PyModule_GetDict(module);
+    class = PyDict_GetItemString(dict, modname);
+    Py_DECREF(dict);
 
+    if (class == NULL) goto gppn_no_class;
+    if (!PyType_Check(class->ob_type)) goto gppn_no_class;
 
-    //Py_DECREF(module);
-
+    instance = PyObject_CallFunction(class, NULL);
+    if (instance == NULL) goto gppn_no_instance;
 
+    Py_DECREF(class);
 
     result = g_object_new(G_TYPE_PYTHON_PLUGIN, NULL);
 
-    G_PLUGIN_MODULE(result)->action = PGA_CODE_PROCESS;
+    G_PLUGIN_MODULE(result)->get_action = g_python_plugin_get_action;
+
+    G_PLUGIN_MODULE(result)->is_matching = g_python_plugin_is_matching;
 
     result->module = module;
+    result->instance = instance;
 
     return G_PLUGIN_MODULE(result);
 
+ gppn_no_instance:
+
+    Py_DECREF(class);
+
+ gppn_no_class:
+
+    Py_DECREF(module);
+
  gppn_bad_exit:
 
     return NULL;
@@ -317,6 +348,138 @@ GPluginModule *g_python_plugin_new(const char *filename)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : plugin = greffon de prise en charge à utiliser.              *
+*                                                                             *
+*  Description : Indique l'utilité pratique du greffon.                       *
+*                                                                             *
+*  Retour      : Action(s) codifiée(s), PGA_NONE par défaut.                  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PluginAction g_python_plugin_get_action(const GPythonPlugin *plugin)
+{
+    PluginAction result;                    /* Valeur à retourner          */
+    PyObject *value;                        /* Valeur obtenue              */
+
+    value = run_python_method(plugin->instance, "get_action", NULL);
+
+    result = PyLong_AsLong(value);
+    Py_DECREF(value);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : plugin   = greffon de prise en charge à utiliser.            *
+*                filename = éventuel nom de fichier associé ou NULL. [OUT]    *
+*                data     = données chargées. [OUT]                           *
+*                length   = quantité de ces données. [OUT]                    *
+*                                                                             *
+*  Description : Indentifie un format à associer à un contenu binaire.        *
+*                                                                             *
+*  Retour      : Bilan de la recherche de correspondances.                    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static MatchingFormatAction g_python_plugin_is_matching(const GPythonPlugin *plugin, char **filename, bin_t **data, off_t *length)
+{
+    MatchingFormatAction result;            /* Valeur à retourner          */
+    PyObject *args;                         /* Arguments pour l'appel      */
+    PyObject *value;                        /* Valeurs obtenues            */
+    PyObject *action;                       /* Action à faire suivre       */
+    PyObject *new_filename;                 /* Nouveau fichier             */
+    PyObject *new_data;                     /* Nouvelles données           */
+    char *tmp;                              /* Stockage avant recopie      */
+
+    if (*filename == NULL)
+        return MFA_NONE;
+
+    args = PyTuple_New(2);
+
+    PyTuple_SetItem(args, 0, PyString_FromString(*filename));
+    PyTuple_SetItem(args, 1, PyByteArray_FromStringAndSize(*data, *length));
+
+    value = run_python_method(plugin->instance, "is_matching", args);
+
+    if (value != NULL && PyTuple_Check(value) && PyTuple_Size(value) == 3)
+    {
+        action = PyTuple_GetItem(value, 0);
+        new_filename = PyTuple_GetItem(value, 1);
+        new_data = PyTuple_GetItem(value, 2);
+
+        if (action == NULL || new_filename == NULL || new_data == NULL)
+            goto is_matching_bad;
+
+        if (!PyInt_Check(action)
+            || (new_filename != Py_None && !PyString_Check(new_filename))
+            || (new_data != Py_None && !PyByteArray_Check(new_data)))
+            goto is_matching_bad;
+
+        result = PyInt_AsLong(action);
+        if (result >= MFA_COUNT) goto is_matching_bad;
+
+        if (result != MFA_NONE && new_data == Py_None) goto is_matching_bad;
+
+        if (new_filename != Py_None)
+            *filename = strdup(PyString_AsString(new_filename));
+        /**
+         * La suppression de la part du greffon n'est permise que
+         * si une prise en charge est assurée.
+         */
+        else if (result != MFA_NONE)
+            *filename = NULL;
+
+        /**
+         * Pareil que précédemment.
+         */
+        if (new_data != Py_None)
+        {
+            tmp = PyByteArray_AsString(new_data);
+            *length = PyByteArray_Size(new_data);
+
+            *data = (bin_t *)calloc(*length, sizeof(bin_t));
+            memcpy(*data, tmp, *length * sizeof(bin_t));
+
+        }
+
+        goto is_matching_ok;
+
+    }
+
+ is_matching_bad:
+
+    printf("<LOG>Bad result from is_matching() plugin function.\n");
+
+    result = MFA_NONE;
+
+ is_matching_ok:
+
+    Py_XDECREF(value);
+    Py_DECREF(args);
+
+    return result;
+
+}
+
+
+
+
+
+
+
+
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : plugin = greffon de prise en charge à utiliser.              *
 *                binary = représentation binaire à traiter.                   *
 *                action = action attendue.                                    *
 *                                                                             *
@@ -421,12 +584,29 @@ static bool pyoida_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_CODE_PROCESS", PyInt_FromLong(PGA_CODE_PROCESS));
     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;
 
 }
@@ -437,6 +617,58 @@ static bool pyoida_plugin_define_constants(PyObject *dict)
 *  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.                                   *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *pyoida_plugin_get_action(PyObject *self, PyObject *args)
+{
+    return PyInt_FromLong(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 *pyoida_plugin_is_matching(PyObject *self, PyObject *args)
+{
+    PyObject *result;                       /* Liste à retourner           */
+
+    result = PyTuple_New(3);
+
+    PyTuple_SetItem(result, 0, PyInt_FromLong(MFA_NONE));
+    PyTuple_SetItem(result, 1, Py_None);
+    PyTuple_SetItem(result, 2, Py_None);
+
+    return result;
+
+}
+
+
+
+
+
+
+/******************************************************************************
+*                                                                             *
+*  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.                                   *
@@ -474,6 +706,12 @@ bool add_plugin_to_python_module(PyObject *module)
 
 
 static PyMethodDef pyoida_plugin_methods[] = {
+    { "get_action", (PyCFunction)pyoida_plugin_get_action, METH_NOARGS,
+     "Register the plugin for given actions."
+    },
+    { "is_matching", (PyCFunction)pyoida_plugin_is_matching, METH_VARARGS,
+     "Define if the given file can be handled."
+    },
     { "run", (PyCFunction)pyoida_plugin_run, METH_VARARGS,
      "Run the plugin for a specific action."
     },
diff --git a/plugins/pyoida/plugin.h b/plugins/pyoida/plugin.h
index f5d4ab4..b8b76d9 100644
--- a/plugins/pyoida/plugin.h
+++ b/plugins/pyoida/plugin.h
@@ -60,7 +60,7 @@ 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 *);
+GPluginModule *g_python_plugin_new(const char *, const char *);
 
 
 
diff --git a/plugins/pyoida/pyoida.c b/plugins/pyoida/pyoida.c
index 4a79bfd..be75b7c 100644
--- a/plugins/pyoida/pyoida.c
+++ b/plugins/pyoida/pyoida.c
@@ -24,6 +24,10 @@
 #include "pyoida.h"
 
 
+#include <config.h>
+#include <dirent.h>
+
+
 #include <Python.h>
 
 
@@ -69,6 +73,7 @@ static PyMethodDef SpamMethods[] = {
 
 
 
+static PyObject *__mod;
 
 
 /******************************************************************************
@@ -85,17 +90,37 @@ static PyMethodDef SpamMethods[] = {
 
 bool init_plugin(GObject *ref)
 {
+    char *paths;                            /* Emplacements de greffons    */
+    char *path;                             /* Chemin à fouiller           */
+    char *save;                             /* Sauvegarde pour ré-entrance */
+    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 *filename;                         /* Chemin d'accès reconstruit  */
+
+
+
+
     GPluginModule *plugin;
-    int ret;
+
+
 
     printf("Init pyoida\n");
 
     _ref = ref;
 
-    add_to_env_var("PYTHONPATH", "/home/ocb/prog/openida/plugins/python", ";");
+
+    /* Définition des zones d'influence */
+
+    add_to_env_var("PYTHONPATH", PLUGINS_DIR G_DIR_SEPARATOR_S "python", ";");
+
+    paths = get_env_var("PYTHONPATH");
+
+    /* Intialisations Python */
 
 
-    return false;
+    //return false;
 
 
     Py_Initialize();
@@ -104,33 +129,92 @@ bool init_plugin(GObject *ref)
 
 
 
+    /* Chargement des greffons */
 
-    plugin = g_python_plugin_new("lnxsyscalls/lnxsyscalls");
-    add_plugin_to_main_list(plugin);
+    printf("Paths :: '%s'\n", paths);
 
+    for (path = strtok_r(paths, ";", &save);
+         path != NULL; 
+         path = strtok_r(NULL, ";", &save))
+    {
+        dir = opendir(path);
+        if (dir == NULL)
+        {
+            perror("opendir");
+            continue;
+        }
 
+        printf("CHEMIN :: '%s'\n", path);
 
-#if 0
+        for (ret = readdir_r(dir, &entry, &next);
+             ret == 0 && next != NULL;
+             ret = readdir_r(dir, &entry, &next))
+        {
+            if (entry.d_name[0] == '.') continue;
 
-#if 0
-    //main2("/home/ocb/prog/openida/plugins/pyoida/lnxsyscalls/lnxsyscalls.py", "get_instance");
-    main2("lnxsyscalls", "get_instance");
-#else
-    //main2("/home/ocb/prog/openida/plugins/pyoida/lnxsyscalls/lnxsyscalls.py", "get_instance");
-    main2("lnxsyscalls/lnxsyscalls", "get_instance");
-#endif
+            filename = strdup(entry.d_name);
+            filename = stradd(filename, ".");
+            filename = stradd(filename, "__init__");
 
-#endif
+            printf(" - entry :: '%s'\n", filename);
 
-    //Py_Finalize();
 
-    //exit(-1);
+            plugin = g_python_plugin_new(entry.d_name, filename);
+
+            if (plugin == NULL)
+                 printf("No suitable Python plugin found in '%s'\n", filename);  /* FIXME : LOG(...) */
+            else
+            {
+                printf("ok pour %s\n", filename);
+                add_plugin_to_main_list(plugin);
+            }
+
+            free(filename);
+
+        }
+
+         closedir(dir);
+
+         break; /* FIXME */
+
+    }
+
+    //Py_Finalize();
 
     return true;
 
 }
 
 
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : plugin = greffon à consulter.                                *
+*                                                                             *
+*  Description : Indique les opérations offertes par un greffon donné.        *
+*                                                                             *
+*  Retour      : Action(s) offerte(s) par le greffon.                         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+PluginAction get_plugin_action(const GPluginModule *plugin)
+{
+    PluginAction result;                    /* Combinaison à retourner     */
+
+    result = PGA_NONE;
+
+
+
+
+    return result;
+
+}
+
+
+
+
+
 #if PY_VERSION_HEX >= 0x03000000
 
 /* Python 3.x code */
@@ -169,6 +253,8 @@ initpyoida(void)
     printf("Passage 2\n");
     module = Py_InitModule("pyoida", SpamMethods);
 
+    __mod = module;
+
     //add_analysis_roptions_to_python_module(module);
     add_analysis_module_to_python_module(module);
     add_arch_module_to_python_module(module);
diff --git a/plugins/python/apkfiles/__init__.py b/plugins/python/apkfiles/__init__.py
new file mode 100644
index 0000000..2ebf824
--- /dev/null
+++ b/plugins/python/apkfiles/__init__.py
@@ -0,0 +1,2 @@
+
+from apkfiles import ApkFiles as apkfiles
diff --git a/plugins/python/apkfiles/apkfiles.py b/plugins/python/apkfiles/apkfiles.py
new file mode 100644
index 0000000..fe7deb8
--- /dev/null
+++ b/plugins/python/apkfiles/apkfiles.py
@@ -0,0 +1,34 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+from pyoida import Plugin
+
+import zipfile
+
+
+class ApkFiles(Plugin):
+    """Open and process APK files."""
+
+    def get_action(self):
+        """Register the plugin for given actions."""
+
+        return Plugin.PGA_FORMAT_MATCHER
+
+    def is_matching(self, filename, data):
+        """Define if the given file can be handled."""
+
+        if not zipfile.is_zipfile(filename):
+            return Plugin.MFA_NONE, None, None
+
+        zf = zipfile.ZipFile(filename)
+
+        if zf.namelist().count('classes.dex') > 0:
+
+            f = zf.open('classes.dex', 'r')
+            data = f.read()
+            f.closed
+
+            return Plugin.MFA_RELOAD, None, bytearray(data)
+
+        else:
+            return Plugin.MFA_NONE, None, None
diff --git a/src/analysis/binary.c b/src/analysis/binary.c
index 15be43e..f5ff3fb 100644
--- a/src/analysis/binary.c
+++ b/src/analysis/binary.c
@@ -365,17 +365,56 @@ static void g_openida_binary_init(GOpenidaBinary *binary)
 GOpenidaBinary *g_openida_binary_new_from_file(const char *filename)
 {
     GOpenidaBinary *result;                 /* Adresse à retourner         */
+    GPluginModule **pglist;                 /* Liste de greffons           */
+    size_t pgcount;                         /* Taille de cette liste       */
+    size_t i;                               /* Boucle de parcours          */
+
+
+    char *file = strdup(filename);
 
     result = g_object_new(G_TYPE_OPENIDA_BINARY, NULL);
 
+
+
+
+    printf("%s\n", filename);
+
+
+
+    pglist = get_all_plugins_for_action(PGA_FORMAT_MATCHER, &pgcount);
+
+    if (pgcount > 0)
+    {
+        printf("===>>>> FOUND :: %d\n", pgcount);
+
+
+        /*
+        for (i = 0; i < pgcount; i++)
+            g_plugin_module_execute_action_on_binary(pglist[i], binary, PGA_CODE_PROCESS);
+        */
+        free(pglist);
+
+    }
+
+
+
+
+
+
+
+
+
     log_variadic_message(LMT_PROCESS, _("Opening '%s' file..."), filename);
 
     result->filename = strdup(filename);
 
+    /*
     result->bin_data = map_binary_file(filename, &result->bin_length);
     if (result->bin_data == NULL) goto lbf_error;
+    */
 
-    result->format = G_EXE_FORMAT(load_new_format(FMT_EXEC, result->bin_data, result->bin_length));
+    result->format = G_EXE_FORMAT(load_new_format(FMT_EXEC, file,
+                                                  &result->bin_data, &result->bin_length));
     if (result->format == NULL)
     {
         log_simple_message(LMT_INFO, _("Unknown binary format"));
diff --git a/src/common/environment.c b/src/common/environment.c
index a0fa568..633d3e2 100644
--- a/src/common/environment.c
+++ b/src/common/environment.c
@@ -52,7 +52,7 @@ char *get_env_var(const char *name)
     result = getenv(name);
 
     if (result == NULL) result = strdup("");
-    else result = strdup(name);
+    else result = strdup(result);
 
     return result;
 
diff --git a/src/format/dex/dex.c b/src/format/dex/dex.c
index 174bd2b..287c9ea 100755
--- a/src/format/dex/dex.c
+++ b/src/format/dex/dex.c
@@ -224,6 +224,8 @@ static void g_dex_format_find_all_sources(GDexFormat *format)
 
     bf = G_BIN_FORMAT(format);
 
+    return; /* FIXME */
+
     for (i = 0; i < format->classes_count; i++)
     {
         source = g_dex_class_get_source_file(format->classes[i], format);
diff --git a/src/format/format.c b/src/format/format.c
index 053a7aa..8e1d864 100644
--- a/src/format/format.c
+++ b/src/format/format.c
@@ -35,6 +35,7 @@
 #include "pe/pe.h"
 #include "../decomp/expr/block.h"
 #include "../panels/log.h"
+#include "../plugins/pglist.h"
 
 
 
@@ -497,9 +498,10 @@ bool init_all_formats(void)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : type    = type de format recherché.                          *
-*                content = contenu binaire à parcourir.                       *
-*                length  = taille du contenu en question.                     *
+*  Paramètres  : type     = type de format recherché.                         *
+*                filename = fichier d'origine des données initiales.          *
+*                content  = contenu binaire à parcourir. [OUT]                *
+*                length   = taille du contenu en question. [OUT]              *
 *                                                                             *
 *  Description : Charge si possible un nouveau format binaire.                *
 *                                                                             *
@@ -509,22 +511,62 @@ bool init_all_formats(void)
 *                                                                             *
 ******************************************************************************/
 
-GBinFormat *load_new_format(FormatType type, const uint8_t *content, off_t length)
+GBinFormat *load_new_format(FormatType type, char *filename, bin_t **content, off_t *length)
 {
     GBinFormat *result;                     /* Adresse à retourner         */
+    GPluginModule **pglist;                 /* Liste de greffons           */
+    size_t pgcount;                         /* Taille de cette liste       */
     size_t i;                               /* Boucle de parcours          */
 
     result = NULL;
 
+    printf("analysing... %s\n", filename);
+
+
+
+    pglist = get_all_plugins_for_action(PGA_FORMAT_MATCHER, &pgcount);
+
+    if (pgcount > 0)
+    {
+ lnf_rescan:
+
+        for (i = 0; i < pgcount; i++)
+            switch (g_plugin_module_is_matching(pglist[i], &filename, content, length))
+            {
+                case MFA_MATCHED:
+                    /* FIXME */
+                    break;
+
+                case MFA_RELOAD:
+                    //goto lnf_rescan;
+                    break;
+
+                default:
+                    break;
+
+            }
+
+        free(pglist);
+
+    }
+
+
+
     for (i = 0; i < FID_COUNT && result == NULL; i++)
-        if (_formats[i].type == type && _formats[i].match(type, content, length))
+        if (_formats[i].type == type && _formats[i].match(type, *content, *length))
         {
             log_variadic_message(LMT_INFO, _("%s is matching..."), _formats[i].name);
 
-            result = _formats[i].load(content, length);
+            result = _formats[i].load(*content, *length);
 
         }
 
+
+
+    printf("FINAL FORMAT :: %p\n", result);
+
+    //exit(0);
+
     return result;
 
 }
diff --git a/src/format/format.h b/src/format/format.h
index dd05dd2..7f0b649 100644
--- a/src/format/format.h
+++ b/src/format/format.h
@@ -121,7 +121,7 @@ typedef GBinFormat * (* format_load_fc) (const bin_t *, off_t);
 bool init_all_formats(void);
 
 /* Charge si possible un nouveau format binaire. */
-GBinFormat *load_new_format(FormatType, const uint8_t *, off_t);
+GBinFormat *load_new_format(FormatType, char *filename, bin_t **, off_t *);
 
 
 
diff --git a/src/gtkext/gtksourceview.c b/src/gtkext/gtksourceview.c
index 33b61c5..5dea05f 100644
--- a/src/gtkext/gtksourceview.c
+++ b/src/gtkext/gtksourceview.c
@@ -149,6 +149,9 @@ static void gtk_source_view_attach_binary(GtkSourceView *view, GOpenidaBinary *b
 
     buffer = g_openida_binary_get_decompiled_buffer(binary, -1);
 
+    /* FIXME */
+    if (buffer != NULL)
+
     gtk_buffer_view_attach_buffer(GTK_BUFFER_VIEW(view), buffer);
 
 }
diff --git a/src/plugins/plugin-def.h b/src/plugins/plugin-def.h
index 50b8df2..43ec28e 100644
--- a/src/plugins/plugin-def.h
+++ b/src/plugins/plugin-def.h
@@ -42,9 +42,13 @@ typedef enum _PluginType
 /* Action(s) menée(s) par le greffon */
 typedef enum _PluginAction
 {
-    PGA_DISASSEMBLE     = (1 << 0),         /* Désassemblage (non trivial) */
+    PGA_NONE            = (0 << 0),         /* Aucun intérêt               */
 
-    PGA_CODE_PROCESS    = (1 << 1)          /* Traitement du code existant */
+    PGA_FORMAT_MATCHER  = (1 << 0),         /* Détection et chargement     */
+
+    PGA_DISASSEMBLE     = (1 << 1),         /* Désassemblage (non trivial) */
+
+    PGA_CODE_PROCESS    = (1 << 2)          /* Traitement du code existant */
 
 } PluginAction;
 
@@ -54,11 +58,28 @@ typedef enum _PluginAction
 typedef PluginType (* get_plugin_type_fc) (void);
 
 /* Fournit une indication sur le type d'opération(s) menée(s). */
-typedef PluginAction (* get_plugin_action_fc) (void);
+//typedef PluginAction (* get_plugin_action_fc) (void);
 
 /* Exécute une action définie sur un binaire chargé. */
 typedef bool (* execute_action_on_binary_fc) (GOpenidaBinary *, PluginAction);
 
 
+/* PGA_FORMAT_MATCHER */
+
+/* Bilans d'une reconnaissance */
+typedef enum _MatchingFormatAction
+{
+    MFA_NONE,                               /* Aucune détection            */
+    MFA_MATCHED,                            /* Format reconnu              */
+    MFA_RELOAD,                             /* Rechargemet opéré           */
+
+    MFA_COUNT
+
+} MatchingFormatAction;
+
+
+
+
+
 
 #endif  /* _PLUGINS_PLUGIN_DEF_H */
diff --git a/src/plugins/plugin-int.h b/src/plugins/plugin-int.h
index 929dbf9..a0b5758 100644
--- a/src/plugins/plugin-int.h
+++ b/src/plugins/plugin-int.h
@@ -36,6 +36,11 @@
 /* Procède à l'initialisation du greffon */
 typedef bool (* init_plugin_fc) (GObject *);
 
+/* Fournit une indication sur le type d'opération(s) menée(s). */
+typedef PluginAction (* get_plugin_action_fc) (const GPluginModule *);
+
+/* Identifie un format à associer à un contenu binaire. */
+typedef MatchingFormatAction (* is_matching_fc) (const GPluginModule *, char **, bin_t **, off_t *);
 
 
 /* Greffon pour OpenIDA (instance) */
@@ -46,9 +51,11 @@ struct _GPluginModule
     GModule *module;                        /* Abstration de manipulation  */
 
     PluginType type;                        /* Type(s) du greffon          */
-    PluginAction action;                    /* Opération(s) menée(s)       */
 
     init_plugin_fc init;                    /* Procédure d'initialisation  */
+    get_plugin_action_fc get_action;        /* Opération(s) menée(s)       */
+
+    is_matching_fc is_matching;             /* Recherche de correspondance */
 
     execute_action_on_binary_fc exec_on_bin;/* Action sur un binaire       */
 
@@ -66,6 +73,9 @@ struct _GPluginModuleClass
 
 
 
+
+
+
 /* Ajoute un greffon à la liste principale de greffons. */
 void add_plugin_to_main_list(GPluginModule *);
 
diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c
index 2443768..ce8ef37 100644
--- a/src/plugins/plugin.c
+++ b/src/plugins/plugin.c
@@ -99,7 +99,7 @@ GPluginModule *g_plugin_module_new(const gchar *filename, GObject *ref)
 {
     GPluginModule *result;                  /* Structure à retourner       */
     get_plugin_action_fc __get_type;        /* Type(s) de greffon          */
-    get_plugin_action_fc __get_action;      /* Actions du greffon          */
+    get_plugin_action_fc get_action;        /* Actions du greffon          */
 
 
     result = g_object_new(G_TYPE_PLUGIN_MODULE, NULL);
@@ -107,6 +107,21 @@ GPluginModule *g_plugin_module_new(const gchar *filename, GObject *ref)
 
     result->module = g_module_open(filename, G_MODULE_BIND_LAZY);
 
+    if (!result->module)
+    {
+        printf("err null mod\n");
+        return NULL;
+
+    }
+
+
+    if (!g_module_symbol(result->module, "init_plugin", (gpointer *)&result->init))
+    {
+        printf("Err plugin init sym\n");
+        /* TODO */
+    }
+
+    /*
 
 
     if (!g_module_symbol(result->module, "get_plugin_type", (gpointer *)&__get_type))
@@ -119,20 +134,20 @@ GPluginModule *g_plugin_module_new(const gchar *filename, GObject *ref)
 
 
     printf("Plugin type :: 0x%08x\n", result->type);
+    */
 
 
 
-
-#if 1
-    if (!g_module_symbol(result->module, "get_plugin_action", (gpointer *)&__get_action))
+    if (!g_module_symbol(result->module, "get_plugin_action", (gpointer *)&get_action))
     {
         printf("Err plugin get_action sym\n");
         //g_object_destroy(result);
         return NULL;
     }
 
-    result->action = __get_action();
+    result->get_action = get_action;
 
+    /*
     if (result->action & (PGA_DISASSEMBLE | PGA_CODE_PROCESS))
     {
         if (!g_module_symbol(result->module, "execute_action_on_binary", (gpointer *)&result->exec_on_bin))
@@ -144,14 +159,7 @@ GPluginModule *g_plugin_module_new(const gchar *filename, GObject *ref)
 
 
     }
-#endif 
-
-
-    if (!g_module_symbol(result->module, "init_plugin", (gpointer *)&result->init))
-    {
-        printf("Err plugin init sym\n");
-        /* TODO */
-    }
+    */
 
 
 
@@ -188,11 +196,56 @@ GPluginModule *g_plugin_module_new(const gchar *filename, GObject *ref)
 
 PluginAction g_plugin_module_get_action(const GPluginModule *plugin)
 {
-    return plugin->action;
+    return plugin->get_action(plugin);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : plugin   = greffon de prise en charge à utiliser.            *
+*                filename = éventuel nom de fichier associé ou NULL. [OUT]    *
+*                data     = données chargées. [OUT]                           *
+*                length   = quantité de ces données. [OUT]                    *
+*                                                                             *
+*  Description : Identifie un format à associer à un contenu binaire.         *
+*                                                                             *
+*  Retour      : Bilan de la recherche de correspondances.                    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+MatchingFormatAction g_plugin_module_is_matching(const GPluginModule *plugin, char **filename, bin_t **data, off_t *length)
+{
+    MatchingFormatAction result;            /* Valeur à retourner          */
+    char *old_filename;                     /* Ancien nom de fichier       */
+    bin_t *old_data;                        /* Ancien contenu binaire      */
+
+    if (plugin->is_matching == NULL)
+        return MFA_NONE;
+
+    old_filename = *filename;
+    old_data = *data;
+
+    result = plugin->is_matching(plugin, filename, data, length);
+
+    if (result == MFA_RELOAD)
+    {
+        if (old_filename != NULL)
+            free(old_filename);
+        free(old_data);
+    }
+
+    return result;
 
 }
 
 
+
+
+
+
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : plugin = greffon à consulter.                                *
diff --git a/src/plugins/plugin.h b/src/plugins/plugin.h
index d17cee5..8df0e0e 100644
--- a/src/plugins/plugin.h
+++ b/src/plugins/plugin.h
@@ -57,9 +57,15 @@ GPluginModule *g_plugin_module_new(const gchar *, GObject *);
 /* Indique les opérations offertes par un greffon donné. */
 PluginAction g_plugin_module_get_action(const GPluginModule *);
 
+/* Identifie un format à associer à un contenu binaire. */
+MatchingFormatAction g_plugin_module_is_matching(const GPluginModule *, char **, bin_t **, off_t *);
+
 /* Exécute une action définie sur un binaire chargé. */
 bool g_plugin_module_execute_action_on_binary(const GPluginModule *, GOpenidaBinary *, PluginAction);
 
 
 
+
+
+
 #endif  /* _PLUGINS_PLUGIN_H */
-- 
cgit v0.11.2-87-g4458