diff options
| author | Cyrille Bagard <nocbos@gmail.com> | 2014-10-16 22:04:29 (GMT) | 
|---|---|---|
| committer | Cyrille Bagard <nocbos@gmail.com> | 2014-10-16 22:04:29 (GMT) | 
| commit | 6d34dbbb00da0c276261d0e1ce4bf862f22fd8e0 (patch) | |
| tree | a5d3c8644691934ba84a91919f7db177f70743f1 /src | |
| parent | e75f44a99c8f984af4c47fa9a2c8e7e9841700d8 (diff) | |
Stored a bookmark into the data base and saved the archive.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@414 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src')
| -rw-r--r-- | src/analysis/binary.c | 6 | ||||
| -rw-r--r-- | src/analysis/db/cdb.c | 47 | ||||
| -rw-r--r-- | src/analysis/db/cdb.h | 2 | ||||
| -rw-r--r-- | src/analysis/db/client.c | 43 | ||||
| -rw-r--r-- | src/analysis/db/client.h | 3 | ||||
| -rw-r--r-- | src/analysis/db/collection.c | 162 | ||||
| -rw-r--r-- | src/analysis/db/collection.h | 6 | ||||
| -rw-r--r-- | src/analysis/db/item-int.h | 10 | ||||
| -rw-r--r-- | src/analysis/db/item.c | 93 | ||||
| -rw-r--r-- | src/analysis/db/item.h | 18 | ||||
| -rw-r--r-- | src/analysis/db/items/bookmark.c | 61 | ||||
| -rw-r--r-- | src/analysis/db/items/bookmark.h | 2 | ||||
| -rw-r--r-- | src/analysis/db/protocol.h | 27 | ||||
| -rw-r--r-- | src/arch/vmpa.c | 56 | ||||
| -rw-r--r-- | src/arch/vmpa.h | 9 | ||||
| -rwxr-xr-x | src/common/Makefile.am | 1 | ||||
| -rw-r--r-- | src/common/sqlite.h | 56 | ||||
| -rw-r--r-- | src/core/collections.c | 2 | ||||
| -rw-r--r-- | src/gui/panels/bookmarks.c | 166 | 
19 files changed, 655 insertions, 115 deletions
| diff --git a/src/analysis/binary.c b/src/analysis/binary.c index 5577bb8..0fcbe0d 100644 --- a/src/analysis/binary.c +++ b/src/analysis/binary.c @@ -309,7 +309,7 @@ GLoadedBinary *g_loaded_binary_new_from_xml(xmlXPathContextPtr context, const ch          bool status; -        init_vmpa(&addr, 123, 0x200); +        init_vmpa(&addr, 0xaeb4, VMPA_NO_VIRTUAL);          bm = g_db_bookmark_new(&addr, "Premier commentaire"); @@ -323,6 +323,10 @@ GLoadedBinary *g_loaded_binary_new_from_xml(xmlXPathContextPtr context, const ch              printf("send nok\n"); +        g_db_client_save(result->local); + + +          /*          safe_send(client->fd, (uint32_t []) { htobe32(DBC_COLLECTION) }, sizeof(uint32_t), MSG_MORE);          safe_send(client->fd, (uint32_t []) { htobe32(DBF_BOOKMARKS) }, sizeof(uint32_t), MSG_MORE); diff --git a/src/analysis/db/cdb.c b/src/analysis/db/cdb.c index 563aa40..55d1b2d 100644 --- a/src/analysis/db/cdb.c +++ b/src/analysis/db/cdb.c @@ -34,7 +34,6 @@  #include <pthread.h>  #include <signal.h>  #include <stdio.h> -#include <sqlite3.h>  #include <string.h>  #include <unistd.h>  #include <sys/stat.h> @@ -283,6 +282,8 @@ GCdbArchive *g_cdb_archive_new(const char *owner, const rle_string *hash, const      result->filename = get_xdg_config_dir(suffix); +    printf("dealing with '%s'...\n", result->filename); +      free(suffix);      if (!mkpath(result->filename)) @@ -318,7 +319,7 @@ 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)) +        if (g_cdb_archive_write(result) != DBE_NONE)              goto gcan_error;      } @@ -473,13 +474,13 @@ static bool g_cdb_archive_read(GCdbArchive *archive)  *                                                                             *  ******************************************************************************/ -bool g_cdb_archive_write(const GCdbArchive *archive) +DBError g_cdb_archive_write(const GCdbArchive *archive)  { -    bool result;                            /* Conclusion à retourner      */ +    DBError result;                         /* Conclusion à retourner      */      struct archive *out;                    /* Archive à constituer        */      int ret;                                /* Bilan d'un appel            */ -    result = false; +    result = DBE_ARCHIVE_ERROR;      out = archive_write_new();      archive_write_add_filter_xz(out); @@ -488,16 +489,19 @@ bool g_cdb_archive_write(const GCdbArchive *archive)      ret = archive_write_open_filename(out, archive->filename);      if (ret != ARCHIVE_OK) goto gcaw_exit; -    bool add_file_to_archive(struct archive *out, const char *src, const char *path) +    DBError add_file_to_archive(struct archive *out, const char *src, const char *path)      { +        DBError status;                     /* Bilan à renvoyer            */          struct stat info;                   /* Informations d'origine      */          struct archive_entry *entry;        /* Elément de l'archive        */          int fd;                             /* Flux ouvert en lecture      */          char buffer[ARCHIVE_RBUF_SIZE];     /* Tampon pour les transferts  */          ssize_t len;                        /* Quantité de données lues    */ +        status = DBE_ARCHIVE_ERROR; +          ret = stat(src, &info); -        if (ret != 0) return false; +        if (ret != 0) return DBE_SYS_ERROR;          entry = archive_entry_new(); @@ -508,7 +512,11 @@ bool g_cdb_archive_write(const GCdbArchive *archive)          if (ret != 0) goto afta_error;          fd = open(src, O_RDONLY); -        if (fd == -1) goto afta_error; +        if (fd == -1) +        { +            status = DBE_SYS_ERROR; +            goto afta_error; +        }          for (len = safe_read(fd, buffer, ARCHIVE_RBUF_SIZE);               len > 0; @@ -522,18 +530,20 @@ bool g_cdb_archive_write(const GCdbArchive *archive)          archive_entry_free(entry); -        return true; +        return DBE_NONE;   afta_error:          archive_entry_free(entry); -        return false; +        return status;      }      result = add_file_to_archive(out, archive->xml_desc, "desc.xml"); -    result &= add_file_to_archive(out, archive->sql_db, "sql.db"); + +    if (result == DBE_NONE) +        result = add_file_to_archive(out, archive->sql_db, "sql.db");   gcaw_exit: @@ -781,6 +791,7 @@ static void *g_cdb_archive_process(GCdbArchive *archive)      uint32_t val32;                         /* Valeur sur 32 bits          */      bool status;                            /* Bilan de lecture initiale   */      uint32_t command;                       /* Commande de la requête      */ +    DBError error;                          /* Bilan d'une opération       */      GDbCollection *collec;                  /* Collection visée au final   */      void interrupt_poll_with_sigusr1(int sig) { }; @@ -843,6 +854,18 @@ static void *g_cdb_archive_process(GCdbArchive *archive)                  switch (command)                  { +                    case DBC_SAVE: + +                        error = g_cdb_archive_write(archive); + +                        if (!safe_send(fds[i].fd, (uint32_t []) { htobe32(DBC_SAVE) }, sizeof(uint32_t), 0)) +                            goto gcap_bad_exchange; + +                        if (!safe_send(fds[i].fd, (uint32_t []) { htobe32(error) }, sizeof(uint32_t), 0)) +                            goto gcap_bad_exchange; + +                        break; +                      case DBC_COLLECTION:                          status = safe_recv(fds[i].fd, &val32, sizeof(uint32_t), 0); @@ -851,7 +874,7 @@ static void *g_cdb_archive_process(GCdbArchive *archive)                          collec = find_collection_in_list(archive->collections, be32toh(val32));                          if (collec == NULL) goto gcap_bad_exchange; -                        status = g_db_collection_recv(collec, fds[i].fd); +                        status = g_db_collection_recv(collec, fds[i].fd, archive->db);                          if (!status) goto gcap_bad_exchange;                          printf("## CDB ## Got something for collection %p...\n", collec); diff --git a/src/analysis/db/cdb.h b/src/analysis/db/cdb.h index 17327f5..e9abb02 100644 --- a/src/analysis/db/cdb.h +++ b/src/analysis/db/cdb.h @@ -60,7 +60,7 @@ GType g_cdb_archive_get_type(void);  GCdbArchive *g_cdb_archive_new(const char *, const rle_string *, const rle_string *, DBError *);  /* Enregistre une archive avec tous les éléments à conserver. */ -bool g_cdb_archive_write(const GCdbArchive *); +DBError g_cdb_archive_write(const GCdbArchive *);  /* Détermine si une empreinte correspond à celle d'une archive. */  int g_cdb_archive_compare_hash(const GCdbArchive *, const rle_string *); diff --git a/src/analysis/db/client.c b/src/analysis/db/client.c index 4b807ae..71df99c 100644 --- a/src/analysis/db/client.c +++ b/src/analysis/db/client.c @@ -328,6 +328,7 @@ static void *g_db_client_update(GDbClient *client)      uint32_t val32;                         /* Valeur sur 32 bits          */      bool status;                            /* Bilan d'une opération       */      uint32_t command;                       /* Commande de la requête      */ +    DBError error;                          /* Bilan d'une commande passée */      GDbCollection *collec;                  /* Collection visée au final   */      fds.fd = client->fd; @@ -353,6 +354,19 @@ static void *g_db_client_update(GDbClient *client)              switch (command)              { +                case DBC_SAVE: + +                    status = safe_recv(fds.fd, &val32, sizeof(uint32_t), 0); +                    if (!status) goto gdcu_bad_exchange; + +                    error = be32toh(val32); + +                    printf("## CLIENT ## Saved ? %d\n", error); + + + +                    break; +                  case DBC_COLLECTION:                      status = safe_recv(fds.fd, &val32, sizeof(uint32_t), 0); @@ -361,7 +375,7 @@ static void *g_db_client_update(GDbClient *client)                      collec = find_collection_in_list(client->collections, be32toh(val32));                      if (collec == NULL) goto gdcu_bad_exchange; -                    status = g_db_collection_recv(collec, fds.fd); +                    status = g_db_collection_recv(collec, fds.fd, NULL);                      if (!status) goto gdcu_bad_exchange; @@ -459,3 +473,30 @@ void g_db_client_put_fd(GDbClient *client)      g_mutex_unlock(&client->sending_lock);  } + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : client = client pour les accès distants à manipuler.         * +*                                                                             * +*  Description : Effectue une demande de sauvegarde de l'état courant.        * +*                                                                             * +*  Retour      : true si la commande a bien été envoyée, false sinon.         * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool g_db_client_save(GDbClient *client) +{ +    bool result;                            /* Bilan partiel à remonter    */ + +    g_db_client_get_fd(client); + +    result = safe_send(client->fd, (uint32_t []) { htobe32(DBC_SAVE) }, sizeof(uint32_t), 0); + +    g_db_client_put_fd(client); + +    return result; + +} diff --git a/src/analysis/db/client.h b/src/analysis/db/client.h index a1a9f8e..963744b 100644 --- a/src/analysis/db/client.h +++ b/src/analysis/db/client.h @@ -65,6 +65,9 @@ int g_db_client_get_fd(GDbClient *);  /* Marque le canal de communication comme disponible. */  void g_db_client_put_fd(GDbClient *); +/* Effectue une demande de sauvegarde de l'état courant. */ +bool g_db_client_save(GDbClient *); +  #endif  /* _ANALYSIS_DB_CLIENT_H */ diff --git a/src/analysis/db/collection.c b/src/analysis/db/collection.c index 20b1ff3..5c25720 100644 --- a/src/analysis/db/collection.c +++ b/src/analysis/db/collection.c @@ -24,6 +24,11 @@  #include "collection.h" +#include <stdio.h> +#include <string.h> + + +#include "../../common/extstr.h"  #include "../../common/io.h"  #include "../../glibext/chrysamarshal.h" @@ -36,6 +41,7 @@ struct _GDbCollection      uint32_t featuring;                     /* Fonctionnalité représentée  */      GType type;                             /* Identifiant GLib équivalent */ +    const char *name;                       /* Nom en base de données      */      GList *items;                           /* Eléments rassemblés         */      GList *sorted;                          /* Eléments triés              */ @@ -71,6 +77,15 @@ static void g_db_collection_finalize(GDbCollection *); +/* --------------------- MANIPULATIONS AVEC UNE BASE DE DONNEES --------------------- */ + + +/* Enregistre un élément de collection dans une base de données. */ +static bool g_db_collection_store_item(const GDbCollection *, const GDbItem *, sqlite3 *); + + + +  /* Indique le type défini pour une collection générique d'éléments. */  G_DEFINE_TYPE(GDbCollection, g_db_collection, G_TYPE_OBJECT); @@ -170,7 +185,8 @@ static void g_db_collection_finalize(GDbCollection *collec)  /******************************************************************************  *                                                                             *  *  Paramètres  : id   = identifiant réseau des éléments à traiter.            * -*                type = type GLib des éléments à intégrer dans la collection. * +*                type = type GLib des éléments à placer dans la collection.   * +*                name = indique le nom désignant la table associée.           *  *                                                                             *  *  Description : Prépare la mise en place d'une nouvelle collection.          *  *                                                                             * @@ -180,7 +196,7 @@ static void g_db_collection_finalize(GDbCollection *collec)  *                                                                             *  ******************************************************************************/ -GDbCollection *g_db_collection_new(uint32_t id, GType type) +GDbCollection *g_db_collection_new(uint32_t id, GType type, const char *name)  {      GDbCollection *result;                  /* Adresse à retourner         */ @@ -188,6 +204,7 @@ GDbCollection *g_db_collection_new(uint32_t id, GType type)      result->featuring = id;      result->type = type; +    result->name = name;      return result; @@ -233,6 +250,7 @@ uint32_t g_db_collection_get_feature(const GDbCollection *collec)  *                                                                             *  *  Paramètres  : collec = ensemble d'éléments à considérer.                   *  *                fd     = flux ouvert en lecture pour la réception de données.* +*                db     = base de données à mettre à jour.                    *  *                                                                             *  *  Description : Réceptionne et traite une requête réseau pour collection.    *  *                                                                             * @@ -244,7 +262,7 @@ uint32_t g_db_collection_get_feature(const GDbCollection *collec)  *                                                                             *  ******************************************************************************/ -bool g_db_collection_recv(GDbCollection *collec, int fd) +bool g_db_collection_recv(GDbCollection *collec, int fd, sqlite3 *db)  {      bool result;                            /* Bilan à faire remonter      */      uint32_t val32;                         /* Valeur sur 32 bits          */ @@ -269,6 +287,8 @@ bool g_db_collection_recv(GDbCollection *collec, int fd)      {          case DBA_ADD_ITEM:              result = g_db_collection_add_item(collec, item); +            if (result && db != NULL) +                result = g_db_collection_store_item(collec, item, db);              break;          case DBA_REM_ITEM: @@ -430,6 +450,10 @@ bool g_db_collection_add_item(GDbCollection *collec, GDbItem *item)          g_signal_emit_by_name(collec, "content-changed", DBA_ADD_ITEM, item); + +        printf(" ==== CONTENT CHANGED !!!\n"); + +          result = true;      } @@ -478,6 +502,138 @@ bool g_db_collection_modify_item(GDbCollection *collec, GDbItem *item)  /* ---------------------------------------------------------------------------------- */  /*                     CREATION DE L'ABSTRACTION POUR COLLECTIONS                     */ +/*                       MANIPULATIONS AVEC UNE BASE DE DONNEES                       */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : collec = ensemble d'éléments à considérer.                   * +*                item   = élément de collection à enregistrer.                * +*                db     = base de données à mettre à jour.                    * +*                                                                             * +*  Description : Enregistre un élément de collection dans une base de données.* +*                                                                             * +*  Retour      : Bilan de l'exécution de l'opération.                         * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_db_collection_store_item(const GDbCollection *collec, const GDbItem *item, sqlite3 *db) +{ +    bool result;                            /* Conclusion à faire remonter */ +    bound_value *values;                    /* Champs de table à inclure   */ +    size_t count;                           /* Nombre de ces champs        */ +    char *sql;                              /* Requête SQL à construire    */ +    size_t i;                               /* Boucle de parcours          */ +    sqlite3_stmt *stmt;                     /* Déclaration mise en place   */ +    int ret;                                /* Bilan d'un appel à SQLite   */ +    int index;                              /* Indice de valeur attachée   */ + +    if (!g_db_item_prepare_db_statement(item, true, &values, &count)) +        return false; + +    result = false; + +    /* Préparation de la requête */ + +    sql = strdup("INSERT INTO "); +    sql = stradd(sql, collec->name); +    sql = stradd(sql, " ("); + +    for (i = 0; i < count; i++) +    { +        if (i > 0) sql = stradd(sql, ", "); + +        sql = stradd(sql, values[i].name); + +    } + +    sql = stradd(sql, ") VALUES ("); + +    for (i = 0; i < count; i++) +    { +        if (i > 0) sql = stradd(sql, ", "); + +        if (values[i].type == SQLITE_RAW) +            sql = stradd(sql, values[i].cstring); +        else +            sql = stradd(sql, "?"); + +    } + +    sql = stradd(sql, ");"); + +	ret = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL); +	if (ret != SQLITE_OK) +    { +		fprintf(stderr, "Can't prepare INSERT statment '%s' (ret=%d): %s\n", sql, ret, sqlite3_errmsg(db)); +        goto gdcsi_exit; +	} + +    /* Attribution des valeurs */ + +    index = 1; + +    for (i = 0; i < count; i++) +    { +        switch (values[i].type) +        { +            case SQLITE_INT64: +                ret = sqlite3_bind_int64(stmt, index, values[i].integer64); +                index++; +                break; + +            case SQLITE_TEXT: +                ret = sqlite3_bind_text(stmt, index, values[i].string, -1, values[i].delete); +                index++; +                break; + +            default: +                ret = SQLITE_OK; +                break; + +        } + +        if (ret != SQLITE_OK) +        { +            fprintf(stderr, "Can't bind value for parameter nb %d in '%s' (ret=%d): %s\n", +                    index - 1, sql, ret, sqlite3_errmsg(db)); +            goto gdcsi_exit; +        } + +    } + +    /* Exécution finale */ + +	ret = sqlite3_step(stmt); + +    if (ret != SQLITE_DONE) +    { +		fprintf(stderr, "INSERT statement '%s' didn't return DONE (ret=%d): %s\n", sql, ret, sqlite3_errmsg(db)); +        goto gdcsi_exit; +    } + +    sqlite3_finalize(stmt); + +    result = true; + + gdcsi_exit: + +    free(sql); + +    printf("INSERT ? %d\n", result); + +    return result; + +} + + + + +/* ---------------------------------------------------------------------------------- */ +/*                     CREATION DE L'ABSTRACTION POUR COLLECTIONS                     */  /* ---------------------------------------------------------------------------------- */ diff --git a/src/analysis/db/collection.h b/src/analysis/db/collection.h index 75ee7df..b400820 100644 --- a/src/analysis/db/collection.h +++ b/src/analysis/db/collection.h @@ -26,6 +26,8 @@  #include <glib-object.h> +#include <sqlite3.h> +#include <stdbool.h>  #include <stdint.h> @@ -52,7 +54,7 @@ typedef struct _GDbCollectionClass GDbCollectionClass;  GType g_db_collection_get_type(void);  /* Prépare la mise en place d'une nouvelle collection. */ -GDbCollection *g_db_collection_new(uint32_t, GType); +GDbCollection *g_db_collection_new(uint32_t, GType, const char *); @@ -63,7 +65,7 @@ uint32_t g_db_collection_get_feature(const GDbCollection *);  /* Réceptionne et traite une requête réseau pour collection. */ -bool g_db_collection_recv(GDbCollection *, int); +bool g_db_collection_recv(GDbCollection *, int, sqlite3 *);  /* Envoie pour traitement une requête réseau pour collection. */  bool g_db_collection_send(GDbCollection *, int, DBAction, GDbItem *); diff --git a/src/analysis/db/item-int.h b/src/analysis/db/item-int.h index b6d8f9c..0f75ed4 100644 --- a/src/analysis/db/item-int.h +++ b/src/analysis/db/item-int.h @@ -32,12 +32,20 @@ + + + + +  /* Importe la définition d'une base d'éléments pour collection. */  typedef bool (* recv_db_item_fc) (GDbItem *, int, int);  /* Exporte la définition d'une base d'éléments pour collection. */  typedef bool (* send_db_item_fc) (const GDbItem *, int, int); +/* Constitue les champs destinés à une insertion / modification. */ +typedef bool (* prepare_db_statement) (const GDbItem *, bool, bound_value **, size_t *); +  /* Base d'un élément pour collection générique (instance) */  struct _GDbItem @@ -61,6 +69,8 @@ struct _GDbItemClass      recv_db_item_fc recv;                   /* Réception depuis le réseau  */      send_db_item_fc send;                   /* Emission depuis le réseau   */ +    prepare_db_statement prepare_stmt;      /* Préparation d'une requête   */ +  }; diff --git a/src/analysis/db/item.c b/src/analysis/db/item.c index e2fd7f3..7fa1a52 100644 --- a/src/analysis/db/item.c +++ b/src/analysis/db/item.c @@ -24,8 +24,13 @@  #include "item.h" +#include <malloc.h> +#include <sqlite3.h> + +  #include "item-int.h"  #include "../../common/io.h" +#include "../../core/params.h" @@ -52,6 +57,13 @@ static bool g_db_item_send_to_fd(const GDbItem *, int, int); +/* --------------------- MANIPULATIONS AVEC UNE BASE DE DONNEES --------------------- */ + + +/* Constitue les champs destinés à une insertion / modification. */ +static bool _g_db_item_prepare_db_statement(const GDbItem *, bool, bound_value **, size_t *); + +  /* Indique le type défini pour une base d'élément de collection générique. */  G_DEFINE_TYPE(GDbItem, g_db_item, G_TYPE_OBJECT); @@ -83,6 +95,8 @@ static void g_db_item_class_init(GDbItemClass *klass)      klass->recv = (recv_db_item_fc)g_db_item_recv_from_fd;      klass->send = (send_db_item_fc)g_db_item_send_to_fd; +    klass->prepare_stmt = (prepare_db_statement)_g_db_item_prepare_db_statement; +  } @@ -354,3 +368,82 @@ bool g_db_item_is_volatile(const GDbItem *item)      return item->is_volatile;  } + + + +/* ---------------------------------------------------------------------------------- */ +/*                       MANIPULATIONS AVEC UNE BASE DE DONNEES                       */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +*                                                                             * +*  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]                        * +*                                                                             * +*  Description : Constitue les champs destinés à une insertion / modification.* +*                                                                             * +*  Retour      : Bilan de l'opération : succès ou non.                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool _g_db_item_prepare_db_statement(const GDbItem *item, bool create, bound_value **values, size_t *count) +{ +    char *author;                           /* Identification à diffuser   */ +    bound_value *value;                     /* Valeur à éditer / définir   */ + +    if (!g_generic_config_get_value(get_main_configuration(), MPK_AUTHOR_NAME, &author)) +        return false; + +    *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; + +    if (!create) +    { +        *values = (bound_value *)realloc(*values, ++(*count) * sizeof(bound_value)); +        value = &(*values)[*count - 1]; + +        value->name = "modified"; +        value->type = SQLITE_RAW; +        value->string = "CURRENT_TIMESTAMP"; +        value->delete = SQLITE_STATIC; + +    } + +    return true; + +} + + +/****************************************************************************** +*                                                                             * +*  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]                        * +*                                                                             * +*  Description : Constitue les champs destinés à une insertion / modification.* +*                                                                             * +*  Retour      : Bilan de l'opération : succès ou non.                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool g_db_item_prepare_db_statement(const GDbItem *item, bool create, bound_value **values, size_t *count) +{ +    *values = NULL; +    *count = 0; + +    return G_DB_ITEM_GET_CLASS(item)->prepare_stmt(item, create, values, count); + +} diff --git a/src/analysis/db/item.h b/src/analysis/db/item.h index 3938610..2f8ee60 100644 --- a/src/analysis/db/item.h +++ b/src/analysis/db/item.h @@ -29,6 +29,9 @@  #include <stdbool.h> +#include "../../common/sqlite.h" + +  #define G_TYPE_DB_ITEM               g_db_item_get_type()  #define G_DB_ITEM(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), g_db_item_get_type(), GDbItem)) @@ -65,4 +68,19 @@ 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 *); + + +  #endif  /* _ANALYSIS_DB_ITEM_H */ diff --git a/src/analysis/db/items/bookmark.c b/src/analysis/db/items/bookmark.c index c28a837..6ff386c 100644 --- a/src/analysis/db/items/bookmark.c +++ b/src/analysis/db/items/bookmark.c @@ -75,6 +75,9 @@ static bool g_db_bookmark_recv_from_fd(GDbBookmark *, int, int);  /* Exporte la définition d'un signet dans un flux réseau. */  static bool g_db_bookmark_send_to_fd(const GDbBookmark *, int, int); +/* Constitue les champs destinés à une insertion / modification. */ +static bool g_db_bookmark_prepare_db_statement(const GDbBookmark *, bool, bound_value **, size_t *); + @@ -97,10 +100,8 @@ bool create_bookmark_db_table(sqlite3 *db)      char *msg;                              /* Message d'erreur            */      sql = "CREATE TABLE Bookmarks ("            \ -             "id INT PRIMARY KEY NOT NULL, "    \ -             "user TEXT NOT NULL, "             \ -             "created INT NOT NULL, "           \ -             "address INT NOT NULL, "           \ +             SQLITE_DB_ITEM_CREATE              \ +             SQLITE_VMPA_CREATE                 \               "comment TEXT"                     \            ");"; @@ -157,6 +158,8 @@ static void g_db_bookmark_class_init(GDbBookmarkClass *klass)      item->recv = (recv_db_item_fc)g_db_bookmark_recv_from_fd;      item->send = (send_db_item_fc)g_db_bookmark_send_to_fd; +    item->prepare_stmt = (prepare_db_statement)g_db_bookmark_prepare_db_statement; +  } @@ -235,13 +238,7 @@ GDbBookmark *g_db_bookmark_new(const vmpa2t *addr, const char *comment)      result = g_object_new(G_TYPE_DB_BOOKMARK, NULL); - - - -    /* TODO */ - -    //dup addr; - +    copy_vmpa(&result->addr, addr);      g_db_bookmark_set_comment(result, comment); @@ -351,6 +348,46 @@ 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]                        * +*                                                                             * +*  Description : Constitue les champs destinés à une insertion / modification.* +*                                                                             * +*  Retour      : Etat du besoin en sauvegarde.                                * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_db_bookmark_prepare_db_statement(const GDbBookmark *bookmark, bool create, 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); +    if (!status) return false; + +    status = prepare_vmpa_db_statement(&bookmark->addr, create, 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; + +    return true; + +} + + + @@ -370,7 +407,7 @@ static bool g_db_bookmark_send_to_fd(const GDbBookmark *bookmark, int fd, int fl  *                                                                             *  ******************************************************************************/ -vmpa2t *g_db_bookmark_get_address(GDbBookmark *bookmark) +const vmpa2t *g_db_bookmark_get_address(GDbBookmark *bookmark)  {      return &bookmark->addr; diff --git a/src/analysis/db/items/bookmark.h b/src/analysis/db/items/bookmark.h index d1b073c..cd5e202 100644 --- a/src/analysis/db/items/bookmark.h +++ b/src/analysis/db/items/bookmark.h @@ -66,7 +66,7 @@ GType g_db_bookmark_get_type(void);  GDbBookmark *g_db_bookmark_new(const vmpa2t *, const char *);  /* Fournit l'adresse associée à un signet. */ -vmpa2t *g_db_bookmark_get_address(GDbBookmark *); +const vmpa2t *g_db_bookmark_get_address(GDbBookmark *);  /* Fournit le commentaire associé à un signet. */  const char *g_db_bookmark_get_comment(const GDbBookmark *); diff --git a/src/analysis/db/protocol.h b/src/analysis/db/protocol.h index 05b559e..85d44cb 100644 --- a/src/analysis/db/protocol.h +++ b/src/analysis/db/protocol.h @@ -113,6 +113,7 @@ typedef enum _DBCommand  {      DBC_HELO,                               /* Connexion initiale C -> S   */      DBC_WELCOME,                            /* Réponse initiale S -> C     */ +    DBC_SAVE,                               /* Enregistrement de l'archive */      DBC_COLLECTION,                         /* Implication d'une collection*/      DBC_COUNT @@ -132,6 +133,8 @@ typedef enum _DBError  {      DBE_NONE,                               /* Succès d'une opération      */      DBE_WRONG_VERSION,                      /* Proto Client != Serveur     */ +    DBE_SYS_ERROR,                          /* Erreur suite à un appel sys.*/ +    DBE_ARCHIVE_ERROR,                      /* Soucis du côté libarchive   */      DBE_COUNT @@ -141,6 +144,30 @@ typedef enum _DBError +/** + * Gestion de la commande 'DBC_SAVE'. + * + * Le client connecté envoie un paquet de la forme suivante : + * + *    [ Ordre de sauvegarde : DBC_SAVE            ] + * + * Le serveur s'exécute et renvoie un bilan : + * + *    [ Ordre de sauvegarde : DBC_SAVE            ] + *    [ Statut d'exécution ; cf. DBError          ] + * + * Les traitements se réalisent dans : + *  - g_db_client_save() pour la partie client en émission. + *  - g_cdb_archive_process() pour la partie serveur. + *  - g_db_client_update() pour la partie client en réception. + * + */ + + + + + + diff --git a/src/arch/vmpa.c b/src/arch/vmpa.c index 6f305fb..024161c 100644 --- a/src/arch/vmpa.c +++ b/src/arch/vmpa.c @@ -482,6 +482,62 @@ vmpa2t *string_to_vmpa_virt(const char *buffer)  } +/****************************************************************************** +*                                                                             * +*  Paramètres  : addr   = adresse virtuelle ou physique à traiter.            * +*                create = indique si la préparation vise une création ou non. * +*                values = couples de champs et de valeurs à lier. [OUT]       * +*                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_vmpa_db_statement(const vmpa2t *addr, bool create, 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 = "phys"; + +    if (addr->physical != VMPA_NO_PHYSICAL) +    { +        value->type = SQLITE_INT64; +        value->integer64 = addr->physical; +    } +    else +    { +        value->type = SQLITE_RAW; +        value->cstring = "NULL"; +    } + +    *values = (bound_value *)realloc(*values, ++(*count) * sizeof(bound_value)); +    value = &(*values)[*count - 1]; + +    value->name = "virt"; + +    if (addr->virtual != VMPA_NO_VIRTUAL) +    { +        value->type = SQLITE_INT64; +        value->integer64 = addr->virtual; +    } +    else +    { +        value->type = SQLITE_RAW; +        value->cstring = "NULL"; +    } + +    return true; + +} + +  /* ---------------------------------------------------------------------------------- */  /*                          DEFINITION D'UNE ZONE EN MEMOIRE                          */ diff --git a/src/arch/vmpa.h b/src/arch/vmpa.h index 52c5d6a..f0a8faf 100644 --- a/src/arch/vmpa.h +++ b/src/arch/vmpa.h @@ -34,6 +34,7 @@  #include "archbase.h"  #include "../common/cpp.h" +#include "../common/sqlite.h" @@ -117,6 +118,14 @@ vmpa2t *string_to_vmpa_phy(const char *);  /* Transforme une chaîne de caractères en adresse virtuelle. */  vmpa2t *string_to_vmpa_virt(const char *); +/* Définition du tronc commun pour les créations SQLite */ +#define SQLITE_VMPA_CREATE  \ +    "phys INTEGER, "        \ +    "virt INTEGER, " + +/* Constitue les champs destinés à une insertion / modification. */ +bool prepare_vmpa_db_statement(const vmpa2t *, bool, bound_value **, size_t *); +  /* ------------------------ DEFINITION D'UNE ZONE EN MEMOIRE ------------------------ */ diff --git a/src/common/Makefile.am b/src/common/Makefile.am index 7ec85ab..198de32 100755 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -13,6 +13,7 @@ libcommon_la_SOURCES =					\  	leb128.h leb128.c					\  	macros.h							\  	net.h net.c							\ +	sqlite.h							\  	xdg.h xdg.c							\  	xml.h xml.c diff --git a/src/common/sqlite.h b/src/common/sqlite.h new file mode 100644 index 0000000..66fb773 --- /dev/null +++ b/src/common/sqlite.h @@ -0,0 +1,56 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * sqlite.h - prototypes pour une extension des définitions propres à SQLite + * + * Copyright (C) 2014 Cyrille Bagard + * + *  This file is part of Chrysalide. + * + *  OpenIDA is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  OpenIDA is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _COMMON_SQLITE_H +#define _COMMON_SQLITE_H + + +#include <stdint.h> + + +/* Type pour les insertions brutes */ +#define SQLITE_RAW      0 +#define SQLITE_INT64    10 + + +/* Description des champs et de leur valeur associée */ +typedef struct _bound_value +{ +    const char *name;                       /* Nom du champ à manipuler    */ +    unsigned int type;                      /* Type de valeur à associer   */ + +    union +    { +        int64_t integer64;                  /* Nombre sur 64 bits          */ +        char *string;                       /* Chaîne de caractères #1     */ +        const char *cstring;                /* Chaîne de caractères #2     */ + +    }; + +    void (* delete) (void *);               /* Suppression éventuelle      */ + +} bound_value; + + + +#endif  /* _COMMON_SQLITE_H */ diff --git a/src/core/collections.c b/src/core/collections.c index 860b7f6..80d2ae3 100644 --- a/src/core/collections.c +++ b/src/core/collections.c @@ -164,7 +164,7 @@ GList *create_collections_list(void)      for (i = 0; i < _collection_definitions_count; i++)      {          def = &_collection_definitions[i]; -        collec = g_db_collection_new(i, def->items); +        collec = g_db_collection_new(i, def->items, "Bookmarks");          result = g_list_append(result, collec); diff --git a/src/gui/panels/bookmarks.c b/src/gui/panels/bookmarks.c index 56e7119..5d2be18 100644 --- a/src/gui/panels/bookmarks.c +++ b/src/gui/panels/bookmarks.c @@ -110,6 +110,8 @@ static void g_bookmarks_panel_finalize(GBookmarksPanel *);  /* Recharge une collection de signets à l'affichage. */  static void reload_bookmarks_into_treeview(GBookmarksPanel *, GLoadedBinary *); +/* Réagit au changement de sélection des signets. */ +static void on_bookmarks_selection_change(GtkTreeSelection *, GBookmarksPanel *); @@ -234,6 +236,7 @@ static void g_bookmarks_panel_init(GBookmarksPanel *panel)      GtkCellRenderer *renderer;              /* Moteur de rendu de colonne  */      GtkTreeViewColumn *column;              /* Colonne de la liste         */      GtkTreeSortable *sortable;              /* Autre vision de la liste    */ +    GtkTreeSelection *select;               /* Sélection dans la liste     */      base = G_EDITOR_ITEM(panel); @@ -294,7 +297,7 @@ static void g_bookmarks_panel_init(GBookmarksPanel *panel)      renderer = gtk_cell_renderer_text_new();      column = gtk_tree_view_column_new_with_attributes(_("Physical address"), renderer, -                                                      "text", BMC_VIRTUAL, +                                                      "text", BMC_PHYSICAL,                                                        NULL);      gtk_tree_view_column_set_sort_column_id(column, BMC_PHYSICAL);      gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); @@ -330,6 +333,12 @@ static void g_bookmarks_panel_init(GBookmarksPanel *panel)      gtk_tree_sortable_set_sort_column_id(sortable, BMC_COMMENT, GTK_SORT_ASCENDING); +    /* Prise en compte de la sélection */ + +    select = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)); +    gtk_tree_selection_set_mode(select, GTK_SELECTION_SINGLE); +    g_signal_connect(G_OBJECT(select), "changed", G_CALLBACK(on_bookmarks_selection_change), panel); +      /* Préparation du menu contextuel */      panel->menu = build_bookmarks_panel_menu(panel); @@ -464,14 +473,17 @@ static void reload_bookmarks_into_treeview(GBookmarksPanel *panel, GLoadedBinary  {      GtkTreeStore *store;                    /* Modèle de gestion           */      GDbCollection *collec;                  /* Collection à lister ici     */ +    GExeFormat *format;                     /* Format du fichier binaire   */ +    GArchProcessor *proc;                   /* Architecture du binaire     */ +    MemoryDataSize msize;                   /* Taille par défaut           */      GList *items;                           /* Liste des éléments groupés  */      GList *b;                               /* Boucle de parcours          */      GDbBookmark *bookmark;                  /* Signet en cours d'étude     */ -    vmpa2t *addr;                           /* Adressse associée au signet */ +    const vmpa2t *addr;                     /* Adressse associée au signet */ +    VMPA_BUFFER(phys);                      /* Position physique           */ +    VMPA_BUFFER(virt);                      /* Adresse virtuelle           */      GtkTreeIter iter;                       /* Point d'insertion           */ -    printf("RELOAD :: %p\n", binary); -      /* Basculement du binaire utilisé */      if (panel->binary != NULL) @@ -491,7 +503,10 @@ static void reload_bookmarks_into_treeview(GBookmarksPanel *panel, GLoadedBinary      /* Actualisation de l'affichage */ -    sleep(1); +    format = g_loaded_binary_get_format(binary); +    proc = get_arch_processor_from_format(format); + +    msize = g_arch_processor_get_memory_size(proc);      collec = g_loaded_binary_find_collection(binary, DBF_BOOKMARKS); @@ -499,107 +514,65 @@ static void reload_bookmarks_into_treeview(GBookmarksPanel *panel, GLoadedBinary      items = g_db_collection_list_items(collec); - -    printf(" ... items = %p\n", items); - -    /* -    gtk_tree_store_append(store, &iter, NULL); -    gtk_tree_store_set(store, &iter, -                       BMC_BOOKMARK, bookmark, -                       BMC_PICTURE, G_BOOKMARKS_PANEL_GET_CLASS(panel)->bookmark_img, -                       BMC_PHYSICAL, "0x01", -                       BMC_VIRTUAL, "0x02", -                       BMC_COMMENT, "desc", -                       -1); -    */ - -      for (b = g_list_first(items); b != NULL; b = g_list_next(b))      {          bookmark = G_DB_BOOKMARK(b->data); - -        printf("Adding // %p\n", bookmark); - -        //printf("add.virt = %s\n", vmpa2_virt_to_string(&addr, MDS_32_BITS)); - -        fflush(NULL); - -          addr = g_db_bookmark_get_address(bookmark); +        vmpa2_phys_to_string(addr, msize, phys, NULL); +        vmpa2_virt_to_string(addr, msize, virt, NULL); +          gtk_tree_store_append(store, &iter, NULL);          gtk_tree_store_set(store, &iter,                             BMC_BOOKMARK, bookmark,                             BMC_PICTURE, G_BOOKMARKS_PANEL_GET_CLASS(panel)->bookmark_img, -                           BMC_PHYSICAL, "vmpa2_phy_to_string(addr, MDS_32_BITS)",    /* FIXME : pareil qu'en bas */ -                           BMC_VIRTUAL, "vmpa2_virt_to_string(&addr, MDS_32_BITS)", /* FIXME : choisir en fonction de l'architecture */ -                           BMC_COMMENT, "g_db_bookmark_get_comment(bookmark)", +                           BMC_PHYSICAL, phys, +                           BMC_VIRTUAL, virt, +                           BMC_COMMENT, g_db_bookmark_get_comment(bookmark),                             -1);      }      g_db_collection_runlock(collec); +} -#if 0 -    GtkTreeStore *store;                    /* Modèle de gestion           */ -    GList *params;                          /* Paramètres de configuration */ -    GCfgParam *param;                       /* Paramètre en cours d'étude  */ -    GList *p;                               /* Boucle de parcours          */ -    char *type_desc;                        /* Type de paramètre           */ -    GtkTreeIter iter;                       /* Point d'insertion           */ - -    store = GTK_TREE_STORE(gtk_tree_view_get_model(panel->treeview)); -    gtk_tree_store_clear(store); - -    g_generic_config_rlock(config); +/****************************************************************************** +*                                                                             * +*  Paramètres  : selection = sélection modifiée.                              * +*                panel     = structure contenant les informations maîtresses. * +*                                                                             * +*  Description : Réagit au changement de sélection des signets.               * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ -    params = g_generic_config_list_params(config); +static void on_bookmarks_selection_change(GtkTreeSelection *selection, GBookmarksPanel *panel) +{ +    GtkTreeIter iter;                       /* Point de sélection          */ +    GtkTreeModel *model;                    /* Modèle de gestion           */ +    GDbBookmark *bookmark;                  /* Signet en cours d'étude     */ +    const vmpa2t *addr;                     /* Adressse associée au signet */ +    GtkViewPanel *vpanel;                   /* Afficheur effectif de code  */ -    for (p = g_list_first(params); p != NULL; p = g_list_next(p)) +    if (gtk_tree_selection_get_selected(selection, &model, &iter))      { -        param = G_CFG_PARAM(p->data); +        gtk_tree_model_get(model, &iter, BMC_BOOKMARK, &bookmark, -1); -        if (is_param_filtered(panel, g_config_param_get_path(param))) -            continue; - -        switch (g_config_param_get_ptype(param)) -        { -            case CPT_BOOLEAN: -                type_desc = _("Boolean"); -                break; - -            case CPT_INTEGER: -                type_desc = _("Integer"); -                break; - -            case CPT_STRING: -                type_desc = _("String"); -                break; - -            default: -                type_desc = _("<Unknown type>"); -                break; - -        } - -        gtk_tree_store_append(store, &iter, NULL); -        gtk_tree_store_set(store, &iter, -                           CPC_BOOKMARK, param, -                           CPC_PATH, g_config_param_get_path(param), -                           CPC_TYPE, type_desc, -                           -1); +        addr = g_db_bookmark_get_address(bookmark); -        update_config_param_value(store, &iter); +        vpanel = g_editor_item_get_current_view(G_EDITOR_ITEM(panel)); +        gtk_view_panel_scroll_to_address(vpanel, addr); -        g_signal_connect(param, "modified", G_CALLBACK(on_config_param_modified), panel); +        g_object_unref(G_OBJECT(bookmark));      } -    g_generic_config_runlock(config); -#endif  } @@ -1008,8 +981,39 @@ static bool is_param_filtered(GBookmarksPanel *panel, const char *name)  static gboolean on_button_press_over_bookmarks(GtkWidget *widget, GdkEventButton *event, GBookmarksPanel *panel)  { -    if (event->button == 3) -        gtk_menu_popup(panel->menu, NULL, NULL, NULL, NULL, event->button, event->time); +    GtkTreeSelection *selection;            /* Sélection courante          */ +    GtkTreeIter iter;                       /* Point de sélection          */ +    GtkTreeModel *model;                    /* Modèle de gestion           */ +    GDbBookmark *bookmark;                  /* Signet en cours d'étude     */ +    const vmpa2t *addr;                     /* Adressse associée au signet */ +    GtkViewPanel *vpanel;                   /* Afficheur effectif de code  */ + +    switch (event->button) +    { +        case 1: + +            selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)); + +            if (gtk_tree_selection_get_selected(selection, &model, &iter)) +            { +                gtk_tree_model_get(model, &iter, BMC_BOOKMARK, &bookmark, -1); + +                addr = g_db_bookmark_get_address(bookmark); + +                vpanel = g_editor_item_get_current_view(G_EDITOR_ITEM(panel)); +                gtk_view_panel_scroll_to_address(vpanel, addr); + +                g_object_unref(G_OBJECT(bookmark)); + +            } + +            break; + +        case 3: +            gtk_menu_popup(panel->menu, NULL, NULL, NULL, NULL, event->button, event->time); +            break; + +    }      return FALSE; | 
