From 1a85f36e0505d75a51ab7b7f2c5078da7ef6bd98 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Fri, 6 Sep 2019 00:53:24 +0200
Subject: Made server connections easier while running analysis.

---
 plugins/pychrysalide/analysis/loaded.c | 90 +++++++++++++++++++++++++---------
 src/analysis/binary.c                  | 41 +++++++++-------
 src/analysis/db/client.c               |  3 +-
 src/analysis/loaded-int.h              |  2 +-
 src/analysis/loaded.c                  | 19 ++++---
 src/analysis/loaded.h                  |  4 +-
 src/analysis/project.c                 |  4 +-
 src/gui/editor.c                       |  2 +-
 8 files changed, 110 insertions(+), 55 deletions(-)

diff --git a/plugins/pychrysalide/analysis/loaded.c b/plugins/pychrysalide/analysis/loaded.c
index 43e749c..ab00038 100644
--- a/plugins/pychrysalide/analysis/loaded.c
+++ b/plugins/pychrysalide/analysis/loaded.c
@@ -34,6 +34,7 @@
 
 
 #include <analysis/loaded.h>
+#include <core/global.h>
 
 
 #include "../access.h"
@@ -42,10 +43,10 @@
 
 
 /* Lance l'analyse propre à l'élément chargé. */
-static PyObject *py_loaded_content_analyze(PyObject *, PyObject *);
+static PyObject *py_loaded_content_analyze(PyObject *, PyObject *, PyObject *);
 
 /* Lance l'analyse de l'élément chargé et attend sa conclusion. */
-static PyObject *py_loaded_content_analyze_and_wait(PyObject *, PyObject *);
+static PyObject *py_loaded_content_analyze_and_wait(PyObject *, PyObject *, PyObject *);
 
 /* Etablit une liste d'obscurcissements présents. */
 static PyObject *py_loaded_content_detect_obfuscators(PyObject *, PyObject *);
@@ -62,6 +63,7 @@ static PyObject *py_loaded_content_get_content(PyObject *, void *);
 *                                                                             *
 *  Paramètres  : self = contenu binaire à manipuler.                          *
 *                args = arguments fournis à l'appel.                          *
+*                kwds = arguments de type key=val fournis.                    *
 *                                                                             *
 *  Description : Lance l'analyse propre à l'élément chargé.                   *
 *                                                                             *
@@ -71,20 +73,44 @@ static PyObject *py_loaded_content_get_content(PyObject *, void *);
 *                                                                             *
 ******************************************************************************/
 
-static PyObject *py_loaded_content_analyze(PyObject *self, PyObject *args)
+static PyObject *py_loaded_content_analyze(PyObject *self, PyObject *args, PyObject *kwds)
 {
+    int connect;                            /* Connexion à la base ?       */
     int cache;                              /* Préparation de rendu ?      */
     int ret;                                /* Bilan de lecture des args.  */
     GLoadedContent *content;                /* Version GLib de l'élément   */
 
-    cache = 0;
-
-    ret = PyArg_ParseTuple(args, "|p", &cache);
+    static char *kwlist[] = { "connect", "cache", NULL };
+
+#define LOADED_CONTENT_ANALYZE_METHOD PYTHON_METHOD_DEF                     \
+(                                                                           \
+    analyze, "$self, /, connect=bool, cache=False",                         \
+    METH_VARARGS | METH_KEYWORDS, py_loaded_content,                        \
+    "Start the analysis of the loaded binary and send an *analyzed* signal" \
+    " when done."                                                           \
+    "\n"                                                                    \
+    "The *connect* parameter defines if connections to database servers"    \
+    " (internal and/or remote) will be established. The default value"      \
+    " depends on the running mode: if the analysis is run from the GUI,"    \
+    " the binary will get connected to servers; in batch mode, no"          \
+    " connection will be made."                                             \
+    "\n"                                                                    \
+    "The *cache* parameter rules the build of the cache for rendering"      \
+    " lines. The same behavior relative to the running mode applies."       \
+    "\n"                                                                    \
+    "All theses operations can be forced by providing True values as"       \
+    " parameters."                                                          \
+)
+
+    connect = is_batch_mode() ? 0 : 1;
+    cache = is_batch_mode() ? 0 : 1;
+
+    ret = PyArg_ParseTupleAndKeywords(args, kwds, "|pp", kwlist, &connect, &cache);
     if (!ret) return NULL;
 
     content = G_LOADED_CONTENT(pygobject_get(self));
 
-    g_loaded_content_analyze(content, cache);
+    g_loaded_content_analyze(content, connect, cache);
 
     Py_RETURN_NONE;
 
@@ -95,6 +121,7 @@ static PyObject *py_loaded_content_analyze(PyObject *self, PyObject *args)
 *                                                                             *
 *  Paramètres  : self = contenu binaire à manipuler.                          *
 *                args = arguments fournis à l'appel.                          *
+*                kwds = arguments de type key=val fournis.                    *
 *                                                                             *
 *  Description : Lance l'analyse de l'élément chargé et attend sa conclusion. *
 *                                                                             *
@@ -104,25 +131,50 @@ static PyObject *py_loaded_content_analyze(PyObject *self, PyObject *args)
 *                                                                             *
 ******************************************************************************/
 
-static PyObject *py_loaded_content_analyze_and_wait(PyObject *self, PyObject *args)
+static PyObject *py_loaded_content_analyze_and_wait(PyObject *self, PyObject *args, PyObject *kwds)
 {
     PyObject *result;                       /* Bilan à retourner           */
+    int connect;                            /* Connexion à la base ?       */
     int cache;                              /* Préparation de rendu ?      */
     int ret;                                /* Bilan de lecture des args.  */
     PyThreadState *_save;                   /* Sauvegarde de contexte      */
     GLoadedContent *content;                /* Version GLib de l'élément   */
     bool status;                            /* Bilan de l'opération        */
 
-    cache = 0;
-
-    ret = PyArg_ParseTuple(args, "|p", &cache);
+    static char *kwlist[] = { "connect", "cache", NULL };
+
+#define LOADED_CONTENT_ANALYZE_AND_WAIT_METHOD PYTHON_METHOD_DEF            \
+(                                                                           \
+    analyze_and_wait, "$self, /, connect=bool, cache=False",                \
+    METH_VARARGS | METH_KEYWORDS, py_loaded_content,                        \
+    "Run the analysis of the loaded binary and wait for its completion."    \
+    "\n"                                                                    \
+    "The final analysis status is returned as boolean."                     \
+    "\n"                                                                    \
+    "The *connect* parameter defines if connections to database servers"    \
+    " (internal and/or remote) will be established. The default value"      \
+    " depends on the running mode: if the analysis is run from the GUI,"    \
+    " the binary will get connected to servers; in batch mode, no"          \
+    " connection will be made."                                             \
+    "\n"                                                                    \
+    "The *cache* parameter rules the build of the cache for rendering"      \
+    " lines. The same behavior relative to the running mode applies."       \
+    "\n"                                                                    \
+    "All theses operations can be forced by providing True values as"       \
+    " parameters."                                                          \
+)
+
+    connect = is_batch_mode() ? 0 : 1;
+    cache = is_batch_mode() ? 0 : 1;
+
+    ret = PyArg_ParseTupleAndKeywords(args, kwds, "|pp", kwlist, &connect, &cache);
     if (!ret) return NULL;
 
     content = G_LOADED_CONTENT(pygobject_get(self));
 
     Py_UNBLOCK_THREADS;
 
-    status = g_loaded_content_analyze_and_wait(content, cache);
+    status = g_loaded_content_analyze_and_wait(content, connect, cache);
 
     Py_BLOCK_THREADS;
 
@@ -257,18 +309,8 @@ static PyObject *py_loaded_content_get_content(PyObject *self, void *closure)
 PyTypeObject *get_python_loaded_content_type(void)
 {
     static PyMethodDef py_loaded_content_methods[] = {
-        {
-            "analyze", py_loaded_content_analyze,
-            METH_VARARGS,
-            "analyze($self, cache, /)\n--\n\nStart the analysis of the loaded binary and " \
-            "send an \"analyzed\" signal when done."
-        },
-        {
-            "analyze_and_wait", py_loaded_content_analyze_and_wait,
-            METH_VARARGS,
-            "analyze_and_wait($self, cache, /)\n--\n\nRun the analysis of the loaded binary and " \
-            "wait for its completion."
-        },
+        LOADED_CONTENT_ANALYZE_METHOD,
+        LOADED_CONTENT_ANALYZE_AND_WAIT_METHOD,
         {
             "detect_obfuscators", py_loaded_content_detect_obfuscators,
             METH_VARARGS,
diff --git a/src/analysis/binary.c b/src/analysis/binary.c
index ec129b1..cf680c3 100644
--- a/src/analysis/binary.c
+++ b/src/analysis/binary.c
@@ -44,7 +44,6 @@
 #include "../common/cpp.h"
 #include "../common/xdg.h"
 #include "../core/collections.h"
-#include "../core/global.h"
 #include "../core/logs.h"
 #include "../core/params.h"
 #include "../core/processors.h"
@@ -169,7 +168,7 @@ static GBinContent *g_loaded_binary_get_content(const GLoadedBinary *);
 static const char *g_loaded_binary_get_format_name(const GLoadedBinary *);
 
 /* Assure le désassemblage en différé. */
-static bool g_loaded_binary_analyze(GLoadedBinary *, bool, wgroup_id_t, GtkStatusStack *);
+static bool g_loaded_binary_analyze(GLoadedBinary *, bool, bool, wgroup_id_t, GtkStatusStack *);
 
 /* Prend note d'une variation des instructions désassemblées. */
 static void on_binary_processor_changed(GArchProcessor *, GArchInstruction *, gboolean, GLoadedBinary *);
@@ -1088,23 +1087,30 @@ bool _g_loaded_binary_add_to_collection(GLoadedBinary *binary, GDbItem *item, bo
         if (storage == DBS_ALL_REMOTE)
             client = binary->remote;
         else
-            client = NULL;
+            client = binary->local;
 
         if (client == NULL)
-            client = binary->local;
+        {
+            log_simple_message(LMT_ERROR, _("No connection to a server in order to forward the item"));
+            result = false;
+        }
 
-        init_packed_buffer(&out_pbuf);
+        else
+        {
+            init_packed_buffer(&out_pbuf);
 
-        fd = g_hub_client_get_fd(client);
+            fd = g_hub_client_get_fd(client);
 
-        result = g_db_collection_pack(collec, &out_pbuf, DBA_ADD_ITEM, item);
+            result = g_db_collection_pack(collec, &out_pbuf, DBA_ADD_ITEM, item);
 
-        g_hub_client_put_fd(client);
+            g_hub_client_put_fd(client);
 
-        if (result)
-            result = send_packed_buffer(&out_pbuf, fd);
+            if (result)
+                result = send_packed_buffer(&out_pbuf, fd);
 
-        exit_packed_buffer(&out_pbuf);
+            exit_packed_buffer(&out_pbuf);
+
+        }
 
     }
 
@@ -1645,10 +1651,11 @@ static const char *g_loaded_binary_get_format_name(const GLoadedBinary *binary)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : binary = élément chargé dont l'analyse est lancée.           *
-*                cache  = précise si la préparation d'un rendu est demandée.  *
-*                gid    = groupe de travail dédié.                            *
-*                status = barre de statut à tenir informée.                   *
+*  Paramètres  : binary  = élément chargé dont l'analyse est lancée.          *
+*                connect = organise le lancement des connexions aux serveurs. *
+*                cache   = précise si la préparation d'un rendu est demandée. *
+*                gid     = groupe de travail dédié.                           *
+*                status  = barre de statut à tenir informée.                  *
 *                                                                             *
 *  Description : Assure le désassemblage en différé.                          *
 *                                                                             *
@@ -1658,7 +1665,7 @@ static const char *g_loaded_binary_get_format_name(const GLoadedBinary *binary)
 *                                                                             *
 ******************************************************************************/
 
-static bool g_loaded_binary_analyze(GLoadedBinary *binary, bool cache, wgroup_id_t gid, GtkStatusStack *status)
+static bool g_loaded_binary_analyze(GLoadedBinary *binary, bool connect, bool cache, wgroup_id_t gid, GtkStatusStack *status)
 {
     bool result;                            /* Bilan à retourner           */
     GBinFormat *format;                     /* Format lié au binaire       */
@@ -1715,7 +1722,7 @@ static bool g_loaded_binary_analyze(GLoadedBinary *binary, bool cache, wgroup_id
 
     /* Phase de désassemblage pur */
 
-    if (!is_batch_mode())
+    if (connect)
         g_loaded_binary_connect_internal(binary);
 
     disassemble_binary(binary, gid, status, &context);
diff --git a/src/analysis/db/client.c b/src/analysis/db/client.c
index c608bfa..9252ccc 100644
--- a/src/analysis/db/client.c
+++ b/src/analysis/db/client.c
@@ -856,7 +856,8 @@ void g_hub_client_stop(GHubClient *client)
     ret = close(fd);
     if (ret == -1) LOG_ERROR_N("close");
 
-    g_thread_join(client->update);
+    if (g_thread_self() != client->update)
+        g_thread_join(client->update);
 
     /* Environnement TLS */
 
diff --git a/src/analysis/loaded-int.h b/src/analysis/loaded-int.h
index c1cba2a..1b04fab 100644
--- a/src/analysis/loaded-int.h
+++ b/src/analysis/loaded-int.h
@@ -43,7 +43,7 @@ typedef GBinContent * (* get_content_fc) (const GLoadedContent *);
 typedef const char * (* get_format_name_fc) (const GLoadedContent *);
 
 /* Assure l'analyse d'un contenu chargé en différé. */
-typedef bool (* analyze_loaded_fc) (GLoadedContent *, bool, wgroup_id_t, GtkStatusStack *);
+typedef bool (* analyze_loaded_fc) (GLoadedContent *, bool, bool, wgroup_id_t, GtkStatusStack *);
 
 /* Fournit le désignation associée à l'élément chargé. */
 typedef const char * (* describe_loaded_fc) (const GLoadedContent *, bool);
diff --git a/src/analysis/loaded.c b/src/analysis/loaded.c
index 6f79bf8..f8b25d5 100644
--- a/src/analysis/loaded.c
+++ b/src/analysis/loaded.c
@@ -69,6 +69,7 @@ struct _GLoadedAnalysis
     GDelayedWork parent;                    /* A laisser en premier        */
 
     GLoadedContent *content;                /* Cible de l'analyse à mener  */
+    bool connect;                           /* Lancement de connexions ?   */
     bool cache;                             /* Degré d'opération à mener   */
 
     bool success;                           /* Bilan de l'opération        */
@@ -99,7 +100,7 @@ static void g_loaded_analysis_dispose(GLoadedAnalysis *);
 static void g_loaded_analysis_finalize(GLoadedAnalysis *);
 
 /* Crée une tâche d'analyse de contenu différée. */
-static GLoadedAnalysis *g_loaded_analysis_new(GLoadedContent *, bool);
+static GLoadedAnalysis *g_loaded_analysis_new(GLoadedContent *, bool, bool);
 
 /* Assure l'analyse d'un contenu chargé en différé. */
 static void g_loaded_analysis_process(GLoadedAnalysis *, GtkStatusStack *);
@@ -261,6 +262,7 @@ const char *g_loaded_content_get_format_name(const GLoadedContent *content)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : content = élément chargé à manipuler.                        *
+*                connect = organise le lancement des connexions aux serveurs. *
 *                cache   = précise si la préparation d'un rendu est demandée. *
 *                                                                             *
 *  Description : Lance l'analyse propre à l'élément chargé.                   *
@@ -271,12 +273,12 @@ const char *g_loaded_content_get_format_name(const GLoadedContent *content)
 *                                                                             *
 ******************************************************************************/
 
-void g_loaded_content_analyze(GLoadedContent *content, bool cache)
+void g_loaded_content_analyze(GLoadedContent *content, bool connect, bool cache)
 {
     GLoadedAnalysis *analysis;              /* Analyse à mener             */
     GWorkQueue *queue;                      /* Gestionnaire de différés    */
 
-    analysis = g_loaded_analysis_new(content, cache);
+    analysis = g_loaded_analysis_new(content, connect, cache);
 
     g_signal_connect(analysis, "work-completed",
                      G_CALLBACK(on_loaded_content_analysis_completed), content);
@@ -311,6 +313,7 @@ static void on_loaded_content_analysis_completed(GLoadedAnalysis *analysis, GLoa
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : content = élément chargé à manipuler.                        *
+*                connect = organise le lancement des connexions aux serveurs. *
 *                cache   = précise si la préparation d'un rendu est demandée. *
 *                                                                             *
 *  Description : Lance l'analyse de l'élément chargé et attend sa conclusion. *
@@ -321,14 +324,14 @@ static void on_loaded_content_analysis_completed(GLoadedAnalysis *analysis, GLoa
 *                                                                             *
 ******************************************************************************/
 
-bool g_loaded_content_analyze_and_wait(GLoadedContent *content, bool cache)
+bool g_loaded_content_analyze_and_wait(GLoadedContent *content, bool connect, bool cache)
 {
     bool result;                            /* Bilan à retourner           */
     GLoadedAnalysis *analysis;              /* Analyse à mener             */
     GWorkQueue *queue;                      /* Gestionnaire de différés    */
     wgroup_id_t gid;                        /* Identifiant pour les tâches */
 
-    analysis = g_loaded_analysis_new(content, cache);
+    analysis = g_loaded_analysis_new(content, connect, cache);
     g_object_ref(G_OBJECT(analysis));
 
     queue = get_work_queue();
@@ -647,6 +650,7 @@ static void g_loaded_analysis_finalize(GLoadedAnalysis *analysis)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : content = contenu chargé à traiter.                          *
+*                connect = organise le lancement des connexions aux serveurs. *
 *                cache   = précise si la préparation d'un rendu est demandée. *
 *                                                                             *
 *  Description : Crée une tâche d'analyse de contenu différée.                *
@@ -657,7 +661,7 @@ static void g_loaded_analysis_finalize(GLoadedAnalysis *analysis)
 *                                                                             *
 ******************************************************************************/
 
-static GLoadedAnalysis *g_loaded_analysis_new(GLoadedContent *content, bool cache)
+static GLoadedAnalysis *g_loaded_analysis_new(GLoadedContent *content, bool connect, bool cache)
 {
     GLoadedAnalysis *result;            /* Tâche à retourner           */
 
@@ -666,6 +670,7 @@ static GLoadedAnalysis *g_loaded_analysis_new(GLoadedContent *content, bool cach
     result->content = content;
     g_object_ref(G_OBJECT(content));
 
+    result->connect = connect;
     result->cache = cache;
 
     return result;
@@ -698,7 +703,7 @@ static void g_loaded_analysis_process(GLoadedAnalysis *analysis, GtkStatusStack
 
     gid = g_work_queue_define_work_group(queue);
 
-    analysis->success = iface->analyze(analysis->content, analysis->cache, gid, status);
+    analysis->success = iface->analyze(analysis->content, analysis->connect, analysis->cache, gid, status);
 
     if (analysis->success)
         handle_loaded_content(PGA_CONTENT_ANALYZED, analysis->content, gid, status);
diff --git a/src/analysis/loaded.h b/src/analysis/loaded.h
index 1d41cef..ee919f2 100644
--- a/src/analysis/loaded.h
+++ b/src/analysis/loaded.h
@@ -71,10 +71,10 @@ GBinContent *g_loaded_content_get_content(const GLoadedContent *);
 const char *g_loaded_content_get_format_name(const GLoadedContent *);
 
 /* Lance l'analyse propre à l'élément chargé. */
-void g_loaded_content_analyze(GLoadedContent *, bool);
+void g_loaded_content_analyze(GLoadedContent *, bool, bool);
 
 /* Lance l'analyse de l'élément chargé et attend sa conclusion. */
-bool g_loaded_content_analyze_and_wait(GLoadedContent *, bool);
+bool g_loaded_content_analyze_and_wait(GLoadedContent *, bool, bool);
 
 /* Fournit le désignation associée à l'élément chargé. */
 const char *g_loaded_content_describe(const GLoadedContent *, bool);
diff --git a/src/analysis/project.c b/src/analysis/project.c
index 84b5d7b..8285e7a 100644
--- a/src/analysis/project.c
+++ b/src/analysis/project.c
@@ -1299,7 +1299,7 @@ static void on_new_content_resolved(GContentResolver *resolver, wgroup_id_t wid,
                         g_signal_connect(available[i], "analyzed",
                                          G_CALLBACK(on_loaded_content_analyzed), handler->project);
 
-                        g_loaded_content_analyze(available[i], handler->cache);
+                        g_loaded_content_analyze(available[i], !is_batch_mode(), handler->cache);
 
                     }
 
@@ -1337,7 +1337,7 @@ static void on_new_content_resolved(GContentResolver *resolver, wgroup_id_t wid,
                         g_signal_connect(available[i], "analyzed",
                                          G_CALLBACK(on_loaded_content_analyzed), handler->project);
 
-                        g_loaded_content_analyze(available[i], handler->cache);
+                        g_loaded_content_analyze(available[i], !is_batch_mode(), handler->cache);
 
                     }
 
diff --git a/src/gui/editor.c b/src/gui/editor.c
index 75efc2f..8280e7c 100644
--- a/src/gui/editor.c
+++ b/src/gui/editor.c
@@ -900,7 +900,7 @@ static void on_editor_content_available(GStudyProject *project, GLoadedContent *
 
     g_signal_connect(content, "analyzed", G_CALLBACK(on_loaded_content_analyzed), project);
 
-    g_loaded_content_analyze(content, true);
+    g_loaded_content_analyze(content, true, true);
 
 }
 
-- 
cgit v0.11.2-87-g4458