From 1430874c1ce9d5e38a23bf27049ebc5f6a6619bb Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sun, 8 Sep 2019 19:41:58 +0200
Subject: Provided a way to save the database updates from Python.

---
 plugins/pychrysalide/analysis/binary.c    | 56 +++++++++++++++++++++++++++++++
 plugins/pychrysalide/analysis/db/client.c | 45 +++++++++++++++++++++++++
 src/analysis/binary.c                     |  7 ++--
 src/analysis/binary.h                     |  4 +--
 src/analysis/db/client.c                  | 21 +++++++-----
 src/gui/panels/history.c                  |  4 +--
 6 files changed, 121 insertions(+), 16 deletions(-)

diff --git a/plugins/pychrysalide/analysis/binary.c b/plugins/pychrysalide/analysis/binary.c
index 98b20dc..9d57952 100644
--- a/plugins/pychrysalide/analysis/binary.c
+++ b/plugins/pychrysalide/analysis/binary.c
@@ -45,6 +45,9 @@
 /* Crée un nouvel objet Python de type 'LoadedBinary'. */
 static PyObject *py_loaded_binary_new(PyTypeObject *, PyObject *, PyObject *);
 
+/* Fournit un client assurant la liaison avec un serveur. */
+static PyObject *py_loaded_binary_get_client(PyObject *, PyObject *);
+
 /* Demande l'intégration d'une modification dans une collection. */
 static PyObject *py_loaded_binary_add_to_collection(PyObject *, PyObject *);
 
@@ -103,6 +106,58 @@ static PyObject *py_loaded_binary_new(PyTypeObject *type, PyObject *args, PyObje
 *  Paramètres  : self = objet représentant un binaire chargé.                 *
 *                args = arguments fournis pour l'opération.                   *
 *                                                                             *
+*  Description : Fournit un client assurant la liaison avec un serveur.       *
+*                                                                             *
+*  Retour      : Client connecté ou None.                                     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_loaded_binary_get_client(PyObject *self, PyObject *args)
+{
+    PyObject *result;                       /* Bilan à retourner           */
+    bool internal;                          /* Nature du client visé       */
+    int ret;                                /* Bilan de lecture des args.  */
+    GLoadedBinary *binary;                  /* Binaire en cours d'analyse  */
+    GHubClient *client;                     /* Eventuel client en place    */
+
+#define LOADED_BINARY_GET_CLIENT_METHOD PYTHON_METHOD_DEF               \
+(                                                                       \
+    get_client, "$self, /, internal=True",                              \
+    METH_VARARGS, py_loaded_binary,                                     \
+    "Provide the client connected to an internal or remote server"      \
+    " if defined, or return None otherwise.\n"                          \
+)
+
+    ret = PyArg_ParseTuple(args, "|p", &internal);
+    if (!ret) return NULL;
+
+    binary = G_LOADED_BINARY(pygobject_get(self));
+
+    client = g_loaded_binary_get_client(binary, internal);
+
+    if (client != NULL)
+    {
+        result = pygobject_new(G_OBJECT(client));
+        g_object_unref(G_OBJECT(client));
+    }
+    else
+    {
+        result = Py_None;
+        Py_INCREF(result);
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = objet représentant un binaire chargé.                 *
+*                args = arguments fournis pour l'opération.                   *
+*                                                                             *
 *  Description : Demande l'intégration d'une modification dans une collection.*
 *                                                                             *
 *  Retour      : Bilan partiel de l'opération demandée.                       *
@@ -303,6 +358,7 @@ static PyObject *py_loaded_binary_get_disassembled_cache(PyObject *self, void *c
 PyTypeObject *get_python_loaded_binary_type(void)
 {
     static PyMethodDef py_loaded_binary_methods[] = {
+        LOADED_BINARY_GET_CLIENT_METHOD,
         LOADED_BINARY_ADD_TO_COLLECTION_METHOD,
         { NULL }
     };
diff --git a/plugins/pychrysalide/analysis/db/client.c b/plugins/pychrysalide/analysis/db/client.c
index a9ad930..13966f5 100644
--- a/plugins/pychrysalide/analysis/db/client.c
+++ b/plugins/pychrysalide/analysis/db/client.c
@@ -48,6 +48,9 @@ static PyObject *py_hub_client_start(PyObject *, PyObject *);
 /* Arrête la connexion à la base de données. */
 static PyObject *py_hub_client_stop(PyObject *, PyObject *);
 
+/* Effectue une demande de sauvegarde de l'état courant. */
+static PyObject *py_hub_client_save(PyObject *, PyObject *);
+
 
 
 /******************************************************************************
@@ -235,6 +238,47 @@ static PyObject *py_hub_client_stop(PyObject *self, PyObject *args)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : self = serveur à manipuler.                                  *
+*                args = arguments d'appel non utilisés ici.                   *
+*                                                                             *
+*  Description : Effectue une demande de sauvegarde de l'état courant.        *
+*                                                                             *
+*  Retour      : True si la commande a bien été envoyée, False sinon.         *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_hub_client_save(PyObject *self, PyObject *args)
+{
+    PyObject *result;                       /* Bilan à retourner           */
+    GHubClient *client;                     /* Version native du serveur   */
+    bool status;                            /* Bilan de l'opération        */
+
+#define HUB_CLIENT_SAVE_METHOD PYTHON_METHOD_DEF                            \
+(                                                                           \
+    save, "$self, /",                                                       \
+    METH_NOARGS, py_hub_client,                                             \
+    "Ask the server for saving the current state of the analyzed binary,"   \
+    " and returns the status of the request transmission."                  \
+)
+
+    client = G_HUB_CLIENT(pygobject_get(self));
+
+    status = g_hub_client_save(client);
+
+    result = status ? Py_True : Py_False;
+    Py_INCREF(result);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : -                                                            *
 *                                                                             *
 *  Description : Fournit un accès à une définition de type à diffuser.        *
@@ -250,6 +294,7 @@ PyTypeObject *get_python_hub_client_type(void)
     static PyMethodDef py_hub_client_methods[] = {
         HUB_CLIENT_START_METHOD,
         HUB_CLIENT_STOP_METHOD,
+        HUB_CLIENT_SAVE_METHOD,
         { NULL }
     };
 
diff --git a/src/analysis/binary.c b/src/analysis/binary.c
index 639d6cc..5d72c41 100644
--- a/src/analysis/binary.c
+++ b/src/analysis/binary.c
@@ -958,9 +958,10 @@ bool g_loaded_binary_save_cache(const GLoadedBinary *binary)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : binary = élément binaire à consulter.                        *
+*  Paramètres  : binary   = élément binaire à consulter.                      *
+*                internal = sélectionne le client à renvoyer selon sa nature. *
 *                                                                             *
-*  Description : Fournit le client assurant la liaison avec un serveur.       *
+*  Description : Fournit un client assurant la liaison avec un serveur.       *
 *                                                                             *
 *  Retour      : Client connecté ou NULL.                                     *
 *                                                                             *
@@ -968,7 +969,7 @@ bool g_loaded_binary_save_cache(const GLoadedBinary *binary)
 *                                                                             *
 ******************************************************************************/
 
-GHubClient *g_loaded_binary_get_db_client(const GLoadedBinary *binary)
+GHubClient *g_loaded_binary_get_client(const GLoadedBinary *binary, bool internal)
 {
     GHubClient *result;                     /* Instance à retourner        */
 
diff --git a/src/analysis/binary.h b/src/analysis/binary.h
index 9b3aa6b..36966c9 100644
--- a/src/analysis/binary.h
+++ b/src/analysis/binary.h
@@ -116,8 +116,8 @@ bool g_loaded_binary_save_cache(const GLoadedBinary *);
 /* -------------------------- MANIPULATION DES COLLECTIONS -------------------------- */
 
 
-/* Fournit le client assurant la liaison avec un serveur. */
-GHubClient *g_loaded_binary_get_db_client(const GLoadedBinary *);
+/* Fournit un client assurant la liaison avec un serveur. */
+GHubClient *g_loaded_binary_get_client(const GLoadedBinary *, bool);
 
 /* Fournit l'ensemble des collections utilisées par un binaire. */
 GDbCollection **g_loaded_binary_get_all_collections(const GLoadedBinary *, size_t *);
diff --git a/src/analysis/db/client.c b/src/analysis/db/client.c
index 2bfa978..329d57d 100644
--- a/src/analysis/db/client.c
+++ b/src/analysis/db/client.c
@@ -61,8 +61,6 @@ struct _GHubClient
 {
     GObject parent;                         /* A laisser en premier        */
 
-    const char *name;                       /* Désignation du binaire      */
-
     rle_string hash;                        /* Empreinte du binaire lié    */
     GList *collections;                     /* Collections d'un binaire    */
 
@@ -756,10 +754,10 @@ static void *g_hub_client_update(GHubClient *client)
 
                     if (error == DBE_NONE)
                         log_variadic_message(LMT_INFO, _("Archive saved for binary '%s'"),
-                                             client->name);
+                                             get_rle_string(&client->hash));
                     else
                         log_variadic_message(LMT_ERROR, _("Failed to save the archive for binary '%s'"),
-                                             client->name);
+                                             get_rle_string(&client->hash));
 
                     break;
 
@@ -951,16 +949,21 @@ void g_hub_client_put_ssl_fd(GHubClient *client, SSL *tls_fd)
 bool g_hub_client_save(GHubClient *client)
 {
     bool result;                            /* Bilan partiel à remonter    */
-    int sent;                               /* Quantité de données traitées*/
+    packed_buffer out_pbuf;                 /* Tampon d'émission           */
+
+    init_packed_buffer(&out_pbuf);
 
     g_hub_client_get_ssl_fd(client);
 
-    sent = SSL_write(client->tls_fd, (uint32_t []) { htobe32(DBC_SAVE) }, sizeof(uint32_t));
+    result = extend_packed_buffer(&out_pbuf, (uint32_t []) { DBC_SAVE }, sizeof(uint32_t), true);
 
-    result = (sent == sizeof(uint32_t));
+    if (result)
+        result = ssl_send_packed_buffer(&out_pbuf, client->tls_fd);
 
     g_hub_client_put_ssl_fd(client, client->tls_fd);
 
+    exit_packed_buffer(&out_pbuf);
+
     return result;
 
 }
@@ -993,11 +996,11 @@ bool g_hub_client_set_last_active(GHubClient *client, timestamp_t timestamp)
     if (result)
         result = pack_timestamp(&timestamp, &out_pbuf);
 
-    g_hub_client_put_ssl_fd(client, client->tls_fd);
-
     if (result)
         result = ssl_send_packed_buffer(&out_pbuf, client->tls_fd);
 
+    g_hub_client_put_ssl_fd(client, client->tls_fd);
+
     exit_packed_buffer(&out_pbuf);
 
     return result;
diff --git a/src/gui/panels/history.c b/src/gui/panels/history.c
index 4383ed6..ac33c2c 100644
--- a/src/gui/panels/history.c
+++ b/src/gui/panels/history.c
@@ -614,7 +614,7 @@ static void do_history_undo(GtkButton *button, GHistoryPanel *panel)
 
         gtk_tree_model_get(model, &iter, HTC_ITEM, &item, -1);
 
-        client = g_loaded_binary_get_db_client(panel->binary);
+        client = g_loaded_binary_get_client(panel->binary, true);
         g_hub_client_set_last_active(client, g_db_item_get_timestamp(item));
         g_object_unref(G_OBJECT(client));
 
@@ -658,7 +658,7 @@ static void do_history_redo(GtkButton *button, GHistoryPanel *panel)
     {
         gtk_tree_model_get(model, &iter, HTC_ITEM, &item, -1);
 
-        client = g_loaded_binary_get_db_client(panel->binary);
+        client = g_loaded_binary_get_client(panel->binary, true);
         g_hub_client_set_last_active(client, g_db_item_get_timestamp(item));
         g_object_unref(G_OBJECT(client));
 
-- 
cgit v0.11.2-87-g4458