diff options
Diffstat (limited to 'src/glibext')
-rw-r--r-- | src/glibext/Makefile.am | 16 | ||||
-rw-r--r-- | src/glibext/comparable-int.h | 47 | ||||
-rw-r--r-- | src/glibext/comparable.c | 110 | ||||
-rw-r--r-- | src/glibext/comparable.h | 46 | ||||
-rw-r--r-- | src/glibext/comparison-int.h | 58 | ||||
-rw-r--r-- | src/glibext/comparison.c | 199 | ||||
-rw-r--r-- | src/glibext/comparison.h | 80 | ||||
-rw-r--r-- | src/glibext/hashable-int.h | 47 | ||||
-rw-r--r-- | src/glibext/hashable.c | 82 | ||||
-rw-r--r-- | src/glibext/hashable.h | 42 | ||||
-rw-r--r-- | src/glibext/objhole-int.h | 166 | ||||
-rw-r--r-- | src/glibext/objhole.c | 191 | ||||
-rw-r--r-- | src/glibext/objhole.h | 114 | ||||
-rw-r--r-- | src/glibext/secstorage-int.h | 60 | ||||
-rw-r--r-- | src/glibext/secstorage.c | 950 | ||||
-rw-r--r-- | src/glibext/secstorage.h | 74 | ||||
-rw-r--r-- | src/glibext/singleton-int.h | 47 | ||||
-rw-r--r-- | src/glibext/singleton.c | 341 | ||||
-rw-r--r-- | src/glibext/singleton.h | 53 | ||||
-rw-r--r-- | src/glibext/strbuilder-int.h | 47 | ||||
-rw-r--r-- | src/glibext/strbuilder.c | 89 | ||||
-rw-r--r-- | src/glibext/strbuilder.h | 46 |
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 */ |