From 98076c3b06700b1cf24f3fdca1844c0dcf6faeb2 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Tue, 22 Feb 2022 20:11:49 +0100
Subject: Include cURL support for network operations.

---
 configure.ac           |  15 ++++
 src/Makefile.am        |   3 +-
 src/common/Makefile.am |   5 +-
 src/common/curl.c      | 231 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/common/curl.h      |  54 ++++++++++++
 5 files changed, 305 insertions(+), 3 deletions(-)
 create mode 100644 src/common/curl.c
 create mode 100644 src/common/curl.h

diff --git a/configure.ac b/configure.ac
index 5c383a7..fbda04a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -395,6 +395,20 @@ AC_SUBST(LIBSSL_CFLAGS)
 AC_SUBST(LIBSSL_LIBS)
 
 
+#--- Checks for libcurl
+
+PKG_CHECK_MODULES(LIBCURL,libcurl >= 7.64,[libcurl_found=yes],[libcurl_found=no])
+
+if test "$libcurl_found" = "yes"; then
+   libcurl_version=`pkg-config libcurl --modversion`
+else
+   libcurl_version='-'
+fi
+
+AC_SUBST(LIBCURL_CFLAGS)
+AC_SUBST(LIBCURL_LIBS)
+
+
 #--- Checks for Python
 
 if test "x$enable_debug" = "xyes"; then
@@ -628,6 +642,7 @@ echo The XML C parser and toolkit of Gnome........ : $libxml_version
 echo The flexible interface for archives I/O...... : $libarchive_version
 echo The small, fast and reliable database engine. : $libsqlite_version
 echo The cryptography and SSL/TLS toolkit......... : $libssl_version
+echo The client URL library....................... : $libcurl_version
 
 echo
 echo Available Python programming language........ : $python3_version
diff --git a/src/Makefile.am b/src/Makefile.am
index f90d3bc..321b472 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -24,7 +24,8 @@ libchrysacore_la_SOURCES = 				\
 libchrysacore_la_LDFLAGS =					\
 	-avoid-version -ldl						\
 	$(LIBGTK_LIBS) $(LIBXML_LIBS)			\
-	$(LIBSQLITE_LIBS) $(LIBARCHIVE_LIBS)
+	$(LIBSQLITE_LIBS) $(LIBARCHIVE_LIBS)	\
+	$(LIBCURL_LIBS)
 
 libchrysacore_la_LIBADD =				\
 	analysis/libanalysis.la				\
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index 3379eed..28e5459 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -9,6 +9,7 @@ libcommon_la_SOURCES =					\
 	bits.h bits.c						\
 	compression.h compression.c			\
 	cpp.h								\
+	curl.h curl.c						\
 	dllist.h dllist.c					\
 	endianness.h endianness.c			\
 	environment.h environment.c			\
@@ -30,7 +31,7 @@ libcommon_la_SOURCES =					\
 	xdg.h xdg.c							\
 	xml.h xml.c
 
-libcommon_la_LDFLAGS = $(LIBGTK_LIBS) $(LIBXML_LIBS)
+libcommon_la_LDFLAGS = $(LIBGTK_LIBS) $(LIBXML_LIBS) $(LIBCURL_LIBS)
 
 
 devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
@@ -38,7 +39,7 @@ devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
 dev_HEADERS = $(libcommon_la_SOURCES:%c=)
 
 
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS)
+AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) $(LIBCURL_CFLAGS)
 
 AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS)
 
diff --git a/src/common/curl.c b/src/common/curl.c
new file mode 100644
index 0000000..573180f
--- /dev/null
+++ b/src/common/curl.c
@@ -0,0 +1,231 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * curl.c - encapsulation des fonctionnalités de cURL
+ *
+ * Copyright (C) 2022 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 "curl.h"
+
+
+#include <malloc.h>
+#include <string.h>
+
+
+
+/* Mémorise les données reçues en réponse à une requête. */
+static size_t receive_data_from_internet(void *, size_t, size_t, curl_net_data_t *);
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : contents = contenu nouveau en arrivance d'Internet.          *
+*                size     = taille d'un élément reçu.                         *
+*                nmemb    = quantité de ces éléments.                         *
+*                data     = zone de collecte à compléter. [OUT]               *
+*                                                                             *
+*  Description : Mémorise les données reçues en réponse à une requête.        *
+*                                                                             *
+*  Retour      : Taille de données effectivement reçue.                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static size_t receive_data_from_internet(void *contents, size_t size, size_t nmemb, curl_net_data_t *data)
+{
+    size_t realsize;                        /* Taille brute en octets      */
+
+    realsize = size * nmemb;
+
+    data->memory = realloc(data->memory, data->size + realsize + 1);
+
+    memcpy(&(data->memory[data->size]), contents, realsize);
+
+    data->size += realsize;
+
+    data->memory[data->size] = 0;
+
+    return realsize;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : url     = resource distant à cibler.                         *
+*                headers = entêtes enventuels à joindre à la requête.         *
+*                hcount  = quantité de ces entêtes.                           *
+*                cookies = éventuels biscuits formatés ou NULL.               *
+*                ecb     = éventuelle fonction d'intervention à appeler.      *
+*                resp    = réponse obtenue du serveur distant. [OUT]          *
+*                                                                             *
+*  Description : Mémorise les données reçues en réponse à une requête.        *
+*                                                                             *
+*  Retour      : Taille de données effectivement reçue.                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool send_http_get_request(const char *url, char * const headers[], size_t hcount, const char *cookies, setup_extra_curl_cb ecb, curl_net_data_t *resp)
+{
+    bool result;                            /* Bilan d'opération à renvoyer*/
+    CURL *req;                              /* Requête HTTP                */
+    struct curl_slist *hlist;               /* Entêtes éventuelles         */
+    size_t i;                               /* Boucle de parcours          */
+    CURLcode ret;                           /* Code de retour d'opération  */
+
+    result = false;
+
+    resp->memory = NULL;
+    resp->size = 0;
+
+    req = curl_easy_init();
+    if (req == NULL) goto exit;
+
+    curl_easy_setopt(req, CURLOPT_URL, url);
+
+    /* Entêtes à transmettre */
+
+    hlist = NULL;
+
+    for (i = 0; i < hcount; i++)
+        hlist = curl_slist_append(hlist, headers[i]);
+
+    curl_easy_setopt(req, CURLOPT_HTTPHEADER, hlist);
+
+    if (cookies != NULL)
+        curl_easy_setopt(req, CURLOPT_COOKIE, cookies);
+
+    /* Réception des données */
+
+    curl_easy_setopt(req, CURLOPT_WRITEDATA, (void *)resp);
+
+    curl_easy_setopt(req, CURLOPT_WRITEFUNCTION, receive_data_from_internet);
+
+    /* Définition de la charge utile */
+
+    curl_easy_setopt(req, CURLOPT_HTTPGET, 1);
+
+    /* Emission de la requête */
+
+    if (ecb != NULL)
+        ecb(req);
+
+    ret = curl_easy_perform(req);
+
+    result = (ret == CURLE_OK);
+
+    if (!result)
+        fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(ret));
+
+    curl_slist_free_all(hlist);
+
+    curl_easy_cleanup(req);
+
+ exit:
+
+    return result;
+
+}
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : url     = resource distant à cibler.                         *
+*                headers = entêtes enventuels à joindre à la requête.         *
+*                hcount  = quantité de ces entêtes.                           *
+*                cookies = éventuels biscuits formatés ou NULL.               *
+*                payload = charge utile à transmettre au serveur distant.     *
+*                ecb     = éventuelle fonction d'intervention à appeler.      *
+*                resp    = réponse obtenue du serveur distant. [OUT]          *
+*                                                                             *
+*  Description : Mémorise les données reçues en réponse à une requête.        *
+*                                                                             *
+*  Retour      : Taille de données effectivement reçue.                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool send_http_post_request(const char *url, char * const headers[], size_t hcount, const char *cookies, const curl_net_data_t *payload, setup_extra_curl_cb ecb, curl_net_data_t *resp)
+{
+    bool result;                            /* Bilan d'opération à renvoyer*/
+    CURL *req;                              /* Requête HTTP                */
+    struct curl_slist *hlist;               /* Entêtes éventuelles         */
+    size_t i;                               /* Boucle de parcours          */
+    CURLcode ret;                           /* Code de retour d'opération  */
+
+    result = false;
+
+    resp->memory = NULL;
+    resp->size = 0;
+
+    req = curl_easy_init();
+    if (req == NULL) goto exit;
+
+    curl_easy_setopt(req, CURLOPT_URL, url);
+
+    /* Entêtes à transmettre */
+
+    hlist = NULL;
+
+    for (i = 0; i < hcount; i++)
+        hlist = curl_slist_append(hlist, headers[i]);
+
+    curl_easy_setopt(req, CURLOPT_HTTPHEADER, hlist);
+
+    if (cookies != NULL)
+        curl_easy_setopt(req, CURLOPT_COOKIE, cookies);
+
+    /* Réception des données */
+
+    curl_easy_setopt(req, CURLOPT_WRITEDATA, (void *)resp);
+
+    curl_easy_setopt(req, CURLOPT_WRITEFUNCTION, receive_data_from_internet);
+
+    /* Définition de la charge utile */
+
+    curl_easy_setopt(req, CURLOPT_POST, 1);
+
+    curl_easy_setopt(req, CURLOPT_POSTFIELDS, payload->memory);
+    curl_easy_setopt(req, CURLOPT_POSTFIELDSIZE, payload->size);
+
+    /* Emission de la requête */
+
+    if (ecb != NULL)
+        ecb(req);
+
+    ret = curl_easy_perform(req);
+
+    result = (ret == CURLE_OK);
+
+    if (!result)
+        fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(ret));
+
+    curl_slist_free_all(hlist);
+
+    curl_easy_cleanup(req);
+
+ exit:
+
+    return result;
+
+}
diff --git a/src/common/curl.h b/src/common/curl.h
new file mode 100644
index 0000000..02d9e91
--- /dev/null
+++ b/src/common/curl.h
@@ -0,0 +1,54 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * curl.h - prototypes pour l'encapsulation des fonctionnalités de cURL
+ *
+ * Copyright (C) 2022 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_CURL_H
+#define _COMMON_CURL_H
+
+
+#include <stdbool.h>
+#include <curl/curl.h>
+
+
+
+/* Données échangées avec Internet */
+typedef struct _curl_net_data_t
+{
+    char *memory;                           /* Zone de mémoire allouée     */
+    size_t size;                            /* Quantité de données         */
+
+} curl_net_data_t;
+
+
+/* Prototype pour une intervention complémentaire dans la préparation des requêtes */
+typedef CURLcode (* setup_extra_curl_cb) (CURL *);
+
+
+/* Mémorise les données reçues en réponse à une requête. */
+bool send_http_get_request(const char *, char * const [], size_t, const char *, setup_extra_curl_cb, curl_net_data_t *);
+
+/* Mémorise les données reçues en réponse à une requête. */
+bool send_http_post_request(const char *, char * const [], size_t, const char *, const curl_net_data_t *, setup_extra_curl_cb, curl_net_data_t *);
+
+
+
+#endif  /* _COMMON_CURL_H */
-- 
cgit v0.11.2-87-g4458