diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2015-07-22 21:23:49 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2015-07-22 21:23:49 (GMT) |
commit | 21537636cd8318cf5a720211619ad3c3023b52e9 (patch) | |
tree | 93380a9152f18e39cf0ba427ede96533c5c6f16a /src/analysis/db/items | |
parent | 361a0953c73635c6c383516280a8d634768f8226 (diff) |
Fortified the client/server protocol and first exchanges.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@554 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/analysis/db/items')
-rw-r--r-- | src/analysis/db/items/Makefile.am | 3 | ||||
-rw-r--r-- | src/analysis/db/items/bookmark.c | 175 | ||||
-rw-r--r-- | src/analysis/db/items/bookmark.h | 7 | ||||
-rw-r--r-- | src/analysis/db/items/comment.c | 400 | ||||
-rw-r--r-- | src/analysis/db/items/comment.h | 38 | ||||
-rw-r--r-- | src/analysis/db/items/switcher.c | 755 | ||||
-rw-r--r-- | src/analysis/db/items/switcher.h | 121 |
7 files changed, 1327 insertions, 172 deletions
diff --git a/src/analysis/db/items/Makefile.am b/src/analysis/db/items/Makefile.am index f026d44..c0e6b47 100644 --- a/src/analysis/db/items/Makefile.am +++ b/src/analysis/db/items/Makefile.am @@ -3,7 +3,8 @@ noinst_LTLIBRARIES = libanalysisdbitems.la libanalysisdbitems_la_SOURCES = \ bookmark.h bookmark.c \ - comment.h comment.c + comment.h comment.c \ + switcher.h switcher.c libanalysisdbitems_la_LIBADD = diff --git a/src/analysis/db/items/bookmark.c b/src/analysis/db/items/bookmark.c index a8182ce..c9d7b7a 100644 --- a/src/analysis/db/items/bookmark.c +++ b/src/analysis/db/items/bookmark.c @@ -30,10 +30,6 @@ #include "../collection-int.h" #include "../item-int.h" -#include "../misc/rlestr.h" - - - @@ -58,7 +54,6 @@ struct _GDbBookmarkClass }; - /* Initialise la classe des signets dans une zone de texte. */ static void g_db_bookmark_class_init(GDbBookmarkClass *); @@ -71,8 +66,6 @@ static void g_db_bookmark_dispose(GDbBookmark *); /* Procède à la libération totale de la mémoire. */ static void g_db_bookmark_finalize(GDbBookmark *); - - /* Effectue la comparaison entre deux signets de collection. */ static gint g_db_bookmark_cmp(GDbBookmark *, GDbBookmark *); @@ -83,18 +76,16 @@ static bool g_db_bookmark_recv_from_fd(GDbBookmark *, int, int); static bool g_db_bookmark_send_to_fd(const GDbBookmark *, int, int); /* Constitue les champs destinés à une insertion / modification. */ -static bool g_db_bookmark_prepare_db_statement(const GDbBookmark *, bool, bound_value **, size_t *); - - +static bool g_db_bookmark_prepare_db_statement(const GDbBookmark *, bound_value **, size_t *); +/* Charge les valeurs utiles pour un signet. */ +static bool g_db_bookmark_load(GDbBookmark *, const bound_value *, size_t); /* ---------------------- DEFINITION DE LA COLLECTION ASSOCIEE ---------------------- */ - - /* Collection dédiée aux signets (instance) */ struct _GBookmarkCollection { @@ -122,12 +113,12 @@ static void g_bookmark_collection_dispose(GBookmarkCollection *); /* Procède à la libération totale de la mémoire. */ static void g_bookmark_collection_finalize(GBookmarkCollection *); +/* Crée la table des signets dans une base de données. */ +static bool g_bookmark_collection_create_db_table(const GBookmarkCollection *, sqlite3 *); + /* Décrit les colonnes utiles à un chargement de données. */ static bool g_bookmark_collection_setup_load(GBookmarkCollection *, bound_value **, size_t *); -/* Charge les valeurs utiles pour une localisation. */ -static bool g_bookmark_collection_load_item(GBookmarkCollection *, const bound_value *, size_t); - /* Détermine si un élément est déjà présent ou non. */ static GDbItem *g_bookmark_collection_has_key(GBookmarkCollection *, va_list *); @@ -172,6 +163,7 @@ static void g_db_bookmark_class_init(GDbBookmarkClass *klass) item->send = (send_db_item_fc)g_db_bookmark_send_to_fd; item->prepare_stmt = (prepare_db_statement)g_db_bookmark_prepare_db_statement; + item->load = (load_db_item_fc)g_db_bookmark_load; } @@ -227,6 +219,8 @@ static void g_db_bookmark_dispose(GDbBookmark *bookmark) static void g_db_bookmark_finalize(GDbBookmark *bookmark) { + exit_rle_string(&bookmark->comment); + G_OBJECT_CLASS(g_db_bookmark_parent_class)->finalize(G_OBJECT(bookmark)); } @@ -260,11 +254,6 @@ GDbBookmark *g_db_bookmark_new(const vmpa2t *addr, const char *comment) } - - - - - /****************************************************************************** * * * Paramètres : a = premier élément à analyser. * @@ -287,8 +276,10 @@ static gint g_db_bookmark_cmp(GDbBookmark *a, GDbBookmark *b) if (result == 0) result = cmp_rle_string(&a->comment, &b->comment); - return result; + if (result == 0) + result = G_DB_ITEM_CLASS(g_db_bookmark_parent_class)->cmp(G_DB_ITEM(a), G_DB_ITEM(b)); + return result; } @@ -314,10 +305,10 @@ static bool g_db_bookmark_recv_from_fd(GDbBookmark *bookmark, int fd, int flags) status = G_DB_ITEM_CLASS(g_db_bookmark_parent_class)->recv(G_DB_ITEM(bookmark), fd, flags); if (!status) return false; - if (!recv_vmpa(&bookmark->addr, fd, 0)) + if (!recv_vmpa(&bookmark->addr, fd, flags)) return false; - if (!recv_rle_string(&bookmark->comment, fd, 0)) + if (!recv_rle_string(&bookmark->comment, fd, flags)) return false; return true; @@ -346,10 +337,6 @@ static bool g_db_bookmark_send_to_fd(const GDbBookmark *bookmark, int fd, int fl status = G_DB_ITEM_CLASS(g_db_bookmark_parent_class)->send(G_DB_ITEM(bookmark), fd, MSG_MORE | flags); if (!status) return false; - - printf("<sending> FROM %s...\n", __FUNCTION__); - - if (!send_vmpa(&bookmark->addr, fd, MSG_MORE | flags)) return false; @@ -363,10 +350,9 @@ static bool g_db_bookmark_send_to_fd(const GDbBookmark *bookmark, int fd, int fl /****************************************************************************** * * -* Paramètres : item = base d'éléments sur laquelle s'appuyer. * -* create = indique si la préparation vise une création ou non. * -* values = couples de champs et de valeurs à lier. [OUT] * -* count = nombre de ces couples. [OUT] * +* Paramètres : bookmark = base d'éléments sur laquelle s'appuyer. * +* values = couples de champs et de valeurs à lier. [OUT] * +* count = nombre de ces couples. [OUT] * * * * Description : Constitue les champs destinés à une insertion / modification.* * * @@ -376,36 +362,51 @@ static bool g_db_bookmark_send_to_fd(const GDbBookmark *bookmark, int fd, int fl * * ******************************************************************************/ -static bool g_db_bookmark_prepare_db_statement(const GDbBookmark *bookmark, bool create, bound_value **values, size_t *count) +static bool g_db_bookmark_prepare_db_statement(const GDbBookmark *bookmark, bound_value **values, size_t *count) { bool status; /* Bilan d'opération initiale */ - bound_value *value; /* Valeur à éditer / définir */ - status = G_DB_ITEM_CLASS(g_db_bookmark_parent_class)->prepare_stmt(G_DB_ITEM(bookmark), create, values, count); + status = G_DB_ITEM_CLASS(g_db_bookmark_parent_class)->prepare_stmt(G_DB_ITEM(bookmark), values, count); if (!status) return false; - status = prepare_vmpa_db_statement(&bookmark->addr, create, values, count); + status = prepare_vmpa_db_statement(&bookmark->addr, values, count); if (!status) return false; - *values = (bound_value *)realloc(*values, ++(*count) * sizeof(bound_value)); - value = &(*values)[*count - 1]; - - value->name = "comment"; - value->type = SQLITE_TEXT; - value->cstring = g_db_bookmark_get_comment(bookmark); - value->delete = SQLITE_STATIC; + status &= prepare_db_statement_for_rle_string(&bookmark->comment, "comment", values, count); + if (!status) return false; return true; } +/****************************************************************************** +* * +* Paramètres : bookmark = bascule d'affichage à charger depuis les réponses.* +* values = tableau d'éléments à consulter. * +* count = nombre de descriptions renseignées. * +* * +* Description : Charge les valeurs utiles pour un signet. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ +static bool g_db_bookmark_load(GDbBookmark *bookmark, const bound_value *values, size_t count) +{ + bool result; /* Bilan à faire remonter */ + result = G_DB_ITEM_CLASS(g_db_bookmark_parent_class)->load(G_DB_ITEM(bookmark), values, count); + result &= load_vmpa(&bookmark->addr, values, count); + result &= load_rle_string(&bookmark->comment, "comment", values, count); + return result; +} /****************************************************************************** @@ -500,8 +501,8 @@ static void g_bookmark_collection_class_init(GBookmarkCollectionClass *klass) collec = G_DB_COLLECTION_CLASS(klass); + collec->create_table = (collec_create_db_table_fc)g_bookmark_collection_create_db_table; collec->setup_load = (collec_setup_load_fc)g_bookmark_collection_setup_load; - collec-> load_item = (collec_load_item)g_bookmark_collection_load_item; collec->has_key = (collec_has_key_fc)g_bookmark_collection_has_key; } @@ -553,7 +554,7 @@ static void g_bookmark_collection_dispose(GBookmarkCollection *collec) /****************************************************************************** * * -* Paramètres : bookmark = instance d'objet GLib à traiter. * +* Paramètres : collec = instance d'objet GLib à traiter. * * * * Description : Procède à la libération totale de la mémoire. * * * @@ -593,17 +594,10 @@ GBookmarkCollection *g_bookmark_collection_new(void) } - - - - - - - - /****************************************************************************** * * -* Paramètres : db = accès à la base de données. * +* Paramètres : collec = ensemble d'éléments spectateur des opérations. * +* db = accès à la base de données. * * * * Description : Crée la table des signets dans une base de données. * * * @@ -613,16 +607,16 @@ GBookmarkCollection *g_bookmark_collection_new(void) * * ******************************************************************************/ -bool create_bookmark_db_table(sqlite3 *db) +static bool g_bookmark_collection_create_db_table(const GBookmarkCollection *collec, sqlite3 *db) { char *sql; /* Requête à exécuter */ int ret; /* Bilan de la création */ char *msg; /* Message d'erreur */ sql = "CREATE TABLE Bookmarks (" \ - SQLITE_DB_ITEM_CREATE \ - SQLITE_VMPA_CREATE \ - "comment TEXT" \ + SQLITE_DB_ITEM_CREATE ", " \ + SQLITE_VMPA_CREATE ", " \ + SQLITE_RLESTR_CREATE("comment") \ ");"; ret = sqlite3_exec(db, sql, NULL, NULL, &msg); @@ -637,9 +631,6 @@ bool create_bookmark_db_table(sqlite3 *db) } - - - /****************************************************************************** * * * Paramètres : collec = ensemble d'éléments à consulter. * @@ -656,69 +647,19 @@ bool create_bookmark_db_table(sqlite3 *db) static bool g_bookmark_collection_setup_load(GBookmarkCollection *collec, bound_value **values, size_t *count) { - // TODO : classe supérieure + bool status; /* Bilan d'une préparation */ + + status = G_DB_COLLECTION_CLASS(g_bookmark_collection_parent_class)->setup_load(G_DB_COLLECTION(collec), \ + values, count); + if (!status) return false; if (!setup_load_for_vmpa(NULL, values, count)) return false; - *values = (bound_value *)realloc(*values, ++(*count) * sizeof(bound_value)); - - (*values)[*count - 1].name = "comment"; - - return true; - - -} - - -/****************************************************************************** -* * -* Paramètres : collec = ensemble d'éléments à compléter. * -* values = tableau d'éléments à consulter. * -* count = nombre de descriptions renseignées. * -* * -* Description : Charge les valeurs utiles pour une localisation. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_bookmark_collection_load_item(GBookmarkCollection *collec, const bound_value *values, size_t count) -{ - vmpa2t addr; /* Localisation d'un signet */ - const char *comment; /* Eventuel commentaire associé*/ - const bound_value *value; /* Valeur à intégrer */ - GDbBookmark *new; /* Nouvel élément à intégrer */ - - if (!load_vmpa(&addr, values, count)) + if (!setup_load_of_rle_string(NULL, "comment", values, count)) return false; - value = find_bound_value(values, count, "comment"); - if (value == NULL) return false; - - switch (value->type) - { - case SQLITE_TEXT: - comment = value->cstring; - break; - - case SQLITE_NULL: - comment = NULL; - break; - - default: - return false; - break; - - } - - new = g_db_bookmark_new(&addr, comment); - - printf(" LOAD new bm :: %p\n", new); - - return g_db_collection_add_item(G_DB_COLLECTION(collec), G_DB_ITEM(new)); + return true; } diff --git a/src/analysis/db/items/bookmark.h b/src/analysis/db/items/bookmark.h index de12b1b..61b2c01 100644 --- a/src/analysis/db/items/bookmark.h +++ b/src/analysis/db/items/bookmark.h @@ -35,13 +35,6 @@ -/* Crée la table des signets dans une base de données. */ -bool create_bookmark_db_table(sqlite3 *); - - - - - /* --------------------- ELABORATION D'UN ELEMENT DE COLLECTION --------------------- */ diff --git a/src/analysis/db/items/comment.c b/src/analysis/db/items/comment.c index 73a18b0..1bed0ab 100644 --- a/src/analysis/db/items/comment.c +++ b/src/analysis/db/items/comment.c @@ -28,17 +28,20 @@ #include <sys/socket.h> +#include "../collection-int.h" #include "../item-int.h" -#include "../misc/rlestr.h" +/* --------------------- ELABORATION D'UN ELEMENT DE COLLECTION --------------------- */ + + /* Commentaire à placer dans du texte quelconque (instance) */ struct _GDbComment { GDbItem parent; /* A laisser en premier */ - vmpa2t *addr; /* Adresse du commentaire */ + vmpa2t addr; /* Adresse du commentaire */ rle_string text; /* Contenu du commentaire */ }; @@ -51,7 +54,6 @@ struct _GDbCommentClass }; - /* Initialise la classe des commentaires dans une zone de texte. */ static void g_db_comment_class_init(GDbCommentClass *); @@ -73,53 +75,58 @@ static bool g_db_comment_recv_from_fd(GDbComment *, int, int); /* Exporte la définition d'un commentaire dans un flux réseau. */ static bool g_db_comment_send_to_fd(const GDbComment *, int, int); +/* Constitue les champs destinés à une insertion / modification. */ +static bool g_db_comment_prepare_db_statement(const GDbComment *, bound_value **, size_t *); +/* Charge les valeurs utiles pour un commentaire. */ +static bool g_db_comment_load(GDbComment *, const bound_value *, size_t); -/****************************************************************************** -* * -* Paramètres : db = accès à la base de données. * -* * -* Description : Crée la table des commentaires dans une base de données. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ -bool create_comment_db_table(sqlite3 *db) +/* ---------------------- DEFINITION DE LA COLLECTION ASSOCIEE ---------------------- */ + + +/* Collection dédiée aux commentaires textuels (instance) */ +struct _GCommentCollection { - char *sql; /* Requête à exécuter */ - int ret; /* Bilan de la création */ - char *msg; /* Message d'erreur */ + GDbCollection parent; /* A laisser en premier */ - sql = "CREATE TABLE Comments (" \ - "id INT PRIMARY KEY NOT NULL, " \ - "user TEXT NOT NULL, " \ - "created INT NOT NULL, " \ - "address INT NOT NULL, " \ - "comment TEXT" \ - ");"; +}; - ret = sqlite3_exec(db, sql, NULL, NULL, &msg); - if (ret != SQLITE_OK) - { - fprintf(stderr, "sqlite3_exec(): %s\n", msg); - sqlite3_free(msg); - } +/* Collection dédiée aux commentaires textuels (classe) */ +struct _GCommentCollectionClass +{ + GDbCollectionClass parent; /* A laisser en premier */ - return (ret == SQLITE_OK); +}; -} +/* Initialise la classe des commentaires sous forme de texte. */ +static void g_comment_collection_class_init(GCommentCollectionClass *); + +/* Initialise un commentaire sous forme de zone de texte. */ +static void g_comment_collection_init(GCommentCollection *); + +/* Supprime toutes les références externes. */ +static void g_comment_collection_dispose(GCommentCollection *); +/* Procède à la libération totale de la mémoire. */ +static void g_comment_collection_finalize(GCommentCollection *); +/* Crée la table des commentaires dans une base de données. */ +static bool g_comment_collection_create_db_table(const GCommentCollection *, sqlite3 *); +/* Décrit les colonnes utiles à un chargement de données. */ +static bool g_comment_collection_setup_load(GCommentCollection *, bound_value **, size_t *); +/* Détermine si un élément est déjà présent ou non. */ +static GDbItem *g_comment_collection_has_key(GCommentCollection *, va_list *); +/* ---------------------------------------------------------------------------------- */ +/* ELABORATION D'UN ELEMENT DE COLLECTION */ +/* ---------------------------------------------------------------------------------- */ /* Indique le type défini pour un commentaire à l'intérieur d'une zone de texte. */ @@ -155,6 +162,9 @@ static void g_db_comment_class_init(GDbCommentClass *klass) item->recv = (recv_db_item_fc)g_db_comment_recv_from_fd; item->send = (send_db_item_fc)g_db_comment_send_to_fd; + item->prepare_stmt = (prepare_db_statement)g_db_comment_prepare_db_statement; + item->load = (load_db_item_fc)g_db_comment_load; + } @@ -209,9 +219,7 @@ static void g_db_comment_dispose(GDbComment *comment) static void g_db_comment_finalize(GDbComment *comment) { - delete_vmpa(comment->addr); - - exit_rle_string(comment->text); + exit_rle_string(&comment->text); G_OBJECT_CLASS(g_db_comment_parent_class)->finalize(G_OBJECT(comment)); @@ -238,7 +246,7 @@ GDbComment *g_db_comment_new(const vmpa2t *addr, const char *text, bool is_volat result = g_object_new(G_TYPE_DB_COMMENT, NULL); - result->addr = dup_vmpa(addr); + copy_vmpa(&result->addr, addr); g_db_comment_set_text(result, text); @@ -266,11 +274,14 @@ static gint g_db_comment_cmp(GDbComment *a, GDbComment *b) { gint result; /* Bilan de la comparaison */ - result = cmp_vmpa_by_phy(a->addr, b->addr); + result = cmp_vmpa_by_phy(&a->addr, &b->addr); if (result == 0) result = cmp_rle_string(&a->text, &b->text); + if (result == 0) + result = G_DB_ITEM_CLASS(g_db_comment_parent_class)->cmp(G_DB_ITEM(a), G_DB_ITEM(b)); + return 0; } @@ -297,10 +308,10 @@ static bool g_db_comment_recv_from_fd(GDbComment *comment, int fd, int flags) status = G_DB_ITEM_CLASS(g_db_comment_parent_class)->recv(G_DB_ITEM(comment), fd, flags); if (!status) return false; - if (!recv_vmpa(comment->addr, fd, 0)) + if (!recv_vmpa(&comment->addr, fd, flags)) return false; - if (!recv_rle_string(&comment->text, fd, 0)) + if (!recv_rle_string(&comment->text, fd, flags)) return false; return true; @@ -329,7 +340,7 @@ static bool g_db_comment_send_to_fd(const GDbComment *comment, int fd, int flags status = G_DB_ITEM_CLASS(g_db_comment_parent_class)->send(G_DB_ITEM(comment), fd, MSG_MORE | flags); if (!status) return false; - if (!send_vmpa(comment->addr, fd, MSG_MORE | flags)) + if (!send_vmpa(&comment->addr, fd, MSG_MORE | flags)) return false; if (!send_rle_string(&comment->text, fd, flags)) @@ -342,6 +353,67 @@ static bool g_db_comment_send_to_fd(const GDbComment *comment, int fd, int flags /****************************************************************************** * * +* Paramètres : comment = base d'éléments sur laquelle s'appuyer. * +* values = couples de champs et de valeurs à lier. [OUT] * +* count = nombre de ces couples. [OUT] * +* * +* Description : Constitue les champs destinés à une insertion / modification.* +* * +* Retour : Etat du besoin en sauvegarde. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_db_comment_prepare_db_statement(const GDbComment *comment, bound_value **values, size_t *count) +{ + bool status; /* Bilan d'opération initiale */ + + status = G_DB_ITEM_CLASS(g_db_comment_parent_class)->prepare_stmt(G_DB_ITEM(comment), values, count); + if (!status) return false; + + status = prepare_vmpa_db_statement(&comment->addr, values, count); + if (!status) return false; + + status &= prepare_db_statement_for_rle_string(&comment->text, "text", values, count); + if (!status) return false; + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : comment = commentaire textuel à charger depuis les réponses. * +* values = tableau d'éléments à consulter. * +* count = nombre de descriptions renseignées. * +* * +* Description : Charge les valeurs utiles pour un commentaire. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_db_comment_load(GDbComment *comment, const bound_value *values, size_t count) +{ + bool result; /* Bilan à faire remonter */ + + result = G_DB_ITEM_CLASS(g_db_comment_parent_class)->load(G_DB_ITEM(comment), values, count); + + result &= load_vmpa(&comment->addr, values, count); + + result &= load_rle_string(&comment->text, "text", values, count); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : comment = informations à consulter. * * * * Description : Fournit l'adresse associée à un commentaire. * @@ -354,7 +426,7 @@ static bool g_db_comment_send_to_fd(const GDbComment *comment, int fd, int flags const vmpa2t *g_db_comment_get_address(GDbComment *comment) { - return comment->addr; + return &comment->addr; } @@ -396,3 +468,247 @@ void g_db_comment_set_text(GDbComment *comment, const char *text) set_rle_string(&comment->text, text); } + + + +/* ---------------------------------------------------------------------------------- */ +/* DEFINITION DE LA COLLECTION ASSOCIEE */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une collection de commentaires. */ +G_DEFINE_TYPE(GCommentCollection, g_comment_collection, G_TYPE_DB_COLLECTION); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des commentaires sous forme de texte. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_comment_collection_class_init(GCommentCollectionClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GDbCollectionClass *collec; /* Encore une autre vision... */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_comment_collection_dispose; + object->finalize = (GObjectFinalizeFunc)g_comment_collection_finalize; + + collec = G_DB_COLLECTION_CLASS(klass); + + collec->create_table = (collec_create_db_table_fc)g_comment_collection_create_db_table; + collec->setup_load = (collec_setup_load_fc)g_comment_collection_setup_load; + collec->has_key = (collec_has_key_fc)g_comment_collection_has_key; + +} + + +/****************************************************************************** +* * +* Paramètres : collec = instance à initialiser. * +* * +* Description : Initialise un commentaire sous forme de zone de texte. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_comment_collection_init(GCommentCollection *collec) +{ + + + G_DB_COLLECTION(collec)->featuring = 0; + G_DB_COLLECTION(collec)->type = G_TYPE_DB_COMMENT; + G_DB_COLLECTION(collec)->name = "Comments"; + + + +} + + +/****************************************************************************** +* * +* Paramètres : collec = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_comment_collection_dispose(GCommentCollection *collec) +{ + G_OBJECT_CLASS(g_comment_collection_parent_class)->dispose(G_OBJECT(collec)); + +} + + +/****************************************************************************** +* * +* Paramètres : collec = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_comment_collection_finalize(GCommentCollection *collec) +{ + G_OBJECT_CLASS(g_comment_collection_parent_class)->finalize(G_OBJECT(collec)); + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Crée une collection dédiée aux commentaires. * +* * +* Retour : Collection mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GCommentCollection *g_comment_collection_new(void) +{ + GCommentCollection *result; /* Instance à retourner */ + + result = g_object_new(G_TYPE_COMMENT_COLLECTION, NULL); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : collec = ensemble d'éléments spectateur des opérations. * +* db = accès à la base de données. * +* * +* Description : Crée la table des commentaires dans une base de données. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_comment_collection_create_db_table(const GCommentCollection *collec, sqlite3 *db) +{ + char *sql; /* Requête à exécuter */ + int ret; /* Bilan de la création */ + char *msg; /* Message d'erreur */ + + sql = "CREATE TABLE Comments (" \ + SQLITE_DB_ITEM_CREATE ", " \ + SQLITE_VMPA_CREATE ", " \ + SQLITE_RLESTR_CREATE("text") \ + ");"; + + ret = sqlite3_exec(db, sql, NULL, NULL, &msg); + if (ret != SQLITE_OK) + { + fprintf(stderr, "sqlite3_exec(): %s\n", msg); + sqlite3_free(msg); + } + + return (ret == SQLITE_OK); + +} + + +/****************************************************************************** +* * +* Paramètres : collec = ensemble d'éléments à consulter. * +* values = tableau d'éléments à compléter. [OUT] * +* count = nombre de descriptions renseignées. [OUT] * +* * +* Description : Décrit les colonnes utiles à un chargement de données. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_comment_collection_setup_load(GCommentCollection *collec, bound_value **values, size_t *count) +{ + bool status; /* Bilan d'une préparation */ + + status = G_DB_COLLECTION_CLASS(g_comment_collection_parent_class)->setup_load(G_DB_COLLECTION(collec), \ + values, count); + if (!status) return false; + + if (!setup_load_for_vmpa(NULL, values, count)) + return false; + + if (!setup_load_of_rle_string(NULL, "text", values, count)) + return false; + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : collec = ensemble d'éléments à consulter. * +* ap = clef identifiant de manière unique un élément. * +* * +* Description : Détermine si un élément est déjà présent ou non. * +* * +* Retour : Elément trouvé ou NULL si aucun. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GDbItem *g_comment_collection_has_key(GCommentCollection *collec, va_list *ap) +{ + GDbItem *result; /* Bilan à retourner */ + vmpa2t *ref; /* Adresse de référence */ + GList *items; /* Eléments déjà en place */ + GList *iter; /* Boucle de parcours */ + GDbComment *bm; /* Signet à consulter */ + + result = NULL; + + ref = va_arg(ap, vmpa2t *); + + items = g_db_collection_list_items(G_DB_COLLECTION(collec)); + + for (iter = g_list_first(items); iter != NULL && result == NULL; iter = g_list_next(iter)) + { + bm = G_DB_COMMENT(iter->data); + + if (cmp_vmpa(&bm->addr, ref) != 0) + + /** + * Un verrou est sensé être posé, donc il n'y a pas besoin + * de toucher au décompte des références car l'élément trouvé + * ne peut pas être supprimé. + */ + result = G_DB_ITEM(bm); + + } + + return result; + +} diff --git a/src/analysis/db/items/comment.h b/src/analysis/db/items/comment.h index 792fb92..316f4c5 100644 --- a/src/analysis/db/items/comment.h +++ b/src/analysis/db/items/comment.h @@ -35,11 +35,7 @@ -/* Crée la table des commentaires dans une base de données. */ -bool create_comment_db_table(sqlite3 *); - - - +/* --------------------- ELABORATION D'UN ELEMENT DE COLLECTION --------------------- */ #define G_TYPE_DB_COMMENT g_db_comment_get_type() @@ -74,4 +70,36 @@ void g_db_comment_set_text(GDbComment *, const char *); + + + + + + +/* ---------------------- DEFINITION DE LA COLLECTION ASSOCIEE ---------------------- */ + + +#define G_TYPE_COMMENT_COLLECTION g_comment_collection_get_type() +#define G_COMMENT_COLLECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_comment_collection_get_type(), GCommentCollection)) +#define G_IS_COMMENT_COLLECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_comment_collection_get_type())) +#define G_COMMENT_COLLECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_COMMENT_COLLECTION, GCommentCollectionClass)) +#define G_IS_COMMENT_COLLECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_COMMENT_COLLECTION)) +#define G_COMMENT_COLLECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_COMMENT_COLLECTION, GCommentCollectionClass)) + + +/* Collection dédiée aux commentaires textuels (instance) */ +typedef struct _GCommentCollection GCommentCollection; + +/* Collection dédiée aux commentaires textuels (classe) */ +typedef struct _GCommentCollectionClass GCommentCollectionClass; + + +/* Indique le type défini pour une collection de commentaires. */ +GType g_comment_collection_get_type(void); + +/* Crée une collection dédiée aux commentaires. */ +GCommentCollection *g_comment_collection_new(void); + + + #endif /* _ANALYSIS_DB_ITEMS_COMMENT_H */ diff --git a/src/analysis/db/items/switcher.c b/src/analysis/db/items/switcher.c new file mode 100644 index 0000000..5063a9c --- /dev/null +++ b/src/analysis/db/items/switcher.c @@ -0,0 +1,755 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * switcher.h - gestion des basculements d'affichage d'opérandes numériques + * + * Copyright (C) 2015 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * OpenIDA 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. + * + * OpenIDA 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 "switcher.h" + + +#include <stdio.h> +#include <sys/socket.h> + + +#include "../collection-int.h" +#include "../item-int.h" +#include "../../../common/io.h" + + + + + +/* --------------------- ELABORATION D'UN ELEMENT DE COLLECTION --------------------- */ + + +/* Bascule d'affichage pour un opérande numérique (instance) */ +struct _GDbSwitcher +{ + GDbItem parent; /* A laisser en premier */ + + vmpa2t addr; /* Adresse de l'instruction */ + size_t index; /* Indice de l'opérande visé */ + + ImmSwitchType type; /* Type de bascule */ + +}; + +/* Bascule d'affichage pour un opérande numérique (classe) */ +struct _GDbSwitcherClass +{ + GDbItemClass parent; /* A laisser en premier */ + +}; + + + +/* Initialise la classe des bascules d'affichage numérique. */ +static void g_db_switcher_class_init(GDbSwitcherClass *); + +/* Initialise une bascule d'affichage pour opérande numérique. */ +static void g_db_switcher_init(GDbSwitcher *); + +/* Supprime toutes les références externes. */ +static void g_db_switcher_dispose(GDbSwitcher *); + +/* Procède à la libération totale de la mémoire. */ +static void g_db_switcher_finalize(GDbSwitcher *); + +/* Effectue la comparaison entre deux signets de collection. */ +static gint g_db_switcher_cmp(GDbSwitcher *, GDbSwitcher *); + +/* Importe la définition d'un signet dans un flux réseau. */ +static bool g_db_switcher_recv_from_fd(GDbSwitcher *, int, int); + +/* Exporte la définition d'un signet dans un flux réseau. */ +static bool g_db_switcher_send_to_fd(const GDbSwitcher *, int, int); + +/* Constitue les champs destinés à une insertion / modification. */ +static bool g_db_switcher_prepare_db_statement(const GDbSwitcher *, bound_value **, size_t *); + +/* Charge les valeurs utiles pour un basculement d'affichage. */ +static bool g_db_switcher_load(GDbSwitcher *, const bound_value *, size_t); + + + + +/* ---------------------- DEFINITION DE LA COLLECTION ASSOCIEE ---------------------- */ + + +/* Collection dédiée aux basculements d'affichage (instance) */ +struct _GSwitcherCollection +{ + GDbCollection parent; /* A laisser en premier */ + +}; + +/* Collection dédiée aux basculements d'affichage (classe) */ +struct _GSwitcherCollectionClass +{ + GDbCollectionClass parent; /* A laisser en premier */ + +}; + + +/* Initialise la classe des signets dans une zone de texte. */ +static void g_switcher_collection_class_init(GSwitcherCollectionClass *); + +/* Initialise un signet dans une zone de texte. */ +static void g_switcher_collection_init(GSwitcherCollection *); + +/* Supprime toutes les références externes. */ +static void g_switcher_collection_dispose(GSwitcherCollection *); + +/* Procède à la libération totale de la mémoire. */ +static void g_switcher_collection_finalize(GSwitcherCollection *); + +/* Crée la table des basculements dans une base de données. */ +static bool g_switcher_collection_create_db_table(const GSwitcherCollection *, sqlite3 *); + +/* Décrit les colonnes utiles à un chargement de données. */ +static bool g_switcher_collection_setup_load(GSwitcherCollection *, bound_value **, size_t *); + +/* Détermine si un élément est déjà présent ou non. */ +static GDbItem *g_switcher_collection_has_key(GSwitcherCollection *, va_list *); + + + +/* ---------------------------------------------------------------------------------- */ +/* ELABORATION D'UN ELEMENT DE COLLECTION */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour un signet à l'intérieur d'une zone de texte. */ +G_DEFINE_TYPE(GDbSwitcher, g_db_switcher, G_TYPE_DB_ITEM); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des bascules d'affichage numérique. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_db_switcher_class_init(GDbSwitcherClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GDbItemClass *item; /* Encore une autre vision... */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_db_switcher_dispose; + object->finalize = (GObjectFinalizeFunc)g_db_switcher_finalize; + + item = G_DB_ITEM_CLASS(klass); + + item->cmp = (GCompareFunc)g_db_switcher_cmp; + + item->recv = (recv_db_item_fc)g_db_switcher_recv_from_fd; + item->send = (send_db_item_fc)g_db_switcher_send_to_fd; + + item->prepare_stmt = (prepare_db_statement)g_db_switcher_prepare_db_statement; + item->load = (load_db_item_fc)g_db_switcher_load; + +} + + +/****************************************************************************** +* * +* Paramètres : switcher = instance à initialiser. * +* * +* Description : Initialise une bascule d'affichage pour opérande numérique. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_db_switcher_init(GDbSwitcher *switcher) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : switcher = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_db_switcher_dispose(GDbSwitcher *switcher) +{ + G_OBJECT_CLASS(g_db_switcher_parent_class)->dispose(G_OBJECT(switcher)); + +} + + +/****************************************************************************** +* * +* Paramètres : switcher = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_db_switcher_finalize(GDbSwitcher *switcher) +{ + G_OBJECT_CLASS(g_db_switcher_parent_class)->finalize(G_OBJECT(switcher)); + +} + + +/****************************************************************************** +* * +* Paramètres : addr = adresse inamovible localisant une position donnée. * +* comment = commentaire construit ou NULL. * +* * +* Description : Crée une définition d'un signet dans une zone de texte. * +* * +* Retour : Signet mis en place ou NULL en cas d'erreur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDbSwitcher *g_db_switcher_new(const GArchInstruction *instr, const GImmOperand *imm, ImmSwitchType type) +{ + GDbSwitcher *result; /* Instance à retourner */ + size_t count; /* Nombre d'opérandes à visiter*/ + size_t i; /* Boucle de parcours */ + const mrange_t *range; /* Localisation de l'instruct° */ + + /* Recherche de la position de l'opérande */ + + count = g_arch_instruction_count_operands(instr); + + for (i = 0; i < count; i++) + if (G_ARCH_OPERAND(imm) == g_arch_instruction_get_operand(instr, i)) + break; + + if (i == count) + return NULL; + + /* Sauvegarde des propriétés */ + + result = g_object_new(G_TYPE_DB_SWITCHER, NULL); + + range = g_arch_instruction_get_range(instr); + copy_vmpa(&result->addr, get_mrange_addr(range)); + + result->index = i; + + result->type = type; + + /* Création d'un intitulé adapté */ + + + + //g_db_switcher_set_comment(result, comment); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : a = premier élément à analyser. * +* b = second élément à analyser. * +* * +* Description : Effectue la comparaison entre deux signets de collection. * +* * +* Retour : Bilan de la comparaison : -1, 0 ou 1. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gint g_db_switcher_cmp(GDbSwitcher *a, GDbSwitcher *b) +{ + gint result; /* Bilan de la comparaison */ + + result = cmp_vmpa(&a->addr, &b->addr); + + if (result == 0) + { + if (a->index < b->index) + result = -1; + + else if (a->index > b->index) + result = 1; + + } + + if (result == 0) + { + if (a->type < b->type) + result = -1; + + else if (a->type > b->type) + result = 1; + + } + + if (result == 0) + result = G_DB_ITEM_CLASS(g_db_switcher_parent_class)->cmp(G_DB_ITEM(a), G_DB_ITEM(b)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : switcher = bascule d'affichage aux infos à charger. [OUT] * +* fd = flux ouvert en lecture pour l'importation. * +* flags = éventuelles options d'envoi supplémentaires. * +* * +* Description : Importe la définition d'une bascule d'affichage d'opérande. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_db_switcher_recv_from_fd(GDbSwitcher *switcher, int fd, int flags) +{ + bool status; /* Bilan d'opération initiale */ + uint32_t val32; /* Valeur sur 32 bits */ + ssize_t got; /* Quantité de données reçues */ + + status = G_DB_ITEM_CLASS(g_db_switcher_parent_class)->recv(G_DB_ITEM(switcher), fd, flags); + if (!status) return false; + + if (!recv_vmpa(&switcher->addr, fd, flags)) + return false; + + got = safe_recv(fd, &val32, sizeof(uint32_t), MSG_WAITALL); + if (got != sizeof(uint32_t)) return false; + + switcher->index = be32toh(val32); + + got = safe_recv(fd, &val32, sizeof(uint32_t), MSG_WAITALL); + if (got != sizeof(uint32_t)) return false; + + switcher->type = be32toh(val32); + + if (switcher->type >= IST_COUNT) + return false; + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : switcher = bascule d'affichage aux infos à sauvegarder. * +* fd = flux ouvert en écriture pour l'exportation. * +* flags = éventuelles options d'envoi supplémentaires. * +* * +* Description : Exporte la définition d'une bascule d'affichage d'opérande. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_db_switcher_send_to_fd(const GDbSwitcher *switcher, int fd, int flags) +{ + bool status; /* Bilan d'opération initiale */ + + status = G_DB_ITEM_CLASS(g_db_switcher_parent_class)->send(G_DB_ITEM(switcher), fd, MSG_MORE | flags); + if (!status) return false; + + if (!send_vmpa(&switcher->addr, fd, MSG_MORE | flags)) + return false; + + status = safe_send(fd, (uint32_t []) { htobe32(switcher->index) }, sizeof(uint32_t), MSG_MORE | flags); + if (!status) return false; + + status = safe_send(fd, (uint32_t []) { htobe32(switcher->type) }, sizeof(uint32_t), flags); + if (!status) return false; + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : switcher = base d'éléments sur laquelle s'appuyer. * +* values = couples de champs et de valeurs à lier. [OUT] * +* count = nombre de ces couples. [OUT] * +* * +* Description : Constitue les champs destinés à une insertion / modification.* +* * +* Retour : Etat du besoin en sauvegarde. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_db_switcher_prepare_db_statement(const GDbSwitcher *switcher, bound_value **values, size_t *count) +{ + bool status; /* Bilan d'opération initiale */ + bound_value *value; /* Valeur à éditer / définir */ + + status = G_DB_ITEM_CLASS(g_db_switcher_parent_class)->prepare_stmt(G_DB_ITEM(switcher), values, count); + if (!status) return false; + + status = prepare_vmpa_db_statement(&switcher->addr, values, count); + if (!status) return false; + + *count += 2; + *values = (bound_value *)realloc(*values, *count * sizeof(bound_value)); + + value = &(*values)[*count - 2]; + + value->name = "op_index"; + value->type = SQLITE_INTEGER; + value->integer = switcher->index; + value->delete = NULL; + + value = &(*values)[*count - 2]; + + value->name = "type"; + value->type = SQLITE_INTEGER; + value->integer = switcher->type; + value->delete = NULL; + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : switcher = bascule d'affichage à charger depuis les réponses.* +* values = tableau d'éléments à consulter. * +* count = nombre de descriptions renseignées. * +* * +* Description : Charge les valeurs utiles pour un basculement d'affichage. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_db_switcher_load(GDbSwitcher *switcher, const bound_value *values, size_t count) +{ + bool result; /* Bilan à faire remonter */ + const bound_value *value; /* Valeur à éditer / définir */ + + result = G_DB_ITEM_CLASS(g_db_switcher_parent_class)->load(G_DB_ITEM(switcher), values, count); + + result &= load_vmpa(&switcher->addr, values, count); + + if (result) + { + value = find_bound_value(values, count, "op_index"); + result = (value != NULL && value->type == SQLITE_INTEGER); + + if (result) + switcher->index = value->integer; + + } + + if (result) + { + value = find_bound_value(values, count, "type"); + result = (value != NULL && value->type == SQLITE_INTEGER); + + if (result) + switcher->type = value->integer; + + } + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* DEFINITION DE LA COLLECTION ASSOCIEE */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une collection de basculements d'affichage. */ +G_DEFINE_TYPE(GSwitcherCollection, g_switcher_collection, G_TYPE_DB_COLLECTION); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des signets dans une zone de texte. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_switcher_collection_class_init(GSwitcherCollectionClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GDbCollectionClass *collec; /* Encore une autre vision... */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_switcher_collection_dispose; + object->finalize = (GObjectFinalizeFunc)g_switcher_collection_finalize; + + collec = G_DB_COLLECTION_CLASS(klass); + + collec->create_table = (collec_create_db_table_fc)g_switcher_collection_create_db_table; + collec->setup_load = (collec_setup_load_fc)g_switcher_collection_setup_load; + collec->has_key = (collec_has_key_fc)g_switcher_collection_has_key; + +} + + +/****************************************************************************** +* * +* Paramètres : collec = instance à initialiser. * +* * +* Description : Initialise un signet dans une zone de texte. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_switcher_collection_init(GSwitcherCollection *collec) +{ + + + G_DB_COLLECTION(collec)->featuring = 0; + G_DB_COLLECTION(collec)->type = G_TYPE_DB_SWITCHER; + G_DB_COLLECTION(collec)->name = "Switchers"; + + + +} + + +/****************************************************************************** +* * +* Paramètres : collec = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_switcher_collection_dispose(GSwitcherCollection *collec) +{ + G_OBJECT_CLASS(g_switcher_collection_parent_class)->dispose(G_OBJECT(collec)); + +} + + +/****************************************************************************** +* * +* Paramètres : collec = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_switcher_collection_finalize(GSwitcherCollection *collec) +{ + G_OBJECT_CLASS(g_switcher_collection_parent_class)->finalize(G_OBJECT(collec)); + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Crée une collection dédiée aux basculements d'affichage. * +* * +* Retour : Collection mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GSwitcherCollection *g_switcher_collection_new(void) +{ + GSwitcherCollection *result; /* Instance à retourner */ + + result = g_object_new(G_TYPE_SWITCHER_COLLECTION, NULL); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : collec = ensemble d'éléments spectateur des opérations. * +* db = accès à la base de données. * +* * +* Description : Crée la table des basculements dans une base de données. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_switcher_collection_create_db_table(const GSwitcherCollection *collec, sqlite3 *db) +{ + char *sql; /* Requête à exécuter */ + int ret; /* Bilan de la création */ + char *msg; /* Message d'erreur */ + + sql = "CREATE TABLE Switchers (" \ + SQLITE_DB_ITEM_CREATE ", " \ + SQLITE_VMPA_CREATE ", " \ + "op_index INTEGER, " \ + "type INTEGER" \ + ");"; + + ret = sqlite3_exec(db, sql, NULL, NULL, &msg); + if (ret != SQLITE_OK) + { + fprintf(stderr, "sqlite3_exec(): %s\n", msg); + sqlite3_free(msg); + } + + return (ret == SQLITE_OK); + +} + + +/****************************************************************************** +* * +* Paramètres : collec = ensemble d'éléments à consulter. * +* values = tableau d'éléments à compléter. [OUT] * +* count = nombre de descriptions renseignées. [OUT] * +* * +* Description : Décrit les colonnes utiles à un chargement de données. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_switcher_collection_setup_load(GSwitcherCollection *collec, bound_value **values, size_t *count) +{ + bool status; /* Bilan d'une préparation */ + + status = G_DB_COLLECTION_CLASS(g_switcher_collection_parent_class)->setup_load(G_DB_COLLECTION(collec), \ + values, count); + if (!status) return false; + + if (!setup_load_for_vmpa(NULL, values, count)) + return false; + + *count += 2; + *values = (bound_value *)realloc(*values, *count * sizeof(bound_value)); + + (*values)[*count - 2].name = "op_index"; + + (*values)[*count - 1].name = "type"; + + return true; + + +} + + +/****************************************************************************** +* * +* Paramètres : collec = ensemble d'éléments à consulter. * +* ap = clef identifiant de manière unique un élément. * +* * +* Description : Détermine si un élément est déjà présent ou non. * +* * +* Retour : Elément trouvé ou NULL si aucun. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GDbItem *g_switcher_collection_has_key(GSwitcherCollection *collec, va_list *ap) +{ + GDbItem *result; /* Bilan à retourner */ + vmpa2t *ref; /* Adresse de référence */ + GList *items; /* Eléments déjà en place */ + GList *iter; /* Boucle de parcours */ + GDbSwitcher *bm; /* Signet à consulter */ + + result = NULL; + + ref = va_arg(ap, vmpa2t *); + + items = g_db_collection_list_items(G_DB_COLLECTION(collec)); + + for (iter = g_list_first(items); iter != NULL && result == NULL; iter = g_list_next(iter)) + { + bm = G_DB_SWITCHER(iter->data); + + if (cmp_vmpa(&bm->addr, ref) != 0) + + /** + * Un verrou est sensé être posé, donc il n'y a pas besoin + * de toucher au décompte des références car l'élément trouvé + * ne peut pas être supprimé. + */ + result = G_DB_ITEM(bm); + + } + + return result; + +} diff --git a/src/analysis/db/items/switcher.h b/src/analysis/db/items/switcher.h new file mode 100644 index 0000000..a839b3a --- /dev/null +++ b/src/analysis/db/items/switcher.h @@ -0,0 +1,121 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * switcher.h - prototypes pour la gestion des basculements d'affichage d'opérandes numériques + * + * Copyright (C) 2015 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * OpenIDA 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. + * + * OpenIDA 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 _ANALYSIS_DB_ITEMS_SWITCHER_H +#define _ANALYSIS_DB_ITEMS_SWITCHER_H + + +#include <glib-object.h> +#include <sqlite3.h> +#include <stdbool.h> + + +#include "../../../arch/immediate.h" +#include "../../../arch/instruction.h" + + + +/* Crée la table des signets dans une base de données. */ +bool create_switcher_db_table(sqlite3 *); + + + + + +/* --------------------- ELABORATION D'UN ELEMENT DE COLLECTION --------------------- */ + + +/* Basculement d'affichage de valeurs immédiates */ +typedef enum _ImmSwitchType +{ + IST_DEFAULT, /* Impression par défaut */ + IST_HEXDECIMAL, /* Impression en hexadécimal */ + IST_DECIMAL, /* Impression en décimal */ + IST_OCTAL, /* Impression en octal */ + IST_BINARY, /* Impression en binaire */ + + IST_COUNT + +} ImmSwitchType; + + +#define G_TYPE_DB_SWITCHER g_db_switcher_get_type() +#define G_DB_SWITCHER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_db_switcher_get_type(), GDbSwitcher)) +#define G_IS_DB_SWITCHER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_db_switcher_get_type())) +#define G_DB_SWITCHER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DB_SWITCHER, GDbSwitcherClass)) +#define G_IS_DB_SWITCHER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DB_SWITCHER)) +#define G_DB_SWITCHER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DB_SWITCHER, GDbSwitcherClass)) + + +/* Bascule d'affichage pour un opérande numérique (instance) */ +typedef struct _GDbSwitcher GDbSwitcher; + +/* Bascule d'affichage pour un opérande numérique (classe) */ +typedef struct _GDbSwitcherClass GDbSwitcherClass; + + +/* Indique le type défini pour un signet à l'intérieur d'une zone de texte. */ +GType g_db_switcher_get_type(void); + +/* Crée une définition d'un signet dans une zone de texte. */ +GDbSwitcher *g_db_switcher_new(const GArchInstruction *, const GImmOperand *, ImmSwitchType); + +#if 0 +/* Fournit l'adresse associée à un signet. */ +const vmpa2t *g_db_switcher_get_address(GDbSwitcher *); + +/* Fournit le commentaire associé à un signet. */ +const char *g_db_switcher_get_comment(const GDbSwitcher *); + +/* Définit le commentaire associé à un signet. */ +void g_db_switcher_set_comment(GDbSwitcher *, const char *); +#endif + + +/* ---------------------- DEFINITION DE LA COLLECTION ASSOCIEE ---------------------- */ + + +#define G_TYPE_SWITCHER_COLLECTION g_switcher_collection_get_type() +#define G_SWITCHER_COLLECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_switcher_collection_get_type(), GSwitcherCollection)) +#define G_IS_SWITCHER_COLLECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_switcher_collection_get_type())) +#define G_SWITCHER_COLLECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SWITCHER_COLLECTION, GSwitcherCollectionClass)) +#define G_IS_SWITCHER_COLLECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SWITCHER_COLLECTION)) +#define G_SWITCHER_COLLECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SWITCHER_COLLECTION, GSwitcherCollectionClass)) + + +/* Collection dédiée aux basculements d'affichage (instance) */ +typedef struct _GSwitcherCollection GSwitcherCollection; + +/* Collection dédiée aux basculements d'affichage (classe) */ +typedef struct _GSwitcherCollectionClass GSwitcherCollectionClass; + + +/* Indique le type défini pour une collection de basculements d'affichage. */ +GType g_switcher_collection_get_type(void); + +/* Crée une collection dédiée aux basculements d'affichage. */ +GSwitcherCollection *g_switcher_collection_new(void); + + + +#endif /* _ANALYSIS_DB_ITEMS_SWITCH_H */ |