summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2015-02-09 22:07:42 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2015-02-09 22:07:42 (GMT)
commit1d79469f69bba33a2280d4bd531652b71148029f (patch)
treee81c094d6e829fb1a79d4c413c1cd162e14868a3
parent8d326041a0379b87e54be44506d544367567e89b (diff)
Created a dialog box to create new bookmarks.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@468 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
-rw-r--r--ChangeLog64
-rw-r--r--src/analysis/binary.c67
-rw-r--r--src/analysis/binary.h4
-rwxr-xr-xsrc/analysis/db/Makefile.am1
-rw-r--r--src/analysis/db/cdb.c44
-rw-r--r--src/analysis/db/collection-int.h78
-rw-r--r--src/analysis/db/collection.c272
-rw-r--r--src/analysis/db/collection.h28
-rw-r--r--src/analysis/db/items/bookmark.c377
-rw-r--r--src/analysis/db/items/bookmark.h27
-rw-r--r--src/analysis/db/server.c11
-rw-r--r--src/arch/vmpa.c130
-rw-r--r--src/arch/vmpa.h6
-rwxr-xr-xsrc/common/Makefile.am2
-rw-r--r--src/common/sqlite.c58
-rw-r--r--src/common/sqlite.h6
-rw-r--r--src/core/collections.c5
-rw-r--r--src/dialogs/Makefile.am1
-rw-r--r--src/dialogs/bookmark.c331
-rw-r--r--src/dialogs/bookmark.h44
-rw-r--r--src/dialogs/goto.c2
-rw-r--r--src/dlg_sections.c0
-rw-r--r--src/dlg_sections.h0
-rw-r--r--src/gtkext/easygtk.c40
-rw-r--r--src/gtkext/easygtk.h5
-rw-r--r--src/gtkext/gtkbufferview.c19
-rw-r--r--src/gtkext/gtkbufferview.h8
-rw-r--r--src/gui/menus/edition.c122
-rw-r--r--src/gui/panels/bookmarks.c89
29 files changed, 1678 insertions, 163 deletions
diff --git a/ChangeLog b/ChangeLog
index 9b3fccd..96684d0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,69 @@
15-02-09 Cyrille Bagard <nocbos@gmail.com>
+ * 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 <nocbos@gmail.com>
+
* 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 <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ANALYSIS_DB_COLLECTION_INT_H
+#define _ANALYSIS_DB_COLLECTION_INT_H
+
+
+#include "collection.h"
+
+
+#include <stdarg.h>
+
+
+
+/* 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 <assert.h>
+#include <malloc.h>
#include <stdio.h>
#include <string.h>
+#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 <sys/socket.h>
+#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 <inttypes.h>
#include <malloc.h>
+#include <sqlite3.h>
#include <stdlib.h>
#include <string.h>
@@ -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 <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "sqlite.h"
+
+
+#include <string.h>
+
+
+
+/******************************************************************************
+* *
+* 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 <stdint.h>
+#include <sys/types.h>
+
/* 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 <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "bookmark.h"
+
+
+#include <ctype.h>
+#include <string.h>
+
+
+#include <i18n.h>
+
+
+#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(_("<b>Localisation</b>"), &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(_("<b>Optional comment</b>"), &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 <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _DIALOGS_BOOKMARK_H
+#define _DIALOGS_BOOKMARK_H
+
+
+#include <gtk/gtk.h>
+
+
+#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
--- a/src/dlg_sections.c
+++ /dev/null
diff --git a/src/dlg_sections.h b/src/dlg_sections.h
deleted file mode 100644
index e69de29..0000000
--- a/src/dlg_sections.h
+++ /dev/null
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 <i18n.h>
+#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, "<Ctrl>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, "<Ctrl>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. *
* *