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