diff options
Diffstat (limited to 'src/analysis/db')
| -rw-r--r-- | src/analysis/db/cdb.c | 76 | ||||
| -rw-r--r-- | src/analysis/db/client.c | 20 | ||||
| -rw-r--r-- | src/analysis/db/client.h | 2 | ||||
| -rw-r--r-- | src/analysis/db/collection-int.h | 4 | ||||
| -rw-r--r-- | src/analysis/db/collection.c | 77 | ||||
| -rw-r--r-- | src/analysis/db/collection.h | 4 | ||||
| -rw-r--r-- | src/analysis/db/item-int.h | 24 | ||||
| -rw-r--r-- | src/analysis/db/item.c | 151 | ||||
| -rw-r--r-- | src/analysis/db/item.h | 12 | ||||
| -rw-r--r-- | src/analysis/db/items/Makefile.am | 3 | ||||
| -rw-r--r-- | src/analysis/db/items/bookmark.c | 175 | ||||
| -rw-r--r-- | src/analysis/db/items/bookmark.h | 7 | ||||
| -rw-r--r-- | src/analysis/db/items/comment.c | 400 | ||||
| -rw-r--r-- | src/analysis/db/items/comment.h | 38 | ||||
| -rw-r--r-- | src/analysis/db/items/switcher.c | 755 | ||||
| -rw-r--r-- | src/analysis/db/items/switcher.h | 121 | ||||
| -rw-r--r-- | src/analysis/db/misc/rlestr.c | 166 | ||||
| -rw-r--r-- | src/analysis/db/misc/rlestr.h | 27 | ||||
| -rw-r--r-- | src/analysis/db/protocol.h | 8 | ||||
| -rw-r--r-- | src/analysis/db/server.c | 141 | 
20 files changed, 1807 insertions, 404 deletions
diff --git a/src/analysis/db/cdb.c b/src/analysis/db/cdb.c index 46cfc23..96e69d5 100644 --- a/src/analysis/db/cdb.c +++ b/src/analysis/db/cdb.c @@ -34,6 +34,7 @@  #include <signal.h>  #include <stdint.h>  #include <stdio.h> +#include <stdlib.h>  #include <string.h>  #include <unistd.h>  #include <sys/stat.h> @@ -44,7 +45,6 @@  #include "collection.h"  #include "protocol.h" -#include "items/bookmark.h"  #include "../../common/cpp.h"  #include "../../common/extstr.h"  #include "../../common/io.h" @@ -127,11 +127,14 @@ static bool g_cdb_archive_read(GCdbArchive *); +/* -------------------------- MANIPULATION DES PARTIES XML -------------------------- */  /* Crée la description XML correspondant à l'archive. */  static bool g_cdb_archive_create_xml_desc(GCdbArchive *, const rle_string *); +/* Vérifie la conformité d'une description XML avec le serveur. */ +static bool g_cdb_archive_check_xml_version(const GCdbArchive *); @@ -201,6 +204,8 @@ static void g_cdb_archive_class_init(GCdbArchiveClass *klass)  static void g_cdb_archive_init(GCdbArchive *archive)  { +    archive->collections = create_collections_list(); +      g_mutex_init(&archive->clients_access);      g_mutex_init(&archive->id_access); @@ -330,7 +335,9 @@ GCdbArchive *g_cdb_archive_new(const char *owner, const rle_string *hash, const          g_cdb_archive_create_xml_desc(result, user);          g_cdb_archive_create_db(result, NULL); -        if (g_cdb_archive_write(result) != DBE_NONE) +        *error = g_cdb_archive_write(result); + +        if (*error != DBE_NONE)              goto gcan_error;      } @@ -342,10 +349,19 @@ GCdbArchive *g_cdb_archive_new(const char *owner, const rle_string *hash, const      if (!g_cdb_archive_read(result))          goto gcan_error; +    if (!g_cdb_archive_check_xml_version(result)) +    { +        *error = DBE_XML_VERSION_ERROR; +        goto gcan_error; +    } +      /* Chargement des éléments sauvegardés */      if (!g_cdb_archive_load_collections(result)) +    { +        *error = DBE_DB_LOADING_ERROR;          goto gcan_error; +    }      return result; @@ -586,12 +602,9 @@ int g_cdb_archive_compare_hash(const GCdbArchive *archive, const rle_string *has - -/* --------------------- OPERATIONS DE LECTURE D'UN FICHIER XML --------------------- */ -/* --------------------- OPERATIONS DE LECTURE D'UN FICHIER XML --------------------- */ - - - +/* ---------------------------------------------------------------------------------- */ +/*                            MANIPULATION DES PARTIES XML                            */ +/* ---------------------------------------------------------------------------------- */  /****************************************************************************** @@ -639,8 +652,38 @@ static bool g_cdb_archive_create_xml_desc(GCdbArchive *archive, const rle_string  } +/****************************************************************************** +*                                                                             * +*  Paramètres  : archive = archive à consulter.                               * +*                                                                             * +*  Description : Vérifie la conformité d'une description XML avec le serveur. * +*                                                                             * +*  Retour      : Bilan de la vérification.                                    * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_cdb_archive_check_xml_version(const GCdbArchive *archive) +{ +    bool result;                            /* Bilan à retourner           */ +    char *version;                          /* Version protocolaire        */ +    unsigned long int used;                 /* Version utilisée            */ + +    result = NULL; + +    version = get_node_text_value(archive->context, "/ChrysalideBinary/Protocol"); +    if (version == NULL) return false; + +    used = strtoul(version, NULL, 16); +    result = (used == CDB_PROTOCOL_VERSION); +    free(version); + +    return result; + +}  /* ---------------------------------------------------------------------------------- */ @@ -666,6 +709,8 @@ static bool g_cdb_archive_create_db(const GCdbArchive *archive, const core_db_in      bool result;                            /* Bilan à retourner           */      sqlite3 *db;                            /* Base de données à constituer*/      int ret;                                /* Bilan de la création        */ +    GList *iter;                            /* Boucle de parcours          */ +    GDbCollection *collec;                  /* Collection visée manipulée  */      ret = sqlite3_open(archive->sql_db, &db); @@ -675,11 +720,16 @@ static bool g_cdb_archive_create_db(const GCdbArchive *archive, const core_db_in          return false;      } +    result = true; - -    result = create_bookmark_db_table(db); - - +    for (iter = g_list_first(archive->collections); +         iter != NULL && result; +         iter = g_list_next(iter)) +    { +        collec = G_DB_COLLECTION(iter->data); +        result = g_db_collection_create_db_table(collec, db); +        fprintf(stderr, "STATUS :: %d\n", result); +    }      sqlite3_close(db); @@ -725,8 +775,6 @@ static bool g_cdb_archive_load_collections(GCdbArchive *archive)      GList *iter;                            /* Boucle de parcours          */      GDbCollection *collec;                  /* Collection visée manipulée  */ -    archive->collections = create_collections_list(); -      for (iter = g_list_first(archive->collections);           iter != NULL;           iter = g_list_next(iter)) diff --git a/src/analysis/db/client.c b/src/analysis/db/client.c index c19a39e..f0d3d4b 100644 --- a/src/analysis/db/client.c +++ b/src/analysis/db/client.c @@ -162,7 +162,7 @@ static void g_db_client_finalize(GDbClient *client)  *                                                                             *  ******************************************************************************/ -GDbClient *g_db_client_new(const char *name, const char *hash, GDbCollection *collections) +GDbClient *g_db_client_new(const char *name, const char *hash, GList *collections)  {      GDbClient *result;                      /* Adresse à retourner         */ @@ -257,7 +257,8 @@ bool g_db_client_start(GDbClient *client, const char *host, unsigned short port,      /**       * Le serveur doit répondre pour un message type :       *    - la commande 'DBC_WELCOME'. -     *    - un identifiant d'erreur ('DBE_NONE' ou 'DBE_WRONG_VERSION'). +     *    - un identifiant d'erreur ('DBE_NONE', 'DBE_BAD_EXCHANGE' +     *      ou 'DBE_WRONG_VERSION' ... 'DBE_LOADING_ERROR').       */      if (!safe_recv(client->fd, &data, sizeof(uint32_t), 0)) @@ -286,8 +287,21 @@ bool g_db_client_start(GDbClient *client, const char *host, unsigned short port,              goto gdcs_error;              break; +        case DBE_XML_VERSION_ERROR: +            log_variadic_message(LMT_ERROR, _("The archive from the server '%s:%hu' does not use our protocol version (0x%08x)..."), +                                 host, port, CDB_PROTOCOL_VERSION); +            goto gdcs_error; +            break; + +        case DBE_DB_LOADING_ERROR: +            log_variadic_message(LMT_ERROR, _("The server '%s:%hu' got into troubles while loading the database...."), +                                 host, port); +            goto gdcs_error; +            break; +          default: -            log_variadic_message(LMT_ERROR, _("The server '%s:%hu' uses an unknown protocol..."), host, port); +            log_variadic_message(LMT_ERROR, _("The server '%s:%hu' has run into an error (%u)..."), +                                 host, port, error);              goto gdcs_error;              break; diff --git a/src/analysis/db/client.h b/src/analysis/db/client.h index 66ebb08..6e9f10b 100644 --- a/src/analysis/db/client.h +++ b/src/analysis/db/client.h @@ -51,7 +51,7 @@ 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 *, const char *, GDbCollection *); +GDbClient *g_db_client_new(const char *, const char *, GList *);  /* Démarre la connexion à la base de données. */  bool g_db_client_start(GDbClient *, const char *, unsigned short, const char *); diff --git a/src/analysis/db/collection-int.h b/src/analysis/db/collection-int.h index 6ca9ab4..93e0ef8 100644 --- a/src/analysis/db/collection-int.h +++ b/src/analysis/db/collection-int.h @@ -32,6 +32,9 @@ +/* Crée la table associée à une collection d'éléments. */ +typedef bool (* collec_create_db_table_fc) (const GDbCollection *, sqlite3 *); +  /* Décrit les colonnes utiles à un chargement de données. */  typedef bool (* collec_setup_load_fc) (GDbCollection *, bound_value **, size_t *); @@ -63,6 +66,7 @@ struct _GDbCollectionClass  {      GObjectClass parent;                    /* A laisser en premier        */ +    collec_create_db_table_fc create_table; /* Création de la table en SQL */      collec_setup_load_fc setup_load;        /* Prépare le chargement       */      collec_load_item load_item;             /* Charge un élément           */      collec_has_key_fc has_key;              /* Recherche de présence       */ diff --git a/src/analysis/db/collection.c b/src/analysis/db/collection.c index 84acc58..27f4ddb 100644 --- a/src/analysis/db/collection.c +++ b/src/analysis/db/collection.c @@ -31,6 +31,7 @@  #include "collection-int.h" +#include "misc/rlestr.h"  #include "../../common/extstr.h"  #include "../../common/io.h"  #include "../../glibext/chrysamarshal.h" @@ -59,6 +60,9 @@ static void g_db_collection_finalize(GDbCollection *);  /* Décrit les colonnes utiles à un chargement de données. */ +static bool _g_db_collection_setup_load(GDbCollection *, bound_value **, size_t *); + +/* Décrit les colonnes utiles à un chargement de données. */  static bool g_db_collection_setup_load(GDbCollection *, bound_value **, size_t *);  /* Enregistre un élément de collection dans une base de données. */ @@ -93,6 +97,8 @@ static void g_db_collection_class_init(GDbCollectionClass *klass)      object->dispose = (GObjectFinalizeFunc/* ! */)g_db_collection_dispose;      object->finalize = (GObjectFinalizeFunc)g_db_collection_finalize; +    klass->setup_load = (collec_setup_load_fc)_g_db_collection_setup_load; +      g_signal_new("content-changed",                   G_TYPE_DB_COLLECTION,                   G_SIGNAL_RUN_LAST, @@ -578,6 +584,65 @@ bool _g_db_collection_modify_item(GDbCollection *collec, GDbItem *item, bool loc  /******************************************************************************  *                                                                             * +*  Paramètres  : collec = ensemble d'éléments spectateur des opérations.      * +*                db     = accès à la base de données.                         * +*                                                                             * +*  Description : Crée la table d'élément dans une base de données.            * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool g_db_collection_create_db_table(const GDbCollection *collec, sqlite3 *db) +{ +    fprintf(stderr, "CREATE '%s'\n", collec->name); + +    return G_DB_COLLECTION_GET_CLASS(collec)->create_table(collec, db); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : collec = ensemble d'éléments à consulter.                    * +*                values = tableau d'éléments à compléter. [OUT]               * +*                count  = nombre de descriptions renseignées. [OUT]           * +*                                                                             * +*  Description : Décrit les colonnes utiles à un chargement de données.       * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool _g_db_collection_setup_load(GDbCollection *collec, bound_value **values, size_t *count) +{ +    *count += 2; +    *values = (bound_value *)realloc(*values, *count * sizeof(bound_value)); + +    (*values)[*count - 2].name = "created"; + +    (*values)[*count - 1].name = "modified"; + +    if (!setup_load_of_rle_string(NULL, "author", values, count)) +        return false; + +    if (!setup_load_of_rle_string(NULL, "tool", values, count)) +        return false; + +    if (!setup_load_of_rle_string(NULL, "label", values, count)) +        return false; + +    return true; + +} + + +/****************************************************************************** +*                                                                             *  *  Paramètres  : collec = ensemble d'éléments à consulter.                    *  *                values = tableau d'éléments à compléter. [OUT]               *  *                count  = nombre de descriptions renseignées. [OUT]           * @@ -622,6 +687,7 @@ bool g_db_collection_load_all_items(GDbCollection *collec, sqlite3 *db)      size_t i;                               /* Boucle de parcours          */      sqlite3_stmt *stmt;                     /* Déclaration mise en place   */      int ret;                                /* Bilan d'un appel à SQLite   */ +    GDbItem *new;                           /* Nouvel élément à insérer    */      if (!g_db_collection_setup_load(collec, &values, &count))          return false; @@ -644,7 +710,7 @@ bool g_db_collection_load_all_items(GDbCollection *collec, sqlite3 *db)      sql = stradd(sql, collec->name);      sql = stradd(sql, ";"); -	ret = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL); +    ret = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);  	if (ret != SQLITE_OK)      {  		fprintf(stderr, "Can't prepare SELECT statment '%s' (ret=%d): %s\n", sql, ret, sqlite3_errmsg(db)); @@ -695,7 +761,10 @@ bool g_db_collection_load_all_items(GDbCollection *collec, sqlite3 *db)          /* Chargement d'un nouvel élément */ -        result = G_DB_COLLECTION_GET_CLASS(collec)->load_item(collec, values, count); +        new = g_object_new(G_DB_COLLECTION(collec)->type, NULL); + +        result = g_db_item_load(new, values, count); +        result &= g_db_collection_add_item(G_DB_COLLECTION(collec), new);      } @@ -707,8 +776,6 @@ bool g_db_collection_load_all_items(GDbCollection *collec, sqlite3 *db)      free(sql); -    printf("LOAD ? %d\n", result); -      return result;  } @@ -739,7 +806,7 @@ static bool g_db_collection_store_item(const GDbCollection *collec, const GDbIte      int ret;                                /* Bilan d'un appel à SQLite   */      int index;                              /* Indice de valeur attachée   */ -    if (!g_db_item_prepare_db_statement(item, true, &values, &count)) +    if (!g_db_item_prepare_db_statement(item, &values, &count))          return false;      result = false; diff --git a/src/analysis/db/collection.h b/src/analysis/db/collection.h index 268c2be..f190acc 100644 --- a/src/analysis/db/collection.h +++ b/src/analysis/db/collection.h @@ -114,12 +114,14 @@ bool _g_db_collection_modify_item(GDbCollection *, GDbItem *, bool);  /* --------------------- MANIPULATIONS AVEC UNE BASE DE DONNEES --------------------- */ +/* Crée la table d'élément dans une base de données. */ +bool g_db_collection_create_db_table(const GDbCollection *, sqlite3 *); +  /* Charge un ensemble d'éléments à partir d'une base de données. */  bool g_db_collection_load_all_items(GDbCollection *, sqlite3 *); -  /* ------------------- CREATION DE L'ABSTRACTION POUR COLLECTIONS ------------------- */ diff --git a/src/analysis/db/item-int.h b/src/analysis/db/item-int.h index 0f75ed4..7b99f4a 100644 --- a/src/analysis/db/item-int.h +++ b/src/analysis/db/item-int.h @@ -31,9 +31,7 @@  #include <stdint.h> - - - +#include "misc/rlestr.h" @@ -44,7 +42,10 @@ typedef bool (* recv_db_item_fc) (GDbItem *, int, int);  typedef bool (* send_db_item_fc) (const GDbItem *, int, int);  /* Constitue les champs destinés à une insertion / modification. */ -typedef bool (* prepare_db_statement) (const GDbItem *, bool, bound_value **, size_t *); +typedef bool (* prepare_db_statement) (const GDbItem *, bound_value **, size_t *); + +/* Charge les valeurs utiles pour une localisation. */ +typedef bool (* load_db_item_fc) (GDbItem *, const bound_value *, size_t);  /* Base d'un élément pour collection générique (instance) */ @@ -55,6 +56,11 @@ struct _GDbItem      uint64_t created;                       /* Date de création            */      uint64_t modified;                      /* Date de modification        */ +    rle_string author;                      /* Utilisateur d'origine       */ +    rle_string tool;                        /* Eventuel outil automatique ?*/ + +    rle_string label;                       /* Représentation humaine      */ +      bool is_volatile;                       /* Pas besoin de sauvegarde ?  */  }; @@ -70,9 +76,19 @@ struct _GDbItemClass      send_db_item_fc send;                   /* Emission depuis le réseau   */      prepare_db_statement prepare_stmt;      /* Préparation d'une requête   */ +    load_db_item_fc load;                   /* Chargement à partir d'une BD*/  }; +/* Définition du tronc commun pour les créations SQLite */ +#define SQLITE_DB_ITEM_CREATE                   \ +    "created INTEGER, "                         \ +    "modified INTEGER, "                        \ +    SQLITE_RLESTR_CREATE("author") ", "         \ +    SQLITE_RLESTR_CREATE("tool") ", "           \ +    SQLITE_RLESTR_CREATE("label") + +  #endif  /* _ANALYSIS_DB_ITEM_INT_H */ diff --git a/src/analysis/db/item.c b/src/analysis/db/item.c index 7fa1a52..746ca27 100644 --- a/src/analysis/db/item.c +++ b/src/analysis/db/item.c @@ -24,6 +24,7 @@  #include "item.h" +#include <assert.h>  #include <malloc.h>  #include <sqlite3.h> @@ -61,7 +62,10 @@ static bool g_db_item_send_to_fd(const GDbItem *, int, int);  /* Constitue les champs destinés à une insertion / modification. */ -static bool _g_db_item_prepare_db_statement(const GDbItem *, bool, bound_value **, size_t *); +static bool _g_db_item_prepare_db_statement(const GDbItem *, bound_value **, size_t *); + +/* Charge les valeurs utiles pour un élément de collection. */ +static bool _g_db_item_load(GDbItem *, const bound_value *, size_t); @@ -96,6 +100,7 @@ static void g_db_item_class_init(GDbItemClass *klass)      klass->send = (send_db_item_fc)g_db_item_send_to_fd;      klass->prepare_stmt = (prepare_db_statement)_g_db_item_prepare_db_statement; +    klass->load = (load_db_item_fc)_g_db_item_load;  } @@ -114,6 +119,15 @@ static void g_db_item_class_init(GDbItemClass *klass)  static void g_db_item_init(GDbItem *item)  { +    const char *author;                     /* Identification à diffuser   */ +    bool status;                            /* Bilan d'une obtention       */ + +    status = g_generic_config_get_value(get_main_configuration(), MPK_AUTHOR_NAME, &author); +    assert(status); + +    set_rle_string(&item->author, author); + +    item->is_volatile = false;  } @@ -193,7 +207,7 @@ static gint g_db_item_cmp(GDbItem *a, GDbItem *b)              result = -1;          else -            result = 0; +            result = cmp_rle_string(&a->label, &b->label);      } @@ -241,16 +255,25 @@ 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); +    status = safe_recv(fd, &val64, sizeof(uint64_t), MSG_WAITALL | flags);      if (!status) return false;      item->created = be64toh(val64); -    status = safe_recv(fd, &val64, sizeof(uint64_t), flags); +    status = safe_recv(fd, &val64, sizeof(uint64_t), MSG_WAITALL | flags);      if (!status) return false;      item->modified = be64toh(val64); +    status = recv_rle_string(&item->author, fd, flags); +    if (!status) return false; + +    status = recv_rle_string(&item->tool, fd, flags); +    if (!status) return false; + +    status = recv_rle_string(&item->label, fd, flags); +    if (!status) return false; +      return true;  } @@ -295,14 +318,19 @@ static bool g_db_item_send_to_fd(const GDbItem *item, int fd, int flags)  {      bool status;                            /* Bilan d'une émission        */ +    status = safe_send(fd, (uint64_t []) { htobe64(item->created) }, sizeof(uint64_t), MSG_MORE | flags); +    if (!status) return false; -    printf("<sending> FROM %s...\n", __FUNCTION__); +    status = safe_send(fd, (uint64_t []) { htobe64(item->modified) }, sizeof(uint64_t), MSG_MORE | flags); +    if (!status) return false; +    status = send_rle_string(&item->author, fd, MSG_MORE | flags); +    if (!status) return false; -    status = safe_send(fd, (uint64_t []) { htobe64(item->created) }, sizeof(uint64_t), MSG_MORE | flags); +    status = send_rle_string(&item->tool, fd, MSG_MORE | flags);      if (!status) return false; -    status = safe_send(fd, (uint64_t []) { htobe64(item->modified) }, sizeof(uint64_t), flags); +    status = send_rle_string(&item->label, fd, flags);      if (!status) return false;      return true; @@ -379,7 +407,6 @@ bool g_db_item_is_volatile(const GDbItem *item)  /******************************************************************************  *                                                                             *  *  Paramètres  : item   = base d'éléments sur laquelle s'appuyer.             * -*                create = indique si la préparation vise une création ou non. *  *                values = couples de champs et de valeurs à lier. [OUT]       *  *                count  = nombre de ces couples. [OUT]                        *  *                                                                             * @@ -391,35 +418,35 @@ bool g_db_item_is_volatile(const GDbItem *item)  *                                                                             *  ******************************************************************************/ -static bool _g_db_item_prepare_db_statement(const GDbItem *item, bool create, bound_value **values, size_t *count) +static bool _g_db_item_prepare_db_statement(const GDbItem *item, bound_value **values, size_t *count)  { -    char *author;                           /* Identification à diffuser   */ +    bool result;                            /* Bilan à retourner           */      bound_value *value;                     /* Valeur à éditer / définir   */ -    if (!g_generic_config_get_value(get_main_configuration(), MPK_AUTHOR_NAME, &author)) -        return false; +    result = true; + +    *count += 2; +    *values = (bound_value *)realloc(*values, *count * sizeof(bound_value)); + +    value = &(*values)[*count - 2]; + +    value->name = "created"; +    value->type = SQLITE_INT64; +    value->integer64 = item->created; -    *values = (bound_value *)realloc(*values, ++(*count) * sizeof(bound_value));      value = &(*values)[*count - 1]; -    value->name = "user"; -    value->type = SQLITE_TEXT; -    value->string = author; -    value->delete = free; +    value->name = "modified"; +    value->type = SQLITE_INT64; +    value->integer64 = item->modified; -    if (!create) -    { -        *values = (bound_value *)realloc(*values, ++(*count) * sizeof(bound_value)); -        value = &(*values)[*count - 1]; +    result &= prepare_db_statement_for_rle_string(&item->author, "author", values, count); -        value->name = "modified"; -        value->type = SQLITE_RAW; -        value->string = "CURRENT_TIMESTAMP"; -        value->delete = SQLITE_STATIC; +    result &= prepare_db_statement_for_rle_string(&item->tool, "tool", values, count); -    } +    result &= prepare_db_statement_for_rle_string(&item->label, "label", values, count); -    return true; +    return result;  } @@ -427,7 +454,6 @@ static bool _g_db_item_prepare_db_statement(const GDbItem *item, bool create, bo  /******************************************************************************  *                                                                             *  *  Paramètres  : item   = base d'éléments sur laquelle s'appuyer.             * -*                create = indique si la préparation vise une création ou non. *  *                values = couples de champs et de valeurs à lier. [OUT]       *  *                count  = nombre de ces couples. [OUT]                        *  *                                                                             * @@ -439,11 +465,76 @@ static bool _g_db_item_prepare_db_statement(const GDbItem *item, bool create, bo  *                                                                             *  ******************************************************************************/ -bool g_db_item_prepare_db_statement(const GDbItem *item, bool create, bound_value **values, size_t *count) +bool g_db_item_prepare_db_statement(const GDbItem *item, bound_value **values, size_t *count)  {      *values = NULL;      *count = 0; -    return G_DB_ITEM_GET_CLASS(item)->prepare_stmt(item, create, values, count); +    return G_DB_ITEM_GET_CLASS(item)->prepare_stmt(item, values, count); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : item   = base d'éléments à charger depuis les réponses.      * +*                values = tableau d'éléments à consulter.                     * +*                count  = nombre de descriptions renseignées.                 * +*                                                                             * +*  Description : Charge les valeurs utiles pour un élément de collection.     * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool _g_db_item_load(GDbItem *item, const bound_value *values, size_t count) +{ +    bool result;                            /* Bilan global à retourner    */ +    const bound_value *value;               /* Valeur à éditer / définir   */ + +    value = find_bound_value(values, count, "created"); +    if (value == NULL) return false; +    if (value->type != SQLITE_INT64) return false; + +    item->created = value->integer64; + +    value = find_bound_value(values, count, "modified"); +    if (value == NULL) return false; +    if (value->type != SQLITE_INT64) return false; + +    item->modified = value->integer64; + +    result = true; + +    result &= load_rle_string(&item->author, "author", values, count); + +    result &= load_rle_string(&item->tool, "tool", values, count); + +    result &= load_rle_string(&item->label, "label", values, count); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : item   = base d'éléments à charger depuis les réponses.      * +*                values = tableau d'éléments à consulter.                     * +*                count  = nombre de descriptions renseignées.                 * +*                                                                             * +*  Description : Charge les valeurs utiles pour un élément de collection.     * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool g_db_item_load(GDbItem *item, const bound_value *values, size_t count) +{ +    return G_DB_ITEM_GET_CLASS(item)->load(item, values, count);  } diff --git a/src/analysis/db/item.h b/src/analysis/db/item.h index 2f8ee60..c70eefa 100644 --- a/src/analysis/db/item.h +++ b/src/analysis/db/item.h @@ -71,15 +71,11 @@ bool g_db_item_is_volatile(const GDbItem *);  /* --------------------- MANIPULATIONS AVEC UNE BASE DE DONNEES --------------------- */ -/* Définition du tronc commun pour les créations SQLite */ -#define SQLITE_DB_ITEM_CREATE                       \ -    "user TEXT, "                                   \ -    "created TIMESTAMP DEFAULT CURRENT_TIMESTAMP, " \ -    "modified TIMESTAMP DEFAULT CURRENT_TIMESTAMP, " - -  /* Constitue les champs destinés à une insertion / modification. */ -bool g_db_item_prepare_db_statement(const GDbItem *, bool, bound_value **, size_t *); +bool g_db_item_prepare_db_statement(const GDbItem *, bound_value **, size_t *); + +/* Charge les valeurs utiles pour un élément de collection. */ +bool g_db_item_load(GDbItem *, const bound_value *, size_t); diff --git a/src/analysis/db/items/Makefile.am b/src/analysis/db/items/Makefile.am index f026d44..c0e6b47 100644 --- a/src/analysis/db/items/Makefile.am +++ b/src/analysis/db/items/Makefile.am @@ -3,7 +3,8 @@ noinst_LTLIBRARIES  = libanalysisdbitems.la  libanalysisdbitems_la_SOURCES =			\  	bookmark.h bookmark.c				\ -	comment.h comment.c +	comment.h comment.c					\ +	switcher.h switcher.c  libanalysisdbitems_la_LIBADD =	 diff --git a/src/analysis/db/items/bookmark.c b/src/analysis/db/items/bookmark.c index a8182ce..c9d7b7a 100644 --- a/src/analysis/db/items/bookmark.c +++ b/src/analysis/db/items/bookmark.c @@ -30,10 +30,6 @@  #include "../collection-int.h"  #include "../item-int.h" -#include "../misc/rlestr.h" - - - @@ -58,7 +54,6 @@ struct _GDbBookmarkClass  }; -  /* Initialise la classe des signets dans une zone de texte. */  static void g_db_bookmark_class_init(GDbBookmarkClass *); @@ -71,8 +66,6 @@ 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 *); @@ -83,18 +76,16 @@ static bool g_db_bookmark_recv_from_fd(GDbBookmark *, int, int);  static bool g_db_bookmark_send_to_fd(const GDbBookmark *, int, int);  /* Constitue les champs destinés à une insertion / modification. */ -static bool g_db_bookmark_prepare_db_statement(const GDbBookmark *, bool, bound_value **, size_t *); - - +static bool g_db_bookmark_prepare_db_statement(const GDbBookmark *, bound_value **, size_t *); +/* Charge les valeurs utiles pour un signet. */ +static bool g_db_bookmark_load(GDbBookmark *, const bound_value *, size_t);  /* ---------------------- DEFINITION DE LA COLLECTION ASSOCIEE ---------------------- */ - -  /* Collection dédiée aux signets (instance) */  struct _GBookmarkCollection  { @@ -122,12 +113,12 @@ static void g_bookmark_collection_dispose(GBookmarkCollection *);  /* Procède à la libération totale de la mémoire. */  static void g_bookmark_collection_finalize(GBookmarkCollection *); +/* Crée la table des signets dans une base de données. */ +static bool g_bookmark_collection_create_db_table(const GBookmarkCollection *, sqlite3 *); +  /* Décrit les colonnes utiles à un chargement de données. */  static bool g_bookmark_collection_setup_load(GBookmarkCollection *, bound_value **, size_t *); -/* Charge les valeurs utiles pour une localisation. */ -static bool g_bookmark_collection_load_item(GBookmarkCollection *, const bound_value *, size_t); -  /* Détermine si un élément est déjà présent ou non. */  static GDbItem *g_bookmark_collection_has_key(GBookmarkCollection *, va_list *); @@ -172,6 +163,7 @@ static void g_db_bookmark_class_init(GDbBookmarkClass *klass)      item->send = (send_db_item_fc)g_db_bookmark_send_to_fd;      item->prepare_stmt = (prepare_db_statement)g_db_bookmark_prepare_db_statement; +    item->load = (load_db_item_fc)g_db_bookmark_load;  } @@ -227,6 +219,8 @@ static void g_db_bookmark_dispose(GDbBookmark *bookmark)  static void g_db_bookmark_finalize(GDbBookmark *bookmark)  { +    exit_rle_string(&bookmark->comment); +      G_OBJECT_CLASS(g_db_bookmark_parent_class)->finalize(G_OBJECT(bookmark));  } @@ -260,11 +254,6 @@ GDbBookmark *g_db_bookmark_new(const vmpa2t *addr, const char *comment)  } - - - - -  /******************************************************************************  *                                                                             *  *  Paramètres  : a = premier élément à analyser.                              * @@ -287,8 +276,10 @@ static gint g_db_bookmark_cmp(GDbBookmark *a, GDbBookmark *b)      if (result == 0)          result = cmp_rle_string(&a->comment, &b->comment); -    return result; +    if (result == 0) +        result = G_DB_ITEM_CLASS(g_db_bookmark_parent_class)->cmp(G_DB_ITEM(a), G_DB_ITEM(b)); +    return result;  } @@ -314,10 +305,10 @@ static bool g_db_bookmark_recv_from_fd(GDbBookmark *bookmark, int fd, int flags)      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)) +    if (!recv_vmpa(&bookmark->addr, fd, flags))          return false; -    if (!recv_rle_string(&bookmark->comment, fd, 0)) +    if (!recv_rle_string(&bookmark->comment, fd, flags))          return false;      return true; @@ -346,10 +337,6 @@ static bool g_db_bookmark_send_to_fd(const GDbBookmark *bookmark, int fd, int fl      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; @@ -363,10 +350,9 @@ static bool g_db_bookmark_send_to_fd(const GDbBookmark *bookmark, int fd, int fl  /******************************************************************************  *                                                                             * -*  Paramètres  : item   = base d'éléments sur laquelle s'appuyer.             * -*                create = indique si la préparation vise une création ou non. * -*                values = couples de champs et de valeurs à lier. [OUT]       * -*                count  = nombre de ces couples. [OUT]                        * +*  Paramètres  : bookmark = base d'éléments sur laquelle s'appuyer.           * +*                values   = couples de champs et de valeurs à lier. [OUT]     * +*                count    = nombre de ces couples. [OUT]                      *  *                                                                             *  *  Description : Constitue les champs destinés à une insertion / modification.*  *                                                                             * @@ -376,36 +362,51 @@ static bool g_db_bookmark_send_to_fd(const GDbBookmark *bookmark, int fd, int fl  *                                                                             *  ******************************************************************************/ -static bool g_db_bookmark_prepare_db_statement(const GDbBookmark *bookmark, bool create, bound_value **values, size_t *count) +static bool g_db_bookmark_prepare_db_statement(const GDbBookmark *bookmark, bound_value **values, size_t *count)  {      bool status;                            /* Bilan d'opération initiale  */ -    bound_value *value;                     /* Valeur à éditer / définir   */ -    status = G_DB_ITEM_CLASS(g_db_bookmark_parent_class)->prepare_stmt(G_DB_ITEM(bookmark), create, values, count); +    status = G_DB_ITEM_CLASS(g_db_bookmark_parent_class)->prepare_stmt(G_DB_ITEM(bookmark), values, count);      if (!status) return false; -    status = prepare_vmpa_db_statement(&bookmark->addr, create, values, count); +    status = prepare_vmpa_db_statement(&bookmark->addr, values, count);      if (!status) return false; -    *values = (bound_value *)realloc(*values, ++(*count) * sizeof(bound_value)); -    value = &(*values)[*count - 1]; - -    value->name = "comment"; -    value->type = SQLITE_TEXT; -    value->cstring = g_db_bookmark_get_comment(bookmark); -    value->delete = SQLITE_STATIC; +    status &= prepare_db_statement_for_rle_string(&bookmark->comment, "comment", values, count); +    if (!status) return false;      return true;  } +/****************************************************************************** +*                                                                             * +*  Paramètres  : bookmark = bascule d'affichage à charger depuis les réponses.* +*                values   = tableau d'éléments à consulter.                   * +*                count    = nombre de descriptions renseignées.               * +*                                                                             * +*  Description : Charge les valeurs utiles pour un signet.                    * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ +static bool g_db_bookmark_load(GDbBookmark *bookmark, const bound_value *values, size_t count) +{ +    bool result;                            /* Bilan à faire remonter      */ +    result = G_DB_ITEM_CLASS(g_db_bookmark_parent_class)->load(G_DB_ITEM(bookmark), values, count); +    result &= load_vmpa(&bookmark->addr, values, count); +    result &= load_rle_string(&bookmark->comment, "comment", values, count); +    return result; +}  /****************************************************************************** @@ -500,8 +501,8 @@ static void g_bookmark_collection_class_init(GBookmarkCollectionClass *klass)      collec = G_DB_COLLECTION_CLASS(klass); +    collec->create_table = (collec_create_db_table_fc)g_bookmark_collection_create_db_table;      collec->setup_load = (collec_setup_load_fc)g_bookmark_collection_setup_load; -    collec-> load_item = (collec_load_item)g_bookmark_collection_load_item;      collec->has_key = (collec_has_key_fc)g_bookmark_collection_has_key;  } @@ -553,7 +554,7 @@ static void g_bookmark_collection_dispose(GBookmarkCollection *collec)  /******************************************************************************  *                                                                             * -*  Paramètres  : bookmark = instance d'objet GLib à traiter.                  * +*  Paramètres  : collec = instance d'objet GLib à traiter.                    *  *                                                                             *  *  Description : Procède à la libération totale de la mémoire.                *  *                                                                             * @@ -593,17 +594,10 @@ GBookmarkCollection *g_bookmark_collection_new(void)  } - - - - - - - -  /******************************************************************************  *                                                                             * -*  Paramètres  : db = accès à la base de données.                             * +*  Paramètres  : collec = ensemble d'éléments spectateur des opérations.      * +*                db     = accès à la base de données.                         *  *                                                                             *  *  Description : Crée la table des signets dans une base de données.          *  *                                                                             * @@ -613,16 +607,16 @@ GBookmarkCollection *g_bookmark_collection_new(void)  *                                                                             *  ******************************************************************************/ -bool create_bookmark_db_table(sqlite3 *db) +static bool g_bookmark_collection_create_db_table(const GBookmarkCollection *collec, sqlite3 *db)  {      char *sql;                              /* Requête à exécuter          */      int ret;                                /* Bilan de la création        */      char *msg;                              /* Message d'erreur            */      sql = "CREATE TABLE Bookmarks ("            \ -             SQLITE_DB_ITEM_CREATE              \ -             SQLITE_VMPA_CREATE                 \ -             "comment TEXT"                     \ +             SQLITE_DB_ITEM_CREATE ", "         \ +             SQLITE_VMPA_CREATE ", "            \ +             SQLITE_RLESTR_CREATE("comment")    \            ");";      ret = sqlite3_exec(db, sql, NULL, NULL, &msg); @@ -637,9 +631,6 @@ bool create_bookmark_db_table(sqlite3 *db)  } - - -  /******************************************************************************  *                                                                             *  *  Paramètres  : collec = ensemble d'éléments à consulter.                    * @@ -656,69 +647,19 @@ bool create_bookmark_db_table(sqlite3 *db)  static bool g_bookmark_collection_setup_load(GBookmarkCollection *collec, bound_value **values, size_t *count)  { -    // TODO : classe supérieure +    bool status;                            /* Bilan d'une préparation     */ + +    status = G_DB_COLLECTION_CLASS(g_bookmark_collection_parent_class)->setup_load(G_DB_COLLECTION(collec), \ +                                                                                   values, count); +    if (!status) return false;      if (!setup_load_for_vmpa(NULL, values, count))          return false; -    *values = (bound_value *)realloc(*values, ++(*count) * sizeof(bound_value)); - -    (*values)[*count - 1].name = "comment"; - -    return true; - - -} - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : collec = ensemble d'éléments à compléter.                    * -*                values = tableau d'éléments à consulter.                     * -*                count  = nombre de descriptions renseignées.                 * -*                                                                             * -*  Description : Charge les valeurs utiles pour une localisation.             * -*                                                                             * -*  Retour      : Bilan de l'opération.                                        * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static bool g_bookmark_collection_load_item(GBookmarkCollection *collec, const bound_value *values, size_t count) -{ -    vmpa2t addr;                            /* Localisation d'un signet    */ -    const char *comment;                    /* Eventuel commentaire associé*/ -    const bound_value *value;               /* Valeur à intégrer           */ -    GDbBookmark *new;                       /* Nouvel élément à intégrer   */ - -    if (!load_vmpa(&addr, values, count)) +    if (!setup_load_of_rle_string(NULL, "comment", values, count))          return false; -    value = find_bound_value(values, count, "comment"); -    if (value == NULL) return false; - -    switch (value->type) -    { -        case SQLITE_TEXT: -            comment = value->cstring; -            break; - -        case SQLITE_NULL: -            comment = NULL; -            break; - -        default: -            return false; -            break; - -    } - -    new = g_db_bookmark_new(&addr, comment); - -    printf(" LOAD new bm :: %p\n", new); - -    return g_db_collection_add_item(G_DB_COLLECTION(collec), G_DB_ITEM(new)); +    return true;  } diff --git a/src/analysis/db/items/bookmark.h b/src/analysis/db/items/bookmark.h index de12b1b..61b2c01 100644 --- a/src/analysis/db/items/bookmark.h +++ b/src/analysis/db/items/bookmark.h @@ -35,13 +35,6 @@ -/* Crée la table des signets dans une base de données. */ -bool create_bookmark_db_table(sqlite3 *); - - - - -  /* --------------------- ELABORATION D'UN ELEMENT DE COLLECTION --------------------- */ diff --git a/src/analysis/db/items/comment.c b/src/analysis/db/items/comment.c index 73a18b0..1bed0ab 100644 --- a/src/analysis/db/items/comment.c +++ b/src/analysis/db/items/comment.c @@ -28,17 +28,20 @@  #include <sys/socket.h> +#include "../collection-int.h"  #include "../item-int.h" -#include "../misc/rlestr.h" +/* --------------------- ELABORATION D'UN ELEMENT DE COLLECTION --------------------- */ + +  /* Commentaire à placer dans du texte quelconque (instance) */  struct _GDbComment  {      GDbItem parent;                         /* A laisser en premier        */ -    vmpa2t *addr;                           /* Adresse du commentaire      */ +    vmpa2t addr;                            /* Adresse du commentaire      */      rle_string text;                        /* Contenu du commentaire      */  }; @@ -51,7 +54,6 @@ struct _GDbCommentClass  }; -  /* Initialise la classe des commentaires dans une zone de texte. */  static void g_db_comment_class_init(GDbCommentClass *); @@ -73,53 +75,58 @@ 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); +/* Constitue les champs destinés à une insertion / modification. */ +static bool g_db_comment_prepare_db_statement(const GDbComment *, bound_value **, size_t *); +/* Charge les valeurs utiles pour un commentaire. */ +static bool g_db_comment_load(GDbComment *, const bound_value *, size_t); -/****************************************************************************** -*                                                                             * -*  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) +/* ---------------------- DEFINITION DE LA COLLECTION ASSOCIEE ---------------------- */ + + +/* Collection dédiée aux commentaires textuels (instance) */ +struct _GCommentCollection  { -    char *sql;                              /* Requête à exécuter          */ -    int ret;                                /* Bilan de la création        */ -    char *msg;                              /* Message d'erreur            */ +    GDbCollection parent;                   /* A laisser en premier        */ -    sql = "CREATE TABLE 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); -    } +/* Collection dédiée aux commentaires textuels (classe) */ +struct _GCommentCollectionClass +{ +    GDbCollectionClass parent;              /* A laisser en premier        */ -    return (ret == SQLITE_OK); +}; -} +/* Initialise la classe des commentaires sous forme de texte. */ +static void g_comment_collection_class_init(GCommentCollectionClass *); + +/* Initialise un commentaire sous forme de zone de texte. */ +static void g_comment_collection_init(GCommentCollection *); + +/* Supprime toutes les références externes. */ +static void g_comment_collection_dispose(GCommentCollection *); +/* Procède à la libération totale de la mémoire. */ +static void g_comment_collection_finalize(GCommentCollection *); +/* Crée la table des commentaires dans une base de données. */ +static bool g_comment_collection_create_db_table(const GCommentCollection *, sqlite3 *); +/* Décrit les colonnes utiles à un chargement de données. */ +static bool g_comment_collection_setup_load(GCommentCollection *, bound_value **, size_t *); +/* Détermine si un élément est déjà présent ou non. */ +static GDbItem *g_comment_collection_has_key(GCommentCollection *, va_list *); +/* ---------------------------------------------------------------------------------- */ +/*                       ELABORATION D'UN ELEMENT DE COLLECTION                       */ +/* ---------------------------------------------------------------------------------- */  /* Indique le type défini pour un commentaire à l'intérieur d'une zone de texte. */ @@ -155,6 +162,9 @@ static void g_db_comment_class_init(GDbCommentClass *klass)      item->recv = (recv_db_item_fc)g_db_comment_recv_from_fd;      item->send = (send_db_item_fc)g_db_comment_send_to_fd; +    item->prepare_stmt = (prepare_db_statement)g_db_comment_prepare_db_statement; +    item->load = (load_db_item_fc)g_db_comment_load; +  } @@ -209,9 +219,7 @@ static void g_db_comment_dispose(GDbComment *comment)  static void g_db_comment_finalize(GDbComment *comment)  { -    delete_vmpa(comment->addr); - -    exit_rle_string(comment->text); +    exit_rle_string(&comment->text);      G_OBJECT_CLASS(g_db_comment_parent_class)->finalize(G_OBJECT(comment)); @@ -238,7 +246,7 @@ GDbComment *g_db_comment_new(const vmpa2t *addr, const char *text, bool is_volat      result = g_object_new(G_TYPE_DB_COMMENT, NULL); -    result->addr = dup_vmpa(addr); +    copy_vmpa(&result->addr, addr);      g_db_comment_set_text(result, text); @@ -266,11 +274,14 @@ 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); +    result = cmp_vmpa_by_phy(&a->addr, &b->addr);      if (result == 0)          result = cmp_rle_string(&a->text, &b->text); +    if (result == 0) +        result = G_DB_ITEM_CLASS(g_db_comment_parent_class)->cmp(G_DB_ITEM(a), G_DB_ITEM(b)); +      return 0;  } @@ -297,10 +308,10 @@ static bool g_db_comment_recv_from_fd(GDbComment *comment, int fd, int flags)      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)) +    if (!recv_vmpa(&comment->addr, fd, flags))          return false; -    if (!recv_rle_string(&comment->text, fd, 0)) +    if (!recv_rle_string(&comment->text, fd, flags))          return false;      return true; @@ -329,7 +340,7 @@ static bool g_db_comment_send_to_fd(const GDbComment *comment, int fd, int flags      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)) +    if (!send_vmpa(&comment->addr, fd, MSG_MORE | flags))          return false;      if (!send_rle_string(&comment->text, fd, flags)) @@ -342,6 +353,67 @@ static bool g_db_comment_send_to_fd(const GDbComment *comment, int fd, int flags  /******************************************************************************  *                                                                             * +*  Paramètres  : comment = base d'éléments sur laquelle s'appuyer.            * +*                values   = couples de champs et de valeurs à lier. [OUT]     * +*                count    = nombre de ces couples. [OUT]                      * +*                                                                             * +*  Description : Constitue les champs destinés à une insertion / modification.* +*                                                                             * +*  Retour      : Etat du besoin en sauvegarde.                                * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_db_comment_prepare_db_statement(const GDbComment *comment, bound_value **values, size_t *count) +{ +    bool status;                            /* Bilan d'opération initiale  */ + +    status = G_DB_ITEM_CLASS(g_db_comment_parent_class)->prepare_stmt(G_DB_ITEM(comment), values, count); +    if (!status) return false; + +    status = prepare_vmpa_db_statement(&comment->addr, values, count); +    if (!status) return false; + +    status &= prepare_db_statement_for_rle_string(&comment->text, "text", values, count); +    if (!status) return false; + +    return true; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : comment = commentaire textuel à charger depuis les réponses. * +*                values  = tableau d'éléments à consulter.                    * +*                count   = nombre de descriptions renseignées.                * +*                                                                             * +*  Description : Charge les valeurs utiles pour un commentaire.               * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_db_comment_load(GDbComment *comment, const bound_value *values, size_t count) +{ +    bool result;                            /* Bilan à faire remonter      */ + +    result = G_DB_ITEM_CLASS(g_db_comment_parent_class)->load(G_DB_ITEM(comment), values, count); + +    result &= load_vmpa(&comment->addr, values, count); + +    result &= load_rle_string(&comment->text, "text", values, count); + +    return result; + +} + + +/****************************************************************************** +*                                                                             *  *  Paramètres  : comment = informations à consulter.                          *  *                                                                             *  *  Description : Fournit l'adresse associée à un commentaire.                 * @@ -354,7 +426,7 @@ static bool g_db_comment_send_to_fd(const GDbComment *comment, int fd, int flags  const vmpa2t *g_db_comment_get_address(GDbComment *comment)  { -    return comment->addr; +    return &comment->addr;  } @@ -396,3 +468,247 @@ void g_db_comment_set_text(GDbComment *comment, const char *text)      set_rle_string(&comment->text, text);  } + + + +/* ---------------------------------------------------------------------------------- */ +/*                        DEFINITION DE LA COLLECTION ASSOCIEE                        */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une collection de commentaires. */ +G_DEFINE_TYPE(GCommentCollection, g_comment_collection, G_TYPE_DB_COLLECTION); + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : klass = classe à initialiser.                                * +*                                                                             * +*  Description : Initialise la classe des commentaires sous forme de texte.   * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_comment_collection_class_init(GCommentCollectionClass *klass) +{ +    GObjectClass *object;                   /* Autre version de la classe  */ +    GDbCollectionClass *collec;             /* Encore une autre vision...  */ + +    object = G_OBJECT_CLASS(klass); + +    object->dispose = (GObjectFinalizeFunc/* ! */)g_comment_collection_dispose; +    object->finalize = (GObjectFinalizeFunc)g_comment_collection_finalize; + +    collec = G_DB_COLLECTION_CLASS(klass); + +    collec->create_table = (collec_create_db_table_fc)g_comment_collection_create_db_table; +    collec->setup_load = (collec_setup_load_fc)g_comment_collection_setup_load; +    collec->has_key = (collec_has_key_fc)g_comment_collection_has_key; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : collec = instance à initialiser.                             * +*                                                                             * +*  Description : Initialise un commentaire sous forme de zone de texte.       * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_comment_collection_init(GCommentCollection *collec) +{ + + +    G_DB_COLLECTION(collec)->featuring = 0; +    G_DB_COLLECTION(collec)->type = G_TYPE_DB_COMMENT; +    G_DB_COLLECTION(collec)->name = "Comments"; + + + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : collec = instance d'objet GLib à traiter.                    * +*                                                                             * +*  Description : Supprime toutes les références externes.                     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_comment_collection_dispose(GCommentCollection *collec) +{ +    G_OBJECT_CLASS(g_comment_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_comment_collection_finalize(GCommentCollection *collec) +{ +    G_OBJECT_CLASS(g_comment_collection_parent_class)->finalize(G_OBJECT(collec)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Crée une collection dédiée aux commentaires.                 * +*                                                                             * +*  Retour      : Collection mise en place.                                    * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GCommentCollection *g_comment_collection_new(void) +{ +    GCommentCollection *result;            /* Instance à retourner        */ + +    result = g_object_new(G_TYPE_COMMENT_COLLECTION, NULL); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : collec = ensemble d'éléments spectateur des opérations.      * +*                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   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_comment_collection_create_db_table(const GCommentCollection *collec, sqlite3 *db) +{ +    char *sql;                              /* Requête à exécuter          */ +    int ret;                                /* Bilan de la création        */ +    char *msg;                              /* Message d'erreur            */ + +    sql = "CREATE TABLE Comments ("         \ +             SQLITE_DB_ITEM_CREATE ", "     \ +             SQLITE_VMPA_CREATE ", "        \ +             SQLITE_RLESTR_CREATE("text")   \ +          ");"; + +    ret = sqlite3_exec(db, sql, NULL, NULL, &msg); +    if (ret != SQLITE_OK) +    { +        fprintf(stderr, "sqlite3_exec(): %s\n", msg); +        sqlite3_free(msg); +    } + +    return (ret == SQLITE_OK); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : collec = ensemble d'éléments à consulter.                    * +*                values = tableau d'éléments à compléter. [OUT]               * +*                count  = nombre de descriptions renseignées. [OUT]           * +*                                                                             * +*  Description : Décrit les colonnes utiles à un chargement de données.       * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_comment_collection_setup_load(GCommentCollection *collec, bound_value **values, size_t *count) +{ +    bool status;                            /* Bilan d'une préparation     */ + +    status = G_DB_COLLECTION_CLASS(g_comment_collection_parent_class)->setup_load(G_DB_COLLECTION(collec), \ +                                                                                  values, count); +    if (!status) return false; + +    if (!setup_load_for_vmpa(NULL, values, count)) +        return false; + +    if (!setup_load_of_rle_string(NULL, "text", values, count)) +        return false; + +    return true; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : collec = ensemble d'éléments à consulter.                    * +*                ap     = clef identifiant de manière unique un élément.      * +*                                                                             * +*  Description : Détermine si un élément est déjà présent ou non.             * +*                                                                             * +*  Retour      : Elément trouvé ou NULL si aucun.                             * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static GDbItem *g_comment_collection_has_key(GCommentCollection *collec, va_list *ap) +{ +    GDbItem *result;                        /* Bilan à retourner           */ +    vmpa2t *ref;                            /* Adresse de référence        */ +    GList *items;                           /* Eléments déjà en place      */ +    GList *iter;                            /* Boucle de parcours          */ +    GDbComment *bm;                        /* Signet à consulter          */ + +    result = NULL; + +    ref = va_arg(ap, vmpa2t *); + +    items = g_db_collection_list_items(G_DB_COLLECTION(collec)); + +    for (iter = g_list_first(items); iter != NULL && result == NULL; iter = g_list_next(iter)) +    { +        bm = G_DB_COMMENT(iter->data); + +        if (cmp_vmpa(&bm->addr, ref) != 0) + +            /** +             * Un verrou est sensé être posé, donc il n'y a pas besoin +             * de toucher au décompte des références car l'élément trouvé +             * ne peut pas être supprimé. +             */ +            result = G_DB_ITEM(bm); + +    } + +    return result; + +} diff --git a/src/analysis/db/items/comment.h b/src/analysis/db/items/comment.h index 792fb92..316f4c5 100644 --- a/src/analysis/db/items/comment.h +++ b/src/analysis/db/items/comment.h @@ -35,11 +35,7 @@ -/* Crée la table des commentaires dans une base de données. */ -bool create_comment_db_table(sqlite3 *); - - - +/* --------------------- ELABORATION D'UN ELEMENT DE COLLECTION --------------------- */  #define G_TYPE_DB_COMMENT               g_db_comment_get_type() @@ -74,4 +70,36 @@ void g_db_comment_set_text(GDbComment *, const char *); + + + + + + +/* ---------------------- DEFINITION DE LA COLLECTION ASSOCIEE ---------------------- */ + + +#define G_TYPE_COMMENT_COLLECTION               g_comment_collection_get_type() +#define G_COMMENT_COLLECTION(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), g_comment_collection_get_type(), GCommentCollection)) +#define G_IS_COMMENT_COLLECTION(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_comment_collection_get_type())) +#define G_COMMENT_COLLECTION_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_COMMENT_COLLECTION, GCommentCollectionClass)) +#define G_IS_COMMENT_COLLECTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_COMMENT_COLLECTION)) +#define G_COMMENT_COLLECTION_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_COMMENT_COLLECTION, GCommentCollectionClass)) + + +/* Collection dédiée aux commentaires textuels (instance) */ +typedef struct _GCommentCollection GCommentCollection; + +/* Collection dédiée aux commentaires textuels (classe) */ +typedef struct _GCommentCollectionClass GCommentCollectionClass; + + +/* Indique le type défini pour une collection de commentaires. */ +GType g_comment_collection_get_type(void); + +/* Crée une collection dédiée aux commentaires. */ +GCommentCollection *g_comment_collection_new(void); + + +  #endif  /* _ANALYSIS_DB_ITEMS_COMMENT_H */ diff --git a/src/analysis/db/items/switcher.c b/src/analysis/db/items/switcher.c new file mode 100644 index 0000000..5063a9c --- /dev/null +++ b/src/analysis/db/items/switcher.c @@ -0,0 +1,755 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * switcher.h - gestion des basculements d'affichage d'opérandes numériques + * + * Copyright (C) 2015 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  OpenIDA is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  OpenIDA is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "switcher.h" + + +#include <stdio.h> +#include <sys/socket.h> + + +#include "../collection-int.h" +#include "../item-int.h" +#include "../../../common/io.h" + + + + + +/* --------------------- ELABORATION D'UN ELEMENT DE COLLECTION --------------------- */ + + +/* Bascule d'affichage pour un opérande numérique (instance) */ +struct _GDbSwitcher +{ +    GDbItem parent;                         /* A laisser en premier        */ + +    vmpa2t addr;                            /* Adresse de l'instruction    */ +    size_t index;                           /* Indice de l'opérande visé   */ + +    ImmSwitchType type;                     /* Type de bascule             */ + +}; + +/* Bascule d'affichage pour un opérande numérique (classe) */ +struct _GDbSwitcherClass +{ +    GDbItemClass parent;                    /* A laisser en premier        */ + +}; + + + +/* Initialise la classe des bascules d'affichage numérique. */ +static void g_db_switcher_class_init(GDbSwitcherClass *); + +/* Initialise une bascule d'affichage pour opérande numérique. */ +static void g_db_switcher_init(GDbSwitcher *); + +/* Supprime toutes les références externes. */ +static void g_db_switcher_dispose(GDbSwitcher *); + +/* Procède à la libération totale de la mémoire. */ +static void g_db_switcher_finalize(GDbSwitcher *); + +/* Effectue la comparaison entre deux signets de collection. */ +static gint g_db_switcher_cmp(GDbSwitcher *, GDbSwitcher *); + +/* Importe la définition d'un signet dans un flux réseau. */ +static bool g_db_switcher_recv_from_fd(GDbSwitcher *, int, int); + +/* Exporte la définition d'un signet dans un flux réseau. */ +static bool g_db_switcher_send_to_fd(const GDbSwitcher *, int, int); + +/* Constitue les champs destinés à une insertion / modification. */ +static bool g_db_switcher_prepare_db_statement(const GDbSwitcher *, bound_value **, size_t *); + +/* Charge les valeurs utiles pour un basculement d'affichage. */ +static bool g_db_switcher_load(GDbSwitcher *, const bound_value *, size_t); + + + + +/* ---------------------- DEFINITION DE LA COLLECTION ASSOCIEE ---------------------- */ + + +/* Collection dédiée aux basculements d'affichage (instance) */ +struct _GSwitcherCollection +{ +    GDbCollection parent;                   /* A laisser en premier        */ + +}; + +/* Collection dédiée aux basculements d'affichage (classe) */ +struct _GSwitcherCollectionClass +{ +    GDbCollectionClass parent;              /* A laisser en premier        */ + +}; + + +/* Initialise la classe des signets dans une zone de texte. */ +static void g_switcher_collection_class_init(GSwitcherCollectionClass *); + +/* Initialise un signet dans une zone de texte. */ +static void g_switcher_collection_init(GSwitcherCollection *); + +/* Supprime toutes les références externes. */ +static void g_switcher_collection_dispose(GSwitcherCollection *); + +/* Procède à la libération totale de la mémoire. */ +static void g_switcher_collection_finalize(GSwitcherCollection *); + +/* Crée la table des basculements dans une base de données. */ +static bool g_switcher_collection_create_db_table(const GSwitcherCollection *, sqlite3 *); + +/* Décrit les colonnes utiles à un chargement de données. */ +static bool g_switcher_collection_setup_load(GSwitcherCollection *, bound_value **, size_t *); + +/* Détermine si un élément est déjà présent ou non. */ +static GDbItem *g_switcher_collection_has_key(GSwitcherCollection *, va_list *); + + + +/* ---------------------------------------------------------------------------------- */ +/*                       ELABORATION D'UN ELEMENT DE COLLECTION                       */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour un signet à l'intérieur d'une zone de texte. */ +G_DEFINE_TYPE(GDbSwitcher, g_db_switcher, G_TYPE_DB_ITEM); + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : klass = classe à initialiser.                                * +*                                                                             * +*  Description : Initialise la classe des bascules d'affichage numérique.     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_db_switcher_class_init(GDbSwitcherClass *klass) +{ +    GObjectClass *object;                   /* Autre version de la classe  */ +    GDbItemClass *item;                     /* Encore une autre vision...  */ + +    object = G_OBJECT_CLASS(klass); + +    object->dispose = (GObjectFinalizeFunc/* ! */)g_db_switcher_dispose; +    object->finalize = (GObjectFinalizeFunc)g_db_switcher_finalize; + +    item = G_DB_ITEM_CLASS(klass); + +    item->cmp = (GCompareFunc)g_db_switcher_cmp; + +    item->recv = (recv_db_item_fc)g_db_switcher_recv_from_fd; +    item->send = (send_db_item_fc)g_db_switcher_send_to_fd; + +    item->prepare_stmt = (prepare_db_statement)g_db_switcher_prepare_db_statement; +    item->load = (load_db_item_fc)g_db_switcher_load; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : switcher = instance à initialiser.                         * +*                                                                             * +*  Description : Initialise une bascule d'affichage pour opérande numérique.  * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_db_switcher_init(GDbSwitcher *switcher) +{ + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : switcher = instance d'objet GLib à traiter.                * +*                                                                             * +*  Description : Supprime toutes les références externes.                     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_db_switcher_dispose(GDbSwitcher *switcher) +{ +    G_OBJECT_CLASS(g_db_switcher_parent_class)->dispose(G_OBJECT(switcher)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : switcher = instance d'objet GLib à traiter.                * +*                                                                             * +*  Description : Procède à la libération totale de la mémoire.                * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_db_switcher_finalize(GDbSwitcher *switcher) +{ +    G_OBJECT_CLASS(g_db_switcher_parent_class)->finalize(G_OBJECT(switcher)); + +} + + +/****************************************************************************** +*                                                                             * +*  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   : -                                                            * +*                                                                             * +******************************************************************************/ + +GDbSwitcher *g_db_switcher_new(const GArchInstruction *instr, const GImmOperand *imm, ImmSwitchType type) +{ +    GDbSwitcher *result;                      /* Instance à retourner        */ +    size_t count;                           /* Nombre d'opérandes à visiter*/ +    size_t i;                               /* Boucle de parcours          */ +    const mrange_t *range;                  /* Localisation de l'instruct° */ + +    /* Recherche de la position de l'opérande */ + +    count = g_arch_instruction_count_operands(instr); + +    for (i = 0; i < count; i++) +        if (G_ARCH_OPERAND(imm) == g_arch_instruction_get_operand(instr, i)) +            break; + +    if (i == count) +        return NULL; + +    /* Sauvegarde des propriétés */ + +    result = g_object_new(G_TYPE_DB_SWITCHER, NULL); + +    range = g_arch_instruction_get_range(instr); +    copy_vmpa(&result->addr, get_mrange_addr(range)); + +    result->index = i; + +    result->type = type; + +    /* Création d'un intitulé adapté */ + + + +    //g_db_switcher_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_switcher_cmp(GDbSwitcher *a, GDbSwitcher *b) +{ +    gint result;                            /* Bilan de la comparaison     */ + +    result = cmp_vmpa(&a->addr, &b->addr); + +    if (result == 0) +    { +        if (a->index < b->index) +            result = -1; + +        else if (a->index > b->index) +            result = 1; + +    } + +    if (result == 0) +    { +        if (a->type < b->type) +            result = -1; + +        else if (a->type > b->type) +            result = 1; + +    } + +    if (result == 0) +        result = G_DB_ITEM_CLASS(g_db_switcher_parent_class)->cmp(G_DB_ITEM(a), G_DB_ITEM(b)); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : switcher = bascule d'affichage aux infos à charger. [OUT]    * +*                fd       = flux ouvert en lecture pour l'importation.        * +*                flags    = éventuelles options d'envoi supplémentaires.      * +*                                                                             * +*  Description : Importe la définition d'une bascule d'affichage d'opérande.  * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_db_switcher_recv_from_fd(GDbSwitcher *switcher, int fd, int flags) +{ +    bool status;                            /* Bilan d'opération initiale  */ +    uint32_t val32;                         /* Valeur sur 32 bits          */ +    ssize_t got;                            /* Quantité de données reçues  */ + +    status = G_DB_ITEM_CLASS(g_db_switcher_parent_class)->recv(G_DB_ITEM(switcher), fd, flags); +    if (!status) return false; + +    if (!recv_vmpa(&switcher->addr, fd, flags)) +        return false; + +    got = safe_recv(fd, &val32, sizeof(uint32_t), MSG_WAITALL); +    if (got != sizeof(uint32_t)) return false; + +    switcher->index = be32toh(val32); + +    got = safe_recv(fd, &val32, sizeof(uint32_t), MSG_WAITALL); +    if (got != sizeof(uint32_t)) return false; + +    switcher->type = be32toh(val32); + +    if (switcher->type >= IST_COUNT) +        return false; + +    return true; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : switcher = bascule d'affichage aux infos à sauvegarder.      * +*                fd       = flux ouvert en écriture pour l'exportation.       * +*                flags    = éventuelles options d'envoi supplémentaires.      * +*                                                                             * +*  Description : Exporte la définition d'une bascule d'affichage d'opérande.  * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_db_switcher_send_to_fd(const GDbSwitcher *switcher, int fd, int flags) +{ +    bool status;                            /* Bilan d'opération initiale  */ + +    status = G_DB_ITEM_CLASS(g_db_switcher_parent_class)->send(G_DB_ITEM(switcher), fd, MSG_MORE | flags); +    if (!status) return false; + +    if (!send_vmpa(&switcher->addr, fd, MSG_MORE | flags)) +        return false; + +    status = safe_send(fd, (uint32_t []) { htobe32(switcher->index) }, sizeof(uint32_t), MSG_MORE | flags); +    if (!status) return false; + +    status = safe_send(fd, (uint32_t []) { htobe32(switcher->type) }, sizeof(uint32_t), flags); +    if (!status) return false; + +    return true; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : switcher = base d'éléments sur laquelle s'appuyer.           * +*                values   = couples de champs et de valeurs à lier. [OUT]     * +*                count    = nombre de ces couples. [OUT]                      * +*                                                                             * +*  Description : Constitue les champs destinés à une insertion / modification.* +*                                                                             * +*  Retour      : Etat du besoin en sauvegarde.                                * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_db_switcher_prepare_db_statement(const GDbSwitcher *switcher, bound_value **values, size_t *count) +{ +    bool status;                            /* Bilan d'opération initiale  */ +    bound_value *value;                     /* Valeur à éditer / définir   */ + +    status = G_DB_ITEM_CLASS(g_db_switcher_parent_class)->prepare_stmt(G_DB_ITEM(switcher), values, count); +    if (!status) return false; + +    status = prepare_vmpa_db_statement(&switcher->addr, values, count); +    if (!status) return false; + +    *count += 2; +    *values = (bound_value *)realloc(*values, *count * sizeof(bound_value)); + +    value = &(*values)[*count - 2]; + +    value->name = "op_index"; +    value->type = SQLITE_INTEGER; +    value->integer = switcher->index; +    value->delete = NULL; + +    value = &(*values)[*count - 2]; + +    value->name = "type"; +    value->type = SQLITE_INTEGER; +    value->integer = switcher->type; +    value->delete = NULL; + +    return true; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : switcher = bascule d'affichage à charger depuis les réponses.* +*                values   = tableau d'éléments à consulter.                   * +*                count    = nombre de descriptions renseignées.               * +*                                                                             * +*  Description : Charge les valeurs utiles pour un basculement d'affichage.   * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_db_switcher_load(GDbSwitcher *switcher, const bound_value *values, size_t count) +{ +    bool result;                            /* Bilan à faire remonter      */ +    const bound_value *value;               /* Valeur à éditer / définir   */ + +    result = G_DB_ITEM_CLASS(g_db_switcher_parent_class)->load(G_DB_ITEM(switcher), values, count); + +    result &= load_vmpa(&switcher->addr, values, count); + +    if (result) +    { +        value = find_bound_value(values, count, "op_index"); +        result = (value != NULL && value->type == SQLITE_INTEGER); + +        if (result) +            switcher->index = value->integer; + +    } + +    if (result) +    { +        value = find_bound_value(values, count, "type"); +        result = (value != NULL && value->type == SQLITE_INTEGER); + +        if (result) +            switcher->type = value->integer; + +    } + +    return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/*                        DEFINITION DE LA COLLECTION ASSOCIEE                        */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une collection de basculements d'affichage. */ +G_DEFINE_TYPE(GSwitcherCollection, g_switcher_collection, G_TYPE_DB_COLLECTION); + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : klass = classe à initialiser.                                * +*                                                                             * +*  Description : Initialise la classe des signets dans une zone de texte.     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_switcher_collection_class_init(GSwitcherCollectionClass *klass) +{ +    GObjectClass *object;                   /* Autre version de la classe  */ +    GDbCollectionClass *collec;             /* Encore une autre vision...  */ + +    object = G_OBJECT_CLASS(klass); + +    object->dispose = (GObjectFinalizeFunc/* ! */)g_switcher_collection_dispose; +    object->finalize = (GObjectFinalizeFunc)g_switcher_collection_finalize; + +    collec = G_DB_COLLECTION_CLASS(klass); + +    collec->create_table = (collec_create_db_table_fc)g_switcher_collection_create_db_table; +    collec->setup_load = (collec_setup_load_fc)g_switcher_collection_setup_load; +    collec->has_key = (collec_has_key_fc)g_switcher_collection_has_key; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : collec = instance à initialiser.                             * +*                                                                             * +*  Description : Initialise un signet dans une zone de texte.                 * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_switcher_collection_init(GSwitcherCollection *collec) +{ + + +    G_DB_COLLECTION(collec)->featuring = 0; +    G_DB_COLLECTION(collec)->type = G_TYPE_DB_SWITCHER; +    G_DB_COLLECTION(collec)->name = "Switchers"; + + + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : collec = instance d'objet GLib à traiter.                    * +*                                                                             * +*  Description : Supprime toutes les références externes.                     * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_switcher_collection_dispose(GSwitcherCollection *collec) +{ +    G_OBJECT_CLASS(g_switcher_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_switcher_collection_finalize(GSwitcherCollection *collec) +{ +    G_OBJECT_CLASS(g_switcher_collection_parent_class)->finalize(G_OBJECT(collec)); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Crée une collection dédiée aux basculements d'affichage.     * +*                                                                             * +*  Retour      : Collection mise en place.                                    * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GSwitcherCollection *g_switcher_collection_new(void) +{ +    GSwitcherCollection *result;            /* Instance à retourner        */ + +    result = g_object_new(G_TYPE_SWITCHER_COLLECTION, NULL); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : collec = ensemble d'éléments spectateur des opérations.      * +*                db     = accès à la base de données.                         * +*                                                                             * +*  Description : Crée la table des basculements dans une base de données.     * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_switcher_collection_create_db_table(const GSwitcherCollection *collec, sqlite3 *db) +{ +    char *sql;                              /* Requête à exécuter          */ +    int ret;                                /* Bilan de la création        */ +    char *msg;                              /* Message d'erreur            */ + +    sql = "CREATE TABLE Switchers ("            \ +             SQLITE_DB_ITEM_CREATE ", "         \ +             SQLITE_VMPA_CREATE ", "            \ +             "op_index INTEGER, "               \ +             "type INTEGER"                     \ +          ");"; + +    ret = sqlite3_exec(db, sql, NULL, NULL, &msg); +    if (ret != SQLITE_OK) +    { +        fprintf(stderr, "sqlite3_exec(): %s\n", msg); +        sqlite3_free(msg); +    } + +    return (ret == SQLITE_OK); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : collec = ensemble d'éléments à consulter.                    * +*                values = tableau d'éléments à compléter. [OUT]               * +*                count  = nombre de descriptions renseignées. [OUT]           * +*                                                                             * +*  Description : Décrit les colonnes utiles à un chargement de données.       * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_switcher_collection_setup_load(GSwitcherCollection *collec, bound_value **values, size_t *count) +{ +    bool status;                            /* Bilan d'une préparation     */ + +    status = G_DB_COLLECTION_CLASS(g_switcher_collection_parent_class)->setup_load(G_DB_COLLECTION(collec), \ +                                                                                   values, count); +    if (!status) return false; + +    if (!setup_load_for_vmpa(NULL, values, count)) +        return false; + +    *count += 2; +    *values = (bound_value *)realloc(*values, *count * sizeof(bound_value)); + +    (*values)[*count - 2].name = "op_index"; + +    (*values)[*count - 1].name = "type"; + +    return true; + + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : collec = ensemble d'éléments à consulter.                    * +*                ap     = clef identifiant de manière unique un élément.      * +*                                                                             * +*  Description : Détermine si un élément est déjà présent ou non.             * +*                                                                             * +*  Retour      : Elément trouvé ou NULL si aucun.                             * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static GDbItem *g_switcher_collection_has_key(GSwitcherCollection *collec, va_list *ap) +{ +    GDbItem *result;                        /* Bilan à retourner           */ +    vmpa2t *ref;                            /* Adresse de référence        */ +    GList *items;                           /* Eléments déjà en place      */ +    GList *iter;                            /* Boucle de parcours          */ +    GDbSwitcher *bm;                        /* Signet à consulter          */ + +    result = NULL; + +    ref = va_arg(ap, vmpa2t *); + +    items = g_db_collection_list_items(G_DB_COLLECTION(collec)); + +    for (iter = g_list_first(items); iter != NULL && result == NULL; iter = g_list_next(iter)) +    { +        bm = G_DB_SWITCHER(iter->data); + +        if (cmp_vmpa(&bm->addr, ref) != 0) + +            /** +             * Un verrou est sensé être posé, donc il n'y a pas besoin +             * de toucher au décompte des références car l'élément trouvé +             * ne peut pas être supprimé. +             */ +            result = G_DB_ITEM(bm); + +    } + +    return result; + +} diff --git a/src/analysis/db/items/switcher.h b/src/analysis/db/items/switcher.h new file mode 100644 index 0000000..a839b3a --- /dev/null +++ b/src/analysis/db/items/switcher.h @@ -0,0 +1,121 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * switcher.h - prototypes pour la gestion des basculements d'affichage d'opérandes numériques + * + * Copyright (C) 2015 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  OpenIDA is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  OpenIDA is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ANALYSIS_DB_ITEMS_SWITCHER_H +#define _ANALYSIS_DB_ITEMS_SWITCHER_H + + +#include <glib-object.h> +#include <sqlite3.h> +#include <stdbool.h> + + +#include "../../../arch/immediate.h" +#include "../../../arch/instruction.h" + + + +/* Crée la table des signets dans une base de données. */ +bool create_switcher_db_table(sqlite3 *); + + + + + +/* --------------------- ELABORATION D'UN ELEMENT DE COLLECTION --------------------- */ + + +/* Basculement d'affichage de valeurs immédiates */ +typedef enum _ImmSwitchType +{ +    IST_DEFAULT,                            /* Impression par défaut       */ +    IST_HEXDECIMAL,                         /* Impression en hexadécimal   */ +    IST_DECIMAL,                            /* Impression en décimal       */ +    IST_OCTAL,                              /* Impression en octal         */ +    IST_BINARY,                             /* Impression en binaire       */ + +    IST_COUNT + +} ImmSwitchType; + + +#define G_TYPE_DB_SWITCHER               g_db_switcher_get_type() +#define G_DB_SWITCHER(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), g_db_switcher_get_type(), GDbSwitcher)) +#define G_IS_DB_SWITCHER(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_db_switcher_get_type())) +#define G_DB_SWITCHER_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DB_SWITCHER, GDbSwitcherClass)) +#define G_IS_DB_SWITCHER_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DB_SWITCHER)) +#define G_DB_SWITCHER_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DB_SWITCHER, GDbSwitcherClass)) + + +/* Bascule d'affichage pour un opérande numérique (instance) */ +typedef struct _GDbSwitcher GDbSwitcher; + +/* Bascule d'affichage pour un opérande numérique (classe) */ +typedef struct _GDbSwitcherClass GDbSwitcherClass; + + +/* Indique le type défini pour un signet à l'intérieur d'une zone de texte. */ +GType g_db_switcher_get_type(void); + +/* Crée une définition d'un signet dans une zone de texte. */ +GDbSwitcher *g_db_switcher_new(const GArchInstruction *, const GImmOperand *, ImmSwitchType); + +#if 0 +/* Fournit l'adresse associée à un signet. */ +const vmpa2t *g_db_switcher_get_address(GDbSwitcher *); + +/* Fournit le commentaire associé à un signet. */ +const char *g_db_switcher_get_comment(const GDbSwitcher *); + +/* Définit le commentaire associé à un signet. */ +void g_db_switcher_set_comment(GDbSwitcher *, const char *); +#endif + + +/* ---------------------- DEFINITION DE LA COLLECTION ASSOCIEE ---------------------- */ + + +#define G_TYPE_SWITCHER_COLLECTION               g_switcher_collection_get_type() +#define G_SWITCHER_COLLECTION(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), g_switcher_collection_get_type(), GSwitcherCollection)) +#define G_IS_SWITCHER_COLLECTION(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_switcher_collection_get_type())) +#define G_SWITCHER_COLLECTION_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SWITCHER_COLLECTION, GSwitcherCollectionClass)) +#define G_IS_SWITCHER_COLLECTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SWITCHER_COLLECTION)) +#define G_SWITCHER_COLLECTION_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SWITCHER_COLLECTION, GSwitcherCollectionClass)) + + +/* Collection dédiée aux basculements d'affichage (instance) */ +typedef struct _GSwitcherCollection GSwitcherCollection; + +/* Collection dédiée aux basculements d'affichage (classe) */ +typedef struct _GSwitcherCollectionClass GSwitcherCollectionClass; + + +/* Indique le type défini pour une collection de basculements d'affichage. */ +GType g_switcher_collection_get_type(void); + +/* Crée une collection dédiée aux basculements d'affichage. */ +GSwitcherCollection *g_switcher_collection_new(void); + + + +#endif  /* _ANALYSIS_DB_ITEMS_SWITCH_H */ diff --git a/src/analysis/db/misc/rlestr.c b/src/analysis/db/misc/rlestr.c index 631b1e9..9986967 100644 --- a/src/analysis/db/misc/rlestr.c +++ b/src/analysis/db/misc/rlestr.c @@ -26,6 +26,7 @@  #include <endian.h>  #include <malloc.h> +#include <sqlite3.h>  #include <string.h> @@ -33,25 +34,6 @@ - -#include <limits.h> -#include <stdio.h> -#include <stdlib.h> - -#include <time.h> -#include <unistd.h> - - - - - - - - - - - -  /******************************************************************************  *                                                                             *  *  Paramètres  : str  = représentation de chaîne à traiter.                   * @@ -180,8 +162,9 @@ int cmp_rle_string(const rle_string *s1, const rle_string *s2)  /******************************************************************************  *                                                                             * -*  Paramètres  : str = informations à constituer. [OUT]                       * -*                fd  = flux ouvert en lecture pour l'importation.             * +*  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.            *  *                                                                             * @@ -191,23 +174,25 @@ int cmp_rle_string(const rle_string *s1, const rle_string *s2)  *                                                                             *  ******************************************************************************/ -bool load_rle_string(rle_string *str, int fd) +bool recv_rle_string(rle_string *str, int fd, int flags)  { -#if 0      uint32_t val32;                         /* Valeur sur 32 bits          */ -    ssize_t got;                            /* Quantité de données reçues  */ +    bool status;                            /* Bilan d'une opération       */ -    got = safe_recv(fd, &val32, sizeof(uint32_t), MSG_WAITALL); -    if (got != sizeof(uint32_t)) return false; +    str->data = NULL; +    str->length = 0; + +    status = safe_recv(fd, &val32, sizeof(uint32_t), MSG_WAITALL | flags); +    if (!status) return false; -    str->length = le32toh(val32); +    str->length = be32toh(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)) +        status = safe_recv(fd, str->data, str->length + 1, MSG_WAITALL | flags); +        if (!status)          {              unset_rle_string(str);              return false; @@ -216,7 +201,7 @@ bool load_rle_string(rle_string *str, int fd)          str->data[str->length] = '\0';      } -#endif +      return true;  } @@ -224,8 +209,9 @@ bool load_rle_string(rle_string *str, int fd)  /******************************************************************************  *                                                                             * -*  Paramètres  : str = informations à sauvegarer.                             * -*                fd  = flux ouvert en écriture pour l'exportation.            * +*  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.            *  *                                                                             * @@ -235,44 +221,70 @@ bool load_rle_string(rle_string *str, int fd)  *                                                                             *  ******************************************************************************/ -bool store_rle_string(const rle_string *str, int fd) +bool send_rle_string(const rle_string *str, int fd, int flags)  { -#if 0 -    ssize_t got;                            /* Quantité de données reçues  */ +    bool status;                            /* Bilan d'une opération       */ -    got = safe_send(fd, (uint32_t []) { htole32(str->length) }, sizeof(uint32_t), MSG_WAITALL); -    if (got != sizeof(uint32_t)) return false; +    status = safe_send(fd, (uint32_t []) { htobe32(str->length) }, sizeof(uint32_t), MSG_MORE | flags); +    if (!status) return false;      if (str->length > 0)      { -        got = safe_send(fd, str->data, str->length + 1, MSG_WAITALL); -        if (got != (str->length + 1)) return false; +        status = safe_send(fd, str->data, str->length + 1, flags); +        if (!status) return false;      } -#endif +      return true;  } +/* ---------------------------------------------------------------------------------- */ +/*                       MANIPULATIONS AVEC UNE BASE DE DONNEES                       */ +/* ---------------------------------------------------------------------------------- */ +/****************************************************************************** +*                                                                             * +*  Paramètres  : str    = chaîne de caractères aux informations inutiles.     * +*                name   = désignation personnalisée du champ dans la BD.      * +*                values = couples de champs et de valeurs à lier. [OUT]       * +*                count  = nombre de ces couples. [OUT]                        * +*                                                                             * +*  Description : Constitue les champs destinés à une insertion / modification.* +*                                                                             * +*  Retour      : Bilan de l'opération : succès ou non.                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ +bool prepare_db_statement_for_rle_string(const rle_string *str, const char *name, bound_value **values, size_t *count) +{ +    bound_value *value;                     /* Valeur à éditer / définir   */ +    *values = (bound_value *)realloc(*values, ++(*count) * sizeof(bound_value)); +    value = &(*values)[*count - 1]; +    value->name = name; +    value->type = SQLITE_TEXT; +    value->cstring = get_rle_string(str); +    value->delete = SQLITE_STATIC; +    return true; - - +}  /******************************************************************************  *                                                                             * -*  Paramètres  : str   = informations à constituer. [OUT]                     * -*                fd    = flux ouvert en lecture pour l'importation.           * -*                flags = éventuelles options de réception supplémentaires.    * +*  Paramètres  : str    = chaîne de caractères aux informations inutiles.     * +*                name   = désignation personnalisée du champ dans la BD.      * +*                values = tableau d'éléments à compléter. [OUT]               * +*                count  = nombre de descriptions renseignées. [OUT]           *  *                                                                             * -*  Description : Importe la définition d'une chaîne de caractères.            * +*  Description : Décrit les colonnes utiles à une chaîne de caractères.       *  *                                                                             *  *  Retour      : Bilan de l'opération.                                        *  *                                                                             * @@ -280,46 +292,26 @@ bool store_rle_string(const rle_string *str, int fd)  *                                                                             *  ******************************************************************************/ -bool recv_rle_string(rle_string *str, int fd, int flags) +bool setup_load_of_rle_string(const rle_string *str, const char *name, bound_value **values, size_t *count)  { -    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'; +    *values = (bound_value *)realloc(*values, ++(*count) * sizeof(bound_value)); -    } +    (*values)[*count - 1].name = name;      return true; +  }  /******************************************************************************  *                                                                             * -*  Paramètres  : str   = informations à sauvegarer.                           * -*                fd    = flux ouvert en écriture pour l'exportation.          * -*                flags = éventuelles options d'envoi supplémentaires.         * +*  Paramètres  : str    = chaîne de caractères à compléter.                   * +*                name   = désignation personnalisée du champ dans la BD.      * +*                values = tableau d'éléments à consulter.                     * +*                count  = nombre de descriptions renseignées.                 *  *                                                                             * -*  Description : Exporte la définition d'une chaîne de caractères.            * +*  Description : Charge les valeurs utiles pour une chaîne de caractères.     *  *                                                                             *  *  Retour      : Bilan de l'opération.                                        *  *                                                                             * @@ -327,17 +319,27 @@ bool recv_rle_string(rle_string *str, int fd, int flags)  *                                                                             *  ******************************************************************************/ -bool send_rle_string(const rle_string *str, int fd, int flags) +bool load_rle_string(rle_string *str, const char *name, const bound_value *values, size_t count)  { -    bool status;                            /* Bilan d'une opération       */ +    const bound_value *value;               /* Valeur à intégrer           */ -    status = safe_send(fd, (uint32_t []) { htobe32(str->length) }, sizeof(uint32_t), MSG_MORE | flags); -    if (!status) return false; +    value = find_bound_value(values, count, name); +    if (value == NULL) return false; -    if (str->length > 0) +    switch (value->type)      { -        status = safe_send(fd, str->data, str->length + 1, flags); -        if (!status) return false; +        case SQLITE_TEXT: +            set_rle_string(str, value->cstring); +            break; + +        case SQLITE_NULL: +            set_rle_string(str, NULL); +            break; + +        default: +            return false; +            break; +      }      return true; diff --git a/src/analysis/db/misc/rlestr.h b/src/analysis/db/misc/rlestr.h index 2aa863f..7faafd0 100644 --- a/src/analysis/db/misc/rlestr.h +++ b/src/analysis/db/misc/rlestr.h @@ -30,6 +30,9 @@  #include <sys/types.h> +#include "../../../common/sqlite.h" + +  /* Informations de base pour tout élément ajouté */  typedef struct _rle_string @@ -49,6 +52,8 @@ void init_rle_string(rle_string *, const char *);  #define get_rle_string(rle) (rle)->data +#define is_rle_string_empty(rle) ((rle)->data == NULL) +  /* Constitue une représentation de chaîne de caractères. */  void set_rle_string(rle_string *, const char *); @@ -58,25 +63,29 @@ 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); +bool recv_rle_string(rle_string *, int, int);  /* Exporte la définition d'une chaîne de caractères. */ -bool store_rle_string(const rle_string *, int); +bool send_rle_string(const rle_string *, int, int); -#define is_rle_string_empty(rle) ((rle)->data == NULL) +/* --------------------- MANIPULATIONS AVEC UNE BASE DE DONNEES --------------------- */ +/* Définition du tronc commun pour les créations SQLite */ +#define SQLITE_RLESTR_CREATE(n)     \ +    n " TEXT" -/* Importe la définition d'une chaîne de caractères. */ -bool recv_rle_string(rle_string *, int, int); +/* Constitue les champs destinés à une insertion / modification. */ +bool prepare_db_statement_for_rle_string(const rle_string *, const char *, bound_value **, size_t *); -/* Exporte la définition d'une chaîne de caractères. */ -bool send_rle_string(const rle_string *, int, int); +/* Décrit les colonnes utiles à une chaîne de caractères. */ +bool setup_load_of_rle_string(const rle_string *, const char *, bound_value **, size_t *); + +/* Charge les valeurs utiles pour une chaîne de caractères. */ +bool load_rle_string(rle_string *, const char *, const bound_value *, size_t); diff --git a/src/analysis/db/protocol.h b/src/analysis/db/protocol.h index 85d44cb..04bbd33 100644 --- a/src/analysis/db/protocol.h +++ b/src/analysis/db/protocol.h @@ -29,7 +29,7 @@  /**   * Version de la définition courante du protocole.   */ -#define CDB_PROTOCOL_VERSION 0xc0de0001 +#define CDB_PROTOCOL_VERSION 0xc0de0002 @@ -84,7 +84,7 @@ typedef enum _DBFeatures  {      DBF_BOOKMARKS,                          /* Signets dans le code        */      DBF_COMMENTS,                           /* Commentaires ajoutés        */ -    DBF_SEGMENTS_DISPLAY,                   /* Choix d'affichage           */ +    DBF_DISPLAY_SWITCHERS,                  /* Choix d'affichage           */      DBF_COUNT @@ -132,9 +132,13 @@ typedef enum _DBCommand  typedef enum _DBError  {      DBE_NONE,                               /* Succès d'une opération      */ +    DBE_BAD_EXCHANGE,                       /* Incohérence des échanges    */ +      DBE_WRONG_VERSION,                      /* Proto Client != Serveur     */      DBE_SYS_ERROR,                          /* Erreur suite à un appel sys.*/      DBE_ARCHIVE_ERROR,                      /* Soucis du côté libarchive   */ +    DBE_XML_VERSION_ERROR,                  /* Vieille archive présente    */ +    DBE_DB_LOADING_ERROR,                   /* Erreur pendant le chargement*/      DBE_COUNT diff --git a/src/analysis/db/server.c b/src/analysis/db/server.c index c51c21e..3ef1ce0 100644 --- a/src/analysis/db/server.c +++ b/src/analysis/db/server.c @@ -24,6 +24,7 @@  #include "server.h" +#include <assert.h>  #include <malloc.h>  #include <netdb.h>  #include <poll.h> @@ -247,26 +248,14 @@ static void *g_db_server_listener(GDbServer *server)      int fd;                                 /* Canal établi vers un client */      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         */ - - +    uint32_t cmd;                           /* Commande initiale lue       */ +    uint32_t version;                       /* Version du client lue       */      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; @@ -307,39 +296,68 @@ static void *g_db_server_listener(GDbServer *server)               * Tout ceci est à synchroniser avec la fonction g_db_client_start().               */ -            if (!safe_recv(fd, &data, sizeof(uint32_t), 0)) -                goto gdsl_error; +            if (!safe_recv(fd, &cmd, sizeof(uint32_t), 0)) +            { +                log_variadic_message(LMT_ERROR, _("Error while getting the initial command from '%s:%hu'..."), +                                     source, ntohs(peer.sin_port)); +                error = DBE_BAD_EXCHANGE; +                goto gdsl_error_sending; +            } -            if (be32toh(data) != DBC_HELO) +            if (!safe_recv(fd, &version, sizeof(uint32_t), 0))              { -                log_variadic_message(LMT_ERROR, _("The client from '%s:%hu' did not introduce itself!"), +                log_variadic_message(LMT_ERROR, _("Error while getting the protocol version from '%s:%hu'..."),                                       source, ntohs(peer.sin_port)); -                goto gdsl_error; +                error = DBE_BAD_EXCHANGE; +                goto gdsl_error_sending;              } -            if (!safe_recv(fd, &data, sizeof(uint32_t), 0)) -                goto gdsl_error; +            if (!recv_rle_string(&hash, fd, 0)) +            { +                log_variadic_message(LMT_ERROR, _("Error while getting the binary hash from '%s:%hu'..."), +                                     source, ntohs(peer.sin_port)); +                error = DBE_BAD_EXCHANGE; +                goto gdsl_error_sending; +            } + +            if (!recv_rle_string(&user, fd, 0)) +            { +                log_variadic_message(LMT_ERROR, _("Error while getting the user name from '%s:%hu'..."), +                                     source, ntohs(peer.sin_port)); +                error = DBE_BAD_EXCHANGE; +                goto gdsl_error_sending; +            } + +            if (be32toh(cmd) != DBC_HELO) +            { +                log_variadic_message(LMT_ERROR, _("The client from '%s:%hu' did not introduce itself!"), +                                     source, ntohs(peer.sin_port)); +                error = DBE_BAD_EXCHANGE; +                goto gdsl_error_sending; +            } -            if (be32toh(data) != CDB_PROTOCOL_VERSION) +            if (be32toh(version) != 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); +                                     source, ntohs(peer.sin_port), be32toh(version), CDB_PROTOCOL_VERSION);                  error = DBE_WRONG_VERSION;                  goto gdsl_error_sending;              } -            if (!recv_rle_string(&hash, fd, 0) || is_rle_string_empty(&hash)) +            if (is_rle_string_empty(&hash))              { -                log_variadic_message(LMT_ERROR, _("Error while getting the binary hash from '%s:%hu'..."), +                log_variadic_message(LMT_ERROR, _("The submitted binary hash from '%s:%hu' is empty!"),                                       source, ntohs(peer.sin_port)); -                goto gdsl_error; +                error = DBE_BAD_EXCHANGE; +                goto gdsl_error_sending;              } -            if (!recv_rle_string(&user, fd, 0) || is_rle_string_empty(&user)) +            if (is_rle_string_empty(&user))              { -                log_variadic_message(LMT_ERROR, _("Error while getting the user name from '%s:%hu'..."), +                log_variadic_message(LMT_ERROR, _("No user is associated with the client from '%s:%hu'..."),                                       source, ntohs(peer.sin_port)); -                goto gdsl_error; +                error = DBE_BAD_EXCHANGE; +                goto gdsl_error_sending;              }              /** @@ -347,6 +365,8 @@ static void *g_db_server_listener(GDbServer *server)               * en cas d'échec, et être le plus précis possible dans la courte réponse.               */ +            assert(error == DBE_NONE); +              for (iter = g_list_first(server->archives);                   iter != NULL;                   iter = g_list_next(iter)) @@ -357,23 +377,13 @@ static void *g_db_server_listener(GDbServer *server)              }              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'). +             *    - un identifiant d'erreur ('DBE_NONE', 'DBE_BAD_EXCHANGE' +             *      ou 'DBE_WRONG_VERSION' ... 'DBE_LOADING_ERROR').               */   gdsl_error_sending: @@ -384,52 +394,37 @@ static void *g_db_server_listener(GDbServer *server)              if (!safe_send(fd, (uint32_t []) { htobe32(error) }, sizeof(uint32_t), 0))                  goto gdsl_error; -            //if (error == DBE_NONE) continue; - +            /** +             * L'ajout dans la liste des clients connectés provoque un envoie de mises à jour. +             * L'éventuelle erreur survenant pendant l'envoi ne peut donc pas être remontée +             * lors des échanges initiaux, car ces derniers seraient alors précédés des mises à jour... +             */              if (archive != NULL) +            { +                assert(error == DBE_NONE); + +                server->archives = g_list_append(server->archives, archive);                  error = g_cdb_archive_add_client(archive, fd, &user); -            continue; +                exit_rle_string(&hash); +                exit_rle_string(&user); +                continue; - gdsl_error: +            } +            assert(error != DBE_NONE); -            /* free RLE !!!! */ + gdsl_error: +            exit_rle_string(&hash); +            exit_rle_string(&user);              close(fd);          } - - - -#if 0 -            g_mutex_lock(&server->mutex); - -            client = (cdb_client *)calloc(1, sizeof(cdb_client)); - -            g_object_ref(G_OBJECT(server)); -            client->server = server; - -            client->fd = fd; -            client->peer = peer; - -            server->clients = (cdb_client **)realloc(server->clients, -                                                     ++server->count * sizeof(cdb_client *)); -            server->clients[server->count - 1] = client; - -            client->thread = g_thread_new("cdb_process", (GThreadFunc)g_db_server_process, -                                          &server->clients[server->count - 1]); - -            g_mutex_unlock(&server->mutex); -#endif - - - -      }      return NULL;  | 
