summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2014-08-18 21:55:24 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2014-08-18 21:55:24 (GMT)
commita0a7b6c1e05c78ae433f353d15e3366107b67d03 (patch)
treebca0b187778cf016c6131bfc982b08c67a38442b /src
parent161c0f8ab227af5033b1b6456607b9b9c3bc60df (diff)
Inserted storages and collections into loaded binaries (first steps).
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@389 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src')
-rw-r--r--src/analysis/binary-int.h2
-rw-r--r--src/analysis/binary.c194
-rw-r--r--src/analysis/binary.h33
-rwxr-xr-xsrc/analysis/db/Makefile.am10
-rw-r--r--src/analysis/db/bookmark.c69
-rw-r--r--src/analysis/db/cdb.c427
-rw-r--r--src/analysis/db/cdb.h19
-rw-r--r--src/analysis/db/client.c272
-rw-r--r--src/analysis/db/client.h13
-rw-r--r--src/analysis/db/collection.c491
-rw-r--r--src/analysis/db/collection.h81
-rw-r--r--src/analysis/db/core.c6
-rw-r--r--src/analysis/db/item-int.h68
-rw-r--r--src/analysis/db/item.c356
-rw-r--r--src/analysis/db/item.h68
-rw-r--r--src/analysis/db/items/Makefile.am17
-rw-r--r--src/analysis/db/items/bookmark.c416
-rw-r--r--src/analysis/db/items/bookmark.h79
-rw-r--r--src/analysis/db/items/comment.c398
-rw-r--r--src/analysis/db/items/comment.h77
-rwxr-xr-xsrc/analysis/db/misc/Makefile.am16
-rw-r--r--src/analysis/db/misc/rlestr.c345
-rw-r--r--src/analysis/db/misc/rlestr.h83
-rw-r--r--src/analysis/db/protocol.h101
-rw-r--r--src/analysis/db/server.c262
-rw-r--r--src/arch/vmpa.h1
-rw-r--r--src/common/io.c102
-rw-r--r--src/common/io.h11
-rwxr-xr-xsrc/core/Makefile.am1
-rw-r--r--src/core/collections.c175
-rw-r--r--src/core/collections.h (renamed from src/analysis/db/bookmark.h)27
-rw-r--r--src/core/core.c5
-rw-r--r--src/core/params.c90
-rw-r--r--src/core/params.h6
-rw-r--r--src/gui/panels/Makefile.am1
-rw-r--r--src/gui/panels/bookmarks.c1179
-rw-r--r--src/gui/panels/bookmarks.h65
-rw-r--r--src/gui/panels/panel.c4
-rw-r--r--src/gui/panels/regedit.c2
39 files changed, 5306 insertions, 266 deletions
diff --git a/src/analysis/binary-int.h b/src/analysis/binary-int.h
index 6361a0c..28d4594 100644
--- a/src/analysis/binary-int.h
+++ b/src/analysis/binary-int.h
@@ -53,7 +53,9 @@ struct _GLoadedBinary
GDbClient *local; /* Enregistrements locaux */
GDbClient *remote; /* Enregistrements distants */
+
DBStorage storages[DBF_COUNT]; /* Lieux d'enregistrement */
+ GList *collections; /* Ensemble de modifications */
save_binary_fc save; /* Sauvegarde au format XML */
get_binary_name_fc get_name; /* Obtention d'une description */
diff --git a/src/analysis/binary.c b/src/analysis/binary.c
index 83e81d8..5577bb8 100644
--- a/src/analysis/binary.c
+++ b/src/analysis/binary.c
@@ -40,6 +40,7 @@
#include "disass/disassembler.h"
#include "../common/extstr.h"
#include "../common/cpp.h"
+#include "../core/params.h"
@@ -222,11 +223,20 @@ 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 */
char *type; /* Type de binaire à charger */
+
+
+
+ char *host; /* Nom du serveur à contacter */
+ int port; /* Numéro du port associé */
+ char *author; /* Identification à diffuser */
+
+
+
bool status; /* Etat de la connexion à la BD*/
result = NULL;
@@ -241,16 +251,101 @@ GLoadedBinary *g_loaded_binary_new_from_xml(xmlXPathContextPtr context, const ch
if (result == NULL)
return NULL;
+ /* --------- %< --------- TODO : à bouger pur + de générique --------- %< --------- */
+
+
+ result->collections = create_collections_list();
+
+
if (!g_loaded_binary_load_storage(result, context, path))
goto glbnfx_error;
+
+ /* --------- %< --------- TODO : à bouger pur + de générique --------- %< --------- */
+
+
+
/*
if (!g_loaded_binary_load_parts_from_xml(result, context, path))
goto glbnfx_error;
*/
- result->local = g_db_client_new("localhost", 1337);
- status = g_db_client_start(result->local);
+
+ printf("data :: %p length :: %d\n", result->bin_data, result->bin_length);
+
+
+
+ /* Détermination de l'identifiant */
+
+ result->checksum = g_checksum_new(G_CHECKSUM_SHA256);
+ g_checksum_update(result->checksum, result->bin_data, result->bin_length);
+
+
+ result->local = g_db_client_new(g_loaded_binary_get_cheksum(result), result->collections);
+
+
+ if (!g_generic_config_get_value(get_main_configuration(), MPK_LOCAL_HOST, &host))
+ /* ... */;
+
+ if (!g_generic_config_get_value(get_main_configuration(), MPK_LOCAL_PORT, &port))
+ /* ... */;
+
+ if (!g_generic_config_get_value(get_main_configuration(), MPK_AUTHOR_NAME, &author))
+ /* ... */;
+
+
+ status = g_db_client_start(result->local, host, port, author);
+
+
+
+
+
+ /* --------- %< --------- %< --------- %< --------- %< --------- */
+
+ do
+ {
+ vmpa2t addr;
+ GDbBookmark *bm;
+ bool status;
+
+
+ init_vmpa(&addr, 123, 0x200);
+
+ 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");
+
+
+ /*
+ 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);
@@ -872,6 +967,97 @@ void g_loaded_binary_set_storage(GLoadedBinary *binary, DBFeatures feature, DBSt
+/* ---------------------------------------------------------------------------------- */
+/* MANIPULATION DES COLLECTIONS */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : binary = élément binaire à consulter. *
+* feature = fonctionnalité assurée par la collection visée. *
+* *
+* Description : Trouve une collection assurant une fonctionnalité donnée. *
+* *
+* Retour : Collection trouvée ou NULL. *
+* *
+* Remarques : Le résultat est à déréfrencer après usage. *
+* *
+******************************************************************************/
+
+GDbCollection *g_loaded_binary_find_collection(GLoadedBinary *binary, DBFeatures feature)
+{
+ GDbCollection *result; /* Collection à retourner */
+
+ /* TODO : lock */
+
+ result = find_collection_in_list(binary->collections, feature);
+
+ if (result != NULL)
+ g_object_ref(G_OBJECT(result));
+
+ /* TODO : unlock */
+
+ return result;
+
+}
+
+
+
+/******************************************************************************
+* *
+* Paramètres : binary = élément binaire à consulter. *
+* feature = fonctionnalité visée par la requête. *
+* item = élémnent à pousser vers un serveur de collection. *
+* *
+* Description : Demande l'intégration d'une modification dans une collection.*
+* *
+* Retour : Bilan partiel de l'opération demandée. *
+* *
+* Remarques : L'appelant perd la propriété de l'élément à ajouté. *
+* *
+******************************************************************************/
+
+bool g_loaded_binary_add_to_collection(GLoadedBinary *binary, DBFeatures feature, GDbItem *item)
+{
+ bool result; /* Bilan à faire remonter */
+ GDbCollection *collec; /* Collection visée au final */
+ DBStorage storage; /* Forme d'enregistrement */
+ GDbClient *client; /* Liaison à utiliser */
+ int fd; /* Identifiant du canal de com.*/
+
+ collec = g_loaded_binary_find_collection(binary, feature);
+ if (collec == NULL) return false;
+
+ /* S'il n'y a pas besoin de sauvegarde... */
+ if (g_db_item_is_volatile(item))
+ g_db_collection_add_item(collec, item);
+
+ /* Sinon on envoie par le réseau ! */
+ else
+ {
+ storage = g_loaded_binary_get_storage(binary, feature);
+
+
+ /* TODO : sélection du bon client... */
+ client = binary->local;
+
+
+ fd = g_db_client_get_fd(client);
+
+ result = g_db_collection_send(collec, fd, DBA_ADD_ITEM, item);
+
+ g_db_client_put_fd(client);
+
+ }
+
+ g_object_unref(G_OBJECT(collec));
+ g_object_unref(G_OBJECT(item));
+
+ return result;
+
+}
+
@@ -946,8 +1132,10 @@ void g_loaded_binary_analyse(GLoadedBinary *binary)
/* Détermination de l'identifiant */
+ /* déplacé
binary->checksum = g_checksum_new(G_CHECKSUM_SHA256);
g_checksum_update(binary->checksum, binary->bin_data, binary->bin_length);
+ */
/* Contacts avec les serveurs */
diff --git a/src/analysis/binary.h b/src/analysis/binary.h
index dbadd64..2a7e7d9 100644
--- a/src/analysis/binary.h
+++ b/src/analysis/binary.h
@@ -28,7 +28,8 @@
#include <glib-object.h>
#include <stdbool.h>
-
+#include "db/collection.h"
+#include "db/item.h"
#include "db/protocol.h"
#include "../arch/processor.h"
#include "../common/xml.h"
@@ -108,10 +109,40 @@ void g_loaded_binary_set_storage(GLoadedBinary *, DBFeatures, DBStorage);
+/* ------------------------- INFORMATIONS D'ENREGISTREMENTS ------------------------- */
+/* -------------------------- MANIPULATION DES COLLECTIONS -------------------------- */
+
+
+
+
+/* Trouve une collection assurant une fonctionnalité donnée. */
+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 *);
+
+
+
+
+
+#define g_loaded_binary_remove_from_collection(b, f, i)
+
+
+/**
+ * TODO :
+ *
+ * - connect_signal
+ * - add_obj
+ *
+ */
+
+
+
/* Définit les parties de binaire à analyser. */
+
void g_loaded_binary_set_parts(GLoadedBinary *, BinaryPartModel, GBinPart **, size_t);
/* Fournit les parties de binaire analysées. */
diff --git a/src/analysis/db/Makefile.am b/src/analysis/db/Makefile.am
index ef98a24..6852821 100755
--- a/src/analysis/db/Makefile.am
+++ b/src/analysis/db/Makefile.am
@@ -2,15 +2,19 @@
noinst_LTLIBRARIES = libanalysisdb.la
libanalysisdb_la_SOURCES = \
- bookmark.h bookmark.c \
cdb.h cdb.c \
client.h client.c \
collection.h collection.c \
core.h core.c \
+ item-int.h \
+ item.h item.c \
protocol.h \
server.h server.c
-libanalysisdb_la_LIBADD =
+libanalysisdb_la_LIBADD = \
+ items/libanalysisdbitems.la \
+ misc/libanalysisdbmisc.la
+
libanalysisdb_la_LDFLAGS =
@@ -19,4 +23,4 @@ AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBARCHIVE_CFLAGS) $(LIBSQLITE
AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
-SUBDIRS =
+SUBDIRS = items misc
diff --git a/src/analysis/db/bookmark.c b/src/analysis/db/bookmark.c
deleted file mode 100644
index 9a46a0d..0000000
--- a/src/analysis/db/bookmark.c
+++ /dev/null
@@ -1,69 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * bookmark.h - prototypes pour la gestion des signets au sein d'un binaire
- *
- * Copyright (C) 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 <malloc.h>
-
-
-
-
-
-
-/******************************************************************************
-* *
-* 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 (" \
- "id INT PRIMARY KEY NOT NULL, " \
- "user TEXT NOT NULL, " \
- "created INT NOT NULL, " \
- "address INT NOT NULL, " \
- "comment TEXT" \
- ");";
-
- ret = sqlite3_exec(db, sql, NULL, NULL, &msg);
- if (ret != SQLITE_OK)
- {
- fprintf(stderr, "sqlite3_exec(): %s\n", msg);
- sqlite3_free(msg);
- }
-
- return (ret == SQLITE_OK);
-
-}
diff --git a/src/analysis/db/cdb.c b/src/analysis/db/cdb.c
index 7e530ac..563aa40 100644
--- a/src/analysis/db/cdb.c
+++ b/src/analysis/db/cdb.c
@@ -28,7 +28,11 @@
#include <archive_entry.h>
#include <errno.h>
#include <fcntl.h>
+#include <limits.h>
#include <malloc.h>
+#include <poll.h>
+#include <pthread.h>
+#include <signal.h>
#include <stdio.h>
#include <sqlite3.h>
#include <string.h>
@@ -39,8 +43,9 @@
#include <config.h>
-#include "bookmark.h"
+#include "collection.h"
#include "protocol.h"
+#include "items/bookmark.h"
#include "../../common/cpp.h"
#include "../../common/extstr.h"
#include "../../common/io.h"
@@ -53,13 +58,26 @@
#define ARCHIVE_RBUF_SIZE 2048
+
+
+
+/* Informations relatives à un client */
+typedef struct _cdb_client
+{
+ int fd; /* Canal de communication */
+ rle_string user; /* Utilisateur à l'autre bout */
+
+ uint64_t last_time; /* Date de dernier envoi */
+
+} cdb_client;
+
+
/* Description d'une archive d'éléments utilisateur (instance) */
struct _GCdbArchive
{
GObject parent; /* A laisser en premier */
- char hash[65]; /* Empreinte SHA256 */
-
+ rle_string hash; /* Empreinte cryptographique */
char *filename; /* Chemin d'accès à l'archive */
@@ -71,6 +89,15 @@ struct _GCdbArchive
sqlite3 *db; /* Base de données à manipuler */
+ GList *collections; /* Ensemble de modifications */
+
+ cdb_client *clients; /* Connexions en place */
+ size_t count; /* Quantité de clients */
+ GMutex clients_access; /* Verrou pour l'accès */
+
+ GThread *process; /* Procédure de traitement */
+ pthread_t process_id; /* Identifiant de la procédure */
+
};
/* Description d'une archive d'éléments utilisateur (classe) */
@@ -101,7 +128,8 @@ static bool g_cdb_archive_read(GCdbArchive *);
/* Crée la description XML correspondant à l'archive. */
-static bool g_cdb_archive_create_xml_desc(GCdbArchive *, const core_db_info *);
+static bool g_cdb_archive_create_xml_desc(GCdbArchive *, const rle_string *);
+
@@ -112,6 +140,22 @@ static bool g_cdb_archive_create_db(const GCdbArchive *, const core_db_info *);
+/////////////////////////:
+
+
+/* Crée et remplit les collections à partir de leurs bases. */
+static bool g_cdb_archive_load_collections(GCdbArchive *);
+
+/* Réagit à une modification au sein d'une collection donnée. */
+static void on_collection_changed(GDbCollection *, DBAction, GDbItem *, GCdbArchive *);
+
+/* Assure le traitement des requêtes de clients. */
+static void *g_cdb_archive_process(GCdbArchive *);
+
+
+
+
+
/* Indique le type défini pour une une archive d'éléments utilisateur. */
G_DEFINE_TYPE(GCdbArchive, g_cdb_archive, G_TYPE_OBJECT);
@@ -155,6 +199,7 @@ static void g_cdb_archive_class_init(GCdbArchiveClass *klass)
static void g_cdb_archive_init(GCdbArchive *archive)
{
+ g_mutex_init(&archive->clients_access);
}
@@ -203,19 +248,21 @@ static void g_cdb_archive_finalize(GCdbArchive *archive)
/******************************************************************************
* *
-* Paramètres : local = indique si l'enregistrement est local ou non. *
-* client = flux ouvert en lecture pour les informations utiles.*
-* info = informations de base associées à la requête. *
+* Paramètres : owner = description humaine du serveur d'accueil. *
+* hash = empreinte du binaire à représenter. *
+* user = désignation d'un éventuel nouveau créateur. *
+* error = indication éventuelle en cas d'échec. [OUT] *
* *
* Description : Définit ou ouvre une archive d'éléments utilisateur. *
* *
* Retour : Structure mise en plae ou NULL en cas d'échec. *
* *
-* Remarques : - *
+* Remarques : Les chaînes sont assurées d'être non vides ; la procédure *
+* assume un transfert de propriété. *
* *
******************************************************************************/
-GCdbArchive *g_cdb_archive_new(bool local, GDbClient *client, const core_db_info *info)
+GCdbArchive *g_cdb_archive_new(const char *owner, const rle_string *hash, const rle_string *user, DBError *error)
{
GCdbArchive *result; /* Adresse à retourner */
char *suffix; /* Fin du nom de fichier */
@@ -224,19 +271,14 @@ GCdbArchive *g_cdb_archive_new(bool local, GDbClient *client, const core_db_info
result = g_object_new(G_TYPE_CDB_ARCHIVE, NULL);
-
-
- strcpy(result->hash, info->hash);
-
-
-
+ dup_rle_string(&result->hash, hash);
/* Chemin de l'archive */
suffix = strdup("chrysalide" G_DIR_SEPARATOR_S);
- suffix = stradd(suffix, local ? "local" : "server");
+ suffix = stradd(suffix, owner);
suffix = stradd(suffix, G_DIR_SEPARATOR_S);
- suffix = stradd(suffix, result->hash);
+ suffix = stradd(suffix, hash->data);
suffix = stradd(suffix, ".tar.xz");
result->filename = get_xdg_config_dir(suffix);
@@ -253,7 +295,7 @@ GCdbArchive *g_cdb_archive_new(bool local, GDbClient *client, const core_db_info
if (result->xml_desc[strlen(result->xml_desc) - 1] != G_DIR_SEPARATOR)
result->xml_desc = stradd(result->xml_desc, G_DIR_SEPARATOR_S);
- result->xml_desc = stradd(result->xml_desc, result->hash);
+ result->xml_desc = stradd(result->xml_desc, result->hash.data);
result->xml_desc = stradd(result->xml_desc, "_desc.xml");
result->sql_db = strdup(g_get_tmp_dir());
@@ -261,7 +303,7 @@ GCdbArchive *g_cdb_archive_new(bool local, GDbClient *client, const core_db_info
if (result->sql_db[strlen(result->sql_db) - 1] != G_DIR_SEPARATOR)
result->sql_db = stradd(result->sql_db, G_DIR_SEPARATOR_S);
- result->sql_db = stradd(result->sql_db, result->hash);
+ result->sql_db = stradd(result->sql_db, result->hash.data);
result->sql_db = stradd(result->sql_db, "_db.sql");
/* Création de l'archive si elle n'existe pas */
@@ -273,8 +315,8 @@ GCdbArchive *g_cdb_archive_new(bool local, GDbClient *client, const core_db_info
/* Le soucis ne vient pas de l'absence du fichier... */
if (errno != ENOENT) goto gcan_error;
- g_cdb_archive_create_xml_desc(result, info);
- g_cdb_archive_create_db(result, info);
+ g_cdb_archive_create_xml_desc(result, user);
+ g_cdb_archive_create_db(result, NULL);
if (!g_cdb_archive_write(result))
goto gcan_error;
@@ -288,6 +330,11 @@ GCdbArchive *g_cdb_archive_new(bool local, GDbClient *client, const core_db_info
if (!g_cdb_archive_read(result) && 0)
goto gcan_error;
+ /* Chargement des éléments sauvegardés */
+
+ if (!g_cdb_archive_load_collections(result))
+ goto gcan_error;
+
return result;
gcan_error:
@@ -301,7 +348,7 @@ GCdbArchive *g_cdb_archive_new(bool local, GDbClient *client, const core_db_info
/******************************************************************************
* *
-* Paramètres : archive = information quant à l'archive à interpréter. *
+* Paramètres : archive = informations quant à l'archive à interpréter. *
* *
* Description : Ouvre une archive avec tous les éléments à conserver. *
* *
@@ -416,7 +463,7 @@ static bool g_cdb_archive_read(GCdbArchive *archive)
/******************************************************************************
* *
-* Paramètres : archive = information quant à l'archive à créer. *
+* Paramètres : archive = informations quant à l'archive à créer. *
* *
* Description : Enregistre une archive avec tous les éléments à conserver. *
* *
@@ -497,9 +544,24 @@ bool g_cdb_archive_write(const GCdbArchive *archive)
}
+/******************************************************************************
+* *
+* Paramètres : archive = informations quant à l'archive à consulter. *
+* hash = empreinte extérieure à comparer. *
+* *
+* Description : Détermine si une empreinte correspond à celle d'une archive. *
+* *
+* Retour : Résultat de la comparaison : -1, 0 ou 1. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+int g_cdb_archive_compare_hash(const GCdbArchive *archive, const rle_string *hash)
+{
+ return cmp_rle_string(&archive->hash, hash);
-
+}
@@ -514,7 +576,7 @@ bool g_cdb_archive_write(const GCdbArchive *archive)
/******************************************************************************
* *
* Paramètres : archive = archive à constituer. *
-* info = informations de base associées à la requête. *
+* user = désignation d'un éventuel nouveau créateur. *
* *
* Description : Crée la description XML correspondant à l'archive. *
* *
@@ -524,7 +586,7 @@ bool g_cdb_archive_write(const GCdbArchive *archive)
* *
******************************************************************************/
-static bool g_cdb_archive_create_xml_desc(GCdbArchive *archive, const core_db_info *info)
+static bool g_cdb_archive_create_xml_desc(GCdbArchive *archive, const rle_string *user)
{
bool result; /* Bilan à retourner */
char tmp[sizeof(STR(ULLONG_MAX))]; /* Stockage temporaire */
@@ -536,12 +598,15 @@ static bool g_cdb_archive_create_xml_desc(GCdbArchive *archive, const core_db_in
"/ChrysalideBinary/Version", PACKAGE_VERSION);
result &= add_content_to_node(archive->xdoc, archive->context,
- "/ChrysalideBinary/Hash", archive->hash);
+ "/ChrysalideBinary/Protocol", XSTR(CDB_PROTOCOL_VERSION));
result &= add_content_to_node(archive->xdoc, archive->context,
- "/ChrysalideBinary/Creation/Author", "**me**");
+ "/ChrysalideBinary/Hash", archive->hash.data);
- snprintf(tmp, sizeof(tmp), "%" PRIu64, (uint64_t)10ull);
+ result &= add_content_to_node(archive->xdoc, archive->context,
+ "/ChrysalideBinary/Creation/Author", user->data);
+
+ snprintf(tmp, sizeof(tmp), "%" PRIu64, (uint64_t)time(NULL));
result &= add_content_to_node(archive->xdoc, archive->context,
"/ChrysalideBinary/Creation/Date", tmp);
@@ -600,3 +665,307 @@ static bool g_cdb_archive_create_db(const GCdbArchive *archive, const core_db_in
return result;
}
+
+
+
+
+
+
+
+
+
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* ACCES A LA BASE DE DONNEES SQL */
+/* ACCES A LA BASE DE DONNEES SQL */
+/* ---------------------------------------------------------------------------------- */
+
+
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : archive = archive dont les collections sont à initialiser. *
+* *
+* Description : Crée et remplit les collections à partir de leurs bases. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_cdb_archive_load_collections(GCdbArchive *archive)
+{
+ GList *iter; /* Boucle de parcours */
+
+ archive->collections = create_collections_list();
+
+ for (iter = g_list_first(archive->collections);
+ iter != NULL;
+ iter = g_list_next(iter))
+ {
+ g_signal_connect(iter->data, "content-changed", G_CALLBACK(on_collection_changed), archive);
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : collec = collection dont le contenu a évolué. *
+* action = type d'évolution rencontrée. *
+* item = élément ajouté, modifié ou supprimé. *
+* archive = centralisation de tous les savoirs. *
+* *
+* Description : Réagit à une modification au sein d'une collection donnée. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void on_collection_changed(GDbCollection *collec, DBAction action, GDbItem *item, GCdbArchive *archive)
+{
+ size_t i; /* Boucle de parcours */
+ bool status; /* Bilan d'un envoi de retour */
+
+ g_mutex_lock(&archive->clients_access);
+
+ for (i = 0; i < archive->count; i++)
+ {
+ status = g_db_collection_send(collec, archive->clients[i].fd, action, item);
+
+ if (!status)
+ {
+ /* TODO : close() */
+ }
+
+ }
+
+ g_mutex_unlock(&archive->clients_access);
+
+ printf("CHANGED !!\n");
+
+
+
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : archive = centralisation de tous les savoirs. *
+* *
+* Description : Assure le traitement des requêtes de clients. *
+* *
+* Retour : NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void *g_cdb_archive_process(GCdbArchive *archive)
+{
+ struct pollfd *fds; /* Surveillance des flux */
+ nfds_t nfds; /* Quantité de ces flux */
+ nfds_t i; /* Boucle de parcours */
+ int ret; /* Bilan d'un appel */
+ uint32_t val32; /* Valeur sur 32 bits */
+ bool status; /* Bilan de lecture initiale */
+ uint32_t command; /* Commande de la requête */
+ GDbCollection *collec; /* Collection visée au final */
+
+ void interrupt_poll_with_sigusr1(int sig) { };
+
+ signal(SIGUSR1, interrupt_poll_with_sigusr1);
+
+ archive->process_id = pthread_self();
+
+ fds = NULL;
+
+ while (1)
+ {
+ /* Reconstitution d'une liste à jour */
+
+ g_mutex_lock(&archive->clients_access);
+
+ nfds = archive->count;
+ fds = (struct pollfd *)realloc(fds, nfds * sizeof(struct pollfd));
+
+ for (i = 0; i < nfds; i++)
+ {
+ fds[i].fd = archive->clients[i].fd;
+ fds[i].events = POLLIN | POLLPRI;
+ }
+
+ if (nfds == 0)
+ goto gcap_no_more_clients;
+
+ g_mutex_unlock(&archive->clients_access);
+
+ /* Lancement d'une phase de surveillance */
+
+ printf("(%p) POLL %d\n", archive, nfds);
+
+ ret = poll(fds, nfds, -1);
+ if (ret == -1)
+ {
+ if (errno == EINTR) continue;
+
+ perror("poll");
+ break;
+
+ }
+
+ /* Traitement des requêtes reçues */
+
+ for (i = 0; i < nfds; i++)
+ {
+ /* Le canal est fermé, une sortie doit être demandée... */
+ if (fds[i].revents & POLLNVAL)
+ goto gcap_bad_exchange;
+
+ /* Données présentes en entrée */
+ if (fds[i].revents & (POLLIN | POLLPRI))
+ {
+ status = safe_recv(fds[i].fd, &val32, sizeof(uint32_t), 0);
+ if (!status) goto gcap_bad_exchange;
+
+ command = be32toh(val32);
+
+ switch (command)
+ {
+ case DBC_COLLECTION:
+
+ status = safe_recv(fds[i].fd, &val32, sizeof(uint32_t), 0);
+ if (!status) goto gcap_bad_exchange;
+
+ collec = find_collection_in_list(archive->collections, be32toh(val32));
+ if (collec == NULL) goto gcap_bad_exchange;
+
+ status = g_db_collection_recv(collec, fds[i].fd);
+ if (!status) goto gcap_bad_exchange;
+
+ printf("## CDB ## Got something for collection %p...\n", collec);
+
+ //GDbCollection *find_collection_in_list(GList *, uint32_t);
+
+ //static GGenConfig *find_collection_in_list(GList *list, uint32_t id)
+
+ break;
+
+ default:
+ printf("bad command :: 0x%08x\n", command);
+ goto gcap_bad_exchange;
+ break;
+
+ }
+
+ continue;
+
+ gcap_bad_exchange:
+
+ printf("Bad exchange...\n");
+
+ /* TODO : close conn */
+
+ ;
+
+
+ }
+
+ }
+
+ }
+
+ /* On disparaît des écrans... */
+
+ g_mutex_lock(&archive->clients_access);
+
+ gcap_no_more_clients:
+
+ archive->process = NULL;
+ archive->process_id = 0;
+
+ g_mutex_unlock(&archive->clients_access);
+
+ if (fds != NULL)
+ free(fds);
+
+
+ return NULL;
+
+}
+
+
+
+/******************************************************************************
+* *
+* Paramètres : archive = archive à connecter avec un utilisateur. *
+* fd = canal de communication réseau ouvert. *
+* user = désignation de l'utilisateur associé. *
+* *
+* Description : Associe un nouvel utilisateur à l'archive. *
+* *
+* Retour : Indication d'une éventuelle erreur lors de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+DBError g_cdb_archive_add_client(GCdbArchive *archive, int fd, const rle_string *user)
+{
+
+ volatile pthread_t *process_id; /* Identifiant de la procédure */
+
+
+
+
+ printf("Add '%s' for archive...\n", user->data);
+
+
+ g_mutex_lock(&archive->clients_access);
+
+ /* Ajout dans la liste officielle */
+
+ archive->clients = (cdb_client *)realloc(archive->clients, ++archive->count * sizeof(cdb_client));
+
+ archive->clients[archive->count - 1].fd = fd;
+ dup_rle_string(&archive->clients[archive->count - 1].user, user);
+
+ /* Démarrage ou redémarrage du processus d'écoute */
+
+ if (archive->process == NULL)
+ {
+ archive->process = g_thread_new("cdb_process", (GThreadFunc)g_cdb_archive_process, archive);
+
+ /* On attend que le processus parallèle soit prêt */
+ for (process_id = &archive->process_id; *process_id == 0; );
+
+ }
+ else
+ pthread_kill(archive->process_id, SIGUSR1);
+
+ g_mutex_unlock(&archive->clients_access);
+
+ /* Envoi des mises à jour au nouveau client... */
+
+
+ /* TODO */
+
+
+
+ return DBE_NONE;
+
+}
+
+
+
diff --git a/src/analysis/db/cdb.h b/src/analysis/db/cdb.h
index a093039..17327f5 100644
--- a/src/analysis/db/cdb.h
+++ b/src/analysis/db/cdb.h
@@ -29,8 +29,13 @@
#include <stdbool.h>
+#include "protocol.h"
+#include "misc/rlestr.h"
+
+//////
#include "client.h"
#include "core.h"
+//////////
@@ -52,11 +57,23 @@ typedef struct _GCdbArchiveClass GCdbArchiveClass;
GType g_cdb_archive_get_type(void);
/* Prépare un client pour une connexion à une BD. */
-GCdbArchive *g_cdb_archive_new(bool, GDbClient *, const core_db_info *);
+GCdbArchive *g_cdb_archive_new(const char *, const rle_string *, const rle_string *, DBError *);
/* Enregistre une archive avec tous les éléments à conserver. */
bool g_cdb_archive_write(const GCdbArchive *);
+/* Détermine si une empreinte correspond à celle d'une archive. */
+int g_cdb_archive_compare_hash(const GCdbArchive *, const rle_string *);
+
+
+
+
+
+/* Associe un nouvel utilisateur à l'archive. */
+DBError g_cdb_archive_add_client(GCdbArchive *, int, const rle_string *);
+
+
+
#endif /* _ANALYSIS_DB_CDB_H */
diff --git a/src/analysis/db/client.c b/src/analysis/db/client.c
index 946f202..4b807ae 100644
--- a/src/analysis/db/client.c
+++ b/src/analysis/db/client.c
@@ -33,6 +33,9 @@
#include "protocol.h"
+#include "misc/rlestr.h"
+#include "../../common/io.h"
+#include "../../gui/panels/log.h"
@@ -41,9 +44,12 @@ struct _GDbClient
{
GObject parent; /* A laisser en premier */
- int fd;
- struct sockaddr_in addr; /* Adresse d'écoute */
+ rle_string hash; /* Empreinte du binaire lié */
+ GList *collections; /* Collections d'un binaire */
+ int fd; /* Canal de communication */
+
+ GMutex sending_lock; /* Concurrence des envois */
GThread *update; /* Procédure de traitement */
};
@@ -118,7 +124,7 @@ static void g_db_client_init(GDbClient *client)
/******************************************************************************
* *
-* Paramètres : binary = instance d'objet GLib à traiter. *
+* Paramètres : client = instance d'objet GLib à traiter. *
* *
* Description : Procède à la libération totale de la mémoire. *
* *
@@ -128,19 +134,19 @@ static void g_db_client_init(GDbClient *client)
* *
******************************************************************************/
-static void g_db_client_finalize(GDbClient *binary)
+static void g_db_client_finalize(GDbClient *client)
{
- //free(binary->filename);
+ unset_rle_string(&client->hash);
- G_OBJECT_CLASS(g_db_client_parent_class)->finalize(G_OBJECT(binary));
+ G_OBJECT_CLASS(g_db_client_parent_class)->finalize(G_OBJECT(client));
}
/******************************************************************************
* *
-* Paramètres : host = hôte à représenter pour le service. *
-* port = port de connexion pour les clients. *
+* Paramètres : hash = empreinte d'un binaire en cours d'analyse. *
+* collections = ensemble de collections existantes. *
* *
* Description : Prépare un client pour une connexion à une BD. *
* *
@@ -150,28 +156,155 @@ static void g_db_client_finalize(GDbClient *binary)
* *
******************************************************************************/
-GDbClient *g_db_client_new(const char *host, short port)
+GDbClient *g_db_client_new(const char *hash, GDbCollection *collections)
{
GDbClient *result; /* Adresse à retourner */
- struct hostent *hp; /* Informations sur l'hôte */
result = g_object_new(G_TYPE_DB_CLIENT, NULL);
+ set_rle_string(&result->hash, hash);
+ result->collections = collections;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : client = client pour les accès distants à manipuler. *
+* host = hôte à représenter pour le service. *
+* port = port de connexion pour les clients. *
+* username = utilisateur effectuant les évolutions. *
+* *
+* Description : Démarre la connexion à la base de données. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_db_client_start(GDbClient *client, const char *host, unsigned short port, const char *username)
+{
+ struct hostent *hp; /* Informations sur l'hôte */
+ struct sockaddr_in addr; /* Adresse de transmission */
+ int ret; /* Bilan d'un appel */
+ rle_string user; /* Nom d'utilisateur associé */
+ uint32_t data; /* Mot de données lues */
+ DBError error; /* Validation de la connexion */
+
+ /* Identification du serveur à contacter */
+
hp = gethostbyname(host);
- if (hp == NULL) goto gdsn_error;
+ if (hp == NULL) return false;
- result->addr.sin_family = hp->h_addrtype;
- memcpy(&result->addr.sin_addr, hp->h_addr_list[0], sizeof(struct in_addr));
+ addr.sin_family = hp->h_addrtype;
+ memcpy(&addr.sin_addr, hp->h_addr_list[0], sizeof(struct in_addr));
- result->addr.sin_port = htons(port);
+ addr.sin_port = htons(port);
- return result;
+ /* Création d'un canal de communication */
+
+ client->fd = socket(AF_INET, SOCK_STREAM, 0);
+ if (client->fd == -1)
+ {
+ perror("socket");
+ return false;
+ }
+
+ ret = connect(client->fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
+ if (ret == -1)
+ {
+ perror("connect");
+ goto gdcs_no_listening;
+ }
- gdsn_error:
+ /* Préparation du nom d'utilisateur à diffuser */
- g_object_unref(G_OBJECT(result));
+ init_rle_string(&user, username);
- return NULL;
+ /**
+ * On réalise l'envoi initial ; le premier paquet doit contenir :
+ * - la commande 'DBC_HELO'.
+ * - le numéro de version du client.
+ * - l'empreinte du binaire analysé.
+ * - l'identifiant de l'utilisateur effectuant des modifications.
+ *
+ * Tout ceci est à synchroniser avec la fonction g_db_server_listener().
+ */
+
+ if (!safe_send(client->fd, (uint32_t []) { htobe32(DBC_HELO) }, sizeof(uint32_t), MSG_MORE))
+ goto gdcs_error;
+
+ if (!safe_send(client->fd, (uint32_t []) { htobe32(CDB_PROTOCOL_VERSION) }, sizeof(uint32_t), MSG_MORE))
+ goto gdcs_error;
+
+ if (!send_rle_string(&client->hash, client->fd, MSG_MORE))
+ goto gdcs_error;
+
+ if (!send_rle_string(&user, client->fd, 0))
+ goto gdcs_error;
+
+ /**
+ * Le serveur doit répondre pour un message type :
+ * - la commande 'DBC_WELCOME'.
+ * - un identifiant d'erreur ('DBE_NONE' ou 'DBE_WRONG_VERSION').
+ */
+
+ if (!safe_recv(client->fd, &data, sizeof(uint32_t), 0))
+ goto gdcs_error;
+
+ if (be32toh(data) != DBC_WELCOME)
+ {
+ log_variadic_message(LMT_ERROR, _("The server '%s:%hu' did not welcome us!"), host, port);
+ goto gdcs_error;
+ }
+
+ if (!safe_recv(client->fd, &data, sizeof(uint32_t), 0))
+ goto gdcs_error;
+
+ error = be32toh(data);
+
+ switch (error)
+ {
+ case DBE_NONE:
+ log_variadic_message(LMT_INFO, _("Connected to the server '%s:%hu'!"), host, port);
+ break;
+
+ case DBE_WRONG_VERSION:
+ log_variadic_message(LMT_ERROR, _("The server '%s:%hu' does not use our protocol version (0x%08x)..."),
+ host, port, CDB_PROTOCOL_VERSION);
+ goto gdcs_error;
+ break;
+
+ default:
+ log_variadic_message(LMT_ERROR, _("The server '%s:%hu' uses an unknown protocol..."), host, port);
+ goto gdcs_error;
+ break;
+
+ }
+
+ client->update = g_thread_try_new("cdb_client", (GThreadFunc)g_db_client_update, client, NULL);
+ if (client->update == NULL)
+ {
+ log_variadic_message(LMT_ERROR, _("Failed to start a listening thread for the server '%s:%hu'!"),
+ host, port);
+ goto gdcs_error;
+ }
+
+ return true;
+
+ gdcs_error:
+
+ unset_rle_string(&user);
+
+ gdcs_no_listening:
+
+ close(client->fd);
+ client->fd = -1;
+
+ return false;
}
@@ -192,6 +325,10 @@ static void *g_db_client_update(GDbClient *client)
{
struct pollfd fds; /* Surveillance des flux */
int ret; /* Bilan d'un appel */
+ uint32_t val32; /* Valeur sur 32 bits */
+ bool status; /* Bilan d'une opération */
+ uint32_t command; /* Commande de la requête */
+ GDbCollection *collec; /* Collection visée au final */
fds.fd = client->fd;
fds.events = POLLIN | POLLPRI;
@@ -209,16 +346,50 @@ static void *g_db_client_update(GDbClient *client)
if (fds.revents & (POLLIN | POLLPRI))
{
+ status = safe_recv(fds.fd, &val32, sizeof(uint32_t), 0);
+ if (!status) goto gdcu_bad_exchange;
+
+ command = be32toh(val32);
+
+ switch (command)
+ {
+ case DBC_COLLECTION:
+
+ status = safe_recv(fds.fd, &val32, sizeof(uint32_t), 0);
+ if (!status) goto gdcu_bad_exchange;
+
+ collec = find_collection_in_list(client->collections, be32toh(val32));
+ if (collec == NULL) goto gdcu_bad_exchange;
+
+ status = g_db_collection_recv(collec, fds.fd);
+ if (!status) goto gdcu_bad_exchange;
+
+
+
+
+ printf("## CLIENT ## Got Something to read...\n");
+
+ break;
+
+ }
+
+ continue;
+
+ gdcu_bad_exchange:
+
+ printf("Bad reception...\n");
+
+ /* TODO : close conn */
+
+ ;
- /* TODO */
- pause();
}
}
- g_db_client_stop(client);
+ //g_db_client_stop(client);
return NULL;
@@ -229,39 +400,44 @@ static void *g_db_client_update(GDbClient *client)
* *
* Paramètres : client = client pour les accès distants à manipuler. *
* *
-* Description : Démarre la connexion à la base de données. *
+* Description : Arrête la connexion à la base de données. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-bool g_db_client_start(GDbClient *client)
+void g_db_client_stop(GDbClient *client)
{
- int ret; /* Bilan d'un appel */
+ if (client->fd != -1)
+ return;
- client->fd = socket(AF_INET, SOCK_STREAM, 0);
- if (client->fd == -1)
- {
- perror("socket");
- return false;
- }
+ close(client->fd);
+ client->fd = -1;
- ret = connect(client->fd, (struct sockaddr *)&client->addr, sizeof(struct sockaddr_in));
- if (ret == -1)
- {
- perror("connect");
- close(client->fd);
- client->fd = -1;
- return false;
- }
+ g_thread_join(client->update);
- //client->update = g_thread_new("cdb_listener", (GThreadFunc)g_db_client_update, client);
+}
- send(client->fd, "A", 1, 0);
- return true;
+/******************************************************************************
+* *
+* Paramètres : client = client pour les accès distants à manipuler. *
+* *
+* Description : Identifie le canal de communication pour envois au serveur. *
+* *
+* Retour : Descripteur de flux normalement ouvert. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int g_db_client_get_fd(GDbClient *client)
+{
+ g_mutex_lock(&client->sending_lock);
+
+ return client->fd;
}
@@ -270,7 +446,7 @@ bool g_db_client_start(GDbClient *client)
* *
* Paramètres : client = client pour les accès distants à manipuler. *
* *
-* Description : Arrête la connexion à la base de données. *
+* Description : Marque le canal de communication comme disponible. *
* *
* Retour : - *
* *
@@ -278,14 +454,8 @@ bool g_db_client_start(GDbClient *client)
* *
******************************************************************************/
-void g_db_client_stop(GDbClient *client)
+void g_db_client_put_fd(GDbClient *client)
{
- if (client->fd != -1)
- return;
-
- close(client->fd);
- client->fd = -1;
-
- g_thread_join(client->update);
+ g_mutex_unlock(&client->sending_lock);
}
diff --git a/src/analysis/db/client.h b/src/analysis/db/client.h
index e57a5b6..a1a9f8e 100644
--- a/src/analysis/db/client.h
+++ b/src/analysis/db/client.h
@@ -29,6 +29,9 @@
#include <stdbool.h>
+#include "collection.h"
+
+
#define G_TYPE_DB_CLIENT g_db_client_get_type()
#define G_DB_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_db_client_get_type(), GDbClient))
@@ -48,14 +51,20 @@ typedef struct _GDbClientClass GDbClientClass;
GType g_db_client_get_type(void);
/* Prépare un client pour une connexion à une BD. */
-GDbClient *g_db_client_new(const char *, short);
+GDbClient *g_db_client_new(const char *, GDbCollection *);
/* Démarre la connexion à la base de données. */
-bool g_db_client_start(GDbClient *);
+bool g_db_client_start(GDbClient *, const char *, unsigned short, const char *);
/* Arrête la connexion à la base de données. */
void g_db_client_stop(GDbClient *);
+/* Identifie le canal de communication pour envois au serveur. */
+int g_db_client_get_fd(GDbClient *);
+
+/* Marque le canal de communication comme disponible. */
+void g_db_client_put_fd(GDbClient *);
+
#endif /* _ANALYSIS_DB_CLIENT_H */
diff --git a/src/analysis/db/collection.c b/src/analysis/db/collection.c
index 9ddba48..20b1ff3 100644
--- a/src/analysis/db/collection.c
+++ b/src/analysis/db/collection.c
@@ -24,3 +24,494 @@
#include "collection.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 */
+
+ 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 *);
+
+};
+
+
+
+
+/* Initialise la classe des collections génériques d'éléments. */
+static void g_db_collection_class_init(GDbCollectionClass *);
+
+/* Initialise une collection générique d'éléments. */
+static void g_db_collection_init(GDbCollection *);
+
+/* Supprime toutes les références externes. */
+static void g_db_collection_dispose(GDbCollection *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_db_collection_finalize(GDbCollection *);
+
+
+
+
+/* Indique le type défini pour une collection générique d'éléments. */
+G_DEFINE_TYPE(GDbCollection, g_db_collection, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des collections génériques d'éléments. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_db_collection_class_init(GDbCollectionClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_db_collection_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_db_collection_finalize;
+
+ g_signal_new("content-changed",
+ G_TYPE_DB_COLLECTION,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(GDbCollectionClass, content_changed),
+ NULL, NULL,
+ g_cclosure_user_marshal_VOID__ENUM_OBJECT,
+ G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_OBJECT);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : collec = instance à initialiser. *
+* *
+* Description : Initialise une collection générique d'éléments. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_db_collection_init(GDbCollection *collec)
+{
+ g_rw_lock_init(&collec->params_access);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : collec = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_db_collection_dispose(GDbCollection *collec)
+{
+ G_OBJECT_CLASS(g_db_collection_parent_class)->dispose(G_OBJECT(collec));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : collec = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_db_collection_finalize(GDbCollection *collec)
+{
+ g_rw_lock_clear(&collec->params_access);
+
+ G_OBJECT_CLASS(g_db_collection_parent_class)->finalize(G_OBJECT(collec));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : id = identifiant réseau des éléments à traiter. *
+* type = type GLib des éléments à intégrer dans la collection. *
+* *
+* Description : Prépare la mise en place d'une nouvelle collection. *
+* *
+* Retour : Adresse de l'instance ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GDbCollection *g_db_collection_new(uint32_t id, GType type)
+{
+ GDbCollection *result; /* Adresse à retourner */
+
+ result = g_object_new(G_TYPE_DB_COLLECTION, NULL);
+
+ result->featuring = id;
+ result->type = type;
+
+ return result;
+
+}
+
+
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : collec = collection générique d'éléments à consulter. *
+* *
+* Description : Décrit le type des éléments rassemblées dans une collection. *
+* *
+* Retour : Identifiant interne des éléments collectionés. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+uint32_t g_db_collection_get_feature(const GDbCollection *collec)
+{
+ return collec->featuring;
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : collec = ensemble d'éléments à considérer. *
+* fd = flux ouvert en lecture pour la réception de données.*
+* *
+* Description : Réceptionne et traite une requête réseau pour collection. *
+* *
+* Retour : Bilan de l'exécution de l'opération. *
+* *
+* Remarques : Cette fonction est uniquement destinée aux appels depuis *
+* la fonction g_cdb_archive_process() ; une partie des *
+* informations ont déjà été tirées des échanges protocolaires. *
+* *
+******************************************************************************/
+
+bool g_db_collection_recv(GDbCollection *collec, int fd)
+{
+ bool result; /* Bilan à faire remonter */
+ uint32_t val32; /* Valeur sur 32 bits */
+ bool status; /* Bilan de lecture initiale */
+ DBAction action; /* Commande de la requête */
+ GDbItem *item; /* Définition d'élément visé */
+
+ status = safe_recv(fd, &val32, sizeof(uint32_t), 0);
+ if (!status) return false;
+
+ action = be32toh(val32);
+ if (action < 0 || action >= DBA_COUNT) return false;
+
+ item = g_object_new(collec->type, NULL);
+
+ status = g_db_item_recv(item, fd, 0);
+ if (!status) return false;
+
+ result = false;
+
+ switch (action)
+ {
+ case DBA_ADD_ITEM:
+ result = g_db_collection_add_item(collec, item);
+ break;
+
+ case DBA_REM_ITEM:
+ break;
+
+ case DBA_MOD_ITEM:
+ result = g_db_collection_modify_item(collec, item);
+ break;
+
+ default:
+ /* Pour GCC : DBA_COUNT */
+ break;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : collec = ensemble d'éléments à considérer. *
+* fd = flux ouvert en écriture pour l'émission de données. *
+* action = avenir de l'élément fourni. *
+* item = élément de collection à sérialiser. *
+* *
+* Description : Envoie pour traitement une requête réseau pour collection. *
+* *
+* Retour : Bilan de l'exécution de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_db_collection_send(GDbCollection *collec, int fd, DBAction action, GDbItem *item)
+{
+ bool status; /* Bilan de lecture initiale */
+
+ status = safe_send(fd, (uint32_t []) { htobe32(DBC_COLLECTION) }, sizeof(uint32_t), MSG_MORE);
+ if (!status) return false;
+
+ status = safe_send(fd, (uint32_t []) { htobe32(collec->featuring) }, sizeof(uint32_t), MSG_MORE);
+ if (!status) return false;
+
+ status = safe_send(fd, (uint32_t []) { htobe32(action) }, sizeof(uint32_t), MSG_MORE);
+ if (!status) return false;
+
+ status = g_db_item_send(item, fd, 0);
+ if (!status) return false;
+
+ return true;
+
+}
+
+
+
+
+
+
+
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : collec = collection à mettre à jour. *
+* write = précise le type d'accès prévu (lecture/écriture). *
+* lock = indique le sens du verrouillage à mener. *
+* *
+* Description : Met à disposition un encadrement des accès aux éléments. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_db_collection_lock_unlock(GDbCollection *collec, bool write, bool lock)
+{
+ if (write)
+ {
+ if (lock) g_rw_lock_writer_lock(&collec->params_access);
+ else g_rw_lock_writer_unlock(&collec->params_access);
+ }
+ else
+ {
+ if (lock) g_rw_lock_reader_lock(&collec->params_access);
+ else g_rw_lock_reader_unlock(&collec->params_access);
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : collec = ensemble d'éléments à consulter. *
+* *
+* Description : Renvoie la liste des éléments rassemblés. *
+* *
+* Retour : Liste d'éléments à parcourir. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GList *g_db_collection_list_items(const GDbCollection *collec)
+{
+ /**
+ * Un verrou doit être posé !
+ * Il n'y a pas d'assert() possible pour le vérifier...
+ */
+
+ return collec->items;
+
+}
+
+
+
+
+
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : collec = ensemble d'éléments à considérer. *
+* item = élément de collection à manipuler. *
+* *
+* Description : Procède à l'ajout d'un nouvel élément dans la collection. *
+* *
+* Retour : Bilan de l'exécution de l'opération. *
+* *
+* Remarques : L'appelant reste le propriétaire de l'object transféré. *
+* *
+******************************************************************************/
+
+bool g_db_collection_add_item(GDbCollection *collec, GDbItem *item)
+{
+ bool result; /* Bilan à faire remonter */
+ GList *found; /* Test de présence existante */
+
+ g_db_collection_wlock(collec);
+
+ found = g_list_find_custom(collec->items, item, (GCompareFunc)g_db_item_compare);
+
+ if (found != NULL)
+ result = g_db_collection_modify_item(collec, item);
+
+ else
+ {
+ g_object_ref(G_OBJECT(item));
+ collec->items = g_list_append(collec->items, item);
+
+ g_object_ref(G_OBJECT(item));
+ collec->sorted = g_list_insert_sorted(collec->sorted, item, (GCompareFunc)g_db_item_compare);
+
+ g_signal_emit_by_name(collec, "content-changed", DBA_ADD_ITEM, item);
+
+ result = true;
+
+ }
+
+ g_db_collection_wunlock(collec);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : collec = ensemble d'éléments à considérer. *
+* item = élément de collection à copier. *
+* *
+* Description : Procède à la modification d'un élément dans la collection. *
+* *
+* Retour : Bilan de l'exécution de l'opération. *
+* *
+* Remarques : L'appelant reste le propriétaire de l'object transféré. *
+* *
+******************************************************************************/
+
+bool g_db_collection_modify_item(GDbCollection *collec, GDbItem *item)
+{
+ bool result; /* Bilan à faire remonter */
+ GList *found; /* Test de présence existante */
+
+ found = g_list_find_custom(collec->items, item, (GCompareFunc)g_db_item_compare);
+
+
+
+ result = true;
+
+
+
+
+
+ return result;
+
+}
+
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* CREATION DE L'ABSTRACTION POUR COLLECTIONS */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : list = ensemble de collectons à parcourir. *
+* id = identifiant interne du type d'éléments groupés. *
+* *
+* Description : Recherche une collection correspondant à un type donné. *
+* *
+* Retour : Collection trouvée ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GDbCollection *find_collection_in_list(GList *list, uint32_t id)
+{
+ GDbCollection *result; /* Collection trouvée renvoyée */
+ GList *iter; /* Boucle de parcours */
+
+ result = NULL;
+
+ for (iter = g_list_first(list);
+ iter != NULL;
+ iter = g_list_next(iter))
+ {
+ result = G_DB_COLLECTION(iter->data);
+
+ if (g_db_collection_get_feature(result) == id)
+ break;
+
+ }
+
+ return (iter != NULL ? result : NULL);
+
+}
diff --git a/src/analysis/db/collection.h b/src/analysis/db/collection.h
index 715cdc9..75ee7df 100644
--- a/src/analysis/db/collection.h
+++ b/src/analysis/db/collection.h
@@ -25,6 +25,87 @@
#define _ANALYSIS_DB_COLLECTION_H
+#include <glib-object.h>
+#include <stdint.h>
+
+
+#include "item.h"
+#include "protocol.h"
+
+
+
+#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_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;
+
+/* Collection générique d'éléments (classe) */
+typedef struct _GDbCollectionClass GDbCollectionClass;
+
+
+/* Indique le type défini pour une collection générique d'éléments. */
+GType g_db_collection_get_type(void);
+
+/* Prépare la mise en place d'une nouvelle collection. */
+GDbCollection *g_db_collection_new(uint32_t, GType);
+
+
+
+/* Décrit le type des éléments rassemblées dans une collection. */
+uint32_t g_db_collection_get_feature(const GDbCollection *);
+
+
+
+
+/* Réceptionne et traite une requête réseau pour collection. */
+bool g_db_collection_recv(GDbCollection *, int);
+
+/* Envoie pour traitement une requête réseau pour collection. */
+bool g_db_collection_send(GDbCollection *, int, DBAction, GDbItem *);
+
+
+
+
+
+
+/* Met à disposition un encadrement des accès aux éléments. */
+void g_db_collection_lock_unlock(GDbCollection *, bool, bool);
+
+
+#define g_db_collection_wlock(col) g_db_collection_lock_unlock(col, true, true);
+#define g_db_collection_wunlock(col) g_db_collection_lock_unlock(col, true, false);
+
+#define g_db_collection_rlock(col) g_db_collection_lock_unlock(col, false, true);
+#define g_db_collection_runlock(col) g_db_collection_lock_unlock(col, false, false);
+
+
+/* Renvoie la liste des éléments rassemblés. */
+GList *g_db_collection_list_items(const GDbCollection *);
+
+
+
+
+/* Procède à l'ajout d'un nouvel élément dans la collection. */
+bool g_db_collection_add_item(GDbCollection *, GDbItem *);
+
+/* Procède à la modification d'un élément dans la collection. */
+bool g_db_collection_modify_item(GDbCollection *, GDbItem *);
+
+
+
+
+
+/* ------------------- CREATION DE L'ABSTRACTION POUR COLLECTIONS ------------------- */
+
+
+/* Recherche une collection correspondant à un type donné. */
+GDbCollection *find_collection_in_list(GList *, uint32_t);
+
#endif /* _ANALYSIS_DB_COLLECTION_H */
diff --git a/src/analysis/db/core.c b/src/analysis/db/core.c
index 0bc5f50..81ea117 100644
--- a/src/analysis/db/core.c
+++ b/src/analysis/db/core.c
@@ -142,6 +142,7 @@ void init_core_db_info(core_db_info *info, uint64_t type, const char *user)
bool load_core_db_info(core_db_info *info, uint64_t type, int fd)
{
+#if 0
ssize_t got; /* Quantité de données reçues */
uint64_t val64; /* Valeur sur 64 bits */
@@ -163,7 +164,7 @@ bool load_core_db_info(core_db_info *info, uint64_t type, int fd)
info->modified = be64toh(val64);
info->saved = info->modified;
-
+#endif
return true;
}
@@ -184,6 +185,7 @@ bool load_core_db_info(core_db_info *info, uint64_t type, int fd)
bool store_core_db_info(core_db_info *info, int fd)
{
+#if 0
ssize_t got; /* Quantité de données reçues */
got = safe_send(fd, (uint64_t []) { htobe64(info->type) }, sizeof(uint64_t), MSG_WAITALL);
@@ -199,7 +201,7 @@ bool store_core_db_info(core_db_info *info, int fd)
if (got != sizeof(uint64_t)) return false;
info->saved = time(NULL);
-
+#endif
return true;
}
diff --git a/src/analysis/db/item-int.h b/src/analysis/db/item-int.h
new file mode 100644
index 0000000..b6d8f9c
--- /dev/null
+++ b/src/analysis/db/item-int.h
@@ -0,0 +1,68 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * item-int.h - prototypes et définitions internes pour les bases d'éléments de collection
+ *
+ * Copyright (C) 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/>.
+ */
+
+
+#ifndef _ANALYSIS_DB_ITEM_INT_H
+#define _ANALYSIS_DB_ITEM_INT_H
+
+
+#include "item.h"
+
+
+#include <stdint.h>
+
+
+
+/* Importe la définition d'une base d'éléments pour collection. */
+typedef bool (* recv_db_item_fc) (GDbItem *, int, int);
+
+/* Exporte la définition d'une base d'éléments pour collection. */
+typedef bool (* send_db_item_fc) (const GDbItem *, int, int);
+
+
+/* Base d'un élément pour collection générique (instance) */
+struct _GDbItem
+{
+ GObject parent; /* A laisser en premier */
+
+ uint64_t created; /* Date de création */
+ uint64_t modified; /* Date de modification */
+
+ bool is_volatile; /* Pas besoin de sauvegarde ? */
+
+};
+
+/* Base d'un élément pour collection générique (classe) */
+struct _GDbItemClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+ GCompareFunc cmp; /* Comparaison entre éléments */
+
+ recv_db_item_fc recv; /* Réception depuis le réseau */
+ send_db_item_fc send; /* Emission depuis le réseau */
+
+};
+
+
+
+#endif /* _ANALYSIS_DB_ITEM_INT_H */
diff --git a/src/analysis/db/item.c b/src/analysis/db/item.c
new file mode 100644
index 0000000..e2fd7f3
--- /dev/null
+++ b/src/analysis/db/item.c
@@ -0,0 +1,356 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * item.c - gestion d'éléments destinés à une collection générique
+ *
+ * Copyright (C) 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 "item.h"
+
+
+#include "item-int.h"
+#include "../../common/io.h"
+
+
+
+/* Initialise la classe des bases d'éléments pour collection. */
+static void g_db_item_class_init(GDbItemClass *);
+
+/* Initialise une base d'élément pour collection générique. */
+static void g_db_item_init(GDbItem *);
+
+/* Supprime toutes les références externes. */
+static void g_db_item_dispose(GDbItem *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_db_item_finalize(GDbItem *);
+
+/* Effectue la comparaison entre deux éléments de collection. */
+static gint g_db_item_cmp(GDbItem *, GDbItem *);
+
+/* Importe la définition d'une base d'éléments pour collection. */
+static bool g_db_item_recv_from_fd(GDbItem *, int, int);
+
+/* Exporte la définition d'une base d'éléments pour collection. */
+static bool g_db_item_send_to_fd(const GDbItem *, int, int);
+
+
+
+
+/* Indique le type défini pour une base d'élément de collection générique. */
+G_DEFINE_TYPE(GDbItem, g_db_item, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des bases d'éléments pour collection. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_db_item_class_init(GDbItemClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_db_item_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_db_item_finalize;
+
+ klass->cmp = (GCompareFunc)g_db_item_cmp;
+
+ klass->recv = (recv_db_item_fc)g_db_item_recv_from_fd;
+ klass->send = (send_db_item_fc)g_db_item_send_to_fd;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = instance à initialiser. *
+* *
+* Description : Initialise une base d'élément pour collection générique. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_db_item_init(GDbItem *item)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_db_item_dispose(GDbItem *item)
+{
+ G_OBJECT_CLASS(g_db_item_parent_class)->dispose(G_OBJECT(item));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_db_item_finalize(GDbItem *item)
+{
+ G_OBJECT_CLASS(g_db_item_parent_class)->finalize(G_OBJECT(item));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : a = premier élément à analyser. *
+* b = second élément à analyser. *
+* *
+* Description : Effectue la comparaison entre deux éléments de collection. *
+* *
+* Retour : Bilan de la comparaison : -1, 0 ou 1. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static gint g_db_item_cmp(GDbItem *a, GDbItem *b)
+{
+ gint result; /* Bilan à retourner */
+
+ /**
+ * A n'utiliser qu'en dernier recours, pour départager deux
+ * éléments par un serveur NTP...
+ */
+
+ if (a->modified > b->modified)
+ result = 1;
+
+ else if (a->modified < b->modified)
+ result = -1;
+
+ else
+ {
+ if (a->created > b->created)
+ result = 1;
+
+ else if (a->created < b->created)
+ result = -1;
+
+ else
+ result = 0;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : a = premier élément à analyser. *
+* b = second élément à analyser. *
+* *
+* Description : Effectue la comparaison entre deux éléments de collection. *
+* *
+* Retour : Bilan de la comparaison : -1, 0 ou 1. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+gint g_db_item_compare(GDbItem *a, GDbItem *b)
+{
+ return G_DB_ITEM_GET_CLASS(a)->cmp(a, b);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = base d'éléments à charger. [OUT] *
+* fd = flux ouvert en lecture pour l'importation. *
+* flags = éventuelles options d'envoi supplémentaires. *
+* *
+* Description : Importe la définition d'une base d'éléments pour collection. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_db_item_recv_from_fd(GDbItem *item, int fd, int flags)
+{
+ uint64_t val64; /* Valeur sur 64 bits */
+ bool status; /* Bilan d'une réception */
+
+ status = safe_recv(fd, &val64, sizeof(uint64_t), flags);
+ if (!status) return false;
+
+ item->created = be64toh(val64);
+
+ status = safe_recv(fd, &val64, sizeof(uint64_t), flags);
+ if (!status) return false;
+
+ item->modified = be64toh(val64);
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = base d'éléments à charger. [OUT] *
+* fd = flux ouvert en lecture pour l'importation. *
+* flags = éventuelles options d'envoi supplémentaires. *
+* *
+* Description : Importe la définition d'une base d'éléments pour collection. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_db_item_recv(GDbItem *item, int fd, int flags)
+{
+ return G_DB_ITEM_GET_CLASS(item)->recv(item, fd, flags);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = informations à sauvegarer. *
+* fd = flux ouvert en écriture pour l'exportation. *
+* flags = éventuelles options d'envoi supplémentaires. *
+* *
+* Description : Exporte la définition d'une base d'éléments pour collection. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_db_item_send_to_fd(const GDbItem *item, int fd, int flags)
+{
+ bool status; /* Bilan d'une émission */
+
+
+ printf("<sending> FROM %s...\n", __FUNCTION__);
+
+
+ status = safe_send(fd, (uint64_t []) { htobe64(item->created) }, sizeof(uint64_t), MSG_MORE | flags);
+ if (!status) return false;
+
+ status = safe_send(fd, (uint64_t []) { htobe64(item->modified) }, sizeof(uint64_t), flags);
+ if (!status) return false;
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = informations à sauvegarer. *
+* fd = flux ouvert en écriture pour l'exportation. *
+* flags = éventuelles options d'envoi supplémentaires. *
+* *
+* Description : Exporte la définition d'une base d'éléments pour collection. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_db_item_send(const GDbItem *item, int fd, int flags)
+{
+ return G_DB_ITEM_GET_CLASS(item)->send(item, fd, flags);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = base d'éléments à modifier. *
+* is_volatile = état du besoin en sauvegarde. *
+* *
+* Description : Définit si l'élément contient des données à oublier ou non. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_db_item_set_volatile(GDbItem *item, bool is_volatile)
+{
+ item->is_volatile = is_volatile;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = base d'éléments à consulter. *
+* *
+* Description : Indique si l'élément contient des données à oublier ou non. *
+* *
+* Retour : Etat du besoin en sauvegarde. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_db_item_is_volatile(const GDbItem *item)
+{
+ return item->is_volatile;
+
+}
diff --git a/src/analysis/db/item.h b/src/analysis/db/item.h
new file mode 100644
index 0000000..3938610
--- /dev/null
+++ b/src/analysis/db/item.h
@@ -0,0 +1,68 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * item.h - prototypes pour la gestion d'éléments destinés à une collection générique
+ *
+ * Copyright (C) 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/>.
+ */
+
+
+#ifndef _ANALYSIS_DB_ITEM_H
+#define _ANALYSIS_DB_ITEM_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+
+
+
+#define G_TYPE_DB_ITEM g_db_item_get_type()
+#define G_DB_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_db_item_get_type(), GDbItem))
+#define G_IS_DB_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_db_item_get_type()))
+#define G_DB_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DB_ITEM, GDbItemClass))
+#define G_IS_DB_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DB_ITEM))
+#define G_DB_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DB_ITEM, GDbItemClass))
+
+
+/* Base d'un élément pour collection générique (instance) */
+typedef struct _GDbItem GDbItem;
+
+/* Base d'un élément pour collection générique (classe) */
+typedef struct _GDbItemClass GDbItemClass;
+
+
+/* Indique le type défini pour une base d'élément de collection générique. */
+GType g_db_item_get_type(void);
+
+/* Effectue la comparaison entre deux éléments de collection. */
+gint g_db_item_compare(GDbItem *, GDbItem *);
+
+/* Importe la définition d'une base d'éléments pour collection. */
+bool g_db_item_recv(GDbItem *, int, int);
+
+/* Exporte la définition d'une base d'éléments pour collection. */
+bool g_db_item_send(const GDbItem *, int, int);
+
+/* Définit si l'élément contient des données à oublier ou non. */
+void g_db_item_set_volatile(GDbItem *, bool);
+
+/* Indique si l'élément contient des données à oublier ou non. */
+bool g_db_item_is_volatile(const GDbItem *);
+
+
+
+#endif /* _ANALYSIS_DB_ITEM_H */
diff --git a/src/analysis/db/items/Makefile.am b/src/analysis/db/items/Makefile.am
new file mode 100644
index 0000000..f026d44
--- /dev/null
+++ b/src/analysis/db/items/Makefile.am
@@ -0,0 +1,17 @@
+
+noinst_LTLIBRARIES = libanalysisdbitems.la
+
+libanalysisdbitems_la_SOURCES = \
+ bookmark.h bookmark.c \
+ comment.h comment.c
+
+libanalysisdbitems_la_LIBADD =
+
+libanalysisdbitems_la_LDFLAGS =
+
+
+AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBARCHIVE_CFLAGS) $(LIBSQLITE_CFLAGS)
+
+AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
+
+SUBDIRS =
diff --git a/src/analysis/db/items/bookmark.c b/src/analysis/db/items/bookmark.c
new file mode 100644
index 0000000..c28a837
--- /dev/null
+++ b/src/analysis/db/items/bookmark.c
@@ -0,0 +1,416 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * bookmark.h - prototypes pour la gestion des signets au sein d'un binaire
+ *
+ * Copyright (C) 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 <stdio.h>
+#include <sys/socket.h>
+
+
+#include "../item-int.h"
+#include "../misc/rlestr.h"
+
+
+
+/* Signet à l'intérieur d'une zone de texte (instance) */
+struct _GDbBookmark
+{
+ GDbItem parent; /* A laisser en premier */
+
+ vmpa2t addr; /* Adresse du signet */
+ rle_string comment; /* Eventuel commentaire associé*/
+
+};
+
+/* Signet à l'intérieur d'une zone de texte (classe) */
+struct _GDbBookmarkClass
+{
+ GDbItemClass parent; /* A laisser en premier */
+
+};
+
+
+
+/* Initialise la classe des signets dans une zone de texte. */
+static void g_db_bookmark_class_init(GDbBookmarkClass *);
+
+/* Initialise un signet dans une zone de texte. */
+static void g_db_bookmark_init(GDbBookmark *);
+
+/* Supprime toutes les références externes. */
+static void g_db_bookmark_dispose(GDbBookmark *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_db_bookmark_finalize(GDbBookmark *);
+
+
+
+/* Effectue la comparaison entre deux signets de collection. */
+static gint g_db_bookmark_cmp(GDbBookmark *, GDbBookmark *);
+
+/* Importe la définition d'un signet dans un flux réseau. */
+static bool g_db_bookmark_recv_from_fd(GDbBookmark *, int, int);
+
+/* Exporte la définition d'un signet dans un flux réseau. */
+static bool g_db_bookmark_send_to_fd(const GDbBookmark *, int, int);
+
+
+
+
+/******************************************************************************
+* *
+* 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 (" \
+ "id INT PRIMARY KEY NOT NULL, " \
+ "user TEXT NOT NULL, " \
+ "created INT NOT NULL, " \
+ "address INT NOT NULL, " \
+ "comment TEXT" \
+ ");";
+
+ ret = sqlite3_exec(db, sql, NULL, NULL, &msg);
+ if (ret != SQLITE_OK)
+ {
+ fprintf(stderr, "sqlite3_exec(): %s\n", msg);
+ sqlite3_free(msg);
+ }
+
+ return (ret == SQLITE_OK);
+
+}
+
+
+
+
+
+
+
+
+
+
+/* Indique le type défini pour un signet à l'intérieur d'une zone de texte. */
+G_DEFINE_TYPE(GDbBookmark, g_db_bookmark, G_TYPE_DB_ITEM);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des signets dans une zone de texte. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_db_bookmark_class_init(GDbBookmarkClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GDbItemClass *item; /* Encore une autre vision... */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_db_bookmark_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_db_bookmark_finalize;
+
+ item = G_DB_ITEM_CLASS(klass);
+
+ item->cmp = (GCompareFunc)g_db_bookmark_cmp;
+
+ item->recv = (recv_db_item_fc)g_db_bookmark_recv_from_fd;
+ item->send = (send_db_item_fc)g_db_bookmark_send_to_fd;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : bookmark = instance à initialiser. *
+* *
+* Description : Initialise un signet dans une zone de texte. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_db_bookmark_init(GDbBookmark *bookmark)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : bookmark = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_db_bookmark_dispose(GDbBookmark *bookmark)
+{
+ G_OBJECT_CLASS(g_db_bookmark_parent_class)->dispose(G_OBJECT(bookmark));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : bookmark = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_db_bookmark_finalize(GDbBookmark *bookmark)
+{
+ G_OBJECT_CLASS(g_db_bookmark_parent_class)->finalize(G_OBJECT(bookmark));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : addr = adresse inamovible localisant une position donnée. *
+* comment = commentaire construit ou NULL. *
+* *
+* Description : Crée une définition d'un signet dans une zone de texte. *
+* *
+* Retour : Signet mis en place ou NULL en cas d'erreur. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GDbBookmark *g_db_bookmark_new(const vmpa2t *addr, const char *comment)
+{
+ GDbBookmark *result; /* Instance à retourner */
+
+ result = g_object_new(G_TYPE_DB_BOOKMARK, NULL);
+
+
+
+
+ /* TODO */
+
+ //dup addr;
+
+
+ g_db_bookmark_set_comment(result, comment);
+
+ return result;
+
+}
+
+
+
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : a = premier élément à analyser. *
+* b = second élément à analyser. *
+* *
+* Description : Effectue la comparaison entre deux signets de collection. *
+* *
+* Retour : Bilan de la comparaison : -1, 0 ou 1. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static gint g_db_bookmark_cmp(GDbBookmark *a, GDbBookmark *b)
+{
+ gint result; /* Bilan de la comparaison */
+
+ result = cmp_vmpa_by_phy(&a->addr, &b->addr);
+
+ if (result == 0)
+ result = cmp_rle_string(&a->comment, &b->comment);
+
+ return 0;
+
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : bookmark = signet dont les informations sont à charger. [OUT]*
+* fd = flux ouvert en lecture pour l'importation. *
+* flags = éventuelles options d'envoi supplémentaires. *
+* *
+* Description : Importe la définition d'un signet dans un flux réseau. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_db_bookmark_recv_from_fd(GDbBookmark *bookmark, int fd, int flags)
+{
+ bool status; /* Bilan d'opération initiale */
+
+ status = G_DB_ITEM_CLASS(g_db_bookmark_parent_class)->recv(G_DB_ITEM(bookmark), fd, flags);
+ if (!status) return false;
+
+ if (!recv_vmpa(&bookmark->addr, fd, 0))
+ return false;
+
+ if (!recv_rle_string(&bookmark->comment, fd, 0))
+ return false;
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : bookmark = informations à sauvegarder. *
+* fd = flux ouvert en écriture pour l'exportation. *
+* flags = éventuelles options d'envoi supplémentaires. *
+* *
+* Description : Exporte la définition d'un signet dans un flux réseau. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_db_bookmark_send_to_fd(const GDbBookmark *bookmark, int fd, int flags)
+{
+ bool status; /* Bilan d'opération initiale */
+
+ status = G_DB_ITEM_CLASS(g_db_bookmark_parent_class)->send(G_DB_ITEM(bookmark), fd, MSG_MORE | flags);
+ if (!status) return false;
+
+
+ printf("<sending> FROM %s...\n", __FUNCTION__);
+
+
+ if (!send_vmpa(&bookmark->addr, fd, MSG_MORE | flags))
+ return false;
+
+ if (!send_rle_string(&bookmark->comment, fd, flags))
+ return false;
+
+ return true;
+
+}
+
+
+
+
+
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : bookmark = informations à consulter. *
+* *
+* Description : Fournit l'adresse associée à un signet. *
+* *
+* Retour : Adresse mémoire. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+vmpa2t *g_db_bookmark_get_address(GDbBookmark *bookmark)
+{
+ return &bookmark->addr;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : bookmark = informations à consulter. *
+* *
+* Description : Fournit le commentaire associé à un signet. *
+* *
+* Retour : Commentaire existant ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const char *g_db_bookmark_get_comment(const GDbBookmark *bookmark)
+{
+ return get_rle_string(&bookmark->comment);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : bookmark = informations à consulter. *
+* comment = commentaire construit ou NULL. *
+* *
+* Description : Définit le commentaire associé à un signet. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_db_bookmark_set_comment(GDbBookmark *bookmark, const char *comment)
+{
+ set_rle_string(&bookmark->comment, comment);
+
+}
diff --git a/src/analysis/db/items/bookmark.h b/src/analysis/db/items/bookmark.h
new file mode 100644
index 0000000..d1b073c
--- /dev/null
+++ b/src/analysis/db/items/bookmark.h
@@ -0,0 +1,79 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * bookmark.h - prototypes pour la gestion des signets au sein d'un binaire
+ *
+ * Copyright (C) 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/>.
+ */
+
+
+#ifndef _ANALYSIS_DB_ITEMS_BOOKMARK_H
+#define _ANALYSIS_DB_ITEMS_BOOKMARK_H
+
+
+
+#include <glib-object.h>
+#include <sqlite3.h>
+#include <stdbool.h>
+
+
+#include "../../../arch/vmpa.h"
+
+
+
+/* Crée la table des signets dans une base de données. */
+bool create_bookmark_db_table(sqlite3 *);
+
+
+
+
+
+
+
+#define G_TYPE_DB_BOOKMARK g_db_bookmark_get_type()
+#define G_DB_BOOKMARK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_db_bookmark_get_type(), GDbBookmark))
+#define G_IS_DB_BOOKMARK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_db_bookmark_get_type()))
+#define G_DB_BOOKMARK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DB_BOOKMARK, GDbBookmarkClass))
+#define G_IS_DB_BOOKMARK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DB_BOOKMARK))
+#define G_DB_BOOKMARK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DB_BOOKMARK, GDbBookmarkClass))
+
+
+/* Signet à l'intérieur d'une zone de texte (instance) */
+typedef struct _GDbBookmark GDbBookmark;
+
+/* Signet à l'intérieur d'une zone de texte (classe) */
+typedef struct _GDbBookmarkClass GDbBookmarkClass;
+
+
+/* Indique le type défini pour un signet à l'intérieur d'une zone de texte. */
+GType g_db_bookmark_get_type(void);
+
+/* Crée une définition d'un signet dans une zone de texte. */
+GDbBookmark *g_db_bookmark_new(const vmpa2t *, const char *);
+
+/* Fournit l'adresse associée à un signet. */
+vmpa2t *g_db_bookmark_get_address(GDbBookmark *);
+
+/* Fournit le commentaire associé à un signet. */
+const char *g_db_bookmark_get_comment(const GDbBookmark *);
+
+/* Définit le commentaire associé à un signet. */
+void g_db_bookmark_set_comment(GDbBookmark *, const char *);
+
+
+
+#endif /* _ANALYSIS_DB_ITEMS_BOOKMARK_H */
diff --git a/src/analysis/db/items/comment.c b/src/analysis/db/items/comment.c
new file mode 100644
index 0000000..73a18b0
--- /dev/null
+++ b/src/analysis/db/items/comment.c
@@ -0,0 +1,398 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * comment.c - gestion des commentaires dans du texte
+ *
+ * Copyright (C) 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 "comment.h"
+
+
+#include <stdio.h>
+#include <sys/socket.h>
+
+
+#include "../item-int.h"
+#include "../misc/rlestr.h"
+
+
+
+/* Commentaire à placer dans du texte quelconque (instance) */
+struct _GDbComment
+{
+ GDbItem parent; /* A laisser en premier */
+
+ vmpa2t *addr; /* Adresse du commentaire */
+ rle_string text; /* Contenu du commentaire */
+
+};
+
+/* Commentaire à placer dans du texte quelconque (classe) */
+struct _GDbCommentClass
+{
+ GDbItemClass parent; /* A laisser en premier */
+
+};
+
+
+
+/* Initialise la classe des commentaires dans une zone de texte. */
+static void g_db_comment_class_init(GDbCommentClass *);
+
+/* Initialise un commentaire dans une zone de texte. */
+static void g_db_comment_init(GDbComment *);
+
+/* Supprime toutes les références externes. */
+static void g_db_comment_dispose(GDbComment *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_db_comment_finalize(GDbComment *);
+
+/* Effectue la comparaison entre deux commentaires enregistrés. */
+static gint g_db_comment_cmp(GDbComment *, GDbComment *);
+
+/* Importe la définition d'un commentaire dans un flux réseau. */
+static bool g_db_comment_recv_from_fd(GDbComment *, int, int);
+
+/* Exporte la définition d'un commentaire dans un flux réseau. */
+static bool g_db_comment_send_to_fd(const GDbComment *, int, int);
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : db = accès à la base de données. *
+* *
+* Description : Crée la table des commentaires dans une base de données. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool create_comment_db_table(sqlite3 *db)
+{
+ char *sql; /* Requête à exécuter */
+ int ret; /* Bilan de la création */
+ char *msg; /* Message d'erreur */
+
+ sql = "CREATE TABLE Comments (" \
+ "id INT PRIMARY KEY NOT NULL, " \
+ "user TEXT NOT NULL, " \
+ "created INT NOT NULL, " \
+ "address INT NOT NULL, " \
+ "comment TEXT" \
+ ");";
+
+ ret = sqlite3_exec(db, sql, NULL, NULL, &msg);
+ if (ret != SQLITE_OK)
+ {
+ fprintf(stderr, "sqlite3_exec(): %s\n", msg);
+ sqlite3_free(msg);
+ }
+
+ return (ret == SQLITE_OK);
+
+}
+
+
+
+
+
+
+
+
+
+
+/* Indique le type défini pour un commentaire à l'intérieur d'une zone de texte. */
+G_DEFINE_TYPE(GDbComment, g_db_comment, G_TYPE_DB_ITEM);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des commentaires dans une zone de texte.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_db_comment_class_init(GDbCommentClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GDbItemClass *item; /* Encore une autre vision... */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_db_comment_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_db_comment_finalize;
+
+ item = G_DB_ITEM_CLASS(klass);
+
+ item->cmp = (GCompareFunc)g_db_comment_cmp;
+
+ item->recv = (recv_db_item_fc)g_db_comment_recv_from_fd;
+ item->send = (send_db_item_fc)g_db_comment_send_to_fd;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : comment = instance à initialiser. *
+* *
+* Description : Initialise un commentaire dans une zone de texte. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_db_comment_init(GDbComment *comment)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : comment = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_db_comment_dispose(GDbComment *comment)
+{
+ G_OBJECT_CLASS(g_db_comment_parent_class)->dispose(G_OBJECT(comment));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : comment = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_db_comment_finalize(GDbComment *comment)
+{
+ delete_vmpa(comment->addr);
+
+ exit_rle_string(comment->text);
+
+ G_OBJECT_CLASS(g_db_comment_parent_class)->finalize(G_OBJECT(comment));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : addr = adresse inamovible localisant une position. *
+* text = commentaire construit ou NULL. *
+* is_volatile = état du besoin en sauvegarde. *
+* *
+* Description : Crée une définition de commentaire dans une zone de texte. *
+* *
+* Retour : Commentaire mis en place ou NULL en cas d'erreur. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GDbComment *g_db_comment_new(const vmpa2t *addr, const char *text, bool is_volatile)
+{
+ GDbComment *result; /* Instance à retourner */
+
+ result = g_object_new(G_TYPE_DB_COMMENT, NULL);
+
+ result->addr = dup_vmpa(addr);
+
+ g_db_comment_set_text(result, text);
+
+ g_db_item_set_volatile(G_DB_ITEM(result), is_volatile);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : a = premier élément à analyser. *
+* b = second élément à analyser. *
+* *
+* Description : Effectue la comparaison entre deux commentaires enregistrés. *
+* *
+* Retour : Bilan de la comparaison : -1, 0 ou 1. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static gint g_db_comment_cmp(GDbComment *a, GDbComment *b)
+{
+ gint result; /* Bilan de la comparaison */
+
+ result = cmp_vmpa_by_phy(a->addr, b->addr);
+
+ if (result == 0)
+ result = cmp_rle_string(&a->text, &b->text);
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : comment = commentaire avec informations sont à charger. [OUT]*
+* fd = flux ouvert en lecture pour l'importation. *
+* flags = éventuelles options d'envoi supplémentaires. *
+* *
+* Description : Importe la définition d'un commentaire dans un flux réseau. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_db_comment_recv_from_fd(GDbComment *comment, int fd, int flags)
+{
+ bool status; /* Bilan d'opération initiale */
+
+ status = G_DB_ITEM_CLASS(g_db_comment_parent_class)->recv(G_DB_ITEM(comment), fd, flags);
+ if (!status) return false;
+
+ if (!recv_vmpa(comment->addr, fd, 0))
+ return false;
+
+ if (!recv_rle_string(&comment->text, fd, 0))
+ return false;
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : comment = informations à sauvegarder. *
+* fd = flux ouvert en écriture pour l'exportation. *
+* flags = éventuelles options d'envoi supplémentaires. *
+* *
+* Description : Exporte la définition d'un commentaire dans un flux réseau. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_db_comment_send_to_fd(const GDbComment *comment, int fd, int flags)
+{
+ bool status; /* Bilan d'opération initiale */
+
+ status = G_DB_ITEM_CLASS(g_db_comment_parent_class)->send(G_DB_ITEM(comment), fd, MSG_MORE | flags);
+ if (!status) return false;
+
+ if (!send_vmpa(comment->addr, fd, MSG_MORE | flags))
+ return false;
+
+ if (!send_rle_string(&comment->text, fd, flags))
+ return false;
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : comment = informations à consulter. *
+* *
+* Description : Fournit l'adresse associée à un commentaire. *
+* *
+* Retour : Adresse mémoire. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const vmpa2t *g_db_comment_get_address(GDbComment *comment)
+{
+ return comment->addr;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : comment = informations à consulter. *
+* *
+* Description : Fournit le commentaire associé à un commentaire. *
+* *
+* Retour : Commentaire existant ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const char *g_db_comment_get_text(const GDbComment *comment)
+{
+ return get_rle_string(&comment->text);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : comment = informations à consulter. *
+* text = commentaire construit ou NULL. *
+* *
+* Description : Définit le commentaire associé à un commentaire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_db_comment_set_text(GDbComment *comment, const char *text)
+{
+ set_rle_string(&comment->text, text);
+
+}
diff --git a/src/analysis/db/items/comment.h b/src/analysis/db/items/comment.h
new file mode 100644
index 0000000..792fb92
--- /dev/null
+++ b/src/analysis/db/items/comment.h
@@ -0,0 +1,77 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * comment.h - prototypes pour la gestion des commentaires dans du texte
+ *
+ * Copyright (C) 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/>.
+ */
+
+
+#ifndef _ANALYSIS_DB_ITEMS_COMMENT_H
+#define _ANALYSIS_DB_ITEMS_COMMENT_H
+
+
+
+#include <glib-object.h>
+#include <sqlite3.h>
+#include <stdbool.h>
+
+
+#include "../../../arch/vmpa.h"
+
+
+
+/* Crée la table des commentaires dans une base de données. */
+bool create_comment_db_table(sqlite3 *);
+
+
+
+
+
+#define G_TYPE_DB_COMMENT g_db_comment_get_type()
+#define G_DB_COMMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_db_comment_get_type(), GDbComment))
+#define G_IS_DB_COMMENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_db_comment_get_type()))
+#define G_DB_COMMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DB_COMMENT, GDbCommentClass))
+#define G_IS_DB_COMMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DB_COMMENT))
+#define G_DB_COMMENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DB_COMMENT, GDbCommentClass))
+
+
+/* Commentaire à placer dans du texte quelconque (instance) */
+typedef struct _GDbComment GDbComment;
+
+/* Commentaire à placer dans du texte quelconque (classe) */
+typedef struct _GDbCommentClass GDbCommentClass;
+
+
+/* Indique le type défini pour un commentaire à l'intérieur d'une zone de texte. */
+GType g_db_comment_get_type(void);
+
+/* Crée une définition de commentaire dans une zone de texte. */
+GDbComment *g_db_comment_new(const vmpa2t *, const char *, bool);
+
+/* Fournit l'adresse associée à un commentaire. */
+const vmpa2t *g_db_comment_get_address(GDbComment *);
+
+/* Fournit le commentaire associé à un commentaire. */
+const char *g_db_comment_get_text(const GDbComment *);
+
+/* Définit le commentaire associé à un commentaire. */
+void g_db_comment_set_text(GDbComment *, const char *);
+
+
+
+#endif /* _ANALYSIS_DB_ITEMS_COMMENT_H */
diff --git a/src/analysis/db/misc/Makefile.am b/src/analysis/db/misc/Makefile.am
new file mode 100755
index 0000000..b3829e3
--- /dev/null
+++ b/src/analysis/db/misc/Makefile.am
@@ -0,0 +1,16 @@
+
+noinst_LTLIBRARIES = libanalysisdbmisc.la
+
+libanalysisdbmisc_la_SOURCES = \
+ rlestr.h rlestr.c
+
+libanalysisdbmisc_la_LIBADD =
+
+libanalysisdbmisc_la_LDFLAGS =
+
+
+AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBARCHIVE_CFLAGS) $(LIBSQLITE_CFLAGS)
+
+AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
+
+SUBDIRS =
diff --git a/src/analysis/db/misc/rlestr.c b/src/analysis/db/misc/rlestr.c
new file mode 100644
index 0000000..d75e7ab
--- /dev/null
+++ b/src/analysis/db/misc/rlestr.c
@@ -0,0 +1,345 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * rlestr.c - encodage par plage unique d'une chaîne de caractères
+ *
+ * Copyright (C) 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 "rlestr.h"
+
+
+#include <endian.h>
+#include <malloc.h>
+#include <string.h>
+
+
+#include "../../../common/io.h"
+
+
+
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <time.h>
+#include <unistd.h>
+
+
+
+
+
+
+
+
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : str = représentation de chaîne à traiter. *
+* data = données à conserver en mémoire. *
+* *
+* Description : Définit une représentation de chaîne de caractères. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void init_rle_string(rle_string *str, const char *data)
+{
+ if (data != NULL)
+ {
+ str->data = strdup(data);
+ str->length = strlen(data);
+ }
+ else
+ {
+ str->data = NULL;
+ str->length = 0;
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : str = représentation de chaîne à traiter. *
+* data = données à conserver en mémoire. *
+* *
+* Description : Constitue une représentation de chaîne de caractères. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void set_rle_string(rle_string *str, const char *data)
+{
+ if (str->data != NULL)
+ unset_rle_string(str);
+
+ if (data != NULL)
+ {
+ str->data = strdup(data);
+ str->length = strlen(data);
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : str = représentation de chaîne à traiter. *
+* *
+* Description : Libère la mémoire associée à la représentation. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void unset_rle_string(rle_string *str)
+{
+ if (str->data != NULL)
+ {
+ free(str->data);
+ str->data = NULL;
+
+ str->length = 0;
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : s1 = première chaîne à comparer. *
+* s2 = seconde chaîne à comparer. *
+* *
+* Description : Effectue la comparaison entre deux chaînes de caractères. *
+* *
+* Retour : Résultat de la comparaison : -1, 0 ou 1. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int cmp_rle_string(const rle_string *s1, const rle_string *s2)
+{
+ int result; /* Bilan à retourner */
+
+ if (s1->length < s2->length)
+ result = -1;
+
+ else if (s1->length > s2->length)
+ result = 1;
+
+ else
+ {
+ if (s1->data == NULL && s2->data == NULL)
+ result = 0;
+
+ else if (s1->data != NULL && s2->data == NULL)
+ result = 1;
+
+ else if (s1->data == NULL && s2->data != NULL)
+ result = -1;
+
+ else
+ result = strcmp(s1->data, s2->data);
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : str = informations à constituer. [OUT] *
+* fd = flux ouvert en lecture pour l'importation. *
+* *
+* Description : Importe la définition d'une chaîne de caractères. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool load_rle_string(rle_string *str, int fd)
+{
+#if 0
+ uint32_t val32; /* Valeur sur 32 bits */
+ ssize_t got; /* Quantité de données reçues */
+
+ got = safe_recv(fd, &val32, sizeof(uint32_t), MSG_WAITALL);
+ if (got != sizeof(uint32_t)) return false;
+
+ str->length = le32toh(val32);
+
+ if (str->length > 0)
+ {
+ str->data = (char *)malloc(str->length + 1);
+
+ got = safe_recv(fd, str->data, str->length + 1, MSG_WAITALL);
+ if (got != (str->length + 1))
+ {
+ unset_rle_string(str);
+ return false;
+ }
+
+ str->data[str->length] = '\0';
+
+ }
+#endif
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : str = informations à sauvegarer. *
+* fd = flux ouvert en écriture pour l'exportation. *
+* *
+* Description : Exporte la définition d'une chaîne de caractères. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool store_rle_string(const rle_string *str, int fd)
+{
+#if 0
+ ssize_t got; /* Quantité de données reçues */
+
+ got = safe_send(fd, (uint32_t []) { htole32(str->length) }, sizeof(uint32_t), MSG_WAITALL);
+ if (got != sizeof(uint32_t)) return false;
+
+ if (str->length > 0)
+ {
+ got = safe_send(fd, str->data, str->length + 1, MSG_WAITALL);
+ if (got != (str->length + 1)) return false;
+ }
+#endif
+ return true;
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : str = informations à constituer. [OUT] *
+* fd = flux ouvert en lecture pour l'importation. *
+* flags = éventuelles options de réception supplémentaires. *
+* *
+* Description : Importe la définition d'une chaîne de caractères. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool recv_rle_string(rle_string *str, int fd, int flags)
+{
+ uint32_t val32; /* Valeur sur 32 bits */
+ bool status; /* Bilan d'une opération */
+
+ str->data = NULL;
+ str->length = 0;
+
+ status = safe_recv(fd, &val32, sizeof(uint32_t), flags);
+ if (!status) return false;
+
+ str->length = be32toh(val32);
+
+ if (str->length > 0)
+ {
+ str->data = (char *)malloc(str->length + 1);
+
+ status = safe_recv(fd, str->data, str->length + 1, flags);
+ if (!status)
+ {
+ unset_rle_string(str);
+ return false;
+ }
+
+ str->data[str->length] = '\0';
+
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : str = informations à sauvegarer. *
+* fd = flux ouvert en écriture pour l'exportation. *
+* flags = éventuelles options d'envoi supplémentaires. *
+* *
+* Description : Exporte la définition d'une chaîne de caractères. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool send_rle_string(const rle_string *str, int fd, int flags)
+{
+ bool status; /* Bilan d'une opération */
+
+ status = safe_send(fd, (uint32_t []) { htobe32(str->length) }, sizeof(uint32_t), flags);
+ if (!status) return false;
+
+ if (str->length > 0)
+ {
+ status = safe_send(fd, str->data, str->length + 1, flags);
+ if (!status) return false;
+ }
+
+ return true;
+
+}
diff --git a/src/analysis/db/misc/rlestr.h b/src/analysis/db/misc/rlestr.h
new file mode 100644
index 0000000..2aa863f
--- /dev/null
+++ b/src/analysis/db/misc/rlestr.h
@@ -0,0 +1,83 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * rlestr.h - prototypes pour l'encodage par plage unique d'une chaîne de caractères
+ *
+ * Copyright (C) 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/>.
+ */
+
+
+#ifndef _ANALYSIS_DB_MISC_RLESTR_H
+#define _ANALYSIS_DB_MISC_RLESTR_H
+
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+
+
+/* Informations de base pour tout élément ajouté */
+typedef struct _rle_string
+{
+ char *data; /* Chaîne de caractères */
+ uint32_t length; /* Taille de la chaîne */
+
+} rle_string;
+
+
+/* Définit une représentation de chaîne de caractères. */
+void init_rle_string(rle_string *, const char *);
+
+#define exit_rle_string(rle) /* TODO */
+
+#define dup_rle_string(dst, src) init_rle_string(dst, (src)->data);
+
+#define get_rle_string(rle) (rle)->data
+
+/* Constitue une représentation de chaîne de caractères. */
+void set_rle_string(rle_string *, const char *);
+
+/* Libère la mémoire associée à la représentation. */
+void unset_rle_string(rle_string *);
+
+/* Effectue la comparaison entre deux chaînes de caractères. */
+int cmp_rle_string(const rle_string *, const rle_string *);
+
+
+
+/* Importe la définition d'une chaîne de caractères. */
+bool load_rle_string(rle_string *, int);
+
+/* Exporte la définition d'une chaîne de caractères. */
+bool store_rle_string(const rle_string *, int);
+
+
+
+#define is_rle_string_empty(rle) ((rle)->data == NULL)
+
+
+
+/* Importe la définition d'une chaîne de caractères. */
+bool recv_rle_string(rle_string *, int, int);
+
+/* Exporte la définition d'une chaîne de caractères. */
+bool send_rle_string(const rle_string *, int, int);
+
+
+
+#endif /* _ANALYSIS_DB_MISC_RLESTR_H */
diff --git a/src/analysis/db/protocol.h b/src/analysis/db/protocol.h
index b1cdfaf..05b559e 100644
--- a/src/analysis/db/protocol.h
+++ b/src/analysis/db/protocol.h
@@ -27,10 +27,12 @@
/**
- * Nombre maximal de connexions à un serveur.
- * cf. listen().
+ * Version de la définition courante du protocole.
*/
-#define CDB_SEVER_BACKLOG 100
+#define CDB_PROTOCOL_VERSION 0xc0de0001
+
+
+
/**
* Délai maximal de réaction pour les coupures de flux (en ms).
@@ -41,27 +43,102 @@
-/* Fonctionnalités offertes */
+/* Comportement vis à vis des éléments */
+typedef enum _DBStorage
+{
+ DBS_ALL_LOCAL = 0x01, /* Enregistrements locaux */
+ DBS_ALL_REMOTE = 0x02, /* Enregistrements distants */
+ DBS_LOCAL_AND_REMOTE = 0x03, /* Enreg. locaux + infos dists.*/
+
+ DBS_MAX = 3
+
+} DBStorage;
+
+
+
+
+
+
+
+
+
+
+
+
+/**
+ * Une fois la connexion établie, les paquets ont tous la forme suivante :
+
+
+
+
+
+ *
+ * [ type de collection visée ; cf. DBFeatures ]
+ * [ action à mener ; cf. DBAction ]
+ * [ élément de type GDbItem sérialisé... ]
+ *
+ */
+
+/* Fonctionnalités offertes nativement */
typedef enum _DBFeatures
{
+ DBF_BOOKMARKS, /* Signets dans le code */
DBF_COMMENTS, /* Commentaires ajoutés */
DBF_SEGMENTS_DISPLAY, /* Choix d'affichage */
- DBF_BOOKMARKS, /* Signets dans le code */
DBF_COUNT
} DBFeatures;
-/* Comportement vis à vis des éléments */
-typedef enum _DBStorage
+/* Interactions disponibles vis à vis d'une collection. */
+typedef enum _DBAction
{
- DBS_ALL_LOCAL = 0x01, /* Enregistrements locaux */
- DBS_ALL_REMOTE = 0x02, /* Enregistrements distants */
- DBS_LOCAL_AND_REMOTE = 0x03, /* Enreg. locaux + infos dists.*/
+ DBA_ADD_ITEM, /* Ajout d'un élément */
+ DBA_REM_ITEM, /* Suppression d'un élément */
+ DBA_MOD_ITEM, /* Modification de l'existant */
+
+ DBA_COUNT
+
+} DBAction;
+
+
+
+
+
+
+/**
+ * Commandes envoyées d'un côté à un autre.
+ */
+typedef enum _DBCommand
+{
+ DBC_HELO, /* Connexion initiale C -> S */
+ DBC_WELCOME, /* Réponse initiale S -> C */
+ DBC_COLLECTION, /* Implication d'une collection*/
+
+ DBC_COUNT
+
+} DBCommand;
+
+
+
+
+
+
+
+/**
+ * Erreurs pouvant survenir...
+ */
+typedef enum _DBError
+{
+ DBE_NONE, /* Succès d'une opération */
+ DBE_WRONG_VERSION, /* Proto Client != Serveur */
+
+ DBE_COUNT
+
+} DBError;
+
- DBS_MAX = 3
-} DBStorage;
diff --git a/src/analysis/db/server.c b/src/analysis/db/server.c
index 3d75b71..42688c8 100644
--- a/src/analysis/db/server.c
+++ b/src/analysis/db/server.c
@@ -29,10 +29,15 @@
#include <poll.h>
#include <string.h>
#include <unistd.h>
+#include <arpa/inet.h>
#include <sys/socket.h>
+#include "cdb.h"
#include "protocol.h"
+#include "misc/rlestr.h"
+#include "../../common/io.h"
+#include "../../core/params.h"
#include "../../gui/panels/log.h"
@@ -56,10 +61,12 @@ struct _GDbServer
int fd; /* Canal de communication */
char *hostname; /* Désignation humaine */
+ char *desc; /* Désignation du serveur */
struct sockaddr_in addr; /* Adresse d'écoute */
GThread *listener; /* Procédure de traitement */
+ GList *archives; /* Liste des binaires ouverts */
cdb_client **clients; /* Connexions en place */
size_t count; /* Quantité de clients */
GMutex mutex; /* Verrou pour l'accès */
@@ -87,7 +94,7 @@ static void g_db_server_finalize(GDbServer *);
static void *g_db_server_listener(GDbServer *);
/* Assure le traitement des requêtes de clients. */
-static void *g_db_server_process(cdb_client **);
+//static void *g_db_server_process(cdb_client **);
@@ -177,19 +184,38 @@ GDbServer *g_db_server_new(const char *host, short port)
{
GDbServer *result; /* Adresse à retourner */
struct hostent *hp; /* Informations sur l'hôte */
+ size_t desclen; /* Taille de désignation */
+
+ const char *ip; /* Adresse IPv4 ou IPv6 */
result = g_object_new(G_TYPE_DB_SERVER, NULL);
result->hostname = strdup(host);
hp = gethostbyname(host);
- if (hp == NULL) goto gdsn_error;
+ if (hp == NULL)
+ {
+ perror("gethostbyname");
+ goto gdsn_error;
+ }
result->addr.sin_family = hp->h_addrtype;
memcpy(&result->addr.sin_addr, hp->h_addr_list[0], sizeof(struct in_addr));
result->addr.sin_port = htons(port);
+ desclen = INET6_ADDRSTRLEN + 1 + 5 + 1;
+ result->desc = (char *)calloc(desclen, sizeof(char));
+
+ ip = inet_ntop(AF_INET, &result->addr.sin_addr, result->desc, INET6_ADDRSTRLEN);
+ if (ip == NULL)
+ {
+ perror("inet_ntop");
+ goto gdsn_error;
+ }
+
+ snprintf(result->desc + strlen(ip), 1 + 5, ":%hu", port);
+
return result;
gdsn_error:
@@ -219,7 +245,27 @@ static void *g_db_server_listener(GDbServer *server)
int ret; /* Bilan d'un appel */
struct sockaddr_in peer; /* Adresse cliente */
int fd; /* Canal établi vers un client */
- cdb_client *client; /* Mémorisation pour poursuite */
+ char source[INET6_ADDRSTRLEN]; /* Adresse du client (IPv4/6) */
+ const char *ip; /* Statut de la conversion */
+
+
+ DBError error; /* Validation de la connexion */
+
+ uint32_t data; /* Mot de données lues */
+
+
+ rle_string hash; /* Empreinte du binaire visé */
+ rle_string user; /* Nom d'utilisateur du client */
+
+ GList *iter; /* Boucle de parcours */
+ GCdbArchive *archive; /* Destinataire final du client*/
+
+
+
+ //cdb_client *client; /* Mémorisation pour poursuite */
+
+
+
fds.fd = server->fd;
fds.events = POLLIN | POLLPRI;
@@ -236,8 +282,122 @@ static void *g_db_server_listener(GDbServer *server)
if (fds.revents & (POLLIN | POLLPRI))
{
fd = accept(server->fd, &peer, (socklen_t []) { sizeof(struct sockaddr_in) });
- if (fd == -1) continue;
+ if (fd == -1)
+ {
+ perror("accept");
+ continue;
+ }
+
+ ip = inet_ntop(AF_INET, &peer.sin_addr, source, sizeof(source));
+ if (ip == NULL)
+ {
+ perror("inet_ntop");
+ goto gdsl_error;
+ }
+
+ error = DBE_NONE;
+
+ /**
+ * Le premier "paquet" reçu de la part d'un client doit contenir les informations suivantes :
+ * - la commande 'DBC_HELO'.
+ * - le numéro de version du client.
+ * - l'empreinte du binaire analysé.
+ * - l'identifiant de l'utilisateur effectuant des modifications.
+ *
+ * Tout ceci est à synchroniser avec la fonction g_db_client_start().
+ */
+
+ if (!safe_recv(fd, &data, sizeof(uint32_t), 0))
+ goto gdsl_error;
+
+ if (be32toh(data) != DBC_HELO)
+ {
+ log_variadic_message(LMT_ERROR, _("The client from '%s:%hu' did not introduce itself!"),
+ source, ntohs(peer.sin_port));
+ goto gdsl_error;
+ }
+
+ if (!safe_recv(fd, &data, sizeof(uint32_t), 0))
+ goto gdsl_error;
+
+ if (be32toh(data) != CDB_PROTOCOL_VERSION)
+ {
+ log_variadic_message(LMT_ERROR, _("The client from '%s:%hu' does not use the same protocol: 0x%08x vs 0x%08x..."),
+ source, ntohs(peer.sin_port), be32toh(data), CDB_PROTOCOL_VERSION);
+ error = DBE_WRONG_VERSION;
+ goto gdsl_error_sending;
+ }
+
+ if (!recv_rle_string(&hash, fd, 0) || is_rle_string_empty(&hash))
+ {
+ log_variadic_message(LMT_ERROR, _("Error while getting the binary hash from '%s:%hu'..."),
+ source, ntohs(peer.sin_port));
+ goto gdsl_error;
+ }
+
+ if (!recv_rle_string(&user, fd, 0) || is_rle_string_empty(&user))
+ {
+ log_variadic_message(LMT_ERROR, _("Error while getting the user name from '%s:%hu'..."),
+ source, ntohs(peer.sin_port));
+ goto gdsl_error;
+ }
+
+ /**
+ * On met en place le maximum ici, de manière à pouvoir indiquer une erreur
+ * en cas d'échec, et être le plus précis possible dans la courte réponse.
+ */
+
+ for (iter = g_list_first(server->archives);
+ iter != NULL;
+ iter = g_list_next(iter))
+ {
+ archive = G_CDB_ARCHIVE(iter->data);
+ if (g_cdb_archive_compare_hash(archive, &hash) == 0)
+ break;
+ }
+
+ if (iter == NULL)
+ {
+ archive = g_cdb_archive_new(server->desc, &hash, &user, &error);
+
+ if (archive != NULL)
+ server->archives = g_list_append(server->archives, archive);
+
+ }
+
+ if (archive != NULL)
+ error = g_cdb_archive_add_client(archive, fd, &user);
+
+ /**
+ * Le serveur doit répondre pour un message type :
+ * - la commande 'DBC_WELCOME'.
+ * - un identifiant d'erreur ('DBE_NONE' ou 'DBE_WRONG_VERSION').
+ */
+
+ gdsl_error_sending:
+
+ if (!safe_send(fd, (uint32_t []) { htobe32(DBC_WELCOME) }, sizeof(uint32_t), MSG_MORE))
+ goto gdsl_error;
+
+ if (!safe_send(fd, (uint32_t []) { htobe32(error) }, sizeof(uint32_t), 0))
+ goto gdsl_error;
+
+ if (error == DBE_NONE) continue;
+
+ gdsl_error:
+
+
+ /* free RLE !!!! */
+
+ close(fd);
+
+ }
+
+
+
+
+#if 0
g_mutex_lock(&server->mutex);
client = (cdb_client *)calloc(1, sizeof(cdb_client));
@@ -256,80 +416,13 @@ static void *g_db_server_listener(GDbServer *server)
&server->clients[server->count - 1]);
g_mutex_unlock(&server->mutex);
+#endif
- }
- }
- return NULL;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : client = informations sur une connexion établie à utiliser. *
-* *
-* Description : Assure le traitement des requêtes de clients. *
-* *
-* Retour : NULL. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void *g_db_server_process(cdb_client **client)
-{
- struct pollfd fds; /* Surveillance des flux */
- int ret; /* Bilan d'un appel */
- GDbServer *server; /* Accès facile en mémoire */
- size_t index; /* Indice courant du client */
- size_t remaining; /* Quantité à déplacer */
-
- fds.fd = (*client)->fd;
- fds.events = POLLIN | POLLPRI;
-
- while (1)
- {
- ret = poll(&fds, 1, -1);
- if (ret != 1) continue;
-
- printf("fds.revents :: %x\n", fds.revents);
-
- /* Le canal est fermé, une sortie doit être demandée... */
- if (fds.revents & POLLNVAL)
- break;
-
- if (fds.revents & (POLLIN | POLLPRI))
- {
-
- /* TODO */
- pause();
-
-
- }
}
- /* Retrait de la liste avant la terminaison */
-
- server = (*client)->server;
-
- g_mutex_lock(&server->mutex);
-
- index = (client - server->clients);
- remaining = server->count - index - 1;
-
- if (remaining > 0)
- memmove(&server->clients[index], &server->clients[index + 1],
- remaining * sizeof(cdb_client *));
-
- g_object_unref(G_OBJECT(server));
-
- free(*client);
-
- g_mutex_unlock(&server->mutex);
-
return NULL;
}
@@ -350,6 +443,7 @@ static void *g_db_server_process(cdb_client **client)
bool g_db_server_start(GDbServer *server)
{
int ret; /* Bilan d'un appel */
+ int backlog; /* Nombre de connexions maximal*/
server->fd = socket(AF_INET, SOCK_STREAM, 0);
if (server->fd == -1)
@@ -362,27 +456,24 @@ bool g_db_server_start(GDbServer *server)
if (ret == -1)
{
perror("setsockopt");
- close(server->fd);
- server->fd = -1;
- return false;
+ goto gdss_error;
}
ret = bind(server->fd, (struct sockaddr *)&server->addr, sizeof(struct sockaddr_in));
if (ret == -1)
{
perror("bind");
- close(server->fd);
- server->fd = -1;
- return false;
+ goto gdss_error;
}
- ret = listen(server->fd, CDB_SEVER_BACKLOG);
+ if (!g_generic_config_get_value(get_main_configuration(), MPK_SERVER_BACKLOG, &backlog))
+ goto gdss_error;
+
+ ret = listen(server->fd, backlog);
if (ret == -1)
{
perror("listen");
- close(server->fd);
- server->fd = -1;
- return false;
+ goto gdss_error;
}
server->listener = g_thread_new("cdb_listener", (GThreadFunc)g_db_server_listener, server);
@@ -392,6 +483,13 @@ bool g_db_server_start(GDbServer *server)
return true;
+ gdss_error:
+
+ close(server->fd);
+ server->fd = -1;
+
+ return false;
+
}
diff --git a/src/arch/vmpa.h b/src/arch/vmpa.h
index 7f417b5..d89c290 100644
--- a/src/arch/vmpa.h
+++ b/src/arch/vmpa.h
@@ -26,6 +26,7 @@
#include <limits.h>
+#include <malloc.h>
#include <stdbool.h>
#include <stdint.h>
#include <sys/types.h>
diff --git a/src/common/io.c b/src/common/io.c
index 2275cb4..23fad54 100644
--- a/src/common/io.c
+++ b/src/common/io.c
@@ -24,16 +24,118 @@
#include "io.h"
+#include <errno.h>
#include <libgen.h>
#include <malloc.h>
+#include <stdint.h>
#include <string.h>
#include <unistd.h>
+#include <sys/socket.h>
#include <sys/stat.h>
/******************************************************************************
* *
+* Paramètres : sockfd = flux ouvert en lecture. *
+* buf = données à recevoir. *
+* len = quantité de ces données. *
+* flags = options de réception. *
+* *
+* Description : Réceptionne des données depuis un flux réseau. *
+* *
+* Retour : true si toutes les données ont été reçues, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool safe_recv(int sockfd, const void *buf, size_t len, int flags)
+{
+ uint8_t *iter; /* Données en attente */
+ size_t remaining; /* Quantité restante */
+ ssize_t got; /* Données envoyées */
+
+ iter = (uint8_t *)buf;
+ remaining = len;
+
+ while (remaining > 0)
+ {
+ got = recv(sockfd, iter, remaining, MSG_NOSIGNAL | flags);
+ if (got == -1)
+ {
+ if (errno == EINTR) continue;
+ else
+ {
+ perror("recv");
+ break;
+ }
+ }
+
+ iter += got;
+ remaining -= got;
+
+ }
+
+ return (remaining == 0);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : sockfd = flux ouvert en écriture. *
+* buf = données à émettre. *
+* len = quantité de ces données. *
+* flags = options d'envoi. *
+* *
+* Description : Envoie des données au travers un flux réseau. *
+* *
+* Retour : true si toutes les données ont été émises, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool safe_send(int sockfd, const void *buf, size_t len, int flags)
+{
+ uint8_t *iter; /* Données en attente */
+ size_t remaining; /* Quantité restante */
+ ssize_t sent; /* Données envoyées */
+
+ iter = (uint8_t *)buf;
+ remaining = len;
+
+ while (remaining > 0)
+ {
+ sent = send(sockfd, iter, remaining, MSG_NOSIGNAL | flags);
+ if (sent == -1)
+ {
+ if (errno == EINTR) continue;
+ else
+ {
+ perror("send");
+ break;
+ }
+ }
+
+ iter += sent;
+ remaining -= sent;
+
+ }
+
+ return (remaining == 0);
+
+}
+
+
+
+
+
+
+
+/******************************************************************************
+* *
* Paramètres : path = chemin d'accès à valider. *
* *
* Description : S'assure qu'un chemin donné existe dans le système. *
diff --git a/src/common/io.h b/src/common/io.h
index 491d8d0..8dd38c8 100644
--- a/src/common/io.h
+++ b/src/common/io.h
@@ -25,14 +25,19 @@
#define _COMMON_IO_H
-
+#include <stdbool.h>
#include <sys/types.h>
#include <sys/socket.h>
-#define safe_recv recv
-#define safe_send send
+/* Réceptionne des données depuis un flux réseau. */
+bool safe_recv(int, const void *, size_t, int);
+
+/* Envoie des données au travers un flux réseau. */
+bool safe_send(int, const void *, size_t, int);
+
+
#define safe_read read
diff --git a/src/core/Makefile.am b/src/core/Makefile.am
index 0724a3f..02b6877 100755
--- a/src/core/Makefile.am
+++ b/src/core/Makefile.am
@@ -2,6 +2,7 @@
noinst_LTLIBRARIES = libcore.la
libcore_la_SOURCES = \
+ collections.h collections.c \
core.h core.c \
params.h params.c
diff --git a/src/core/collections.c b/src/core/collections.c
new file mode 100644
index 0000000..860b7f6
--- /dev/null
+++ b/src/core/collections.c
@@ -0,0 +1,175 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * collections.c - enregistrement et la diffusion des collections
+ *
+ * Copyright (C) 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 "collections.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+#include <pthread.h>
+
+
+#include "../analysis/db/collection.h"
+#include "../analysis/db/protocol.h"
+#include "../analysis/db/items/bookmark.h"
+
+
+
+/* Caractéristiques d'une collection */
+typedef struct _collec_t
+{
+ GType items; /* Type d'éléments rassemblés */
+ create_db_table_fc create; /* Création de la BD associée */
+
+} collec_t;
+
+
+/* Mémorisation des types de collection enregistrés */
+static collec_t *_collection_definitions = NULL;
+static uint32_t _collection_definitions_count = 0;
+
+/* Verrou pour des accès atomiques */
+/* ... */
+
+
+
+/******************************************************************************
+* *
+* Paramètres : items = type GLib des éléments constituant une collection. *
+* create = création de la base de données correspondante. *
+* *
+* Description : Enregistre un type d'élément à gérer par collection. *
+* *
+* Retour : Identifiant unique attribué "dynamiquement". *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+uint32_t register_collection_type(GType items, create_db_table_fc create)
+{
+ uint32_t result; /* Identifiant à retourner */
+
+ /* TODO : lock */
+
+ result = _collection_definitions_count++;
+
+ _collection_definitions = (collec_t *)realloc(_collection_definitions,
+ _collection_definitions_count * sizeof(collec_t));
+
+ _collection_definitions[result].items = items;
+ _collection_definitions[result].create = create;
+
+ /* TODO : unlock */
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Charge les définitions de collections "natives". *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool load_hard_coded_collection_definitions(void)
+{
+ uint32_t id; /* Identifiant unique retourné */
+
+ /**
+ * La liste des chargements doit se faire dans le même ordre que
+ * la définition de l'énumération 'DBFeatures' dans le fichier 'protocol.h',
+ * afin de garder la correspondance entre les identifiants.
+ */
+
+ id = register_collection_type(G_TYPE_DB_BOOKMARK, create_bookmark_db_table);
+ assert(id == DBF_BOOKMARKS);
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Décharge toutes les définitions de collections. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void unload_collection_definitions(void)
+{
+ if (_collection_definitions != NULL)
+ free(_collection_definitions);
+
+ _collection_definitions = NULL;
+ _collection_definitions_count = 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Construit un nouvel ensemble de collections. *
+* *
+* Retour : Liste complète de collections vierges. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GList *create_collections_list(void)
+{
+ GList *result; /* Groupe à retourner */
+ uint32_t i; /* Boucle de parcours */
+ const collec_t *def; /* Définition brute à lire */
+ GDbCollection *collec; /* Nouveau groupe à intégrer */
+
+ result = NULL;
+
+ for (i = 0; i < _collection_definitions_count; i++)
+ {
+ def = &_collection_definitions[i];
+ collec = g_db_collection_new(i, def->items);
+
+ result = g_list_append(result, collec);
+
+ }
+
+ return result;
+
+}
diff --git a/src/analysis/db/bookmark.h b/src/core/collections.h
index 5308e92..b84bdd9 100644
--- a/src/analysis/db/bookmark.h
+++ b/src/core/collections.h
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * bookmark.h - prototypes pour la gestion des signets au sein d'un binaire
+ * collections.h - prototypes pour l'enregistrement et la diffusion des collections
*
* Copyright (C) 2014 Cyrille Bagard
*
@@ -21,21 +21,34 @@
*/
-#ifndef _ANALYSIS_DB_BOOKMARK_H
-#define _ANALYSIS_DB_BOOKMARK_H
-
+#ifndef _CORE_COLLECTIONS_H
+#define _CORE_COLLECTIONS_H
+#include <glib-object.h>
#include <sqlite3.h>
#include <stdbool.h>
+#include <stdint.h>
+
+
+
+/* Crée la table dans une base de données. */
+typedef bool (* create_db_table_fc) (sqlite3 *);
+
+/* Enregistre un type d'élément à gérer par collection. */
+uint32_t register_collection_type(GType, create_db_table_fc);
-/* Crée la table des signets dans une base de données. */
-bool create_bookmark_db_table(sqlite3 *);
+/* Charge les définitions de collections "natives". */
+bool load_hard_coded_collection_definitions(void);
+/* Décharge toutes les définitions de collections. */
+void unload_collection_definitions(void);
+/* Construit un nouvel ensemble de collections. */
+GList *create_collections_list(void);
-#endif /* _ANALYSIS_DB_BOOKMARK_H */
+#endif /* _ANALYSIS_DB_COLLECTION_H */
diff --git a/src/core/core.c b/src/core/core.c
index d90dd5c..d7e7755 100644
--- a/src/core/core.c
+++ b/src/core/core.c
@@ -24,6 +24,7 @@
#include "core.h"
+#include "collections.h"
#include "params.h"
@@ -50,6 +51,8 @@ bool load_all_basic_components(void)
result &= g_generic_config_read(get_main_configuration());
+ result &= load_hard_coded_collection_definitions();
+
return result;
}
@@ -69,6 +72,8 @@ bool load_all_basic_components(void)
void unload_all_basic_components(void)
{
+ unload_collection_definitions();
+
g_generic_config_write(get_main_configuration());
unload_main_config_parameters();
diff --git a/src/core/params.c b/src/core/params.c
index c8263f0..7bc1162 100644
--- a/src/core/params.c
+++ b/src/core/params.c
@@ -24,6 +24,75 @@
#include "params.h"
+#include <limits.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Détermine une fois pour toute la désignation de l'usager. *
+* *
+* Retour : Nom déterminé à libérer de la mémoire. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *get_author_name(void)
+{
+ char *result; /* Désignation à retourner */
+ char *chrysalide_user; /* Eventuel nom spécifique */
+ char *logname; /* Nom depuis l'environnement */
+ char hostname[HOST_NAME_MAX]; /* Nom de la machine courante */
+ int ret; /* Bilan d'un appel */
+ size_t length; /* Taille de la désignation */
+
+ chrysalide_user = getenv("CHRYSALIDE_USER");
+
+ if (chrysalide_user != NULL)
+ result = strdup(chrysalide_user);
+
+ else
+ {
+ logname = getenv("LOGNAME");
+
+ ret = gethostname(hostname, HOST_NAME_MAX);
+ if (ret != 0)
+ hostname[0] = '\0';
+
+ if (logname != NULL && hostname[0] != '\0')
+ {
+ length = strlen(logname) + 1 + strlen(hostname) + 1;
+ result = (char *)calloc(length, sizeof(char));
+ snprintf(result, length, "%s@%s", logname, hostname);
+ }
+ else if (logname != NULL && hostname[0] == '\0')
+ {
+ length = strlen(logname) + 1;
+ result = (char *)calloc(length, sizeof(char));
+ snprintf(result, length, "%s", logname);
+ }
+ else if (logname == NULL && hostname[0] != '\0')
+ {
+ length = 1 + strlen(hostname) + 1;
+ result = (char *)calloc(length, sizeof(char));
+ snprintf(result, length, "@%s", hostname);
+ }
+ else
+ result = strdup("anonymous");
+
+ }
+
+ return result;
+
+}
+
/******************************************************************************
* *
@@ -41,10 +110,31 @@ bool load_main_config_parameters(void)
{
GGenConfig *config; /* Configuration à charger */
GCfgParam *param; /* Paramètre chargé */
+ char *string; /* Valeur sous forme de texte */
config = g_generic_config_new("main");
set_main_configuration(config);
+ string = get_author_name();
+ param = g_generic_config_create_param(config, MPK_AUTHOR_NAME, CPT_STRING, string);
+ free(string);
+ if (param == NULL) return false;
+
+ param = g_generic_config_create_param(config, MPK_REMOTE_HOST, CPT_STRING, "localhost");
+ if (param == NULL) return false;
+
+ param = g_generic_config_create_param(config, MPK_REMOTE_PORT, CPT_INTEGER, 9999);
+ if (param == NULL) return false;
+
+ param = g_generic_config_create_param(config, MPK_LOCAL_HOST, CPT_STRING, "localhost");
+ if (param == NULL) return false;
+
+ param = g_generic_config_create_param(config, MPK_LOCAL_PORT, CPT_INTEGER, 1337);
+ if (param == NULL) return false;
+
+ param = g_generic_config_create_param(config, MPK_SERVER_BACKLOG, CPT_INTEGER, 20);
+ if (param == NULL) return false;
+
param = g_generic_config_create_param(config, MPK_LAST_PROJECT, CPT_STRING, NULL);
if (param == NULL) return false;
diff --git a/src/core/params.h b/src/core/params.h
index b79cc3a..db01d20 100644
--- a/src/core/params.h
+++ b/src/core/params.h
@@ -33,6 +33,12 @@
* Clefs de paramètres de configuration principale.
*/
+#define MPK_AUTHOR_NAME "cdb.default.author"
+#define MPK_REMOTE_HOST "cdb.default.network.remote.server"
+#define MPK_REMOTE_PORT "cdb.default.network.remote.port"
+#define MPK_LOCAL_HOST "cdb.network.local.server"
+#define MPK_LOCAL_PORT "cdb.network.local.port"
+#define MPK_SERVER_BACKLOG "cdb.network.server.backlog"
#define MPK_LAST_PROJECT "gui.editor.last_project"
#define MPK_ELLIPSIS_HEADER "gui.editor.panels.ellipsis_header"
#define MPK_ELLIPSIS_TAB "gui.editor.panels.ellipsis_tab"
diff --git a/src/gui/panels/Makefile.am b/src/gui/panels/Makefile.am
index 0f7768c..ad8c6b2 100644
--- a/src/gui/panels/Makefile.am
+++ b/src/gui/panels/Makefile.am
@@ -2,6 +2,7 @@
noinst_LTLIBRARIES = libguipanels.la
libguipanels_la_SOURCES = \
+ bookmarks.h bookmarks.c \
glance.h glance.c \
log.h log.c \
panel.h panel.c \
diff --git a/src/gui/panels/bookmarks.c b/src/gui/panels/bookmarks.c
new file mode 100644
index 0000000..a61f6bc
--- /dev/null
+++ b/src/gui/panels/bookmarks.c
@@ -0,0 +1,1179 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * bookmarks.c - panneau d'affichage des signets d'un binaire
+ *
+ * Copyright (C) 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "bookmarks.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+#include <regex.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <cairo-gobject.h>
+#include <gtk/gtk.h>
+
+
+#include "panel-int.h"
+#include "../../analysis/db/items/bookmark.h"
+#include "../../core/params.h"
+#include "../../common/cpp.h"
+#include "../../common/extstr.h"
+#include "../../gtkext/easygtk.h"
+#include "../../gtkext/support.h"
+
+
+
+/* -------------------------- PARTIE PRINCIPALE DU PANNEAU -------------------------- */
+
+
+/* Panneau d'affichage des signets liés à un binaire (instance) */
+struct _GBookmarksPanel
+{
+ GPanelItem parent; /* A laisser en premier */
+
+ GtkTreeView *treeview; /* Composant d'affichage */
+ regex_t *filter; /* Filtre appliqué ou NULL */
+
+ GtkMenu *menu; /* Menu contextuel pour param. */
+
+ GLoadedBinary *binary; /* Binaire en cours d'analyse */
+
+};
+
+/* Panneau d'affichage des signets liés à un binaire (classe) */
+struct _GBookmarksPanelClass
+{
+ GPanelItemClass parent; /* A laisser en premier */
+
+ cairo_surface_t *bookmark_img; /* Image pour les signets */
+
+};
+
+
+/* Colonnes de la liste visuelle */
+typedef enum _BookmarkColumn
+{
+ BMC_BOOKMARK, /* Elément GLib représenté */
+
+ BMC_PICTURE, /* Image d'agrément */
+ BMC_PHYSICAL, /* Adresse phyisque */
+ BMC_VIRTUAL, /* Adresse virtuelle */
+ BMC_COMMENT, /* Commentaire associé */
+
+ BMC_COUNT /* Nombre de colonnes */
+
+} CfgParamColumn;
+
+
+
+
+/* Initialise la classe des panneaux des paramètres de config. */
+static void g_bookmarks_panel_class_init(GBookmarksPanelClass *);
+
+/* Initialise une instance de panneau de paramètres de config. */
+static void g_bookmarks_panel_init(GBookmarksPanel *);
+
+/* Supprime toutes les références externes. */
+static void g_bookmarks_panel_dispose(GBookmarksPanel *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_bookmarks_panel_finalize(GBookmarksPanel *);
+
+
+
+/* ------------------------- AFFICHAGE A L'AIDE D'UNE LISTE ------------------------- */
+
+
+/* Recharge une collection de signets à l'affichage. */
+static void reload_bookmarks_into_treeview(GBookmarksPanel *, GLoadedBinary *);
+
+
+
+
+/* Actualise l'affichage des données d'un paramètre modifié. */
+static void on_config_param_modified(GCfgParam *, GBookmarksPanel *);
+
+/* Actualise la valeur affichée d'un paramètre de configuration. */
+static void update_config_param_value(GtkTreeStore *, GtkTreeIter *);
+
+/* Etablit une comparaison entre deux lignes de paramètres. */
+static gint compare_bookmarks_list_columns(GtkTreeModel *, GtkTreeIter *, GtkTreeIter *, gpointer);
+
+/* Réagit à une pression sur <Shift+F2> et simule l'édition. */
+static gboolean on_key_pressed_over_params(GtkTreeView *, GdkEventKey *, GBookmarksPanel *);
+
+/* Réagit à une édition de la valeur d'un paramètre. */
+static void on_param_value_edited(GtkCellRendererText *, gchar *, gchar *, GtkTreeStore *);
+
+
+
+/* ------------------------- FILTRAGE DES SYMBOLES PRESENTS ------------------------- */
+
+
+/* Démarre l'actualisation du filtrage des paramètres. */
+static void on_param_search_changed(GtkSearchEntry *, GBookmarksPanel *);
+
+/*Détermine si un paramètre doit être filtré ou non. */
+static bool is_param_filtered(GBookmarksPanel *, const char *);
+
+
+
+/* ------------------------ ATTRIBUTION D'UN MENU CONTEXTUEL ------------------------ */
+
+
+/* Assure la gestion des clics de souris sur les signets. */
+static gboolean on_button_press_over_bookmarks(GtkWidget *, GdkEventButton *, GBookmarksPanel *);
+
+/* Construit le menu contextuel pour les signets. */
+GtkMenu *build_bookmarks_panel_menu(GBookmarksPanel *);
+
+/* Fournit le signet sélectionné dans la liste. */
+static GDbBookmark *get_selected_panel_bookmark(GtkTreeView *, GtkTreeIter *);
+
+/* Réagit avec le menu "Editer". */
+static void mcb_bookmarks_panel_edit(GtkMenuItem *, GBookmarksPanel *);
+
+/* Réagit avec le menu "Supprimer". */
+static void mcb_bookmarks_panel_delete(GtkMenuItem *, GBookmarksPanel *);
+
+/* Réagit avec le menu "Filtrer...". */
+static void mcb_bookmarks_panel_filter(GtkMenuItem *, GBookmarksPanel *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* PARTIE PRINCIPALE DU PANNEAU */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type définit pour un panneau d'affichage des signets liés à un binaire. */
+G_DEFINE_TYPE(GBookmarksPanel, g_bookmarks_panel, G_TYPE_PANEL_ITEM);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des panneaux des paramètres de config. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_bookmarks_panel_class_init(GBookmarksPanelClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GEditorItemClass *editem; /* Encore une autre vision... */
+ gchar *filename; /* Chemin d'accès à utiliser */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_bookmarks_panel_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_bookmarks_panel_finalize;
+
+ editem = G_EDITOR_ITEM_CLASS(klass);
+
+ editem->update_binary = (update_item_binary_fc)reload_bookmarks_into_treeview;
+
+ filename = find_pixmap_file("bookmark.png");
+ /* assert(filename != NULL); */
+
+ klass->bookmark_img = cairo_image_surface_create_from_png(filename);
+
+ g_free(filename);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = instance à initialiser. *
+* *
+* Description : Initialise une instance de panneau de paramètres de config. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_bookmarks_panel_init(GBookmarksPanel *panel)
+{
+ GEditorItem *base; /* Version basique d'instance */
+ GObject *ref; /* Espace de référencement */
+ GtkWidget *label; /* Etiquette à utiliser */
+ GtkWidget *search; /* Zone de recherche */
+ GtkWidget *scrolled; /* Fenêtre défilante */
+ GtkTreeStore *store; /* Modèle de gestion */
+ GtkWidget *treeview; /* Affichage de la liste */
+ GtkCellRenderer *renderer; /* Moteur de rendu de colonne */
+ GtkTreeViewColumn *column; /* Colonne de la liste */
+ GtkTreeSortable *sortable; /* Autre vision de la liste */
+
+ base = G_EDITOR_ITEM(panel);
+
+ base->widget = gtk_grid_new();
+ gtk_widget_show(base->widget);
+
+ gtk_grid_set_row_spacing(GTK_GRID(base->widget), 8);
+
+ ref = G_OBJECT(base->widget);
+ g_object_set_data(ref, "panel", panel);
+
+ /* Partie recherche */
+
+ label = qck_create_label(NULL, NULL, _("Look for:"));
+ g_object_set(label, "margin", 8, NULL);
+ gtk_grid_attach(GTK_GRID(base->widget), label, 0, 0, 1, 1);
+
+ search = gtk_search_entry_new();
+ ///g_signal_connect(search, "search-changed", G_CALLBACK(on_param_search_changed), panel);
+ gtk_widget_show(search);
+ gtk_widget_set_hexpand(search, TRUE);
+ gtk_grid_attach_next_to(GTK_GRID(base->widget), search, label, GTK_POS_RIGHT, 1, 1);
+
+ /* Partie paramètres */
+
+ scrolled = gtk_scrolled_window_new(NULL, NULL);
+ gtk_widget_show(scrolled);
+ gtk_widget_set_vexpand(scrolled, TRUE);
+ gtk_grid_attach_next_to(GTK_GRID(base->widget), scrolled, label, GTK_POS_BOTTOM, 2, 1);
+
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
+
+ store = gtk_tree_store_new(BMC_COUNT, G_TYPE_OBJECT,
+ CAIRO_GOBJECT_TYPE_SURFACE, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+
+ treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
+ gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE);
+ panel->treeview = GTK_TREE_VIEW(treeview);
+
+ g_signal_connect(G_OBJECT(treeview), "button-press-event",
+ G_CALLBACK(on_button_press_over_bookmarks), panel);
+ g_signal_connect(G_OBJECT(treeview), "key-press-event",
+ G_CALLBACK(on_key_pressed_over_params), panel);
+
+ gtk_widget_show(treeview);
+ gtk_container_add(GTK_CONTAINER(scrolled), treeview);
+
+ g_object_unref(G_OBJECT(store));
+
+ /* Cellules d'affichage */
+
+ renderer = gtk_cell_renderer_pixbuf_new();
+ column = gtk_tree_view_column_new_with_attributes("", renderer,
+ "surface", BMC_PICTURE,
+ NULL);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
+
+ renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes(_("Physical address"), renderer,
+ "text", BMC_VIRTUAL,
+ NULL);
+ gtk_tree_view_column_set_sort_column_id(column, BMC_PHYSICAL);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
+
+ renderer = gtk_cell_renderer_text_new();
+ column = gtk_tree_view_column_new_with_attributes(_("Virtual address"), renderer,
+ "text", BMC_VIRTUAL,
+ NULL);
+ gtk_tree_view_column_set_sort_column_id(column, BMC_VIRTUAL);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
+
+ renderer = gtk_cell_renderer_text_new();
+ g_object_set(G_OBJECT(renderer), "editable", TRUE, NULL);
+ ///g_signal_connect(renderer, "edited", G_CALLBACK(on_param_value_edited), store);
+ column = gtk_tree_view_column_new_with_attributes(_("Comment"), renderer,
+ "text", BMC_COMMENT,
+ NULL);
+ gtk_tree_view_column_set_sort_column_id(column, BMC_COMMENT);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
+
+ /* Tri de la liste */
+
+ sortable = GTK_TREE_SORTABLE(store);
+
+ gtk_tree_sortable_set_sort_func(sortable, BMC_PHYSICAL, compare_bookmarks_list_columns,
+ GINT_TO_POINTER(BMC_PHYSICAL), NULL);
+
+ gtk_tree_sortable_set_sort_func(sortable, BMC_VIRTUAL, compare_bookmarks_list_columns,
+ GINT_TO_POINTER(BMC_VIRTUAL), NULL);
+
+ gtk_tree_sortable_set_sort_func(sortable, BMC_COMMENT, compare_bookmarks_list_columns,
+ GINT_TO_POINTER(BMC_COMMENT), NULL);
+
+ gtk_tree_sortable_set_sort_column_id(sortable, BMC_COMMENT, GTK_SORT_ASCENDING);
+
+ /* Préparation du menu contextuel */
+
+ panel->menu = build_bookmarks_panel_menu(panel);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_bookmarks_panel_dispose(GBookmarksPanel *panel)
+{
+ if (panel->binary != NULL)
+ g_object_unref(G_OBJECT(panel->binary));
+
+ G_OBJECT_CLASS(g_bookmarks_panel_parent_class)->dispose(G_OBJECT(panel));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_bookmarks_panel_finalize(GBookmarksPanel *panel)
+{
+ if (panel->filter != NULL)
+ regfree(panel->filter);
+
+ G_OBJECT_CLASS(g_bookmarks_panel_parent_class)->finalize(G_OBJECT(panel));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : ref = espace de référencement global. *
+* *
+* Description : Crée un panneau d'affichage des paramètres de configuration. *
+* *
+* Retour : Adresse de la structure mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GEditorItem *g_bookmarks_panel_new(GObject *ref)
+{
+ GEditorItem *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_BOOKMARKS_PANEL, NULL);
+
+ g_panel_item_init_ext(G_PANEL_ITEM(result), ref, PANEL_BOOKMARKS_ID,
+ _("Bookmarks"), G_EDITOR_ITEM(result)->widget, "SE");
+
+ //reload_config_into_treeview(G_BOOKMARKS_PANEL(result), get_main_configuration());
+
+
+ //GDbCollection *g_loaded_binary_find_collection(GLoadedBinary *binary, DBFeatures feature)
+
+
+
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : ref = espace de référencement global. *
+* *
+* Description : Construit le panneau d'affichage des signets courants. *
+* *
+* Retour : Adresse du panneau mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GPanelItem *create_bookmarks_panel(GObject *ref)
+{
+ GEditorItem *result; /* Elément réactif à renvoyer */
+
+ result = g_bookmarks_panel_new(ref);
+
+ /* Enregistre correctement le tout */
+ register_editor_item(result);
+
+ return G_PANEL_ITEM(result);
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* AFFICHAGE A L'AIDE D'UNE LISTE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = panneau d'affichage des signets liés à un binaire. *
+* binary = propriétaire de la collection à présenter. *
+* *
+* Description : Recharge une collection de signets à l'affichage. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void reload_bookmarks_into_treeview(GBookmarksPanel *panel, GLoadedBinary *binary)
+{
+ GtkTreeStore *store; /* Modèle de gestion */
+ GDbCollection *collec; /* Collection à lister ici */
+ GList *items; /* Liste des éléments groupés */
+ GList *b; /* Boucle de parcours */
+ GDbBookmark *bookmark; /* Signet en cours d'étude */
+ vmpa2t *addr; /* Adressse associée au signet */
+ GtkTreeIter iter; /* Point d'insertion */
+
+ printf("RELOAD :: %p\n", binary);
+
+ /* Basculement du binaire utilisé */
+
+ if (panel->binary != NULL)
+ g_object_unref(G_OBJECT(panel->binary));
+
+ panel->binary = binary;
+
+ if (panel->binary != NULL)
+ g_object_ref(G_OBJECT(binary));
+
+ store = GTK_TREE_STORE(gtk_tree_view_get_model(panel->treeview));
+ gtk_tree_store_clear(store);
+
+ /* Si le panneau actif ne représente pas un binaire... */
+
+ if (binary == NULL) return;
+
+ /* Actualisation de l'affichage */
+
+ sleep(1);
+
+ collec = g_loaded_binary_find_collection(binary, DBF_BOOKMARKS);
+
+ g_db_collection_rlock(collec);
+
+ items = g_db_collection_list_items(collec);
+
+
+ printf(" ... items = %p\n", items);
+
+ /*
+ 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, "0x01",
+ BMC_VIRTUAL, "0x02",
+ BMC_COMMENT, "desc",
+ -1);
+ */
+
+
+ for (b = g_list_first(items); b != NULL; b = g_list_next(b))
+ {
+ bookmark = G_DB_BOOKMARK(b->data);
+
+
+ printf("Adding // %p\n", bookmark);
+
+ //printf("add.virt = %s\n", vmpa2_virt_to_string(&addr, MDS_32_BITS));
+
+ fflush(NULL);
+
+
+ addr = g_db_bookmark_get_address(bookmark);
+
+ 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, "vmpa2_phy_to_string(addr, MDS_32_BITS)", /* FIXME : pareil qu'en bas */
+ BMC_VIRTUAL, "vmpa2_virt_to_string(&addr, MDS_32_BITS)", /* FIXME : choisir en fonction de l'architecture */
+ BMC_COMMENT, "g_db_bookmark_get_comment(bookmark)",
+ -1);
+
+ }
+
+ g_db_collection_runlock(collec);
+
+
+
+#if 0
+ GtkTreeStore *store; /* Modèle de gestion */
+ GList *params; /* Paramètres de configuration */
+ GCfgParam *param; /* Paramètre en cours d'étude */
+ GList *p; /* Boucle de parcours */
+ char *type_desc; /* Type de paramètre */
+ GtkTreeIter iter; /* Point d'insertion */
+
+ store = GTK_TREE_STORE(gtk_tree_view_get_model(panel->treeview));
+ gtk_tree_store_clear(store);
+
+ g_generic_config_rlock(config);
+
+ params = g_generic_config_list_params(config);
+
+ for (p = g_list_first(params); p != NULL; p = g_list_next(p))
+ {
+ param = G_CFG_PARAM(p->data);
+
+ if (is_param_filtered(panel, g_config_param_get_path(param)))
+ continue;
+
+ switch (g_config_param_get_ptype(param))
+ {
+ case CPT_BOOLEAN:
+ type_desc = _("Boolean");
+ break;
+
+ case CPT_INTEGER:
+ type_desc = _("Integer");
+ break;
+
+ case CPT_STRING:
+ type_desc = _("String");
+ break;
+
+ default:
+ type_desc = _("<Unknown type>");
+ break;
+
+ }
+
+ gtk_tree_store_append(store, &iter, NULL);
+ gtk_tree_store_set(store, &iter,
+ CPC_BOOKMARK, param,
+ CPC_PATH, g_config_param_get_path(param),
+ CPC_TYPE, type_desc,
+ -1);
+
+ update_config_param_value(store, &iter);
+
+ g_signal_connect(param, "modified", G_CALLBACK(on_config_param_modified), panel);
+
+ }
+
+ g_generic_config_runlock(config);
+#endif
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : param = instance dont le contenu a évolué. *
+* panel = panneau d'affichage de paramètres à mettre à jour. *
+* *
+* Description : Actualise l'affichage des données d'un paramètre modifié. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void on_config_param_modified(GCfgParam *param, GBookmarksPanel *panel)
+{
+ GtkTreeModel *model; /* Gestionnaire de données */
+ GtkTreeIter iter; /* Point de recherche */
+ gboolean looping; /* Autorisation de bouclage */
+ GCfgParam *item; /* Elément de la liste */
+
+ model = gtk_tree_view_get_model(panel->treeview);
+
+ for (looping = gtk_tree_model_get_iter_first (model, &iter);
+ looping;
+ looping = gtk_tree_model_iter_next(model, &iter))
+ {
+ gtk_tree_model_get(model, &iter, BMC_BOOKMARK, &item, -1);
+
+ if (item == param)
+ {
+ update_config_param_value(GTK_TREE_STORE(model), &iter);
+ break;
+ }
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : store = gestionnaire du tableau de données. *
+* iter = point de modification dans les lignes. *
+* param = paramètre dont la valeur est à afficher. *
+* *
+* Description : Actualise la valeur affichée d'un paramètre de configuration.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void update_config_param_value(GtkTreeStore *store, GtkTreeIter *iter)
+{
+ GCfgParam *param; /* Paramètre à consulter */
+ ConfigParamState state; /* Etat du paramètre */
+ char *state_desc; /* Version chaînée de l'état */
+ bool boolean; /* Valeur booléenne */
+ int integer; /* Valeur entière */
+ char int_val[sizeof(XSTR(INT_MIN)) + 1];/* Valeur en chaîne de carac. */
+ char *string; /* Chaîne de caractères */
+ char *desc; /* Description à afficher */
+
+ gtk_tree_model_get(GTK_TREE_MODEL(store), iter, BMC_BOOKMARK, &param, -1);
+
+ state = g_config_param_get_state(param);
+
+ if (state & CPS_DEFAULT)
+ state_desc = strdup(_("By default"));
+ else
+ state_desc = strdup(_("Changed"));
+
+ if (state & CPS_EMPTY)
+ state_desc = stradd(state_desc, _(" + empty"));
+
+ if (state & CPS_EMPTY)
+ desc = "";
+
+ else
+ switch (g_config_param_get_ptype(param))
+ {
+ case CPT_BOOLEAN:
+ g_config_param_get_value(param, &boolean);
+ desc = (boolean ? _("true") : _("false"));
+ break;
+
+ case CPT_INTEGER:
+ g_config_param_get_value(param, &integer);
+ snprintf(int_val, sizeof(int_val), "%d", integer);
+ desc = int_val;
+ break;
+
+ case CPT_STRING:
+ g_config_param_get_value(param, &string);
+ desc = (string != NULL ? string : "");
+ break;
+
+ default:
+ assert(false);
+ desc = "???";
+ break;
+
+ }
+
+ /*
+ gtk_tree_store_set(store, iter,
+ CPC_BOLD, state & CPS_DEFAULT ? 400 : 800,
+ CPC_STATUS, state_desc,
+ CPC_VALUE, desc, -1);
+ */
+
+ free(state_desc);
+
+ g_object_unref(G_OBJECT(param));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : model = gestionnaire du tableau de données. *
+* a = première ligne de données à traiter. *
+* b = seconde ligne de données à traiter. *
+* column = indice de la colonne à considérer, encodée. *
+* *
+* Description : Etablit une comparaison entre deux lignes de signets. *
+* *
+* Retour : Indication de tri entre les deux lignes fournies. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static gint compare_bookmarks_list_columns(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer column)
+{
+ gint result; /* Valeur calculée à retourner */
+ gchar *value_a; /* Cellule de la ligne 'a' */
+ gchar *value_b; /* Cellule de la ligne 'b' */
+
+ gtk_tree_model_get(model, a, GPOINTER_TO_INT(column), &value_a, -1);
+ gtk_tree_model_get(model, b, GPOINTER_TO_INT(column), &value_b, -1);
+
+ if (value_a == NULL || value_b == NULL)
+ {
+ if (value_a == NULL && value_b == NULL)
+ result = 0;
+ else
+ result = (value_a == NULL ? -1 : 1);
+ }
+ else
+ result = g_utf8_collate(value_a,value_b);
+
+ g_free(value_a);
+ g_free(value_b);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : treeview = composant graphique présentant les paramètres. *
+* event = informations liées à l'événement. *
+* panel = panneau d'affichage sur lequel s'appuyer. *
+* *
+* Description : Réagit à une pression sur <Shift+F2> et simule l'édition. *
+* *
+* Retour : FALSE pour poursuivre la propagation de l'événement. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static gboolean on_key_pressed_over_params(GtkTreeView *treeview, GdkEventKey *event, GBookmarksPanel *panel)
+{
+ const gchar *accelerator; /* Combinaison de raccourci */
+ guint accel_key; /* Touche de raccourci */
+ GdkModifierType accel_mod; /* Modifiateurs attendus aussi */
+ GtkTreeIter iter; /* Point de la sélection */
+ GtkTreeModel *model; /* Gestionnaire de données */
+ GtkTreePath *path; /* Chemin d'accès à ce point */
+
+ if (!g_generic_config_get_value(get_main_configuration(), MPK_KEYBINDINGS_EDIT, &accelerator))
+ return FALSE;
+
+ if (accelerator == NULL)
+ return FALSE;
+
+ gtk_accelerator_parse(accelerator, &accel_key, &accel_mod);
+
+ if (event->keyval == accel_key && event->state == accel_mod)
+ {
+ /* FIXME : unref(result) */
+ if (get_selected_panel_bookmark(treeview, &iter) != NULL)
+ {
+ model = gtk_tree_view_get_model(treeview);
+ path = gtk_tree_model_get_path(model, &iter);
+
+ gtk_tree_view_set_cursor(treeview, path,
+ gtk_tree_view_get_column(treeview, BMC_COMMENT - BMC_PHYSICAL),
+ TRUE);
+
+ gtk_tree_path_free(path);
+
+ }
+
+ }
+
+ return FALSE;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : renderer = moteur de rendu pour la cellule. *
+* path = chemin d'accès vers la cellule éditée. *
+* new = nouvelle valeur sous forme de texte à valider. *
+* store = gestionnaire des données de la liste affichée. *
+* *
+* Description : Réagit à une édition de la valeur d'un paramètre. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void on_param_value_edited(GtkCellRendererText *renderer, gchar *path, gchar *new, GtkTreeStore *store)
+{
+ GtkTreePath *tree_path; /* Chemin d'accès natif */
+ GtkTreeIter iter; /* Point de la modification */
+ GCfgParam *param; /* Paramètre à actualiser */
+ bool boolean; /* Valeur booléenne */
+ int integer; /* Valeur entière */
+ char *end; /* Pointeur vers '\0' final ? */
+
+ tree_path = gtk_tree_path_new_from_string(path);
+ if (tree_path == NULL) return;
+
+ if (!gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &iter, tree_path))
+ goto opve_bad_iter;
+
+ gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, BMC_BOOKMARK, &param, -1);
+
+ switch (g_config_param_get_ptype(param))
+ {
+ case CPT_BOOLEAN:
+
+ if (strcmp(new, "true") != 0 && strcmp(new, "false") != 0)
+ goto opve_bad_value;
+
+ boolean = (strcmp(new, "true") == 0);
+ g_config_param_set_value(param, boolean);
+
+ break;
+
+ case CPT_INTEGER:
+
+ integer = strtol(new, &end, 10);
+ if (*end != '\0') goto opve_bad_value;
+
+ g_config_param_set_value(param, integer);
+
+ break;
+
+ case CPT_STRING:
+ g_config_param_set_value(param, new);
+ break;
+
+ default:
+ assert(false);
+ goto opve_bad_value;
+ break;
+
+ }
+
+ opve_bad_value:
+
+ g_object_unref(G_OBJECT(param));
+
+ opve_bad_iter:
+
+ gtk_tree_path_free(tree_path);
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* FILTRAGE DES SYMBOLES PRESENTS */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : entry = entrée de texte contenant le filtre brut. *
+* panel = panneau assurant l'affichage des paramètres. *
+* *
+* Description : Démarre l'actualisation du filtrage des paramètres. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void on_param_search_changed(GtkSearchEntry *entry, GBookmarksPanel *panel)
+{
+ const gchar *text; /* Texte de l'utilisateur */
+ int ret; /* Bilan de mise en place */
+ GdkRGBA error; /* Couleur d'erreur */
+
+ if (panel->filter != NULL)
+ {
+ regfree(panel->filter);
+ free(panel->filter);
+ panel->filter = NULL;
+ }
+
+ text = gtk_entry_get_text(GTK_ENTRY(entry));
+
+ if (strlen(text) > 0)
+ {
+ panel->filter = (regex_t *)calloc(1, sizeof(regex_t));
+ ret = regcomp(panel->filter, text, REG_EXTENDED);
+
+ if (ret != 0)
+ {
+ free(panel->filter);
+ panel->filter = NULL;
+
+ error.red = 1.0;
+ error.green = 0.0;
+ error.blue = 0.0;
+ error.alpha = 1.0;
+ gtk_widget_override_color(GTK_WIDGET(entry), GTK_STATE_NORMAL, &error);
+
+ return;
+
+ }
+
+ }
+
+ gtk_widget_override_color(GTK_WIDGET(entry), GTK_STATE_NORMAL, NULL);
+
+ reload_config_into_treeview(panel, get_main_configuration());
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = panneau assurant l'affichage des paramètres. *
+* name = chemin d'accès au paramètre à traiter. *
+* *
+* Description : Détermine si un paramètre doit être filtré ou non. *
+* *
+* Retour : true si le paramètre ne doit pas être affiché, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool is_param_filtered(GBookmarksPanel *panel, const char *name)
+{
+ regmatch_t match; /* Récupération des trouvailles*/
+ int ret; /* Bilan du filtrage */
+
+ if (panel->filter == NULL)
+ return false;
+
+ ret = regexec(panel->filter, name, 1, &match, 0);
+ if (ret == REG_NOMATCH)
+ return true;
+
+ return false;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* ATTRIBUTION D'UN MENU CONTEXTUEL */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : widget = composant GTK visé par l'opération. *
+* event = informations liées à l'événement. *
+* panel = informations liées au panneau associé. *
+* *
+* Description : Assure la gestion des clics de souris sur les signets. *
+* *
+* Retour : FALSE pour poursuivre la propagation de l'événement. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static gboolean on_button_press_over_bookmarks(GtkWidget *widget, GdkEventButton *event, GBookmarksPanel *panel)
+{
+ if (event->button == 3)
+ gtk_menu_popup(panel->menu, NULL, NULL, NULL, NULL, event->button, event->time);
+
+ return FALSE;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = panneau d'affichage des signets liés à un binaire. *
+* *
+* Description : Construit le menu contextuel pour les signets. *
+* *
+* Retour : Panneau de menus mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GtkMenu *build_bookmarks_panel_menu(GBookmarksPanel *panel)
+{
+ GtkWidget *result; /* Support à retourner */
+ GtkWidget *submenuitem; /* Sous-élément de menu */
+
+ result = gtk_menu_new();
+
+ submenuitem = qck_create_menu_item(NULL, NULL, _("Edit"), G_CALLBACK(mcb_bookmarks_panel_edit), panel);
+ gtk_container_add(GTK_CONTAINER(result), submenuitem);
+
+ submenuitem = qck_create_menu_item(NULL, NULL, _("Delete"), G_CALLBACK(mcb_bookmarks_panel_delete), panel);
+ gtk_container_add(GTK_CONTAINER(result), submenuitem);
+
+ submenuitem = qck_create_menu_separator();
+ gtk_container_add(GTK_CONTAINER(result), submenuitem);
+
+ submenuitem = qck_create_menu_item(NULL, NULL, _("Filter..."), G_CALLBACK(mcb_bookmarks_panel_filter), panel);
+ gtk_container_add(GTK_CONTAINER(result), submenuitem);
+
+ return GTK_MENU(result);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : treeview = liste d'affichage à consulter. *
+* save = zone de conservation du point de trouvaille. [OUT]*
+* *
+* Description : Fournit le signet sélectionné dans la liste. *
+* *
+* Retour : Signet en cours d'édition ou NULL en cas de soucis. *
+* *
+* Remarques : Le résultat non nul est à déréférencer après usage. *
+* *
+******************************************************************************/
+
+static GDbBookmark *get_selected_panel_bookmark(GtkTreeView *treeview, GtkTreeIter *save)
+{
+ GDbBookmark *result; /* Paramètre à renvoyer */
+ GtkTreeSelection *selection; /* Représentation de sélection */
+ GtkTreeModel *model; /* Gestionnaire des données */
+ GtkTreeIter iter; /* Point de la sélection */
+
+ result = NULL;
+
+ selection = gtk_tree_view_get_selection(treeview);
+
+ if (gtk_tree_selection_get_selected(selection, &model, &iter))
+ gtk_tree_model_get(model, &iter, BMC_BOOKMARK, &result, -1);
+
+ if (save != NULL)
+ *save = iter;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : menuitem = élément de menu sélectionné. *
+* panel = panneau d'affichage des signets liés à un binaire.*
+* *
+* Description : Réagit avec le menu "Editer". *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void mcb_bookmarks_panel_edit(GtkMenuItem *menuitem, GBookmarksPanel *panel)
+{
+ GtkTreeIter iter; /* Point de la sélection */
+ GDbBookmark *mark; /* Signet sélectionné */
+ GtkTreeModel *model; /* Gestionnaire de données */
+ GtkTreePath *path; /* Chemin d'accès à ce point */
+
+ mark = get_selected_panel_bookmark(panel->treeview, &iter);
+ if (mark == NULL) return;
+
+ model = gtk_tree_view_get_model(panel->treeview);
+ path = gtk_tree_model_get_path(model, &iter);
+
+ gtk_tree_view_set_cursor(panel->treeview, path,
+ gtk_tree_view_get_column(panel->treeview, BMC_COMMENT - BMC_PHYSICAL),
+ TRUE);
+
+ gtk_tree_path_free(path);
+
+ g_object_unref(G_OBJECT(mark));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : menuitem = élément de menu sélectionné. *
+* panel = panneau d'affichage des signets liés à un binaire.*
+* *
+* Description : Réagit avec le menu "Supprimer". *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void mcb_bookmarks_panel_delete(GtkMenuItem *menuitem, GBookmarksPanel *panel)
+{
+ GDbBookmark *mark; /* Signet sélectionné */
+
+ mark = get_selected_panel_bookmark(panel->treeview, NULL);
+ if (mark == NULL) return;
+
+ g_loaded_binary_remove_from_collection(panel->binary, DBF_BOOKMARKS, G_DB_ITEM(mark));
+
+ g_object_unref(G_OBJECT(mark));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : menuitem = élément de menu sélectionné. *
+* panel = panneau d'affichage des signets liés à un binaire.*
+* *
+* Description : Réagit avec le menu "Filtrer...". *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void mcb_bookmarks_panel_filter(GtkMenuItem *menuitem, GBookmarksPanel *panel)
+{
+#if 0
+ GCfgParam *param; /* Paramètre sélectionné */
+
+ param = get_selected_panel_bookmark(panel->treeview, NULL);
+ if (param == NULL) return;
+
+ g_config_param_make_empty(param);
+
+ g_object_unref(G_OBJECT(param));
+#endif
+}
diff --git a/src/gui/panels/bookmarks.h b/src/gui/panels/bookmarks.h
new file mode 100644
index 0000000..507cc09
--- /dev/null
+++ b/src/gui/panels/bookmarks.h
@@ -0,0 +1,65 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * bookmarks.h - prototypes pour le panneau d'affichage des signets d'un binaire
+ *
+ * Copyright (C) 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#ifndef _GUI_PANELS_BOOKMARKS_H
+#define _GUI_PANELS_BOOKMARKS_H
+
+
+#include <i18n.h>
+
+
+#include "panel.h"
+
+
+
+#define PANEL_BOOKMARKS_ID _("Bookmarks")
+
+
+#define G_TYPE_BOOKMARKS_PANEL g_bookmarks_panel_get_type()
+#define G_BOOKMARKS_PANEL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_bookmarks_panel_get_type(), GBookmarksPanel))
+#define G_IS_BOOKMARKS_PANEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_bookmarks_panel_get_type()))
+#define G_BOOKMARKS_PANEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_BOOKMARKS_PANEL, GBookmarksPanelClass))
+#define G_IS_BOOKMARKS_PANEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_BOOKMARKS_PANEL))
+#define G_BOOKMARKS_PANEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_BOOKMARKS_PANEL, GBookmarksPanelClass))
+
+
+/* Panneau d'affichage des signets liés à un binaire (instance) */
+typedef struct _GBookmarksPanel GBookmarksPanel;
+
+/* Panneau d'affichage des signets liés à un binaire (classe) */
+typedef struct _GBookmarksPanelClass GBookmarksPanelClass;
+
+
+/* Indique le type définit pour un panneau d'affichage des signets liés à un binaire. */
+GType g_bookmarks_panel_get_type(void);
+
+/* Crée un panneau d'affichage des paramètres de configuration. */
+GEditorItem *g_bookmarks_panel_new(GObject *);
+
+/* Construit le panneau d'affichage des signets courants. */
+GPanelItem *create_bookmarks_panel(GObject *);
+
+
+
+#endif /* _GUI_PANELS_BOOKMARKS_H */
diff --git a/src/gui/panels/panel.c b/src/gui/panels/panel.c
index 5a7fc53..06be865 100644
--- a/src/gui/panels/panel.c
+++ b/src/gui/panels/panel.c
@@ -30,6 +30,7 @@
#include <sys/param.h>
+#include "bookmarks.h"
#include "glance.h"
#include "log.h"
#include "panel-int.h"
@@ -388,6 +389,9 @@ void load_main_panels(GObject *ref)
item = create_glance_panel(ref);
g_panel_item_dock(item);
+ item = create_bookmarks_panel(ref);
+ g_panel_item_dock(item);
+
}
diff --git a/src/gui/panels/regedit.c b/src/gui/panels/regedit.c
index 77fea39..159a4d0 100644
--- a/src/gui/panels/regedit.c
+++ b/src/gui/panels/regedit.c
@@ -263,7 +263,7 @@ static void g_regedit_panel_init(GRegeditPanel *panel)
g_object_unref(G_OBJECT(store));
- /* Cellule d'affichage */
+ /* Cellules d'affichage */
renderer = gtk_cell_renderer_text_new();
column = gtk_tree_view_column_new_with_attributes(_("Access path"), renderer,