summaryrefslogtreecommitdiff
path: root/src/glibext
diff options
context:
space:
mode:
Diffstat (limited to 'src/glibext')
-rw-r--r--src/glibext/Makefile.am16
-rw-r--r--src/glibext/comparable-int.h47
-rw-r--r--src/glibext/comparable.c110
-rw-r--r--src/glibext/comparable.h46
-rw-r--r--src/glibext/comparison-int.h58
-rw-r--r--src/glibext/comparison.c199
-rw-r--r--src/glibext/comparison.h80
-rw-r--r--src/glibext/hashable-int.h47
-rw-r--r--src/glibext/hashable.c82
-rw-r--r--src/glibext/hashable.h42
-rw-r--r--src/glibext/objhole-int.h166
-rw-r--r--src/glibext/objhole.c191
-rw-r--r--src/glibext/objhole.h114
-rw-r--r--src/glibext/secstorage-int.h60
-rw-r--r--src/glibext/secstorage.c950
-rw-r--r--src/glibext/secstorage.h74
-rw-r--r--src/glibext/singleton-int.h47
-rw-r--r--src/glibext/singleton.c341
-rw-r--r--src/glibext/singleton.h53
-rw-r--r--src/glibext/strbuilder-int.h47
-rw-r--r--src/glibext/strbuilder.c89
-rw-r--r--src/glibext/strbuilder.h46
22 files changed, 2149 insertions, 756 deletions
diff --git a/src/glibext/Makefile.am b/src/glibext/Makefile.am
index adbec4c..81d13d2 100644
--- a/src/glibext/Makefile.am
+++ b/src/glibext/Makefile.am
@@ -4,8 +4,6 @@ BUILT_SOURCES = chrysamarshal.h chrysamarshal.c resources.h resources.c
noinst_LTLIBRARIES = libglibext.la libglibextui.la
# libglibext_la_SOURCES = \
-# comparison-int.h \
-# comparison.h comparison.c \
# configuration-int.h \
# configuration.h configuration.c \
# gbinarycursor.h gbinarycursor.c \
@@ -13,7 +11,7 @@ noinst_LTLIBRARIES = libglibext.la libglibextui.la
# glinecursor.h glinecursor.c \
# gnhash.h gnhash.c \
# notifier.h \
-# objhole.h \
+# \
# proto.h \
# seq.h seq.c \
# _signal.h signal.c \
@@ -40,9 +38,21 @@ noinst_LTLIBRARIES = libglibext.la libglibextui.la
libglibext_la_SOURCES = \
chrysamarshal.h chrysamarshal.c \
+ comparable-int.h \
+ comparable.h comparable.c \
+ hashable-int.h \
+ hashable.h hashable.c \
helpers.h \
+ objhole-int.h \
+ objhole.h objhole.c \
portion-int.h \
portion.h portion.c \
+ secstorage-int.h \
+ secstorage.h secstorage.c \
+ singleton-int.h \
+ singleton.h singleton.c \
+ strbuilder-int.h \
+ strbuilder.h strbuilder.c \
work-int.h \
work.h work.c \
workgroup-int.h \
diff --git a/src/glibext/comparable-int.h b/src/glibext/comparable-int.h
new file mode 100644
index 0000000..18972c2
--- /dev/null
+++ b/src/glibext/comparable-int.h
@@ -0,0 +1,47 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * comparable-int.h - définitions internes propres aux opérations de comparaison d'objets
+ *
+ * Copyright (C) 2022-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 _GLIBEXT_COMPARABLE_INT_H
+#define _GLIBEXT_COMPARABLE_INT_H
+
+
+#include "comparable.h"
+
+
+
+/* Réalise une comparaison étendue entre objets. */
+typedef int (* compare_object_fc) (const GComparableObject *, const GComparableObject *);
+
+
+/* Instance d'objet comparable (interface) */
+struct _GComparableObjectInterface
+{
+ GTypeInterface base_iface; /* A laisser en premier */
+
+ compare_object_fc compare; /* Comparaison étendue */
+
+};
+
+
+
+#endif /* _GLIBEXT_COMPARABLE_INT_H */
diff --git a/src/glibext/comparable.c b/src/glibext/comparable.c
new file mode 100644
index 0000000..95e7de7
--- /dev/null
+++ b/src/glibext/comparable.c
@@ -0,0 +1,110 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * comparable.c - opérations de comparaison d'objets
+ *
+ * Copyright (C) 2022-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 "comparable.h"
+
+
+#include "comparable-int.h"
+
+
+
+/* Procède à l'initialisation de l'interface de comparaison. */
+static void g_comparable_object_default_init(GComparableObjectInterface *);
+
+
+
+/* Détermine le type d'une interface pour un objet comparable. */
+G_DEFINE_INTERFACE(GComparableObject, g_comparable_object, G_TYPE_OBJECT)
+
+
+/******************************************************************************
+* *
+* Paramètres : iface = interface GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'interface de comparaison. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_comparable_object_default_init(GComparableObjectInterface *iface)
+{
+ iface->compare = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = premier objet à consulter pour une comparaison. *
+* other = second objet à consulter pour une comparaison. *
+* *
+* Description : Réalise une comparaison étendue entre objets. *
+* *
+* Retour : Bilan de la comparaison. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int g_comparable_object_compare(const GComparableObject *object, const GComparableObject *other)
+{
+ int result; /* Bilan à retourner */
+ GComparableObjectInterface *iface; /* Interface utilisée */
+
+ iface = G_COMPARABLE_OBJECT_GET_IFACE(object);
+
+ result = iface->compare(object, other);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = premier objet à consulter pour une comparaison. *
+* other = second objet à consulter pour une comparaison. *
+* *
+* Description : Détermine si deux objets sont fonctionnellement identiques. *
+* *
+* Retour : Bilan de la comparaison. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+gboolean g_comparable_object_is_equal(const GComparableObject *object, const GComparableObject *other)
+{
+ gboolean result; /* Bilan à renvoyer */
+ int ret; /* Bilan d'une comparaison */
+
+ ret = g_comparable_object_compare(object, other);
+
+ result = (ret == 0);
+
+ return result;
+
+}
diff --git a/src/glibext/comparable.h b/src/glibext/comparable.h
new file mode 100644
index 0000000..7a652ff
--- /dev/null
+++ b/src/glibext/comparable.h
@@ -0,0 +1,46 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * comparable.h - prototypes pour les opérations de comparaison d'objets
+ *
+ * Copyright (C) 2022-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 _GLIBEXT_COMPARABLE_H
+#define _GLIBEXT_COMPARABLE_H
+
+
+#include "helpers.h"
+
+
+
+#define G_TYPE_COMPARABLE_OBJECT (g_comparable_object_get_type())
+
+DECLARE_INTERFACE(GComparableObject, g_comparable_object, G, COMPARABLE_OBJECT);
+
+
+
+/* Réalise une comparaison étendue entre objets. */
+int g_comparable_object_compare(const GComparableObject *, const GComparableObject *);
+
+/* Détermine si deux objets sont fonctionnellement identiques. */
+gboolean g_comparable_object_is_equal(const GComparableObject *, const GComparableObject *);
+
+
+
+#endif /* _GLIBEXT_COMPARABLE_H */
diff --git a/src/glibext/comparison-int.h b/src/glibext/comparison-int.h
deleted file mode 100644
index 446f25d..0000000
--- a/src/glibext/comparison-int.h
+++ /dev/null
@@ -1,58 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * comparison-int.h - définitions internes propres aux opérations de comparaison d'objets
- *
- * Copyright (C) 2022 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 _GLIBEXT_COMPARISON_INT_H
-#define _GLIBEXT_COMPARISON_INT_H
-
-
-#include "comparison.h"
-
-
-
-/* Réalise une comparaison entre objets selon un critère précis. */
-typedef bool (* compare_rich_fc) (const GComparableItem *, const GComparableItem *, RichCmpOperation, bool *);
-
-
-/* Instance d'élément comparable (interface) */
-struct _GComparableItemIface
-{
- GTypeInterface base_iface; /* A laisser en premier */
-
- compare_rich_fc cmp_rich; /* Comparaison de façon précise*/
-
-};
-
-
-/* Redéfinition */
-typedef GComparableItemIface GComparableItemInterface;
-
-
-/* Réalise une comparaison riche entre valeurs entière. */
-bool compare_rich_integer_values_signed(long long, long long, RichCmpOperation);
-
-/* Réalise une comparaison riche entre valeurs entière. */
-bool compare_rich_integer_values_unsigned(unsigned long long, unsigned long long, RichCmpOperation);
-
-
-
-#endif /* _GLIBEXT_COMPARISON_INT_H */
diff --git a/src/glibext/comparison.c b/src/glibext/comparison.c
deleted file mode 100644
index 8ce6941..0000000
--- a/src/glibext/comparison.c
+++ /dev/null
@@ -1,199 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * comparison.c - opérations de comparaison d'objets
- *
- * Copyright (C) 2022 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 "comparison.h"
-
-
-#include <assert.h>
-
-
-#include "comparison-int.h"
-
-
-
-/* Procède à l'initialisation de l'interface de comparaison. */
-static void g_comparable_item_default_init(GComparableItemInterface *);
-
-
-
-/* Détermine le type d'une interface pour un objet comparable. */
-G_DEFINE_INTERFACE(GComparableItem, g_comparable_item, G_TYPE_OBJECT)
-
-
-/******************************************************************************
-* *
-* Paramètres : iface = interface GLib à initialiser. *
-* *
-* Description : Procède à l'initialisation de l'interface de comparaison. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void g_comparable_item_default_init(GComparableItemInterface *iface)
-{
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : item = premier objet à consulter pour une comparaison. *
-* other = second objet à consulter pour une comparaison. *
-* op = opération de comparaison à réaliser. *
-* status = bilan des opérations de comparaison. [OUT] *
-* *
-* Description : Réalise une comparaison entre objets selon un critère précis.*
-* *
-* Retour : true si la comparaison a pu être effectuée, false sinon. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool g_comparable_item_compare_rich(const GComparableItem *item, const GComparableItem *other, RichCmpOperation op, bool *status)
-{
- bool result; /* Etat à retourner */
- GComparableItemIface *iface; /* Interface utilisée */
-
- iface = G_COMPARABLE_ITEM_GET_IFACE(item);
-
- result = iface->cmp_rich(item, other, op, status);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : a = premier élément à consulter pour une comparaison. *
-* b = second objet à consulter pour une comparaison. *
-* op = opération de comparaison à réaliser. *
-* *
-* Description : Réalise une comparaison riche entre valeurs entière. *
-* *
-* Retour : Bilan des opérations de comparaison. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool compare_rich_integer_values_signed(long long a, long long b, RichCmpOperation op)
-{
- bool result; /* Bilan à retourner */
-
- switch (op)
- {
- case RCO_LT:
- result = (a < b);
- break;
-
- case RCO_LE:
- result = (a <= b);
- break;
-
- case RCO_EQ:
- result = (a == b);
- break;
-
- case RCO_NE:
- result = (a != b);
- break;
-
- case RCO_GT:
- result = (a > b);
- break;
-
- case RCO_GE:
- result = (a >= b);
- break;
-
- default:
- assert(false);
- result = false;
- break;
-
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : a = premier élément à consulter pour une comparaison. *
-* b = second objet à consulter pour une comparaison. *
-* op = opération de comparaison à réaliser. *
-* *
-* Description : Réalise une comparaison riche entre valeurs entière. *
-* *
-* Retour : Bilan des opérations de comparaison. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool compare_rich_integer_values_unsigned(unsigned long long a, unsigned long long b, RichCmpOperation op)
-{
- bool result; /* Bilan à retourner */
-
- switch (op)
- {
- case RCO_LT:
- result = (a < b);
- break;
-
- case RCO_LE:
- result = (a <= b);
- break;
-
- case RCO_EQ:
- result = (a == b);
- break;
-
- case RCO_NE:
- result = (a != b);
- break;
-
- case RCO_GT:
- result = (a > b);
- break;
-
- case RCO_GE:
- result = (a >= b);
- break;
-
- default:
- assert(false);
- result = false;
- break;
-
- }
-
- return result;
-
-}
diff --git a/src/glibext/comparison.h b/src/glibext/comparison.h
deleted file mode 100644
index 8d43210..0000000
--- a/src/glibext/comparison.h
+++ /dev/null
@@ -1,80 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * comparison.h - prototypes pour les opérations de comparaison d'objets
- *
- * Copyright (C) 2022 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 _GLIBEXT_COMPARISON_H
-#define _GLIBEXT_COMPARISON_H
-
-
-#include <glib-object.h>
-#include <stdbool.h>
-
-
-
-#define G_TYPE_COMPARABLE_ITEM (g_comparable_item_get_type())
-#define G_COMPARABLE_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_COMPARABLE_ITEM, GComparableItem))
-#define G_COMPARABLE_ITEM_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST((vtable), G_TYPE_COMPARABLE_ITEM, GComparableItemIface))
-#define G_IS_COMPARABLE_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_COMPARABLE_ITEM))
-#define G_IS_COMPARABLE_ITEM_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE((vtable), G_TYPE_COMPARABLE_ITEM))
-#define G_COMPARABLE_ITEM_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), G_TYPE_COMPARABLE_ITEM, GComparableItemIface))
-
-
-/* Instance d'élément comparable (coquille vide) */
-typedef struct _GComparableItem GComparableItem;
-
-/* Instance d'élément comparable (interface) */
-typedef struct _GComparableItemIface GComparableItemIface;
-
-
-/* Modes de comparaison */
-typedef enum _RichCmpOperation
-{
- RCO_LT, /* Equivalent de '<' */
- RCO_LE, /* Equivalent de '<=' */
- RCO_EQ, /* Equivalent de '==' */
- RCO_NE, /* Equivalent de '!=' */
- RCO_GT, /* Equivalent de '>' */
- RCO_GE, /* Equivalent de '>°' */
-
-} RichCmpOperation;
-
-/* Détermination d'un besoin de comparaison supplémentaire */
-#define STATUS_NOT_EQUAL(_s, _o) \
- ({ \
- bool __result; \
- if (_o == RCO_LE || _o == RCO_EQ || _o == RCO_GE) \
- __result = !_s; \
- else \
- __result = _s; \
- __result; \
- })
-
-
-/* Détermine le type d'une interface pour un objet comparable. */
-GType g_comparable_item_get_type(void) G_GNUC_CONST;
-
-/* Réalise une comparaison entre objets selon un critère précis. */
-bool g_comparable_item_compare_rich(const GComparableItem *, const GComparableItem *, RichCmpOperation, bool *);
-
-
-
-#endif /* _GLIBEXT_COMPARISON_H */
diff --git a/src/glibext/hashable-int.h b/src/glibext/hashable-int.h
new file mode 100644
index 0000000..f8a85e1
--- /dev/null
+++ b/src/glibext/hashable-int.h
@@ -0,0 +1,47 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * hashable-int.h - définitions internes propres aux calculs de l'empreinte d'un objet
+ *
+ * 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 _GLIBEXT_HASHABLE_INT_H
+#define _GLIBEXT_HASHABLE_INT_H
+
+
+#include "hashable.h"
+
+
+
+/* Calcule l'empreinte sur 32 bits d'un objet. */
+typedef guint (* hash_object_fc) (const GHashableObject *);
+
+
+/* Instance d'objet visant à être unique (interface) */
+struct _GHashableObjectInterface
+{
+ GTypeInterface base_iface; /* A laisser en premier */
+
+ hash_object_fc hash; /* Réduction en valeur */
+
+};
+
+
+
+#endif /* _GLIBEXT_HASHABLE_INT_H */
diff --git a/src/glibext/hashable.c b/src/glibext/hashable.c
new file mode 100644
index 0000000..f988a90
--- /dev/null
+++ b/src/glibext/hashable.c
@@ -0,0 +1,82 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * hashable.c - calculs de l'empreinte d'un objet
+ *
+ * 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 "hashable.h"
+
+
+#include "hashable-int.h"
+
+
+
+/* Procède à l'initialisation de l'interface de détermination. */
+static void g_hashable_object_default_init(GHashableObjectInterface *);
+
+
+
+/* Détermine le type d'une interface pour la réduction d'un objet à une valeur. */
+G_DEFINE_INTERFACE(GHashableObject, g_hashable_object, G_TYPE_OBJECT)
+
+
+/******************************************************************************
+* *
+* Paramètres : iface = interface GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'interface de détermination. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_hashable_object_default_init(GHashableObjectInterface *iface)
+{
+ iface->hash = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = objet dont l'instance est à consulter. *
+* *
+* Description : Calcule l'empreinte sur 32 bits d'un objet. *
+* *
+* Retour : Valeur de représentation, unique pour l'objet ou non. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+guint g_hashable_object_hash(const GHashableObject *object)
+{
+ guint result; /* Valeur à retourner */
+ GHashableObjectInterface *iface; /* Interface utilisée */
+
+ iface = G_HASHABLE_OBJECT_GET_IFACE(object);
+
+ result = iface->hash(object);
+
+ return result;
+
+}
diff --git a/src/glibext/hashable.h b/src/glibext/hashable.h
new file mode 100644
index 0000000..165c744
--- /dev/null
+++ b/src/glibext/hashable.h
@@ -0,0 +1,42 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * hashable.h - prototypes pour les calculs de l'empreinte d'un objet
+ *
+ * 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 _GLIBEXT_HASHABLE_H
+#define _GLIBEXT_HASHABLE_H
+
+
+#include "helpers.h"
+
+
+
+#define G_TYPE_HASHABLE_OBJECT (g_hashable_object_get_type())
+
+DECLARE_INTERFACE(GHashableObject, g_hashable_object, G, HASHABLE_OBJECT);
+
+
+/* Calcule l'empreinte sur 32 bits d'un objet. */
+guint g_hashable_object_hash(const GHashableObject *);
+
+
+
+#endif /* _GLIBEXT_HASHABLE_H */
diff --git a/src/glibext/objhole-int.h b/src/glibext/objhole-int.h
new file mode 100644
index 0000000..b4abf6f
--- /dev/null
+++ b/src/glibext/objhole-int.h
@@ -0,0 +1,166 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * objhole.h - définitions internes pour ll'utilisation d'un espace inutilisé dans la structure GObject
+ *
+ * Copyright (C) 2024 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 _GLIBEXT_OBJHOLE_INT_H
+#define _GLIBEXT_OBJHOLE_INT_H
+
+
+#include "objhole.h"
+
+
+#include "../common/cpp.h"
+
+
+
+/**
+ * Une structure GObject a la définition suivante :
+ *
+ * struct _GObject
+ * {
+ * GTypeInstance g_type_instance;
+ * volatile guint ref_count;
+ * GData *qdata;
+ * };
+ *
+ * Chaque objet GLib alloué comporte ainsi 4 octets inutilisés :
+ *
+ * (gdb) pt /o GObject
+ * type = struct _GObject {
+ * / 0 | 8 / GTypeInstance g_type_instance;
+ * / 8 | 4 / guint ref_count;
+ * / XXX 4-byte hole /
+ * / 16 | 8 / GData *qdata;
+ *
+ * / total size (bytes): 24 /
+ * }
+ *
+ * La situation n'a pas échappé aux développeurs GLib, avec la définition réelle
+ * de la structure (cf. https://github.com/GNOME/glib/blob/main/gobject/gobject.c) :
+ *
+ * #if SIZEOF_INT == 4 && GLIB_SIZEOF_VOID_P == 8
+ * #define HAVE_OPTIONAL_FLAGS
+ * #endif
+ *
+ * typedef struct
+ * {
+ * GTypeInstance g_type_instance;
+ * guint ref_count;
+ * #ifdef HAVE_OPTIONAL_FLAGS
+ * guint optional_flags;
+ * #endif
+ * GData *qdata;
+ * } GObjectReal;
+ *
+ * G_STATIC_ASSERT(sizeof(GObject) == sizeof(GObjectReal));
+ * G_STATIC_ASSERT(G_STRUCT_OFFSET(GObject, ref_count) == G_STRUCT_OFFSET(GObjectReal, ref_count));
+ * G_STATIC_ASSERT(G_STRUCT_OFFSET(GObject, qdata) == G_STRUCT_OFFSET(GObjectReal, qdata));
+ *
+ * L'espace entre les deux derniers champs ne peut donc être pleinement exploité deux fois.
+ */
+
+/**
+ * Les bits effectivements utilisés par GLib s'identifie ainsi (02/12/24) :
+ *
+ * $ wget -qO /dev/stdout https://raw.githubusercontent.com/GNOME/glib/refs/heads/main/gobject/gobject.c \
+ * | grep ' * #define OPTIONAL_FLAG_'
+ * #define OPTIONAL_FLAG_IN_CONSTRUCTION (1 << 0)
+ * #define OPTIONAL_FLAG_HAS_SIGNAL_HANDLER (1 << 1)
+ * #define OPTIONAL_FLAG_HAS_NOTIFY_HANDLER (1 << 2)
+ * #define OPTIONAL_FLAG_LOCK (1 << 3)
+ * #define OPTIONAL_FLAG_EVER_HAD_WEAK_REF (1 << 4)
+ *
+ * Les n premiers bits doivent ainsi être préservés, même s'il est possible de
+ * partager le bit de verrouilage OPTIONAL_FLAG_LOCK.
+ */
+
+
+#ifndef HAVE_OPTIONAL_FLAGS_IN_GOBJECT
+
+# if SIZEOF_INT == 4 && GLIB_SIZEOF_VOID_P >= 8
+# define HAVE_OPTIONAL_FLAGS_IN_GOBJECT 1
+# else
+# define HAVE_OPTIONAL_FLAGS_IN_GOBJECT 0
+# endif
+
+#endif
+
+
+/* Nouvelle version dense des objets (instance) */
+typedef struct _GThickObject
+{
+ /**
+ * (cf. structure GObjectReal officielle).
+ */
+
+ GTypeInstance g_type_instance; /* Type d'objet */
+ guint ref_count; /* Décompte des références */
+
+#ifdef HAVE_OPTIONAL_FLAGS_IN_GOBJECT
+ guint extra; /* Zone partagée avec GLib */
+#endif
+
+ GData *qdata; /* Données complémentaires ? */
+
+#ifndef HAVE_OPTIONAL_FLAGS_IN_GOBJECT
+ guint extra; /* Zone supplémentaire propre */
+#endif
+
+} GThickObject;
+
+/* Nouvelle version dense des objets (classe) */
+struct _GThickObjectClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+};
+
+
+/**
+ * Définition du périmètre et des moyens d'accès.
+ */
+
+/* GLib 2.83.0 - cfa36f5e9 */
+#define GOBJECT_RESERVED_EXTRA_BITS 5
+
+#define GET_GOBJECT_EXTRA(obj, tp) \
+ ({ \
+ BUILD_BUG_ON(sizeof(tp) > sizeof(guint)); \
+ tp *___result; \
+ guint __val; \
+ __val = g_thick_object_get_extra(obj); \
+ ___result = (tp *)(guint []){ __val }; \
+ ___result; \
+ })
+
+#define SET_GOBJECT_EXTRA(obj, tp, data) \
+ ({ \
+ BUILD_BUG_ON(sizeof(tp) > sizeof(guint)); \
+ BUILD_BUG_ON(sizeof(data) > sizeof(guint *)); \
+ guint __val; \
+ __val = *(guint *)data; \
+ g_thick_object_set_extra(obj, __val); \
+ })
+
+
+
+#endif /* _GLIBEXT_OBJHOLE_INT_H */
diff --git a/src/glibext/objhole.c b/src/glibext/objhole.c
new file mode 100644
index 0000000..20bb2a8
--- /dev/null
+++ b/src/glibext/objhole.c
@@ -0,0 +1,191 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * objhole.c - utilisation d'un espace inutilisé dans la structure GObject
+ *
+ * Copyright (C) 2024 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 "objhole.h"
+
+
+#include <assert.h>
+
+
+#include "objhole-int.h"
+
+
+
+/* Initialise la classe des objets à la structure dense. */
+static void g_thick_object_class_init(GThickObjectClass *);
+
+/* Initialise une instance d'objet à la structure dense. */
+static void g_thick_object_init(GThickObject *);
+
+/* Supprime toutes les références externes. */
+static void g_thick_object_dispose(GThickObject *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_thick_object_finalize(GThickObject *);
+
+
+
+G_DEFINE_TYPE(GThickObject, g_thick_object, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des objets à la structure dense. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_thick_object_class_init(GThickObjectClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_thick_object_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_thick_object_finalize;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : obj = instance à initialiser. *
+* *
+* Description : Initialise une instance d'objet à la structure dense. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_thick_object_init(GThickObject *obj)
+{
+ obj->extra = 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : obj = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_thick_object_dispose(GThickObject *obj)
+{
+ G_OBJECT_CLASS(g_thick_object_parent_class)->dispose(G_OBJECT(obj));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : obj = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_thick_object_finalize(GThickObject *obj)
+{
+ G_OBJECT_CLASS(g_thick_object_parent_class)->finalize(G_OBJECT(obj));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : obj = instance d'objet GLib à consulter. *
+* *
+* Description : Fournit la valeur courante de la zone de stockage d'un objet.*
+* *
+* Retour : Valeur de 32 lues et expurgées des bits GLib. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+guint g_thick_object_get_extra(const GThickObject *obj)
+{
+ guint result; /* Valeur à retourner */
+ guint mask; /* Masque à appliquer */
+
+ result = g_atomic_int_get(&obj->extra);
+
+ assert(GOBJECT_RESERVED_EXTRA_BITS < 30);
+
+ mask = (1 << GOBJECT_RESERVED_EXTRA_BITS) - 1;
+
+ result &= ~mask;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : obj = instance d'objet GLib à consulter. *
+* val = valeur de 32 à conserver. *
+* *
+* Description : Définit la valeur courante de la zone de stockage d'un objet.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_thick_object_set_extra(GThickObject *obj, guint val)
+{
+ guint mask; /* Masque à appliquer */
+
+ assert(GOBJECT_RESERVED_EXTRA_BITS < 30);
+
+ mask = (1 << GOBJECT_RESERVED_EXTRA_BITS) - 1;
+
+ assert((val & mask) == 0);
+
+ val &= ~mask;
+
+ g_atomic_int_and(&obj->extra, val | mask);
+
+ g_atomic_int_or(&obj->extra, val);
+
+}
diff --git a/src/glibext/objhole.h b/src/glibext/objhole.h
index 38f4bd5..c1e8cf1 100644
--- a/src/glibext/objhole.h
+++ b/src/glibext/objhole.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* objhole.h - prototypes pour l'utilisation d'un espace inutilisé dans la structure GObject
*
- * Copyright (C) 2020 Cyrille Bagard
+ * Copyright (C) 2020-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -25,118 +25,20 @@
#define _GLIBEXT_OBJHOLE_H
-#include <glib.h>
-#include <glib-object.h>
+#include "../glibext/helpers.h"
-#include "../common/cpp.h"
+#define G_TYPE_THICK_OBJECT (g_thick_object_get_type())
+DECLARE_GTYPE(GThickObject, g_thick_object, G, THICK_OBJECT);
-/**
- * Une structure GObject a la définition suivante :
- *
- * struct _GObject
- * {
- * GTypeInstance g_type_instance;
- * volatile guint ref_count;
- * GData *qdata;
- * };
- *
- * En revanche, le fichier "glib/gobject/gobject.c" précise la définition
- * réelle de la structure selon l'environnement :
- *
- * #if SIZEOF_INT == 4 && GLIB_SIZEOF_VOID_P == 8
- * #define HAVE_OPTIONAL_FLAGS
- * #endif
- *
- * typedef struct
- * {
- * GTypeInstance g_type_instance;
- * guint ref_count;
- * #ifdef HAVE_OPTIONAL_FLAGS
- * guint optional_flags;
- * #endif
- * GData *qdata;
- * } GObjectReal;
- *
- * G_STATIC_ASSERT(sizeof(GObject) == sizeof(GObjectReal));
- * G_STATIC_ASSERT(G_STRUCT_OFFSET(GObject, ref_count) == G_STRUCT_OFFSET(GObjectReal, ref_count));
- * G_STATIC_ASSERT(G_STRUCT_OFFSET(GObject, qdata) == G_STRUCT_OFFSET(GObjectReal, qdata));
- *
- * L'espace entre les deux derniers champs ne peut donc être pleinement exploité deux fois.
- */
-
-#if 0
-
-# define GET_GOBJECT_EXTRA(obj, tp) \
- ({ \
- BUILD_BUG_ON(sizeof(tp) > sizeof(guint)); \
- tp *___result; \
- ___result = (tp *)(((guint *)&obj->ref_count) + 1); \
- BUILD_BUG_ON((___result + 1) == (tp *)&obj->qdata); \
- ___result; \
- })
-
-#endif
-
-
-/**
- * Choix du bit de verrou pour le champ "lock".
- *
- * Dans la structure exploitant le mot utilisé ici, ce verrou est généralement
- * placé dans le bit de poids fort pour les objets qui l'utilisent.
- */
-
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-
-# define HOLE_LOCK_BIT 31
-
-#elif __BYTE_ORDER == __BIG_ENDIAN
-
-# define HOLE_LOCK_BIT 0
-
-#else
-
-# error "Unknown byte order"
-
-#endif
-
-
-/* Verrou d'accès pour une encapsulation */
-typedef struct _lockable_obj_extra_t
-{
- gint lock; /* Gestion d'accès aux fanions */
-
-} lockable_obj_extra_t;
-
-
-#define INIT_GOBJECT_EXTRA_LOCK(xtr) \
- do \
- { \
- lockable_obj_extra_t *__lockable; \
- __lockable = (lockable_obj_extra_t *)xtr; \
- __lockable->lock = 0; \
- } \
- while (0)
-#define LOCK_GOBJECT_EXTRA(xtr) \
- do \
- { \
- lockable_obj_extra_t *__lockable; \
- __lockable = (lockable_obj_extra_t *)xtr; \
- g_bit_lock(&__lockable->lock, HOLE_LOCK_BIT); \
- } \
- while (0)
+/* Fournit la valeur courante de la zone de stockage d'un objet. */
+guint g_thick_object_get_extra(const GThickObject *);
-#define UNLOCK_GOBJECT_EXTRA(xtr) \
- do \
- { \
- lockable_obj_extra_t *__lockable; \
- __lockable = (lockable_obj_extra_t *)xtr; \
- g_bit_unlock(&__lockable->lock, HOLE_LOCK_BIT); \
- } \
- while (0)
+/* Définit la valeur courante de la zone de stockage d'un objet. */
+void g_thick_object_set_extra(GThickObject *, guint);
diff --git a/src/glibext/secstorage-int.h b/src/glibext/secstorage-int.h
new file mode 100644
index 0000000..bbac133
--- /dev/null
+++ b/src/glibext/secstorage-int.h
@@ -0,0 +1,60 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * secstorage-int.h - définitions internes pour la conservation sécurisée d'éléments 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 _GLIBEXT_SECSTORAGE_INT_H
+#define _GLIBEXT_SECSTORAGE_INT_H
+
+
+#include "secstorage.h"
+
+
+
+/* Gardien des secrets avec support des stockages (instance) */
+struct _GSecretStorage
+{
+ GObject parent; /* A laisser en premier */
+
+ GSettings *settings; /* Configuration sollicitée */
+
+ void *master_key; /* Clef déverrouillée */
+
+};
+
+/* Gardien des secrets avec support des stockages (classe) */
+struct _GSecretStorageClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+ /* Signaux */
+
+ void (* lock_update) (GSecretStorage *);
+
+};
+
+
+/* Met en place un gardien des secrets avec support de stockage. */
+bool g_secret_storage_create(GSecretStorage *, GSettings *);
+
+
+
+#endif /* _GLIBEXT_SECSTORAGE_INT_H */
diff --git a/src/glibext/secstorage.c b/src/glibext/secstorage.c
new file mode 100644
index 0000000..b118aa6
--- /dev/null
+++ b/src/glibext/secstorage.c
@@ -0,0 +1,950 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * secstorage.c - conservation sécurisée d'éléments 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/>.
+ */
+
+
+#include "secstorage.h"
+
+
+#include <assert.h>
+#include <string.h>
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+
+
+#include "secstorage-int.h"
+#include "../core/logs.h"
+
+
+
+/**
+ * Les mécanismes de hachage de mot de passe doivent être utilisés avec un sel,
+ * et la longueur du sel doit être d’au moins 128 bits.
+ *
+ * Cette note concerne le hachage de mots de passe et non la dérivation de secrets
+ * cependant.
+ *
+ * Source : https://cyber.gouv.fr/sites/default/files/2021/03/anssi-guide-selection_crypto-1.0.pdf
+ */
+
+#define SECRET_STORAGE_SALT_SIZE (256 / 8)
+
+
+/**
+ * Nombre d'itérations pour PBKDF2 : en 2023, OWASP recommande 600000 itérations
+ * pour PBKDF2-HMAC-SHA256 (et 210000 pour PBKDF2-HMAC-SHA512).
+ *
+ * Source : https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#pbkdf2
+ */
+
+#define PBKDF2_HMAC_SHA256_ITERATIONS (2 << 20)
+
+
+/**
+ * AES 256 : clef de 256 bits, IV de 128 bits
+ */
+
+#define SECRET_STORAGE_KEK_SIZE (256 / 8)
+
+#define SECRET_STORAGE_KEY_SIZE (256 / 8)
+
+#define SECRET_STORAGE_BLOCK_SIZE (128 / 8)
+
+#define SECRET_STORAGE_IV_SIZE SECRET_STORAGE_BLOCK_SIZE
+
+
+
+/* Initialise la classe des stockages de secrets. */
+static void g_secret_storage_class_init(GSecretStorageClass *);
+
+/* Initialise une instance de stockage de secrets. */
+static void g_secret_storage_init(GSecretStorage *);
+
+/* Supprime toutes les références externes. */
+static void g_secret_storage_dispose(GObject *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_secret_storage_finalize(GObject *);
+
+/* Teste un mot de passe par Déverrouillage de clef maître. */
+static bool g_secret_storage_check_primary_password(GSecretStorage *, const char *, void **);
+
+
+
+/* Indique le type défini pour un gardien des secrets avec support des stockages. */
+G_DEFINE_TYPE(GSecretStorage, g_secret_storage, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des stockages de secrets. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_secret_storage_class_init(GSecretStorageClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = g_secret_storage_dispose;
+ object->finalize = g_secret_storage_finalize;
+
+ g_signal_new("lock-update",
+ G_TYPE_SECRET_STORAGE,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(GSecretStorageClass, lock_update),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : storage = instance à initialiser. *
+* *
+* Description : Initialise une instance de stockage de secrets. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_secret_storage_init(GSecretStorage *storage)
+{
+ storage->settings = NULL;
+
+ storage->master_key = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_secret_storage_dispose(GObject *object)
+{
+ GSecretStorage *storage; /* Gestion de stockage sécurisé*/
+
+ storage = G_SECRET_STORAGE(object);
+
+ g_clear_object(&storage->settings);
+
+ G_OBJECT_CLASS(g_secret_storage_parent_class)->dispose(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_secret_storage_finalize(GObject *object)
+{
+ GSecretStorage *storage; /* Gestion de stockage sécurisé*/
+
+ storage = G_SECRET_STORAGE(object);
+
+ if (storage->master_key != NULL)
+ free(storage->master_key);
+
+ G_OBJECT_CLASS(g_secret_storage_parent_class)->finalize(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : settings = éventuel espace de configuration à utiliser. *
+* *
+* Description : Créé un nouveau gardien des secrets avec support de stockage.*
+* *
+* Retour : Gestionnaire de stockage sécurisé mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GSecretStorage *g_secret_storage_new(GSettings *settings)
+{
+ GSecretStorage *result; /* Instance à retourner */
+
+ result = g_object_new(G_TYPE_SECRET_STORAGE, NULL);
+
+ if (!g_secret_storage_create(result, settings))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : storage = stockage sécurisé à initialiser. *
+* settings = éventuel espace de configuration à utiliser. *
+* *
+* Description : Met en place un gardien des secrets avec support de stockage.*
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_secret_storage_create(GSecretStorage *storage, GSettings *settings)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ if (settings != NULL)
+ {
+ ref_object(settings);
+ storage->settings = settings;
+ }
+ else
+ storage->settings = g_settings_new("re.chrysalide.framework.secstorage");
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : storage = espace de stockage sécurisé à consulter. *
+* *
+* Description : Détermine si une clef de chiffrement protégée est en place. *
+* *
+* Retour : Bilan de l'analyse. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_secret_storage_has_key(const GSecretStorage *storage)
+{
+ bool result; /* Bilan à retourner */
+ GVariant *value; /* Valeur de configuration */
+ gsize length; /* Taille d'une valeur donnée */
+
+ result = false;
+
+ value = g_settings_get_value(storage->settings, "master");
+
+ g_variant_get_fixed_array(value, &length, 1);
+
+ result = (length > SECRET_STORAGE_IV_SIZE);
+
+ g_variant_unref(value);
+
+ return result;;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : storage = espace de stockage sécurisé à consulter. *
+* password = mot de passe principal à appliquer. *
+* *
+* Description : Définit un mot de passe pour protéger une clef maître. *
+* *
+* Retour : Bilan de la mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_secret_storage_set_password(GSecretStorage *storage, const char *passwd)
+{
+ bool result; /* Bilan à retourner */
+ unsigned char salt[SECRET_STORAGE_SALT_SIZE]; /* Sel pour la dérivation*/
+ int ret; /* Bilan à d'un appel */
+ GVariant *value; /* Valeur de configuration */
+ unsigned char kek[SECRET_STORAGE_KEK_SIZE]; /* Clef de protection */
+ unsigned char key[SECRET_STORAGE_KEY_SIZE]; /* Clef maître */
+ unsigned char iv[SECRET_STORAGE_IV_SIZE]; /* IV associé */
+ EVP_CIPHER_CTX *ctx; /* Contexte pour le chiffrement*/
+ unsigned char encrypted[64]; /* Partie chiffrée à conserver */
+ unsigned char *iter; /* Tête d'écriture */
+ int outlen; /* Taille des données utiles */
+
+ result = false;
+
+ if (g_secret_storage_has_key(storage))
+ goto exit;
+
+ /* Création d'un sel pour la dérivation du mot de passe */
+
+ ret = RAND_bytes(salt, sizeof(salt));
+ if (ret != 1)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit;
+ }
+
+ /**
+ * La fonction g_variant_new_fixed_array() retourne un variant
+ * avec un décompte de référence flottant.
+ */
+
+ value = g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE,
+ salt, SECRET_STORAGE_SALT_SIZE, sizeof(unsigned char));
+
+ /**
+ * Comme le variant à une référence flottante, la fonction
+ * g_settings_set_value() consomme cette référence.
+ *
+ * Il n'y a donc pas lieu d'appeler g_variant_unref().
+ */
+
+ g_settings_set_value(storage->settings, "salt", value);
+
+ /* Dérivation du mot de passe */
+
+ ret = PKCS5_PBKDF2_HMAC(passwd, strlen(passwd),
+ salt, SECRET_STORAGE_SALT_SIZE,
+ PBKDF2_HMAC_SHA256_ITERATIONS, EVP_sha256(),
+ SECRET_STORAGE_KEK_SIZE, kek);
+
+ if (ret != 1)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit;
+ }
+
+ /* Définition de la clef maître et de son IV de chiffrement */
+
+ ret = RAND_bytes(key, sizeof(key));
+ if (ret != 1)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit;
+ }
+
+ ret = RAND_bytes(iv, sizeof(iv));
+ if (ret != 1)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit;
+ }
+
+ /* Chiffrement de la clef maître */
+
+ ctx = EVP_CIPHER_CTX_new();
+
+ if (ctx == NULL)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit;
+ }
+
+ EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
+
+ ret = EVP_EncryptInit_ex2(ctx, EVP_aes_256_wrap_pad(), kek, iv, NULL);
+ if (ret != 1)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit_with_ctx;
+ }
+
+ memcpy(encrypted, iv, SECRET_STORAGE_IV_SIZE);
+
+ iter = encrypted + SECRET_STORAGE_IV_SIZE;
+
+ ret = EVP_EncryptUpdate(ctx, iter, &outlen, key, SECRET_STORAGE_KEY_SIZE);
+ if (ret != 1)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit_with_ctx;
+ }
+
+ iter += outlen;
+
+ ret = EVP_EncryptFinal_ex(ctx, iter, &outlen);
+ if (ret != 1)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit_with_ctx;
+ }
+
+ iter += outlen;
+
+ assert((iter - encrypted) < 64);
+
+ /* Conservation de la clef protégée */
+
+ value = g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE,
+ encrypted, iter - encrypted, sizeof(unsigned char));
+
+ g_settings_set_value(storage->settings, "master", value);
+
+ g_signal_emit_by_name(storage, "lock-update");
+
+ result = true;
+
+ exit_with_ctx:
+
+ EVP_CIPHER_CTX_free(ctx);
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : storage = espace de stockage sécurisé à consulter. *
+* old = ancien mot de passe principal à vérifier. *
+* new = nouveau mot de passe principal à appliquer. *
+* *
+* Description : Modifie le mot de passe protégeant une clef maître. *
+* *
+* Retour : Bilan de la mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_secret_storage_change_password(GSecretStorage *storage, const char *old, const char *new)
+{
+ bool result; /* Bilan à retourner */
+
+ result = false;
+
+ if (!g_secret_storage_has_key(storage))
+ goto exit;
+
+ if (!g_secret_storage_check_primary_password(storage, old, NULL))
+ goto exit;
+
+ if (!g_secret_storage_is_locked(storage))
+ g_secret_storage_lock(storage);
+
+ g_settings_reset(storage->settings, "salt");
+ g_settings_reset(storage->settings, "master");
+
+ result = g_secret_storage_set_password(storage, new);
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : storage = espace de stockage sécurisé à consulter. *
+* password = mot de passe principal à appliquer. *
+* *
+* Description : Supprime le mot de passe protégeant une clef maître. *
+* *
+* Retour : Bilan de la mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_secret_storage_remove_password(GSecretStorage *storage, const char *passwd)
+{
+ bool result; /* Bilan à retourner */
+
+ result = false;
+
+ if (!g_secret_storage_has_key(storage))
+ goto exit;
+
+ if (!g_secret_storage_check_primary_password(storage, passwd, NULL))
+ goto exit;
+
+ if (!g_secret_storage_is_locked(storage))
+ g_secret_storage_lock(storage);
+
+ g_settings_reset(storage->settings, "salt");
+ g_settings_reset(storage->settings, "master");
+
+ g_signal_emit_by_name(storage, "lock-update");
+
+ result = true;
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : storage = espace de stockage sécurisé à consulter. *
+* *
+* Description : Détermine si la clef de chiffrement maître est vérouillée. *
+* *
+* Retour : Bilan de la détermination. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_secret_storage_is_locked(const GSecretStorage *storage)
+{
+ bool result; /* Bilan à retourner */
+
+ result = (storage->master_key == NULL);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : storage = espace de stockage sécurisé à manipuler. *
+* password = mot de passe principal à utiliser. *
+* master = éventuelle adresse pour un stockage de clef. [OUT]*
+* *
+* Description : Teste un mot de passe par Déverrouillage de clef maître. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_secret_storage_check_primary_password(GSecretStorage *storage, const char *passwd, void **master)
+{
+ bool result; /* Bilan à retourner */
+ GVariant *salt_value; /* Valeur du sel configuré */
+ gsize salt_length; /* Taille du sel conservé */
+ gconstpointer salt; /* Données associées #1 */
+ unsigned char kek[SECRET_STORAGE_KEK_SIZE]; /* Clef de protection */
+ int ret; /* Bilan à d'un appel */
+ GVariant *enc_value; /* Paramètres de chiffrement */
+ gsize enc_length; /* Taille de ces paramètrs */
+ gconstpointer encrypted; /* Données associées #2 */
+ EVP_CIPHER_CTX *ctx; /* Contexte de déchiffrement */
+ unsigned char iv[SECRET_STORAGE_IV_SIZE]; /* IV associé */
+ unsigned char key[SECRET_STORAGE_KEY_SIZE]; /* Clef maître */
+ unsigned char *iter; /* Tête d'écriture */
+ int outlen; /* Taille des données utiles */
+
+ result = false;
+
+ if (!g_secret_storage_is_locked(storage))
+ {
+ result = true;
+ goto quick_exit;
+ }
+
+ /* Récupération du sel mis en place */
+
+ salt_value = g_settings_get_value(storage->settings, "salt");
+
+ salt = g_variant_get_fixed_array(salt_value, &salt_length, sizeof(bin_t));
+
+ if (salt_length != SECRET_STORAGE_SALT_SIZE)
+ goto exit_with_salt;
+
+ /* Dérivation du mot de passe */
+
+ ret = PKCS5_PBKDF2_HMAC(passwd, strlen(passwd),
+ salt, SECRET_STORAGE_SALT_SIZE,
+ PBKDF2_HMAC_SHA256_ITERATIONS, EVP_sha256(),
+ SECRET_STORAGE_KEK_SIZE, kek);
+
+ if (ret != 1)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit_with_salt;
+ }
+
+ /* Récupération des paramètres chiffrés */
+
+ enc_value = g_settings_get_value(storage->settings, "master");
+
+ encrypted = g_variant_get_fixed_array(enc_value, &enc_length, sizeof(bin_t));
+
+ if (enc_length <= SECRET_STORAGE_IV_SIZE)
+ goto exit_with_enc;
+
+ /* Déhiffrement de la clef maître */
+
+ ctx = EVP_CIPHER_CTX_new();
+
+ if (ctx == NULL)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit_with_enc;
+ }
+
+ EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
+
+ memcpy(iv, encrypted, SECRET_STORAGE_IV_SIZE);
+
+ ret = EVP_DecryptInit_ex2(ctx, EVP_aes_256_wrap_pad(), kek, iv, NULL);
+ if (ret != 1)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit_with_ctx;
+ }
+
+ iter = key;
+
+ ret = EVP_DecryptUpdate(ctx, iter, &outlen,
+ ((unsigned char *)encrypted) + SECRET_STORAGE_IV_SIZE,
+ enc_length - SECRET_STORAGE_IV_SIZE);
+ if (ret != 1)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit_with_ctx;
+ }
+
+ iter += outlen;
+
+ ret = EVP_DecryptFinal_ex(ctx, iter, &outlen);
+ if (ret != 1)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit_with_ctx;
+ }
+
+ assert((iter - key) == SECRET_STORAGE_KEY_SIZE);
+
+ /* Stockage de la clef maître en mémoire */
+
+ if (master != NULL)
+ {
+ *master = malloc(SECRET_STORAGE_KEY_SIZE);
+ memcpy(*master, key, SECRET_STORAGE_KEY_SIZE);
+ }
+
+ result = true;
+
+ /* Sortie */
+
+ exit_with_ctx:
+
+ EVP_CIPHER_CTX_free(ctx);
+
+ exit_with_enc:
+
+ g_variant_unref(enc_value);
+
+ exit_with_salt:
+
+ g_variant_unref(salt_value);
+
+ quick_exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : storage = espace de stockage sécurisé à manipuler. *
+* password = mot de passe principal à utiliser. *
+* *
+* Description : Déverrouille la clef de chiffrement maître. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_secret_storage_unlock(GSecretStorage *storage, const char *passwd)
+{
+ bool result; /* Bilan à retourner */
+
+ result = g_secret_storage_check_primary_password(storage, passwd, &storage->master_key);
+
+ if (result)
+ g_signal_emit_by_name(storage, "lock-update");
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : storage = espace de stockage sécurisé à manipuler. *
+* *
+* Description : Verrouille la clef de chiffrement maître. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_secret_storage_lock(GSecretStorage *storage)
+{
+ if (storage->master_key != NULL)
+ {
+ free(storage->master_key);
+ storage->master_key = NULL;
+
+ g_signal_emit_by_name(storage, "lock-update");
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : storage = espace de stockage sécurisé à consulter. *
+* in = séquence d'octets à traiter. *
+* out = séquence d'octets résultantes. [OUT] *
+* *
+* Description : Chiffre des données avec la clef de chiffrement maître. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_secret_storage_encrypt_data(const GSecretStorage *storage, const sized_binary_t *in, sized_binary_t *out)
+{
+ bool result; /* Bilan à retourner */
+ unsigned char iv[SECRET_STORAGE_IV_SIZE]; /* IV associé */
+ int ret; /* Bilan à d'un appel */
+ EVP_CIPHER_CTX *ctx; /* Contexte pour le chiffrement*/
+ size_t needed; /* Taille de la sortie */
+ unsigned char *iter; /* Tête d'écriture */
+ int outlen; /* Taille des données utiles */
+
+ result = false;
+
+ if (g_secret_storage_is_locked(storage))
+ goto quick_exit;
+
+ /* Récupération de la clef maître et d'un IV de chiffrement */
+
+ ret = RAND_bytes(iv, sizeof(iv));
+ if (ret != 1)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit;
+ }
+
+ /* Préparation de la zone de réception */
+
+ needed = SECRET_STORAGE_IV_SIZE + ((in->size / SECRET_STORAGE_BLOCK_SIZE) + 1) * SECRET_STORAGE_BLOCK_SIZE;
+
+ setup_sized_binary(out, needed);
+
+ /* Chiffrement des données */
+
+ ctx = EVP_CIPHER_CTX_new();
+
+ if (ctx == NULL)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit;
+ }
+
+ ret = EVP_EncryptInit_ex2(ctx, EVP_aes_256_cbc(), storage->master_key, iv, NULL);
+ if (ret != 1)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit_with_ctx;
+ }
+
+ memcpy(out->data, iv, SECRET_STORAGE_IV_SIZE);
+
+ iter = out->bin_data + SECRET_STORAGE_IV_SIZE;
+
+ ret = EVP_EncryptUpdate(ctx, iter, &outlen, in->bin_data, in->size);
+ if (ret != 1)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit_with_ctx;
+ }
+
+ iter += outlen;
+
+ ret = EVP_EncryptFinal_ex(ctx, iter, &outlen);
+ if (ret != 1)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit_with_ctx;
+ }
+
+ iter += outlen;
+
+ assert((iter - out->bin_data) == out->size);
+
+ result = true;
+
+ /* Sortie */
+
+ exit_with_ctx:
+
+ EVP_CIPHER_CTX_free(ctx);
+
+ if (!result)
+ exit_sized_binary(out);
+
+ exit:
+ quick_exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : storage = espace de stockage sécurisé à consulter. *
+* in = séquence d'octets à traiter. *
+* out = séquence d'octets résultantes. [OUT] *
+* *
+* Description : Déchiffre des données avec la clef de chiffrement maître. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_secret_storage_decrypt_data(const GSecretStorage *storage, const sized_binary_t *in, sized_binary_t *out)
+{
+ bool result; /* Bilan à retourner */
+ unsigned char iv[SECRET_STORAGE_IV_SIZE]; /* IV associé */
+ int ret; /* Bilan à d'un appel */
+ EVP_CIPHER_CTX *ctx; /* Contexte pour le chiffrement*/
+ size_t needed; /* Taille de la sortie */
+ unsigned char *iter; /* Tête d'écriture */
+ int outlen; /* Taille des données utiles */
+
+ result = false;
+
+ if (g_secret_storage_is_locked(storage))
+ goto quick_exit;
+
+ /* Récupération d'un IV de déchiffrement */
+
+ if (in->size < SECRET_STORAGE_IV_SIZE)
+ goto exit;
+
+ memcpy(iv, in->data, SECRET_STORAGE_IV_SIZE);
+
+ /* Préparation de la zone de réception */
+
+ needed = in->size - SECRET_STORAGE_IV_SIZE;
+
+ setup_sized_binary(out, needed);
+
+ /* Chiffrement des données */
+
+ ctx = EVP_CIPHER_CTX_new();
+
+ if (ctx == NULL)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit;
+ }
+
+ ret = EVP_DecryptInit_ex2(ctx, EVP_aes_256_cbc(), storage->master_key, iv, NULL);
+ if (ret != 1)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit_with_ctx;
+ }
+
+ iter = out->bin_data;
+
+ ret = EVP_DecryptUpdate(ctx, iter, &outlen,
+ in->bin_data + SECRET_STORAGE_IV_SIZE, in->size - SECRET_STORAGE_IV_SIZE);
+ if (ret != 1)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit_with_ctx;
+ }
+
+ iter += outlen;
+
+ ret = EVP_DecryptFinal_ex(ctx, iter, &outlen);
+ if (ret != 1)
+ {
+ LOG_ERROR_OPENSSL;
+ goto exit_with_ctx;
+ }
+
+ iter += outlen;
+
+ assert((iter - out->bin_data) <= out->size);
+
+ resize_sized_binary(out, iter - out->bin_data);
+
+ result = true;
+
+ /* Sortie */
+
+ exit_with_ctx:
+
+ EVP_CIPHER_CTX_free(ctx);
+
+ if (!result)
+ exit_sized_binary(out);
+
+ exit:
+ quick_exit:
+
+ return result;
+
+}
diff --git a/src/glibext/secstorage.h b/src/glibext/secstorage.h
new file mode 100644
index 0000000..ed3f79c
--- /dev/null
+++ b/src/glibext/secstorage.h
@@ -0,0 +1,74 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * secstorage.h - prototypes pour la conservation sécurisée d'éléments 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 _GLIBEXT_SECSTORAGE_H
+#define _GLIBEXT_SECSTORAGE_H
+
+
+#include <stdbool.h>
+#include <gio/gio.h>
+
+
+#include "helpers.h"
+#include "../common/szbin.h"
+
+
+
+#define G_TYPE_SECRET_STORAGE (g_secret_storage_get_type())
+
+DECLARE_GTYPE(GSecretStorage, g_secret_storage, G, SECRET_STORAGE);
+
+
+/* Créé un nouveau gardien des secrets avec support de stockage. */
+GSecretStorage *g_secret_storage_new(GSettings *);
+
+/* Détermine si une clef de chiffrement protégée est en place. */
+bool g_secret_storage_has_key(const GSecretStorage *);
+
+/* Définit un mot de passe pour protéger une clef maître. */
+bool g_secret_storage_set_password(GSecretStorage *, const char *);
+
+/* Modifie le mot de passe protégeant une clef maître. */
+bool g_secret_storage_change_password(GSecretStorage *, const char *, const char *);
+
+/* Supprime le mot de passe protégeant une clef maître. */
+bool g_secret_storage_remove_password(GSecretStorage *, const char *);
+
+/* Détermine si la clef de chiffrement maître est vérouillée. */
+bool g_secret_storage_is_locked(const GSecretStorage *);
+
+/* Déverrouille la clef de chiffrement maître. */
+bool g_secret_storage_unlock(GSecretStorage *, const char *);
+
+/* Verrouille la clef de chiffrement maître. */
+void g_secret_storage_lock(GSecretStorage *);
+
+/* Chiffre des données avec la clef de chiffrement maître. */
+bool g_secret_storage_encrypt_data(const GSecretStorage *, const sized_binary_t *, sized_binary_t *);
+
+/* Déchiffre des données avec la clef de chiffrement maître. */
+bool g_secret_storage_decrypt_data(const GSecretStorage *, const sized_binary_t *, sized_binary_t *);
+
+
+
+#endif /* _GLIBEXT_SECSTORAGE_H */
diff --git a/src/glibext/singleton-int.h b/src/glibext/singleton-int.h
index 3db17f9..747e64a 100644
--- a/src/glibext/singleton-int.h
+++ b/src/glibext/singleton-int.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* singleton-int.h - définitions internes propres aux réductions du nombre d'instances d'un même type
*
- * Copyright (C) 2021 Cyrille Bagard
+ * Copyright (C) 2021-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -29,44 +29,61 @@
+/* ------------------ INTERFACE POUR CANDIDAT A UNE CENTRALISATION ------------------ */
+
+
/* Fournit une liste de candidats embarqués par un candidat. */
typedef GSingletonCandidate ** (* list_inner_instances_fc) (const GSingletonCandidate *, size_t *);
/* Met à jour une liste de candidats embarqués par un candidat. */
typedef void (* update_inner_instances_fc) (GSingletonCandidate *, GSingletonCandidate **, size_t);
-/* Fournit l'empreinte d'un candidat à une centralisation. */
-typedef guint (* hash_candidate_fc) (const GSingletonCandidate *);
-
-/* Détermine si deux candidats à l'unicité sont identiques. */
-typedef gboolean (* is_candidate_equal_fc) (const GSingletonCandidate *, const GSingletonCandidate *);
-
/* Marque un candidat comme figé. */
-typedef void (* set_candidate_ro_fc) (GSingletonCandidate *);
+typedef void (* mark_candidate_as_ro_fc) (GSingletonCandidate *);
/* Indique si le candidat est figé. */
typedef bool (* is_candidate_ro_fc) (const GSingletonCandidate *);
+/* Crée une copie modifiable d'un object unique. */
+typedef GSingletonCandidate * (* dup_candidate_fc) (const GSingletonCandidate *);
+
/* Instance d'objet visant à être unique (interface) */
-struct _GSingletonCandidateIface
+struct _GSingletonCandidateInterface
{
GTypeInterface base_iface; /* A laisser en premier */
list_inner_instances_fc list_inner; /* Récupération d'internes */
update_inner_instances_fc update_inner; /* Mise à jour des éléments */
- hash_candidate_fc hash; /* Prise d'empreinte */
- is_candidate_equal_fc is_equal; /* Comparaison */
-
- set_candidate_ro_fc set_ro; /* Bascule en mode figé */
+ mark_candidate_as_ro_fc mark_as_ro; /* Bascule en mode figé */
is_candidate_ro_fc is_ro; /* Consultation de l'état */
+ dup_candidate_fc dup; /* Création de copie modifiable*/
+
+};
+
+
+
+/* ------------------------- COLLECTION D'INSTANCES UNIQUES ------------------------- */
+
+
+/* Définition d'un compacteur d'instances de types (instance) */
+struct _GSingletonFactory
+{
+ GObject parent; /* A laisser en premier */
+
+ GHashTable *table; /* Suivi des conservations */
+ GMutex access; /* Verrou pour la concurrence */
+
};
+/* Définition d'un compacteur d'instances de types (classe) */
+struct _GSingletonFactoryClass
+{
+ GObjectClass parent; /* A laisser en premier */
-/* Redéfinition */
-typedef GSingletonCandidateIface GSingletonCandidateInterface;
+};
diff --git a/src/glibext/singleton.c b/src/glibext/singleton.c
index 78a3ad4..0a50d19 100644
--- a/src/glibext/singleton.c
+++ b/src/glibext/singleton.c
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* singleton.c - réduction du nombre d'instances d'un même type
*
- * Copyright (C) 2021 Cyrille Bagard
+ * Copyright (C) 2021-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -25,52 +25,35 @@
#include <assert.h>
+#include <malloc.h>
+#include "comparable.h"
+#include "hashable.h"
#include "singleton-int.h"
/* ------------------ INTERFACE POUR CANDIDAT A UNE CENTRALISATION ------------------ */
+
/* Procède à l'initialisation de l'interface de rassemblement. */
static void g_singleton_candidate_default_init(GSingletonCandidateInterface *);
+/* Fournit une liste de candidats embarqués par un candidat. */
+static GSingletonCandidate **g_singleton_candidate_list_inner_instances(const GSingletonCandidate *, size_t *);
+
/* Met à jour une liste de candidats embarqués par un candidat. */
static void g_singleton_candidate_update_inner_instances(GSingletonCandidate *, GSingletonCandidate **, size_t);
-/* Fournit l'empreinte d'un candidat à une centralisation. */
-static guint _g_singleton_candidate_hash(GSingletonCandidate *, GList **);
-
-/* Détermine si deux candidats à l'unicité sont identiques. */
-static gboolean _g_singleton_candidate_is_equal(GSingletonCandidate *, GSingletonCandidate *, GList **);
-
/* Marque un candidat comme figé. */
-static void _g_singleton_candidate_set_read_only(GSingletonCandidate *, GList **);
+static void g_singleton_candidate_mark_as_read_only(GSingletonCandidate *);
/* ------------------------- COLLECTION D'INSTANCES UNIQUES ------------------------- */
-/* Définition d'un compacteur d'instances de types (instance) */
-struct _GSingletonFactory
-{
- GObject parent; /* A laisser en premier */
-
- GHashTable *table; /* Suivi des conservations */
- GMutex access; /* Verrou pour la concurrence */
-
-};
-
-/* Définition d'un compacteur d'instances de types (classe) */
-struct _GSingletonFactoryClass
-{
- GObjectClass parent; /* A laisser en premier */
-
-};
-
-
/* Initialise la classe des compacteurs d'instances de types. */
static void g_singleton_factory_class_init(GSingletonFactoryClass *);
@@ -90,8 +73,10 @@ static void g_singleton_factory_finalize(GSingletonFactory *);
/* ---------------------------------------------------------------------------------- */
-/* Détermine le type d'une interface pour la lecture de binaire. */
-G_DEFINE_INTERFACE(GSingletonCandidate, g_singleton_candidate, G_TYPE_OBJECT)
+/* Détermine le type d'une interface pour la constitution d'objets uniques. */
+G_DEFINE_INTERFACE_WITH_CODE(GSingletonCandidate, g_singleton_candidate, G_TYPE_OBJECT,
+ g_type_interface_add_prerequisite(g_define_type_id, G_TYPE_HASHABLE_OBJECT);
+ g_type_interface_add_prerequisite(g_define_type_id, G_TYPE_COMPARABLE_OBJECT))
/******************************************************************************
@@ -108,6 +93,13 @@ G_DEFINE_INTERFACE(GSingletonCandidate, g_singleton_candidate, G_TYPE_OBJECT)
static void g_singleton_candidate_default_init(GSingletonCandidateInterface *iface)
{
+ iface->list_inner = NULL;
+ iface->update_inner = NULL;
+
+ iface->mark_as_ro = NULL;
+ iface->is_ro = NULL;
+
+ iface->dup = NULL;
}
@@ -128,14 +120,17 @@ static void g_singleton_candidate_default_init(GSingletonCandidateInterface *ifa
GSingletonCandidate **g_singleton_candidate_list_inner_instances(const GSingletonCandidate *candidate, size_t *count)
{
GSingletonCandidate **result; /* Instances à retourner */
- GSingletonCandidateIface *iface; /* Interface utilisée */
+ GSingletonCandidateInterface *iface; /* Interface utilisée */
iface = G_SINGLETON_CANDIDATE_GET_IFACE(candidate);
if (iface->list_inner == NULL)
{
+ assert(iface->update_inner == NULL);
+
*count = 0;
result = NULL;
+
}
else
@@ -162,7 +157,7 @@ GSingletonCandidate **g_singleton_candidate_list_inner_instances(const GSingleto
static void g_singleton_candidate_update_inner_instances(GSingletonCandidate *candidate, GSingletonCandidate **instances, size_t count)
{
- GSingletonCandidateIface *iface; /* Interface utilisée */
+ GSingletonCandidateInterface *iface; /* Interface utilisée */
iface = G_SINGLETON_CANDIDATE_GET_IFACE(candidate);
@@ -181,82 +176,36 @@ static void g_singleton_candidate_update_inner_instances(GSingletonCandidate *ca
/******************************************************************************
* *
* Paramètres : candidate = objet dont l'instance se veut unique. *
-* processed = liste de candidats déjà traités. *
* *
-* Description : Fournit l'empreinte d'un candidat à une centralisation. *
+* Description : Marque un candidat comme figé. *
* *
-* Retour : Empreinte de l'élément représenté. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-static guint _g_singleton_candidate_hash(GSingletonCandidate *candidate, GList **processed)
+static void g_singleton_candidate_mark_as_read_only(GSingletonCandidate *candidate)
{
- guint result; /* Valeur à retourner */
- GList *skip; /* Détection de boucle */
- GSingletonCandidateIface *iface; /* Interface utilisée */
+ GSingletonCandidateInterface *iface; /* Interface utilisée */
GSingletonCandidate **children; /* Instances internes */
size_t count; /* Quantité de ces instances */
size_t i; /* Boucle de parcours */
- skip = g_list_find(*processed, candidate);
-
- if (skip != NULL)
- result = 0;
-
- else
- {
- iface = G_SINGLETON_CANDIDATE_GET_IFACE(candidate);
-
- result = iface->hash(candidate);
-
- *processed = g_list_append(*processed, candidate);
-
- children = g_singleton_candidate_list_inner_instances(candidate, &count);
+ iface = G_SINGLETON_CANDIDATE_GET_IFACE(candidate);
- for (i = 0; i < count; i++)
- {
- result ^= _g_singleton_candidate_hash(children[i], processed);
- g_object_unref(G_OBJECT(children[i]));
- }
+ iface->mark_as_ro(candidate);
- if (children != NULL)
- free(children);
+ children = g_singleton_candidate_list_inner_instances(candidate, &count);
+ for (i = 0; i < count; i++)
+ {
+ g_singleton_candidate_mark_as_read_only(children[i]);
+ unref_object(G_OBJECT(children[i]));
}
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : candidate = objet dont l'instance se veut unique. *
-* *
-* Description : Fournit l'empreinte d'un candidat à une centralisation. *
-* *
-* Retour : Empreinte de l'élément représenté. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-guint g_singleton_candidate_hash(GSingletonCandidate *candidate)
-{
- guint result; /* Valeur à retourner */
- GList *processed; /* Suivi des traitements */
-
- processed = NULL;
-
- result = _g_singleton_candidate_hash(candidate, &processed);
-
- assert(processed != NULL);
-
- g_list_free(processed);
-
- return result;
+ if (children != NULL)
+ free(children);
}
@@ -264,116 +213,43 @@ guint g_singleton_candidate_hash(GSingletonCandidate *candidate)
/******************************************************************************
* *
* Paramètres : candidate = objet dont l'instance se veut unique. *
-* other = second élément à analyser. *
-* processed = liste de candidats déjà traités. *
* *
-* Description : Détermine si deux candidats à l'unicité sont identiques. *
+* Description : Indique si le candidat est figé. *
* *
-* Retour : Bilan de la comparaison. *
+* Retour : true si le contenu du candidat ne peut plus être modifié. *
* *
* Remarques : - *
* *
******************************************************************************/
-static gboolean _g_singleton_candidate_is_equal(GSingletonCandidate *candidate, GSingletonCandidate *other, GList **processed)
+bool g_singleton_candidate_is_read_only(const GSingletonCandidate *candidate)
{
- gboolean result; /* Bilan à renvoyer */
- GList *skip; /* Détection de boucle */
- GSingletonCandidateIface *iface; /* Interface utilisée */
- GSingletonCandidate **children[2]; /* Instances internes */
- size_t count[2]; /* Quantité de ces instances */
+ bool result; /* Etat à retourner */
+ GSingletonCandidateInterface *iface; /* Interface utilisée */
+#ifndef NDEBUG
+ GSingletonCandidate **children; /* Instances internes */
+ size_t count; /* Quantité de ces instances */
size_t i; /* Boucle de parcours */
+#endif
- skip = g_list_find(processed[0], candidate);
-
- if (skip != NULL)
- result = (g_list_find(processed[1], other) != NULL);
-
- else
- {
- iface = G_SINGLETON_CANDIDATE_GET_IFACE(candidate);
-
- result = iface->is_equal(candidate, other);
-
- processed[0] = g_list_append(processed[0], candidate);
- processed[1] = g_list_append(processed[1], other);
-
- if (!result)
- goto done;
-
- children[0] = g_singleton_candidate_list_inner_instances(candidate, &count[0]);
- children[1] = g_singleton_candidate_list_inner_instances(other, &count[1]);
-
- if (count[0] != count[1])
- {
- for (i = 0; i < count[0]; i++)
- g_object_unref(G_OBJECT(children[0][i]));
-
- for (i = 0; i < count[1]; i++)
- g_object_unref(G_OBJECT(children[1][i]));
-
- }
-
- else
- {
- for (i = 0; i < count[0] && result; i++)
- {
- result = _g_singleton_candidate_is_equal(children[0][i], children[1][i], processed);
- g_object_unref(G_OBJECT(children[0][i]));
- g_object_unref(G_OBJECT(children[1][i]));
- }
-
- for (; i < count[0]; i++)
- {
- g_object_unref(G_OBJECT(children[0][i]));
- g_object_unref(G_OBJECT(children[1][i]));
- }
+ iface = G_SINGLETON_CANDIDATE_GET_IFACE(candidate);
- if (children[0] != NULL)
- free(children[0]);
+ result = iface->is_ro(candidate);
- if (children[1] != NULL)
- free(children[1]);
+#ifndef NDEBUG
- }
+ children = g_singleton_candidate_list_inner_instances(candidate, &count);
+ for (i = 0; i < count; i++)
+ {
+ assert(result == g_singleton_candidate_is_read_only(children[i]));
+ unref_object(G_OBJECT(children[i]));
}
- done:
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : candidate = objet dont l'instance se veut unique. *
-* other = second élément à analyser. *
-* *
-* Description : Détermine si deux candidats à l'unicité sont identiques. *
-* *
-* Retour : Bilan de la comparaison. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-gboolean g_singleton_candidate_is_equal(GSingletonCandidate *candidate, GSingletonCandidate *other)
-{
- gboolean result; /* Bilan à renvoyer */
- GList *processed[2]; /* Suivi des traitements */
+ if (children != NULL)
+ free(children);
- processed[0] = NULL;
- processed[1] = NULL;
-
- result = _g_singleton_candidate_is_equal(candidate, other, processed);
-
- assert(processed[0] != NULL);
- assert(processed[1] != NULL);
-
- g_list_free(processed[0]);
- g_list_free(processed[1]);
+#endif
return result;
@@ -383,97 +259,60 @@ gboolean g_singleton_candidate_is_equal(GSingletonCandidate *candidate, GSinglet
/******************************************************************************
* *
* Paramètres : candidate = objet dont l'instance se veut unique. *
-* processed = liste de candidats déjà traités. *
* *
-* Description : Marque un candidat comme figé. *
+* Description : Crée une copie modifiable d'un object unique. *
* *
-* Retour : - *
+* Retour : Nouvelle instance mise en place. *
* *
* Remarques : - *
* *
******************************************************************************/
-static void _g_singleton_candidate_set_read_only(GSingletonCandidate *candidate, GList **processed)
+GSingletonCandidate *g_singleton_candidate_dup(const GSingletonCandidate *candidate)
{
- GList *skip; /* Détection de boucle */
- GSingletonCandidateIface *iface; /* Interface utilisée */
- GSingletonCandidate **children; /* Instances internes */
- size_t count; /* Quantité de ces instances */
+ GSingletonCandidate *result; /* Instance à retourner */
+ GSingletonCandidateInterface *iface; /* Interface utilisée */
+ size_t count; /* Quantité d'objets internes */
+ GSingletonCandidate **children; /* Liste d'instances internes */
size_t i; /* Boucle de parcours */
+ GSingletonCandidate **new_children; /* Nouvelle liste d'instances */
- skip = g_list_find(*processed, candidate);
+ iface = G_SINGLETON_CANDIDATE_GET_IFACE(candidate);
- if (skip == NULL)
- {
- iface = G_SINGLETON_CANDIDATE_GET_IFACE(candidate);
+ result = iface->dup(candidate);
- iface->set_ro(candidate);
+ assert(!g_singleton_candidate_is_read_only(result));
- *processed = g_list_append(*processed, candidate);
+ children = g_singleton_candidate_list_inner_instances(candidate, &count);
- children = g_singleton_candidate_list_inner_instances(candidate, &count);
+ if (count > 0)
+ {
+ new_children = malloc(count * sizeof(GSingletonCandidate *));
for (i = 0; i < count; i++)
{
- _g_singleton_candidate_set_read_only(candidate, processed);
- g_object_unref(G_OBJECT(children[i]));
- }
-
- if (children != NULL)
- free(children);
-
- }
-
-}
+ new_children[i] = g_singleton_candidate_dup(children[i]);
+ assert(!g_singleton_candidate_is_read_only(new_children[i]));
-/******************************************************************************
-* *
-* Paramètres : candidate = objet dont l'instance se veut unique. *
-* *
-* Description : Marque un candidat comme figé. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_singleton_candidate_set_read_only(GSingletonCandidate *candidate)
-{
- GList *processed; /* Suivi des traitements */
-
- processed = NULL;
-
- _g_singleton_candidate_set_read_only(candidate, &processed);
-
- assert(processed != NULL);
+ }
- g_list_free(processed);
-
-}
+ g_singleton_candidate_update_inner_instances(result, new_children, count);
+ for (i = 0; i < count; i++)
+ {
+ unref_object(G_OBJECT(new_children[i]));
+ unref_object(G_OBJECT(children[i]));
+ }
-/******************************************************************************
-* *
-* Paramètres : candidate = objet dont l'instance se veut unique. *
-* *
-* Description : Indique si le candidat est figé. *
-* *
-* Retour : true si le contenu du candidat ne peut plus être modifié. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ free(new_children);
-bool g_singleton_candidate_is_read_only(const GSingletonCandidate *candidate)
-{
- bool result; /* Etat à retourner */
- GSingletonCandidateIface *iface; /* Interface utilisée */
+ }
- iface = G_SINGLETON_CANDIDATE_GET_IFACE(candidate);
+ if (children != NULL)
+ free(children);
- result = iface->is_ro(candidate);
+ assert(G_OBJECT_TYPE(result) == G_OBJECT_TYPE(candidate));
return result;
@@ -528,8 +367,8 @@ static void g_singleton_factory_class_init(GSingletonFactoryClass *klass)
static void g_singleton_factory_init(GSingletonFactory *factory)
{
- factory->table = g_hash_table_new_full((GHashFunc)g_singleton_candidate_hash,
- (GEqualFunc)g_singleton_candidate_is_equal,
+ factory->table = g_hash_table_new_full((GHashFunc)g_hashable_object_hash,
+ (GEqualFunc)g_comparable_object_is_equal,
g_object_unref, NULL);
g_mutex_init(&factory->access);
@@ -688,7 +527,7 @@ GSingletonCandidate *g_singleton_factory_get_instance(GSingletonFactory *factory
g_hash_table_add(factory->table, candidate);
#endif
- g_singleton_candidate_set_read_only(candidate);
+ g_singleton_candidate_mark_as_read_only(candidate);
result = candidate;
diff --git a/src/glibext/singleton.h b/src/glibext/singleton.h
index 629687a..11afffd 100644
--- a/src/glibext/singleton.h
+++ b/src/glibext/singleton.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* singleton.h - prototypes pour la réduction du nombre d'instances d'un même type
*
- * Copyright (C) 2021 Cyrille Bagard
+ * Copyright (C) 2021-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -25,71 +25,36 @@
#define _GLIBEXT_SINGLETON_H
-#include <glib-object.h>
#include <stdbool.h>
-
-/* Définition d'un compacteur d'instances de types (instance) */
-typedef struct _GSingletonFactory GSingletonFactory;
+#include "helpers.h"
/* ------------------ INTERFACE POUR CANDIDAT A UNE CENTRALISATION ------------------ */
-#define G_TYPE_SINGLETON_CANDIDATE (g_singleton_candidate_get_type())
-#define G_SINGLETON_CANDIDATE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SINGLETON_CANDIDATE, GSingletonCandidate))
-#define G_SINGLETON_CANDIDATE_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST((vtable), G_TYPE_SINGLETON_CANDIDATE, GSingletonCandidateIface))
-#define G_IS_SINGLETON_CANDIDATE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SINGLETON_CANDIDATE))
-#define G_IS_SINGLETON_CANDIDATE_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE((vtable), G_TYPE_SINGLETON_CANDIDATE))
-#define G_SINGLETON_CANDIDATE_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), G_TYPE_SINGLETON_CANDIDATE, GSingletonCandidateIface))
-
-
-/* Instance d'objet visant à être unique (coquille vide) */
-typedef struct _GSingletonCandidate GSingletonCandidate;
-
-/* Instance d'objet visant à être unique (interface) */
-typedef struct _GSingletonCandidateIface GSingletonCandidateIface;
-
-
-/* Détermine le type d'une interface pour la lecture de binaire. */
-GType g_singleton_candidate_get_type(void) G_GNUC_CONST;
+#define G_TYPE_SINGLETON_CANDIDATE (g_singleton_candidate_get_type())
-/* Fournit une liste de candidats embarqués par un candidat. */
-GSingletonCandidate **g_singleton_candidate_list_inner_instances(const GSingletonCandidate *, size_t *);
+DECLARE_INTERFACE(GSingletonCandidate, g_singleton_candidate, G, SINGLETON_CANDIDATE);
-/* Fournit l'empreinte d'un candidat à une centralisation. */
-guint g_singleton_candidate_hash(GSingletonCandidate *);
-
-/* Détermine si deux candidats à l'unicité sont identiques. */
-gboolean g_singleton_candidate_is_equal(GSingletonCandidate *, GSingletonCandidate *);
-
-/* Marque un candidat comme figé. */
-void g_singleton_candidate_set_read_only(GSingletonCandidate *);
/* Indique si le candidat est figé. */
bool g_singleton_candidate_is_read_only(const GSingletonCandidate *);
+/* Crée une copie modifiable d'un object unique. */
+GSingletonCandidate *g_singleton_candidate_dup(const GSingletonCandidate *);
-/* ------------------------- COLLECTION D'INSTANCES UNIQUES ------------------------- */
-
-#define G_TYPE_SINGLETON_FACTORY g_singleton_factory_get_type()
-#define G_SINGLETON_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SINGLETON_FACTORY, GSingletonFactory))
-#define G_IS_SINGLETON_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SINGLETON_FACTORY))
-#define G_SINGLETON_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SINGLETON_FACTORY, GSingletonFactoryClass))
-#define G_IS_SINGLETON_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SINGLETON_FACTORY))
-#define G_SINGLETON_FACTORY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SINGLETON_FACTORY, GSingletonFactoryClass))
+/* ------------------------- COLLECTION D'INSTANCES UNIQUES ------------------------- */
-/* Définition d'un compacteur d'instances de types (classe) */
-typedef struct _GSingletonFactoryClass GSingletonFactoryClass;
+#define G_TYPE_SINGLETON_FACTORY (g_singleton_factory_get_type())
+DECLARE_GTYPE(GSingletonFactory, g_singleton_factory, G, SINGLETON_FACTORY);
-/* Indique le type défini pour une mémoire de types d'objets. */
-GType g_singleton_factory_get_type(void);
/* Crée un compacteur d'instances de types. */
GSingletonFactory *g_singleton_factory_new(void);
diff --git a/src/glibext/strbuilder-int.h b/src/glibext/strbuilder-int.h
new file mode 100644
index 0000000..d74e65c
--- /dev/null
+++ b/src/glibext/strbuilder-int.h
@@ -0,0 +1,47 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * strbuilder-int.h - définitions internes propres aux éléments exportant une chaîne de caractères
+ *
+ * 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 _GLIBEXT_STRBUILDER_INT_H
+#define _GLIBEXT_STRBUILDER_INT_H
+
+
+#include "strbuilder.h"
+
+
+
+/* Exporte une chaîne de caractères à partir d'un objet. */
+typedef bool (* strbuilder_to_string_fc) (const GStringBuilder *, unsigned int, sized_binary_t *);
+
+
+/* Instance d'objet visant à être unique (interface) */
+struct _GStringBuilderInterface
+{
+ GTypeInterface base_iface; /* A laisser en premier */
+
+ strbuilder_to_string_fc to_string; /* Conversion en chaîne */
+
+};
+
+
+
+#endif /* _GLIBEXT_STRBUILDER_INT_H */
diff --git a/src/glibext/strbuilder.c b/src/glibext/strbuilder.c
new file mode 100644
index 0000000..e48674c
--- /dev/null
+++ b/src/glibext/strbuilder.c
@@ -0,0 +1,89 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * strbuilder.c - exportation d'une chaîne de caractères depuis un élément
+ *
+ * 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 "strbuilder.h"
+
+
+#include "strbuilder-int.h"
+
+
+
+/* Procède à l'initialisation de l'interface d'exportation. */
+static void g_string_builder_default_init(GStringBuilderInterface *);
+
+
+
+/* Détermine le type d'une interface pour la constitution d'objets uniques. */
+G_DEFINE_INTERFACE(GStringBuilder, g_string_builder, G_TYPE_OBJECT)
+
+
+/******************************************************************************
+* *
+* Paramètres : iface = interface GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'interface d'exportation. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_string_builder_default_init(GStringBuilderInterface *iface)
+{
+ iface->to_string = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : builder = objet dont l'instance est exportable. *
+* flags = éventuelles indications pour l'opération. *
+* out = chaîne de caractères mise en place. [OUT] *
+* *
+* Description : Exporte une chaîne de caractères à partir d'un objet. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : La sortie out est à nettoyer avec exit_sized_binary() après *
+* usage. *
+* *
+******************************************************************************/
+
+bool g_string_builder_to_string(const GStringBuilder *builder, unsigned int flags, sized_binary_t *out)
+{
+ bool result; /* Bilan à retourner */
+ GStringBuilderInterface *iface; /* Interface utilisée */
+
+ iface = G_STRING_BUILDER_GET_IFACE(builder);
+
+ if (iface->to_string == NULL)
+ result = false;
+
+ else
+ result = iface->to_string(builder, flags, out);
+
+ return result;
+
+}
diff --git a/src/glibext/strbuilder.h b/src/glibext/strbuilder.h
new file mode 100644
index 0000000..b6422f7
--- /dev/null
+++ b/src/glibext/strbuilder.h
@@ -0,0 +1,46 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * strbuilder.h - prototypes pour l'exportation d'une chaîne de caractères depuis un élément
+ *
+ * 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 _GLIBEXT_STRBUILDER_H
+#define _GLIBEXT_STRBUILDER_H
+
+
+#include <stdbool.h>
+
+
+#include "helpers.h"
+#include "../common/szbin.h"
+
+
+
+#define G_TYPE_STRING_BUILDER (g_string_builder_get_type())
+
+DECLARE_INTERFACE(GStringBuilder, g_string_builder, G, STRING_BUILDER);
+
+
+/* Exporte une chaîne de caractères à partir d'un objet. */
+bool g_string_builder_to_string(const GStringBuilder *, unsigned int, sized_binary_t *);
+
+
+
+#endif /* _GLIBEXT_STRBUILDER_H */