From 5108aad8eb7b20a14c1e7d9e084af2272035192d Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sat, 15 Feb 2020 18:22:18 +0100
Subject: Improved the documentation for the loaded content Python bindings.

---
 plugins/pychrysalide/analysis/loaded.c | 315 +++++++++++++++++++++++++++++++--
 1 file changed, 302 insertions(+), 13 deletions(-)

diff --git a/plugins/pychrysalide/analysis/loaded.c b/plugins/pychrysalide/analysis/loaded.c
index 4a762ef..768b11c 100644
--- a/plugins/pychrysalide/analysis/loaded.c
+++ b/plugins/pychrysalide/analysis/loaded.c
@@ -42,24 +42,45 @@
 
 
 
+#define LOADED_CONTENT_DOC                                                  \
+    "The LoadedContent interface is an intermediary level of abstraction"   \
+    " for all loaded binary contents to analyze."                           \
+    "\n"                                                                    \
+    "No matter if the loaded content comes from an ELF file or XML data,"   \
+    " some basic features are available here."
+
+
+
 /* Lance l'analyse propre à l'élément chargé. */
 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 *, PyObject *);
 
+/* Fournit le désignation associée à l'élément chargé. */
+static PyObject *py_loaded_content_describe(PyObject *, PyObject *);
+
 /* Etablit une liste d'obscurcissements présents. */
 static PyObject *py_loaded_content_detect_obfuscators(PyObject *, PyObject *);
 
 /* Détermine le nombre de vues disponibles pour un contenu. */
 static PyObject *py_loaded_content_count_views(PyObject *, PyObject *);
 
+/* Fournit le nom d'une vue donnée d'un contenu chargé. */
+static PyObject *py_loaded_content_get_view_name(PyObject *, PyObject *);
+
 /* Met en place la vue initiale pour un contenu chargé. */
 static PyObject *py_loaded_content_build_default_view(PyObject *, PyObject *);
 
+/* Met en place la vue initiale pour un contenu chargé. */
+static PyObject *py_loaded_content_build_view(PyObject *, PyObject *);
+
 /* Fournit le contenu représenté de l'élément chargé. */
 static PyObject *py_loaded_content_get_content(PyObject *, void *);
 
+/* Fournit le format associé à l'élément chargé. */
+static PyObject *py_loaded_content_get_format_name(PyObject *, void *);
+
 
 
 /******************************************************************************
@@ -192,7 +213,54 @@ static PyObject *py_loaded_content_analyze_and_wait(PyObject *self, PyObject *ar
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : self = contenu binaire à manipuler.                          *
-*                args = non utilisé ici.                                      *
+*                args = arguments associés à l'appel.                         *
+*                                                                             *
+*  Description : Fournit le désignation associée à l'élément chargé.          *
+*                                                                             *
+*  Retour      : Description courante.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_loaded_content_describe(PyObject *self, PyObject *args)
+{
+    PyObject *result;                       /* Bilan à retourner           */
+    int full;                               /* Précision quant aux attentes*/
+    int ret;                                /* Bilan de lecture des args.  */
+    GLoadedContent *content;                /* Version GLib de l'élément   */
+    const char *desc;                       /* Description associée        */
+
+#define LOADED_CONTENT_DESCRIBE_METHOD PYTHON_METHOD_DEF                        \
+(                                                                               \
+    describe, "$self, full",                                                    \
+    METH_VARARGS, py_loaded_content,                                            \
+    "Describe the loaded content.\n"                                            \
+    "\n"                                                                        \
+    "The boolean *full* parameter shapes the size of the returned string.\n"    \
+    "\n"                                                                        \
+    "This method is mainly used to provide a label (or a tooltip text)"         \
+    " for tabs in the graphical main window."                                   \
+)
+
+    ret = PyArg_ParseTuple(args, "p", &full);
+    if (!ret) return NULL;
+
+    content = G_LOADED_CONTENT(pygobject_get(self));
+
+    desc = g_loaded_content_describe(content, full);
+
+    result = PyUnicode_FromString(desc);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = contenu binaire à manipuler.                          *
+*                args = arguments associés à l'appel.                         *
 *                                                                             *
 *  Description : Etablit une liste d'obscurcissements présents.               *
 *                                                                             *
@@ -212,6 +280,18 @@ static PyObject *py_loaded_content_detect_obfuscators(PyObject *self, PyObject *
     char **detections;                      /* Liste d'obscurcissements    */
     size_t i;                               /* Boucle de parcours          */
 
+#define LOADED_CONTENT_DETECT_OBFUSCATORS_METHOD PYTHON_METHOD_DEF          \
+(                                                                           \
+    detect_obfuscators, "$self, version",                                   \
+    METH_VARARGS, py_loaded_content,                                        \
+    "List all detected obfuscators.\n"                                      \
+    "\n"                                                                    \
+    "If the *version* parameter is equal to True, the operation tries to"   \
+    " resolve obfuscators versions too.\n"                                  \
+    "\n"                                                                    \
+    "The result is a tuple of strings or an empty tuple."                   \
+)
+
     ret = PyArg_ParseTuple(args, "p", &version);
     if (!ret) return NULL;
 
@@ -238,7 +318,7 @@ static PyObject *py_loaded_content_detect_obfuscators(PyObject *self, PyObject *
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : self = contenu chargé à manipuler.                           *
-*                args = non utilisé ici.                                      *
+*                args = arguments associés à l'appel.                         *
 *                                                                             *
 *  Description : Détermine le nombre de vues disponibles pour un contenu.     *
 *                                                                             *
@@ -254,6 +334,13 @@ static PyObject *py_loaded_content_count_views(PyObject *self, PyObject *args)
     GLoadedContent *content;                /* Version GLib de l'élément   */
     size_t count;                           /* Quantité à retourner        */
 
+#define LOADED_CONTENT_COUNT_VIEWS_METHOD PYTHON_METHOD_DEF             \
+(                                                                       \
+    count_views, "$self",                                               \
+    METH_NOARGS, py_loaded_content,                                     \
+    "Compute the quantity of available views for the loaded binary."    \
+)
+
     content = G_LOADED_CONTENT(pygobject_get(self));
 
     count = g_loaded_content_count_views(content);
@@ -268,6 +355,51 @@ static PyObject *py_loaded_content_count_views(PyObject *self, PyObject *args)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : self = contenu chargé à manipuler.                           *
+*                args = arguments associés à l'appel.                         *
+*                                                                             *
+*  Description : Fournit le nom d'une vue donnée d'un contenu chargé.         *
+*                                                                             *
+*  Retour      : Désignation humainement lisible.                             *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_loaded_content_get_view_name(PyObject *self, PyObject *args)
+{
+    PyObject *result;                       /* Instance à retourner        */
+    unsigned int index;                     /* Indice de la vue ciblée     */
+    int ret;                                /* Bilan de lecture des args.  */
+    GLoadedContent *content;                /* Version GLib de l'élément   */
+    const char *name;                       /* Dénomination récupérée      */
+
+#define LOADED_CONTENT_GET_VIEW_NAME_METHOD PYTHON_METHOD_DEF                   \
+(                                                                               \
+    get_view_name, "$self, index",                                              \
+    METH_VARARGS, py_loaded_content,                                            \
+    "Provide the human readable name for a given view of a loaded binary.\n"    \
+    "\n"                                                                        \
+    "Such a method is used in the graphical main window for building menu"      \
+    " labels."                                                                  \
+)
+
+    ret = PyArg_ParseTuple(args, "I", &index);
+    if (!ret) return NULL;
+
+    content = G_LOADED_CONTENT(pygobject_get(self));
+
+    name = g_loaded_content_get_view_name(content, index);
+
+    result = PyUnicode_FromString(name);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = contenu chargé à manipuler.                           *
 *                args = non utilisé ici.                                      *
 *                                                                             *
 *  Description : Met en place la vue initiale pour un contenu chargé.         *
@@ -310,6 +442,126 @@ static PyObject *py_loaded_content_build_default_view(PyObject *self, PyObject *
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : self = contenu chargé à manipuler.                           *
+*                args = arguments associés à l'appel.                         *
+*                                                                             *
+*  Description : Met en place la vue initiale pour un contenu chargé.         *
+*                                                                             *
+*  Retour      : Composant graphique nouveau.                                 *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_loaded_content_build_view(PyObject *self, PyObject *args)
+{
+    PyObject *result;                       /* Instance à retourner        */
+    unsigned int index;                     /* Indice de la vue ciblée     */
+    int ret;                                /* Bilan de lecture des args.  */
+    GLoadedContent *content;                /* Version GLib de l'élément   */
+    GtkWidget *view;                        /* Composant GTK à transposer  */
+
+#define LOADED_CONTENT_BUILD_VIEW_METHOD PYTHON_METHOD_DEF                  \
+(                                                                           \
+    build_view, "$self, index",                                             \
+    METH_VARARGS, py_loaded_content,                                        \
+    "Build a new widget for a given graphical view of the loaded content."  \
+    "\n"                                                                    \
+    "This method is aimed to only be called from the GUI internals."        \
+    " It provides a view displayed in the main Chrysalide window"           \
+    " once the binary is loaded."                                           \
+)
+
+    ret = PyArg_ParseTuple(args, "I", &index);
+    if (!ret) return NULL;
+
+    content = G_LOADED_CONTENT(pygobject_get(self));
+
+    view = g_loaded_content_build_default_view(content);
+
+    result = new_pygobject_widget(view);
+
+    g_object_unref(G_OBJECT(view));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = contenu chargé à manipuler.                           *
+*                args = arguments associés à l'appel.                         *
+*                                                                             *
+*  Description : Retrouve l'indice correspondant à la vue donnée d'un contenu.*
+*                                                                             *
+*  Retour      : Indice de la vue représentée, ou -1 en cas d'erreur.         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_loaded_content_get_view_index(PyObject *self, PyObject *args)
+{
+    PyObject *result;                       /* Instance à retourner        */
+    PyObject *gtk_mod;                      /* Module Python Gtk           */
+    PyObject *type;                         /* Module "GtkWidget"          */
+    PyObject *widget_obj;                   /* Composant GTK en Python     */
+    int ret;                                /* Bilan de lecture des args.  */
+    GLoadedContent *content;                /* Version GLib de l'élément   */
+    GtkWidget *widget;                      /* Composant GTK à retrouver   */
+    unsigned int index;                     /* Indice de la vue fournie    */
+
+#define LOADED_CONTENT_GET_VIEW_INDEX_METHOD PYTHON_METHOD_DEF              \
+(                                                                           \
+    get_view_index, "$self, widget",                                        \
+    METH_VARARGS, py_loaded_content,                                        \
+    "Define the index of a given view for the loaded binary.\n"             \
+    "\n"                                                                    \
+    "The view is provided as a GTK *widget*.\n"                             \
+    "\n"                                                                    \
+    "The result is the index of the type of view, or -1 in case of error."  \
+)
+
+    gtk_mod = PyImport_ImportModule("gi.repository.Gtk");
+
+    if (gtk_mod == NULL)
+    {
+        PyErr_SetString(PyExc_TypeError, "unable to find the Gtk Python module");
+        return NULL;
+    }
+
+    type = PyObject_GetAttrString(gtk_mod, "Widget");
+
+    Py_DECREF(gtk_mod);
+
+    ret = PyArg_ParseTuple(args, "O!", type, &widget_obj);
+
+    Py_DECREF(type);
+
+    if (!ret) return NULL;
+
+    if (!GTK_IS_WIDGET(pygobject_get(widget_obj)))
+    {
+        PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to GTK widget");
+        return NULL;
+    }
+
+    content = G_LOADED_CONTENT(pygobject_get(self));
+
+    widget = GTK_WIDGET(pygobject_get(widget_obj));
+
+    index = g_loaded_content_get_view_index(content, widget);
+
+    result = PyLong_FromUnsignedLong(index);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : self    = objet Python concerné par l'appel.                 *
 *                closure = non utilisé ici.                                   *
 *                                                                             *
@@ -348,6 +600,46 @@ static PyObject *py_loaded_content_get_content(PyObject *self, void *closure)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : self    = objet Python concerné par l'appel.                 *
+*                closure = non utilisé ici.                                   *
+*                                                                             *
+*  Description : Fournit le format associé à l'élément chargé.                *
+*                                                                             *
+*  Retour      : Format associé à l'élément chargé.                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_loaded_content_get_format_name(PyObject *self, void *closure)
+{
+    PyObject *result;                       /* Instance Python à retourner */
+    GLoadedContent *content;                /* Version GLib de l'élément   */
+    GBinContent *bincnt;                    /* Contenu binaire associé     */
+
+#define LOADED_CONTENT_FORMAT_NAME_ATTRIB PYTHON_GET_DEF_FULL               \
+(                                                                           \
+    format_name, py_loaded_content,                                         \
+    "Raw name of the format connected to the loaded content.\n"             \
+    "\n"                                                                    \
+    "The name associated to a loaded Elf binary is for instance 'elf'."     \
+)
+
+    content = G_LOADED_CONTENT(pygobject_get(self));
+
+    bincnt = g_loaded_content_get_content(content);
+
+    result = pygobject_new(G_OBJECT(bincnt));
+
+    g_object_unref(G_OBJECT(bincnt));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : -                                                            *
 *                                                                             *
 *  Description : Fournit un accès à une définition de type à diffuser.        *
@@ -363,22 +655,19 @@ PyTypeObject *get_python_loaded_content_type(void)
     static PyMethodDef py_loaded_content_methods[] = {
         LOADED_CONTENT_ANALYZE_METHOD,
         LOADED_CONTENT_ANALYZE_AND_WAIT_METHOD,
-        {
-            "detect_obfuscators", py_loaded_content_detect_obfuscators,
-            METH_VARARGS,
-            "detect_obfuscators($self, version, /)\n--\n\nList all detected obfuscators."
-        },
-        {
-            "count_views", py_loaded_content_count_views,
-            METH_NOARGS,
-            "count_views($self, /)\n--\n\nCompute the quantity of available views."
-        },
+        LOADED_CONTENT_DESCRIBE_METHOD,
+        LOADED_CONTENT_DETECT_OBFUSCATORS_METHOD,
+        LOADED_CONTENT_COUNT_VIEWS_METHOD,
+        LOADED_CONTENT_GET_VIEW_NAME_METHOD,
         LOADED_CONTENT_BUILD_DEFAULT_VIEW_METHOD,
+        LOADED_CONTENT_BUILD_VIEW_METHOD,
+        LOADED_CONTENT_GET_VIEW_INDEX_METHOD,
         { NULL }
     };
 
     static PyGetSetDef py_loaded_content_getseters[] = {
         LOADED_CONTENT_CONTENT_ATTRIB,
+        LOADED_CONTENT_FORMAT_NAME_ATTRIB,
         { NULL }
     };
 
@@ -391,7 +680,7 @@ PyTypeObject *get_python_loaded_content_type(void)
 
         .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
 
-        .tp_doc         = "PyChrysalide loaded content",
+        .tp_doc         = LOADED_CONTENT_DOC,
 
         .tp_methods     = py_loaded_content_methods,
         .tp_getset      = py_loaded_content_getseters
-- 
cgit v0.11.2-87-g4458