summaryrefslogtreecommitdiff
path: root/src/analysis
diff options
context:
space:
mode:
Diffstat (limited to 'src/analysis')
-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/bookmark.h41
-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
26 files changed, 3648 insertions, 296 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/bookmark.h b/src/analysis/db/bookmark.h
deleted file mode 100644
index 5308e92..0000000
--- a/src/analysis/db/bookmark.h
+++ /dev/null
@@ -1,41 +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/>.
- */
-
-
-#ifndef _ANALYSIS_DB_BOOKMARK_H
-#define _ANALYSIS_DB_BOOKMARK_H
-
-
-
-#include <sqlite3.h>
-#include <stdbool.h>
-
-
-
-/* Crée la table des signets dans une base de données. */
-bool create_bookmark_db_table(sqlite3 *);
-
-
-
-
-
-#endif /* _ANALYSIS_DB_BOOKMARK_H */
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;
+
}