From 1d79469f69bba33a2280d4bd531652b71148029f Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Mon, 9 Feb 2015 22:07:42 +0000 Subject: Created a dialog box to create new bookmarks. git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@468 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a --- ChangeLog | 64 +++++++ src/analysis/binary.c | 67 +------ src/analysis/binary.h | 4 +- src/analysis/db/Makefile.am | 1 + src/analysis/db/cdb.c | 44 +++-- src/analysis/db/collection-int.h | 78 ++++++++ src/analysis/db/collection.c | 272 ++++++++++++++++++++++++---- src/analysis/db/collection.h | 28 ++- src/analysis/db/items/bookmark.c | 377 +++++++++++++++++++++++++++++++++++---- src/analysis/db/items/bookmark.h | 27 +++ src/analysis/db/server.c | 11 +- src/arch/vmpa.c | 130 ++++++++++++-- src/arch/vmpa.h | 6 + src/common/Makefile.am | 2 +- src/common/sqlite.c | 58 ++++++ src/common/sqlite.h | 6 + src/core/collections.c | 5 +- src/dialogs/Makefile.am | 1 + src/dialogs/bookmark.c | 331 ++++++++++++++++++++++++++++++++++ src/dialogs/bookmark.h | 44 +++++ src/dialogs/goto.c | 2 +- src/dlg_sections.c | 0 src/dlg_sections.h | 0 src/gtkext/easygtk.c | 40 +++++ src/gtkext/easygtk.h | 5 + src/gtkext/gtkbufferview.c | 19 ++ src/gtkext/gtkbufferview.h | 8 + src/gui/menus/edition.c | 122 ++++++++++++- src/gui/panels/bookmarks.c | 89 ++++++++- 29 files changed, 1678 insertions(+), 163 deletions(-) create mode 100644 src/analysis/db/collection-int.h create mode 100644 src/common/sqlite.c create mode 100644 src/dialogs/bookmark.c create mode 100644 src/dialogs/bookmark.h delete mode 100644 src/dlg_sections.c delete mode 100644 src/dlg_sections.h diff --git a/ChangeLog b/ChangeLog index 9b3fccd..96684d0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,69 @@ 15-02-09 Cyrille Bagard + * src/analysis/binary.c: + * src/analysis/binary.h: + Remove the old debug code registering one bookmark. Update code. + + * src/analysis/db/cdb.c: + * src/analysis/db/collection.c: + * src/analysis/db/collection.h: + Reload collections from archives and send loaded items to clients. + + * src/analysis/db/collection-int.h: + New entry: make the definitions external to allow inheritance. + + * src/analysis/db/items/bookmark.c: + * src/analysis/db/items/bookmark.h: + Define collections dedicated to bookmarks. + + * src/analysis/db/Makefile.am: + Add the 'collection-int.h' file to libanalysisdb_la_SOURCES. + + * src/analysis/db/server.c: + Send all updates to new clients using debug code. + + * src/arch/vmpa.c: + * src/arch/vmpa.h: + Fix the rendering of empty physical offsets. Load addresses from databases. + + * src/common/Makefile.am: + Add the 'sqlite.c' file to libcommon_la_SOURCES. + + * src/common/sqlite.c: + New entry: look for a given bound value. + + * src/common/sqlite.h: + Update declarations. + + * src/core/collections.c: + Write the first steps towards a new loading of collections. + + * src/dialogs/bookmark.c: + * src/dialogs/bookmark.h: + New entries: create a dialog box to create new bookmarks. + + * src/dialogs/goto.c: + Typo. + + * src/dialogs/Makefile.am: + Add the 'bookmark.[ch]' files to libdialogs_la_SOURCES. + + * src/gtkext/easygtk.c: + * src/gtkext/easygtk.h: + Provide a way to to quickly build message windows. + + * src/gtkext/gtkbufferview.c: + * src/gtkext/gtkbufferview.h: + Provide the caret location on demand. + + * src/gui/menus/edition.c: + Add a menu to toggle bookmarks. + + * src/gui/panels/bookmarks.c: + Ask to get informed about each collection content change. + +15-02-09 Cyrille Bagard + * configure.ac: Put the Python library ABI flags into LIBPYTHON_ABI_FLAGS. diff --git a/src/analysis/binary.c b/src/analysis/binary.c index 55b984a..96e774c 100644 --- a/src/analysis/binary.c +++ b/src/analysis/binary.c @@ -232,7 +232,7 @@ static void g_loaded_binary_finalize(GLoadedBinary *binary) * Remarques : - * * * ******************************************************************************/ -#include "db/items/bookmark.h" + GLoadedBinary *g_loaded_binary_new_from_xml(xmlXPathContextPtr context, const char *path) { GLoadedBinary *result; /* Adresse à retourner */ @@ -303,61 +303,6 @@ GLoadedBinary *g_loaded_binary_new_from_xml(xmlXPathContextPtr context, const ch status = g_db_client_start(result->local, host, port, author); - - - - - /* --------- %< --------- %< --------- %< --------- %< --------- */ - - do - { - vmpa2t addr; - GDbBookmark *bm; - bool status; - - - init_vmpa(&addr, 0xaeb4, VMPA_NO_VIRTUAL); - - bm = g_db_bookmark_new(&addr, "Premier commentaire"); - - - - status = g_loaded_binary_add_to_collection(result, DBF_BOOKMARKS, G_DB_ITEM(bm)); - - if (status) - printf("send OK\n"); - else - printf("send nok\n"); - - - g_db_client_save(result->local); - - - - /* - safe_send(client->fd, (uint32_t []) { htobe32(DBC_COLLECTION) }, sizeof(uint32_t), MSG_MORE); - safe_send(client->fd, (uint32_t []) { htobe32(DBF_BOOKMARKS) }, sizeof(uint32_t), MSG_MORE); - safe_send(client->fd, (uint32_t []) { htobe32(DBA_ADD_ITEM) }, sizeof(uint32_t), MSG_MORE); - - if (g_db_item_send(G_DB_ITEM(bm), client->fd, 0)) - printf("send OK\n"); - else - printf("send nok\n"); - - */ - - - } - while (0); - - /* --------- %< --------- %< --------- %< --------- %< --------- */ - - - - - - - printf("DB status :: %d\n", status); return result; @@ -394,6 +339,11 @@ bool g_loaded_binary_save(const GLoadedBinary *binary, xmlDocPtr xdoc, xmlXPathC result = g_loaded_binary_save_storage(binary, xdoc, context, path); + + //// + g_db_client_save(binary->local); + + return result; } @@ -797,6 +747,7 @@ GDbCollection *g_loaded_binary_find_collection(GLoadedBinary *binary, DBFeatures * Paramètres : binary = élément binaire à consulter. * * feature = fonctionnalité visée par la requête. * * item = élémnent à pousser vers un serveur de collection. * +* lock = indique si le verrou d'écriture doit être posé. * * * * Description : Demande l'intégration d'une modification dans une collection.* * * @@ -806,7 +757,7 @@ GDbCollection *g_loaded_binary_find_collection(GLoadedBinary *binary, DBFeatures * * ******************************************************************************/ -bool g_loaded_binary_add_to_collection(GLoadedBinary *binary, DBFeatures feature, GDbItem *item) +bool _g_loaded_binary_add_to_collection(GLoadedBinary *binary, DBFeatures feature, GDbItem *item, bool lock) { bool result; /* Bilan à faire remonter */ GDbCollection *collec; /* Collection visée au final */ @@ -819,7 +770,7 @@ bool g_loaded_binary_add_to_collection(GLoadedBinary *binary, DBFeatures feature /* S'il n'y a pas besoin de sauvegarde... */ if (g_db_item_is_volatile(item)) - g_db_collection_add_item(collec, item); + _g_db_collection_add_item(collec, item, lock); /* Sinon on envoie par le réseau ! */ else diff --git a/src/analysis/binary.h b/src/analysis/binary.h index 625ff4a..26367c4 100644 --- a/src/analysis/binary.h +++ b/src/analysis/binary.h @@ -119,8 +119,10 @@ void g_loaded_binary_set_storage(GLoadedBinary *, DBFeatures, DBStorage); GDbCollection *g_loaded_binary_find_collection(GLoadedBinary *, DBFeatures); /* Demande l'intégration d'une modification dans une collection. */ -bool g_loaded_binary_add_to_collection(GLoadedBinary *, DBFeatures, GDbItem *); +bool _g_loaded_binary_add_to_collection(GLoadedBinary *, DBFeatures, GDbItem *, bool); +#define g_loaded_binary_add_to_collection(b, f, i) \ + _g_loaded_binary_add_to_collection(b, f, i, true); diff --git a/src/analysis/db/Makefile.am b/src/analysis/db/Makefile.am index 6852821..2e8e0f1 100755 --- a/src/analysis/db/Makefile.am +++ b/src/analysis/db/Makefile.am @@ -4,6 +4,7 @@ noinst_LTLIBRARIES = libanalysisdb.la libanalysisdb_la_SOURCES = \ cdb.h cdb.c \ client.h client.c \ + collection-int.h \ collection.h collection.c \ core.h core.c \ item-int.h \ diff --git a/src/analysis/db/cdb.c b/src/analysis/db/cdb.c index 24da20e..014a6d8 100644 --- a/src/analysis/db/cdb.c +++ b/src/analysis/db/cdb.c @@ -328,7 +328,7 @@ GCdbArchive *g_cdb_archive_new(const char *owner, const rle_string *hash, const /* Ouverture de l'archive */ - if (!g_cdb_archive_read(result) && 0) + if (!g_cdb_archive_read(result)) goto gcan_error; /* Chargement des éléments sauvegardés */ @@ -712,6 +712,7 @@ static bool g_cdb_archive_create_db(const GCdbArchive *archive, const core_db_in static bool g_cdb_archive_load_collections(GCdbArchive *archive) { GList *iter; /* Boucle de parcours */ + GDbCollection *collec; /* Collection visée manipulée */ archive->collections = create_collections_list(); @@ -719,7 +720,12 @@ static bool g_cdb_archive_load_collections(GCdbArchive *archive) iter != NULL; iter = g_list_next(iter)) { - g_signal_connect(iter->data, "content-changed", G_CALLBACK(on_collection_changed), archive); + collec = G_DB_COLLECTION(iter->data); + g_signal_connect(collec, "content-changed", G_CALLBACK(on_collection_changed), archive); + + if (!g_db_collection_load_all_items(collec, archive->db)) + return false; + } return true; @@ -762,7 +768,7 @@ static void on_collection_changed(GDbCollection *collec, DBAction action, GDbIte g_mutex_unlock(&archive->clients_access); - printf("CHANGED !!\n"); + printf("CHANGED for %d clients !!\n", (int)archive->count); @@ -947,6 +953,8 @@ static void *g_cdb_archive_process(GCdbArchive *archive) DBError g_cdb_archive_add_client(GCdbArchive *archive, int fd, const rle_string *user) { + GList *iter; /* Boucle de parcours */ + GDbCollection *collec; /* Collection visée manipulée */ volatile pthread_t *process_id; /* Identifiant de la procédure */ @@ -964,6 +972,28 @@ DBError g_cdb_archive_add_client(GCdbArchive *archive, int fd, const rle_string archive->clients[archive->count - 1].fd = fd; dup_rle_string(&archive->clients[archive->count - 1].user, user); + + + /* Envoi des mises à jour au nouveau client... */ + + + for (iter = g_list_first(archive->collections); + iter != NULL; + iter = g_list_next(iter)) + { + collec = G_DB_COLLECTION(iter->data); + + if (!g_db_collection_send_all_updates(collec, fd)) + /* TODO */; + + + + + + } + + + /* Démarrage ou redémarrage du processus d'écoute */ if (archive->process == NULL) @@ -979,14 +1009,8 @@ DBError g_cdb_archive_add_client(GCdbArchive *archive, int fd, const rle_string g_mutex_unlock(&archive->clients_access); - /* Envoi des mises à jour au nouveau client... */ - - - /* TODO */ - - - return DBE_NONE; + return DBE_NONE; //// } diff --git a/src/analysis/db/collection-int.h b/src/analysis/db/collection-int.h new file mode 100644 index 0000000..6ca9ab4 --- /dev/null +++ b/src/analysis/db/collection-int.h @@ -0,0 +1,78 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * collection-int.h - prototypes et définitions internes pour les collections d'éléments + * + * 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 . + */ + + +#ifndef _ANALYSIS_DB_COLLECTION_INT_H +#define _ANALYSIS_DB_COLLECTION_INT_H + + +#include "collection.h" + + +#include + + + +/* Décrit les colonnes utiles à un chargement de données. */ +typedef bool (* collec_setup_load_fc) (GDbCollection *, bound_value **, size_t *); + +/* Charge les valeurs utiles pour une localisation. */ +typedef bool (* collec_load_item) (GDbCollection *, const bound_value *, size_t); + +/* Détermine si un élément est déjà présent ou non. */ +typedef GDbItem * (* collec_has_key_fc) (GDbCollection *, va_list *); + + + +/* Collection générique d'éléments (instance) */ +struct _GDbCollection +{ + GObject parent; /* A laisser en premier */ + + uint32_t featuring; /* Fonctionnalité représentée */ + GType type; /* Identifiant GLib équivalent */ + const char *name; /* Nom en base de données */ + + GList *items; /* Eléments rassemblés */ + GList *sorted; /* Eléments triés */ + GRWLock params_access; /* Verrou de protection */ + +}; + +/* Collection générique d'éléments (classe) */ +struct _GDbCollectionClass +{ + GObjectClass parent; /* A laisser en premier */ + + collec_setup_load_fc setup_load; /* Prépare le chargement */ + collec_load_item load_item; /* Charge un élément */ + collec_has_key_fc has_key; /* Recherche de présence */ + + /* Signaux */ + + void (* content_changed) (GDbCollection *, DBAction, GDbItem *); + +}; + + + +#endif /* _ANALYSIS_DB_COLLECTION_INT_H */ diff --git a/src/analysis/db/collection.c b/src/analysis/db/collection.c index 5c25720..84acc58 100644 --- a/src/analysis/db/collection.c +++ b/src/analysis/db/collection.c @@ -24,41 +24,19 @@ #include "collection.h" +#include +#include #include #include +#include "collection-int.h" #include "../../common/extstr.h" #include "../../common/io.h" #include "../../glibext/chrysamarshal.h" -/* Collection générique d'éléments (instance) */ -struct _GDbCollection -{ - GObject parent; /* A laisser en premier */ - - uint32_t featuring; /* Fonctionnalité représentée */ - GType type; /* Identifiant GLib équivalent */ - const char *name; /* Nom en base de données */ - - GList *items; /* Eléments rassemblés */ - GList *sorted; /* Eléments triés */ - GRWLock params_access; /* Verrou de protection */ - -}; - -/* Collection générique d'éléments (classe) */ -struct _GDbCollectionClass -{ - GObjectClass parent; /* A laisser en premier */ - - /* Signaux */ - - void (* content_changed) (GDbCollection *, DBAction, GDbItem *); - -}; @@ -80,6 +58,9 @@ static void g_db_collection_finalize(GDbCollection *); /* --------------------- MANIPULATIONS AVEC UNE BASE DE DONNEES --------------------- */ +/* Décrit les colonnes utiles à un chargement de données. */ +static bool g_db_collection_setup_load(GDbCollection *, bound_value **, size_t *); + /* Enregistre un élément de collection dans une base de données. */ static bool g_db_collection_store_item(const GDbCollection *, const GDbItem *, sqlite3 *); @@ -345,8 +326,37 @@ bool g_db_collection_send(GDbCollection *collec, int fd, DBAction action, GDbIte } +/****************************************************************************** +* * +* Paramètres : collec = ensemble d'éléments à considérer. * +* fd = flux ouvert en écriture pour l'émission de données. * +* * +* Description : Envoie pour mise à jour tous les éléments courants. * +* * +* Retour : Bilan de l'exécution de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ +bool g_db_collection_send_all_updates(GDbCollection *collec, int fd) +{ + bool result; /* Bilan à renvoyer */ + GList *iter; /* Boucle de parcours */ + + result = true; + + for (iter = g_list_first(collec->items); + iter != NULL && result; + iter = g_list_next(iter)) + { + result = g_db_collection_send(collec, fd, DBA_ADD_ITEM, G_DB_ITEM(iter->data)); + + } + + return result; +} @@ -408,17 +418,76 @@ GList *g_db_collection_list_items(const GDbCollection *collec) } +/****************************************************************************** +* * +* Paramètres : collec = ensemble d'éléments à consulter. * +* ... = 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 : - * +* * +******************************************************************************/ + +GDbItem *g_db_collection_has_key(GDbCollection *collec, ...) +{ + GDbItem *result; /* Bilan à retourner */ + va_list ap; /* Liste d'arguments en plus */ + + va_start(ap, collec); + + result = G_DB_COLLECTION_GET_CLASS(collec)->has_key(collec, &ap); + + va_end(ap); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : collec = ensemble d'éléments à consulter. * +* item = élément complet dont un double est à rechercher. * +* * +* Description : Détermine si un élément est déjà présent ou non. * +* * +* Retour : true si un élément similaire est présent dans la collection. * +* * +* Remarques : - * +* * +******************************************************************************/ +bool g_db_collection_has_item(GDbCollection *collec, GDbItem *item) +{ + bool result; /* Bilan à retourner */ + GList *found; /* Test de présence existante */ + + /** + * Un verrou doit être posé ! + * Il n'y a pas d'assert() possible pour le vérifier... + */ + + printf(" --- has\n"); + + found = g_list_find_custom(collec->items, item, (GCompareFunc)g_db_item_compare); + printf(" --- has: %p\n", found); + result = (found != NULL); + return result; +} /****************************************************************************** * * * Paramètres : collec = ensemble d'éléments à considérer. * * item = élément de collection à manipuler. * +* lock = indique si le verrou d'écriture doit être posé. * * * * Description : Procède à l'ajout d'un nouvel élément dans la collection. * * * @@ -428,12 +497,13 @@ GList *g_db_collection_list_items(const GDbCollection *collec) * * ******************************************************************************/ -bool g_db_collection_add_item(GDbCollection *collec, GDbItem *item) +bool _g_db_collection_add_item(GDbCollection *collec, GDbItem *item, bool lock) { bool result; /* Bilan à faire remonter */ GList *found; /* Test de présence existante */ - g_db_collection_wlock(collec); + if (lock) + g_db_collection_wlock(collec); found = g_list_find_custom(collec->items, item, (GCompareFunc)g_db_item_compare); @@ -451,14 +521,15 @@ bool g_db_collection_add_item(GDbCollection *collec, GDbItem *item) g_signal_emit_by_name(collec, "content-changed", DBA_ADD_ITEM, item); - printf(" ==== CONTENT CHANGED !!!\n"); + printf(" ==== CONTENT CHANGED (-> %u) !!!\n", g_list_length(collec->items)); result = true; } - g_db_collection_wunlock(collec); + if (lock) + g_db_collection_wunlock(collec); return result; @@ -469,6 +540,7 @@ bool g_db_collection_add_item(GDbCollection *collec, GDbItem *item) * * * Paramètres : collec = ensemble d'éléments à considérer. * * item = élément de collection à copier. * +* lock = indique si le verrou d'écriture doit être posé. * * * * Description : Procède à la modification d'un élément dans la collection. * * * @@ -478,7 +550,7 @@ bool g_db_collection_add_item(GDbCollection *collec, GDbItem *item) * * ******************************************************************************/ -bool g_db_collection_modify_item(GDbCollection *collec, GDbItem *item) +bool _g_db_collection_modify_item(GDbCollection *collec, GDbItem *item, bool lock) { bool result; /* Bilan à faire remonter */ GList *found; /* Test de présence existante */ @@ -499,15 +571,151 @@ bool g_db_collection_modify_item(GDbCollection *collec, GDbItem *item) - /* ---------------------------------------------------------------------------------- */ -/* CREATION DE L'ABSTRACTION POUR COLLECTIONS */ /* MANIPULATIONS AVEC UNE BASE DE DONNEES */ /* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * +* 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_db_collection_setup_load(GDbCollection *collec, bound_value **values, size_t *count) +{ + *values = NULL; + *count = 0; + + return G_DB_COLLECTION_GET_CLASS(collec)->setup_load(collec, values, count); + +} + + +/****************************************************************************** +* * +* Paramètres : collec = ensemble d'éléments à peupler. * +* db = base de données repondant aux requêtes. * +* * +* Description : Charge un ensemble d'éléments à partir d'une base de données.* +* * +* Retour : Bilan de l'exécution de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_db_collection_load_all_items(GDbCollection *collec, sqlite3 *db) +{ + bool result; /* Conclusion à faire remonter */ + bound_value *values; /* Champs de table à inclure */ + size_t count; /* Nombre de ces champs */ + char *sql; /* Requête SQL à construire */ + size_t i; /* Boucle de parcours */ + sqlite3_stmt *stmt; /* Déclaration mise en place */ + int ret; /* Bilan d'un appel à SQLite */ + + if (!g_db_collection_setup_load(collec, &values, &count)) + return false; + + result = false; + + /* Préparation de la requête */ + + sql = strdup("SELECT "); + + for (i = 0; i < count; i++) + { + if (i > 0) sql = stradd(sql, ", "); + + sql = stradd(sql, values[i].name); + + } + + sql = stradd(sql, " FROM "); + sql = stradd(sql, collec->name); + sql = stradd(sql, ";"); + + ret = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL); + if (ret != SQLITE_OK) + { + fprintf(stderr, "Can't prepare SELECT statment '%s' (ret=%d): %s\n", sql, ret, sqlite3_errmsg(db)); + goto gdclai_exit; + } + + /* Chargement des valeurs existantes */ + + result = true; + + for (ret = sqlite3_step(stmt); ret == SQLITE_ROW && result; ret = sqlite3_step(stmt)) + { + /* Conversion des valeurs */ + + for (i = 0; i < count; i++) + { + values[i].type = sqlite3_column_type(stmt, i); + + switch (values[i].type) + { + case SQLITE_INTEGER: + values[i].type = SQLITE_INT64; + values[i].integer64 = sqlite3_column_int64(stmt, i); + break; + + case SQLITE_FLOAT: + assert(0); /* TODO */ + break; + + case SQLITE_TEXT: + values[i].cstring = (const char *)sqlite3_column_text(stmt, i); + break; + + case SQLITE_BLOB: + assert(0); /* TODO */ + break; + + case SQLITE_NULL: + break; + + default: + assert(0); + break; + + } + + } + + /* Chargement d'un nouvel élément */ + + result = G_DB_COLLECTION_GET_CLASS(collec)->load_item(collec, values, count); + + } + + /* Sortie propre */ + + sqlite3_finalize(stmt); + + gdclai_exit: + + free(sql); + + printf("LOAD ? %d\n", result); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : collec = ensemble d'éléments à considérer. * * item = élément de collection à enregistrer. * * db = base de données à mettre à jour. * diff --git a/src/analysis/db/collection.h b/src/analysis/db/collection.h index b400820..268c2be 100644 --- a/src/analysis/db/collection.h +++ b/src/analysis/db/collection.h @@ -39,10 +39,14 @@ #define G_TYPE_DB_COLLECTION g_db_collection_get_type() #define G_DB_COLLECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_db_collection_get_type(), GDbCollection)) #define G_IS_DB_COLLECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_db_collection_get_type())) -#define G_DB_COLLECTION_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_db_collection_get_type(), GDbCollectionIface)) +#define G_DB_COLLECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DB_COLLECTION, GDbCollectionClass)) +#define G_IS_DB_COLLECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DB_COLLECTION)) #define G_DB_COLLECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DB_COLLECTION, GDbCollectionClass)) + + + /* Collection générique d'éléments (instance) */ typedef struct _GDbCollection GDbCollection; @@ -70,7 +74,8 @@ bool g_db_collection_recv(GDbCollection *, int, sqlite3 *); /* Envoie pour traitement une requête réseau pour collection. */ bool g_db_collection_send(GDbCollection *, int, DBAction, GDbItem *); - +/* Envoie pour mise à jour tous les éléments courants. */ +bool g_db_collection_send_all_updates(GDbCollection *, int); @@ -89,15 +94,28 @@ void g_db_collection_lock_unlock(GDbCollection *, bool, bool); /* Renvoie la liste des éléments rassemblés. */ GList *g_db_collection_list_items(const GDbCollection *); +/* Détermine si un élément est déjà présent ou non. */ +GDbItem *g_db_collection_has_key(GDbCollection *, ...); - +/* Détermine si un élément est déjà présent ou non. */ +bool g_db_collection_has_item(GDbCollection *, GDbItem *); /* Procède à l'ajout d'un nouvel élément dans la collection. */ -bool g_db_collection_add_item(GDbCollection *, GDbItem *); +bool _g_db_collection_add_item(GDbCollection *, GDbItem *, bool); /* Procède à la modification d'un élément dans la collection. */ -bool g_db_collection_modify_item(GDbCollection *, GDbItem *); +bool _g_db_collection_modify_item(GDbCollection *, GDbItem *, bool); + +#define g_db_collection_add_item(c, i) _g_db_collection_add_item(c, i, true) +#define g_db_collection_modify_item(c, i) _g_db_collection_modify_item(c, i, true) + + + +/* --------------------- MANIPULATIONS AVEC UNE BASE DE DONNEES --------------------- */ + +/* Charge un ensemble d'éléments à partir d'une base de données. */ +bool g_db_collection_load_all_items(GDbCollection *, sqlite3 *); diff --git a/src/analysis/db/items/bookmark.c b/src/analysis/db/items/bookmark.c index 6ff386c..a8182ce 100644 --- a/src/analysis/db/items/bookmark.c +++ b/src/analysis/db/items/bookmark.c @@ -28,11 +28,18 @@ #include +#include "../collection-int.h" #include "../item-int.h" #include "../misc/rlestr.h" + + + +/* --------------------- ELABORATION D'UN ELEMENT DE COLLECTION --------------------- */ + + /* Signet à l'intérieur d'une zone de texte (instance) */ struct _GDbBookmark { @@ -81,48 +88,54 @@ static bool g_db_bookmark_prepare_db_statement(const GDbBookmark *, bool, bound_ -/****************************************************************************** -* * -* Paramètres : db = accès à la base de données. * -* * -* Description : Crée la table des signets dans une base de données. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ -bool create_bookmark_db_table(sqlite3 *db) + +/* ---------------------- DEFINITION DE LA COLLECTION ASSOCIEE ---------------------- */ + + + + +/* Collection dédiée aux signets (instance) */ +struct _GBookmarkCollection { - 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 Bookmarks (" \ - SQLITE_DB_ITEM_CREATE \ - SQLITE_VMPA_CREATE \ - "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 signets (classe) */ +struct _GBookmarkCollectionClass +{ + GDbCollectionClass parent; /* A laisser en premier */ - return (ret == SQLITE_OK); +}; -} +/* Initialise la classe des signets dans une zone de texte. */ +static void g_bookmark_collection_class_init(GBookmarkCollectionClass *); +/* Initialise un signet dans une zone de texte. */ +static void g_bookmark_collection_init(GBookmarkCollection *); +/* Supprime toutes les références externes. */ +static void g_bookmark_collection_dispose(GBookmarkCollection *); + +/* Procède à la libération totale de la mémoire. */ +static void g_bookmark_collection_finalize(GBookmarkCollection *); + +/* 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 *); +/* ---------------------------------------------------------------------------------- */ +/* ELABORATION D'UN ELEMENT DE COLLECTION */ +/* ---------------------------------------------------------------------------------- */ /* Indique le type défini pour un signet à l'intérieur d'une zone de texte. */ @@ -269,12 +282,12 @@ static gint g_db_bookmark_cmp(GDbBookmark *a, GDbBookmark *b) { gint result; /* Bilan de la comparaison */ - result = cmp_vmpa_by_phy(&a->addr, &b->addr); + result = cmp_vmpa(&a->addr, &b->addr); if (result == 0) result = cmp_rle_string(&a->comment, &b->comment); - return 0; + return result; } @@ -451,3 +464,307 @@ void g_db_bookmark_set_comment(GDbBookmark *bookmark, const char *comment) set_rle_string(&bookmark->comment, comment); } + + + +/* ---------------------------------------------------------------------------------- */ +/* DEFINITION DE LA COLLECTION ASSOCIEE */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une collection de signets. */ +G_DEFINE_TYPE(GBookmarkCollection, g_bookmark_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_bookmark_collection_class_init(GBookmarkCollectionClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GDbCollectionClass *collec; /* Encore une autre vision... */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_bookmark_collection_dispose; + object->finalize = (GObjectFinalizeFunc)g_bookmark_collection_finalize; + + collec = G_DB_COLLECTION_CLASS(klass); + + 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; + +} + + +/****************************************************************************** +* * +* Paramètres : collec = instance à initialiser. * +* * +* Description : Initialise un signet dans une zone de texte. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_bookmark_collection_init(GBookmarkCollection *collec) +{ + + + G_DB_COLLECTION(collec)->featuring = 0; + G_DB_COLLECTION(collec)->type = G_TYPE_DB_BOOKMARK; + G_DB_COLLECTION(collec)->name = "Bookmarks"; + + + +} + + +/****************************************************************************** +* * +* Paramètres : collec = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_bookmark_collection_dispose(GBookmarkCollection *collec) +{ + G_OBJECT_CLASS(g_bookmark_collection_parent_class)->dispose(G_OBJECT(collec)); + +} + + +/****************************************************************************** +* * +* Paramètres : bookmark = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_bookmark_collection_finalize(GBookmarkCollection *collec) +{ + G_OBJECT_CLASS(g_bookmark_collection_parent_class)->finalize(G_OBJECT(collec)); + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Crée une collection dédiée aux signets. * +* * +* Retour : Collection mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBookmarkCollection *g_bookmark_collection_new(void) +{ + GBookmarkCollection *result; /* Instance à retourner */ + + result = g_object_new(G_TYPE_BM_COLLECTION, NULL); + + return result; + +} + + + + + + + + + + +/****************************************************************************** +* * +* Paramètres : db = accès à la base de données. * +* * +* Description : Crée la table des signets dans une base de données. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool create_bookmark_db_table(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" \ + ");"; + + 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_bookmark_collection_setup_load(GBookmarkCollection *collec, bound_value **values, size_t *count) +{ + // TODO : classe supérieure + + 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)) + 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)); + +} + + +/****************************************************************************** +* * +* 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_bookmark_collection_has_key(GBookmarkCollection *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 */ + GDbBookmark *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_BOOKMARK(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/bookmark.h b/src/analysis/db/items/bookmark.h index cd5e202..de12b1b 100644 --- a/src/analysis/db/items/bookmark.h +++ b/src/analysis/db/items/bookmark.h @@ -42,6 +42,7 @@ bool create_bookmark_db_table(sqlite3 *); +/* --------------------- ELABORATION D'UN ELEMENT DE COLLECTION --------------------- */ #define G_TYPE_DB_BOOKMARK g_db_bookmark_get_type() @@ -76,4 +77,30 @@ void g_db_bookmark_set_comment(GDbBookmark *, const char *); +/* ---------------------- DEFINITION DE LA COLLECTION ASSOCIEE ---------------------- */ + + +#define G_TYPE_BM_COLLECTION g_bookmark_collection_get_type() +#define G_BM_COLLECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_bookmark_collection_get_type(), GBookmarkCollection)) +#define G_IS_BM_COLLECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_bookmark_collection_get_type())) +#define G_BM_COLLECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BM_COLLECTION, GBookmarkCollectionClass)) +#define G_IS_BM_COLLECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BM_COLLECTION)) +#define G_BM_COLLECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BM_COLLECTION, GBookmarkCollectionClass)) + + +/* Collection dédiée aux signets (instance) */ +typedef struct _GBookmarkCollection GBookmarkCollection; + +/* Collection dédiée aux signets (classe) */ +typedef struct _GBookmarkCollectionClass GBookmarkCollectionClass; + + +/* Indique le type défini pour une collection de signets. */ +GType g_bookmark_collection_get_type(void); + +/* Crée une collection dédiée aux signets. */ +GBookmarkCollection *g_bookmark_collection_new(void); + + + #endif /* _ANALYSIS_DB_ITEMS_BOOKMARK_H */ diff --git a/src/analysis/db/server.c b/src/analysis/db/server.c index 42688c8..04b0dc4 100644 --- a/src/analysis/db/server.c +++ b/src/analysis/db/server.c @@ -365,8 +365,10 @@ static void *g_db_server_listener(GDbServer *server) } + /* if (archive != NULL) error = g_cdb_archive_add_client(archive, fd, &user); + */ /** * Le serveur doit répondre pour un message type : @@ -382,7 +384,14 @@ static void *g_db_server_listener(GDbServer *server) if (!safe_send(fd, (uint32_t []) { htobe32(error) }, sizeof(uint32_t), 0)) goto gdsl_error; - if (error == DBE_NONE) continue; + //if (error == DBE_NONE) continue; + + + if (archive != NULL) + error = g_cdb_archive_add_client(archive, fd, &user); + + + gdsl_error: diff --git a/src/arch/vmpa.c b/src/arch/vmpa.c index 46d1a04..c479319 100644 --- a/src/arch/vmpa.c +++ b/src/arch/vmpa.c @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -356,29 +357,33 @@ char *vmpa2_phys_to_string(const vmpa2t *addr, MemoryDataSize msize, char buffer { size_t ret; /* Retour de l'impression */ - switch (msize) - { - case MDS_8_BITS: - ret = snprintf(buffer, VMPA_MAX_LEN,"0x%02" PRIx64, (uint64_t)addr->physical); - break; + if (addr->physical == VMPA_NO_PHYSICAL) + ret = snprintf(buffer, VMPA_MAX_LEN, _("(none)")); - case MDS_16_BITS: - ret = snprintf(buffer, VMPA_MAX_LEN, "0x%04" PRIx64, (uint64_t)addr->physical); - break; + else + switch (msize) + { + case MDS_8_BITS: + ret = snprintf(buffer, VMPA_MAX_LEN,"0x%02" PRIx64, (uint64_t)addr->physical); + break; - case MDS_32_BITS: - ret = snprintf(buffer, VMPA_MAX_LEN, "0x%08" PRIx64, (uint64_t)addr->physical); - break; + case MDS_16_BITS: + ret = snprintf(buffer, VMPA_MAX_LEN, "0x%04" PRIx64, (uint64_t)addr->physical); + break; - case MDS_64_BITS: - ret = snprintf(buffer, VMPA_MAX_LEN, "0x%016" PRIx64, (uint64_t)addr->physical); - break; + case MDS_32_BITS: + ret = snprintf(buffer, VMPA_MAX_LEN, "0x%08" PRIx64, (uint64_t)addr->physical); + break; - default: - ret = snprintf(buffer, VMPA_MAX_LEN, "0x%" PRIx64, (uint64_t)addr->physical); - break; + case MDS_64_BITS: + ret = snprintf(buffer, VMPA_MAX_LEN, "0x%016" PRIx64, (uint64_t)addr->physical); + break; - } + default: + ret = snprintf(buffer, VMPA_MAX_LEN, "0x%" PRIx64, (uint64_t)addr->physical); + break; + + } if (length != NULL) *length = ret; @@ -491,6 +496,95 @@ vmpa2t *string_to_vmpa_virt(const char *buffer) /****************************************************************************** * * +* Paramètres : addr = localisation dont la définition est à 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 : - * +* * +******************************************************************************/ + +bool setup_load_for_vmpa(const vmpa2t *addr, bound_value **values, size_t *count) +{ + (*count) += 2; + + *values = (bound_value *)realloc(*values, (*count) * sizeof(bound_value)); + + (*values)[*count - 2].name = "phys"; + (*values)[*count - 1].name = "virt"; + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : addr = localisation dont la définition est à définir. * +* 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 : - * +* * +******************************************************************************/ + +bool load_vmpa(vmpa2t *addr, const bound_value *values, size_t count) +{ + const bound_value *value; /* Valeur à intégrer */ + + value = find_bound_value(values, count, "phys"); + if (value == NULL) return false; + + switch (value->type) + { + case SQLITE_INT64: + addr->physical = value->integer64; + break; + + case SQLITE_NULL: + addr->physical = VMPA_NO_PHYSICAL; + break; + + default: + return false; + break; + + } + + value = find_bound_value(values, count, "virt"); + if (value == NULL) return false; + + switch (value->type) + { + case SQLITE_INT64: + addr->virtual = value->integer64; + break; + + case SQLITE_NULL: + addr->virtual = VMPA_NO_VIRTUAL; + break; + + default: + return false; + break; + + } + + return true; + +} + + +/****************************************************************************** +* * * Paramètres : addr = adresse virtuelle ou physique à traiter. * * create = indique si la préparation vise une création ou non. * * values = couples de champs et de valeurs à lier. [OUT] * diff --git a/src/arch/vmpa.h b/src/arch/vmpa.h index 97b2610..ec356c8 100644 --- a/src/arch/vmpa.h +++ b/src/arch/vmpa.h @@ -126,6 +126,12 @@ vmpa2t *string_to_vmpa_virt(const char *); "phys INTEGER, " \ "virt INTEGER, " +/* Décrit les colonnes utiles à un chargement de données. */ +bool setup_load_for_vmpa(const vmpa2t *, bound_value **, size_t *); + +/* Charge les valeurs utiles pour une localisation. */ +bool load_vmpa(vmpa2t *, const bound_value *, size_t); + /* Constitue les champs destinés à une insertion / modification. */ bool prepare_vmpa_db_statement(const vmpa2t *, bool, bound_value **, size_t *); diff --git a/src/common/Makefile.am b/src/common/Makefile.am index 7615f43..1ab4768 100755 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -14,7 +14,7 @@ libcommon_la_SOURCES = \ leb128.h leb128.c \ macros.h \ net.h net.c \ - sqlite.h \ + sqlite.h sqlite.c \ xdg.h xdg.c \ xml.h xml.c diff --git a/src/common/sqlite.c b/src/common/sqlite.c new file mode 100644 index 0000000..ec3c280 --- /dev/null +++ b/src/common/sqlite.c @@ -0,0 +1,58 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * sqlite.c - extension des définitions propres à SQLite + * + * 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 . + */ + + +#include "sqlite.h" + + +#include + + + +/****************************************************************************** +* * +* Paramètres : values = tableau d'éléments à consulter. * +* count = nombre de descriptions renseignées. * +* name = désignation de la valeur recherchée. * +* * +* Description : Effectue une recherche au sein d'un ensemble de valeurs. * +* * +* Retour : Elément retrouvé ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const bound_value *find_bound_value(const bound_value *values, size_t count, const char *name) +{ + const bound_value *result; /* Trouvaille à retourner */ + size_t i; /* Boucle de parcours */ + + result = NULL; + + for (i = 0; i < count && result == NULL; i++) + if (strcmp(values[i].name, name) == 0) + result = &values[i]; + + return result; + +} diff --git a/src/common/sqlite.h b/src/common/sqlite.h index 66fb773..559af38 100644 --- a/src/common/sqlite.h +++ b/src/common/sqlite.h @@ -26,6 +26,8 @@ #include +#include + /* Type pour les insertions brutes */ @@ -52,5 +54,9 @@ typedef struct _bound_value } bound_value; +/* Effectue une recherche au sein d'un ensemble de valeurs. */ +const bound_value *find_bound_value(const bound_value *, size_t, const char *); + + #endif /* _COMMON_SQLITE_H */ diff --git a/src/core/collections.c b/src/core/collections.c index 80d2ae3..c867d57 100644 --- a/src/core/collections.c +++ b/src/core/collections.c @@ -109,7 +109,7 @@ bool load_hard_coded_collection_definitions(void) * afin de garder la correspondance entre les identifiants. */ - id = register_collection_type(G_TYPE_DB_BOOKMARK, create_bookmark_db_table); + id = register_collection_type(G_TYPE_BM_COLLECTION, create_bookmark_db_table); assert(id == DBF_BOOKMARKS); return true; @@ -164,7 +164,8 @@ GList *create_collections_list(void) for (i = 0; i < _collection_definitions_count; i++) { def = &_collection_definitions[i]; - collec = g_db_collection_new(i, def->items, "Bookmarks"); + //collec = g_db_collection_new(i, def->items, "Bookmarks"); + collec = g_object_new(def->items, NULL); result = g_list_append(result, collec); diff --git a/src/dialogs/Makefile.am b/src/dialogs/Makefile.am index 9adb0f6..54b6fa2 100644 --- a/src/dialogs/Makefile.am +++ b/src/dialogs/Makefile.am @@ -3,6 +3,7 @@ noinst_LTLIBRARIES = libdialogs.la libdialogs_la_SOURCES = \ about.h about.c \ + bookmark.h bookmark.c \ export.h export.c \ goto.h goto.c \ plugins.h plugins.c \ diff --git a/src/dialogs/bookmark.c b/src/dialogs/bookmark.c new file mode 100644 index 0000000..abff500 --- /dev/null +++ b/src/dialogs/bookmark.c @@ -0,0 +1,331 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * bookmark.c - boîte de dialogue pour les sauts à une adresse donnée + * + * Copyright (C) 2012-2014 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 . + */ + + +#include "bookmark.h" + + +#include +#include + + +#include + + +#include "..//analysis/db/items/bookmark.h" +#include "../gtkext/easygtk.h" + + + +/* Filtre les adresses en hexadécimal pendant l'édition. */ +static void filter_addresses(GtkEntry *, const gchar *, gint, gint *, gpointer); + +/* Clôture l'édition d'une adresse. */ +static void validate_addresses(GtkEntry *, GtkDialog *); + + + +/****************************************************************************** +* * +* Paramètres : entry = composant GTK concerné par la procédure. * +* text = nouveau texte inséré. * +* length = taille de ce texte. * +* position = point d'insertion. * +* data = adresse non utilisée ici. * +* * +* Description : Filtre les adresses en hexadécimal pendant l'édition. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void filter_addresses(GtkEntry *entry, const gchar *text, gint length, gint *position, gpointer data) +{ + gboolean has_hex; /* Préfixe '0x' déjà présent ? */ + gchar *filtered; /* Contenu nouveau approuvé */ + gint count; /* Nouvelle taille validée */ + gint i; /* Boucle de parcours */ + + /** + * On cherche à empêcher l'édition avant un '0x' présent, + * ce qui viendrait fausser le fitrage. + */ + has_hex = g_str_has_prefix(gtk_entry_get_text(entry), "0x"); + + filtered = g_new(gchar, length); + + count = 0; + + for (i = 0; i < length; i++) + switch (text[i]) + { + case '0' ... '9': + case 'a' ... 'f': + if (!has_hex || ((i + *position) >= 2)) + filtered[count++] = text[i]; + break; + case 'A' ... 'F': + if (!has_hex || ((i + *position) >= 2)) + filtered[count++] = tolower(text[i]); + break; + case 'x': + case 'X': + if ((i + *position) == 1) + filtered[count++] = 'x'; + break; + } + + if (count > 0) + { + g_signal_handlers_block_by_func(G_OBJECT(entry), G_CALLBACK(filter_addresses), data); + gtk_editable_insert_text(GTK_EDITABLE(entry), filtered, count, position); + g_signal_handlers_unblock_by_func(G_OBJECT(entry), G_CALLBACK(filter_addresses), data); + } + + g_signal_stop_emission_by_name(G_OBJECT(entry), "insert_text"); + + g_free(filtered); + +} + + +/****************************************************************************** +* * +* Paramètres : entry = composant GTK concerné par la procédure. * +* dialog = boîte de dialogue à valider. * +* * +* Description : Clôture l'édition d'une adresse. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void validate_addresses(GtkEntry *entry, GtkDialog *dialog) +{ + gtk_dialog_response(dialog, GTK_RESPONSE_OK); + +} + + +/****************************************************************************** +* * +* Paramètres : parent = fenêtre parente à surpasser. * +* addr = localisation du point à consigner. * +* * +* Description : Construit la fenêtre de création de signet. * +* * +* Retour : Adresse de la fenêtre mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GtkWidget *create_bookmark_dialog(GtkWindow *parent, const vmpa2t *addr) +{ + GtkWidget *result; /* Fenêtre à renvoyer */ + GtkWidget *dlgvbox; /* Zone principale de la boîte */ + GtkWidget *vbox; /* Support à construire #1 */ + GtkWidget *alignment; /* Support véritable interne */ + GtkWidget *frame; /* Support avec encadrement */ + GtkWidget *sub_vbox; /* Support à construire #2 */ + GtkWidget *hbox; /* Support à construire #3 */ + GtkWidget *label; /* Message d'introduction */ + GtkWidget *entry; /* Zone de saisie principale */ + GtkWidget *radio; /* Définition de localisation */ + VMPA_BUFFER(target); /* Désignation humaine de cible*/ + + result = gtk_dialog_new(); + gtk_window_set_title(GTK_WINDOW(result), _("Add a bookmark")); + gtk_window_set_position(GTK_WINDOW(result), GTK_WIN_POS_CENTER); + gtk_window_set_modal(GTK_WINDOW(result), TRUE); + gtk_window_set_type_hint(GTK_WINDOW(result), GDK_WINDOW_TYPE_HINT_DIALOG); + + dlgvbox = gtk_dialog_get_content_area(GTK_DIALOG(result)); + gtk_widget_show(dlgvbox); + + vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8); + gtk_widget_show(vbox); + gtk_box_pack_start(GTK_BOX(dlgvbox), vbox, TRUE, TRUE, 0); + gtk_container_set_border_width(GTK_CONTAINER(vbox), 8); + + /* Localisation dans l'espace */ + + frame = qck_create_frame(_("Localisation"), &alignment, 8, 0, 12, 0); + gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0); + + sub_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8); + gtk_widget_show(sub_vbox); + gtk_container_add(GTK_CONTAINER(alignment), sub_vbox); + + /* 1) Adresse */ + + hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8); + gtk_widget_show(hbox); + gtk_box_pack_start(GTK_BOX(sub_vbox), hbox, FALSE, TRUE, 0); + + label = qck_create_label(NULL, NULL, _("Target:")); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + + entry = qck_create_entry(G_OBJECT(result), "addr", NULL); + //g_signal_connect(G_OBJECT(entry), "changed", G_CALLBACK(forbid_text_empty_entry), assistant); + gtk_box_pack_start(GTK_BOX(hbox), entry, FALSE, TRUE, 0); + + /* 2) Type d'adresse */ + + hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8); + gtk_widget_show(hbox); + gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0); + gtk_container_set_border_width(GTK_CONTAINER(hbox), 8); + + radio = qck_create_radio_button(G_OBJECT(result), "phys", _("Value is physical offset"), + NULL, NULL, NULL); + gtk_box_pack_start(GTK_BOX(hbox), radio, TRUE, TRUE, 0); + + radio = qck_create_radio_button(G_OBJECT(result), "virt", _("Value is virtual address"), + GTK_RADIO_BUTTON(radio), NULL, NULL); + gtk_box_pack_start(GTK_BOX(hbox), radio, TRUE, TRUE, 0); + + /* Commentaire éventuel */ + + frame = qck_create_frame(_("Optional comment"), &alignment, 8, 0, 12, 0); + gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0); + + entry = qck_create_entry(G_OBJECT(result), "comment", NULL); + gtk_container_add(GTK_CONTAINER(alignment), entry); + + /* Zone de validation */ + + gtk_dialog_add_button(GTK_DIALOG(result), _("_Cancel"), GTK_RESPONSE_CANCEL); + gtk_dialog_add_button(GTK_DIALOG(result), _("_Ok"), GTK_RESPONSE_OK); + + /* Remplissage avec les valeurs fournies */ + + entry = GTK_WIDGET(g_object_get_data(G_OBJECT(result), "addr")); + + if (addr != NULL && has_virt_addr(addr)) + { + vmpa2_virt_to_string(addr, MDS_UNDEFINED, target, NULL); + radio = GTK_WIDGET(g_object_get_data(G_OBJECT(result), "virt")); + } + + else if (addr != NULL && has_phys_addr(addr)) + { + vmpa2_virt_to_string(addr, MDS_UNDEFINED, target, NULL); + radio = GTK_WIDGET(g_object_get_data(G_OBJECT(result), "virt")); + } + + else + radio = NULL; + + if (radio == NULL) + { + gtk_entry_set_text(GTK_ENTRY(entry), "0x"); + gtk_editable_set_position(GTK_EDITABLE(entry), -1); + gtk_widget_grab_focus(entry); + } + + else + { + gtk_entry_set_text(GTK_ENTRY(entry), target); + gtk_editable_set_position(GTK_EDITABLE(entry), -1); + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), TRUE); + + } + + if (radio != NULL) + { + entry = GTK_WIDGET(g_object_get_data(G_OBJECT(result), "comment")); + gtk_widget_grab_focus(entry); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : dialog = boîte de dialogue ayant reçu une validation. * +* * +* Description : Fournit le signet conçu via la saisie de l'utilisateur. * +* * +* Retour : Adresse reccueillie par la boîte de dialogue. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDbItem *get_item_from_bookmark_dialog(GtkWidget *dialog) +{ + GDbItem *result; /* Signet nouveau à retourner */ + GObject *ref; /* Espace de référencements */ + vmpa2t *orig; /* Copie de valeur originale */ + vmpa2t addr; /* Localisation finale utilisée*/ + GtkWidget *entry; /* Zone de saisie principale */ + const gchar *text; /* Adresse en version texte */ + GtkToggleButton *radio; /* Définition de localisation */ + + ref = G_OBJECT(dialog); + + /* Si la valeur d'origine a été conservée intacte... */ + + orig = (vmpa2t *)g_object_get_data(ref, "orig"); + + if (orig == NULL) + { + entry = GTK_WIDGET(g_object_get_data(ref, "addr")); + text = gtk_entry_get_text(GTK_ENTRY(entry)); + + radio = GTK_TOGGLE_BUTTON(g_object_get_data(ref, "phys")); + + if (gtk_toggle_button_get_active(radio)) + orig = string_to_vmpa_phy(text); + else + orig = string_to_vmpa_virt(text); + + + + } + + copy_vmpa(&addr, orig); + delete_vmpa(orig); + + /* Récupération du commentaire éventuel */ + + entry = GTK_WIDGET(g_object_get_data(ref, "comment")); + text = gtk_entry_get_text(GTK_ENTRY(entry)); + + /* Mise en place du signet défini */ + + if (strlen(text) > 0) + result = G_DB_ITEM(g_db_bookmark_new(&addr, text)); + else + result = G_DB_ITEM(g_db_bookmark_new(&addr, NULL)); + + return result; + +} diff --git a/src/dialogs/bookmark.h b/src/dialogs/bookmark.h new file mode 100644 index 0000000..0afdb4c --- /dev/null +++ b/src/dialogs/bookmark.h @@ -0,0 +1,44 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * bookmark.h - prototypes pour la boîte de dialogue pour les sauts à une adresse donnée + * + * Copyright (C) 2012 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 . + */ + + +#ifndef _DIALOGS_BOOKMARK_H +#define _DIALOGS_BOOKMARK_H + + +#include + + +#include "../arch/vmpa.h" +#include "../analysis/db/item.h" + + + +/* Construit la fenêtre de création de signet. */ +GtkWidget *create_bookmark_dialog(GtkWindow *, const vmpa2t *); + +/* Fournit le signet conçu via la saisie de l'utilisateur. */ +GDbItem *get_item_from_bookmark_dialog(GtkWidget *); + + + +#endif /* _DIALOGS_BOOKMARK_H */ diff --git a/src/dialogs/goto.c b/src/dialogs/goto.c index dc607d0..847fa9a 100644 --- a/src/dialogs/goto.c +++ b/src/dialogs/goto.c @@ -231,8 +231,8 @@ vmpa2t *get_address_from_goto_dialog(GtkWidget *dialog) vmpa2t *result; /* Adresse à retourner */ GtkWidget *combobox; /* Liste de sélection */ GtkWidget *entry; /* Zone de saisie principale */ - GtkToggleButton *radio; /* Définition de localisation */ const gchar *text; /* Adresse en version texte */ + GtkToggleButton *radio; /* Définition de localisation */ combobox = GTK_WIDGET(g_object_get_data(G_OBJECT(dialog), "combobox")); entry = gtk_bin_get_child(GTK_BIN(combobox)); diff --git a/src/dlg_sections.c b/src/dlg_sections.c deleted file mode 100644 index e69de29..0000000 diff --git a/src/dlg_sections.h b/src/dlg_sections.h deleted file mode 100644 index e69de29..0000000 diff --git a/src/gtkext/easygtk.c b/src/gtkext/easygtk.c index 11e17a4..fa99f38 100644 --- a/src/gtkext/easygtk.c +++ b/src/gtkext/easygtk.c @@ -876,3 +876,43 @@ GtkWidget *qck_create_tool_separator(GObject *object, const char *name) return result; } + + + + + + +/****************************************************************************** +* * +* Paramètres : parent = fenêtre parente pour la modalité d'affichage. * +* title = titre de la boîte de dialogue. * +* question = teneur de la question posée. * +* * +* Description : Affiche une boîte de dialogue offrant un choix "Oui/Non". * +* * +* Retour : Identifiant de la réponse choisie. * +* * +* Remarques : - * +* * +******************************************************************************/ + +gint qck_show_question(GtkWindow *parent, const char *title, const char *question) +{ + gint result; /* Choix arrêté à renvoyer */ + GtkWidget *dialog; /* Boîte de dialogue affichée */ + + dialog = gtk_message_dialog_new(parent, + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_QUESTION, + GTK_BUTTONS_YES_NO, + question); + + gtk_window_set_title(GTK_WINDOW(dialog), title); + + result = gtk_dialog_run(GTK_DIALOG(dialog)); + + gtk_widget_destroy(dialog); + + return result; + +} diff --git a/src/gtkext/easygtk.h b/src/gtkext/easygtk.h index 5f8fb29..65d1127 100644 --- a/src/gtkext/easygtk.h +++ b/src/gtkext/easygtk.h @@ -106,4 +106,9 @@ GtkWidget *qck_create_tool_separator(GObject *, const char *); +/* Affiche une boîte de dialogue offrant un choix "Oui/Non". */ +gint qck_show_question(GtkWindow *, const char *, const char *); + + + #endif /* _EASYGTK_H */ diff --git a/src/gtkext/gtkbufferview.c b/src/gtkext/gtkbufferview.c index 8b9b83b..f179845 100644 --- a/src/gtkext/gtkbufferview.c +++ b/src/gtkext/gtkbufferview.c @@ -746,6 +746,25 @@ static void gtk_buffer_view_relocate_caret(GtkBufferView *view, const GdkRectang * * * Paramètres : view = composant GTK à manipuler. * * * +* Description : Indique la position courante du curseur. * +* * +* Retour : Emplacement courant du curseur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const vmpa2t *gtk_buffer_view_get_caret_location(const GtkBufferView *view) +{ + return view->caret_addr; + +} + + +/****************************************************************************** +* * +* Paramètres : view = composant GTK à manipuler. * +* * * Description : Redémarre l'affichage du curseur à l'emplacement courant. * * * * Retour : - * diff --git a/src/gtkext/gtkbufferview.h b/src/gtkext/gtkbufferview.h index 1ee17fe..0cdcf4f 100644 --- a/src/gtkext/gtkbufferview.h +++ b/src/gtkext/gtkbufferview.h @@ -67,4 +67,12 @@ void gtk_buffer_view_compute_relative_coords(GtkBufferView *, gint *, gint *); +/* ------------------------------ ANIMATION DU CURSEUR ------------------------------ */ + + +/* Indique la position courante du curseur. */ +const vmpa2t *gtk_buffer_view_get_caret_location(const GtkBufferView *); + + + #endif /* _GTK_BUFFERVIEW_H */ diff --git a/src/gui/menus/edition.c b/src/gui/menus/edition.c index fc23f49..eec3016 100644 --- a/src/gui/menus/edition.c +++ b/src/gui/menus/edition.c @@ -28,11 +28,16 @@ #include +#include "../../dialogs/bookmark.h" #include "../../dialogs/goto.h" #include "../../gtkext/easygtk.h" +#include "../../gtkext/gtkbufferview.h" +/* Réagit avec le menu "Edition -> Signets -> Basculer...". */ +static void mcb_edition_bookmarks_toggle(GtkMenuItem *, GMenuBar *); + /* Réagit avec le menu "Edition -> Aller à l'adresse...". */ static void mcb_edition_goto(GtkMenuItem *, GMenuBar *); @@ -56,7 +61,9 @@ GtkWidget *build_menu_edition(GObject *ref, GtkAccelGroup *accgroup, GMenuBar *b { GtkWidget *result; /* Support à retourner */ GtkWidget *menubar; /* Support pour éléments */ - GtkWidget *submenuitem; /* Sous-élément de menu */ + GtkWidget *submenuitem; /* Sous-élément de menu #1 */ + GtkWidget *deepmenubar; /* Support pour éléments #2 */ + GtkWidget *deepmenuitem; /* Sous-élément de menu #2 */ result = gtk_menu_item_new_with_mnemonic(_("_Edition")); gtk_widget_show(result); @@ -64,6 +71,20 @@ GtkWidget *build_menu_edition(GObject *ref, GtkAccelGroup *accgroup, GMenuBar *b menubar = gtk_menu_new(); gtk_menu_item_set_submenu(GTK_MENU_ITEM(result), menubar); + submenuitem = qck_create_menu_item(NULL, NULL, _("Bookmarks"), NULL, NULL); + gtk_container_add(GTK_CONTAINER(menubar), submenuitem); + + deepmenubar = gtk_menu_new(); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(submenuitem), deepmenubar); + + deepmenuitem = qck_create_menu_item(NULL, NULL, _("Toggle at current location"), + G_CALLBACK(mcb_edition_bookmarks_toggle), bar); + add_accelerator_to_menu_item(deepmenuitem, "D", accgroup); + gtk_container_add(GTK_CONTAINER(deepmenubar), deepmenuitem); + + submenuitem = qck_create_menu_separator(); + gtk_container_add(GTK_CONTAINER(menubar), submenuitem); + submenuitem = qck_create_menu_item(NULL, NULL, _("Go to address..."), G_CALLBACK(mcb_edition_goto), bar); add_accelerator_to_menu_item(submenuitem, "G", accgroup); @@ -79,6 +100,105 @@ GtkWidget *build_menu_edition(GObject *ref, GtkAccelGroup *accgroup, GMenuBar *b * Paramètres : menuitem = élément de menu sélectionné. * * bar = barre de menu parente. * * * +* Description : Réagit avec le menu "Edition -> Signets -> Basculer...". * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void mcb_edition_bookmarks_toggle(GtkMenuItem *menuitem, GMenuBar *bar) +{ + GEditorItem *editem; /* Autre version de la barre */ + GtkViewPanel *panel; /* Vue offrant l'affichage */ + const vmpa2t *curloc; /* Localisation d'un curseur */ + GLoadedBinary *binary; /* Binaire en cours d'étude */ + GDbCollection *collec; /* Collection à manipuler */ + GDbItem *exist; /* Sens du basculement courant */ + GObject *ref; /* Espace de référencements */ + GtkWidget *dialog; /* Boîte de dialogue à montrer */ + GDbItem *bookmark; /* Nouveau signet défini */ + gint ret; /* Retour de confirmation */ + + editem = G_EDITOR_ITEM(bar); + + /* Détermination de l'adresse visée */ + + panel = g_editor_item_get_current_view(editem); + + if (!GTK_IS_BUFFER_VIEW(panel)) + curloc = NULL; + else + curloc = gtk_buffer_view_get_caret_location(GTK_BUFFER_VIEW(panel)); + + /* Accès à la collection */ + + binary = g_editor_item_get_current_binary(editem); + collec = g_loaded_binary_find_collection(binary, DBF_BOOKMARKS); + + /** + * On choisit de se passer de verrou ici : + * - si l'élément existe, la suppression prend en compte le fait + * que l'élément puisse disparaître entre temps. + * - si l'élément n'existe pas, une boîte de dialogue est prévue + * au moment de l'insertion finale. Dans ce cas, l'utilisateur + * peut de plus modifier la position pendant la définition. + */ + + if (curloc == NULL) + exist = NULL; + else + exist = NULL;//g_db_collection_has_key(collec, curloc); + + if (exist != NULL) + g_loaded_binary_remove_from_collection(binary, DBF_BOOKMARKS, exist); + + else + { + ref = g_editor_item_get_global_ref(G_EDITOR_ITEM(bar)); + dialog = create_bookmark_dialog(GTK_WINDOW(ref), curloc); + + if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK) + { + bookmark = get_item_from_bookmark_dialog(dialog); + + g_db_collection_wlock(G_DB_COLLECTION(collec)); + + if (g_db_collection_has_item(collec, G_DB_ITEM(bookmark))) + { + ret = qck_show_question(GTK_WINDOW(ref), + _("Location already bookmarked!"), + _("A bookmark has been defined at the same location.\n" \ + "Do you want to replace it ?")); + + if (ret != GTK_RESPONSE_YES) + goto mcb_ebt_add_finish; + + } + + _g_loaded_binary_add_to_collection(binary, DBF_BOOKMARKS, G_DB_ITEM(bookmark), false); + + mcb_ebt_add_finish: + + g_db_collection_wunlock(G_DB_COLLECTION(collec)); + + } + + gtk_widget_destroy(dialog); + + } + + g_object_unref(G_OBJECT(collec)); + +} + + +/****************************************************************************** +* * +* Paramètres : menuitem = élément de menu sélectionné. * +* bar = barre de menu parente. * +* * * Description : Réagit avec le menu "Edition -> Aller à l'adresse...". * * * * Retour : - * diff --git a/src/gui/panels/bookmarks.c b/src/gui/panels/bookmarks.c index 9239203..7397ef5 100644 --- a/src/gui/panels/bookmarks.c +++ b/src/gui/panels/bookmarks.c @@ -110,6 +110,9 @@ static void g_bookmarks_panel_finalize(GBookmarksPanel *); /* Recharge une collection de signets à l'affichage. */ static void reload_bookmarks_into_treeview(GBookmarksPanel *, GLoadedBinary *); +/* Met à jour une collection suite à une modification. */ +static void on_collection_content_changed(GDbCollection *, DBAction, GDbBookmark *, GBookmarksPanel *); + /* Réagit au changement de sélection des signets. */ static void on_bookmarks_selection_change(GtkTreeSelection *, GBookmarksPanel *); @@ -471,8 +474,8 @@ GPanelItem *create_bookmarks_panel(GObject *ref) static void reload_bookmarks_into_treeview(GBookmarksPanel *panel, GLoadedBinary *binary) { - GtkTreeStore *store; /* Modèle de gestion */ GDbCollection *collec; /* Collection à lister ici */ + GtkTreeStore *store; /* Modèle de gestion */ GArchProcessor *proc; /* Architecture du binaire */ MemoryDataSize msize; /* Taille par défaut */ GList *items; /* Liste des éléments groupés */ @@ -486,13 +489,25 @@ static void reload_bookmarks_into_treeview(GBookmarksPanel *panel, GLoadedBinary /* Basculement du binaire utilisé */ if (panel->binary != NULL) + { + collec = g_loaded_binary_find_collection(panel->binary, DBF_BOOKMARKS); + g_signal_handlers_disconnect_by_func(collec, G_CALLBACK(on_collection_content_changed), panel); + g_object_unref(G_OBJECT(panel->binary)); + } + panel->binary = binary; if (panel->binary != NULL) + { g_object_ref(G_OBJECT(binary)); + collec = g_loaded_binary_find_collection(binary, DBF_BOOKMARKS); + g_signal_connect(collec, "content-changed", G_CALLBACK(on_collection_content_changed), panel); + + } + store = GTK_TREE_STORE(gtk_tree_view_get_model(panel->treeview)); gtk_tree_store_clear(store); @@ -506,8 +521,6 @@ static void reload_bookmarks_into_treeview(GBookmarksPanel *panel, GLoadedBinary msize = g_arch_processor_get_memory_size(proc); g_object_unref(G_OBJECT(proc)); - collec = g_loaded_binary_find_collection(binary, DBF_BOOKMARKS); - g_db_collection_rlock(collec); items = g_db_collection_list_items(collec); @@ -539,6 +552,76 @@ static void reload_bookmarks_into_treeview(GBookmarksPanel *panel, GLoadedBinary /****************************************************************************** * * +* Paramètres : collec = collection dont le contenu vient de changer. * +* action = type de modification notifiée par la collection. * +* bookmark = élément en cause dans le changement survenu. * +* pane = structure contenant les informations maîtresses. * +* * +* Description : Met à jour une collection suite à une modification. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_collection_content_changed(GDbCollection *collec, DBAction action, GDbBookmark *bookmark, GBookmarksPanel *panel) +{ + + GtkTreeStore *store; /* Modèle de gestion */ + + + GExeFormat *format; /* Format du fichier binaire */ + GArchProcessor *proc; /* Architecture du binaire */ + MemoryDataSize msize; /* Taille par défaut */ + + const vmpa2t *addr; /* Adressse associée au signet */ + VMPA_BUFFER(phys); /* Position physique */ + VMPA_BUFFER(virt); /* Adresse virtuelle */ + GtkTreeIter iter; /* Point d'insertion */ + + + + + printf(" Passage :: %d\n", action); + + + store = GTK_TREE_STORE(gtk_tree_view_get_model(panel->treeview)); + + format = g_loaded_binary_get_format(panel->binary); + + + proc = g_loaded_binary_get_processor(panel->binary); + msize = g_arch_processor_get_memory_size(proc); + g_object_unref(G_OBJECT(proc)); + + + + + + + addr = g_db_bookmark_get_address(bookmark); + + vmpa2_phys_to_string(addr, msize, phys, NULL); + vmpa2_virt_to_string(addr, msize, virt, NULL); + + gtk_tree_store_append(store, &iter, NULL); + gtk_tree_store_set(store, &iter, + BMC_BOOKMARK, bookmark, + BMC_PICTURE, G_BOOKMARKS_PANEL_GET_CLASS(panel)->bookmark_img, + BMC_PHYSICAL, phys, + BMC_VIRTUAL, virt, + BMC_COMMENT, g_db_bookmark_get_comment(bookmark), + -1); + + + + +} + + +/****************************************************************************** +* * * Paramètres : selection = sélection modifiée. * * panel = structure contenant les informations maîtresses. * * * -- cgit v0.11.2-87-g4458