summaryrefslogtreecommitdiff
path: root/src/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/Makefile.am19
-rw-r--r--src/plugins/dt.c562
-rw-r--r--src/plugins/dt.h50
-rw-r--r--src/plugins/manager-int.h54
-rw-r--r--src/plugins/manager.c113
-rw-r--r--src/plugins/manager.h61
-rw-r--r--src/plugins/native-int.h73
-rw-r--r--src/plugins/native.c295
-rw-r--r--src/plugins/native.h46
-rw-r--r--src/plugins/pglist.c435
-rw-r--r--src/plugins/pglist.h98
-rw-r--r--src/plugins/plugin-def.h16
-rw-r--r--src/plugins/plugin-int.h88
-rw-r--r--src/plugins/plugin.c962
-rw-r--r--src/plugins/plugin.h41
-rw-r--r--src/plugins/self.h99
-rw-r--r--src/plugins/tweakable-int.h50
-rw-r--r--src/plugins/tweakable.c98
-rw-r--r--src/plugins/tweakable.h62
19 files changed, 1528 insertions, 1694 deletions
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index dd191fa..fa65484 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -1,13 +1,18 @@
noinst_LTLIBRARIES = libplugins.la
-libplugins_la_SOURCES = \
- dt.h dt.c \
- pglist.h pglist.c \
- plugin-def.h \
- plugin-int.h \
- plugin.h plugin.c \
- self.h
+libplugins_la_SOURCES = \
+ manager-int.h \
+ manager.h manager.c \
+ native-int.h \
+ native.h native.c \
+ pglist.h pglist.c \
+ plugin-def.h \
+ plugin-int.h \
+ plugin.h plugin.c \
+ self.h \
+ tweakable-int.h \
+ tweakable.h tweakable.c
libplugins_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS)
diff --git a/src/plugins/dt.c b/src/plugins/dt.c
deleted file mode 100644
index 2899845..0000000
--- a/src/plugins/dt.c
+++ /dev/null
@@ -1,562 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * dt.c - possibilité de créer de nouveaux types de façon dynamique
- *
- * Copyright (C) 2019 Cyrille Bagard
- *
- * This file is part of Chrysalide.
- *
- * Chrysalide is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * Chrysalide is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include "dt.h"
-
-
-#include <assert.h>
-#include <malloc.h>
-#include <string.h>
-
-
-#include "pglist.h"
-
-
-
-/* ------------------------- MODULE DE GESTION DES NOUVEAUX ------------------------- */
-
-
-#define G_TYPE_DYNAMIC_TYPES g_dynamic_types_get_type()
-#define G_DYNAMIC_TYPES(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_DYNAMIC_TYPES, GDynamicTypes))
-#define G_IS_DYNAMIC_TYPES(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_DYNAMIC_TYPES))
-#define G_DYNAMIC_TYPES_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DYNAMIC_TYPES, GDynamicTypesClass))
-#define G_IS_DYNAMIC_TYPES_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DYNAMIC_TYPES))
-#define G_DYNAMIC_TYPES_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DYNAMIC_TYPES, GDynamicTypesClass))
-
-
-/* Mémorisation des caractéristiques de type */
-typedef struct _type_dyn_info_t
-{
- GType type; /* Identifiant unique obtenu */
-
- GClassInitFunc cinit; /* Phase d'initialisation #1 */
- gconstpointer data; /* Eventuelles données utiles */
-
- GInstanceInitFunc init; /* Phase d'initialisation #2 */
-
-} type_dyn_info_t;
-
-/* Description de fichier binaire (instance) */
-typedef struct _GDynamicTypes
-{
- GObject parent; /* A laisser en premier */
-
- type_dyn_info_t **info; /* Liste d'informations utiles */
- size_t count; /* Taille de cette liste */
-
-} GDynamicTypes;
-
-/* Description de fichier binaire (classe) */
-typedef struct _GDynamicTypesClass
-{
- GObjectClass parent; /* A laisser en premier */
-
-} GDynamicTypesClass;
-
-
-/* Indique le type défini pour une gestion de types dynamique. */
-static GType g_dynamic_types_get_type(void);
-
-/* Initialise la classe de gestion de types dynamique. */
-static void g_dynamic_types_class_init(GDynamicTypesClass *);
-
-/* Initialise une gestion de types dynamique. */
-static void g_dynamic_types_init(GDynamicTypes *);
-
-/* Procède à l'initialisation de l'interface de typage nouveau. */
-static void g_dynamic_types_interface_init(GTypePluginClass *);
-
-/* Supprime toutes les références externes. */
-static void g_dynamic_types_dispose(GDynamicTypes *);
-
-/* Procède à la libération totale de la mémoire. */
-static void g_dynamic_types_finalize(GDynamicTypes *);
-
-/* Crée un nouveau gestionnaire de nouveaux types. */
-static GDynamicTypes *g_dynamic_types_new(void);
-
-/* Marque une augmentation des utilisations. */
-static void g_dynamic_types_use(GDynamicTypes *);
-
-/* Marque une diminution des utilisations. */
-static void g_dynamic_types_unuse(GDynamicTypes *);
-
-/* Complète la définition d'un type dynamiquement. */
-static void g_dynamic_types_complete_type(GDynamicTypes *, GType, GTypeInfo *, GTypeValueTable *);
-
-/* Retrouve les informations concernant un type dynamique. */
-static type_dyn_info_t *g_dynamic_types_find(const GDynamicTypes *, GType);
-
-/* Fournit un identifiant GLib pour un nouveau type. */
-static GType g_dynamic_types_register_type(GDynamicTypes *, GType, const char *, GClassInitFunc, gconstpointer, GInstanceInitFunc);
-
-
-
-/* ----------------------- ACCOMPAGNEMENTS DES NOUVEAUX TYPES ----------------------- */
-
-
-/* Encadrement des nouveaux types dérivés */
-static GDynamicTypes *_chrysalide_dtypes = NULL;
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* MODULE DE GESTION DES NOUVEAUX */
-/* ---------------------------------------------------------------------------------- */
-
-/* Indique le type défini pour une gestion de types dynamique. */
-G_DEFINE_TYPE_WITH_CODE(GDynamicTypes, g_dynamic_types, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE(G_TYPE_TYPE_PLUGIN, g_dynamic_types_interface_init));
-
-
-/******************************************************************************
-* *
-* Paramètres : klass = classe à initialiser. *
-* *
-* Description : Initialise la classe de gestion de types dynamique. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_dynamic_types_class_init(GDynamicTypesClass *klass)
-{
- GObjectClass *object; /* Autre version de la classe */
-
- object = G_OBJECT_CLASS(klass);
-
- object->dispose = (GObjectFinalizeFunc/* ! */)g_dynamic_types_dispose;
- object->finalize = (GObjectFinalizeFunc)g_dynamic_types_finalize;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : types = instance à initialiser. *
-* *
-* Description : Initialise une gestion de types dynamique. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_dynamic_types_init(GDynamicTypes *types)
-{
-
-}
-
-/******************************************************************************
-* *
-* Paramètres : iface = interface GLib à initialiser. *
-* *
-* Description : Procède à l'initialisation de l'interface de typage nouveau. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_dynamic_types_interface_init(GTypePluginClass *iface)
-{
- iface->use_plugin = (GTypePluginUse)g_dynamic_types_use;
- iface->unuse_plugin = (GTypePluginUnuse)g_dynamic_types_unuse;
- iface->complete_type_info = (GTypePluginCompleteTypeInfo)g_dynamic_types_complete_type;
-
-}
-
-/******************************************************************************
-* *
-* Paramètres : types = instance d'objet GLib à traiter. *
-* *
-* Description : Supprime toutes les références externes. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_dynamic_types_dispose(GDynamicTypes *types)
-{
- size_t i; /* Boucle de parcours */
- type_dyn_info_t *info; /* Information à exploiter */
- gpointer g_class; /* Classe à oublier */
-
- for (i = 0; i < types->count; i++)
- {
- info = types->info[i];
-
- if (info->type != G_TYPE_INVALID)
- {
- g_class = g_type_class_peek(info->type);
-
- /**
- * Constat est fait qu'un type implémenté en Python mais dont les
- * instanciations conduisent toutes à des exceptions n'est pas
- * associé à une classe à ce moment d'exécution.
- *
- * Cf. fonction testKnownFormatConstructor() de la suite de tests
- *
- * Cf. documentation de g_type_class_unref() également :
- *
- * """
- * Once the last reference count of a class has been released,
- * classes may be finalized by the type system
- * """
- */
-
- if (g_class != NULL)
- g_type_class_unref(g_class);
-
- info->type = G_TYPE_INVALID;
-
- }
-
- }
-
- G_OBJECT_CLASS(g_dynamic_types_parent_class)->dispose(G_OBJECT(types));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : types = instance d'objet GLib à traiter. *
-* *
-* Description : Procède à la libération totale de la mémoire. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_dynamic_types_finalize(GDynamicTypes *types)
-{
- size_t i; /* Boucle de parcours */
-
- for (i = 0; i < types->count; i++)
- free(types->info[i]);
-
- if (types->info != NULL)
- free(types->info);
-
- G_OBJECT_CLASS(g_dynamic_types_parent_class)->finalize(G_OBJECT(types));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : - *
-* *
-* Description : Crée un nouveau gestionnaire de nouveaux types. *
-* *
-* Retour : Instance mise en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static GDynamicTypes *g_dynamic_types_new(void)
-{
- GDynamicTypes *result; /* Adresse à retourner */
-
- result = g_object_new(G_TYPE_DYNAMIC_TYPES, NULL);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : types = gestionnaire de types courant. *
-* *
-* Description : Marque une augmentation des utilisations. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_dynamic_types_use(GDynamicTypes *types)
-{
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : types = gestionnaire de types courant. *
-* *
-* Description : Marque une diminution des utilisations. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_dynamic_types_unuse(GDynamicTypes *types)
-{
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : types = gestionnaire de types courant. *
-* type = nouveau type GLib à traiter. *
-* info = information concernant ce type à constituer. [OUT] *
-* table = table de valeur à éventuellement initialiser. [OUT] *
-* *
-* Description : Complète la définition d'un type dynamiquement. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_dynamic_types_complete_type(GDynamicTypes *types, GType type, GTypeInfo *info, GTypeValueTable *table)
-{
- type_dyn_info_t *nfo; /* Source d'inspiration */
- GType parent; /* Type parent du type */
- GTypeQuery query; /* Informations complémentaires*/
-
- /* Consultation */
-
- nfo = g_dynamic_types_find(types, type);
- assert(nfo != NULL);
-
- parent = g_type_parent(type);
- g_type_query(parent, &query);
-
- /* Définition */
-
- info->class_size = query.class_size;
- info->class_init = nfo->cinit;
- info->class_data = nfo->data;
-
- info->instance_size = query.instance_size;
- info->instance_init = nfo->init;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : parent = type GLib parent. *
-* type = identifiant du type GLib à considérer. *
-* *
-* Description : Retrouve les informations concernant un type dynamique. *
-* *
-* Retour : Structure contenant les informations associées au type. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static type_dyn_info_t *g_dynamic_types_find(const GDynamicTypes *types, GType target)
-{
- type_dyn_info_t *result; /* Informations à retourner */
- size_t i; /* Boucle de parcours */
-
- result = NULL;
-
- for (i = 0; i < types->count && result == NULL; i++)
- if (types->info[i]->type == target)
- result = types->info[i];
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : parent = type GLib parent. *
-* name = désignation du nouveau type. *
-* cinit = procédure d'initialisation de la classe associée. *
-* data = éventuelles données à associer à la future classe. *
-* init = procédure d'initialisation pour chaque instance. *
-* *
-* Description : Fournit un identifiant GLib pour un nouveau type. *
-* *
-* Retour : identifiant d'un nouveau type valide, ou G_TYPE_INVALID. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static GType g_dynamic_types_register_type(GDynamicTypes *types, GType parent, const char *name, GClassInitFunc cinit, gconstpointer data, GInstanceInitFunc init)
-{
- GType result; /* Identifiant à retourner */
- type_dyn_info_t *new; /* Mémorisation de paramètres */
-
- /* Création d'un nouveau type adapté */
-
- result = g_type_register_dynamic(parent, name, G_TYPE_PLUGIN(types), 0);
-
- if (result == G_TYPE_INVALID)
- goto exit;
-
- new = malloc(sizeof(type_dyn_info_t));
-
- new->type = result;
-
- new->cinit = cinit;
- new->data = data;
-
- new->init = init;
-
- /* Inscription définitive */
-
- types->info = realloc(types->info, ++types->count * sizeof(type_dyn_info_t *));
-
- types->info[types->count - 1] = new;
-
- exit:
-
- return result;
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* ACCOMPAGNEMENTS DES NOUVEAUX TYPES */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-* *
-* Paramètres : - *
-* *
-* Description : Lance le support de dérivations de types dans Chrysalide. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool init_chrysalide_dynamic_types(void)
-{
- bool result; /* Bilan à retourner */
-
- _chrysalide_dtypes = g_dynamic_types_new();
-
- result = (_chrysalide_dtypes != NULL);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : - *
-* *
-* Description : Arrête le support de dérivations de types dans Chrysalide. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void exit_chrysalide_dynamic_types(void)
-{
- g_object_unref(G_OBJECT(_chrysalide_dtypes));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : parent = type GLib parent. *
-* name = désignation du nouveau type. *
-* cinit = procédure d'initialisation de la classe associée. *
-* data = éventuelles données à associer à la future classe. *
-* init = procédure d'initialisation pour chaque instance. *
-* *
-* Description : Fournit un identifiant GLib pour un nouveau type. *
-* *
-* Retour : Identifiant d'un nouveau type valide, ou G_TYPE_INVALID. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GType build_dynamic_type(GType parent, const char *name, GClassInitFunc cinit, gconstpointer data, GInstanceInitFunc init)
-{
- GType result; /* Identifiant à retourner */
-
- result = g_type_from_name(name);
-
- if (result == 0)
- result = g_dynamic_types_register_type(_chrysalide_dtypes, parent, name, cinit, data, init);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : type = type d'instance à créer. *
-* *
-* Description : Crée un objet à partir d'un type, dynamique ou classique. *
-* *
-* Retour : Instance d'objet mise en place ou NULL en cas d'erreur. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-gpointer create_object_from_type(GType type)
-{
- GObject *result; /* Instance à retourner */
-
- result = NULL;
-
- if (g_dynamic_types_find(_chrysalide_dtypes, type) != NULL)
- result = build_type_instance(type);
-
- else
- result = g_object_new(type, NULL);
-
- assert(result != NULL);
-
- return result;
-
-}
diff --git a/src/plugins/dt.h b/src/plugins/dt.h
deleted file mode 100644
index 5c92593..0000000
--- a/src/plugins/dt.h
+++ /dev/null
@@ -1,50 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * dt.h - prototypes pour la possibilité de créer de nouveaux types de façon dynamique
- *
- * Copyright (C) 2019 Cyrille Bagard
- *
- * This file is part of Chrysalide.
- *
- * Chrysalide is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * Chrysalide is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#ifndef _PLUGINS_DT_H
-#define _PLUGINS_DT_H
-
-
-#include <glib-object.h>
-#include <stdbool.h>
-
-
-
-/* ----------------------- ACCOMPAGNEMENTS DES NOUVEAUX TYPES ----------------------- */
-
-
-/* Lance le support de dérivations de types dans Chrysalide. */
-bool init_chrysalide_dynamic_types(void);
-
-/* Arrête le support de dérivations de types dans Chrysalide. */
-void exit_chrysalide_dynamic_types(void);
-
-/* Fournit un identifiant GLib pour un nouveau type. */
-GType build_dynamic_type(GType, const char *, GClassInitFunc, gconstpointer, GInstanceInitFunc);
-
-/* Crée un objet à partir d'un type, dynamique ou classique. */
-gpointer create_object_from_type(GType);
-
-
-
-#endif /* _PLUGINS_PYCHRYSALIDE_DT_H */
diff --git a/src/plugins/manager-int.h b/src/plugins/manager-int.h
new file mode 100644
index 0000000..dbd1d69
--- /dev/null
+++ b/src/plugins/manager-int.h
@@ -0,0 +1,54 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * manager-int.h - définitions internes propres aux interventions dans la gestion des extensions
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_MANAGER_INT_H
+#define _PLUGINS_MANAGER_INT_H
+
+
+#include "manager.h"
+
+
+
+/* -------------------- INTERVENTION DANS LA GESTION DE GREFFONS -------------------- */
+
+
+/* Accompagne la fin du chargement des modules natifs. */
+typedef void (* handle_native_plugins_cb) (GPluginManager *);
+
+/* Prend acte du chargement de l'ensemble des greffons. */
+typedef void (* handle_all_plugins_cb) (GPluginManager *);
+
+
+/* Accompagnant dans la gestion des extensions (interface) */
+struct _GPluginManagerInterface
+{
+ GTypeInterface base_iface; /* A laisser en premier */
+
+ handle_native_plugins_cb handle_native; /* Greffons natifs chargés */
+ handle_all_plugins_cb handle_all; /* Ensemble des greffons chargé*/
+
+};
+
+
+
+#endif /* _PLUGINS_MANAGER_INT_H */
diff --git a/src/plugins/manager.c b/src/plugins/manager.c
new file mode 100644
index 0000000..381fbc1
--- /dev/null
+++ b/src/plugins/manager.c
@@ -0,0 +1,113 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * manager.c - intervention dans la gestion des extensions
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "manager.h"
+
+
+#include "manager-int.h"
+
+
+
+/* -------------------- INTERVENTION DANS LA GESTION DE GREFFONS -------------------- */
+
+
+/* Procède à l'initialisation de l'interface de gestion. */
+static void g_plugin_manager_default_init(GPluginManagerInterface *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTERVENTION DANS LA GESTION DE GREFFONS */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Détermine le type d'une interface pour l'intervention dans la gestion des greffons. */
+G_DEFINE_INTERFACE(GPluginManager, g_plugin_manager, G_TYPE_OBJECT)
+
+
+/******************************************************************************
+* *
+* Paramètres : iface = interface GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'interface de gestion. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_plugin_manager_default_init(GPluginManagerInterface *iface)
+{
+ iface->handle_native = NULL;
+ iface->handle_all = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : manager = interface à manipuler. *
+* *
+* Description : Accompagne la fin du chargement des modules natifs. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_plugin_manager_handle_native_plugins_loaded_event(GPluginManager *manager)
+{
+ GPluginManagerInterface *iface; /* Interface utilisée */
+
+ iface = G_PLUGIN_MANAGER_GET_IFACE(manager);
+
+ if (iface->handle_native != NULL)
+ iface->handle_native(manager);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : manager = interface à manipuler. *
+* *
+* Description : Prend acte du chargement de l'ensemble des greffons. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_plugin_manager_handle_all_plugins_loaded_event(GPluginManager *manager)
+{
+ GPluginManagerInterface *iface; /* Interface utilisée */
+
+ iface = G_PLUGIN_MANAGER_GET_IFACE(manager);
+
+ if (iface->handle_all != NULL)
+ iface->handle_all(manager);
+
+}
diff --git a/src/plugins/manager.h b/src/plugins/manager.h
new file mode 100644
index 0000000..2eb90a8
--- /dev/null
+++ b/src/plugins/manager.h
@@ -0,0 +1,61 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * manager.h - prototypes pour l'intervention dans la gestion des extensions
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_MANAGER_H
+#define _PLUGINS_MANAGER_H
+
+
+#include "../glibext/helpers.h"
+
+
+
+/* -------------------- INTERVENTION DANS LA GESTION DE GREFFONS -------------------- */
+
+
+#define G_TYPE_PLUGIN_MANAGER (g_plugin_manager_get_type())
+
+DECLARE_INTERFACE(GPluginManager, g_plugin_manager, G, PLUGIN_MANAGER);
+
+
+/* Accompagne la fin du chargement des modules natifs. */
+void g_plugin_manager_handle_native_plugins_loaded_event(GPluginManager *);
+
+/* Prend acte du chargement de l'ensemble des greffons. */
+void g_plugin_manager_handle_all_plugins_loaded_event(GPluginManager *);
+
+
+
+/* -------------------- SOLLICITATION DES FONCTIONNALITES CREEES -------------------- */
+
+
+#define notify_native_plugins_loaded() \
+ process_all_plugins_for(G_TYPE_PLUGIN_MANAGER, G_PLUGIN_MANAGER, \
+ g_plugin_manager_handle_native_plugins_loaded_event)
+
+#define notify_all_plugins_loaded() \
+ process_all_plugins_for(G_TYPE_PLUGIN_MANAGER, G_PLUGIN_MANAGER, \
+ g_plugin_manager_handle_all_plugins_loaded_event)
+
+
+
+#endif /* _PLUGINS_MANAGER_H */
diff --git a/src/plugins/native-int.h b/src/plugins/native-int.h
new file mode 100644
index 0000000..575994f
--- /dev/null
+++ b/src/plugins/native-int.h
@@ -0,0 +1,73 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * native-int.h - prototypes pour les structures internes des greffons natifs
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_NATIVE_INT_H
+#define _PLUGINS_NATIVE_INT_H
+
+
+#include "native.h"
+
+
+#include "plugin-int.h"
+
+
+
+/* Marqueur identifiable */
+#define CHRYSALIDE_PLUGIN_MAGIC 0xdeadc0de
+
+
+/* Greffon natif pour Chrysalide (instance) */
+struct _GNativePlugin
+{
+ GPluginModule parent; /* A laisser en premier */
+
+ /**
+ * Le module porte le code et les données en mémoire.
+ *
+ * Les fonctions *_dispose() et *_finalize() accompagnant la libération des
+ * greffons de la mémoire ne peuvent donc pas libérer ce module car elles
+ * scieraient la branche sur laquelle elles se trouvent.
+ *
+ * Par ailleurs, même s'ils sont conservés dans chaque greffon, les modules
+ * sont mis en place dans le code principal. C'est donc ce dernier qui les
+ * libère, dans la fonction on_plugin_ref_toggle().
+ */
+ GModule *module; /* Structure de chargement GLib*/
+
+};
+
+
+/* Greffon natif pour Chrysalide (classe) */
+struct _GNativePluginClass
+{
+ GPluginModuleClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place un greffon natif. */
+bool g_native_plugin_create(GNativePlugin *, const char *, const char *, const char *, const char *, const char * const *, size_t, GModule *);
+
+
+
+#endif /* _PLUGINS_NATIVE_INT_H */
diff --git a/src/plugins/native.c b/src/plugins/native.c
new file mode 100644
index 0000000..de20abe
--- /dev/null
+++ b/src/plugins/native.c
@@ -0,0 +1,295 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * native.c - interactions avec un greffon natif donné
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "native.h"
+
+
+#include "native-int.h"
+#include "../common/cpp.h"
+
+
+
+/* ------------------------- COMPOSITION DE NOUVEAU GREFFON ------------------------- */
+
+
+/* Initialise la classe des greffons natifs. */
+static void g_native_plugin_class_init(GNativePluginClass *);
+
+/* Initialise une instance de greffon natif. */
+static void g_native_plugin_init(GNativePlugin *);
+
+/* Supprime toutes les références externes. */
+static void g_native_plugin_dispose(GNativePlugin *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_native_plugin_finalize(GNativePlugin *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Pointe le fichier contenant le greffon manipulé. */
+static char *g_native_plugin_get_filename(const GNativePlugin *);
+
+/* Fournit le nom brut associé au greffon. */
+static char *g_native_plugin_get_modname(const GNativePlugin *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* COMPOSITION DE NOUVEAU GREFFON */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un greffon Python. */
+G_DEFINE_TYPE(GNativePlugin, g_native_plugin, G_TYPE_PLUGIN_MODULE);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe à initialiser. *
+* *
+* Description : Initialise la classe des greffons natifs. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_native_plugin_class_init(GNativePluginClass *class)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GPluginModuleClass *plugin; /* Version parente de la classe*/
+
+ object = G_OBJECT_CLASS(class);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_native_plugin_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_native_plugin_finalize;
+
+ plugin = G_PLUGIN_MODULE_CLASS(class);
+
+ plugin->get_filename = (get_plugin_filename_fc)g_native_plugin_get_filename;
+ plugin->get_modname = (get_plugin_modname_fc)g_native_plugin_get_modname;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : plugin = instance à initialiser. *
+* *
+* Description : Initialise une instance de greffon natif. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_native_plugin_init(GNativePlugin *plugin)
+{
+ plugin->module = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : plugin = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_native_plugin_dispose(GNativePlugin *plugin)
+{
+ G_OBJECT_CLASS(g_native_plugin_parent_class)->dispose(G_OBJECT(plugin));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : plugin = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_native_plugin_finalize(GNativePlugin *plugin)
+{
+ G_OBJECT_CLASS(g_native_plugin_parent_class)->finalize(G_OBJECT(plugin));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : plugin = instance à initialiser pleinement. *
+* name = nom du greffon pour référence, principalement. *
+* desc = présentation éventuelle à destination humaine. *
+* version = indication de version éventuelle. *
+* url = référence vers une ressource en ligne. *
+* required = liste de dépendances éventuelles ou NULL. *
+* count = taille de cette liste. *
+* module = extension vue du système. *
+* *
+* Description : Met en place un greffon natif. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : Le transfert de propriétée du module est total. *
+* *
+******************************************************************************/
+
+bool g_native_plugin_create(GNativePlugin *plugin, const char *name, const char *desc, const char *version, const char *url, const char * const *required, size_t count, GModule *module)
+{
+ bool result; /* Bilan à retourner */
+
+ result = g_plugin_module_create(G_PLUGIN_MODULE(plugin), name, desc, version, url, required, count);
+
+ if (result)
+ plugin->module = module;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : plugin = greffon à consulter. *
+* *
+* Description : Renvoie la structure opaque associée au module en mémoire. *
+* *
+* Retour : Structure de chargement côté GLib. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GModule *g_native_plugin_get_module(const GNativePlugin *plugin)
+{
+ GModule *result; /* Accès au module à renvoyer */
+
+ result = plugin->module;
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : plugin = greffon à consulter. *
+* *
+* Description : Pointe le fichier contenant le greffon manipulé. *
+* *
+* Retour : Chemin d'accès au greffon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_native_plugin_get_filename(const GNativePlugin *plugin)
+{
+ char *result; /* Chemin d'accès à renvoyer */
+
+ result = strdup(g_module_name(plugin->module));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : plugin = greffon à valider. *
+* *
+* Description : Fournit le nom brut associé au greffon. *
+* *
+* Retour : Désignation brute du greffon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_native_plugin_get_modname(const GNativePlugin *plugin)
+{
+ char *result; /* Désignation brute à renvoyer*/
+ char *path; /* Chemin à traiter */
+ char *filename; /* Nom de bibliothèque partagée*/
+ size_t length; /* Taille du nom */
+ int ret; /* Bilan d'une comparaison */
+
+ path = g_native_plugin_get_filename(plugin);
+
+ filename = basename(path);
+
+ if (strncmp(filename, "lib", 3) == 0)
+ filename += 3;
+
+ length = strlen(filename);
+
+#ifdef _WIN32
+# define SHARED_SUFFIX ".dll"
+#else
+# define SHARED_SUFFIX ".so"
+#endif
+
+ if (length >= STATIC_STR_SIZE(SHARED_SUFFIX))
+ {
+ ret = strncmp(&filename[length - STATIC_STR_SIZE(SHARED_SUFFIX)],
+ SHARED_SUFFIX,
+ STATIC_STR_SIZE(SHARED_SUFFIX));
+
+ if (ret == 0)
+ filename[length - STATIC_STR_SIZE(SHARED_SUFFIX)] = '\0';
+
+ }
+
+ result = strdup(filename);
+
+ free(path);
+
+ return result;
+
+}
diff --git a/src/plugins/native.h b/src/plugins/native.h
new file mode 100644
index 0000000..18039c8
--- /dev/null
+++ b/src/plugins/native.h
@@ -0,0 +1,46 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * native.h - prototypes pour les interactions avec un greffon natif donné
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _PLUGINS_NATIVE_H
+#define _PLUGINS_NATIVE_H
+
+
+#include <gmodule.h>
+
+
+#include "../glibext/helpers.h"
+
+
+
+#define G_TYPE_NATIVE_PLUGIN (g_native_plugin_get_type())
+
+DECLARE_GTYPE(GNativePlugin, g_native_plugin, G, NATIVE_PLUGIN);
+
+
+/* Renvoie la structure opaque associée au module en mémoire. */
+GModule *g_native_plugin_get_module(const GNativePlugin *);
+
+
+
+#endif /* _PLUGINS_NATIVE_H */
diff --git a/src/plugins/pglist.c b/src/plugins/pglist.c
index e4cb825..3e107b8 100644
--- a/src/plugins/pglist.c
+++ b/src/plugins/pglist.c
@@ -30,13 +30,16 @@
#include <malloc.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include <i18n.h>
-#include "dt.h"
+#include "manager.h"
+#include "native.h"
#include "plugin-int.h"
+#include "../common/cpp.h"
#include "../common/extstr.h"
#include "../core/logs.h"
#include "../core/nox.h"
@@ -44,6 +47,12 @@
+/**
+ * Prototype de la fonction de création, à garder synchronisé avec
+ * NATIVE_PLUGIN_ENTRYPOINT() (cf. native-int.h).
+ */
+typedef GPluginModule * (* get_plugin_instance_cb) (GModule *);
+
/* Liste de l'ensemble des greffons */
static GPluginModule **_pg_list = NULL;
static size_t _pg_count = 0;
@@ -61,6 +70,9 @@ static void browse_directory_for_plugins(const char *);
/* Suit les variations du compteur de références d'un greffon. */
static void on_plugin_ref_toggle(gpointer, GPluginModule *, gboolean);
+/* Fournit le greffon répondant à un nom donné. */
+static GPluginModule *_find_plugin_by_name(const char *, size_t *);
+
/******************************************************************************
@@ -83,8 +95,7 @@ bool init_all_plugins(bool load)
char *saveptr; /* Sauvegarde pour parcours */
char *udir; /* Répertoire supplémentaire ? */
- result = init_chrysalide_dynamic_types();
- if (!result) goto exit;
+ result = true;
g_rw_lock_init(&_pg_lock);
@@ -108,8 +119,6 @@ bool init_all_plugins(bool load)
if (load)
load_remaning_plugins();
- exit:
-
return result;
}
@@ -130,64 +139,22 @@ bool init_all_plugins(bool load)
void exit_all_plugins(void)
{
size_t i; /* Boucle de parcours */
- const plugin_interface *pg_iface; /* Définition du greffon */
lock_plugin_list_for_reading();
- if (_pg_list != NULL)
+ for (i = 0; i < _pg_count; i++)
{
- for (i = 0; i < _pg_count; i++)
- {
- assert(_pg_list[i] != NULL);
-
- /**
- * Si le greffon a conduit à la mise en place d'autres greffons, le
- * système de dépendances ne suffit pas pour le décompte des références :
- * le greffon voit à un instant T son compteur décroître ici ; à un
- * instant T+1, un greffon fils décrémente à son tour le compteur vers
- * le greffon principal.
- *
- * Le compteur du conteneur tombe alors à 0, et le code correspondant
- * est retiré. Lorsque que le flot d'exécution revient à la procédure
- * de sortie du second greffon, son code n'est plus en mémoire.
- *
- * On s'assure donc que les greffons qui génèrent d'autres greffons
- * sont bien traités en dernier.
- */
-
- pg_iface = g_plugin_module_get_interface(_pg_list[i]);
-
- if (pg_iface != NULL && pg_iface->container)
- g_object_ref(_pg_list[i]);
-
- g_object_unref(_pg_list[i]);
-
- }
-
- for (i = 0; i < _pg_count; i++)
- {
- if (_pg_list[i] == NULL)
- continue;
-
- pg_iface = g_plugin_module_get_interface(_pg_list[i]);
-
- if (pg_iface == NULL || !pg_iface->container)
- continue;
-
- g_object_unref(_pg_list[i]);
-
- }
+ assert(_pg_list[i] != NULL);
+ unref_object(_pg_list[i]);
+ }
+ if (_pg_list != NULL)
free(_pg_list);
- }
-
unlock_plugin_list_for_reading();
g_rw_lock_clear(&_pg_lock);
- exit_chrysalide_dynamic_types();
-
}
@@ -244,83 +211,95 @@ static int filter_dirs_or_mods(const struct dirent *entry)
* *
* Paramètres : dir = répertoire à parcourir en quête de greffons (sans /). *
* *
-* Description : Part à la recherche de greffons sous forme de modules. *
+* Description : Indique la version (NOX/UI) associée à un nom de fichier. *
* *
-* Retour : - *
+* Retour : true si la version complémentaire existe ou false. *
* *
* Remarques : - *
* *
******************************************************************************/
-static void browse_directory_for_plugins(const char *dir)
+static bool check_for_plugin_versions(const char *dir, const char *filename, bool *is_nox, bool *is_ui)
{
- struct dirent **namelist; /* Eléments trouvés */
- int ret; /* Bilan du parcours */
- bool nox; /* Absence de support graphique*/
- char *filename; /* Elément à ausculter */
- GPluginModule *plugin; /* Greffon à intégrer ou pas */
-
- ret = scandir(dir, &namelist, filter_dirs_or_mods, alphasort);
- if (ret < 0)
- {
- LOG_ERROR_N("scandir");
- return;
- }
-
- nox = run_in_nox_mode();
-
- while (ret--)
- {
+ bool result; /* Bilan à renvoyer */
+ size_t length; /* Taille du nom de fichier */
+ char *alt_path; /* Autre chemin complet testé */
+ int ret; /* Bilan d'une impression */
- if (nox)
- {
#ifdef _WIN32
-# define UI_SHARED_SUFFIX "-ui.dll"
+# define SHARED_SUFFIX ".dll"
#else
-# define UI_SHARED_SUFFIX "-ui.so"
+# define SHARED_SUFFIX ".so"
#endif
+#define UI_SHARED_SUFFIX "ui" SHARED_SUFFIX
- if (strstr(namelist[ret]->d_name, UI_SHARED_SUFFIX) != NULL)
- {
- log_variadic_message(LMT_ERROR, _("Skipping unsuitable file: %s"), namelist[ret]->d_name);
- continue;
- }
+ result = false;
- }
+ /* Propriétés du fichier courant */
- filename = (char *)calloc(strlen(dir) + 1 + strlen(namelist[ret]->d_name) + 1, sizeof(char));
+ length = strlen(filename);
- strcpy(filename, dir);
- strcat(filename, G_DIR_SEPARATOR_S);
- strcat(filename, namelist[ret]->d_name);
+ if (length < STATIC_STR_SIZE(UI_SHARED_SUFFIX))
+ *is_ui = false;
- if (namelist[ret]->d_type == DT_DIR)
- browse_directory_for_plugins(filename);
+ else
+ *is_ui = (strcmp(filename + length - STATIC_STR_SIZE(UI_SHARED_SUFFIX), UI_SHARED_SUFFIX) == 0);
+
+ if (*is_ui)
+ *is_nox = false;
+
+ else
+ {
+ if (length < STATIC_STR_SIZE(SHARED_SUFFIX))
+ *is_nox = false;
else
- {
- plugin = g_plugin_module_new(filename);
+ *is_nox = (strcmp(filename + length - STATIC_STR_SIZE(SHARED_SUFFIX), SHARED_SUFFIX) == 0);
+
+ }
+
+ /* Recherche d'une version alternative */
- if (plugin != NULL)
- register_plugin(plugin);
+ if (*is_nox || *is_ui)
+ {
+
+ if (*is_nox)
+ ret = asprintf(&alt_path, "%s%s%.*s%s",
+ dir, G_DIR_SEPARATOR_S,
+ (int)(length - STATIC_STR_SIZE(SHARED_SUFFIX)), filename,
+ UI_SHARED_SUFFIX);
+ else
+ ret = asprintf(&alt_path, "%s%s%.*s%s",
+ dir, G_DIR_SEPARATOR_S,
+ (int)(length - STATIC_STR_SIZE(SHARED_SUFFIX)), filename,
+ SHARED_SUFFIX);
+ if (ret <= 0)
+ {
+ LOG_ERROR_N("asprintf");
+ goto exit;
}
- free(filename);
- free(namelist[ret]);
+ ret = access(alt_path, R_OK | X_OK);
+
+ result = (ret == 0);
+
+ free(alt_path);
}
- free(namelist);
+ exit:
+
+ return result;
}
/******************************************************************************
* *
-* Paramètres : plugin = greffon à ajouter aux autres disponibles. *
+* Paramètres : dir = répertoire à parcourir en quête de greffons (sans /). *
* *
-* Description : Ajoute un greffon à la liste principale de greffons. *
+* Description : Part à la recherche de greffons sous forme de modules. *
* *
* Retour : - *
* *
@@ -328,52 +307,91 @@ static void browse_directory_for_plugins(const char *dir)
* *
******************************************************************************/
-void _register_plugin(GPluginModule *plugin)
+static void browse_directory_for_plugins(const char *dir)
{
- size_t i; /* Boucle de parcours */
- const plugin_interface *pg_iface; /* Informations à consulter */
- const char *name; /* Désignation du greffon */
-
- /**
- * L'appel sans verrou n'est fourni que pour les greffons
- * mettant en place des greffons en interne !
- */
-
- /* Recherche d'un éventuel doublon */
+ struct dirent **namelist; /* Eléments trouvés */
+ int ret; /* Bilan d'un appel */
+ int k; /* Boucle de parcours */
+ bool nox_mode; /* Absence de support graphique*/
+ char *filename; /* Elément à ausculter */
+ bool is_nox; /* Chemin de version basique ? */
+ bool is_ui; /* Chemin de version graphique */
+ bool has_alt; /* Existence d'une alternative */
+ GModule *module; /* Abstration de manipulation */
+ get_plugin_instance_cb get_instance; /* Point d'entrée exporté */
+ GPluginModule *plugin; /* Greffon à intégrer ou pas */
- pg_iface = g_plugin_module_get_interface(plugin);
+ ret = scandir(dir, &namelist, filter_dirs_or_mods, alphasort);
+ if (ret < 0)
+ {
+ LOG_ERROR_N("scandir");
+ return;
+ }
- name = pg_iface->name;
+ nox_mode = run_in_nox_mode();
- for (i = 0; i < _pg_count; i++)
+ for (k = ret; k--; )
{
- pg_iface = g_plugin_module_get_interface(_pg_list[i]);
-
- if (strcmp(name, pg_iface->name) == 0)
+ ret = asprintf(&filename, "%s%s%s", dir, G_DIR_SEPARATOR_S, namelist[k]->d_name);
+ if (ret <= 0)
{
- log_variadic_message(LMT_ERROR,
- _("Plugin '%s' already registered!"), name);
+ LOG_ERROR_N("asprintf");
+ continue;
+ }
- break;
+ if (namelist[k]->d_type == DT_DIR)
+ browse_directory_for_plugins(filename);
- }
+ else
+ {
+ has_alt = check_for_plugin_versions(dir, namelist[k]->d_name, &is_nox, &is_ui);
- }
+ if ((nox_mode && is_nox) || (!nox_mode && ((is_nox && !has_alt) || is_ui)))
+ {
+ module = g_module_open(filename, G_MODULE_BIND_LAZY);
+ if (module == NULL)
+ {
+ log_variadic_message(LMT_ERROR,
+ _("Error while loading the plugin candidate '%s' : %s"),
+ filename, g_module_error());
+ goto next_file;
+ }
+
+ get_instance = NULL;
+
+ if (!g_module_symbol(module, "get_chrysalide_plugin_instance", (gpointer *)&get_instance))
+ log_variadic_message(LMT_ERROR,
+ _("No '%s' entry in plugin candidate '%s'"),
+ "<sym>", filename);
+
+ if (get_instance == NULL)
+ plugin = NULL;
+ else
+ plugin = get_instance(module);
+
+ if (plugin != NULL)
+ {
+ register_plugin(plugin);
+ unref_object(plugin);
+ }
+
+ else
+ g_module_close(module);
- /* Ajout du greffon à la liste */
+ }
+ else
+ log_variadic_message(LMT_INFO, _("Skipping unsuitable file for plugin: %s"), filename);
- if (i == _pg_count)
- {
- _pg_list = (GPluginModule **)realloc(_pg_list, ++_pg_count * sizeof(GPluginModule));
+ }
- _pg_list[_pg_count - 1] = plugin;
+ next_file:
- g_object_add_toggle_ref(G_OBJECT(plugin), (GToggleNotify)on_plugin_ref_toggle, NULL);
+ free(filename);
+ free(namelist[k]);
}
- else
- /* FIXME : leak(plugin); */;
+ free(namelist);
}
@@ -394,24 +412,55 @@ void _register_plugin(GPluginModule *plugin)
static void on_plugin_ref_toggle(gpointer unused, GPluginModule *plugin, gboolean last)
{
- const plugin_interface *pg_iface; /* Vitrine d'un greffon */
+ const char *name; /* Désignation du greffon */
size_t index; /* Indice du greffon */
GPluginModule *same; /* Juste pour la récupération */
+ GModule *module; /* Structure de chargement GLib*/
if (last)
{
assert(g_rw_lock_writer_trylock(&_pg_lock) == FALSE);
- pg_iface = g_plugin_module_get_interface(plugin);
+ name = g_plugin_module_get_name(plugin);
+
+ /**
+ * Les mécanismes de g_object_unref() prennent en compte la bascule d'un
+ * compteur de références initialement à 2 avant appel pour déclencher
+ * cet appel à on_plugin_ref_toggle() mis en place par g_object_add_toggle_ref().
+ *
+ * Incrémenter ce compteur à nouveau, via get_plugin_by_name(), puis le
+ * décrémenter ensuite via unref_object() va conduire à une nouvelle
+ * bascule des statuts de suivi dans g_object_unref().
+ *
+ * Il est ainsi impératif de rechercher une instance du greffon dans
+ * la liste des extensions sans toucher au compteur de références.
+ */
+
+ same = _find_plugin_by_name(name, &index);
- same = get_plugin_by_name(pg_iface->name, &index);
assert(same != NULL);
+ assert(same == plugin);
_pg_list[index] = NULL;
- g_object_remove_toggle_ref(G_OBJECT(plugin), (GToggleNotify)on_plugin_ref_toggle, NULL);
+ /**
+ * Suppression de la dernière référence.
+ */
+
+ if (G_IS_NATIVE_PLUGIN(plugin))
+ module = g_native_plugin_get_module(G_NATIVE_PLUGIN(plugin));
+ else
+ module = NULL;
+
+ g_object_remove_toggle_ref(G_OBJECT(same), (GToggleNotify)on_plugin_ref_toggle, NULL);
+
+ /**
+ * Plus aucun code issu du greffon n'est désormais utile. Le module associé peut
+ * être libéré de la mémoire.
+ */
- g_object_unref(G_OBJECT(same));
+ if (module != NULL)
+ g_module_close(module);
}
@@ -432,9 +481,40 @@ static void on_plugin_ref_toggle(gpointer unused, GPluginModule *plugin, gboolea
void register_plugin(GPluginModule *plugin)
{
+ size_t i; /* Boucle de parcours */
+ const char *name; /* Désignation du greffon */
+ const char *existing; /* Nom d'un greffon en place */
+
g_rw_lock_writer_lock(&_pg_lock);
- _register_plugin(plugin);
+ /* Recherche d'un éventuel doublon */
+
+ name = g_plugin_module_get_name(plugin);
+
+ for (i = 0; i < _pg_count; i++)
+ {
+ existing = g_plugin_module_get_name(_pg_list[i]);
+
+ if (strcmp(name, existing) == 0)
+ {
+ log_variadic_message(LMT_ERROR, _("Plugin '%s' already registered!"), name);
+ break;
+ }
+
+ }
+
+ /* Ajout du greffon à la liste */
+
+ if (i == _pg_count)
+ {
+ _pg_list = realloc(_pg_list, ++_pg_count * sizeof(GPluginModule));
+
+ _pg_list[_pg_count - 1] = plugin;
+ ref_object(plugin);
+
+ g_object_add_toggle_ref(G_OBJECT(plugin), (GToggleNotify)on_plugin_ref_toggle, NULL);
+
+ }
g_rw_lock_writer_unlock(&_pg_lock);
@@ -502,13 +582,18 @@ void load_remaning_plugins(void)
/* Supprime les greffons non chargés */
- for (i = 0; i < _pg_count; i++)
+ for (i = 0; i < _pg_count;)
{
flags = g_plugin_module_get_flags(_pg_list[i]);
- if ((flags & PSF_LOADED) == 0)
+ if (flags & PSF_LOADED)
+ i++;
+
+ else
{
- g_object_unref(G_OBJECT(_pg_list[i]));
+ unref_object(_pg_list[i]);
+
+ assert(_pg_list[i] == NULL);
memmove(&_pg_list[i], &_pg_list[i + 1], (_pg_count - i - 1) * sizeof(GPluginModule *));
_pg_count--;
@@ -535,15 +620,16 @@ void load_remaning_plugins(void)
* *
* Retour : Instance du greffon trouvé ou NULL si aucun. *
* *
-* Remarques : - *
+* Remarques : Le compteur de référence d'un greffon trouvé n'est pas *
+* modifié. *
* *
******************************************************************************/
-GPluginModule *get_plugin_by_name(const char *name, size_t *index)
+static GPluginModule *_find_plugin_by_name(const char *name, size_t *index)
{
GPluginModule *result; /* Greffon trouvé à renvoyer */
size_t i; /* Boucle de parcours */
- const plugin_interface *pg_iface; /* Vitrine d'un greffon */
+ const char *current; /* Nom du greffon courant */
result = NULL;
@@ -557,9 +643,9 @@ GPluginModule *get_plugin_by_name(const char *name, size_t *index)
/* Si on est en train de procéder à un nettoyage... */
if (_pg_list[i] == NULL) continue;
- pg_iface = g_plugin_module_get_interface(_pg_list[i]);
+ current = g_plugin_module_get_name(_pg_list[i]);
- if (strcmp(pg_iface->name, name) == 0)
+ if (strcmp(current, name) == 0)
{
result = _pg_list[i];
@@ -570,9 +656,6 @@ GPluginModule *get_plugin_by_name(const char *name, size_t *index)
}
- if (result != NULL)
- g_object_ref(G_OBJECT(result));
-
return result;
}
@@ -580,33 +663,25 @@ GPluginModule *get_plugin_by_name(const char *name, size_t *index)
/******************************************************************************
* *
-* Paramètres : count = nombre de greffons trouvés. [OUT] *
+* Paramètres : name = désignation du greffon recherché. *
+* index = indice du greffon trouvé. [OUT] *
* *
-* Description : Fournit la liste de l'ensemble des greffons. *
+* Description : Fournit le greffon répondant à un nom donné. *
* *
-* Retour : Liste de tous les greffons chargés. *
+* Retour : Instance du greffon trouvé ou NULL si aucun. *
* *
* Remarques : - *
* *
******************************************************************************/
-GPluginModule **get_all_plugins(size_t *count)
+GPluginModule *get_plugin_by_name(const char *name, size_t *index)
{
- GPluginModule **result; /* Liste à retourner */
- size_t i; /* Boucle de parcours */
-
- g_rw_lock_reader_lock(&_pg_lock);
-
- result = malloc(_pg_count * sizeof(GPluginModule *));
- *count = _pg_count;
+ GPluginModule *result; /* Greffon trouvé à renvoyer */
- for (i = 0; i < _pg_count; i++)
- {
- result[i] = _pg_list[i];
- g_object_ref(G_OBJECT(_pg_list[i]));
- }
+ result = _find_plugin_by_name(name, index);
- g_rw_lock_reader_unlock(&_pg_lock);
+ if (result != NULL)
+ ref_object(result);
return result;
@@ -615,48 +690,30 @@ GPluginModule **get_all_plugins(size_t *count)
/******************************************************************************
* *
-* Paramètres : action = fonctionnalité recherchée. *
-* count = nombre de greffons trouvés. [OUT] *
+* Paramètres : count = nombre de greffons trouvés. [OUT] *
* *
-* Description : Fournit les greffons offrant le service demandé. *
+* Description : Fournit la liste de l'ensemble des greffons. *
* *
-* Retour : Liste de greffons correspondants issue d'un tri interne. *
+* Retour : Liste de tous les greffons chargés. *
* *
* Remarques : - *
* *
******************************************************************************/
-GPluginModule **get_all_plugins_for_action(PluginAction action, size_t *count)
+GPluginModule **get_all_plugins(size_t *count)
{
GPluginModule **result; /* Liste à retourner */
- size_t i; /* Boucle de parcours #1 */
- const plugin_interface *pg_iface; /* Informations à consulter */
- size_t j; /* Boucle de parcours #2 */
-
- result = NULL;
- *count = 0;
+ size_t i; /* Boucle de parcours */
g_rw_lock_reader_lock(&_pg_lock);
+ result = malloc(_pg_count * sizeof(GPluginModule *));
+ *count = _pg_count;
+
for (i = 0; i < _pg_count; i++)
{
- pg_iface = g_plugin_module_get_interface(_pg_list[i]);
-
- for (j = 0; j < pg_iface->actions_count; j++)
- {
- if (pg_iface->actions[j] == action)
- {
- result = realloc(result, ++(*count) * sizeof(GPluginModule *));
-
- result[*count - 1] = _pg_list[i];
- g_object_ref(G_OBJECT(_pg_list[i]));
-
- break;
-
- }
-
- }
-
+ result[i] = _pg_list[i];
+ ref_object(result[i]);
}
g_rw_lock_reader_unlock(&_pg_lock);
diff --git a/src/plugins/pglist.h b/src/plugins/pglist.h
index 83e9091..777b19c 100644
--- a/src/plugins/pglist.h
+++ b/src/plugins/pglist.h
@@ -52,9 +52,6 @@ void _lock_unlock_plugin_list_for_reading(bool lock);
#define unlock_plugin_list_for_reading() _lock_unlock_plugin_list_for_reading(false)
/* Ajoute un greffon à la liste principale de greffons. */
-void _register_plugin(GPluginModule *);
-
-/* Ajoute un greffon à la liste principale de greffons. */
void register_plugin(GPluginModule *);
/* Charge tous les greffons restant à charger. */
@@ -66,16 +63,74 @@ GPluginModule *get_plugin_by_name(const char *, size_t *);
/* Fournit la liste de l'ensemble des greffons. */
GPluginModule **get_all_plugins(size_t *);
-/* Fournit les greffons offrant le service demandé. */
-GPluginModule **get_all_plugins_for_action(PluginAction, size_t *);
-
/**
* Définitions des opérations appliquables à une catégories de greffons.
*/
-#define process_all_plugins_for(a, f, ...) \
+#define process_all_plugins_for(tp, cst, fc) \
+ do \
+ { \
+ size_t __count; \
+ GPluginModule **__list; \
+ size_t __i; \
+ GPluginModule *__pg; \
+ __list = get_all_plugins(&__count); \
+ for (__i = 0; __i < __count; __i++) \
+ { \
+ __pg = __list[__i]; \
+ if (G_TYPE_CHECK_INSTANCE_TYPE(__pg, tp)) \
+ fc(cst(__pg)); \
+ unref_object(__pg); \
+ } \
+ if (__list != NULL) \
+ free(__list); \
+ } \
+ while (0)
+
+#define accumulate_from_all_plugins(tp, cst, fc, atp, cnt) \
+ ({ \
+ atp *__acc_list; \
+ size_t __count; \
+ GPluginModule **__list; \
+ size_t __i; \
+ GPluginModule *__pg; \
+ size_t __tmp_count; \
+ atp *__tmp_list; \
+ *cnt = 0; \
+ __acc_list = NULL; \
+ __list = get_all_plugins(&__count); \
+ for (__i = 0; __i < __count; __i++) \
+ { \
+ __pg = __list[__i]; \
+ if (G_TYPE_CHECK_INSTANCE_TYPE(__pg, tp)) \
+ { \
+ __tmp_list = fc(cst(__pg), &__tmp_count); \
+ if (__tmp_list != NULL) \
+ { \
+ __acc_list = realloc(__acc_list, \
+ (*cnt + __tmp_count) * sizeof(atp)); \
+ memcpy(&__acc_list[*cnt], __tmp_list, \
+ __tmp_count * sizeof(atp)); \
+ *cnt += __tmp_count; \
+ free(__tmp_list); \
+ } \
+ } \
+ unref_object(__pg); \
+ } \
+ if (__list != NULL) \
+ free(__list); \
+ __acc_list; \
+ })
+
+
+
+#if 0
+
+// TODO : REMME
+
+#define process_all_plugins_for_old__(a, f, ...) \
do \
{ \
size_t __count; \
@@ -114,11 +169,13 @@ GPluginModule **get_all_plugins_for_action(PluginAction, size_t *);
/* DPS_PG_MANAGEMENT */
+/*
#define notify_native_plugins_loaded() \
- process_all_plugins_for(PGA_NATIVE_PLUGINS_LOADED, g_plugin_module_notify_plugins_loaded, NULL)
+ process_all_plugins_for_old__(PGA_NATIVE_PLUGINS_LOADED, g_plugin_module_notify_plugins_loaded, NULL)
#define notify_all_plugins_loaded() \
- process_all_plugins_for(PGA_ALL_PLUGINS_LOADED, g_plugin_module_notify_plugins_loaded, NULL)
+ process_all_plugins_for_old__(PGA_ALL_PLUGINS_LOADED, g_plugin_module_notify_plugins_loaded, NULL)
+*/
#define build_type_instance(t) \
process_plugins_while_null(PGA_TYPE_BUILDING, g_plugin_module_build_type_instance, t)
@@ -126,44 +183,47 @@ GPluginModule **get_all_plugins_for_action(PluginAction, size_t *);
/* DPS_SETUP */
#define include_plugin_theme(d, r, c) \
- process_all_plugins_for(PGA_GUI_THEME, g_plugin_module_include_theme, d, r, c)
+ process_all_plugins_for_old__(PGA_GUI_THEME, g_plugin_module_include_theme, d, r, c)
/* DPS_RUNNING */
#define notify_panel_creation(i) \
- process_all_plugins_for(PGA_PANEL_CREATION, g_plugin_module_notify_panel_creation, i)
+ process_all_plugins_for_old__(PGA_PANEL_CREATION, g_plugin_module_notify_panel_creation, i)
#define notify_panel_docking(i, d) \
- process_all_plugins_for(PGA_PANEL_DOCKING, g_plugin_module_notify_panel_docking, i, d)
+ process_all_plugins_for_old__(PGA_PANEL_DOCKING, g_plugin_module_notify_panel_docking, i, d)
/* DPS_CONTENT */
#define handle_binary_content(a, c, i, s) \
- process_all_plugins_for(a, g_plugin_module_handle_binary_content, c, i, s)
+ process_all_plugins_for_old__(a, g_plugin_module_handle_binary_content, c, i, s)
#define handle_loaded_content(a, c, i, s) \
- process_all_plugins_for(a, g_plugin_module_handle_loaded_content, c, i, s)
+ process_all_plugins_for_old__(a, g_plugin_module_handle_loaded_content, c, i, s)
/* DPS_FORMAT */
#define handle_known_format_analysis(a, f, g, s) \
- process_all_plugins_for(a, g_plugin_module_handle_known_format_analysis, f, g, s)
+ process_all_plugins_for_old__(a, g_plugin_module_handle_known_format_analysis, f, g, s)
#define preload_binary_format(a, f, i, s) \
- process_all_plugins_for(a, g_plugin_module_preload_binary_format, f, i, s)
+ process_all_plugins_for_old__(a, g_plugin_module_preload_binary_format, f, i, s)
#define attach_debug_format(f) \
- process_all_plugins_for(PGA_FORMAT_ATTACH_DEBUG, g_plugin_module_attach_debug_format, f)
+ process_all_plugins_for_old__(PGA_FORMAT_ATTACH_DEBUG, g_plugin_module_attach_debug_format, f)
/* DPS_DISASSEMBLY */
#define process_disassembly_event(a, b, s, c) \
- process_all_plugins_for(a, g_plugin_module_process_disassembly_event, b, s, c)
+ process_all_plugins_for_old__(a, g_plugin_module_process_disassembly_event, b, s, c)
/* DPS_DETECTION */
#define detect_external_tools(a, cnt, v, n, c) \
- process_all_plugins_for(a, g_plugin_module_detect_external_tools, cnt, v, n, c)
+ process_all_plugins_for_old__(a, g_plugin_module_detect_external_tools, cnt, v, n, c)
+
+
+#endif
diff --git a/src/plugins/plugin-def.h b/src/plugins/plugin-def.h
index 1118140..b5e0b51 100644
--- a/src/plugins/plugin-def.h
+++ b/src/plugins/plugin-def.h
@@ -35,18 +35,6 @@
/* ------------------------ IDENTIFICATION DE COMPATIBILITES ------------------------ */
-/* Version identifiant les définitions courantes */
-typedef uint32_t plugin_abi_version_t;
-
-#define DEFINE_PLUGIN_ABI_VERSION(maj, min, rev) \
- (((maj & 0xff) << 24) | ((min & 0xff) << 16) | (rev & 0xffff))
-
-#define GET_ABI_MAJ_VERSION(vs) ((vs >> 24) & 0xff)
-#define GET_ABI_MIN_VERSION(vs) ((vs >> 16) & 0xff)
-#define GET_ABI_REV_VERSION(vs) (vs & 0xffff)
-
-#define CURRENT_ABI_VERSION DEFINE_PLUGIN_ABI_VERSION(0, 3, 0)
-
/* ------------------------- DEFINITION D'UN PROJET INTERNE ------------------------- */
@@ -232,14 +220,14 @@ typedef enum _PluginAction
/* ------------------------ PREMIER INTERFACAGE PROTOCOLAIRE ------------------------ */
-#define CHRYSALIDE_PLUGIN_MAGIC 0xdeadc0de1234abcdull
+//#define CHRYSALIDE_PLUGIN_MAGIC 0xdeadc0de1234abcdull
/* Définition d'un greffon */
typedef struct _plugin_interface
{
uint64_t magic; /* Vérification a minima */
- plugin_abi_version_t abi_version; /* Version du protocole utilisé*/
+ uint32_t /*plugin_abi_version_t*/ abi_version; /* Version du protocole utilisé*/
/**
* Les champs suivants ne sont généralement pas alloués dynamiquement,
diff --git a/src/plugins/plugin-int.h b/src/plugins/plugin-int.h
index 3ba19dc..07b455a 100644
--- a/src/plugins/plugin-int.h
+++ b/src/plugins/plugin-int.h
@@ -37,21 +37,28 @@
#include "../common/bits.h"
-/* Transfert de la conscience de soi. */
-typedef void (* pg_set_self_fc) (GPluginModule *);
-/* Prend acte du [dé]chargement du greffon. */
+/* Pointe le fichier contenant le greffon manipulé. */
+typedef char * (* get_plugin_filename_fc) (const GPluginModule *);
+
+/* Fournit le nom brut associé au greffon. */
+typedef char * (* get_plugin_modname_fc) (const GPluginModule *);
+
+/* Prend acte de (l'|la dés)activation du greffon. */
typedef bool (* pg_management_fc) (GPluginModule *);
+
+
+
+/* Transfert de la conscience de soi. */
+typedef void (* pg_set_self_fc) (GPluginModule *);
+
/* Accompagne la fin du chargement des modules natifs. */
typedef void (* pg_plugins_loaded_fc) (GPluginModule *, PluginAction);
/* Crée une instance à partir d'un type dynamique externe. */
typedef gpointer (* pg_build_instance_fc) (GPluginModule *, PluginAction, GType);
-/* Fournit le nom brut associé au greffon. */
-typedef char * (* pg_get_modname_fc) (const GPluginModule *);
-
#if 0
/* Procède à une opération liée à un contenu binaire. */
@@ -90,22 +97,47 @@ typedef void (* pg_detect_tools_fc) (const GPluginModule *, PluginAction, const
#endif
+/* Marqueur identifiable */
+#define CHRYSALIDE_PLUGIN_MAGIC 0xdeadc0de
+
+
+/* Version identifiant les définitions courantes */
+typedef uint32_t plugin_abi_version_t;
+
+#define DEFINE_PLUGIN_ABI_VERSION(maj, min, rev) \
+ (((maj & 0xff) << 24) | ((min & 0xff) << 16) | (rev & 0xffff))
+
+#define GET_ABI_MAJ_VERSION(vs) ((vs >> 24) & 0xff)
+#define GET_ABI_MIN_VERSION(vs) ((vs >> 16) & 0xff)
+#define GET_ABI_REV_VERSION(vs) (vs & 0xffff)
+
+/**
+ * 0.3.0 : dernière version avec actions et fonctions associées
+ * 1.0.0 (04/01/25) : bascule en chargement d'objet et interfaces
+ */
+#define CURRENT_ABI_VERSION DEFINE_PLUGIN_ABI_VERSION(1, 0, 0)
+
+
/* Greffon pour Chrysalide (instance) */
struct _GPluginModule
{
GObject parent; /* A laisser en premier */
- char *filename; /* Fichier associé au greffon */
- GModule *module; /* Abstration de manipulation */
+ uint32_t magic; /* Vérification a minima */
+ plugin_abi_version_t abi_version; /* Version du protocole utilisé*/
+
+ char *name; /* Désignation humaine courte */
+ char *desc; /* Description plus loquace */
+ char *version; /* Version du greffon */
+ char *url; /* Site Web associé */
- const plugin_interface *interface; /* Déclaration d'interfaçage */
+ char **required; /* Pré-chargements requis */
+ size_t required_count; /* Quantité de ces dépendances */
PluginStatusFlags flags; /* Fanion pour l'état courant */
bitfield_t *dependencies; /* Cartographie des dépendances*/
- //GGenConfig *config; /* Configuration dédiée */
-
};
@@ -114,6 +146,18 @@ struct _GPluginModuleClass
{
GObjectClass parent; /* A laisser en premier */
+ get_plugin_filename_fc get_filename; /* Obtention du chemin */
+ get_plugin_modname_fc get_modname; /* Fourniture du nom brut */
+
+ pg_management_fc enable; /* Procédure d'activation */
+ pg_management_fc disable; /* Procédure d'extinction */
+
+
+
+ /////////////////////////////////////////////
+
+#if 0
+
pg_management_fc init; /* Procédure d'initialisation */
pg_management_fc manage; /* Etape dans la vie du greffon*/
pg_management_fc exit; /* Procédure d'extinction */
@@ -121,8 +165,6 @@ struct _GPluginModuleClass
pg_plugins_loaded_fc plugins_loaded; /* Fin des chargements */
pg_build_instance_fc build_instance; /* Création d'objets */
- pg_get_modname_fc get_modname; /* Fourniture du nom brut */
-
#if 0
#ifdef INCLUDE_GTK_SUPPORT
pg_include_theme_fc include_theme; /* Extension d'un thème */
@@ -141,12 +183,28 @@ struct _GPluginModuleClass
pg_detect_tools_fc detect; /* Lancement de détections */
#endif
+#endif
+
+ /////////////////////////////////////////////
+
};
-/* Met en place la configuration dédiée au greffon. */
-void g_plugin_module_create_config(GPluginModule *);
+
+#define STORE_PLUGIN_ABI(p) \
+ do \
+ { \
+ GPluginModule *_p; \
+ _p = G_PLUGIN_MODULE(p); \
+ _p->magic = CHRYSALIDE_PLUGIN_MAGIC; \
+ _p->abi_version = CURRENT_ABI_VERSION; \
+ } \
+ while (0);
+
+
+/* Met en place un greffon. */
+bool g_plugin_module_create(GPluginModule *, const char *, const char *, const char *, const char *, const char * const *, size_t);
diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c
index 75cf4e0..dfdf3ed 100644
--- a/src/plugins/plugin.c
+++ b/src/plugins/plugin.c
@@ -30,14 +30,13 @@
#include <libgen.h>
#include <malloc.h>
#include <stdarg.h>
-#include <stdbool.h>
#include <stdio.h>
#include <string.h>
-#include "dt.h"
#include "pglist.h"
#include "plugin-int.h"
+#include "../common/compiler.h"
#include "../common/extstr.h"
#include "../common/pathname.h"
#include "../common/xdg.h"
@@ -56,19 +55,12 @@ static void g_plugin_module_dispose(GPluginModule *);
/* Procède à la libération totale de la mémoire. */
static void g_plugin_module_finalize(GPluginModule *);
-/* Initialise la classe des greffons d'extension. */
-static void g_plugin_module_init_gclass(GPluginModuleClass *, GModule *);
-
-/* Fournit le nom brut associé au greffon. */
-static char *_g_plugin_module_get_modname(const GPluginModule *);
-
/* Indique le type défini pour un greffon. */
G_DEFINE_TYPE(GPluginModule, g_plugin_module, G_TYPE_OBJECT);
-
/******************************************************************************
* *
* Paramètres : class = classe à initialiser. *
@@ -84,16 +76,17 @@ G_DEFINE_TYPE(GPluginModule, g_plugin_module, G_TYPE_OBJECT);
static void g_plugin_module_class_init(GPluginModuleClass *class)
{
GObjectClass *object; /* Autre version de la classe */
- GPluginModuleClass *plugin; /* Version parente de la classe*/
object = G_OBJECT_CLASS(class);
object->dispose = (GObjectFinalizeFunc/* ! */)g_plugin_module_dispose;
object->finalize = (GObjectFinalizeFunc)g_plugin_module_finalize;
- plugin = G_PLUGIN_MODULE_CLASS(class);
+ class->get_filename = NULL;
+ class->get_modname = NULL;
- plugin->get_modname = (pg_get_modname_fc)_g_plugin_module_get_modname;
+ class->enable = NULL;
+ class->disable = NULL;
}
@@ -112,7 +105,17 @@ static void g_plugin_module_class_init(GPluginModuleClass *class)
static void g_plugin_module_init(GPluginModule *plugin)
{
- //plugin->config = NULL;
+ plugin->name = NULL;
+ plugin->desc = NULL;
+ plugin->version = NULL;
+ plugin->url = NULL;
+
+ plugin->required = NULL;
+ plugin->required_count = 0;
+
+ plugin->flags = PSF_NONE;
+
+ plugin->dependencies = NULL;
}
@@ -131,29 +134,29 @@ static void g_plugin_module_init(GPluginModule *plugin)
static void g_plugin_module_dispose(GPluginModule *plugin)
{
- const plugin_interface *pg_iface; /* Définition du greffon */
size_t i; /* Boucle de parcours */
+ size_t index; /* Indice de greffon visé */
GPluginModule *dependency; /* Module nécessaire */
GPluginModuleClass *class; /* Classe de l'instance active */
- pg_iface = g_plugin_module_get_interface(plugin);
-
- if (pg_iface != NULL)
+ if (plugin->dependencies != NULL)
{
lock_plugin_list_for_reading();
- for (i = 0; i < pg_iface->required_count; i++)
+ for (i = 0; i < plugin->required_count; i++)
{
- dependency = get_plugin_by_name(pg_iface->required[i], NULL);
+ dependency = get_plugin_by_name(plugin->required[i], &index);
- /* Si le chargement a bien été complet avant la sortie... */
- if (dependency != NULL)
+ /* Si la dépendance a bien été pris en compte... */
+ if (test_in_bit_field(plugin->dependencies, index))
{
+ assert(dependency != NULL);
+
/* Un coup pour l'appel à get_plugin_by_name(). */
- g_object_unref(G_OBJECT(dependency));
+ unref_object(dependency);
/* Un coup pour la dépendance */
- g_object_unref(G_OBJECT(dependency));
+ unref_object(dependency);
}
@@ -163,25 +166,13 @@ static void g_plugin_module_dispose(GPluginModule *plugin)
}
- class = G_PLUGIN_MODULE_GET_CLASS(plugin);
-
- if (class->exit != NULL)
- class->exit(plugin);
-
- /*
- if (plugin->config != NULL)
+ if (plugin->flags & PSF_LOADED)
{
- g_generic_config_write(plugin->config);
-
- g_clear_object(&plugin->config);
+ class = G_PLUGIN_MODULE_GET_CLASS(plugin);
- }
- */
+ if (class->disable != NULL)
+ class->disable(plugin);
- if (plugin->module != NULL)
- {
- g_module_close(plugin->module);
- plugin->module = NULL;
}
G_OBJECT_CLASS(g_plugin_module_parent_class)->dispose(G_OBJECT(plugin));
@@ -203,7 +194,25 @@ static void g_plugin_module_dispose(GPluginModule *plugin)
static void g_plugin_module_finalize(GPluginModule *plugin)
{
- free(plugin->filename);
+ size_t i; /* Boucle de parcours */
+
+ if (plugin->name != NULL)
+ free(plugin->name);
+
+ if (plugin->desc != NULL)
+ free(plugin->desc);
+
+ if (plugin->version != NULL)
+ free(plugin->version);
+
+ if (plugin->url != NULL)
+ free(plugin->url);
+
+ for (i = 0; i < plugin->required_count; i++)
+ free(plugin->required[i]);
+
+ if (plugin->required != NULL)
+ free(plugin->required);
if (plugin->dependencies != NULL)
delete_bit_field(plugin->dependencies);
@@ -215,627 +224,173 @@ static void g_plugin_module_finalize(GPluginModule *plugin)
/******************************************************************************
* *
-* Paramètres : filename = nom du fichier à charger. *
+* Paramètres : plugin = instance à initialiser pleinement. *
+* name = nom du greffon pour référence, principalement. *
+* desc = présentation éventuelle à destination humaine. *
+* version = indication de version éventuelle. *
+* url = référence vers une ressource en ligne. *
+* required = liste de dépendances éventuelles ou NULL. *
+* count = taille de cette liste. *
* *
-* Description : Crée un module pour un greffon donné. *
+* Description : Met en place un greffon. *
* *
-* Retour : Adresse de la structure mise en place. *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-GPluginModule *g_plugin_module_new(const gchar *filename)
+bool g_plugin_module_create(GPluginModule *plugin, const char *name, const char *desc, const char *version, const char *url, const char * const *required, size_t count)
{
- GPluginModule *result; /* Structure à retourner */
- GModule *module; /* Abstration de manipulation */
- pg_set_self_fc set_self; /* Copie du greffon */
- const plugin_interface *interface; /* Déclaration d'interfaçage */
- plugin_abi_version_t current; /* Version de l'ABI actuelle */
- bool valid; /* Statut de validité */
- size_t i; /* Boucle de parcours */
- uint32_t action; /* Identifiant d'une action */
- uint32_t category; /* Catégorie principale */
- uint32_t sub; /* Sous-catégorie visée */
- GType gtype; /* Nouveau type de greffon */
-
- module = g_module_open(filename, G_MODULE_BIND_LAZY);
- if (module == NULL)
- {
- log_variadic_message(LMT_ERROR,
- _("Error while loading the plugin candidate '%s' : %s"),
- filename, g_module_error());
- goto bad_module;
- }
-
-
-#define load_plugin_symbol(mod, sym, dest) \
- ({ \
- bool __result; \
- if (!g_module_symbol(mod, sym, (gpointer *)dest)) \
- { \
- log_variadic_message(LMT_ERROR, \
- _("No '%s' entry in plugin candidate '%s'"), \
- sym, filename); \
- __result = false; \
- } \
- else __result = true; \
- __result; \
- })
-
-
- /* Récupération de la version d'ABI */
-
- if (!load_plugin_symbol(module, "chrysalide_plugin_set_self", &set_self))
- goto no_self_setter;
-
- if (!load_plugin_symbol(module, "_chrysalide_plugin", &interface))
- goto no_interface;
-
- current = CURRENT_ABI_VERSION;
-
- if (current != interface->abi_version)
- goto wrong_abi;
-
- /* Localisation des différents points d'entrée déclarés */
-
+ bool result; /* Bilan à retourner */
+ size_t i; /* Boucle de parcours #1 */
+ size_t k; /* Boucle de parcours #2 */
-#define check_plugin_symbol(mod, sym) \
- ({ \
- bool __result; \
- __result = g_module_symbol(mod, sym, (gpointer []) { NULL }); \
- if (!__result) \
- log_variadic_message(LMT_ERROR, \
- _("No '%s' entry in plugin candidate '%s'"), \
- sym, filename); \
- __result; \
- })
+ /* Validations préalables */
+ assert(name != NULL);
- valid = true;
+ result = (name != NULL);
- for (i = 0; i < interface->actions_count && valid; i++)
+ if (result && plugin->abi_version != CURRENT_ABI_VERSION)
{
- action = interface->actions[i];
- category = MASK_PLUGIN_CATEGORY(action);
- sub = MASK_PLUGIN_SUB_CATEGORY(action);
-
- switch (category)
- {
- case DPC_BASIC:
-
- switch (sub)
- {
- case DPS_NONE:
- break;
-
- case DPS_PG_MANAGEMENT:
-
- switch (action)
- {
- case PGA_PLUGIN_INIT:
- valid = check_plugin_symbol(module, "chrysalide_plugin_init");
- break;
-
- case PGA_PLUGIN_LOADED:
- valid = check_plugin_symbol(module, "chrysalide_plugin_manage");
- break;
-
- case PGA_PLUGIN_EXIT:
- valid = check_plugin_symbol(module, "chrysalide_plugin_exit");
- break;
-
- default:
- log_variadic_message(LMT_WARNING,
- _("Unknown action '0x%02x' in plugin '%s'..."),
- interface->actions[i], filename);
- break;
-
- }
-
- break;
-
- case DPS_CORE_MANAGEMENT:
-
- switch (action)
- {
- case PGA_NATIVE_PLUGINS_LOADED:
- case PGA_ALL_PLUGINS_LOADED:
- valid = check_plugin_symbol(module, "chrysalide_plugin_on_plugins_loaded");
- break;
-
- case PGA_TYPE_BUILDING:
- valid = check_plugin_symbol(module, "chrysalide_plugin_build_type_instance");
- break;
-
- default:
- log_variadic_message(LMT_WARNING,
- _("Unknown action '0x%02x' in plugin '%s'..."),
- interface->actions[i], filename);
- break;
-
- }
-
- break;
-
- default:
- log_variadic_message(LMT_WARNING,
- _("Unknown sub-category '0x%02x' in plugin '%s'..."), sub, filename);
- break;
-
- }
-
- break;
-
-#if 0
-
- case DPC_GUI:
-
- switch (sub)
- {
- case DPS_SETUP:
-
- switch (action)
- {
- case PGA_GUI_THEME:
- valid = check_plugin_symbol(module, "chrysalide_plugin_include_theme");
- break;
-
- default:
- log_variadic_message(LMT_WARNING,
- _("Unknown action '0x%02x' in plugin '%s'..."),
- interface->actions[i], filename);
- break;
-
- }
-
- break;
-
- case DPS_RUNNING:
-
- switch (action)
- {
- case PGA_PANEL_CREATION:
- valid = check_plugin_symbol(module, "chrysalide_plugin_on_panel_creation");
- break;
-
- case PGA_PANEL_DOCKING:
- valid = check_plugin_symbol(module, "chrysalide_plugin_on_panel_docking");
- break;
-
- default:
- log_variadic_message(LMT_WARNING,
- _("Unknown action '0x%02x' in plugin '%s'..."),
- interface->actions[i], filename);
- break;
-
- }
-
- break;
-
- default:
- log_variadic_message(LMT_WARNING,
- _("Unknown sub-category '0x%02x' in plugin '%s'..."), sub, filename);
- break;
-
- }
-
- break;
-
- case DPC_BINARY_PROCESSING:
-
- switch (sub)
- {
- case DPS_CONTENT:
-
- switch (action)
- {
- case PGA_CONTENT_EXPLORER:
- case PGA_CONTENT_RESOLVER:
- valid = check_plugin_symbol(module, "chrysalide_plugin_handle_binary_content");
- break;
-
- case PGA_CONTENT_ANALYZED:
- valid = check_plugin_symbol(module, "chrysalide_plugin_handle_loaded_content");
- break;
-
- default:
- log_variadic_message(LMT_WARNING,
- _("Unknown action '0x%02x' in plugin '%s'..."),
- interface->actions[i], filename);
- break;
-
- }
+ result = false;
- break;
-
- case DPS_FORMAT:
+ log_variadic_message(LMT_ERROR, _("ABI mismatch detected: %08x (plugin) vs %08x (core)"),
+ plugin->abi_version, CURRENT_ABI_VERSION);
- switch (action)
- {
- case PGA_FORMAT_ANALYSIS_STARTED:
- case PGA_FORMAT_ANALYSIS_ENDED:
- case PGA_FORMAT_POST_ANALYSIS_STARTED:
- case PGA_FORMAT_POST_ANALYSIS_ENDED:
- valid = check_plugin_symbol(module, "chrysalide_plugin_handle_binary_format_analysis");
- break;
+ }
- case PGA_FORMAT_PRELOAD:
- valid = check_plugin_symbol(module, "chrysalide_plugin_preload_binary_format");
- break;
+ /* Mémorisation des informations */
- case PGA_FORMAT_ATTACH_DEBUG:
- valid = check_plugin_symbol(module, "chrysalide_plugin_attach_debug");
- break;
+ if (result)
+ {
+ plugin->name = strdup(name);
- default:
- log_variadic_message(LMT_WARNING,
- _("Unknown action '0x%02x' in plugin '%s'..."),
- interface->actions[i], filename);
- break;
+ if (desc != NULL)
+ plugin->desc = strdup(desc);
- }
+ if (version != NULL)
+ plugin->version = strdup(version);
- break;
+ if (url != NULL)
+ plugin->url = strdup(url);
- case DPS_DISASSEMBLY:
- valid = check_plugin_symbol(module, "chrysalide_plugin_process_disassembly_event");
- break;
-
- case DPS_DETECTION:
- valid = check_plugin_symbol(module, "chrysalide_plugin_detect_external_tools");
- break;
+ if (count > 0)
+ {
+ plugin->required = malloc(count * sizeof(char *));
+ plugin->required_count = 0;
- default:
- log_variadic_message(LMT_WARNING,
- _("Unknown sub-category '0x%02x' in plugin '%s'..."), sub, filename);
+ for (i = 0; i < count; i++)
+ {
+ for (k = 0; k < plugin->required_count; k++)
+ if (strcmp(required[i], plugin->required[k]) == 0)
break;
- }
+ if (k < plugin->required_count)
+ continue;
-#endif
+ plugin->required[plugin->required_count++] = strdup(required[i]);
- break;
+ }
- default:
- log_variadic_message(LMT_WARNING,
- _("Unknown category '0x%02x' in plugin '%s'..."), category, filename);
- break;
+ plugin->required = realloc(plugin->required, plugin->required_count * sizeof(char *));
}
}
- if (!valid)
- goto missing_feature;
-
- gtype = build_dynamic_type(G_TYPE_PLUGIN_MODULE, interface->gtp_name,
- (GClassInitFunc)g_plugin_module_init_gclass, module, NULL);
-
- if (gtype == G_TYPE_INVALID)
- goto no_instance;
-
- result = g_object_new(gtype, NULL);
-
- result->filename = strdup(filename);
- result->module = module;
-
- result->interface = interface;
-
- set_self(result);
-
return result;
- no_self_setter:
-
- log_variadic_message(LMT_ERROR, _("Self pointer setter is missing for plugin '%s'"), filename);
- goto bad_plugin;
-
- no_interface:
-
- log_variadic_message(LMT_ERROR, _("Main interface is missing for plugin '%s'"), filename);
- goto bad_plugin;
-
- wrong_abi:
-
- log_variadic_message(LMT_ERROR, _("ABI mismatch detected! Plugin '%s' rejected"), filename);
- goto bad_plugin;
-
- missing_feature:
-
- log_variadic_message(LMT_ERROR, _("An expected feature is missing for plugin '%s'"), filename);
- goto bad_plugin;
-
- no_instance:
-
- log_variadic_message(LMT_ERROR, _("Unabled to create an instance of plugin '%s'"), filename);
-
- bad_plugin:
-
- g_module_close(module);
-
- bad_module:
-
- return NULL;
-
}
/******************************************************************************
* *
-* Paramètres : class = classe à initialiser. *
-* module = module représentant le greffon chargé en mémoire. *
+* Paramètres : plugin = greffon à consulter. *
* *
-* Description : Initialise la classe des greffons d'extension. *
+* Description : Indique le nom associé à un greffon. *
* *
-* Retour : - *
+* Retour : Désignation interne de l'extension, pour référence(s). *
* *
* Remarques : - *
* *
******************************************************************************/
-static void g_plugin_module_init_gclass(GPluginModuleClass *class, GModule *module)
+const char *g_plugin_module_get_name(const GPluginModule *plugin)
{
- const plugin_interface *interface; /* Déclaration d'interfaçage */
- size_t i; /* Boucle de parcours */
- uint32_t action; /* Identifiant d'une action */
- uint32_t category; /* Catégorie principale */
- uint32_t sub; /* Sous-catégorie visée */
-
-
-#undef load_plugin_symbol
-
-#define load_plugin_symbol(mod, sym, dest) \
- ({ \
- bool __result; \
- __result = g_module_symbol(mod, sym, (gpointer *)dest); \
- assert(__result); \
- __result; \
- })
-
-
- load_plugin_symbol(module, "_chrysalide_plugin", &interface);
-
- for (i = 0; i < interface->actions_count; i++)
- {
- action = interface->actions[i];
- category = MASK_PLUGIN_CATEGORY(action);
- sub = MASK_PLUGIN_SUB_CATEGORY(action);
-
- switch (category)
- {
- case DPC_BASIC:
-
- switch (sub)
- {
- case DPS_NONE:
- break;
-
- case DPS_PG_MANAGEMENT:
-
- switch (action)
- {
- case PGA_PLUGIN_INIT:
- load_plugin_symbol(module, "chrysalide_plugin_init", &class->init);
- break;
-
- case PGA_PLUGIN_LOADED:
- load_plugin_symbol(module, "chrysalide_plugin_manage", &class->manage);
- break;
-
- case PGA_PLUGIN_EXIT:
- load_plugin_symbol(module, "chrysalide_plugin_exit", &class->exit);
- break;
-
- default:
- assert(false);
- break;
-
- }
-
- break;
-
- case DPS_CORE_MANAGEMENT:
-
- switch (action)
- {
- case PGA_NATIVE_PLUGINS_LOADED:
- case PGA_ALL_PLUGINS_LOADED:
- load_plugin_symbol(module, "chrysalide_plugin_on_plugins_loaded",
- &class->plugins_loaded);
- break;
-
- case PGA_TYPE_BUILDING:
- load_plugin_symbol(module, "chrysalide_plugin_build_type_instance",
- &class->build_instance);
- break;
-
- default:
- assert(false);
- break;
-
- }
-
- break;
-
- default:
- assert(false);
- break;
-
- }
-
- break;
-#if 0
- case DPC_GUI:
-
- switch (sub)
- {
- case DPS_SETUP:
-
- switch (action)
- {
- case PGA_GUI_THEME:
-#ifdef INCLUDE_GTK_SUPPORT
- load_plugin_symbol(module, "chrysalide_plugin_include_theme",
- &class->include_theme);
-#endif
- break;
-
- default:
- assert(false);
- break;
-
- }
-
- break;
-
- case DPS_RUNNING:
-
- switch (action)
- {
- case PGA_PANEL_CREATION:
-#ifdef INCLUDE_GTK_SUPPORT
- load_plugin_symbol(module, "chrysalide_plugin_on_panel_creation",
- &class->notify_panel);
-#endif
- break;
-
- case PGA_PANEL_DOCKING:
-#ifdef INCLUDE_GTK_SUPPORT
- load_plugin_symbol(module, "chrysalide_plugin_on_panel_docking",
- &class->notify_docking);
-#endif
- break;
-
- default:
- assert(false);
- break;
-
- }
-
- break;
-
- default:
- assert(false);
- break;
+ const char *result; /* Valeur finale à renvoyer */
- }
+ result = plugin->name;
- break;
-
- case DPC_BINARY_PROCESSING:
-
- switch (sub)
- {
- case DPS_CONTENT:
-
- switch (action)
- {
- case PGA_CONTENT_EXPLORER:
- case PGA_CONTENT_RESOLVER:
- load_plugin_symbol(module, "chrysalide_plugin_handle_binary_content",
- &class->handle_content);
- break;
-
- case PGA_CONTENT_ANALYZED:
- load_plugin_symbol(module, "chrysalide_plugin_handle_loaded_content",
- &class->handle_loaded);
- break;
-
- default:
- assert(false);
- break;
-
- }
-
- break;
-
- case DPS_FORMAT:
-
- switch (action)
- {
- case PGA_FORMAT_ANALYSIS_STARTED:
- case PGA_FORMAT_ANALYSIS_ENDED:
- case PGA_FORMAT_POST_ANALYSIS_STARTED:
- case PGA_FORMAT_POST_ANALYSIS_ENDED:
- load_plugin_symbol(module, "chrysalide_plugin_handle_binary_format_analysis",
- &class->handle_fmt_analysis);
- break;
-
- case PGA_FORMAT_PRELOAD:
- load_plugin_symbol(module, "chrysalide_plugin_preload_binary_format", &class->preload_format);
- break;
-
- case PGA_FORMAT_ATTACH_DEBUG:
- load_plugin_symbol(module, "chrysalide_plugin_attach_debug", &class->attach_debug);
- break;
+ return result;
- default:
- assert(false);
- break;
+}
- }
- break;
+/******************************************************************************
+* *
+* Paramètres : plugin = greffon à consulter. *
+* *
+* Description : Fournit une description fonctionnelle d'un greffon. *
+* *
+* Retour : Description textuelle associée à une extension ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- case DPS_DISASSEMBLY:
- load_plugin_symbol(module, "chrysalide_plugin_process_disassembly_event", &class->process_disass);
- break;
+const char *g_plugin_module_get_desc(const GPluginModule *plugin)
+{
+ const char *result; /* Valeur finale à renvoyer */
- case DPS_DETECTION:
- load_plugin_symbol(module, "chrysalide_plugin_detect_external_tools", &class->detect);
- break;
+ result = plugin->desc;
- default:
- assert(false);
- break;
+ return result;
- }
+}
-#endif
- break;
+/******************************************************************************
+* *
+* Paramètres : plugin = greffon à consulter. *
+* *
+* Description : Fournit la version d'un greffon et de ses fonctionnalités. *
+* *
+* Retour : Version sous forme de chaîne de caractères ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
- default:
- assert(false);
- break;
+const char *g_plugin_module_get_version(const GPluginModule *plugin)
+{
+ const char *result; /* Valeur finale à renvoyer */
- }
+ result = plugin->version;
- }
+ return result;
}
/******************************************************************************
* *
-* Paramètres : plugin = greffon à valider. *
+* Paramètres : plugin = greffon à consulter. *
* *
-* Description : Fournit le nom brut associé au greffon. *
+* Description : Fournit l'URL des ressources en ligne liées à un greffon. *
* *
-* Retour : Désignation brute du greffon. *
+* Retour : URL de renvoi associée à une extension ou NULL. *
* *
* Remarques : - *
* *
******************************************************************************/
-char *g_plugin_module_get_modname(const GPluginModule *plugin)
+const char *g_plugin_module_get_url(const GPluginModule *plugin)
{
- char *result; /* Désignation brute à renvoyer*/
- GPluginModuleClass *class; /* Classe de l'instance active */
-
- class = G_PLUGIN_MODULE_GET_CLASS(plugin);
-
- result = class->get_modname(plugin);
+ const char *result; /* Valeur finale à renvoyer */
- /**
- * Tente une opération de la dernière chance.
- *
- * Dans le cas d'un module Python, la fonction de classe peut ne pas
- * trouver de support si l'extension Python n'est pas au point.
- */
- if (result == NULL && class->get_modname != _g_plugin_module_get_modname)
- result = _g_plugin_module_get_modname(plugin);
+ result = plugin->url;
return result;
@@ -844,41 +399,24 @@ char *g_plugin_module_get_modname(const GPluginModule *plugin)
/******************************************************************************
* *
-* Paramètres : plugin = greffon à valider. *
+* Paramètres : plugin = greffon à consulter. *
+* count = taille de la liste fournie. [OUT] *
* *
-* Description : Fournit le nom brut associé au greffon. *
+* Description : Fournit la liste des dépendances d'un greffon donné. *
* *
-* Retour : Désignation brute du greffon. *
+* Retour : Liste des noms d'extensions requises pour une extension. *
* *
* Remarques : - *
* *
******************************************************************************/
-static char *_g_plugin_module_get_modname(const GPluginModule *plugin)
+const char * const *g_plugin_module_get_requirements(const GPluginModule *plugin, size_t *count)
{
- char *result; /* Désignation brute à renvoyer*/
- char *path; /* Chemin à traiter */
- char *filename; /* Nom de bibliothèque partagée*/
- size_t length; /* Taille du nom */
-
- path = strdup(g_plugin_module_get_filename(G_PLUGIN_MODULE(plugin)));
-
- filename = basename(path);
-
- if (strncmp(filename, "lib", 3) == 0)
- filename += 3;
-
- length = strlen(filename);
-
- if (length >= 3)
- {
- if (strncmp(&filename[length - 3], ".so", 3) == 0)
- filename[length - 3] = '\0';
- }
+ const char * const *result; /* Valeur finale à renvoyer */
- result = strdup(filename);
+ result = CONST_ARRAY_CAST(plugin->required, char);
- free(path);
+ *count = plugin->required_count;
return result;
@@ -889,7 +427,7 @@ static char *_g_plugin_module_get_modname(const GPluginModule *plugin)
* *
* Paramètres : plugin = greffon à consulter. *
* *
-* Description : Indique le fichier contenant le greffon manipulé. *
+* Description : Pointe le fichier contenant le greffon manipulé. *
* *
* Retour : Chemin d'accès au greffon. *
* *
@@ -897,28 +435,42 @@ static char *_g_plugin_module_get_modname(const GPluginModule *plugin)
* *
******************************************************************************/
-const char *g_plugin_module_get_filename(const GPluginModule *plugin)
+char *g_plugin_module_get_filename(const GPluginModule *plugin)
{
- return plugin->filename;
+ char *result; /* Chemin d'accès à renvoyer */
+ GPluginModuleClass *class; /* Classe de l'instance active */
+
+ class = G_PLUGIN_MODULE_GET_CLASS(plugin);
+
+ result = class->get_filename(plugin);
+
+ return result;
}
/******************************************************************************
* *
-* Paramètres : plugin = greffon à consulter. *
+* Paramètres : plugin = greffon à valider. *
* *
-* Description : Fournit la description du greffon dans son intégralité. *
+* Description : Fournit le nom brut associé au greffon. *
* *
-* Retour : Interfaçage renseigné. *
+* Retour : Désignation brute du greffon. *
* *
* Remarques : - *
* *
******************************************************************************/
-const plugin_interface *g_plugin_module_get_interface(const GPluginModule *plugin)
+char *g_plugin_module_get_modname(const GPluginModule *plugin)
{
- return plugin->interface;
+ char *result; /* Désignation brute à renvoyer*/
+ GPluginModuleClass *class; /* Classe de l'instance active */
+
+ class = G_PLUGIN_MODULE_GET_CLASS(plugin);
+
+ result = class->get_modname(plugin);
+
+ return result;
}
@@ -979,7 +531,6 @@ void g_plugin_module_override_flags(GPluginModule *plugin, PluginStatusFlags fla
bool g_plugin_module_resolve_dependencies(GPluginModule *plugin, GPluginModule **list, size_t count)
{
bool result; /* Bilan à faire remonter */
- const plugin_interface *pg_iface; /* Définition du greffon */
bitfield_t *new; /* Nouvelle définition */
size_t i; /* Boucle de parcours */
GPluginModule *dependency; /* Module nécessaire */
@@ -997,15 +548,13 @@ bool g_plugin_module_resolve_dependencies(GPluginModule *plugin, GPluginModule *
if ((plugin->flags & (PSF_UNKNOW_DEP | PSF_DEP_LOOP)) == 0)
{
- pg_iface = g_plugin_module_get_interface(plugin);
-
/* Collecte des dépendances */
new = dup_bit_field(plugin->dependencies);
- for (i = 0; i < pg_iface->required_count; i++)
+ for (i = 0; i < plugin->required_count; i++)
{
- dependency = get_plugin_by_name(pg_iface->required[i], &index);
+ dependency = get_plugin_by_name(plugin->required[i], &index);
if (dependency == NULL)
plugin->flags |= PSF_UNKNOW_DEP;
@@ -1023,7 +572,7 @@ bool g_plugin_module_resolve_dependencies(GPluginModule *plugin, GPluginModule *
*/
if (test_in_bit_field(plugin->dependencies, index))
- g_object_unref(G_OBJECT(dependency));
+ unref_object(dependency);
}
@@ -1041,13 +590,14 @@ bool g_plugin_module_resolve_dependencies(GPluginModule *plugin, GPluginModule *
/* Vérification sanitaire */
- dependency = get_plugin_by_name(pg_iface->name, &index);
+ dependency = get_plugin_by_name(plugin->name, &index);
assert(dependency != NULL);
+ assert(dependency == plugin);
if (test_in_bit_field(plugin->dependencies, index))
plugin->flags |= PSF_DEP_LOOP;
- g_object_unref(G_OBJECT(dependency));
+ unref_object(dependency);
}
@@ -1075,12 +625,12 @@ bool g_plugin_module_load(GPluginModule *plugin, GPluginModule **list, size_t co
{
bool result; /* Bilan à retourner */
PluginStatusFlags flags; /* Fanions de greffon */
- const plugin_interface *pg_iface; /* Définition du greffon */
size_t i; /* Boucle de parcours */
GPluginModule *dependency; /* Module nécessaire */
+ char *filename; /* Chemin d'accès au greffon */
GPluginModuleClass *class; /* Classe de l'instance active */
- //GGenConfig *config; /* Configuration à charger */
- char *dir; /* Répertoire modifiable */
+ char *tmp; /* Chaîne modifiable */
+ char *dir; /* Pointeur vers répertoire */
/* Si un essai précédent a déjà échoué ou réussi... */
@@ -1092,40 +642,41 @@ bool g_plugin_module_load(GPluginModule *plugin, GPluginModule **list, size_t co
/* Chargement des dépendances */
- pg_iface = g_plugin_module_get_interface(plugin);
-
result = true;
- for (i = 0; i < pg_iface->required_count && result; i++)
+ filename = g_plugin_module_get_filename(plugin);
+
+ for (i = 0; i < plugin->required_count && result; i++)
{
- dependency = get_plugin_by_name(pg_iface->required[i], NULL);
+ dependency = get_plugin_by_name(plugin->required[i], NULL);
assert(dependency != NULL);
result = g_plugin_module_load(dependency, list, count);
- g_object_unref(G_OBJECT(dependency));
+ unref_object(dependency);
}
if (!result)
{
- log_variadic_message(LMT_ERROR,
- _("Some dependencies failed to load for plugin '%s'"), plugin->filename);
+ log_variadic_message(LMT_ERROR, _("Some dependencies failed to load for plugin '%s'"), filename);
+
+ plugin->flags |= PSF_FAILURE;
goto failure;
+
}
/* Chargement du greffon courant */
class = G_PLUGIN_MODULE_GET_CLASS(plugin);
- if (class->init != NULL)
+ if (class->enable != NULL)
{
- result = class->init(plugin);
+ result = class->enable(plugin);
if (!result)
{
- log_variadic_message(LMT_ERROR,
- _("Plugin '%s' failed to load itself..."), plugin->filename);
+ log_variadic_message(LMT_ERROR, _("Plugin '%s' failed to load itself..."), filename);
plugin->flags |= PSF_FAILURE;
goto failure;
@@ -1134,39 +685,23 @@ bool g_plugin_module_load(GPluginModule *plugin, GPluginModule **list, size_t co
}
- g_plugin_module_create_config(plugin);
-
- result = g_plugin_module_manage(plugin, PGA_PLUGIN_LOADED);
-
- if (!result)
- {
- log_variadic_message(LMT_ERROR,
- _("Plugin '%s' failed to complete loading..."), plugin->filename);
-
- plugin->flags |= PSF_FAILURE;
- goto failure;
-
- }
-
- /*
- config = g_plugin_module_get_config(plugin);
- g_generic_config_read(config);
- g_object_unref(G_OBJECT(config));
- */
+ /* Message de bilan */
- dir = strdup(plugin->filename);
- dir = dirname(dir);
+ tmp = strdup(filename);
+ dir = dirname(tmp);
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);
+ strrchr(filename, G_DIR_SEPARATOR) + 1, dir);
- free(dir);
+ free(tmp);
plugin->flags |= PSF_LOADED;
failure:
+ free(filename);
+
return result;
}
@@ -1227,31 +762,6 @@ char *g_plugin_module_build_config_filename(const GPluginModule *plugin, const c
/******************************************************************************
* *
-* Paramètres : plugin = greffon à compléter. *
-* *
-* Description : Met en place la configuration dédiée au greffon. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_plugin_module_create_config(GPluginModule *plugin)
-{
- char *filename; /* Chemin d'accès particulier */
-
- filename = g_plugin_module_build_config_filename(plugin, "config.xml", false);
-
- //plugin->config = g_generic_config_new_from_file(filename);
-
- free(filename);
-
-}
-
-
-/******************************************************************************
-* *
* Paramètres : plugin = greffon à consulter. *
* *
* Description : Fournit la configuration mise en place pour le greffon. *
@@ -1295,11 +805,11 @@ void g_plugin_module_log_simple_message(const GPluginModule *plugin, LogMessageT
size_t len; /* Taille tampon disponible */
char *buffer; /* Tampon du msg reconstitué */
- len = 4 + strlen(plugin->interface->name) + 6 + strlen(msg) + 1;
+ len = 4 + strlen(plugin->name) + 6 + strlen(msg) + 1;
buffer = calloc(len, sizeof(char));
strcpy(buffer, "<i>[");
- strcat(buffer, plugin->interface->name);
+ strcat(buffer, plugin->name);
strcat(buffer, "]</i> ");
strcat(buffer, msg);
@@ -1345,80 +855,12 @@ void g_plugin_module_log_variadic_message(const GPluginModule *plugin, LogMessag
}
-/******************************************************************************
-* *
-* Paramètres : plugin = greffon à manipuler. *
-* action = type d'action attendue. *
-* *
-* Description : Encadre une étape de la vie d'un greffon. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool g_plugin_module_manage(GPluginModule *plugin, PluginAction action)
-{
- bool result; /* Bilan à faire remonter */
- GPluginModuleClass *class; /* Classe de l'instance active */
- const plugin_interface *pg_iface; /* Informations à consulter */
- size_t i; /* Boucle de parcours */
- bool handle_action; /* Action supportée ? */
-
- class = G_PLUGIN_MODULE_GET_CLASS(plugin);
-
- if (class->manage == NULL)
- result = true;
-
- else
- {
- handle_action = false;
-
- pg_iface = g_plugin_module_get_interface(plugin);
-
- for (i = 0; i < pg_iface->actions_count; i++)
- if (pg_iface->actions[i] == PGA_PLUGIN_LOADED)
- {
- handle_action = true;
- break;
- }
-
- if (handle_action)
- result = class->manage(plugin/*, action*/);
- else
- result = true;
-
- }
-
- return result;
-
-}
-
-/******************************************************************************
-* *
-* Paramètres : plugin = greffon à manipuler. *
-* action = type d'action attendue. *
-* unused = variable non utilisé pour l'usage de __VA_ARGS__. *
-* *
-* Description : Accompagne la fin du chargement des modules. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-void g_plugin_module_notify_plugins_loaded(GPluginModule *plugin, PluginAction action, void *unused)
-{
- GPluginModuleClass *class; /* Classe de l'instance active */
- class = G_PLUGIN_MODULE_GET_CLASS(plugin);
- class->plugins_loaded(plugin, action);
-}
+#if 0
/******************************************************************************
@@ -1450,8 +892,6 @@ gpointer g_plugin_module_build_type_instance(GPluginModule *plugin, PluginAction
-#if 0
-
#ifdef INCLUDE_GTK_SUPPORT
diff --git a/src/plugins/plugin.h b/src/plugins/plugin.h
index 5c473b2..a4cc388 100644
--- a/src/plugins/plugin.h
+++ b/src/plugins/plugin.h
@@ -52,6 +52,27 @@
DECLARE_GTYPE(GPluginModule, g_plugin_module, G, PLUGIN_MODULE);
+/* Indique le nom associé à un greffon. */
+const char *g_plugin_module_get_name(const GPluginModule *);
+
+/* Fournit une description fonctionnelle d'un greffon. */
+const char *g_plugin_module_get_desc(const GPluginModule *);
+
+/* Fournit la version d'un greffon et de ses fonctionnalités. */
+const char *g_plugin_module_get_version(const GPluginModule *);
+
+/* Fournit l'URL des ressources en ligne liées à un greffon. */
+const char *g_plugin_module_get_url(const GPluginModule *);
+
+/* Fournit la liste des dépendances d'un greffon donné. */
+const char * const *g_plugin_module_get_requirements(const GPluginModule *, size_t *);
+
+/* Pointe le fichier contenant le greffon manipulé. */
+char *g_plugin_module_get_filename(const GPluginModule *);
+
+/* Fournit le nom brut associé au greffon. */
+char *g_plugin_module_get_modname(const GPluginModule *);
+
/* Fanions indiquant le statut du greffon */
typedef enum _PluginStatusFlags
{
@@ -66,19 +87,6 @@ typedef enum _PluginStatusFlags
#define BROKEN_PLUGIN_STATUS (PSF_UNKNOW_DEP | PSF_DEP_LOOP | PSF_FAILURE)
-
-/* Crée un module pour un greffon donné. */
-GPluginModule *g_plugin_module_new(const gchar *);
-
-/* Fournit le nom brut associé au greffon. */
-char *g_plugin_module_get_modname(const GPluginModule *);
-
-/* Indique le fichier contenant le greffon manipulé. */
-const char *g_plugin_module_get_filename(const GPluginModule *);
-
-/* Fournit la description du greffon dans son intégralité. */
-const plugin_interface *g_plugin_module_get_interface(const GPluginModule *);
-
/* Fournit des indications sur l'état du greffon. */
PluginStatusFlags g_plugin_module_get_flags(const GPluginModule *);
@@ -103,17 +111,12 @@ void g_plugin_module_log_simple_message(const GPluginModule *, LogMessageType, c
/* Présente dans le journal un message complexe. */
void g_plugin_module_log_variadic_message(const GPluginModule *, LogMessageType, const char *, ...);
-/* Encadre une étape de la vie d'un greffon. */
-bool g_plugin_module_manage(GPluginModule *, PluginAction);
-/* Accompagne la fin du chargement des modules natifs. */
-void g_plugin_module_notify_plugins_loaded(GPluginModule *, PluginAction, void *);
+#if 0
/* Crée une instance à partir d'un type dynamique externe. */
gpointer g_plugin_module_build_type_instance(GPluginModule *, PluginAction, GType);
-#if 0
-
#ifdef INCLUDE_GTK_SUPPORT
/* Complète une liste de resources pour thème. */
diff --git a/src/plugins/self.h b/src/plugins/self.h
index 4d5ddb0..78a3fe6 100644
--- a/src/plugins/self.h
+++ b/src/plugins/self.h
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * self.h - définitions pour inclusion dans les différents greffons
+ * self.h - définitions de fonctionnalités facilitant la mise en place d'extensions natives
*
- * Copyright (C) 2020 Cyrille Bagard
+ * Copyright (C) 2020-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -26,72 +26,55 @@
#define _PLUGINS_SELF_H
-#ifndef _PLUGINS_PLUGIN_H
-# include "plugin.h"
-#endif
+#include <assert.h>
+#include <malloc.h>
+
+
+#include "plugin.h"
#include "../common/compiler.h"
-/* Facilitations de déclarations */
+/* Symboles principaux */
+
+#define PLUGIN_CORE_SELF \
+static GPluginModule *_this_plugin = NULL; \
+static void chrysalide_plugin_set_self(GPluginModule *); \
+static void chrysalide_plugin_set_self(GPluginModule *plugin) \
+{ \
+ assert(_this_plugin == NULL); \
+ _this_plugin = plugin; \
+}; \
+__private GPluginModule *_chrysalide_plugin_get_self(void); \
+__private GPluginModule *_chrysalide_plugin_get_self(void) \
+{ \
+ return _this_plugin; \
+};
+
+#define NATIVE_PLUGIN_ENTRYPOINT(fc) \
+PLUGIN_CORE_SELF; \
+G_MODULE_EXPORT GPluginModule *get_chrysalide_plugin_instance(GModule *); \
+G_MODULE_EXPORT GPluginModule *get_chrysalide_plugin_instance(GModule *module) \
+{ \
+ GPluginModule *result; /* Instance à retourner */ \
+ result = fc(module); \
+ chrysalide_plugin_set_self(result); \
+ return result; \
+}
+
+
+/* Spécifications */
#define CHRYSALIDE_WEBSITE(p) "https://www.chrysalide.re/" p
-#define EMPTY_PG_LIST(name) \
- name = NULL, \
- name ## _count = 0 \
-
-#define BUILD_PG_LIST(name, lst) \
- name = lst, \
- name ## _count = sizeof(lst) / sizeof(lst[0]) \
-
-#define AL(...) BUILD_PG_LIST(.actions, ((plugin_action_t []){ __VA_ARGS__ }))
-
-#define RL(...) BUILD_PG_LIST(.required, ((char *[]){ __VA_ARGS__ }))
-
-#define NO_REQ EMPTY_PG_LIST(.required)
-
-
-/* Composants d'interface */
-
-#define PLUGIN_CORE_SELF \
-static GPluginModule *_this_plugin = NULL; \
-G_MODULE_EXPORT void chrysalide_plugin_set_self(GPluginModule *p); \
-G_MODULE_EXPORT void chrysalide_plugin_set_self(GPluginModule *p) { _this_plugin = p; }; \
-__private GPluginModule *_chrysalide_plugin_get_self(void); \
-__private GPluginModule *_chrysalide_plugin_get_self(void) { return _this_plugin; };
-
-#define PLUGIN_CORE_PROPS(n, d, v, u, c) \
- \
- .magic = CHRYSALIDE_PLUGIN_MAGIC, \
- .abi_version = CURRENT_ABI_VERSION, \
- \
- .gtp_name = "G" n "Plugin", \
- .name = n, \
- .desc = d, \
- .version = v, \
- .url = u, \
- \
- .container = c
-
-#define DEFINE_CHRYSALIDE_PLUGIN(n, d, v, u, r, a) \
-PLUGIN_CORE_SELF \
-G_MODULE_EXPORT const plugin_interface _chrysalide_plugin = { \
- PLUGIN_CORE_PROPS(n, d, v, u, false), \
- r, \
- a, \
-}
+#define NO_REQ NULL, 0
-#define DEFINE_CHRYSALIDE_CONTAINER_PLUGIN(n, d, v, u, r, a) \
-PLUGIN_CORE_SELF \
-G_MODULE_EXPORT const plugin_interface _chrysalide_plugin = { \
- PLUGIN_CORE_PROPS(n, d, v, u, true), \
- r, \
- a, \
-}
+#define BUILD_PG_LIST(lst) lst, sizeof(lst) / sizeof(lst[0])
+
+#define REQ_LIST(...) BUILD_PG_LIST((const char *[]){ __VA_ARGS__ })
-/* Manipulations accélérées */
+/* Journalisation */
__private GPluginModule *_chrysalide_plugin_get_self(void);
diff --git a/src/plugins/tweakable-int.h b/src/plugins/tweakable-int.h
new file mode 100644
index 0000000..776626f
--- /dev/null
+++ b/src/plugins/tweakable-int.h
@@ -0,0 +1,50 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * tweakable-int.h - définitions internes propres aux participations aux mécanismes de configuration
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_TWEAKABLE_INT_H
+#define _PLUGINS_TWEAKABLE_INT_H
+
+
+#include "tweakable.h"
+
+
+
+/* ------------------- INTEGRATION DANS L'EDITION DES PREFERENCES ------------------- */
+
+
+/* Fournit une liste de sections de configuration. */
+typedef tweak_info_t * (* get_tweakable_plugin_info) (const GTweakablePlugin *, size_t *);
+
+
+/* Greffon avec des compléments pour l'interface de configuration (interface) */
+struct _GTweakablePluginInterface
+{
+ GTypeInterface base_iface; /* A laisser en premier */
+
+ get_tweakable_plugin_info get_info; /* Récupération de section(s) */
+
+};
+
+
+
+#endif /* _PLUGINS_TWEAKABLE_INT_H */
diff --git a/src/plugins/tweakable.c b/src/plugins/tweakable.c
new file mode 100644
index 0000000..517c4a3
--- /dev/null
+++ b/src/plugins/tweakable.c
@@ -0,0 +1,98 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * tweakable.c - participation aux mécanismes de configuration
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "tweakable.h"
+
+
+#include "tweakable-int.h"
+
+
+
+/* ------------------- INTEGRATION DANS L'EDITION DES PREFERENCES ------------------- */
+
+
+/* Procède à l'initialisation de l'interface d'intervention. */
+static void g_tweakable_plugin_default_init(GTweakablePluginInterface *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTEGRATION DANS L'EDITION DES PREFERENCES */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Détermine le type d'une interface pour l'intervention dans la gestion des greffons. */
+G_DEFINE_INTERFACE(GTweakablePlugin, g_tweakable_plugin, G_TYPE_OBJECT)
+
+
+/******************************************************************************
+* *
+* Paramètres : iface = interface GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'interface d'intervention. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_tweakable_plugin_default_init(GTweakablePluginInterface *iface)
+{
+ iface->get_info = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : plugin = interface à manipuler. *
+* count = taille de la liste renvoyée. [OUT] *
+* *
+* Description : Fournit une liste de sections de configuration. *
+* *
+* Retour : Définition(s) de section de configuration ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+tweak_info_t *g_tweakable_plugin_get_tweak_info(const GTweakablePlugin *plugin, size_t *count)
+{
+ tweak_info_t *result; /* Liste à renvoyer */
+ GTweakablePluginInterface *iface; /* Interface utilisée */
+
+ iface = G_TWEAKABLE_PLUGIN_GET_IFACE(plugin);
+
+ if (iface->get_info != NULL)
+ result = iface->get_info(plugin, count);
+
+ else
+ {
+ *count = 0;
+ result = NULL;
+ }
+
+ return result;
+
+}
diff --git a/src/plugins/tweakable.h b/src/plugins/tweakable.h
new file mode 100644
index 0000000..aea70b4
--- /dev/null
+++ b/src/plugins/tweakable.h
@@ -0,0 +1,62 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * tweakable.h - prototypes pour la participation aux mécanismes de configuration
+ *
+ * Copyright (C) 2025 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _PLUGINS_TWEAKABLE_H
+#define _PLUGINS_TWEAKABLE_H
+
+
+#include "../glibext/helpers.h"
+#include "../gtkext/tweak.h"
+
+
+
+/* ------------------- INTEGRATION DANS L'EDITION DES PREFERENCES ------------------- */
+
+
+#define G_TYPE_TWEAKABLE_PLUGIN (g_tweakable_plugin_get_type())
+
+DECLARE_INTERFACE(GTweakablePlugin, g_tweakable_plugin, G, TWEAKABLE_PLUGIN);
+
+
+/* Fournit une liste de sections de configuration. */
+tweak_info_t *g_tweakable_plugin_get_tweak_info(const GTweakablePlugin *, size_t *);
+
+
+
+/* -------------------- SOLLICITATION DES FONCTIONNALITES CREEES -------------------- */
+
+
+#define get_tweakable_plugins_info(c) \
+ ({ \
+ tweak_info_t *__all_info; \
+ __all_info = accumulate_from_all_plugins(G_TYPE_TWEAKABLE_PLUGIN, \
+ G_TWEAKABLE_PLUGIN, \
+ g_tweakable_plugin_get_tweak_info, \
+ tweak_info_t, \
+ c); \
+ __all_info; \
+ })
+
+
+
+#endif /* _PLUGINS_TWEAKABLE_H */