From a0532508524a37444d15b878c5e494cd348b0cae Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sun, 25 Aug 2024 19:03:08 +0200
Subject: Include support for the JSON format.

---
 configure.ac           |  15 ++++
 src/Makefile.am        |   2 +-
 src/common/Makefile.am |   3 +-
 src/common/json.c      | 203 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/common/json.h      |  44 +++++++++++
 5 files changed, 265 insertions(+), 2 deletions(-)
 create mode 100644 src/common/json.c
 create mode 100644 src/common/json.h

diff --git a/configure.ac b/configure.ac
index 6bf6ca1..13288b9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -587,6 +587,20 @@ AC_SUBST(LIBHS_CFLAGS)
 AC_SUBST(LIBHS_LIBS)
 
 
+#--- Checks for json-glib-1.0
+
+PKG_CHECK_MODULES(LIBJSONGLIB,json-glib-1.0 >= 1.6.6,[libjsonglib_found=yes],[libjsonglib_found=no])
+
+if test "$libjsonglib_found" = "yes"; then
+   libjsonglib_version=`pkg-config json-glib-1.0 --modversion`
+else
+   libjsonglib_version='-'
+fi
+
+AC_SUBST(LIBJSONGLIB_CFLAGS)
+AC_SUBST(LIBJSONGLIB_LIBS)
+
+
 #--- Checks for Python
 
 if test "x$enable_debug" = "xyes"; then
@@ -873,6 +887,7 @@ echo The client URL library....................... : $libcurl_version
 echo The YAML support library..................... : $libyaml_version
 echo The magic number recognition library......... : $libmagic_version
 echo The high-performance matching library........ : $libhs_version
+echo The JSON Parser for GLib library............. : $libjsonglib_version
 
 echo
 echo Available Python programming language........ : $python3_version
diff --git a/src/Makefile.am b/src/Makefile.am
index 4e8c07c..54a9d0c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -85,7 +85,7 @@ libchrysacore4_la_LIBADD =					\
 	plugins/libplugins.la
 
 libchrysacore4_la_LDFLAGS =					\
-	$(TOOLKIT_LIBS) $(LIBSSL_LIBS)
+	$(TOOLKIT_LIBS) $(LIBSSL_LIBS) $(LIBJSONGLIB_LIBS)
 
 if BUILD_CURL_SUPPORT
 
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index 24929e7..7f0fe4e 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -56,6 +56,7 @@ libcommon4_la_SOURCES =						\
 	extstr.h extstr.c						\
 	fnv1a.h fnv1a.c							\
 	io.h io.c								\
+	json.h json.c							\
 	leb128.h leb128.c						\
 	macros.h								\
 	packed.h packed.c						\
@@ -72,7 +73,7 @@ libcommon4_la_SOURCES +=					\
 
 endif
 
-libcommon4_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBSSL_CFLAGS)
+libcommon4_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBSSL_CFLAGS) $(LIBJSONGLIB_CFLAGS)
 
 if BUILD_CURL_SUPPORT
 
diff --git a/src/common/json.c b/src/common/json.c
new file mode 100644
index 0000000..cb64822
--- /dev/null
+++ b/src/common/json.c
@@ -0,0 +1,203 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * json.c - manipulations génériques de données au format JSON
+ *
+ * Copyright (C) 2024 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide 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.
+ *
+ *  Chrysalide 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 Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "json.h"
+
+
+#include <assert.h>
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : root  = racine d'une arborescence JSON chargée.              *
+*                query = chemin XPath d'une requête à mener.                  *
+*                error = description d'une éventuelle erreur rencontrée. [OUT]*
+*                                                                             *
+*  Description : Détermine la présence d'un élément avec une valeur textuelle.*
+*                                                                             *
+*  Retour      : true si le noeud existe et porte une chaîne comme valeur.    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool has_json_string_value(JsonNode *root, const char *xpath, GError **error)
+{
+    bool result;                            /* Bilan à retourner           */
+    JsonNode *found;                        /* Accès direct aux trouvailles*/
+    JsonArray *array;                       /* Liste des résultats         */
+    guint count;                            /* Taille de la liste          */
+    JsonNode *node;                         /* Noeud portant la cible      */
+    GValue value;                           /* Valeur correspondante       */
+
+    result = false;
+
+    *error = NULL;
+    found = json_path_query(xpath, root, error);
+
+    if (found != NULL)
+    {
+        assert(*error == NULL);
+
+        array = json_node_get_array(found);
+
+        count = json_array_get_length(array);
+
+        if (count == 1)
+        {
+            node = json_array_get_element(array, 0);
+
+            memset(&value, 0, sizeof(GValue));
+            json_node_get_value(node, &value);
+
+            if (G_VALUE_HOLDS(&value, G_TYPE_STRING))
+                result = true;
+
+        }
+
+        json_node_unref(found);
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : root  = racine d'une arborescence JSON chargée.              *
+*                query = chemin XPath d'une requête à mener.                  *
+*                error = description d'une éventuelle erreur rencontrée. [OUT]*
+*                                                                             *
+*  Description : Fournit le contenu d'un élément avec une valeur textuelle.   *
+*                                                                             *
+*  Retour      : Valeur trouvée ou NULL en cas d'échec.                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+char *get_json_string_value(JsonNode *root, const char *xpath, GError **error)
+{
+    char *result;                           /* Valeur à retourner          */
+    JsonNode *found;                        /* Accès direct aux trouvailles*/
+    JsonArray *array;                       /* Liste des résultats         */
+    guint count;                            /* Taille de la liste          */
+    JsonNode *node;                         /* Noeud portant la cible      */
+    GValue value;                           /* Valeur correspondante       */
+    const gchar *raw;                       /* Valeur brute présente       */
+
+    result = NULL;
+
+    *error = NULL;
+    found = json_path_query(xpath, root, error);
+
+    if (found != NULL)
+    {
+        assert(*error == NULL);
+
+        array = json_node_get_array(found);
+
+        count = json_array_get_length(array);
+
+        if (count == 1)
+        {
+            node = json_array_get_element(array, 0);
+
+            memset(&value, 0, sizeof(GValue));
+            json_node_get_value(node, &value);
+
+            if (G_VALUE_HOLDS(&value, G_TYPE_STRING))
+            {
+                raw = json_array_get_string_element(array, 0);
+                result = strdup(raw);
+            }
+
+        }
+
+        json_node_unref(found);
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : root  = racine d'une arborescence JSON chargée.              *
+*                query = chemin XPath d'une requête à mener.                  *
+*                error = description d'une éventuelle erreur rencontrée. [OUT]*
+*                                                                             *
+*  Description : Fournit le contenu d'un élément avec une valeur entière.     *
+*                                                                             *
+*  Retour      : Valeur trouvée ou NULL en cas d'échec.                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+long long get_json_integer_value(JsonNode *root, const char *xpath, GError **error)
+{
+    long long result;                       /* Valeur à retourner          */
+    JsonNode *found;                        /* Accès direct aux trouvailles*/
+    JsonArray *array;                       /* Liste des résultats         */
+    guint count;                            /* Taille de la liste          */
+    JsonNode *node;                         /* Noeud portant la cible      */
+    GValue value;                           /* Valeur correspondante       */
+
+    result = 0xffffffffffffffffll;
+
+    *error = NULL;
+    found = json_path_query(xpath, root, error);
+
+    if (found != NULL)
+    {
+        assert(*error == NULL);
+
+        array = json_node_get_array(found);
+
+        count = json_array_get_length(array);
+
+        if (count == 1)
+        {
+            node = json_array_get_element(array, 0);
+
+            memset(&value, 0, sizeof(GValue));
+            json_node_get_value(node, &value);
+
+            if (G_VALUE_HOLDS(&value, G_TYPE_INT64))
+                result = json_array_get_int_element(array, 0);
+
+        }
+
+        json_node_unref(found);
+
+    }
+
+    return result;
+
+}
diff --git a/src/common/json.h b/src/common/json.h
new file mode 100644
index 0000000..8794bf6
--- /dev/null
+++ b/src/common/json.h
@@ -0,0 +1,44 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * json.h - prototypes pour des manipulations génériques de données au format JSON
+ *
+ * Copyright (C) 2024 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  Chrysalide 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.
+ *
+ *  Chrysalide 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 Chrysalide.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _COMMON_JSON_H
+#define _COMMON_JSON_H
+
+
+#include <stdbool.h>
+#include <json-glib/json-glib.h>
+
+
+
+/* Détermine la présence d'un élément avec une valeur textuelle. */
+bool has_json_string_value(JsonNode *, const char *, GError **);
+
+/* Fournit le contenu d'un élément avec une valeur textuelle. */
+char *get_json_string_value(JsonNode *, const char *, GError **);
+
+/* Fournit le contenu d'un élément avec une valeur entière. */
+long long get_json_integer_value(JsonNode *, const char *, GError **);
+
+
+
+#endif  /* _COMMON_JSON_H */
-- 
cgit v0.11.2-87-g4458